001/* 002 * #%L 003 * Netarchivesuite - archive 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.archive.arcrepository.bitpreservation; 024 025import java.io.File; 026import java.util.Date; 027import java.util.List; 028import java.util.Set; 029 030import dk.netarkivet.archive.ArchiveSettings; 031import dk.netarkivet.common.distribute.arcrepository.Replica; 032import dk.netarkivet.common.exceptions.ArgumentNotValid; 033import dk.netarkivet.common.exceptions.IOFailure; 034import dk.netarkivet.common.exceptions.IllegalState; 035import dk.netarkivet.common.utils.FileUtils; 036import dk.netarkivet.common.utils.Settings; 037 038/** 039 * This class encapsulates access to the files used in bitpreservation. 040 * <p> 041 * The following files are encapsulated: 042 * <p> 043 * "unsorted.txt": Unsorted list of files in a bitarchive "sorted.txt": Sorted list of files in a bitarchive 044 * <p> 045 * "missingba.txt": Files that are missing in a bitarchive "missingadmindata.txt"; Files that are missing from admin 046 * data "wrongfiles.txt": Files with wrong checksum??? "referenceba.txt"; File list from reference ba? 047 * <p> 048 * "wrongstates.txt"; Files that are in wrong state "insertinadmin.txt"; Files to insert into admin data 049 * "deletefromadmin.txt"; Files to delete from admin data "uploadtoba.txt"; Files to upload to the bitarchive 050 * "deletefromba.txt"; Files to delete from the bitarchive 051 */ 052public enum WorkFiles { 053 /** 054 * The MISSING_FILES_BA is the workfile for the list of missing files for a bitarchive. 055 */ 056 MISSING_FILES_BA, 057 /** 058 * The MISSING_FILES_ADMINDATA is the workfile for the list of missing files for the admin data. 059 */ 060 MISSING_FILES_ADMINDATA, 061 /** WRONG_FILES. Files with wrong checksum??? . */ 062 WRONG_FILES, 063 /** FILES_ON_REFERENCE_BA. File list from reference ba?. */ 064 FILES_ON_REFERENCE_BA, 065 /** INSERT_IN_ADMIN. Files to insert into admin data . */ 066 INSERT_IN_ADMIN, 067 /** DELETE_FROM_ADMIN. Files to delete from admin data . */ 068 DELETE_FROM_ADMIN, 069 /** UPLOAD_TO_BA. Files to upload to the bitarchive . */ 070 UPLOAD_TO_BA, 071 /** DELETE_FROM_BA. Files to delete from the bitarchive . */ 072 DELETE_FROM_BA, 073 /** WRONG_STATES. Files that are in wrong state . */ 074 WRONG_STATES, 075 /** FILES_ON_BA. Unsorted list of files in a bitarchive . */ 076 FILES_ON_BA, 077 /** CHECKSUMS_ON_BA. Unsorted list of files in a bitarchive . */ 078 CHECKSUMS_ON_BA; 079 080 /** 081 * Directory and filenames to be used by ActiveBitPreservation when checking for missing files in a bitarchive. 082 */ 083 private static final String FILELIST_OUTPUT_DIR = "filelistOutput"; 084 /** missingFiles . */ 085 private static final String MISSING_FILES_DIR = "missingFiles"; 086 /** checksums . */ 087 private static final String CHECKSUM_DIR = "checksums"; 088 /** wrongFiles . */ 089 private static final String WRONGFILESDIR = "wrongFiles"; 090 /** referenceFiles . */ 091 private static final String BA_LIST_DIR = "referenceFiles"; 092 /** actionsList . */ 093 private static final String ACTION_LIST_DIR = "actionList"; 094 095 /** unsorted.txt . */ 096 private static final String FILE_LISTING_FILENAME = "unsorted.txt"; 097 /** sorted.txt . */ 098 private static final String SORTED_OUTPUT_FILE = "sorted.txt"; 099 /** missingba.txt . */ 100 private static final String MISSING_FILES_BA_FILENAME = "missingba.txt"; 101 /** missingadmindata.txt . */ 102 private static final String MISSING_FILES_ADMINDATA_FILENAME = "missingadmindata.txt"; 103 /** wrongfiles.txt . */ 104 private static final String WRONG_FILES_FILENAME = "wrongfiles.txt"; 105 /** insertinadmin.txt . */ 106 private static final String INSERT_IN_ADMIN_FILENAME = "insertinadmin.txt"; 107 /** deletefromadmin.txt . */ 108 private static final String DELETE_FROM_ADMIN_FILENAME = "deletefromadmin.txt"; 109 /** uploadtoba.txt . */ 110 private static final String UPLOAD_TO_BA_FILENAME = "uploadtoba.txt"; 111 /** deletefromba.txt . */ 112 private static final String DELETE_FROM_BA_FILENAME = "deletefromba.txt"; 113 /** wrongstates.txt . */ 114 private static final String WRONG_STATES_FILENAME = "wrongstates.txt"; 115 116 /** 117 * Get the name of the file (sans dir) that corresponds to a given type of workfile. 118 * 119 * @param fileType the type of workfile. 120 * @return A string with the filename (sans dir) of the corresponding file. 121 * @throws IllegalState If it is an unsupported file type. 122 */ 123 private static String getFileName(WorkFiles fileType) throws IllegalState { 124 // check the filetype 125 switch (fileType) { 126 case MISSING_FILES_BA: 127 return MISSING_FILES_BA_FILENAME; 128 case MISSING_FILES_ADMINDATA: 129 return MISSING_FILES_ADMINDATA_FILENAME; 130 case WRONG_FILES: 131 return WRONG_FILES_FILENAME; 132 case INSERT_IN_ADMIN: 133 return INSERT_IN_ADMIN_FILENAME; 134 case DELETE_FROM_ADMIN: 135 return DELETE_FROM_ADMIN_FILENAME; 136 case UPLOAD_TO_BA: 137 return UPLOAD_TO_BA_FILENAME; 138 case DELETE_FROM_BA: 139 return DELETE_FROM_BA_FILENAME; 140 case WRONG_STATES: 141 return WRONG_STATES_FILENAME; 142 case FILES_ON_REFERENCE_BA: 143 case FILES_ON_BA: 144 case CHECKSUMS_ON_BA: 145 return FILE_LISTING_FILENAME; 146 default: 147 throw new IllegalState("Impossible workfile type " + fileType); 148 } 149 } 150 151 /** 152 * Get the directory that files of a given type should go into. 153 * 154 * @param rep The replica that we're doing bitpreservation for. 155 * @param fileType The type of file we will be using. 156 * @return A directory (created if necessary) under the bitpreservation dir (see settings) for the file to go into. 157 * @throws IllegalState If it is an unsupported file type. 158 */ 159 private static File getDir(Replica rep, WorkFiles fileType) throws IllegalState { 160 // check the type 161 switch (fileType) { 162 case MISSING_FILES_BA: 163 case MISSING_FILES_ADMINDATA: 164 return makeRelativeDir(rep, MISSING_FILES_DIR); 165 case WRONG_STATES: 166 case WRONG_FILES: 167 return makeRelativeDir(rep, WRONGFILESDIR); 168 case FILES_ON_BA: 169 return getFilelistOutputDir(makeRelativeDir(rep, MISSING_FILES_DIR)); 170 case FILES_ON_REFERENCE_BA: 171 return getFilelistOutputDir(makeRelativeDir(rep, BA_LIST_DIR)); 172 case INSERT_IN_ADMIN: 173 case DELETE_FROM_ADMIN: 174 case UPLOAD_TO_BA: 175 case DELETE_FROM_BA: 176 return makeRelativeDir(rep, ACTION_LIST_DIR); 177 case CHECKSUMS_ON_BA: 178 return getFilelistOutputDir(makeRelativeDir(rep, CHECKSUM_DIR)); 179 default: 180 throw new IllegalState("Impossible workfile type " + fileType); 181 } 182 } 183 184 /** 185 * Get the directory that file listings are to live in, creating it if necessary. 186 * 187 * @param dir The directory that the file listings should live under. Note that this is not directly derived from 188 * the name of the replica, as it can also be used for reference file listings. 189 * @return The directory to put file listings in under the given dir. 190 */ 191 private static File getFilelistOutputDir(File dir) { 192 String filelistOutputDir = FILELIST_OUTPUT_DIR; 193 File outputDir = new File(dir, filelistOutputDir); 194 FileUtils.createDir(outputDir); 195 return outputDir; 196 } 197 198 /** 199 * Get the base dir for all files related to bitpreservation for a given bitarchive. 200 * 201 * @param replica The name of a bitarchive. 202 * @return The directory to place bitpreservation for the archive under. 203 */ 204 protected static File getPreservationDir(Replica replica) { 205 File base = new File(Settings.get(ArchiveSettings.DIR_ARCREPOSITORY_BITPRESERVATION)); 206 return new File(base, replica.getId()); 207 } 208 209 /** 210 * Make a directory object relative to an replica, creating the directory if necessary. 211 * 212 * @param replica The replica that we're doing bitpreservation for 213 * @param dirname The name of the directory to create 214 * @return An object representing the directory 215 */ 216 private static File makeRelativeDir(Replica replica, String dirname) { 217 File dir = getPreservationDir(replica); 218 File outputDir = new File(dir, dirname); 219 FileUtils.createDir(outputDir); 220 return outputDir; 221 } 222 223 /** 224 * Get a sorted file from an unsorted one, updating if necessary. 225 * 226 * @param unsortedFile An unsorted file 227 * @return A file that contains the same lines as unsortedFile, but sorted. The file will be placed in the same 228 * directory as the input file, but have the name Constants.SORTED_OUTPUT_FILE defines. 229 * @throws IOFailure If the file does not exist. 230 */ 231 protected static File getSortedFile(File unsortedFile) throws IOFailure { 232 unsortedFile = unsortedFile.getAbsoluteFile(); 233 File sortedOutput = new File(unsortedFile.getParentFile(), SORTED_OUTPUT_FILE); 234 if (!unsortedFile.exists()) { 235 throw new IOFailure("Unsorted input file '" + unsortedFile + "' does not exist"); 236 } 237 if (unsortedFile.lastModified() >= sortedOutput.lastModified()) { 238 FileUtils.makeSortedFile(unsortedFile, sortedOutput); 239 } 240 return sortedOutput; 241 } 242 243 /* public interfaces below here. */ 244 245 /** 246 * Method for writing the list of files to a work file. 247 * 248 * @param replica The replica for the working file. 249 * @param fileType The type of working file. 250 * @param files The list of filenames (?) to write to the working file. 251 */ 252 public static void write(Replica replica, WorkFiles fileType, Set<String> files) { 253 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 254 ArgumentNotValid.checkNotNull(fileType, "WorkFiles fileType"); 255 ArgumentNotValid.checkNotNull(files, "Set<String> files"); 256 FileUtils.writeCollectionToFile(getFile(replica, fileType), files); 257 } 258 259 /** 260 * Method for retrieving a working file. Note: it is not tested, whether the file exists. 261 * 262 * @param rep The replica to whom the file corresponds. 263 * @param fileType The type of working file. 264 * @return The requested working file. 265 */ 266 public static File getFile(Replica rep, WorkFiles fileType) { 267 ArgumentNotValid.checkNotNull(rep, "Replica rep"); 268 ArgumentNotValid.checkNotNull(fileType, "WorkFiles fileType"); 269 return new File(getDir(rep, fileType), getFileName(fileType)); 270 } 271 272 /** 273 * Method for retrieving the last modified date of a working file for a specific replica. 274 * <p> 275 * FIXME this might throw odd exceptions if the file does not exist. 276 * 277 * @param rep The replica for the working file. 278 * @param fileType The type of working file. 279 * @return The last modified date for the working file. 280 */ 281 public static Date getLastUpdate(Replica rep, WorkFiles fileType) { 282 ArgumentNotValid.checkNotNull(rep, "Replica rep"); 283 ArgumentNotValid.checkNotNull(fileType, "WorkFiles fileType"); 284 return new Date(getFile(rep, fileType).lastModified()); 285 } 286 287 /** 288 * Method for retrieving the lines of a working file for a specific replica. 289 * 290 * @param replica The replica of the working file. 291 * @param fileType The type of workfile. 292 * @return A list containing the lines of the file. 293 */ 294 public static List<String> getLines(Replica replica, WorkFiles fileType) { 295 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 296 ArgumentNotValid.checkNotNull(fileType, "WorkFiles fileType"); 297 return FileUtils.readListFromFile(getFile(replica, fileType)); 298 } 299}