Java tutorial
/* * Assurance * * Created by Mark Johnson * * Copyright (c) 2015 Digital Generalists, LLC. * */ /* * Copyright 2015 Digital Generalists, LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.digitalgeneralists.assurance.model.compare; import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.Collection; import org.apache.commons.io.FilenameUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.digitalgeneralists.assurance.model.compare.file.IFileComparor; import com.digitalgeneralists.assurance.model.concurrency.ComparisonWorker; import com.digitalgeneralists.assurance.model.concurrency.IAssuranceThreadPool; import com.digitalgeneralists.assurance.model.entities.ComparisonResult; import com.digitalgeneralists.assurance.model.entities.FileReference; import com.digitalgeneralists.assurance.model.entities.Scan; import com.digitalgeneralists.assurance.model.entities.ScanDefinition; import com.digitalgeneralists.assurance.model.enums.AssuranceResultReason; import com.digitalgeneralists.assurance.model.enums.AssuranceResultResolution; import com.digitalgeneralists.assurance.model.factories.IFileComparorFactory; import com.digitalgeneralists.assurance.notification.IProgressMonitor; import com.digitalgeneralists.assurance.utils.AssuranceUtils; @Component("ComparisonEngine") public class ComparisonEngine implements IComparisonEngine { private Logger logger = Logger.getLogger(ComparisonEngine.class); @Autowired private IFileComparorFactory comparorFactory; public void determineDifferences(File source, File target, Scan scan, IAssuranceThreadPool threadPool, IScanOptions options) { this.determineDifferences(source, target, scan, threadPool, options, null); } public void determineDifferences(File source, File target, Scan scan, IAssuranceThreadPool threadPool, IScanOptions options, Collection<FileReference> exclusions) { this.determineDifferences(source, target, scan, threadPool, options, exclusions, null); } public void determineDifferences(File source, File target, Scan scan, IAssuranceThreadPool threadPool, IScanOptions options, Collection<FileReference> exclusions, IProgressMonitor monitor) { IFileComparor comparor = comparorFactory.createInstance(); this.determineDifferences(source, target, scan, comparor, threadPool, options, exclusions, monitor); } public void determineDifferences(File source, File target, Scan scan, IAssuranceThreadPool threadPool, IScanOptions options, boolean performDeepScan) { this.determineDifferences(source, target, scan, threadPool, options, null, performDeepScan); } public void determineDifferences(File source, File target, Scan scan, IAssuranceThreadPool threadPool, IScanOptions options, Collection<FileReference> exclusions, boolean performDeepScan) { this.determineDifferences(source, target, scan, threadPool, options, exclusions, null, performDeepScan); } public void determineDifferences(File source, File target, Scan scan, IAssuranceThreadPool threadPool, IScanOptions options, Collection<FileReference> exclusions, IProgressMonitor monitor, boolean performDeepScan) { IFileComparor comparor = comparorFactory.createInstance(performDeepScan); this.determineDifferences(source, target, scan, comparor, threadPool, options, exclusions, monitor); comparor = null; } private void determineDifferences(File source, File target, Scan scan, IFileComparor comparor, IAssuranceThreadPool threadPool, IScanOptions options, Collection<FileReference> exclusions, IProgressMonitor monitor) { if (monitor != null) { StringBuffer message = new StringBuffer(512); monitor.publish(message.append("Comparing ").append(source.toString()).append(" to ") .append(target.toString())); message.setLength(0); message = null; } if ((source == null) && (target == null)) { StringBuffer message = new StringBuffer(512); logger.info(message.append(source).append(" and ").append(target).append(" are both null.")); message.setLength(0); message = null; } else { // If the source file or target file is in the the global // ignore or exclusion list, just bypass it. // Checking both files in case one is null, in which case // we would have a mismatch. if (((!this.fileIsInGlobalIgnore(source, options)) && (!this.fileIsInGlobalIgnore(target, options))) && ((!this.fileIsInExclusions(source, exclusions)) && (!this.fileIsInExclusions(target, exclusions)))) { // Neither source or target is in the global ignore lists. // Only if both the source and target are not null. // NOTE: This logical condition isn't ideal. It works but // it is still not great in terms of readability. if ((source != null) && (target != null)) { if ((source.isDirectory()) && (!target.isDirectory()) || ((!source.isDirectory()) && (target.isDirectory()))) { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.FILE_DIRECTORY_MISMATCH, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info(message.append(source).append(" does not match ").append(target)); message.setLength(0); message = null; } else { // Both files are either both simple files or both // directories. boolean sourceIsSymbolicLink = AssuranceUtils.checkIfFileIsSymbolicLink(source); boolean targetIsSymbolicLink = AssuranceUtils.checkIfFileIsSymbolicLink(target); if (sourceIsSymbolicLink && targetIsSymbolicLink) { // Both files are symbolic links. Only compare the paths. if (!(source.getPath().equals(target.getPath()))) { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.COMPARE_FAILED, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info(message.append(source).append(" does not match ").append(target)); message.setLength(0); message = null; } } else { // Either file could be symbolic links. Check for a mismatch. if ((sourceIsSymbolicLink && !targetIsSymbolicLink) || (!sourceIsSymbolicLink && targetIsSymbolicLink)) { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.SYMBOLIC_LINK_MISMATCH, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info(message.append(source).append(" does not match ").append(target)); message.setLength(0); message = null; } } if (!sourceIsSymbolicLink && !targetIsSymbolicLink) { // Both files are not symbolic links. if (source.isDirectory()) { // The files are both directories. for (File sourceFile : source.listFiles()) { StringBuilder path = new StringBuilder(512); File targetFile = new File(path.append(target.getPath()).append(File.separator) .append(sourceFile.getName()).toString()); path.setLength(0); path = null; // If the source file or target file is in the the global // ignore or exclusion list, just bypass it. // Checking both files in case one is null, in which case // we would have a mismatch. if (((!this.fileIsInGlobalIgnore(sourceFile, options)) && (!this.fileIsInGlobalIgnore(targetFile, options))) && ((!this.fileIsInExclusions(sourceFile, exclusions)) && (!this.fileIsInExclusions(targetFile, exclusions)))) { if (targetFile.exists()) { threadPool.submit(new ComparisonWorker(this, sourceFile, targetFile, scan, threadPool, options, exclusions, monitor)); } else { ComparisonResult result = new ComparisonResult(sourceFile, targetFile, AssuranceResultReason.TARGET_DOES_NOT_EXIST, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info(message.append(targetFile).append(" does not exist.")); message.setLength(0); logger.info(message.append(sourceFile).append(" does not match ") .append(targetFile)); message.setLength(0); message = null; } } targetFile = null; } this.identifyTargetItemsNotInSource(source, target, scan, comparor, options, exclusions, monitor); } else { // The files are both simple files. try { boolean includeTimestamps = true; boolean includeAdvancedAttributes = true; ScanDefinition scanDefinition = scan.getScanDef(); if (scanDefinition != null) { includeTimestamps = scanDefinition.getIncludeNonCreationTimestamps(); includeAdvancedAttributes = scanDefinition.getIncludeAdvancedAttributes(); } scanDefinition = null; if (comparor.compare(source, target, includeTimestamps, includeAdvancedAttributes)) { StringBuffer message = new StringBuffer(512); logger.info( message.append(source).append(" is identical to ").append(target)); message.setLength(0); message = null; } else { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.COMPARE_FAILED, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info( message.append(source).append(" does not match ").append(target)); message.setLength(0); message = null; } } catch (NoSuchAlgorithmException e) { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.UNDETERMINED, comparor); result.setResolution(AssuranceResultResolution.PROCESSING_ERROR_ENCOUNTERED); result.setResolutionError(e.getMessage()); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.error(message.append("Error comparing ").append(source).append(" to ") .append(target), e); message.setLength(0); message = null; } catch (IOException e) { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.UNDETERMINED, comparor); result.setResolution(AssuranceResultResolution.PROCESSING_ERROR_ENCOUNTERED); result.setResolutionError(e.getMessage()); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.error(message.append("Error comparing ").append(source).append(" to ") .append(target), e); message.setLength(0); message = null; } } } } } else { ComparisonResult result = new ComparisonResult(source, target, AssuranceResultReason.FILE_NULL, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info(message.append(source).append(" does not match ").append(target)); message.setLength(0); message = null; } } } } private void identifyTargetItemsNotInSource(File source, File target, Scan scan, IFileComparor comparor, IScanOptions options, Collection<FileReference> exclusions, IProgressMonitor monitor) { if (target.isDirectory() && source.isDirectory()) { for (File targetFile : target.listFiles()) { StringBuilder path = new StringBuilder(512); File sourceFile = new File(path.append(source.getPath()).append(File.separator) .append(targetFile.getName()).toString()); path.setLength(0); path = null; // If the source file or target file is in the the global // ignore or exclusion list, just bypass it. // Checking both files in case one is null, in which case // we would have a mismatch. if (((!this.fileIsInGlobalIgnore(sourceFile, options)) && (!this.fileIsInGlobalIgnore(targetFile, options))) && ((!this.fileIsInExclusions(sourceFile, exclusions)) && (!this.fileIsInExclusions(targetFile, exclusions)))) { if (!sourceFile.exists()) { ComparisonResult result = new ComparisonResult(sourceFile, targetFile, AssuranceResultReason.SOURCE_DOES_NOT_EXIST, comparor); scan.addResult(result); result = null; StringBuffer message = new StringBuffer(512); logger.info(message.append(sourceFile).append(" does not exist.")); message.setLength(0); logger.info(message.append(sourceFile).append(" does not match ").append(targetFile)); message.setLength(0); message = null; } } sourceFile = null; targetFile = null; } } } private boolean fileIsInGlobalIgnore(File file, IScanOptions options) { if (file != null) { // NOTE: May want to reconsider the toLowercase conversion. if (options.getIngnoredFileNames().contains(file.getName().toLowerCase())) { return true; } // NOTE: May want to reconsider the toLowercase conversion. if (options.getIngnoredFileExtensions() .contains(FilenameUtils.getExtension(file.getName()).toLowerCase())) { return true; } } return false; } private boolean fileIsInExclusions(File file, Collection<FileReference> exclusions) { if ((file != null) && (exclusions != null)) { for (FileReference exclusion : exclusions) { if (exclusion.getFile().getPath().equals(file.getPath())) { return true; } } } return false; } }