1 34 package org.dspace.checker; 35 36 import java.io.File ; 37 import java.io.IOException ; 38 import java.io.InputStream ; 39 import java.security.DigestInputStream ; 40 import java.security.MessageDigest ; 41 import java.security.NoSuchAlgorithmException ; 42 import java.sql.SQLException ; 43 import java.util.Date ; 44 45 import org.apache.log4j.Logger; 46 import org.apache.log4j.PropertyConfigurator; 47 import org.dspace.core.ConfigurationManager; 48 import org.dspace.core.Utils; 49 50 65 public final class CheckerCommand 66 { 67 68 private static final Logger LOG = Logger.getLogger(CheckerCommand.class); 69 70 71 private static final String DEFAULT_DIGEST_ALGORITHM = "MD5"; 72 73 74 private int BYTE_ARRAY_SIZE = 4 * 1024; 75 76 77 private BitstreamInfoDAO bitstreamInfoDAO = null; 78 79 80 private BitstreamDAO bitstreamDAO = null; 81 82 85 private ChecksumHistoryDAO checksumHistoryDAO = null; 86 87 88 private Date processStartDate = null; 89 90 93 private BitstreamDispatcher dispatcher = null; 94 95 98 private ChecksumResultsCollector collector = null; 99 100 101 private boolean reportVerbose = false; 102 103 106 public CheckerCommand() 107 { 108 bitstreamInfoDAO = new BitstreamInfoDAO(); 109 bitstreamDAO = new BitstreamDAO(); 110 checksumHistoryDAO = new ChecksumHistoryDAO(); 111 } 112 113 125 public void process() 126 { 127 LOG.debug("Begin Checker Processing"); 128 129 if (dispatcher == null) 130 { 131 throw new IllegalStateException ("No BitstreamDispatcher provided"); 132 } 133 134 if (collector == null) 135 { 136 collector = new ResultsLogger(processStartDate); 137 } 138 139 bitstreamInfoDAO.updateMissingBitstreams(); 142 143 int id = dispatcher.next(); 144 145 while (id != BitstreamDispatcher.SENTINEL) 146 { 147 LOG.debug("Processing bitstream id = " + id); 148 BitstreamInfo info = checkBitstream(id); 149 150 if (reportVerbose 151 || (info.getChecksumCheckResult() != ChecksumCheckResults.CHECKSUM_MATCH)) 152 { 153 collector.collect(info); 154 } 155 156 id = dispatcher.next(); 157 } 158 } 159 160 168 private BitstreamInfo checkBitstream(final int id) 169 { 170 BitstreamInfo info = bitstreamInfoDAO.findByBitstreamId(id); 172 173 if (info == null) 176 { 177 info = new BitstreamInfo(id); 182 processNullInfoBitstream(info); 183 } 184 else if (!info.getToBeProcessed()) 185 { 186 info 190 .setChecksumCheckResult(ChecksumCheckResults.BITSTREAM_NOT_PROCESSED); 191 } 192 else if (info.getDeleted()) 193 { 194 processDeletedBitstream(info); 196 } 197 else 198 { 199 processBitstream(info); 200 } 201 202 return info; 203 } 204 205 221 private String digestStream(InputStream stream, String algorithm) 222 throws java.security.NoSuchAlgorithmException , java.io.IOException 223 { 224 DigestInputStream dStream = new DigestInputStream (stream, MessageDigest 226 .getInstance(algorithm)); 227 228 byte[] bytes = new byte[BYTE_ARRAY_SIZE]; 229 230 while (dStream.read(bytes, 0, BYTE_ARRAY_SIZE) != -1) 232 { 233 } 235 236 return Utils.toHex(dStream.getMessageDigest().digest()); 237 } 238 239 249 private String compareChecksums(String checksumA, String checksumB) 250 { 251 String result = ChecksumCheckResults.CHECKSUM_NO_MATCH; 252 253 if ((checksumA == null) || (checksumB == null)) 254 { 255 result = ChecksumCheckResults.CHECKSUM_PREV_NOT_FOUND; 256 } 257 else if (checksumA.equals(checksumB)) 258 { 259 result = ChecksumCheckResults.CHECKSUM_MATCH; 260 } 261 262 return result; 263 } 264 265 274 private void processDeletedBitstream(BitstreamInfo info) 275 { 276 info.setProcessStartDate(new Date ()); 277 info 278 .setChecksumCheckResult(ChecksumCheckResults.BITSTREAM_MARKED_DELETED); 279 info.setProcessStartDate(new Date ()); 280 info.setProcessEndDate(new Date ()); 281 info.setToBeProcessed(false); 282 bitstreamInfoDAO.update(info); 283 checksumHistoryDAO.insertHistory(info); 284 } 285 286 295 private void processNullInfoBitstream(BitstreamInfo info) 296 { 297 info.setInfoFound(false); 298 info.setProcessStartDate(new Date ()); 299 info.setProcessEndDate(new Date ()); 300 info 301 .setChecksumCheckResult(ChecksumCheckResults.BITSTREAM_INFO_NOT_FOUND); 302 } 303 304 320 private void processBitstream(BitstreamInfo info) 321 { 322 info.setProcessStartDate(new Date ()); 323 324 if (info.getChecksumAlgorithm() == null) 325 { 326 info.setChecksumAlgorithm(DEFAULT_DIGEST_ALGORITHM); 327 } 328 329 try 330 { 331 InputStream bitstream = bitstreamDAO.getBitstream(info 332 .getBitstreamId()); 333 334 info.setBitstreamFound(true); 335 336 String checksum = digestStream(bitstream, info 337 .getChecksumAlgorithm()); 338 339 info.setCalculatedChecksum(checksum); 340 341 info.setChecksumCheckResult(compareChecksums(info 343 .getStoredChecksum(), info.getCalculatedChecksum())); 344 } 345 catch (IOException e) 346 { 347 info 349 .setChecksumCheckResult(ChecksumCheckResults.BITSTREAM_NOT_FOUND); 350 info.setToBeProcessed(false); 351 LOG.error("Error retrieving bitstream ID " + info.getBitstreamId() 352 + " from " + "asset store.", e); 353 } 354 catch (SQLException e) 355 { 356 info 360 .setChecksumCheckResult(ChecksumCheckResults.BITSTREAM_INFO_NOT_FOUND); 361 LOG.error("Error retrieving metadata for bitstream ID " 362 + info.getBitstreamId(), e); 363 } 364 catch (NoSuchAlgorithmException e) 365 { 366 info 367 .setChecksumCheckResult(ChecksumCheckResults.CHECKSUM_ALGORITHM_INVALID); 368 info.setToBeProcessed(false); 369 LOG.error("Invalid digest algorithm type for bitstream ID" 370 + info.getBitstreamId(), e); 371 } 372 finally 373 { 374 info.setProcessEndDate(new Date ()); 375 376 bitstreamInfoDAO.update(info); 378 checksumHistoryDAO.insertHistory(info); 379 } 380 } 381 382 387 public BitstreamDispatcher getDispatcher() 388 { 389 return dispatcher; 390 } 391 392 398 public void setDispatcher(BitstreamDispatcher dispatcher) 399 { 400 this.dispatcher = dispatcher; 401 } 402 403 408 public ChecksumResultsCollector getCollector() 409 { 410 return collector; 411 } 412 413 419 public void setCollector(ChecksumResultsCollector collector) 420 { 421 this.collector = collector; 422 } 423 424 429 public Date getProcessStartDate() 430 { 431 return processStartDate; 432 } 433 434 440 public void setProcessStartDate(Date startDate) 441 { 442 processStartDate = startDate; 443 } 444 445 448 public void configureLog() 449 { 450 String log4jConf = ConfigurationManager.getProperty("dspace.dir") 452 + File.separator + "config" + File.separator 453 + "log4j.properties"; 454 455 PropertyConfigurator.configure(log4jConf); 456 } 457 458 463 public boolean isReportVerbose() 464 { 465 return reportVerbose; 466 } 467 468 474 public void setReportVerbose(boolean reportVerbose) 475 { 476 this.reportVerbose = reportVerbose; 477 } 478 } 479 | Popular Tags |