diff --git a/Core/build.xml b/Core/build.xml index 6ea271b16e..00bcca3a01 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -5,11 +5,7 @@ Builds, tests, and runs the project org.sleuthkit.autopsy.core - - - - - + @@ -30,7 +26,6 @@ - diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 718f0bb9fb..dc9774ed72 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -19,15 +19,13 @@ package org.sleuthkit.autopsy.casemodule; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.logging.Level; - import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitJNI; @@ -35,66 +33,220 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; /* - * A background task that adds the given image to database using the Sleuthkit - * JNI interface. - * - * It updates the given ProgressMonitor as it works through adding the image, - * and et the end, calls the specified Callback. + * A runnable that adds an image data source to the case database. */ class AddImageTask implements Runnable { private final Logger logger = Logger.getLogger(AddImageTask.class.getName()); - - private final Case currentCase; - - // true if the process was requested to cancel - private final Object lock = new Object(); // synchronization object for cancelRequested - private volatile boolean cancelRequested = false; - - //true if revert has been invoked. - private boolean reverted = false; - - // true if there was a critical error in adding the data source - private boolean hasCritError = false; - - private final List errorList = new ArrayList<>(); - - private final DataSourceProcessorProgressMonitor progressMonitor; - private final DataSourceProcessorCallback callbackObj; - - private final List newContents = Collections.synchronizedList(new ArrayList()); - - private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; - private Thread dirFetcher; - + private final String deviceId; private final String imagePath; - String timeZone; - boolean noFatOrphans; - - private final String dataSourceId; + private final String timeZone; + private final boolean ignoreFatOrphanFiles; + private final DataSourceProcessorProgressMonitor progressMonitor; + private final DataSourceProcessorCallback callback; + private boolean criticalErrorOccurred; /* - * A thread that updates the progressMonitor with the name of the directory - * currently being processed by the AddImageTask + * The cancellation requested flag and SleuthKit add image process are + * guarded by a monitor (called a lock here to avoid confusion with the + * progress monitor) to synchronize cancelling the process (setting the flag + * and calling its stop method) and calling either its commit or revert + * method. The built-in monitor of the add image process can't be used for + * this because it is already used to synchronize its run (init part), + * commit, revert, and currentDirectory methods. + * + * TODO (AUT-2021): Merge SleuthkitJNI.AddImageProcess and AddImageTask */ - private class CurrentDirectoryFetcher implements Runnable { + private final Object tskAddImageProcessLock; + private boolean tskAddImageProcessStopped; + private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess; - DataSourceProcessorProgressMonitor progressMonitor; - SleuthkitJNI.CaseDbHandle.AddImageProcess process; + /** + * Constructs a runnable task that adds an image to the case database. + * + * @param deviceId An ASCII-printable identifier for the device + * associated with the data source that is + * intended to be unique across multiple cases + * (e.g., a UUID). + * @param imagePath Path to the image file. + * @param timeZone The time zone to use when processing dates + * and times for the image, obtained from + * java.util.TimeZone.getID. + * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a + * FAT filesystem. + * @param progressMonitor Progress monitor to report progress during + * processing. + * @param callback Callback to call when processing is done. + */ + AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { + this.deviceId = deviceId; + this.imagePath = imagePath; + this.timeZone = timeZone; + this.ignoreFatOrphanFiles = ignoreFatOrphanFiles; + this.callback = callback; + this.progressMonitor = progressMonitor; + tskAddImageProcessLock = new Object(); + } - CurrentDirectoryFetcher(DataSourceProcessorProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { - this.progressMonitor = aProgressMonitor; - this.process = proc; + /** + * Adds the image to the case database. + */ + @Override + public void run() { + progressMonitor.setIndeterminate(true); + progressMonitor.setProgress(0); + Case currentCase = Case.getCurrentCase(); + List errorMessages = new ArrayList<>(); + List newDataSources = new ArrayList<>(); + try { + currentCase.getSleuthkitCase().acquireExclusiveLock(); + synchronized (tskAddImageProcessLock) { + tskAddImageProcess = currentCase.makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles); + } + Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess)); + progressUpdateThread.start(); + runAddImageProcess(errorMessages); + if (null != progressUpdateThread) { + progressUpdateThread.interrupt(); + } + commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources); + progressMonitor.setProgress(100); + } finally { + currentCase.getSleuthkitCase().releaseExclusiveLock(); + DataSourceProcessorCallback.DataSourceProcessorResult result; + if (criticalErrorOccurred) { + result = DataSourceProcessorResult.CRITICAL_ERRORS; + } else if (!errorMessages.isEmpty()) { + result = DataSourceProcessorResult.NONCRITICAL_ERRORS; + } else { + result = DataSourceProcessorResult.NO_ERRORS; + } + callback.done(result, errorMessages, newDataSources); + } + } + + /* + * Attempts to cancel adding the image to the case database. + */ + public void cancelTask() { + synchronized (tskAddImageProcessLock) { + if (null != tskAddImageProcess) { + try { + /* + * All this does is set a flag that will make the TSK add + * image process exit when the flag is checked between + * processing steps. The state of the flag is not + * accessible, so record it here so that it is known that + * the revert method of the process object needs to be + * called. + */ + tskAddImageProcess.stop(); + tskAddImageProcessStopped = true; + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error cancelling adding image %s to the case database", imagePath), ex); //NON-NLS + } + } + } + } + + /** + * Runs the TSK add image process. + * + * @param errorMessages Error messages, if any, are added to this list for + * eventual return via the callback. + */ + private void runAddImageProcess(List errorMessages) { + try { + tskAddImageProcess.run(deviceId, new String[]{imagePath}); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Critical error occurred adding image %s", imagePath), ex); //NON-NLS + criticalErrorOccurred = true; + errorMessages.add(ex.getMessage()); + } catch (TskDataException ex) { + logger.log(Level.WARNING, String.format("Non-critical error occurred adding image %s", imagePath), ex); //NON-NLS + errorMessages.add(ex.getMessage()); + } + } + + /** + * Commits or reverts the results of the TSK add image process. If the + * process was stopped before it completed or there was a critical error the + * results are reverted, otherwise they are committed. + * + * @param currentCase The current case. + * @param errorMessages Error messages, if any, are added to this list for + * eventual return via the callback. + * @param newDataSources If the new image is successfully committed, it is + * added to this list for eventual return via the + * callback. + * + * @return + */ + private void commitOrRevertAddImageProcess(Case currentCase, List errorMessages, List newDataSources) { + synchronized (tskAddImageProcessLock) { + if (tskAddImageProcessStopped || criticalErrorOccurred) { + try { + tskAddImageProcess.revert(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error reverting adding image %s to the case database", imagePath), ex); //NON-NLS + errorMessages.add(ex.getMessage()); + criticalErrorOccurred = true; + } + } else { + try { + long imageId = tskAddImageProcess.commit(); + if (imageId != 0) { + Image newImage = currentCase.getSleuthkitCase().getImageById(imageId); + String verificationError = newImage.verifyImageSize(); + if (!verificationError.isEmpty()) { + errorMessages.add(verificationError); + } + newDataSources.add(newImage); + } else { + String errorMessage = String.format("Error commiting adding image %s to the case database, no object id returned", imagePath); //NON-NLS + logger.log(Level.SEVERE, errorMessage); + errorMessages.add(errorMessage); + criticalErrorOccurred = true; + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error committing adding image %s to the case database", imagePath), ex); //NON-NLS + errorMessages.add(ex.getMessage()); + criticalErrorOccurred = true; + } + } + } + } + + /** + * A Runnable that updates the progress monitor with the name of the + * directory currently being processed by the SleuthKit add image process. + */ + private class ProgressUpdater implements Runnable { + + private final DataSourceProcessorProgressMonitor progressMonitor; + private final SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess; + + /** + * Constructs a Runnable that updates the progress monitor with the name + * of the directory currently being processed by the SleuthKit. + * + * @param progressMonitor + * @param tskAddImageProcess + */ + ProgressUpdater(DataSourceProcessorProgressMonitor progressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess) { + this.progressMonitor = progressMonitor; + this.tskAddImageProcess = tskAddImageProcess; } /** - * @return the currently processing directory + * Updates the progress monitor with the name of the directory currently + * being processed by the SleuthKit add image process. */ @Override public void run() { try { while (!Thread.currentThread().isInterrupted()) { - String currDir = process.currentDirectory(); + String currDir = tskAddImageProcess.currentDirectory(); if (currDir != null) { if (!currDir.isEmpty()) { progressMonitor.setProgressText( @@ -102,227 +254,20 @@ class AddImageTask implements Runnable { currDir)); } } - // this sleep here prevents the UI from locking up - // due to too frequent updates to the progressMonitor above + /* + * The sleep here throttles the UI updates and provides a + * non-standard mechanism for completing this task by + * interrupting the thread in which it is running. + * + * TODO (AUT-1870): Replace this with giving the task to a + * java.util.concurrent.ScheduledThreadPoolExecutor that is + * shut down when the main task completes. + */ Thread.sleep(500); } - } catch (InterruptedException ie) { - // nothing to do, thread was interrupted externally - // signaling the end of AddImageProcess + } catch (InterruptedException expected) { } } } - /** - * Constructs a runnable task that adds an image to the case database. - * - * @param dataSourceId An ASCII-printable identifier for the data - * source that is intended to be unique across - * multiple cases (e.g., a UUID). - * @param imagePath Path to the image file. - * @param timeZone The time zone to use when processing dates - * and times for the image, obtained from - * java.util.TimeZone.getID. - * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a - * FAT filesystem. - * @param monitor Progress monitor to report progress during - * processing. - * @param cbObj Callback to call when processing is done. - */ - AddImageTask(String dataSourceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor monitor, DataSourceProcessorCallback cbObj) { - currentCase = Case.getCurrentCase(); - this.dataSourceId = dataSourceId; - this.imagePath = imagePath; - this.timeZone = timeZone; - this.noFatOrphans = ignoreFatOrphanFiles; - this.callbackObj = cbObj; - this.progressMonitor = monitor; - } - - /** - * Starts the addImage process, but does not commit the results. - * - * @return - * - * @throws Exception - */ - @Override - public void run() { - errorList.clear(); - try { - currentCase.getSleuthkitCase().acquireExclusiveLock(); - addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); - dirFetcher = new Thread(new CurrentDirectoryFetcher(progressMonitor, addImageProcess)); - try { - progressMonitor.setIndeterminate(true); - progressMonitor.setProgress(0); - dirFetcher.start(); - addImageProcess.run(dataSourceId, new String[]{imagePath}); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Core errors occurred while running add image on " + imagePath, ex); //NON-NLS - hasCritError = true; - errorList.add(ex.getMessage()); - } catch (TskDataException ex) { - logger.log(Level.WARNING, "Data errors occurred while running add image " + imagePath, ex); //NON-NLS - errorList.add(ex.getMessage()); - } - postProcess(); - } finally { - currentCase.getSleuthkitCase().releaseExclusiveLock(); - } - } - - /** - * Commit the newly added image to DB - * - * - * @throws Exception if commit or adding the image to the case failed - */ - private void commitImage() throws Exception { - - long imageId = 0; - try { - imageId = addImageProcess.commit(); - } catch (TskCoreException e) { - logger.log(Level.WARNING, "Errors occurred while committing the image " + imagePath, e); //NON-NLS - errorList.add(e.getMessage()); - } finally { - if (imageId != 0) { - // get the newly added Image so we can return to caller - Image newImage = currentCase.getSleuthkitCase().getImageById(imageId); - - //while we have the image, verify the size of its contents - String verificationErrors = newImage.verifyImageSize(); - if (verificationErrors.equals("") == false) { - //data error (non-critical) - errorList.add(verificationErrors); - } - - // Add the image to the list of new content - newContents.add(newImage); - } - - logger.log(Level.INFO, "Image committed, imageId: {0}", imageId); //NON-NLS - logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo()); - } - } - - /** - * Post processing after the addImageProcess is done. - * - */ - private void postProcess() { - - // cancel the directory fetcher - dirFetcher.interrupt(); - - if (cancelRequested() || hasCritError) { - logger.log(Level.WARNING, "Critical errors or interruption in add image process on {0}. Image will not be committed.", imagePath); //NON-NLS - revert(); - } - - if (!errorList.isEmpty()) { - logger.log(Level.INFO, "There were errors that occurred in add image process for {0}", imagePath); //NON-NLS - } - - // When everything happens without an error: - if (!(cancelRequested() || hasCritError)) { - try { - if (addImageProcess != null) { - // commit image - try { - commitImage(); - } catch (Exception ex) { - errorList.add(ex.getMessage()); - // Log error/display warning - logger.log(Level.SEVERE, "Error adding image " + imagePath + " to case.", ex); //NON-NLS - } - } else { - logger.log(Level.SEVERE, "Missing image process object"); //NON-NLS - } - - // Tell the progress monitor we're done - progressMonitor.setProgress(100); - } catch (Exception ex) { - //handle unchecked exceptions post image add - errorList.add(ex.getMessage()); - - logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup for " + imagePath, ex); //NON-NLS - logger.log(Level.SEVERE, "Error adding image " + imagePath + " to case", ex); //NON-NLS - } - } - - // invoke the callBack, unless the caller cancelled - if (!cancelRequested()) { - doCallBack(); - } - } - - /* - * Call the callback with results, new content, and errors, if any - */ - private void doCallBack() { - DataSourceProcessorCallback.DataSourceProcessorResult result; - - if (hasCritError) { - result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS; - } else if (!errorList.isEmpty()) { - result = DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS; - } else { - result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS; - } - - // invoke the callback, passing it the result, list of new contents, and list of errors - callbackObj.done(result, errorList, newContents); - } - - /* - * cancel the image addition, if possible - */ - public void cancelTask() { - - synchronized (lock) { - cancelRequested = true; - try { - interrupt(); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Failed to interrupt the add image task..."); //NON-NLS - } - } - } - - /* - * Interrupt the add image process if it is still running - */ - private void interrupt() throws Exception { - - try { - logger.log(Level.INFO, "interrupt() add image process"); //NON-NLS - addImageProcess.stop(); //it might take time to truly stop processing and writing to db - } catch (TskCoreException ex) { - throw new Exception(NbBundle.getMessage(this.getClass(), "AddImageTask.interrupt.exception.msg"), ex); - } - } - - /* - * Revert - if image has already been added but not committed yet - */ - private void revert() { - - if (!reverted) { - logger.log(Level.INFO, "Revert after add image process"); //NON-NLS - try { - addImageProcess.revert(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error reverting add image process", ex); //NON-NLS - } - reverted = true; - } - } - - private boolean cancelRequested() { - synchronized (lock) { - return cancelRequested; - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 1db3ab9c5c..489c713af8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -146,6 +146,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * * @param panel instance of ImageTypePanel to change to */ + @SuppressWarnings("deprecation") private void updateCurrentPanel(JPanel panel) { currentPanel = panel; typePanel.removeAll(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 46114c52fb..6e1d353e22 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -68,6 +68,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { dataSourceProcessorDone(dataSourceId, result, errList, contents); } - }; progressPanel.setStateStarted(); @@ -258,9 +259,6 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { - Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId); - }).start(); dsProcessor.cancel(); } @@ -303,21 +301,23 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { - if (!newContents.isEmpty()) { - Case.getCurrentCase().notifyDataSourceAdded(newContents.get(0), dataSourceId); + if (!contents.isEmpty()) { + Case.getCurrentCase().notifyDataSourceAdded(contents.get(0), dataSourceId); } else { Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId); } }).start(); - // Start ingest if we can - progressPanel.setStateStarted(); - startIngest(); + if (!cancelled) { + newContents.clear(); + newContents.addAll(contents); + progressPanel.setStateStarted(); + startIngest(); + } else { + cancelled = false; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6d0aca0f6e..6615cde7e6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -219,11 +219,11 @@ public class Case implements SleuthkitCase.ErrorObserver { * multi-user (using PostgreSql) */ @NbBundle.Messages({"Case_caseType_singleUser=Single-user case", - "Case_caseType_multiUser=Multi-user case"}) + "Case_caseType_multiUser=Multi-user case"}) public enum CaseType { - SINGLE_USER_CASE(Bundle.Case_caseType_singleUser()), - MULTI_USER_CASE(Bundle.Case_caseType_multiUser()); + SINGLE_USER_CASE("Single-user case"), //NON-NLS + MULTI_USER_CASE("Multi-user case"); //NON-NLS private final String caseType; @@ -250,6 +250,14 @@ public class Case implements SleuthkitCase.ErrorObserver { public String toString() { return caseType; } + + String getLocalizedDisplayName() { + if (fromString(caseType) == SINGLE_USER_CASE) { + return Bundle.Case_caseType_singleUser(); + } else { + return Bundle.Case_caseType_multiUser(); + } + } }; private String name; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java index c9c4d87864..eae7cf228d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java @@ -92,7 +92,7 @@ class CasePropertiesForm extends javax.swing.JPanel { CaseMetadata caseMetadata = new CaseMetadata(Paths.get(currentCase.getConfigFilePath())); tbDbName.setText(caseMetadata.getCaseDatabaseName()); Case.CaseType caseType = caseMetadata.getCaseType(); - tbDbType.setText(caseType.toString()); + tbDbType.setText(caseType.getLocalizedDisplayName()); if (caseType == Case.CaseType.SINGLE_USER_CASE) { deleteCaseButton.setEnabled(true); } else { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java index 0fb3601d88..afa68ac5c3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java @@ -466,7 +466,11 @@ final class CollaborationMonitor { */ @Override public void run() { - eventPublisher.publishRemotely(new CollaborationEvent(hostName, localTasksManager.getCurrentTasks())); + try { + eventPublisher.publishRemotely(new CollaborationEvent(hostName, localTasksManager.getCurrentTasks())); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Unexpected exception in HeartbeatTask", ex); //NON-NLS + } } } @@ -482,7 +486,11 @@ final class CollaborationMonitor { */ @Override public void run() { - remoteTasksManager.finishStaleTasks(); + try { + remoteTasksManager.finishStaleTasks(); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Unexpected exception in StaleTaskDetectionTask", ex); //NON-NLS + } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index be3c9466a7..fa9f92188c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** - * An image file data source processor that implements the DataSourceProcessor + * A image file data source processor that implements the DataSourceProcessor * service provider interface to allow integration with the add data source * wizard. It also provides a run method overload to allow it to be used * independently of the wizard. @@ -81,10 +81,10 @@ public class ImageDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ public static String getType() { return DATA_SOURCE_TYPE; @@ -92,21 +92,23 @@ public class ImageDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ @Override public String getDataSourceType() { - return DATA_SOURCE_TYPE; + return getType(); } /** * Gets the panel that allows a user to select a data source and do any - * configuration the data source processor may require. + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ @Override public JPanel getPanel() { @@ -116,10 +118,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ @Override public boolean isPanelValid() { @@ -127,16 +130,18 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { @@ -151,10 +156,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * given settings instead of those provided by the panel. Returns as soon as - * the background task is started and uses the callback object to signal - * task completion and return results. + * Adds a data source to the case database using a background task in a + * separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. * * @param deviceId An ASCII-printable identifier for the device * associated with the data source that is @@ -176,8 +182,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. */ @Override public void cancel() { @@ -185,7 +194,8 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ @Override public void reset() { @@ -199,7 +209,7 @@ public class ImageDSProcessor implements DataSourceProcessor { /** * Sets the configuration of the data source processor without using the - * configuration panel. + * selection and configuration panel. * * @param imagePath Path to the image file. * @param timeZone The time zone to use when processing dates diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 4d59cd4d91..5c7cca0a59 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -190,7 +190,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents - + @SuppressWarnings("deprecation") private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed String oldText = pathTextField.getText(); // set the current directory of the FileChooser if the ImagePath Field is valid diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index cb80535e01..c699eb740d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -61,10 +61,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ public static String getType() { return DATA_SOURCE_TYPE; @@ -72,10 +72,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ @Override public String getDataSourceType() { @@ -83,10 +83,12 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Gets the JPanel that allows a user to select a data source and do any - * configuration the data source processor may require. + * Gets the panel that allows a user to select a data source and do any + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ @Override public JPanel getPanel() { @@ -95,10 +97,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ @Override public boolean isPanelValid() { @@ -106,16 +109,18 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { @@ -130,10 +135,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * given settings instead of those provided by the panel. Returns as soon as - * the background task is started and uses the callback object to signal - * task completion and return results. + * Adds a data source to the case database using a background task in a + * separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. * * @param deviceId An ASCII-printable identifier for the device * associated with the data source that is @@ -155,8 +161,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. */ @Override public void cancel() { @@ -164,7 +173,8 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ @Override public void reset() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 6d5c028cbb..4eae9e4e7e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -59,10 +59,10 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ public static String getType() { return DATA_SOURCE_TYPE; @@ -70,10 +70,10 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ @Override public String getDataSourceType() { @@ -82,9 +82,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { /** * Gets the panel that allows a user to select a data source and do any - * configuration the data source processor may require. + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ @Override public JPanel getPanel() { @@ -93,10 +95,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ @Override public boolean isPanelValid() { @@ -104,16 +107,18 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { @@ -125,10 +130,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * given settings instead of those provided by the panel. Returns as soon as - * the background task is started and uses the callback object to signal - * task completion and return results. + * Adds a data source to the case database using a background task in a + * separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. * * @param deviceId An ASCII-printable identifier for the * device associated with the data source @@ -151,18 +157,22 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. + * + * TODO (AUT-1907): Implement cancellation by deleting rows added to the + * case database. */ @Override public void cancel() { - /* - * Cancellation is not currently supported. - */ } /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ @Override public void reset() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java index b7b432a9eb..24c1e2a17e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java @@ -239,7 +239,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,56 +23,72 @@ import java.util.List; import org.sleuthkit.datamodel.Content; /** - * Abstract class for a callback for a DataSourceProcessor. - * - * Ensures that DSP invokes the caller overridden method, doneEDT(), in the EDT - * thread. + * An abstract base class for callback objects to be given to data source + * processors for use by the background tasks that add data sources to a case + * database. The callback objects are used to signal task completion and return + * results. * + * Concrete implementations of DataSourceProcessorCallback should override + * either the done method or the doneEDT method, but not both. */ public abstract class DataSourceProcessorCallback { public enum DataSourceProcessorResult { - NO_ERRORS, ///< No errors were encountered while ading the data source - CRITICAL_ERRORS, ///< No data was added to the database. There were fundamental errors processing the data (such as no data or system failure). - NONCRITICAL_ERRORS, ///< There was data added to the database, but there were errors from data corruption or a small number of minor issues. + /** + * No errors occurred while ading the data source to the case database. + */ + NO_ERRORS, + /** + * Critical errors occurred while ading the data source to the case + * database. The data source was not added to the case database. + */ + CRITICAL_ERRORS, + /** + * Non-critical errors occurred while adding the data source to the case + * database. The data source was added to the database, but the data + * source may have been corrupted in some way. + */ + NONCRITICAL_ERRORS }; /** - * Called by a DSP implementation when it is done adding a data source to - * the database. Users of the DSP can override this method if they do not - * want to be notified on the EDT. Otherwise, this method will call - * doneEDT() with the same arguments. + * Called by a data source processor when it is done adding a data source to + * the case database, this method adds a task to call the doneEDT method to + * the EDT task queue. * - * @param result Code for status - * @param errList List of error strings - * @param newContents List of root Content objects that were added to - * database. Typically only one is given. + * IMPORTANT: Concrete implementations of DataSourceProcessorCallback should + * override this method if the callback SHOULD NOT be done in the EDT. + * + * @param result Result code. + * @param errList List of error messages, possibly empty. + * @param newDataSources A list of the data sources added, empty if critical + * errors occurred or processing was successfully + * cancelled. */ - public void done(DataSourceProcessorResult result, List errList, List newContents) { - + public void done(DataSourceProcessorResult result, List errList, List newDataSources) { final DataSourceProcessorResult resultf = result; final List errListf = errList; - final List newContentsf = newContents; - - // Invoke doneEDT() that runs on the EDT . - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - doneEDT(resultf, errListf, newContentsf); - } + final List newContentsf = newDataSources; + EventQueue.invokeLater(() -> { + doneEDT(resultf, errListf, newContentsf); }); } /** - * Called by done() if the default implementation is used. Users of DSPs - * that have UI updates to do after the DSP is finished adding the DS can - * implement this method to receive the updates on the EDT. + * Called by a data source processor when it is done adding a data source to + * the case database, if the default done method has not been overridden. * - * @param result Code for status - * @param errList List of error strings - * @param newContents List of root Content objects that were added to - * database. Typically only one is given. + * IMPORTANT: Concrete implementations of DataSourceProcessorCallback should + * override the done method and provide an implementation of this method + * that throws an UnsupportedOperationException if the callback SHOULD NOT + * be done in the EDT. + * + * @param result Result code. + * @param errList List of error messages, possibly empty. + * @param newDataSources A list of the data sources added, empty if critical + * errors occurred or processing was successfully + * cancelled. */ - public abstract void doneEDT(DataSourceProcessorResult result, List errList, List newContents); + abstract public void doneEDT(DataSourceProcessorResult result, List errList, List newDataSources); }; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java index 04501c4c5b..3584cb5211 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,16 +47,22 @@ import org.sleuthkit.datamodel.SleuthkitJNI; */ public final class AboutWindowPanel extends JPanel implements HyperlinkListener { - private static final Logger Logger = org.sleuthkit.autopsy.coreutils.Logger.getLogger(AboutWindowPanel.class.getName()); - + private static final long serialVersionUID = 1L; private URL url = null; - - private Icon about; - + private final Icon about; private boolean verboseLogging; + public AboutWindowPanel() { + about = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/splash.png")); + init(); + } + public AboutWindowPanel(String pathToBrandingImage) { about = new ImageIcon(ImageUtilities.loadImage(pathToBrandingImage)); + init(); + } + + private void init() { initComponents(); logoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); description.setText(org.openide.util.NbBundle.getMessage(AboutWindowPanel.class, @@ -67,8 +73,7 @@ public final class AboutWindowPanel extends JPanel implements HyperlinkListener copyright.setBackground(getBackground()); if (verboseLoggingIsSet()) { disableVerboseLoggingButton(); - } - + } } // //GEN-BEGIN:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 2db3a4d69b..a0aeb51314 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -148,7 +148,7 @@ FXVideoPanel.progress.bufferingCancelled=media buffering was canceled FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk OptionsCategory_Name_Multi_User_Settings=Multi-user -OptionsCategory_Keywords_Multi_User_Options=Multi-user Options +OptionsCategory_Keywords_Multi_User_Options=Multi-user Settings MultiUserSettingsPanel.lbSolrSettings.text=Solr Settings MultiUserSettingsPanel.cbEnableMultiUser.text=Enable Multi-user cases MultiUserSettingsPanel.lbDatabaseSettings.text=Database Settings diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java index bcb1657314..753483e42c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,38 +23,67 @@ import org.openide.nodes.FilterNode; import org.openide.nodes.Node; /** - * Complementary class to TableFilterNode. + * A children (child factory) implementation for a TableFilterNode. A + * TableFilterNode creates at most one layer of child nodes for the node it + * wraps. It is designed to be used for nodes displayed in Autopsy table views. */ class TableFilterChildren extends FilterNode.Children { /** - * the constructor + * Constructs a children (child factory) implementation for a + * TableFilterNode. A TableFilterNode creates at most one layer of child + * nodes for the node it wraps. It is designed to be used for nodes + * displayed in Autopsy table views. + * + * @param wrappedNode The node wrapped by the TableFilterNode. */ - TableFilterChildren(Node arg) { - super(arg); - } - - @Override - protected Node copyNode(Node arg0) { - return new TableFilterNode(arg0, false); - } - - @Override - protected Node[] createNodes(Node arg0) { - // filter out the children - return new Node[]{this.copyNode(arg0)}; + TableFilterChildren(Node wrappedNode) { + super(wrappedNode); } /** - * Converts the given FsContent into "Children". + * Copies a TableFilterNode, with the create children (child factory) flag + * set to false. * - * @param fs + * @param nodeToCopy The TableFilterNode to copy. * - * @return children + * @return A copy of a TableFilterNode. */ - public static Children createInstance(Node arg, boolean createChild) { - if (createChild) { - return new TableFilterChildren(arg); + @Override + protected Node copyNode(Node nodeToCopy) { + return new TableFilterNode(nodeToCopy, false); + } + + /** + * Creates the child nodes represented by this children (child factory) + * object. + * + * @param key The key, i.e., the node, for which to create the child nodes. + * + * @return + */ + @Override + protected Node[] createNodes(Node key) { + return new Node[]{this.copyNode(key)}; + } + + /** + * Creates a children (child factory) object for a node wrapped in a + * TableFilterNode. A TableFilterNode creates at most one layer of child + * nodes for the node it wraps. It is designed to be used for nodes + * displayed in Autopsy table views. + * + * + * @param wrappedNode The node wrapped by the TableFilterNode. + * @param createChildren True if a children (child factory) object should be + * created for the wrapped node. + * + * @return A children (child factory) object for a node wrapped by a + * TableFilterNode. + */ + public static Children createInstance(Node wrappedNode, boolean createChildren) { + if (createChildren) { + return new TableFilterChildren(wrappedNode); } else { return Children.LEAF; } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java index 11caf66c75..9a524bcbd3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,48 +23,40 @@ import org.openide.nodes.Node; import org.openide.util.NbBundle; /** - * This class is used to filter the nodes that we want to show on the - * "TreeTableView". So basically we just want to show one layer of nodes from - * it's parent. - * - * @author jantonius + * A filter node that creates at most one layer of child nodes for the node it + * wraps. It is designed to be used for nodes displayed in Autopsy table views. */ public class TableFilterNode extends FilterNode { - private boolean createChild; - private String itemType; + private final boolean createChildren; /** - * the constructor - */ - public TableFilterNode(Node arg, boolean crChild) { - super(arg, TableFilterChildren.createInstance(arg, crChild)); - this.createChild = crChild; - this.itemType = ""; - } - - public TableFilterNode(Node arg, boolean crChild, String itemType) { - super(arg, TableFilterChildren.createInstance(arg, crChild)); - this.createChild = crChild; - this.itemType = itemType; - } - - /** - * Override the display name / header for the first (tree) column on the - * "TreeTableView". + * Constructs a filter node that creates at most one layer of child nodes + * for the node it wraps. It is designed to be used for nodes displayed in + * Autopsy table views. * - * @return disName the display name for the first column + * @param wrappedNode The node to wrap in the filter node. + * @param createChildren True if a children (child factory) object should be + * created for the wrapped node. + */ + public TableFilterNode(Node wrappedNode, boolean createChildren) { + super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren)); + this.createChildren = createChildren; + } + + /** + * Returns a display name for the wrapped node, for use in the first column + * of an Autopsy table view. + * + * @return The display name. */ @Override public String getDisplayName() { - if (createChild) { + if (createChildren) { return NbBundle.getMessage(this.getClass(), "TableFilterNode.displayName.text"); } else { return super.getDisplayName(); } } - - public String getItemType() { - return itemType; - } + } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java index dc06466d54..5ac5b95c67 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-16 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -95,16 +95,18 @@ class ThumbnailViewNode extends FilterNode { super.done(); try { iconCache = new SoftReference<>(super.get()); - progressHandle.finish(); fireIconChange(); + } catch (InterruptedException | ExecutionException ex) { + Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon", ex); //NON-NLS + } finally { + progressHandle.finish(); if (timer != null) { timer.stop(); timer = null; + } - } catch (InterruptedException | ExecutionException ex) { - Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon", ex); //NON-NLS + swingWorker = null; } - swingWorker = null; } }; swingWorker.execute(); diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties index 643a4b75f1..f633003d1d 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties @@ -20,8 +20,4 @@ PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, fre PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ {1}\n\ Process Virtual Memory\: {2} -StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract -ImageUtils.GetOrGenerateThumbnailTask.loadingThumbnailFor=Loading thumbnail for {0} -ImageUtils.GetOrGenerateThumbnailTask.generatingPreviewFor=Generating preview for {0} -ImageUtils.ReadImageTask.mesage.text=Reading image\: {0} -VideoUtils.genVideoThumb.progress.text=extracting temporary file {0} +StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index be29d789c9..4e627ea09d 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-15 Basis Technology Corp. + * Copyright 2012-16 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -30,6 +30,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Paths; +import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; @@ -74,10 +75,6 @@ public class ImageUtils { private static final Logger LOGGER = Logger.getLogger(ImageUtils.class.getName()); - private static final String COULD_NOT_WRITE_CACHE_THUMBNAIL = "Could not write cache thumbnail: "; //NOI18N NON-NLS - private static final String COULD_NOT_CREATE_IMAGE_INPUT_STREAM = "Could not create ImageInputStream."; //NOI18N NON-NLS - private static final String NO_IMAGE_READER_FOUND_FOR_ = "No ImageReader found for "; //NOI18N NON-NLS - /** * save thumbnails to disk as this format */ @@ -594,7 +591,7 @@ public class ImageUtils { try (InputStream inputStream = new BufferedInputStream(new ReadContentInputStream(file));) { try (ImageInputStream input = ImageIO.createImageInputStream(inputStream)) { if (input == null) { - IIOException iioException = new IIOException(COULD_NOT_CREATE_IMAGE_INPUT_STREAM); + IIOException iioException = new IIOException("Could not create ImageInputStream."); LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file)); throw iioException; } @@ -613,7 +610,7 @@ public class ImageUtils { reader.dispose(); } } else { - IIOException iioException = new IIOException(NO_IMAGE_READER_FOUND_FOR_ + getContentPathSafe(file)); + IIOException iioException = new IIOException("No ImageReader found."); LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file)); throw iioException; @@ -646,18 +643,19 @@ public class ImageUtils { */ static private class GetThumbnailTask extends ReadImageTaskBase { - private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read image for thumbnail generation."; //NOI18N NON-NLS + private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read {0} for thumbnail generation."; //NOI18N NON-NLS private final int iconSize; private final File cacheFile; private final boolean defaultOnFailure; -// @NbBundle.Messages({"# {0} - file name", -// "GetOrGenerateThumbnailTask.loadingThumbnailFor=Loading thumbnail for {0}", "# {0} - file name", -// "GetOrGenerateThumbnailTask.generatingPreviewFor=Generating preview for {0}"}) + @NbBundle.Messages({"# {0} - file name", + "GetOrGenerateThumbnailTask.loadingThumbnailFor=Loading thumbnail for {0}", + "# {0} - file name", + "GetOrGenerateThumbnailTask.generatingPreviewFor=Generating preview for {0}"}) private GetThumbnailTask(AbstractFile file, int iconSize, boolean defaultOnFailure) { super(file); - updateMessage(NbBundle.getMessage(this.getClass(), "ImageUtils.GetOrGenerateThumbnailTask.loadingThumbnailFor", file.getName())); + updateMessage(Bundle.GetOrGenerateThumbnailTask_loadingThumbnailFor(file.getName())); this.iconSize = iconSize; this.defaultOnFailure = defaultOnFailure; this.cacheFile = getCachedThumbnailLocation(file.getId()); @@ -678,36 +676,39 @@ public class ImageUtils { if (nonNull(cachedThumbnail) && cachedThumbnail.getWidth() == iconSize) { return SwingFXUtils.toFXImage(cachedThumbnail, null); } - } catch (IOException ex) { - LOGGER.log(Level.WARNING, "ImageIO had a problem reading thumbnail for image {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + } catch (Exception ex) { + LOGGER.log(Level.WARNING, "ImageIO had a problem reading the cached thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + cacheFile.delete(); //since we can't read the file we might as well delete it. } } if (isCancelled()) { return null; } + //There was no correctly-sized cached thumbnail so make one. BufferedImage thumbnail = null; - if (VideoUtils.isVideoThumbnailSupported(file)) { if (openCVLoaded) { - updateMessage(NbBundle.getMessage(this.getClass(), "ImageUtils.GetOrGenerateThumbnailTask.generatingPreviewFor", file.getName())); + updateMessage(Bundle.GetOrGenerateThumbnailTask_generatingPreviewFor(file.getName())); thumbnail = VideoUtils.generateVideoThumbnail(file, iconSize); } if (null == thumbnail) { if (defaultOnFailure) { thumbnail = DEFAULT_THUMBNAIL; } else { - throw new IIOException("Failed to generate thumbnail for video file."); + throw new IIOException("Failed to generate a thumbnail for " + getContentPathSafe(file)); } } } else { //read the image into a buffered image. + //TODO: I don't like this, we just converted it from BufferedIamge to fx Image -jm BufferedImage bufferedImage = SwingFXUtils.fromFXImage(readImage(), null); if (null == bufferedImage) { - LOGGER.log(Level.WARNING, FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION); - throw new IIOException(FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION); + String msg = MessageFormat.format(FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION, getContentPathSafe(file)); + LOGGER.log(Level.WARNING, msg); + throw new IIOException(msg); } updateProgress(-1, 1); @@ -716,23 +717,21 @@ public class ImageUtils { thumbnail = ScalrWrapper.resizeFast(bufferedImage, iconSize); } catch (IllegalArgumentException | OutOfMemoryError e) { // if resizing does not work due to extreme aspect ratio or oom, crop the image instead. - LOGGER.log(Level.WARNING, "Could not scale image {0}: " + e.toString() + ". Attemptying to crop {0} instead", ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Cropping {0}, because it could not be scaled: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS final int height = bufferedImage.getHeight(); final int width = bufferedImage.getWidth(); if (iconSize < height || iconSize < width) { final int cropHeight = Math.min(iconSize, height); final int cropWidth = Math.min(iconSize, width); - try { thumbnail = ScalrWrapper.cropImage(bufferedImage, cropWidth, cropHeight); } catch (Exception cropException) { - LOGGER.log(Level.WARNING, "Could not crop image {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS - throw cropException; + LOGGER.log(Level.WARNING, "Could not crop {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS } } } catch (Exception e) { - LOGGER.log(Level.WARNING, "Could not scale image {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Could not scale {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS throw e; } } @@ -744,7 +743,7 @@ public class ImageUtils { updateProgress(-1, 1); //if we got a valid thumbnail save it - if ((cacheFile != null) && nonNull(thumbnail) && DEFAULT_THUMBNAIL != thumbnail) { + if ((cacheFile != null) && thumbnail != null && DEFAULT_THUMBNAIL != thumbnail) { saveThumbnail(thumbnail); } @@ -790,16 +789,16 @@ public class ImageUtils { /** * A task that reads the content of a AbstractFile as a javafx Image. */ + @NbBundle.Messages({ + "# {0} - file name", + "ReadImageTask.mesageText=Reading image: {0}"}) static private class ReadImageTask extends ReadImageTaskBase { ReadImageTask(AbstractFile file) { super(file); - updateMessage(NbBundle.getMessage(this.getClass(), "ImageUtils.ReadImageTask.mesage.text", file.getName())); + updateMessage(Bundle.ReadImageTask_mesageText(file.getName())); } -// @NbBundle.Messages({ -// "# {0} - file name", -// "LoadImageTask.mesageText=Reading image: {0}"}) @Override protected javafx.scene.image.Image call() throws Exception { return readImage(); @@ -811,70 +810,55 @@ public class ImageUtils { */ static private abstract class ReadImageTaskBase extends Task implements IIOReadProgressListener { - private static final String IMAGE_UTILS_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageUtils could not read {0}. It may be unsupported or corrupt"; //NOI18N NON-NLS + private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NOI18N NON-NLS final AbstractFile file; - private ImageReader reader; +// private ImageReader reader; ReadImageTaskBase(AbstractFile file) { this.file = file; } protected javafx.scene.image.Image readImage() throws IOException { - try (InputStream inputStream = new BufferedInputStream(new ReadContentInputStream(file));) { - if (ImageUtils.isGIF(file)) { - //use JavaFX to directly read GIF to preserve potential animation, - javafx.scene.image.Image image = new javafx.scene.image.Image(new BufferedInputStream(inputStream)); - if (image.isError() == false) { - return image; - } - //fall through to default image reading code if there was an error + if (ImageUtils.isGIF(file)) { + //use JavaFX to directly read GIF to preserve potential animation + javafx.scene.image.Image image = new javafx.scene.image.Image(new BufferedInputStream(new ReadContentInputStream(file))); + if (image.isError() == false) { + return image; } - if (isCancelled()) { - return null; - } - try (ImageInputStream input = ImageIO.createImageInputStream(inputStream)) { - if (input == null) { - throw new IIOException(COULD_NOT_CREATE_IMAGE_INPUT_STREAM); - } - Iterator readers = ImageIO.getImageReaders(input); + //fall through to default image reading code if there was an error + } + if (isCancelled()) { + return null; + } - //we use the first ImageReader, is there any point to trying the others? - if (readers.hasNext()) { - reader = readers.next(); - reader.addIIOReadProgressListener(this); - reader.setInput(input); + return getImageProperty(file, "ImageIO could not read {0}: ", + imageReader -> { + imageReader.addIIOReadProgressListener(ReadImageTaskBase.this); /* * This is the important part, get or create a * ImageReadParam, create a destination image to hold * the decoded result, then pass that image with the * param. */ - ImageReadParam param = reader.getDefaultReadParam(); - - BufferedImage bufferedImage = reader.getImageTypes(0).next().createBufferedImage(reader.getWidth(0), reader.getHeight(0)); + ImageReadParam param = imageReader.getDefaultReadParam(); + BufferedImage bufferedImage = imageReader.getImageTypes(0).next().createBufferedImage(imageReader.getWidth(0), imageReader.getHeight(0)); param.setDestination(bufferedImage); try { - bufferedImage = reader.read(0, param); //should always be same bufferedImage object + bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object } catch (IOException iOException) { - // Ignore this exception or display a warning or similar, for exceptions happening during decoding - LOGGER.log(Level.WARNING, IMAGE_UTILS_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N + LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N } finally { - reader.removeIIOReadProgressListener(this); - reader.dispose(); + imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this); } if (isCancelled()) { return null; } return SwingFXUtils.toFXImage(bufferedImage, null); - } else { - throw new IIOException(NO_IMAGE_READER_FOUND_FOR_ + ImageUtils.getContentPathSafe(file)); - } - } - } + }); } @Override - public void imageProgress(ImageReader source, float percentageDone) { + public void imageProgress(ImageReader reader, float percentageDone) { //update this task with the progress reported by ImageReader.read updateProgress(percentageDone, 100); if (isCancelled()) { @@ -890,11 +874,11 @@ public class ImageUtils { try { javafx.scene.image.Image fxImage = get(); if (fxImage == null) { - LOGGER.log(Level.WARNING, IMAGE_UTILS_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT, ImageUtils.getContentPathSafe(file)); + LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT, ImageUtils.getContentPathSafe(file)); } else { if (fxImage.isError()) { //if there was somekind of error, log it - LOGGER.log(Level.WARNING, IMAGE_UTILS_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + ObjectUtils.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file)); + LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + ObjectUtils.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file)); } } } catch (InterruptedException | ExecutionException ex) { @@ -905,7 +889,7 @@ public class ImageUtils { @Override protected void failed() { super.failed(); - LOGGER.log(Level.WARNING, IMAGE_UTILS_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + ObjectUtils.toString(getException()), ImageUtils.getContentPathSafe(file)); + LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + ObjectUtils.toString(getException()), ImageUtils.getContentPathSafe(file)); } @Override @@ -950,7 +934,7 @@ public class ImageUtils { * * @return */ - private static String getContentPathSafe(Content content) { + static String getContentPathSafe(Content content) { try { return content.getUniquePath(); } catch (TskCoreException tskCoreException) { diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java index dc06b75019..58c61e955b 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-16 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.coreutils; +import com.google.common.io.Files; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -91,33 +92,33 @@ public class VideoUtils { return isMediaThumbnailSupported(file, SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS, CONDITIONAL_MIME_TYPES); } + @NbBundle.Messages({"# {0} - file name", + "VideoUtils.genVideoThumb.progress.text=extracting temporary file {0}"}) static BufferedImage generateVideoThumbnail(AbstractFile file, int iconSize) { java.io.File tempFile = getTempVideoFile(file); - - try { - if (tempFile.exists() == false || tempFile.length() < file.getSize()) { - com.google.common.io.Files.createParentDirs(tempFile); - ProgressHandle progress = ProgressHandleFactory.createHandle(NbBundle.getMessage(VideoUtils.class, "VideoUtils.genVideoThumb.progress.text", file.getName())); - progress.start(100); - try { - ContentUtils.writeToFile(file, tempFile, progress, null, true); - } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Error buffering file", ex); //NON-NLS - } + if (tempFile.exists() == false || tempFile.length() < file.getSize()) { + ProgressHandle progress = ProgressHandleFactory.createHandle(Bundle.VideoUtils_genVideoThumb_progress_text(file.getName())); + progress.start(100); + try { + Files.createParentDirs(tempFile); + ContentUtils.writeToFile(file, tempFile, progress, null, true); + } catch (IOException ex) { + LOGGER.log(Level.WARNING, "Error extracting temporary file for " + ImageUtils.getContentPathSafe(file), ex); //NON-NLS + } finally { progress.finish(); } - } catch (IOException ex) { - return null; } VideoCapture videoFile = new VideoCapture(); // will contain the video if (!videoFile.open(tempFile.toString())) { + LOGGER.log(Level.WARNING, "Error opening {0} for preview generation.", ImageUtils.getContentPathSafe(file)); //NON-NLS return null; } double fps = videoFile.get(CV_CAP_PROP_FPS); // gets frame per second double totalFrames = videoFile.get(CV_CAP_PROP_FRAME_COUNT); // gets total frames if (fps <= 0 || totalFrames <= 0) { + LOGGER.log(Level.WARNING, "Error getting fps or total frames for {0}", ImageUtils.getContentPathSafe(file)); //NON-NLS return null; } double milliseconds = 1000 * (totalFrames / fps); //total milliseconds @@ -132,10 +133,12 @@ public class VideoUtils { for (int x = 0; x < THUMB_COLUMNS; x++) { for (int y = 0; y < THUMB_ROWS; y++) { if (!videoFile.set(CV_CAP_PROP_POS_MSEC, timestamp + x * framkeskip + y * framkeskip * THUMB_COLUMNS)) { + LOGGER.log(Level.WARNING, "Error seeking to " + timestamp + "ms in {0}", ImageUtils.getContentPathSafe(file)); //NON-NLS break; // if we can't set the time, return black for that frame } //read the frame into the image/matrix if (!videoFile.read(imageMatrix)) { + LOGGER.log(Level.WARNING, "Error reading frames at " + timestamp + "ms from {0}", ImageUtils.getContentPathSafe(file)); //NON-NLS break; //if the image for some reason is bad, return black for that frame } diff --git a/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java b/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java index 6b679415f9..5fe17a57ef 100644 --- a/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java +++ b/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java @@ -40,7 +40,7 @@ public final class AutopsyEventPublisher { * Composed of thread-safe objects. */ private static final Logger logger = Logger.getLogger(AutopsyEventPublisher.class.getName()); - private static final int MAX_REMOTE_EVENT_PUBLISH_TRIES = 3; + private static final int MAX_REMOTE_EVENT_PUBLISH_TRIES = 1; private final LocalEventPublisher localPublisher; private RemoteEventPublisher remotePublisher; private String currentChannelName; @@ -86,15 +86,8 @@ public final class AutopsyEventPublisher { * events from other Autopsy nodes. */ public void closeRemoteEventChannel() { + stopRemotePublisher(); currentChannelName = null; - if (null != remotePublisher) { - try { - remotePublisher.stop(); - } catch (JMSException ex) { - logger.log(Level.SEVERE, "Error closing remote event channel", ex); //NON-NLS - } - remotePublisher = null; - } } /** @@ -162,12 +155,10 @@ public final class AutopsyEventPublisher { * @param event The event to publish. */ public void publishRemotely(AutopsyEvent event) { - /* - * This is a no-op if a remote channel has not been opened. - */ if (null != currentChannelName) { boolean published = false; int tryCount = 1; + while (false == published && tryCount <= MAX_REMOTE_EVENT_PUBLISH_TRIES) { try { if (null == remotePublisher) { @@ -175,16 +166,28 @@ public final class AutopsyEventPublisher { } remotePublisher.publish(event); published = true; - } catch (JMSException ex) { + } catch (AutopsyEventException | JMSException ex) { logger.log(Level.SEVERE, String.format("Failed to publish %s using channel %s (tryCount = %s)", event.getPropertyName(), currentChannelName, tryCount), ex); //NON-NLS - closeRemoteEventChannel(); - ++tryCount; - } catch (AutopsyEventException ex) { - logger.log(Level.SEVERE, String.format("Failed to reopen channel %s to publish %s event (tryCount = %s)", currentChannelName, event.getPropertyName(), tryCount), ex); //NON-NLS + stopRemotePublisher(); ++tryCount; } } - } + } + } + + /** + * Stops the remote event publisher, but does not reset the current channel + * name. + */ + private void stopRemotePublisher() { + if (null != remotePublisher) { + try { + remotePublisher.stop(); + } catch (JMSException ex) { + logger.log(Level.SEVERE, String.format("Error closing remote event publisher for channel %s", currentChannelName), ex); //NON-NLS + } + remotePublisher = null; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index ba1e445d8a..ad71c7e523 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -115,5 +115,5 @@ IngestJob.cancelReason.notCancelled.text=Not cancelled IngestJob.cancelReason.cancelledByUser.text=Cancelled by user IngestJob.cancelReason.ingestModStartFail.text=Ingest modules startup failed IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space -IngestJob.cancelReason.servicesDown.text=Not cancelled +IngestJob.cancelReason.servicesDown.text=Services Down IngestJob.cancelReason.caseClosed.text=Case closed diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index b11134b1ac..68034d6409 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -1,116 +1,115 @@ -CTL_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8 -HINT_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8\u30A6\u30A3\u30F3\u30C9\u30A6 -IngestDialog.closeButton.title=\u9589\u3058\u308B -IngestDialog.startButton.title=\u958B\u59CB -IngestDialog.title.text=\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestJob.progress.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -IngestJob.progress.dataSourceIngest.displayName={1}\u306E{0} -IngestJob.progress.fileIngest.displayName={0}\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u89E3\u6790\u4E2D -IngestManager.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestManager.StartIngestJobsTask.run.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -IngestManager.StartIngestJobsTask.run.displayName=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u958B\u59CB\u4E2D -IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30BD\u30FC\u30B9\u3001\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u3001\u8A73\u7D30\u304A\u3088\u3073\u30C7\u30FC\u30BF\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.exception.srcSubjNotNull.msg=\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.exception.typeSrcSubjNotNull.msg=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7\u3001\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.toString.data.text=\ \u30C7\u30FC\u30BF\uFF1A{0} -IngestMessage.toString.date.text=\ \u65E5\u4ED8\uFF1A{0} -IngestMessage.toString.details.text=\ \u8A73\u7D30\uFF1A{0} -IngestMessage.toString.subject.text=\ \u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\uFF1A{0} -IngestMessage.toString.type.text=\u30BF\u30A4\u30D7\uFF1A{0} -IngestMessageDetailsPanel.copyMenuItem.text=\u30B3\u30D4\u30FC -IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30C6\u30AD\u30B9\u30C8\uFF0Fhtml -IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E -IngestMessageDetailsPanel.viewArtifactButton.text=\u7D50\u679C\u3078\u79FB\u52D5 -IngestMessageDetailsPanel.viewContentButton.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3078\u79FB\u52D5 -IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30D6\u30FC\u30EB\u5024\u3067\u306F\u306A\u3044\u3082\u306E\u306BBooleanRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002 -IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65E5\u4ED8\u3067\u306F\u306A\u3044\u3082\u306E\u306BDateRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002 -IngestMessagePanel.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestMessagePanel.MsgTableMod.colNames.module=\u30E2\u30B8\u30E5\u30FC\u30EB -IngestMessagePanel.MsgTableMod.colNames.new=\u65B0\u898F\uFF1F -IngestMessagePanel.MsgTableMod.colNames.num=\u756A\u53F7 -IngestMessagePanel.MsgTableMod.colNames.subject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 -IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7 -IngestMessagePanel.sortByComboBox.model.priority=\u512A\u5148\u5EA6 +CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8 +HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6 +IngestDialog.closeButton.title=\u9589\u3058\u308b +IngestDialog.startButton.title=\u958b\u59cb +IngestDialog.title.text=\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0} +IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d +IngestManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestManager.StartIngestJobsTask.run.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestManager.StartIngestJobsTask.run.displayName=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u958b\u59cb\u4e2d +IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30bd\u30fc\u30b9\u3001\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u3001\u8a73\u7d30\u304a\u3088\u3073\u30c7\u30fc\u30bf\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.exception.srcSubjNotNull.msg=\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.exception.typeSrcSubjNotNull.msg=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u3001\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.toString.data.text=\ \u30c7\u30fc\u30bf\uff1a{0} +IngestMessage.toString.date.text=\ \u65e5\u4ed8\uff1a{0} +IngestMessage.toString.details.text=\ \u8a73\u7d30\uff1a{0} +IngestMessage.toString.subject.text=\ \u30b5\u30d6\u30b8\u30a7\u30af\u30c8\uff1a{0} +IngestMessage.toString.type.text=\u30bf\u30a4\u30d7\uff1a{0} +IngestMessageDetailsPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30c6\u30ad\u30b9\u30c8\uff0fhtml +IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +IngestMessageDetailsPanel.viewArtifactButton.text=\u7d50\u679c\u3078\u79fb\u52d5 +IngestMessageDetailsPanel.viewContentButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u79fb\u52d5 +IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30d6\u30fc\u30eb\u5024\u3067\u306f\u306a\u3044\u3082\u306e\u306bBooleanRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002 +IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65e5\u4ed8\u3067\u306f\u306a\u3044\u3082\u306e\u306bDateRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002 +IngestMessagePanel.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestMessagePanel.MsgTableMod.colNames.module=\u30e2\u30b8\u30e5\u30fc\u30eb +IngestMessagePanel.MsgTableMod.colNames.new=\u65b0\u898f\uff1f +IngestMessagePanel.MsgTableMod.colNames.num=\u756a\u53f7 +IngestMessagePanel.MsgTableMod.colNames.subject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8 +IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7 +IngestMessagePanel.sortByComboBox.model.priority=\u512a\u5148\u5ea6 IngestMessagePanel.sortByComboBox.model.time=\u6642\u9593 -IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uFF08\u6642\u7CFB\u5217\uFF09\u307E\u305F\u306F\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u512A\u5148\u5EA6\u3067\u30BD\u30FC\u30C8 -IngestMessagePanel.sortByLabel.text=\u6B21\u3067\u30BD\u30FC\u30C8\uFF1A -IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8A08\uFF1A +IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uff08\u6642\u7cfb\u5217\uff09\u307e\u305f\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u512a\u5148\u5ea6\u3067\u30bd\u30fc\u30c8 +IngestMessagePanel.sortByLabel.text=\u6b21\u3067\u30bd\u30fc\u30c8\uff1a +IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8a08\uff1a IngestMessagePanel.totalMessagesNameVal.text=- -IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30E6\u30CB\u30FC\u30AF\uFF1A +IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30e6\u30cb\u30fc\u30af\uff1a IngestMessagePanel.totalUniqueMessagesNameVal.text=- -IngestMessagesToolbar.customizeButton.toolTipText=\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMessageTopComponent.displayName=\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMessageTopComponent.displayReport.option.GenRpt=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 +IngestMessagesToolbar.customizeButton.toolTipText=\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMessageTopComponent.displayName=\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMessageTopComponent.displayReport.option.GenRpt=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 IngestMessageTopComponent.displayReport.option.OK=OK -IngestMessageTopComponent.initComponents.name=\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30EC\u30DD\u30FC\u30C8\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30C7\u30A3\u30B9\u30AF{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3\u306E\u305F\u3081\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3059\u3002\n\u30B1\u30FC\u30B9\u30C9\u30E9\u30A4\u30D6\u306B\u6700\u4F4E1GB\u306E\u7A7A\u304D\u9818\u57DF\u304C\u3042\u308B\u306E\u3092\u78BA\u8A8D\u3057\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002 -IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u4E2D\u6B62\u3055\u308C\u307E\u3057\u305F\u30FC{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3 -OpenIDE-Module-Name=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30A8\u30E9\u30FC\uFF1A\n{0} -IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\u5358\u6570\u307E\u305F\u306F\u8907\u6570\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30B9\u30BF\u30FC\u30C8\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u306F\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002 -IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305F\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u7121\u52B9\u5316\u3059\u308B\u304B\u30A8\u30E9\u30FC\u3092\u89E3\u6C7A\u3057\u3001\u305D\u306E\u5F8C\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u53F3\u30AF\u30EA\u30C3\u30AF\u3057\u3001\n\u300C\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u5B9F\u884C\u300D\u3092\u9078\u629E\u3057\u3066\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002 -IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u5931\u6557 -IngestJobSettings.createModuleSettingsFolder.warning=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u8A2D\u5B9A\u30D5\u30A9\u30EB\u30C0\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3002 -IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89E3\u6790\u4E2D -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7D4C\u904E\u6642\u9593\uFF08\u6642\uFF1A\u5206\uFF1A\u79D2\uFF09 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30D5\u30A1\u30A4\u30EB -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958B\u59CB\u6642\u9593 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30B9\u30EC\u30C3\u30C9ID -IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306E\u30A8\u30E9\u30FC\u304A\u3088\u3073\u307E\u305F\u306F\u8B66\u544A\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F\u3002\u3055\u3089\u306A\u308B\u30A8\u30E9\u30FC\uFF0F\u8B66\u544A\u306F\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\uFF08\u30D8\u30EB\u30D7->\u30ED\u30B0\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u958B\u304F\uFF09 -IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306E\u30A8\u30E9\u30FC\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F -IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30DE\u30CD\u30B8\u30E3\u30FC -IngestManager.IngestThreadActivitySnapshot.idleThread=\u30A2\u30A4\u30C9\u30EB -IngestProgressSnapshotDialog.title.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30D7\u30ED\u30B0\u30EC\u30B9\u30FB\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8 -IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308B -IngestProgressSnapshotPanel.refreshButton.text=\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3 -IngestJobSettingsPanel.advancedButton.actionCommand=\u30A2\u30C9\u30D0\u30F3\u30B9 -IngestJobSettingsPanel.advancedButton.text=\u30A2\u30C9\u30D0\u30F3\u30B9 +IngestMessageTopComponent.initComponents.name=\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30ec\u30dd\u30fc\u30c8\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30c7\u30a3\u30b9\u30af{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3\u306e\u305f\u3081\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u4e2d\u6b62\u3057\u307e\u3059\u3002\n\u30b1\u30fc\u30b9\u30c9\u30e9\u30a4\u30d6\u306b\u6700\u4f4e1GB\u306e\u7a7a\u304d\u9818\u57df\u304c\u3042\u308b\u306e\u3092\u78ba\u8a8d\u3057\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002 +IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u4e2d\u6b62\u3055\u308c\u307e\u3057\u305f\u30fc{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3 +OpenIDE-Module-Name=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30a8\u30e9\u30fc\uff1a\n{0} +IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\u5358\u6570\u307e\u305f\u306f\u8907\u6570\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30b9\u30bf\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002 +IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305f\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u7121\u52b9\u5316\u3059\u308b\u304b\u30a8\u30e9\u30fc\u3092\u89e3\u6c7a\u3057\u3001\u305d\u306e\u5f8c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001\n\u300c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u5b9f\u884c\u300d\u3092\u9078\u629e\u3057\u3066\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002 +IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5931\u6557 +IngestJobSettings.createModuleSettingsFolder.warning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u8a2d\u5b9a\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 +IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89e3\u6790\u4e2d +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7d4c\u904e\u6642\u9593\uff08\u6642\uff1a\u5206\uff1a\u79d2\uff09 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30d5\u30a1\u30a4\u30eb +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958b\u59cb\u6642\u9593 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30b9\u30ec\u30c3\u30c9ID +IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306e\u30a8\u30e9\u30fc\u304a\u3088\u3073\u307e\u305f\u306f\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f\u3002\u3055\u3089\u306a\u308b\u30a8\u30e9\u30fc\uff0f\u8b66\u544a\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\uff08\u30d8\u30eb\u30d7->\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u304f\uff09 +IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306e\u30a8\u30e9\u30fc\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f +IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30de\u30cd\u30b8\u30e3\u30fc +IngestManager.IngestThreadActivitySnapshot.idleThread=\u30a2\u30a4\u30c9\u30eb +IngestProgressSnapshotDialog.title.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30b0\u30ec\u30b9\u30fb\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 +IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308b +IngestProgressSnapshotPanel.refreshButton.text=\u30ea\u30d5\u30ec\u30c3\u30b7\u30e5 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 +IngestJobSettingsPanel.advancedButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9 +IngestJobSettingsPanel.advancedButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9 ModuleTableModel.colName.duration=\u6240\u8981\u6642\u9593 -IngestJob.cancellationDialog.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB -IngestJobSettings.missingModule.warning=\u4EE5\u524D\u306B\u8AAD\u307F\u8FBC\u3093\u3060{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u5168\u3066\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AD\u30E3\u30F3\u30BB\u30EB -DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=\u73FE\u5728\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u307F\u30AD\u30E3\u30F3\u30BB\u30EB -FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u306E\u307F\u30AD\u30E3\u30F3\u30BB\u30EB -FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304A\u3088\u3073\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB -IngestJobSettings.moduleSettingsLoad.warning={1}\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u7528\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002 -IngestJobSettings.save.warning={0}\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -IngestJobTableModel.colName.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9 -IngestJobTableModel.colName.dirQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA -IngestJobTableModel.colName.filesPerSec=\u30D5\u30A1\u30A4\u30EB\uFF0F\u79D2 -IngestJobTableModel.colName.filesQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB -IngestJobTableModel.colName.inProgress=\u51E6\u7406\u4E2D -IngestJobTableModel.colName.jobID=\u30B8\u30E7\u30D6ID -IngestJobTableModel.colName.numProcessed=\u51E6\u7406\u3055\u308C\u305F\u6570 -IngestJobTableModel.colName.rootQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30EB\u30FC\u30C8 -IngestJobTableModel.colName.start=\u30B9\u30BF\u30FC\u30C8 -IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u540D\u524D\u3092\u91CD\u8907\u3059\u308B\u3001{0}\u306E\u540D\u524D\u3092\u6301\u3064\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u4F7F\u7528\u3057\u307E\u305B\u3093\u3002 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30B8\u30E7\u30D6ID -ModuleTableModel.colName.module=\u30E2\u30B8\u30E5\u30FC\u30EB -IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524A\u9664\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u7B49\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u3092\u51E6\u7406\u3002\u3088\u308A\u5B8C\u5168\u306A\u7D50\u679C\u304C\u51FA\u307E\u3059\u304C\u3001\u5927\u304D\u3044\u30A4\u30E1\u30FC\u30B8\u3067\u306F\u51E6\u7406\u6642\u9593\u304C\u9577\u304F\u306A\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 +IngestJob.cancellationDialog.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb +IngestJobSettings.missingModule.warning=\u4ee5\u524d\u306b\u8aad\u307f\u8fbc\u3093\u3060{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u5168\u3066\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30ad\u30e3\u30f3\u30bb\u30eb +DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=\u73fe\u5728\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u307f\u30ad\u30e3\u30f3\u30bb\u30eb +FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u307f\u30ad\u30e3\u30f3\u30bb\u30eb +FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304a\u3088\u3073\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb +IngestJobSettings.moduleSettingsLoad.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u3092\u4f7f\u7528\u3057\u3066\u3044\u307e\u3059\u3002 +IngestJobSettings.save.warning={0}\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +IngestJobTableModel.colName.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +IngestJobTableModel.colName.dirQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea +IngestJobTableModel.colName.filesPerSec=\u30d5\u30a1\u30a4\u30eb\uff0f\u79d2 +IngestJobTableModel.colName.filesQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb +IngestJobTableModel.colName.inProgress=\u51e6\u7406\u4e2d +IngestJobTableModel.colName.jobID=\u30b8\u30e7\u30d6ID +IngestJobTableModel.colName.numProcessed=\u51e6\u7406\u3055\u308c\u305f\u6570 +IngestJobTableModel.colName.rootQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30eb\u30fc\u30c8 +IngestJobTableModel.colName.start=\u30b9\u30bf\u30fc\u30c8 +IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u540d\u524d\u3092\u91cd\u8907\u3059\u308b\u3001{0}\u306e\u540d\u524d\u3092\u6301\u3064\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u4f7f\u7528\u3057\u307e\u305b\u3093\u3002 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30b8\u30e7\u30d6ID +ModuleTableModel.colName.module=\u30e2\u30b8\u30e5\u30fc\u30eb +IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u7b49\u306e\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u51e6\u7406\u3002\u3088\u308a\u5b8c\u5168\u306a\u7d50\u679c\u304c\u51fa\u307e\u3059\u304c\u3001\u5927\u304d\u3044\u30a4\u30e1\u30fc\u30b8\u3067\u306f\u51e6\u7406\u6642\u9593\u304c\u9577\u304f\u306a\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 -IngestJobSettingsPanel.processUnallocCheckbox.text=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u51E6\u7406 -Menu/Tools/RunIngestModules=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C -IngestJob.progress.fileIngest.cancelMessage={1}\u306E{0}\u3092\u5F85\u3063\u3066\u3044\u307E\u3059 -IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306E\u30B1\u30FC\u30B9\u3067\u4F7F\u308F\u308C\u3066\u3044\u308B\u304B\u3082\u3057\u308C\u306A\u3044\u4ED6\u306E\u30CE\u30FC\u30C9\u306B\u89E3\u6790\u30D7\u30ED\u30BB\u30B9\u304C\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -IngestManager.OpenEventChannel.Fail.Title=\u63A5\u7D9A\u5931\u6557 -IngestJobSettings.moduleSettingsSave.warning={1}\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u7528\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -IngestJobTableModel.colName.dsQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305FDS -IngestJobSettingsPanel.jButtonSelectAll.text=\u5168\u3066\u9078\u629E -IngestJobSettingsPanel.jButtonDeselectAll.text=\u5168\u3066\u9078\u629E\u89E3\u9664 -IngestManager.cancellingIngest.msgDlg.text=\u73FE\u5728\u5B9F\u884C\u4E2D\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D -IngestManager.serviceIsDown.msgDlg.text={0}\u304C\u30C0\u30A6\u30F3\u3057\u3066\u3044\u307E\u3059 -RunIngestSubMenu.menuItem.empty=\u30FC\u7A7A\u767D\u30FC -RunIngestModulesMenu.getName.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C -DataSourceIngestPipeline.moduleError.title.text={0}\u30A8\u30E9\u30FC -FileIngestPipeline.moduleError.title.text={0}\u30A8\u30E9\u30FC -IngestJob.cancelReason.notCancelled.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -IngestJob.cancelReason.cancelledByUser.text=\u30E6\u30FC\u30B6\u30FC\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F -IngestJob.cancelReason.ingestModStartFail.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u8D77\u52D5\u306B\u5931\u6557 -IngestJob.cancelReason.outOfDiskSpace.text=\u30C7\u30A3\u30B9\u30AF\u30B9\u30DA\u30FC\u30B9\u304C\u8DB3\u308A\u307E\u305B\u3093 -IngestJob.cancelReason.servicesDown.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F -IngestJob.cancelReason.caseClosed.text=\u30B1\u30FC\u30B9\u3092\u9589\u3058\u307E\u3057\u305F +IngestJobSettingsPanel.processUnallocCheckbox.text=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u306e\u51e6\u7406 +Menu/Tools/RunIngestModules=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c +IngestJob.progress.fileIngest.cancelMessage={1}\u306e{0}\u3092\u5f85\u3063\u3066\u3044\u307e\u3059 +IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306e\u30b1\u30fc\u30b9\u3067\u4f7f\u308f\u308c\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u4ed6\u306e\u30ce\u30fc\u30c9\u306b\u89e3\u6790\u30d7\u30ed\u30bb\u30b9\u304c\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +IngestManager.OpenEventChannel.Fail.Title=\u63a5\u7d9a\u5931\u6557 +IngestJobSettings.moduleSettingsSave.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +IngestJobTableModel.colName.dsQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305fDS +IngestJobSettingsPanel.jButtonSelectAll.text=\u5168\u3066\u9078\u629e +IngestJobSettingsPanel.jButtonDeselectAll.text=\u5168\u3066\u9078\u629e\u89e3\u9664 +IngestManager.cancellingIngest.msgDlg.text=\u73fe\u5728\u5b9f\u884c\u4e2d\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d +IngestManager.serviceIsDown.msgDlg.text={0}\u304c\u30c0\u30a6\u30f3\u3057\u3066\u3044\u307e\u3059 +RunIngestSubMenu.menuItem.empty=\u30fc\u7a7a\u767d\u30fc +RunIngestModulesMenu.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c +DataSourceIngestPipeline.moduleError.title.text={0}\u30a8\u30e9\u30fc +FileIngestPipeline.moduleError.title.text={0}\u30a8\u30e9\u30fc +IngestJob.cancelReason.notCancelled.text=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +IngestJob.cancelReason.cancelledByUser.text=\u30e6\u30fc\u30b6\u30fc\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f +IngestJob.cancelReason.ingestModStartFail.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u8d77\u52d5\u306b\u5931\u6557 +IngestJob.cancelReason.outOfDiskSpace.text=\u30c7\u30a3\u30b9\u30af\u30b9\u30da\u30fc\u30b9\u304c\u8db3\u308a\u307e\u305b\u3093 +IngestJob.cancelReason.caseClosed.text=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u307e\u3057\u305f diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java index de15f82949..827bbc016d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,8 +39,10 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.python.util.PythonObjectInputStream; /** - * Encapsulates the ingest job settings for a particular context such as the Add - * Data Source wizard or the Run Ingest Modules dialog. + * Encapsulates the ingest job settings for a particular execution context. + * Examples of execution contexts include the add data source wizard and the run + * ingest modules dialog. Different execution conterxts may have different + * ingest job settings. */ public class IngestJobSettings { @@ -60,19 +62,30 @@ public class IngestJobSettings { private boolean processUnallocatedSpace; private final List warnings; - // Determines which modeules to run + /** + * The type of ingest modules to run. + */ public enum IngestType { - // Run all modules + /** + * Run both data source level and file-level ingest modules. + */ ALL_MODULES, - // Run only data source modules + /** + * Run only data source level ingest modules. + */ DATA_SOURCE_ONLY, - // Run only files modules + /** + * Run only file level ingest modules. + */ FILES_ONLY } /** - * Constructs an ingest job settings object for a given context. + * Constructs an ingest job settings object for a given execution context. + * Examples of execution contexts include the add data source wizard and the + * run ingest modules dialog. Different execution conterxts may have + * different ingest job settings. * * @param executionContext The ingest execution context identifier. */ @@ -87,7 +100,10 @@ public class IngestJobSettings { } /** - * Constructs an ingest job settings object for a given context. + * Constructs an ingest job settings object for a given context. Examples of + * execution contexts include the add data source wizard and the run ingest + * modules dialog. Different execution conterxts may have different ingest + * job settings. * * @param context The context identifier string. * @param ingestType The type of modules ingest is running. @@ -116,9 +132,12 @@ public class IngestJobSettings { } /** - * Get the ingest execution context identifier. + * Gets the ingest execution context identifier. Examples of execution + * contexts include the add data source wizard and the run ingest modules + * dialog. Different execution conterxts may have different ingest job + * settings. * - * @return The context string. + * @return The execution context identifier. */ String getExecutionContext() { return this.executionContext; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index f528cba6e6..c196caba8a 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -71,28 +71,27 @@ public class IngestManager { private static IngestManager instance; private final Object ingestMessageBoxLock = new Object(); - /** - * The ingest manager maintains a mapping of ingest job IDs to running + /* + * The ingest manager maintains a mapping of ingest job ids to running * ingest jobs. */ - private final ConcurrentHashMap jobsById; + private final Map jobsById; - /** + /* * Each runnable/callable task the ingest manager submits to its thread * pools is given a unique thread/task ID. */ private final AtomicLong nextThreadId; - /** - * Ingest jobs may be queued to be started on a pool thread by ingest job - * starters. A mapping of thread/task IDs to the result objects associated - * with each ingest job starter is maintained to provide handles that can be - * used to cancel the ingest job starter. + /* + * Ingest jobs may be queued to be started on a pool thread by start ingest + * job tasks. A mapping of task ids to the Future objects for each task is + * maintained to allow for task cancellation. */ - private final ConcurrentHashMap> ingestJobStarters; + private final Map> startIngestJobTasks; private final ExecutorService startIngestJobsThreadPool; - /** + /* * Ingest jobs use an ingest task scheduler to break themselves down into * data source level and file level tasks. The ingest scheduler puts these * ingest tasks into queues for execution on ingest manager pool threads by @@ -118,14 +117,14 @@ public class IngestManager { private AutopsyEventPublisher moduleEventPublisher; private final ExecutorService eventPublishingExecutor; - /** + /* * The ingest manager uses an ingest monitor to determine when system * resources are under pressure. If the monitor detects such a situation, it * calls back to the ingest manager to cancel all ingest jobs in progress. */ private final IngestMonitor ingestMonitor; - /** + /* * The ingest manager provides access to a top component that is used by * ingest module to post messages for the user. A count of the posts is used * as a cap to avoid bogging down the application. @@ -134,7 +133,7 @@ public class IngestManager { private volatile IngestMessageTopComponent ingestMessageBox; private final AtomicLong ingestErrorMessagePosts; - /** + /* * The ingest manager supports reporting of ingest processing progress by * collecting snapshots of the activities of the ingest threads, ingest job * progress, and ingest module run times. @@ -142,13 +141,13 @@ public class IngestManager { private final ConcurrentHashMap ingestThreadActivitySnapshots; private final ConcurrentHashMap ingestModuleRunTimes; - /** + /* * The ingest job creation capability of the ingest manager can be turned on * and off to support an orderly shut down of the application. */ private volatile boolean jobCreationIsEnabled; - /** + /* * Ingest manager subscribes to service outage notifications. If key * services are down, ingest manager cancels all ingest jobs in progress. */ @@ -264,8 +263,8 @@ public class IngestManager { this.dataSourceIngestThreadPool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("IM-data-source-ingest-%d").build()); //NON-NLS this.startIngestJobsThreadPool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("IM-start-ingest-jobs-%d").build()); //NON-NLS this.nextThreadId = new AtomicLong(0L); - this.jobsById = new ConcurrentHashMap<>(); - this.ingestJobStarters = new ConcurrentHashMap<>(); + this.jobsById = new HashMap<>(); + this.startIngestJobTasks = new ConcurrentHashMap<>(); this.servicesMonitor = ServicesMonitor.getInstance(); subscribeToServiceMonitorEvents(); @@ -329,7 +328,7 @@ public class IngestManager { public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue().equals(ServicesMonitor.ServiceStatus.DOWN.toString())) { - // check whether a milti-user case is currently being processed + // check whether a multi-user case is currently being processed try { if (!Case.isCaseOpen() || Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) { return; @@ -474,13 +473,13 @@ public class IngestManager { * @param dataSources The data sources to process. * @param settings The settings for the ingest job. */ - public synchronized void queueIngestJob(Collection dataSources, IngestJobSettings settings) { - if (this.jobCreationIsEnabled) { + public void queueIngestJob(Collection dataSources, IngestJobSettings settings) { + if (jobCreationIsEnabled) { IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive()); if (job.hasIngestPipeline()) { long taskId = nextThreadId.incrementAndGet(); Future task = startIngestJobsThreadPool.submit(new StartIngestJobTask(taskId, job)); - ingestJobStarters.put(taskId, task); + startIngestJobTasks.put(taskId, task); } } } @@ -544,20 +543,18 @@ public class IngestManager { ingestMonitor.start(); } - /** - * Add the job to the jobs map now so that isIngestRunning() will - * return true while the modules read global settings during start - * up. This works because the core global settings panels restrict - * changes while analysis is in progress. - */ - this.jobsById.put(job.getId(), job); + synchronized (jobsById) { + jobsById.put(job.getId(), job); + } List errors = job.start(); if (errors.isEmpty()) { this.fireIngestJobStarted(job.getId()); IngestManager.logger.log(Level.INFO, "Ingest job {0} started", job.getId()); //NON-NLS success = true; } else { - this.jobsById.remove(job.getId()); + synchronized (jobsById) { + this.jobsById.remove(job.getId()); + } for (IngestModuleError error : errors) { logger.log(Level.SEVERE, String.format("Error starting %s ingest module", error.getModuleDisplayName()), error.getModuleError()); //NON-NLS } @@ -599,13 +596,15 @@ public class IngestManager { synchronized void finishIngestJob(IngestJob job) { long jobId = job.getId(); - this.jobsById.remove(jobId); + synchronized (jobsById) { + jobsById.remove(jobId); + } if (!job.isCancelled()) { IngestManager.logger.log(Level.INFO, "Ingest job {0} completed", jobId); //NON-NLS - this.fireIngestJobCompleted(jobId); + fireIngestJobCompleted(jobId); } else { IngestManager.logger.log(Level.INFO, "Ingest job {0} cancelled", jobId); //NON-NLS - this.fireIngestJobCancelled(jobId); + fireIngestJobCancelled(jobId); } } @@ -615,7 +614,9 @@ public class IngestManager { * @return True or false. */ public boolean isIngestRunning() { - return !this.jobsById.isEmpty(); + synchronized (jobsById) { + return !jobsById.isEmpty(); + } } /** @@ -625,7 +626,7 @@ public class IngestManager { * instead. */ @Deprecated - public synchronized void cancelAllIngestJobs() { + public void cancelAllIngestJobs() { cancelAllIngestJobs(IngestJob.CancellationReason.USER_CANCELLED); } @@ -634,15 +635,21 @@ public class IngestManager { * * @param reason The cancellation reason. */ - public synchronized void cancelAllIngestJobs(IngestJob.CancellationReason reason) { - // Stop creating new ingest jobs. - for (Future handle : ingestJobStarters.values()) { + public void cancelAllIngestJobs(IngestJob.CancellationReason reason) { + /* + * Cancel the start job tasks. + */ + for (Future handle : startIngestJobTasks.values()) { handle.cancel(true); } - // Cancel all the jobs already created. - for (IngestJob job : this.jobsById.values()) { - job.cancel(reason); + /* + * Cancel the jobs in progress. + */ + synchronized (jobsById) { + for (IngestJob job : this.jobsById.values()) { + job.cancel(reason); + } } } @@ -903,8 +910,10 @@ public class IngestManager { */ List getIngestJobSnapshots() { List snapShots = new ArrayList<>(); - for (IngestJob job : this.jobsById.values()) { - snapShots.addAll(job.getDataSourceIngestJobSnapshots()); + synchronized (jobsById) { + for (IngestJob job : jobsById.values()) { + snapShots.addAll(job.getDataSourceIngestJobSnapshots()); + } } return snapShots; } @@ -941,7 +950,9 @@ public class IngestManager { public Void call() { try { if (Thread.currentThread().isInterrupted()) { - jobsById.remove(job.getId()); + synchronized (jobsById) { + jobsById.remove(job.getId()); + } return null; } @@ -953,7 +964,7 @@ public class IngestManager { if (progress != null) { progress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.cancelling", displayName)); } - Future handle = ingestJobStarters.remove(threadId); + Future handle = startIngestJobTasks.remove(threadId); handle.cancel(true); return true; } @@ -968,7 +979,7 @@ public class IngestManager { if (null != progress) { progress.finish(); } - ingestJobStarters.remove(threadId); + startIngestJobTasks.remove(threadId); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java index 27b7f3ecf5..26f4fd6a11 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,11 +39,14 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Directory; /** - * Dialog box that allows a user to configure and run an ingest job on one or - * more data sources. + * + * A dialog box that allows a user to configure and execute analysis of one or + * more data sources with ingest modules or analysis of the contents of a + * directory with file-level ingest modules. */ public final class RunIngestModulesDialog extends JDialog { + private static final long serialVersionUID = 1L; private static final String TITLE = NbBundle.getMessage(RunIngestModulesDialog.class, "IngestDialog.title.text"); private final IngestType ingestType; private static Dimension DIMENSIONS = new Dimension(500, 300); @@ -51,13 +54,13 @@ public final class RunIngestModulesDialog extends JDialog { private IngestJobSettingsPanel ingestJobSettingsPanel; /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. + * Constructs a dialog box that allows a user to configure and execute + * analysis of one or more data sources with ingest modules. * * @param frame The dialog parent window. * @param title The title for the dialog. * @param modal True if the dialog should be modal, false otherwise. - * @param dataSources The data sources to be processed. + * @param dataSources The data sources to be analyzed. */ public RunIngestModulesDialog(JFrame frame, String title, boolean modal, List dataSources) { super(frame, title, modal); @@ -66,60 +69,26 @@ public final class RunIngestModulesDialog extends JDialog { } /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. + * Constructs a dialog box that allows a user to configure and execute + * analysis of one or more data sources with ingest modules. * * @param dataSources The data sources to be processed. */ public RunIngestModulesDialog(List dataSources) { this(new JFrame(TITLE), TITLE, true, dataSources); } - + + /** + * Constructs a dialog box that allows a user to configure and execute + * analysis of the contents of a directory with file-level ingest modules. + * + * @param dir + */ public RunIngestModulesDialog(Directory dir) { this.dataSources.add(dir); this.ingestType = IngestType.FILES_ONLY; } - /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. - * - * @param frame The dialog parent window. - * @param title The title for the dialog. - * @param modal True if the dialog should be modal, false otherwise. - * - * @deprecated - */ - @Deprecated - public RunIngestModulesDialog(JFrame frame, String title, boolean modal) { - super(frame, title, modal); - this.ingestType = IngestType.ALL_MODULES; - } - - /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. - * - * @deprecated - */ - @Deprecated - public RunIngestModulesDialog() { - this(new JFrame(TITLE), TITLE, true); - } - - /** - * Set the data sources to be processed. - * - * @param dataSources The data sources. - * - * @deprecated - */ - @Deprecated - public void setDataSources(List dataSources) { - this.dataSources.clear(); - this.dataSources.addAll(dataSources); - } - /** * Displays this dialog. */ @@ -139,7 +108,7 @@ public final class RunIngestModulesDialog extends JDialog { * Get the default or saved ingest job settings for this context and use * them to create and add an ingest job settings panel. */ - IngestJobSettings ingestJobSettings = new IngestJobSettings(RunIngestModulesDialog.class.getCanonicalName(), this.ingestType); + IngestJobSettings ingestJobSettings = new IngestJobSettings(RunIngestModulesDialog.class.getCanonicalName(), this.ingestType); RunIngestModulesDialog.showWarnings(ingestJobSettings); this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings); add(this.ingestJobSettingsPanel, BorderLayout.PAGE_START); @@ -227,4 +196,45 @@ public final class RunIngestModulesDialog extends JDialog { JOptionPane.showMessageDialog(null, warningMessage.toString()); } } + + /** + * Constructs a dialog box that allows a user to configure and execute + * analysis of one or more data sources with ingest modules. + * + * @param frame The dialog parent window. + * @param title The title for the dialog. + * @param modal True if the dialog should be modal, false otherwise. + * + * @deprecated + */ + @Deprecated + public RunIngestModulesDialog(JFrame frame, String title, boolean modal) { + super(frame, title, modal); + this.ingestType = IngestType.ALL_MODULES; + } + + /** + * Constructs a dialog box that allows a user to configure and run an ingest + * job on one or more data sources. + * + * @deprecated + */ + @Deprecated + public RunIngestModulesDialog() { + this(new JFrame(TITLE), TITLE, true); + } + + /** + * Sets the data sources to be processed. + * + * @param dataSources The data sources. + * + * @deprecated + */ + @Deprecated + public void setDataSources(List dataSources) { + this.dataSources.clear(); + this.dataSources.addAll(dataSources); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java index 7e0d220f11..b7f6529786 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java @@ -79,7 +79,7 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule } catch (SecurityException ex) { logger.log(Level.SEVERE, "Error initializing output dir: " + moduleDirAbsolute, ex); //NON-NLS services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), "Error initializing", "Error initializing output dir: " + moduleDirAbsolute)); //NON-NLS - throw new IngestModuleException(ex.getMessage()); + throw new IngestModuleException(ex.getMessage(), ex); } } @@ -87,7 +87,7 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - throw new IngestModuleException(ex.getMessage()); + throw new IngestModuleException(ex.getMessage(), ex); } // initialize the extraction modules. diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java index 44052df224..881e7c5fa4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java @@ -133,7 +133,7 @@ class SevenZipExtractor { String details = NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.init.errCantInitLib", e.getMessage()); services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details)); - throw new IngestModuleException(e.getMessage()); + throw new IngestModuleException(e.getMessage(), e); } } this.context = context; diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java index de946ffd0f..b2ce0beca2 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java @@ -91,7 +91,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule { try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "ExifParserFileIngestModule.startUp.fileTypeDetectorInitializationException.msg")); + throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "ExifParserFileIngestModule.startUp.fileTypeDetectorInitializationException.msg"), ex); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java index e22e73ae26..c579c69014 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,13 +18,11 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.logging.Level; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; @@ -40,7 +38,6 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; -import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskException; @@ -58,6 +55,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); private static Blackboard blackboard; + private FileTypeDetector detector; private static class IngestJobTotals { @@ -94,6 +92,11 @@ public class FileExtMismatchIngestModule implements FileIngestModule { FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault(); SigTypeToExtMap = xmlLoader.load(); + try { + this.detector = new FileTypeDetector(); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + throw new IngestModuleException("Could not create file type detector.", ex); + } } @@ -157,7 +160,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { if (settings.skipFilesWithNoExtension() && currActualExt.isEmpty()) { return false; } - String currActualSigType = abstractFile.getMIMEType(); + String currActualSigType = detector.getFileType(abstractFile); if (currActualSigType == null) { return false; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index 0d82d62731..fdcf90eae5 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -35,10 +35,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.datamodel.TskDataException; /** - * Detects the type of a file by an inspection of its contents. + * Detects the MIME type of a file by an inspection of its contents, using both + * user-defined type definitions and Tika. */ public class FileTypeDetector { @@ -49,11 +49,14 @@ public class FileTypeDetector { private static final Logger logger = Logger.getLogger(FileTypeDetector.class.getName()); /** - * Constructs an object that detects the type of a file by an inspection of - * its contents. + * Constructs an object that detects the MIME type of a file by an + * inspection of its contents, using both user-defined type definitions and + * Tika. * - * @throws FileTypeDetector.FileTypeDetectorInitException if an - * initialization error occurs. + * @throws FileTypeDetectorInitException if an initialization error occurs, + * e.g., user-defined file type + * definitions exist but cannot be + * loaded. */ public FileTypeDetector() throws FileTypeDetectorInitException { try { @@ -64,12 +67,26 @@ public class FileTypeDetector { } /** - * Determines whether or not a given MIME type is detectable by this - * detector. + * Gets the names of the user-defined MIME types. * - * @param mimeType The MIME type name, e.g. "text/html", to look up. + * @return A list of the user-defined MIME types. + */ + public List getUserDefinedTypes() { + List list = new ArrayList<>(); + if (userDefinedFileTypes != null) { + for (FileType fileType : userDefinedFileTypes) { + list.add(fileType.getMimeType()); + } + } + return list; + } + + /** + * Determines whether or not a given MIME type is detectable. * - * @return True if MIME type is detectable. + * @param mimeType The MIME type name (e.g., "text/html"). + * + * @return True if the given MIME type is detectable. */ public boolean isDetectable(String mimeType) { return isDetectableAsUserDefinedType(mimeType) || isDetectableByTika(mimeType); @@ -77,11 +94,11 @@ public class FileTypeDetector { /** * Determines whether or not a given MIME type is detectable as a - * user-defined file type. + * user-defined MIME type. * - * @param mimeType The MIME type name, e.g. "text/html", to look up. + * @param mimeType The MIME type name (e.g., "text/html"). * - * @return True if MIME type is detectable. + * @return True if the given MIME type is detectable. */ private boolean isDetectableAsUserDefinedType(String mimeType) { for (FileType fileType : userDefinedFileTypes) { @@ -95,9 +112,9 @@ public class FileTypeDetector { /** * Determines whether or not a given MIME type is detectable by Tika. * - * @param mimeType The MIME type name, e.g. "text/html", to look up. + * @param mimeType The MIME type name (e.g., "text/html"). * - * @return True if MIME type is detectable. + * @return True if the given MIME type is detectable. */ private boolean isDetectableByTika(String mimeType) { String[] split = mimeType.split("/"); @@ -112,59 +129,42 @@ public class FileTypeDetector { } /** - * Look up the MIME type of a file using the blackboard. If it is not - * already posted, detect the type of the file, posting it to the blackboard - * if detection succeeds. + * Gets the MIME type of a file, detecting it if it is not already known. If + * detection is necessary, the result is added to the case database. * - * @param file The file to test. + * @param file The file. * - * @return The MIME type name if detection was successful, null otherwise. + * @return A MIME type name. * - * @throws TskCoreException - */ - public String getFileType(AbstractFile file) throws TskCoreException { - String fileType = file.getMIMEType(); - if (null != fileType) { - return fileType; - } - return detectAndPostToBlackboard(file); - } - - /** - * Detect the MIME type of a file, posting it to the blackboard if detection - * succeeds. Note that this method should currently be called at most once - * per file. - * - * @param file The file to test. - * - * @return The MIME type name id detection was successful, null otherwise. - * - * @throws TskCoreException + * @throws TskCoreException if detection is required and there is a problem + * writing the result to the case database. */ @SuppressWarnings("deprecation") - public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException { - String mimeType = detect(file); + public String getFileType(AbstractFile file) throws TskCoreException { + String mimeType = file.getMIMEType(); if (null != mimeType) { - /** - * Add the file type attribute to the general info artifact. Note - * that no property change is fired for this blackboard posting - * because general info artifacts are different from other - * artifacts, e.g., they are not displayed in the results tree. - */ - try { - file.setMIMEType(mimeType); - BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); - BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); - getInfoArt.addAttribute(batt); - } catch (TskDataException ex) { - //Swallowing exception so that the logs aren't clogged in the case that ingest is run multiple times. - } + return mimeType; } + + mimeType = detect(file); + Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); + + /* + * Add the file type attribute to the general info artifact. Note that + * no property change is fired for this blackboard posting because + * general info artifacts are different from other artifacts, e.g., they + * are not displayed in the results tree. + */ + BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); + BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); + getInfoArt.addAttribute(batt); + return mimeType; } /** - * Detect the MIME type of a file. + * Detects the MIME type of a file. The result is not added to the case + * database. * * @param file The file to test. * @@ -173,9 +173,12 @@ public class FileTypeDetector { * @throws TskCoreException */ public String detect(AbstractFile file) throws TskCoreException { - // consistently mark non-regular files (refer TskData.TSK_FS_META_TYPE_ENUM), - // 0 sized files, unallocated, and unused blocks (refer TskData.TSK_DB_FILES_TYPE_ENUM) - // as octet-stream. + /* + * Consistently mark non-regular files (refer to + * TskData.TSK_FS_META_TYPE_ENUM), zero-sized files, unallocated space, + * and unused blocks (refer to TskData.TSK_DB_FILES_TYPE_ENUM) as + * octet-stream. + */ if (!file.isFile() || file.getSize() <= 0 || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) @@ -183,8 +186,8 @@ public class FileTypeDetector { return MimeTypes.OCTET_STREAM; } - String fileType = detectUserDefinedType(file); - if (null == fileType) { + String mimeType = detectUserDefinedType(file); + if (null == mimeType) { try { byte buf[]; int len = file.read(buffer, 0, BUFFER_SIZE); @@ -195,23 +198,25 @@ public class FileTypeDetector { buf = buffer; } - String mimetype = tika.detect(buf, file.getName()); + String tikaType = tika.detect(buf, file.getName()); /** * Strip out any Tika enhancements to the MIME type name. */ - return mimetype.replace("tika-", ""); //NON-NLS + mimeType = tikaType.replace("tika-", ""); //NON-NLS } catch (Exception ignored) { - /** - * This exception is swallowed rather than propagated because - * files in images are not always consistent with their file - * system meta data making for read errors, and Tika can be a - * bit flaky at times, making this a best effort endeavor. + /* + * This exception is swallowed and not logged rather than + * propagated because files in data sources are not always + * consistent with their file system metadata, making for read + * errors, and Tika can be a bit flaky at times, making this a + * best effort endeavor. Default to octet-stream. */ + mimeType = MimeTypes.OCTET_STREAM; } } - return fileType; + return mimeType; } /** @@ -235,7 +240,7 @@ public class FileTypeDetector { BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, FileTypeIdModuleFactory.getModuleName(), fileType.getFilesSetName()); artifact.addAttribute(setNameAttribute); - /** + /* * Use the MIME type as the category, i.e., the rule that * determined this file belongs to the interesting files * set. @@ -259,6 +264,7 @@ public class FileTypeDetector { } public static class FileTypeDetectorInitException extends Exception { + private static final long serialVersionUID = 1L; FileTypeDetectorInitException(String message) { @@ -271,17 +277,22 @@ public class FileTypeDetector { } /** - * Gets the list of user defined file types (MIME types) + * Gets the MIME type of a file, detecting it if it is not already known. If + * detection is necessary, the result is added to the case database. * - * @return the List of user defined file types + * @param file The file. + * + * @return A MIME type name. + * + * @throws TskCoreException if detection is required and there is a problem + * writing the result to the case database. + * @deprecated Use getFileType instead and use AbstractFile.getMIMEType + * instead of querying the blackboard. */ - public List getUserDefinedTypes() { - List list = new ArrayList<>(); - if (userDefinedFileTypes != null) { - for (FileType fileType : userDefinedFileTypes) { - list.add(fileType.getMimeType()); - } - } - return list; + @Deprecated + @SuppressWarnings("deprecation") + public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException { + return getFileType(file); } + } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.form deleted file mode 100644 index 183425da42..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.form +++ /dev/null @@ -1,52 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.java deleted file mode 100644 index 658e0c00b9..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2013 - 2014 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * 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 org.sleuthkit.autopsy.modules.filetypeid; - -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; - -/** - * UI component used to set ingest job options for file type identifier ingest - * modules. - */ -class FileTypeIdIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel { - - private final FileTypeIdModuleSettings settings; - - FileTypeIdIngestJobSettingsPanel(FileTypeIdModuleSettings settings) { - this.settings = settings; - initComponents(); - customizeComponents(); - } - - /** - * @inheritDoc - */ - @Override - public IngestModuleIngestJobSettings getSettings() { - return settings; - } - - /** - * Does child component initialization in addition to that done by the - * Matisse generated code. - */ - private void customizeComponents() { - skipKnownCheckBox.setSelected(settings.skipKnownFiles()); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - skipKnownCheckBox = new javax.swing.JCheckBox(); - - skipKnownCheckBox.setSelected(true); - skipKnownCheckBox.setText(org.openide.util.NbBundle.getMessage(FileTypeIdIngestJobSettingsPanel.class, "FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text")); // NOI18N - skipKnownCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(FileTypeIdIngestJobSettingsPanel.class, "FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText")); // NOI18N - skipKnownCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - skipKnownCheckBoxActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(skipKnownCheckBox) - .addContainerGap(46, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(11, 11, 11) - .addComponent(skipKnownCheckBox) - .addContainerGap(86, Short.MAX_VALUE)) - ); - }// //GEN-END:initComponents - - private void skipKnownCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipKnownCheckBoxActionPerformed - settings.setSkipKnownFiles(skipKnownCheckBox.isSelected()); - }//GEN-LAST:event_skipKnownCheckBoxActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JCheckBox skipKnownCheckBox; - // End of variables declaration//GEN-END:variables -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java index b3c09dfb81..3e6e35e8ae 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java @@ -27,7 +27,6 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskData.FileKnown; import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; @@ -38,7 +37,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; public class FileTypeIdIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(FileTypeIdIngestModule.class.getName()); - private final FileTypeIdModuleSettings settings; private long jobId; private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); @@ -66,11 +64,8 @@ public class FileTypeIdIngestModule implements FileIngestModule { /** * Creates an ingest module that detects the type of a file based on * signature (magic) values. Posts results to the blackboard. - * - * @param settings The ingest module settings. */ - FileTypeIdIngestModule(FileTypeIdModuleSettings settings) { - this.settings = settings; + FileTypeIdIngestModule() { } /** @@ -83,7 +78,7 @@ public class FileTypeIdIngestModule implements FileIngestModule { try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg")); + throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg"), ex); } } @@ -93,13 +88,6 @@ public class FileTypeIdIngestModule implements FileIngestModule { @Override public ProcessResult process(AbstractFile file) { - /** - * Skip known files if configured to do so. - */ - if (settings.skipKnownFiles() && (file.getKnown() == FileKnown.KNOWN)) { - return ProcessResult.OK; - } - /** * Attempt to detect the file type. Do it within an exception firewall, * so that any issues with reading file content or complaints from tika @@ -153,7 +141,7 @@ public class FileTypeIdIngestModule implements FileIngestModule { * Update the match time total and increment number of files processed for * this ingest job. * - * @param jobId The ingest job identifier. + * @param jobId The ingest job identifier. * @param matchTimeInc Amount of time to add. */ private static synchronized void addToTotals(long jobId, long matchTimeInc) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java index 38823ca03d..78ccd986a0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java @@ -26,7 +26,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleFactory; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; /** * A factory that creates file ingest modules that determine the types of files. @@ -92,35 +91,6 @@ public class FileTypeIdModuleFactory extends IngestModuleFactoryAdapter { return globalSettingsPanel; } - /** - * @inheritDoc - */ - @Override - public IngestModuleIngestJobSettings getDefaultIngestJobSettings() { - return new FileTypeIdModuleSettings(); - } - - /** - * @inheritDoc - */ - @Override - public boolean hasIngestJobSettingsPanel() { - return true; - } - - /** - * @inheritDoc - */ - @Override - public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) { - assert settings instanceof FileTypeIdModuleSettings; - if (!(settings instanceof FileTypeIdModuleSettings)) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), - "FileTypeIdModuleFactory.getIngestJobSettingsPanel.exception.msg")); - } - return new FileTypeIdIngestJobSettingsPanel((FileTypeIdModuleSettings) settings); - } - /** * @inheritDoc */ @@ -134,11 +104,6 @@ public class FileTypeIdModuleFactory extends IngestModuleFactoryAdapter { */ @Override public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) { - assert settings instanceof FileTypeIdModuleSettings; - if (!(settings instanceof FileTypeIdModuleSettings)) { - throw new IllegalArgumentException( - NbBundle.getMessage(this.getClass(), "FileTypeIdModuleFactory.createFileIngestModule.exception.msg")); - } - return new FileTypeIdIngestModule((FileTypeIdModuleSettings) settings); + return new FileTypeIdIngestModule(); } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java deleted file mode 100755 index 8d8e4150d5..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * 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 org.sleuthkit.autopsy.modules.filetypeid; - -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - -/** - * Ingest job options for the file type identifier ingest module instances. - */ -// TODO: This class does not need to be public. -public class FileTypeIdModuleSettings implements IngestModuleIngestJobSettings { - - private static final long serialVersionUID = 1L; - private boolean skipKnownFiles = true; - private boolean skipSmallFiles = false; // No longer used. - - FileTypeIdModuleSettings() { - } - - FileTypeIdModuleSettings(boolean skipKnownFiles) { - this.skipKnownFiles = skipKnownFiles; - } - - /** - * @inheritDoc - */ - @Override - public long getVersionNumber() { - return serialVersionUID; - } - - void setSkipKnownFiles(boolean enabled) { - skipKnownFiles = enabled; - } - - boolean skipKnownFiles() { - return skipKnownFiles; - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java index f848838d02..16ae16e4bd 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java @@ -152,7 +152,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule { // Initialize job totals initTotalsForIngestJob(jobId); } catch (SecurityException | IOException | UnsupportedOperationException ex) { - throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage())); + throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()), ex); } } } @@ -396,7 +396,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule { } catch (FileAlreadyExistsException ex) { // No worries. } catch (IOException | SecurityException | UnsupportedOperationException ex) { - throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage())); + throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()), ex); } return path; } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index b1dc6bf23d..196f770ca7 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -983,8 +983,8 @@ class ReportHTML implements TableReportModule { StringBuilder head = new StringBuilder(); head.append("\n\n").append( //NON-NLS NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.title")).append("\n"); //NON-NLS - head.append("