Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 3198-TagPropertiesUpdate

This commit is contained in:
William Schaefer 2017-11-15 11:59:44 -05:00
commit 273434f50f
125 changed files with 1479 additions and 902 deletions

View File

@ -30,6 +30,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -40,7 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
final class MultiUserCaseManager { final class MultiUserCaseManager {
private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName()); private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName());
private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; private static final String ALERT_FILE_NAME = "autoingest.alert";
private static MultiUserCaseManager instance; private static MultiUserCaseManager instance;
private CoordinationService coordinationService; private CoordinationService coordinationService;
@ -82,19 +83,74 @@ final class MultiUserCaseManager {
List<MultiUserCase> cases = new ArrayList<>(); List<MultiUserCase> cases = new ArrayList<>();
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
for (String node : nodeList) { for (String node : nodeList) {
Path casePath = Paths.get(node); Path casePath = Paths.get(node);
File caseFolder = casePath.toFile(); File caseFolder = casePath.toFile();
if(caseFolder.exists()) { if (caseFolder.exists()) {
File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut")); /*
if(autFiles != null && autFiles.length > 0) { * Search for '*.aut' and 'autoingest.alert' files.
try { */
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFiles[0].getAbsolutePath())); File[] fileArray = caseFolder.listFiles();
cases.add(new MultiUserCase(casePath, caseMetadata)); if (fileArray == null) {
} catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { continue;
LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFiles[0].getAbsolutePath()), ex); }
String autFilePath = null;
boolean alertFileFound = false;
for (File file : fileArray) {
String name = file.getName().toLowerCase();
if (autFilePath == null && name.endsWith(".aut")) {
autFilePath = file.getAbsolutePath();
if (!alertFileFound) {
continue;
}
}
if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) {
alertFileFound = true;
}
if (autFilePath != null && alertFileFound) {
break;
}
}
if (autFilePath != null) {
try {
CaseStatus caseStatus;
if (alertFileFound) {
/*
* When an alert file exists, ignore the node data
* and use the ALERT status.
*/
caseStatus = CaseStatus.ALERT;
} else {
byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, node);
if (rawData != null && rawData.length > 0) {
/*
* When node data exists, use the status stored
* in the node data.
*/
CaseNodeData caseNodeData = new CaseNodeData(rawData);
if (caseNodeData.getErrorsOccurred()) {
caseStatus = CaseStatus.ALERT;
} else {
caseStatus = CaseStatus.OK;
}
} else {
/*
* When no node data is available, use the 'OK'
* status to avoid confusing the end-user.
*/
caseStatus = CaseStatus.OK;
} }
} }
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath));
cases.add(new MultiUserCase(casePath, caseMetadata, caseStatus));
} catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) {
LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex);
} catch (InterruptedException | CaseNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex);
}
} }
}
} }
return cases; return cases;
} }
@ -112,7 +168,7 @@ final class MultiUserCaseManager {
*/ */
Case.openAsCurrentCase(caseMetadataFilePath.toString()); Case.openAsCurrentCase(caseMetadataFilePath.toString());
} }
/** /**
* Exception type thrown when there is an error completing a multi-user case * Exception type thrown when there is an error completing a multi-user case
* manager operation. * manager operation.
@ -143,7 +199,7 @@ final class MultiUserCaseManager {
} }
} }
/** /**
* A representation of a multi-user case. * A representation of a multi-user case.
*/ */
@ -154,21 +210,22 @@ final class MultiUserCaseManager {
private final String metadataFileName; private final String metadataFileName;
private final Date createDate; private final Date createDate;
private final Date lastAccessedDate; private final Date lastAccessedDate;
private CaseStatus status;
/** /**
* Constructs a representation of a multi-user case * Constructs a representation of a multi-user case
* *
* @param caseDirectoryPath The case directory path. * @param caseDirectoryPath The case directory path.
* @param caseMetadata The case metadata. * @param caseMetadata The case metadata.
* *
* @throws MultiUserCaseException If no case metadata (.aut) * @throws MultiUserCaseException If no case metadata (.aut) file is
* file is found in the case * found in the case directory.
* directory.
*/ */
MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata) throws MultiUserCaseException { MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata, CaseStatus status) throws MultiUserCaseException {
this.caseDirectoryPath = caseDirectoryPath; this.caseDirectoryPath = caseDirectoryPath;
caseDisplayName = caseMetadata.getCaseDisplayName(); caseDisplayName = caseMetadata.getCaseDisplayName();
metadataFileName = caseMetadata.getFilePath().getFileName().toString(); metadataFileName = caseMetadata.getFilePath().getFileName().toString();
this.status = status;
BasicFileAttributes fileAttrs = null; BasicFileAttributes fileAttrs = null;
try { try {
fileAttrs = Files.readAttributes(Paths.get(caseDirectoryPath.toString(), metadataFileName), BasicFileAttributes.class); fileAttrs = Files.readAttributes(Paths.get(caseDirectoryPath.toString(), metadataFileName), BasicFileAttributes.class);
@ -194,8 +251,8 @@ final class MultiUserCaseManager {
} }
/** /**
* Gets the case display name. This may differ from the name supplied to the * Gets the case display name. This may differ from the name supplied to
* directory or metadata file names if a case has been renamed. * the directory or metadata file names if a case has been renamed.
* *
* @return The case display name. * @return The case display name.
*/ */
@ -204,8 +261,8 @@ final class MultiUserCaseManager {
} }
/** /**
* Gets the creation date for the case, defined as the create time of the * Gets the creation date for the case, defined as the create time of
* case metadata file. * the case metadata file.
* *
* @return The case creation date. * @return The case creation date.
*/ */
@ -214,8 +271,8 @@ final class MultiUserCaseManager {
} }
/** /**
* Gets the last accessed date for the case, defined as the last accessed * Gets the last accessed date for the case, defined as the last
* time of the case metadata file. * accessed time of the case metadata file.
* *
* @return The last accessed date. * @return The last accessed date.
*/ */
@ -225,7 +282,7 @@ final class MultiUserCaseManager {
/** /**
* Gets metadata (.aut) file name. * Gets metadata (.aut) file name.
* *
* @return The metadata file name. * @return The metadata file name.
*/ */
String getMetadataFileName() { String getMetadataFileName() {
@ -233,17 +290,12 @@ final class MultiUserCaseManager {
} }
/** /**
* Gets the status of this case based on the auto ingest result file in the * Gets the status of this case.
* case directory.
* *
* @return See CaseStatus enum definition. * @return See CaseStatus enum definition.
*/ */
CaseStatus getStatus() { CaseStatus getStatus() {
if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) { return status;
return CaseStatus.ALERT;
} else {
return CaseStatus.OK;
}
} }
/** /**
@ -252,7 +304,7 @@ final class MultiUserCaseManager {
* @param caseDirectoryPath The case directory path. * @param caseDirectoryPath The case directory path.
* *
* @return Case metadata. * @return Case metadata.
* *
* @throws CaseMetadata.CaseMetadataException If the CaseMetadata object * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object
* cannot be constructed. * cannot be constructed.
* @throws MultiUserCaseException If no case metadata (.aut) * @throws MultiUserCaseException If no case metadata (.aut)
@ -276,7 +328,7 @@ final class MultiUserCaseManager {
} }
} }
if(autFile == null || !autFile.isFile()) { if (autFile == null || !autFile.isFile()) {
throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString())); throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString()));
} }
@ -334,14 +386,15 @@ final class MultiUserCaseManager {
static class LastAccessedDateDescendingComparator implements Comparator<MultiUserCase> { static class LastAccessedDateDescendingComparator implements Comparator<MultiUserCase> {
/** /**
* Compares two MultiUserCase objects for order based on last accessed * Compares two MultiUserCase objects for order based on last
* date (descending). * accessed date (descending).
* *
* @param object The first MultiUserCase object * @param object The first MultiUserCase object
* @param otherObject The second MultiUserCase object. * @param otherObject The second MultiUserCase object.
* *
* @return A negative integer, zero, or a positive integer as the first * @return A negative integer, zero, or a positive integer as the
* argument is less than, equal to, or greater than the second. * first argument is less than, equal to, or greater than
* the second.
*/ */
@Override @Override
public int compare(MultiUserCase object, MultiUserCase otherObject) { public int compare(MultiUserCase object, MultiUserCase otherObject) {
@ -357,8 +410,8 @@ final class MultiUserCaseManager {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Constructs an exception to throw when there is a problem creating a * Constructs an exception to throw when there is a problem creating
* multi-user case. * a multi-user case.
* *
* @param message The exception message. * @param message The exception message.
*/ */
@ -367,11 +420,12 @@ final class MultiUserCaseManager {
} }
/** /**
* Constructs an exception to throw when there is a problem creating a * Constructs an exception to throw when there is a problem creating
* multi-user case. * a multi-user case.
* *
* @param message The exception message. * @param message The exception message.
* @param cause The cause of the exception, if it was an exception. * @param cause The cause of the exception, if it was an
* exception.
*/ */
private MultiUserCaseException(String message, Throwable cause) { private MultiUserCaseException(String message, Throwable cause) {
super(message, cause); super(message, cause);

View File

@ -0,0 +1,141 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.coordinationservice;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
/**
* An object that converts case data for a case directory coordination service
* node to and from byte arrays.
*/
public final class CaseNodeData {
private static final int CURRENT_VERSION = 0;
private int version;
private boolean errorsOccurred;
/**
* Gets the current version of the case directory coordination service node
* data.
*
* @return The version number.
*/
public static int getCurrentVersion() {
return CaseNodeData.CURRENT_VERSION;
}
/**
* Uses coordination service node data to construct an object that converts
* case data for a case directory coordination service node to and from byte
* arrays.
*
* @param nodeData The raw bytes received from the coordination service.
*
* @throws InvalidDataException If the node data buffer is smaller than
* expected.
*/
public CaseNodeData(byte[] nodeData) throws InvalidDataException {
if(nodeData == null || nodeData.length == 0) {
this.version = CURRENT_VERSION;
this.errorsOccurred = false;
} else {
/*
* Get fields from node data.
*/
ByteBuffer buffer = ByteBuffer.wrap(nodeData);
try {
if (buffer.hasRemaining()) {
this.version = buffer.getInt();
/*
* Flags bit format: 76543210
* 0-6 --> reserved for future use
* 7 --> errorsOccurred
*/
byte flags = buffer.get();
this.errorsOccurred = (flags < 0);
}
} catch (BufferUnderflowException ex) {
throw new InvalidDataException("Node data is incomplete", ex);
}
}
}
/**
* Gets whether or not any errors occurred during the processing of the job.
*
* @return True or false.
*/
public boolean getErrorsOccurred() {
return this.errorsOccurred;
}
/**
* Sets whether or not any errors occurred during the processing of job.
*
* @param errorsOccurred True or false.
*/
public void setErrorsOccurred(boolean errorsOccurred) {
this.errorsOccurred = errorsOccurred;
}
/**
* Gets the node data version number.
*
* @return The version number.
*/
public int getVersion() {
return this.version;
}
/**
* Gets the node data as a byte array that can be sent to the coordination
* service.
*
* @return The node data as a byte array.
*/
public byte[] toArray() {
ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.putInt(this.version);
buffer.put((byte)(this.errorsOccurred ? 0x80 : 0));
// Prepare the array
byte[] array = new byte[buffer.position()];
buffer.rewind();
buffer.get(array, 0, array.length);
return array;
}
public final static class InvalidDataException extends Exception {
private static final long serialVersionUID = 1L;
private InvalidDataException(String message) {
super(message);
}
private InvalidDataException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@ -24,7 +24,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
/** /**
* Additional functionality of viewers supporting black board results such as * Additional functionality of viewers supporting black board results such as
* the directory tree * the directory tree
*
*@deprecated No longer used.
*/ */
@Deprecated
public interface BlackboardResultViewer { public interface BlackboardResultViewer {
public static final String FINISHED_DISPLAY_EVT = "FINISHED_DISPLAY_EVT"; //NON-NLS public static final String FINISHED_DISPLAY_EVT = "FINISHED_DISPLAY_EVT"; //NON-NLS

View File

@ -43,9 +43,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
* or less means the data source is not supported by the * or less means the data source is not supported by the
* DataSourceProcessor. Value of 100 indicates high certainty in * DataSourceProcessor. Value of 100 indicates high certainty in
* being able to process the data source. * being able to process the data source.
* * @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
* @throws
* org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
*/ */
int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException; int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException;
@ -65,9 +63,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
* background task to report progress. * background task to report progress.
* @param callBack Callback that will be used by the background task * @param callBack Callback that will be used by the background task
* to return results. * to return results.
* * @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
* @throws
* org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
*/ */
void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException; void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException;

View File

@ -59,8 +59,6 @@ DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=Open File Search by Attributes DirectoryTreeFilterNode.action.openFileSrcByAttr.text=Open File Search by Attributes
DirectoryTreeFilterNode.action.runIngestMods.text=Run Ingest Modules DirectoryTreeFilterNode.action.runIngestMods.text=Run Ingest Modules
DirectoryTreeTopComponent.action.viewArtContent.text=View Artifact Content DirectoryTreeTopComponent.action.viewArtContent.text=View Artifact Content
DirectoryTreeTopComponent.moduleErr=Module Error
DirectoryTreeTopComponent.moduleErr.msg=A module caused an error listening to DirectoryTreeTopComponent updates. See log to determine which module. Some data could be incomplete.
DirectoryTreeTopComponent.showRejectedCheckBox.text=Show Rejected Results DirectoryTreeTopComponent.showRejectedCheckBox.text=Show Rejected Results
ExplorerNodeActionVisitor.action.imgDetails.title=Image Details ExplorerNodeActionVisitor.action.imgDetails.title=Image Details
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=Extract Unallocated Space to Single Files ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=Extract Unallocated Space to Single Files

View File

@ -56,8 +56,6 @@ DataResultFilterNode.action.viewInDir.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u3092\u958b\u304f DirectoryTreeFilterNode.action.openFileSrcByAttr.text=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u3092\u958b\u304f
DirectoryTreeFilterNode.action.runIngestMods.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c DirectoryTreeFilterNode.action.runIngestMods.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c
DirectoryTreeTopComponent.action.viewArtContent.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u8868\u793a DirectoryTreeTopComponent.action.viewArtContent.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u8868\u793a
DirectoryTreeTopComponent.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc
DirectoryTreeTopComponent.moduleErr.msg=DirectoryTreeTopComponent\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
ExplorerNodeActionVisitor.action.imgDetails.title=\u30a4\u30e1\u30fc\u30b8\u8a73\u7d30 ExplorerNodeActionVisitor.action.imgDetails.title=\u30a4\u30e1\u30fc\u30b8\u8a73\u7d30
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u5185\u306e\u30c7\u30fc\u30bf\u3092\u30b7\u30f3\u30b0\u30eb\u30d5\u30a1\u30a4\u30eb\u306b\u62bd\u51fa ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u5185\u306e\u30c7\u30fc\u30bf\u3092\u30b7\u30f3\u30b0\u30eb\u30d5\u30a1\u30a4\u30eb\u306b\u62bd\u51fa
ExplorerNodeActionVisitor.action.fileSystemDetails.title=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u8a73\u7d30 ExplorerNodeActionVisitor.action.fileSystemDetails.title=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u8a73\u7d30
@ -87,4 +85,4 @@ ExtractUnallocAction.done.notifyMsg.completedExtract.msg=\u30d5\u30a1\u30a4\u30e
ExtractUnallocAction.done.errMsg.title=\u62bd\u51fa\u30a8\u30e9\u30fc ExtractUnallocAction.done.errMsg.title=\u62bd\u51fa\u30a8\u30e9\u30fc
ExtractUnallocAction.done.errMsg.msg=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0} ExtractUnallocAction.done.errMsg.msg=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
DirectoryTreeFilterNode.action.collapseAll.text=\u3059\u3079\u3066\u30b3\u30e9\u30d7\u30b9 DirectoryTreeFilterNode.action.collapseAll.text=\u3059\u3079\u3066\u30b3\u30e9\u30d7\u30b9
ExtractAction.done.notifyMsg.extractErr=\u4e0b\u8a18\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0} ExtractAction.done.notifyMsg.extractErr=\u4e0b\u8a18\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0}

View File

@ -27,7 +27,6 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -56,13 +55,11 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl; import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer; import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ArtifactNodeSelectionInfo; import org.sleuthkit.autopsy.datamodel.ArtifactNodeSelectionInfo;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.CreditCards; import org.sleuthkit.autopsy.datamodel.CreditCards;
@ -99,7 +96,7 @@ import org.sleuthkit.datamodel.TskCoreException;
@Messages({ @Messages({
"DirectoryTreeTopComponent.resultsView.title=Listing" "DirectoryTreeTopComponent.resultsView.title=Listing"
}) })
public final class DirectoryTreeTopComponent extends TopComponent implements DataExplorer, ExplorerManager.Provider, BlackboardResultViewer { public final class DirectoryTreeTopComponent extends TopComponent implements DataExplorer, ExplorerManager.Provider {
private final transient ExplorerManager em = new ExplorerManager(); private final transient ExplorerManager em = new ExplorerManager();
private static DirectoryTreeTopComponent instance; private static DirectoryTreeTopComponent instance;
@ -851,7 +848,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
return false; return false;
} }
@Override
public void viewArtifact(final BlackboardArtifact art) { public void viewArtifact(final BlackboardArtifact art) {
int typeID = art.getArtifactTypeID(); int typeID = art.getArtifactTypeID();
String typeName = art.getArtifactTypeName(); String typeName = art.getArtifactTypeName();
@ -1064,28 +1060,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// Another thread is needed because we have to wait for dataResult to populate // Another thread is needed because we have to wait for dataResult to populate
} }
@Override
public void viewArtifactContent(BlackboardArtifact art) { public void viewArtifactContent(BlackboardArtifact art) {
new ViewContextAction( new ViewContextAction(
NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.action.viewArtContent.text"), NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.action.viewArtContent.text"),
new BlackboardArtifactNode(art)).actionPerformed(null); new BlackboardArtifactNode(art)).actionPerformed(null);
} }
@Override
public void addOnFinishedListener(PropertyChangeListener l) { public void addOnFinishedListener(PropertyChangeListener l) {
DirectoryTreeTopComponent.this.addPropertyChangeListener(l); DirectoryTreeTopComponent.this.addPropertyChangeListener(l);
} }
void fireViewerComplete() {
try {
firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
NbBundle.getMessage(this.getClass(),
"DirectoryTreeTopComponent.moduleErr.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
}
} }

View File

@ -3,7 +3,7 @@
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties> <Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[750, 500]"/> <Dimension value="[701, 453]"/>
</Property> </Property>
</Properties> </Properties>
<AuxValues> <AuxValues>
@ -32,19 +32,24 @@
</Layout> </Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1"> <Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[701, 453]"/>
</Property>
</Properties>
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="externalViewerTitleLabel" pref="777" max="32767" attributes="0"/> <Component id="externalViewerTitleLabel" pref="681" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="777" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -55,7 +60,7 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/> <Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="475" max="32767" attributes="0"/> <EmptySpace pref="428" max="32767" attributes="0"/>
</Group> </Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
@ -81,13 +86,18 @@
<SubComponents> <SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1"> <Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties> <Properties>
<Property name="dividerLocation" type="int" value="350"/> <Property name="dividerLocation" type="int" value="365"/>
<Property name="dividerSize" type="int" value="1"/> <Property name="dividerSize" type="int" value="1"/>
</Properties> </Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="exePanel"> <Container class="javax.swing.JPanel" name="exePanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[311, 224]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/> <JSplitPaneConstraints position="right"/>
@ -103,7 +113,7 @@
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace pref="159" max="32767" attributes="0"/> <EmptySpace pref="47" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -114,7 +124,7 @@
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/> <Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/> <Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="408" max="32767" attributes="0"/> <EmptySpace pref="361" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -137,6 +147,11 @@
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="rulesPanel"> <Container class="javax.swing.JPanel" name="rulesPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[365, 406]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/> <JSplitPaneConstraints position="left"/>
@ -149,42 +164,35 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Component id="ruleListLabel" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Component id="rulesScrollPane" min="-2" pref="345" max="-2" attributes="0"/>
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/> <Group type="102" alignment="1" attributes="0">
<Group type="102" attributes="0"> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="rulesScrollPane" min="-2" pref="311" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/> <Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/> <Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/> <Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="ruleListLabel" min="-2" max="-2" attributes="0"/> <Component id="ruleListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="rulesScrollPane" pref="380" max="32767" attributes="0"/> <Component id="rulesScrollPane" pref="328" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editRuleButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="editRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -224,6 +232,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.newRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.newRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newRuleButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newRuleButtonActionPerformed"/>
@ -237,6 +254,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editRuleButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editRuleButtonActionPerformed"/>
@ -250,6 +276,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/>

View File

@ -93,13 +93,17 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
editRuleButton = new javax.swing.JButton(); editRuleButton = new javax.swing.JButton();
deleteRuleButton = new javax.swing.JButton(); deleteRuleButton = new javax.swing.JButton();
setPreferredSize(new java.awt.Dimension(750, 500)); setPreferredSize(new java.awt.Dimension(701, 453));
jPanel1.setPreferredSize(new java.awt.Dimension(701, 453));
org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N
jSplitPane1.setDividerLocation(350); jSplitPane1.setDividerLocation(365);
jSplitPane1.setDividerSize(1); jSplitPane1.setDividerSize(1);
exePanel.setPreferredSize(new java.awt.Dimension(311, 224));
org.openide.awt.Mnemonics.setLocalizedText(exePathLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(exePathLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(exePathNameLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathNameLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(exePathNameLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathNameLabel.text")); // NOI18N
@ -113,7 +117,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(exePathLabel) .addComponent(exePathLabel)
.addComponent(exePathNameLabel)) .addComponent(exePathNameLabel))
.addContainerGap(159, Short.MAX_VALUE)) .addContainerGap(47, Short.MAX_VALUE))
); );
exePanelLayout.setVerticalGroup( exePanelLayout.setVerticalGroup(
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -122,17 +126,22 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addComponent(exePathLabel) .addComponent(exePathLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(exePathNameLabel) .addComponent(exePathNameLabel)
.addContainerGap(408, Short.MAX_VALUE)) .addContainerGap(361, Short.MAX_VALUE))
); );
jSplitPane1.setRightComponent(exePanel); jSplitPane1.setRightComponent(exePanel);
rulesPanel.setPreferredSize(new java.awt.Dimension(365, 406));
org.openide.awt.Mnemonics.setLocalizedText(ruleListLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ruleListLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(ruleListLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ruleListLabel.text")); // NOI18N
rulesScrollPane.setViewportView(rulesList); rulesScrollPane.setViewportView(rulesList);
newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton.text")); // NOI18N
newRuleButton.setMaximumSize(new java.awt.Dimension(111, 25));
newRuleButton.setMinimumSize(new java.awt.Dimension(111, 25));
newRuleButton.setPreferredSize(new java.awt.Dimension(111, 25));
newRuleButton.addActionListener(new java.awt.event.ActionListener() { newRuleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newRuleButtonActionPerformed(evt); newRuleButtonActionPerformed(evt);
@ -141,6 +150,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
editRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N editRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.editRuleButton.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.editRuleButton.text")); // NOI18N
editRuleButton.setMaximumSize(new java.awt.Dimension(111, 25));
editRuleButton.setMinimumSize(new java.awt.Dimension(111, 25));
editRuleButton.setPreferredSize(new java.awt.Dimension(111, 25));
editRuleButton.addActionListener(new java.awt.event.ActionListener() { editRuleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
editRuleButtonActionPerformed(evt); editRuleButtonActionPerformed(evt);
@ -149,6 +161,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.deleteRuleButton.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.deleteRuleButton.text")); // NOI18N
deleteRuleButton.setMaximumSize(new java.awt.Dimension(111, 25));
deleteRuleButton.setMinimumSize(new java.awt.Dimension(111, 25));
deleteRuleButton.setPreferredSize(new java.awt.Dimension(111, 25));
deleteRuleButton.addActionListener(new java.awt.event.ActionListener() { deleteRuleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteRuleButtonActionPerformed(evt); deleteRuleButtonActionPerformed(evt);
@ -162,20 +177,16 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(rulesPanelLayout.createSequentialGroup() .addGroup(rulesPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(rulesPanelLayout.createSequentialGroup() .addComponent(ruleListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, rulesPanelLayout.createSequentialGroup()
.addGroup(rulesPanelLayout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 311, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
.addGroup(rulesPanelLayout.createSequentialGroup()
.addComponent(newRuleButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editRuleButton) .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteRuleButton) .addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))) .addContainerGap())
); );
rulesPanelLayout.setVerticalGroup( rulesPanelLayout.setVerticalGroup(
rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -183,12 +194,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addContainerGap() .addContainerGap()
.addComponent(ruleListLabel) .addComponent(ruleListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) .addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newRuleButton) .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(editRuleButton) .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(deleteRuleButton)) .addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap()) .addContainerGap())
); );
@ -202,12 +213,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE) .addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 681, Short.MAX_VALUE)
.addContainerGap()) .addContainerGap())
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE) .addComponent(jScrollPane1)
.addContainerGap())) .addContainerGap()))
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
@ -215,7 +226,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(externalViewerTitleLabel) .addComponent(externalViewerTitleLabel)
.addContainerGap(475, Short.MAX_VALUE)) .addContainerGap(428, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(32, 32, 32) .addGap(32, 32, 32)

View File

@ -21,14 +21,11 @@ package org.sleuthkit.autopsy.ingest;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet; import javax.swing.text.html.StyleSheet;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
import org.sleuthkit.autopsy.ingest.IngestMessagePanel.IngestMessageGroup; import org.sleuthkit.autopsy.ingest.IngestMessagePanel.IngestMessageGroup;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -40,7 +37,8 @@ import org.sleuthkit.datamodel.TskException;
*/ */
class IngestMessageDetailsPanel extends javax.swing.JPanel { class IngestMessageDetailsPanel extends javax.swing.JPanel {
private IngestMessageMainPanel mainPanel; private final IngestMessageMainPanel mainPanel;
private final DirectoryTreeTopComponent dtc = DirectoryTreeTopComponent.findInstance();
/** /**
* Creates new form IngestMessageDetailsPanel * Creates new form IngestMessageDetailsPanel
@ -69,18 +67,6 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
styleSheet.addRule("td {white-space:pre-wrap;overflow:hidden;}"); //NON-NLS styleSheet.addRule("td {white-space:pre-wrap;overflow:hidden;}"); //NON-NLS
styleSheet.addRule("th {font-weight:bold;}"); //NON-NLS styleSheet.addRule("th {font-weight:bold;}"); //NON-NLS
BlackboardResultViewer v = Lookup.getDefault().lookup(BlackboardResultViewer.class);
v.addOnFinishedListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(BlackboardResultViewer.FINISHED_DISPLAY_EVT)) {
artifactViewerFinished();
}
}
});
//right click //right click
messageDetailsPane.setComponentPopupMenu(rightClickMenu); messageDetailsPane.setComponentPopupMenu(rightClickMenu);
ActionListener actList = new ActionListener() { ActionListener actList = new ActionListener() {
@ -193,11 +179,27 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void viewContentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewContentButtonActionPerformed private void viewContentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewContentButtonActionPerformed
viewContent(evt); messageDetailsPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
dtc.viewArtifactContent(art);
}
}
messageDetailsPane.setCursor(null);
}//GEN-LAST:event_viewContentButtonActionPerformed }//GEN-LAST:event_viewContentButtonActionPerformed
private void viewArtifactButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewArtifactButtonActionPerformed private void viewArtifactButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewArtifactButtonActionPerformed
viewArtifact(evt); messageDetailsPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
dtc.viewArtifact(art);
}
}
messageDetailsPane.setCursor(null);
}//GEN-LAST:event_viewArtifactButtonActionPerformed }//GEN-LAST:event_viewArtifactButtonActionPerformed
private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed
@ -216,46 +218,6 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
private javax.swing.JButton viewContentButton; private javax.swing.JButton viewContentButton;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
private void viewArtifact(java.awt.event.ActionEvent evt) {
artifactViewerInvoked();
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
BlackboardResultViewer v = Lookup.getDefault().lookup(BlackboardResultViewer.class);
v.viewArtifact(art);
}
}
}
private void viewContent(java.awt.event.ActionEvent evt) {
artifactViewerInvoked();
final IngestMessageGroup messageGroup = mainPanel.getMessagePanel().getSelectedMessage();
if (messageGroup != null) {
BlackboardArtifact art = messageGroup.getData();
if (art != null) {
BlackboardResultViewer v = Lookup.getDefault().lookup(BlackboardResultViewer.class);
v.viewArtifactContent(art);
}
}
}
private void artifactViewerInvoked() {
//viewArtifactButton.setEnabled(false);
//viewContentButton.setEnabled(false);
messageDetailsPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
private void artifactViewerFinished() {
//viewArtifactButton.setEnabled(true);
//viewContentButton.setEnabled(true);
messageDetailsPane.setCursor(null);
}
/** /**
* Display the details of a given message * Display the details of a given message
* *

View File

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[718, 430]"/>
</Property>
</Properties>
<AuxValues> <AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -16,12 +21,12 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" pref="817" max="32767" attributes="0"/> <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" pref="526" max="32767" attributes="0"/> <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
@ -29,7 +34,7 @@
<Container class="javax.swing.JPanel" name="jPanel1"> <Container class="javax.swing.JPanel" name="jPanel1">
<Properties> <Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[687, 450]"/> <Dimension value="[718, 430]"/>
</Property> </Property>
</Properties> </Properties>
@ -37,36 +42,45 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="797" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jScrollPane1" max="32767" attributes="0"/> <Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1"> <Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1"> <Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties> <Properties>
<Property name="dividerLocation" type="int" value="430"/> <Property name="dividerLocation" type="int" value="365"/>
<Property name="dividerSize" type="int" value="1"/> <Property name="dividerSize" type="int" value="1"/>
</Properties> </Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="mimePanel"> <Container class="javax.swing.JPanel" name="mimePanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[369, 424]"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/> <JSplitPaneConstraints position="left"/>
@ -76,23 +90,26 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" alignment="0" pref="0" max="32767" attributes="0"/> <Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="286" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jScrollPane2" min="-2" pref="349" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="newTypeButton" min="-2" max="-2" attributes="0"/> <Component id="newTypeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Component id="removeTypeButton" min="-2" max="-2" attributes="0"/> <Component id="removeTypeButton" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace min="0" pref="191" max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -101,14 +118,14 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="427" max="32767" attributes="0"/> <Component id="jScrollPane2" pref="348" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newTypeButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newTypeButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="removeTypeButton" alignment="3" min="-2" pref="25" max="-2" attributes="0"/> <Component id="removeTypeButton" alignment="3" min="-2" pref="25" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -142,6 +159,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTypeButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTypeButtonActionPerformed"/>
@ -166,6 +192,11 @@
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="extensionPanel"> <Container class="javax.swing.JPanel" name="extensionPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[344, 424]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/> <JSplitPaneConstraints position="right"/>
@ -198,16 +229,16 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="extHeaderLabel" min="-2" max="-2" attributes="0"/> <Component id="extHeaderLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane3" pref="427" max="32767" attributes="0"/> <Component id="jScrollPane3" pref="348" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="removeExtButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="removeExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -221,6 +252,12 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.newExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[111, 25]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newExtButtonActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newExtButtonActionPerformed"/>

View File

@ -154,11 +154,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
removeExtButton = new javax.swing.JButton(); removeExtButton = new javax.swing.JButton();
extHeaderLabel = new javax.swing.JLabel(); extHeaderLabel = new javax.swing.JLabel();
jPanel1.setPreferredSize(new java.awt.Dimension(687, 450)); setPreferredSize(new java.awt.Dimension(718, 430));
jSplitPane1.setDividerLocation(430); jPanel1.setPreferredSize(new java.awt.Dimension(718, 430));
jScrollPane1.setRequestFocusEnabled(false);
jSplitPane1.setDividerLocation(365);
jSplitPane1.setDividerSize(1); jSplitPane1.setDividerSize(1);
mimePanel.setPreferredSize(new java.awt.Dimension(369, 424));
mimePanel.setRequestFocusEnabled(false);
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N
mimeTable.setModel(mimeTableModel); mimeTable.setModel(mimeTableModel);
@ -166,6 +173,9 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
newTypeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N newTypeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
newTypeButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newTypeButton.text")); // NOI18N newTypeButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newTypeButton.text")); // NOI18N
newTypeButton.setMaximumSize(new java.awt.Dimension(111, 25));
newTypeButton.setMinimumSize(new java.awt.Dimension(111, 25));
newTypeButton.setPreferredSize(new java.awt.Dimension(111, 25));
newTypeButton.addActionListener(new java.awt.event.ActionListener() { newTypeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newTypeButtonActionPerformed(evt); newTypeButtonActionPerformed(evt);
@ -188,16 +198,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(mimePanelLayout.createSequentialGroup() .addGroup(mimePanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addGroup(mimePanelLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(jLabel1)
.addGap(286, 286, 286))
.addGroup(mimePanelLayout.createSequentialGroup() .addGroup(mimePanelLayout.createSequentialGroup()
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 349, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(mimePanelLayout.createSequentialGroup() .addGroup(mimePanelLayout.createSequentialGroup()
.addComponent(newTypeButton) .addComponent(newTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(10, 10, 10)
.addComponent(removeTypeButton))) .addComponent(removeTypeButton)))
.addGap(0, 191, Short.MAX_VALUE))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
); );
mimePanelLayout.setVerticalGroup( mimePanelLayout.setVerticalGroup(
mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -205,18 +217,22 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addContainerGap() .addContainerGap()
.addComponent(jLabel1) .addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newTypeButton) .addComponent(newTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(removeTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(removeTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap()) .addContainerGap())
); );
jSplitPane1.setLeftComponent(mimePanel); jSplitPane1.setLeftComponent(mimePanel);
extensionPanel.setPreferredSize(new java.awt.Dimension(344, 424));
newExtButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N newExtButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
newExtButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newExtButton.text")); // NOI18N newExtButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.newExtButton.text")); // NOI18N
newExtButton.setMaximumSize(new java.awt.Dimension(111, 25));
newExtButton.setMinimumSize(new java.awt.Dimension(111, 25));
newExtButton.addActionListener(new java.awt.event.ActionListener() { newExtButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newExtButtonActionPerformed(evt); newExtButtonActionPerformed(evt);
@ -248,7 +264,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extHeaderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 324, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(extHeaderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 324, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(extensionPanelLayout.createSequentialGroup() .addGroup(extensionPanelLayout.createSequentialGroup()
.addComponent(newExtButton) .addComponent(newExtButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(removeExtButton))) .addComponent(removeExtButton)))
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
@ -260,10 +276,10 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addContainerGap() .addContainerGap()
.addComponent(extHeaderLabel) .addComponent(extHeaderLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE) .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newExtButton) .addComponent(newExtButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(removeExtButton)) .addComponent(removeExtButton))
.addContainerGap()) .addContainerGap())
); );
@ -277,27 +293,27 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 797, Short.MAX_VALUE) .addComponent(jScrollPane1)
.addContainerGap()) .addGap(0, 0, 0))
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE) .addComponent(jScrollPane1)
.addContainerGap()) .addGap(0, 0, 0))
); );
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 817, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 526, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -18,22 +18,34 @@
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.experimental.autoingest;
import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.LocalDiskDSProcessor;
import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils; import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
/* /*
* A runnable that adds an archive data source as well as data sources * A runnable that adds an archive data source as well as data sources contained
* contained in the archive to the case database. * in the archive to the case database.
*/ */
class AddArchiveTask implements Runnable { class AddArchiveTask implements Runnable {
@ -43,6 +55,7 @@ class AddArchiveTask implements Runnable {
private final DataSourceProcessorProgressMonitor progressMonitor; private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback; private final DataSourceProcessorCallback callback;
private boolean criticalErrorOccurred; private boolean criticalErrorOccurred;
private final Object archiveDspLock;
private static final String ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR = "Archive Extractor"; private static final String ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR = "Archive Extractor";
@ -50,19 +63,20 @@ class AddArchiveTask implements Runnable {
* Constructs a runnable task that adds an archive as well as data sources * Constructs a runnable task that adds an archive as well as data sources
* contained in the archive to the case database. * contained in the archive to the case database.
* *
* @param deviceId An ASCII-printable identifier for the device associated * @param deviceId An ASCII-printable identifier for the device
* with the data source that is intended to be unique across multiple cases * associated with the data source that is intended
* (e.g., a UUID). * to be unique across multiple cases (e.g., a UUID).
* @param archivePath Path to the archive file. * @param archivePath Path to the archive file.
* @param progressMonitor Progress monitor to report progress during * @param progressMonitor Progress monitor to report progress during
* processing. * processing.
* @param callback Callback to call when processing is done. * @param callback Callback to call when processing is done.
*/ */
AddArchiveTask(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { AddArchiveTask(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId; this.deviceId = deviceId;
this.archivePath = archivePath; this.archivePath = archivePath;
this.callback = callback; this.callback = callback;
this.progressMonitor = progressMonitor; this.progressMonitor = progressMonitor;
this.archiveDspLock = new Object();
} }
/** /**
@ -70,39 +84,172 @@ class AddArchiveTask implements Runnable {
*/ */
@Override @Override
public void run() { public void run() {
progressMonitor.setIndeterminate(true);
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
List<Content> newDataSources = new ArrayList<>(); List<Content> newDataSources = new ArrayList<>();
DataSourceProcessorCallback.DataSourceProcessorResult result; DataSourceProcessorCallback.DataSourceProcessorResult result;
if (!ArchiveUtil.isArchive(Paths.get(archivePath))) { if (!ArchiveUtil.isArchive(Paths.get(archivePath))) {
criticalErrorOccurred = true; criticalErrorOccurred = true;
logger.log(Level.SEVERE, String.format("Input data source is not a valid datasource: %s", archivePath)); //NON-NLS logger.log(Level.SEVERE, String.format("Input data source is not a valid datasource: %s", archivePath)); //NON-NLS
errorMessages.add("Input data source is not a valid datasource: " + archivePath); errorMessages.add("Input data source is not a valid datasource: " + archivePath);
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS; result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
callback.done(result, errorMessages, newDataSources); callback.done(result, errorMessages, newDataSources);
} }
logger.log(Level.INFO, "Using Archive Extractor DSP to process archive {0} ", archivePath);
// extract the archive and pass the extracted folder as input // extract the archive and pass the extracted folder as input
Path destinationFolder = Paths.get("");
try { try {
Case currentCase = Case.getCurrentCase(); Case currentCase = Case.getCurrentCase();
// get file name without full path or extension
String dataSourceFileNameNoExt = FilenameUtils.getBaseName(archivePath);
// create folder to extract archive to // create folder to extract archive to
destinationFolder = Paths.get(currentCase.getModuleDirectory(), ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp()); Path destinationFolder = createDirectoryForFile(archivePath, currentCase.getModuleDirectory());
destinationFolder.toFile().mkdirs(); if (destinationFolder.toString().isEmpty()) {
// unable to create directory
criticalErrorOccurred = true;
errorMessages.add(String.format("Unable to create directory {0} to extract archive {1} ", new Object[]{destinationFolder.toString(), archivePath}));
logger.log(Level.SEVERE, String.format("Unable to create directory {0} to extract archive {1} ", new Object[]{destinationFolder.toString(), archivePath}));
return;
}
// extract contents of ZIP archive into destination folder // extract contents of ZIP archive into destination folder
//ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString()); progressMonitor.setProgressText(String.format("Extracting archive contents to: %s", destinationFolder.toString()));
List<String> extractedFiles = ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString());
int numExtractedFilesRemaining = extractedFiles.size();
// lookup all AutomatedIngestDataSourceProcessors so that we only do it once.
// LocalDisk, LocalFiles, and ArchiveDSP are removed from the list.
List<AutoIngestDataSourceProcessor> processorCandidates = getListOfValidDataSourceProcessors();
// do processing // do processing
for (String file : extractedFiles) {
// we only care about files, skip directories
File fileObject = new File(file);
if (fileObject.isDirectory()) {
numExtractedFilesRemaining--;
continue;
}
// identify all "valid" DSPs that can process this file
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = getDataSourceProcessorsForFile(Paths.get(file), errorMessages, processorCandidates);
if (validDataSourceProcessors.isEmpty()) {
continue;
}
// identified a "valid" data source within the archive
progressMonitor.setProgressText(String.format("Adding: %s", file));
/*
* NOTE: we have to move the valid data sources to a separate
* folder and then add the data source from that folder. This is
* necessary because after all valid data sources have been
* identified, we are going to add the remaining extracted
* contents of the archive as a single logical file set. Hence,
* if we do not move the data sources out of the extracted
* contents folder, those data source files will get added twice
* and can potentially result in duplicate keyword hits.
*/
Path newFolder = createDirectoryForFile(file, currentCase.getModuleDirectory());
if (newFolder.toString().isEmpty()) {
// unable to create directory
criticalErrorOccurred = true;
errorMessages.add(String.format("Unable to create directory {0} to extract content of archive {1} ", new Object[]{newFolder.toString(), archivePath}));
logger.log(Level.SEVERE, String.format("Unable to create directory {0} to extract content of archive {1} ", new Object[]{newFolder.toString(), archivePath}));
return;
}
// Copy it to a different folder
FileUtils.copyFileToDirectory(fileObject, newFolder.toFile());
Path newFilePath = Paths.get(newFolder.toString(), FilenameUtils.getName(file));
// Try each DSP in decreasing order of confidence
boolean success = false;
for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
logger.log(Level.INFO, "Using {0} to process extracted file {1} ", new Object[]{selectedProcessor.getDataSourceType(), file});
synchronized (archiveDspLock) {
try {
UUID taskId = UUID.randomUUID();
currentCase.notifyAddingDataSource(taskId);
AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, newFilePath);
DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock);
selectedProcessor.process(deviceId, newFilePath, progressMonitor, internalArchiveDspCallBack);
archiveDspLock.wait();
// at this point we got the content object(s) from the current DSP.
// check whether the data source was processed successfully
if ((internalDataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS)
|| internalDataSource.getContent().isEmpty()) {
// move onto the the next DSP that can process this data source
continue;
}
// if we are here it means the data source was addedd successfully
success = true;
newDataSources.addAll(internalDataSource.getContent());
// skip all other DSPs for this data source
break;
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
// Log that the current DSP failed and set the error flag. We consider it an error
// if a DSP fails even if a later one succeeds since we expected to be able to process
// the data source which each DSP on the list.
criticalErrorOccurred = true;
errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{newFilePath.toString(), selectedProcessor.getDataSourceType()});
}
}
}
if (success) {
// one of the DSPs successfully processed the data source. delete the
// copy of the data source in the original extracted archive folder.
// otherwise the data source is going to be added again as a logical file.
numExtractedFilesRemaining--;
FileUtils.deleteQuietly(fileObject);
} else {
// none of the DSPs were able to process the data source. delete the
// copy of the data source in the temporary folder. the data source is
// going to be added as a logical file with the rest of the extracted contents.
FileUtils.deleteQuietly(newFolder.toFile());
}
}
// after all archive contents have been examined (and moved to separate folders if necessary),
// add remaining extracted contents as one logical file set
if (numExtractedFilesRemaining > 0) {
progressMonitor.setProgressText(String.format("Adding: %s", destinationFolder.toString()));
logger.log(Level.INFO, "Adding directory {0} as logical file set", destinationFolder.toString());
synchronized (archiveDspLock) {
UUID taskId = UUID.randomUUID();
currentCase.notifyAddingDataSource(taskId);
AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, destinationFolder);
DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock);
// folder where archive was extracted to
List<String> pathsList = new ArrayList<>();
pathsList.add(destinationFolder.toString());
// use archive file name as the name of the logical file set
String archiveFileName = FilenameUtils.getName(archivePath);
LocalFilesDSProcessor localFilesDSP = new LocalFilesDSProcessor();
localFilesDSP.run(deviceId, archiveFileName, pathsList, progressMonitor, internalArchiveDspCallBack);
archiveDspLock.wait();
// at this point we got the content object(s) from the current DSP
newDataSources.addAll(internalDataSource.getContent());
}
}
} catch (Exception ex) { } catch (Exception ex) {
criticalErrorOccurred = true; criticalErrorOccurred = true;
errorMessages.add(ex.getMessage()); errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
} finally { } finally {
logger.log(Level.INFO, "Finished processing of archive {0}", archivePath);
progressMonitor.setProgress(100);
if (criticalErrorOccurred) { if (criticalErrorOccurred) {
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS; result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
} else if (!errorMessages.isEmpty()) { } else if (!errorMessages.isEmpty()) {
@ -114,10 +261,78 @@ class AddArchiveTask implements Runnable {
} }
} }
/* /**
* Attempts to cancel adding the archive to the case database. * Get a list of data source processors. LocalDisk, LocalFiles, and
* ArchiveDSP are removed from the list.
*
* @return List of data source processors
*/ */
public void cancelTask() { private List<AutoIngestDataSourceProcessor> getListOfValidDataSourceProcessors() {
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = processorCandidates.stream().collect(Collectors.toList());
for (Iterator<AutoIngestDataSourceProcessor> iterator = validDataSourceProcessors.iterator(); iterator.hasNext();) {
AutoIngestDataSourceProcessor selectedProcessor = iterator.next();
// skip local files and local disk DSPs, only looking for "valid" data sources.
// also skip nested archive files, those will be ingested as logical files and extracted during ingest
if ((selectedProcessor instanceof LocalDiskDSProcessor)
|| (selectedProcessor instanceof LocalFilesDSProcessor)
|| (selectedProcessor instanceof ArchiveExtractorDSProcessor)) {
iterator.remove();
}
}
return validDataSourceProcessors;
}
/**
* Get a list of data source processors that can process the data source of
* interest. The list is sorted by confidence in decreasing order.
*
* @param dataSourcePath Full path to the data source
* @param errorMessages List<String> for error messages
* @param errorMessages List of AutoIngestDataSourceProcessor to try
*
* @return Ordered list of applicable DSPs
*/
private List<AutoIngestDataSourceProcessor> getDataSourceProcessorsForFile(Path dataSourcePath, List<String> errorMessages,
List<AutoIngestDataSourceProcessor> processorCandidates) {
// Get an ordered list of data source processors to try
List<AutoIngestDataSourceProcessor> validDataSourceProcessorsForFile = Collections.emptyList();
try {
validDataSourceProcessorsForFile = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
criticalErrorOccurred = true;
errorMessages.add(ex.getMessage());
logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
return Collections.emptyList();
}
return validDataSourceProcessorsForFile;
}
/**
* Create a directory in ModuleOutput folder based on input file name. A
* time stamp is appended to the directory name.
*
* @param fileName File name
* @param baseDirectory Base directory. Typically the case output directory.
*
* @return Full path to the new directory
*/
private Path createDirectoryForFile(String fileName, String baseDirectory) {
// get file name without full path or extension
String fileNameNoExt = FilenameUtils.getBaseName(fileName);
// create folder to extract archive to
Path newFolder = Paths.get(baseDirectory, ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, fileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
if (newFolder.toFile().mkdirs() == false) {
// unable to create directory
return Paths.get("");
}
return newFolder;
} }
} }

View File

@ -35,7 +35,7 @@ import org.sleuthkit.datamodel.Content;
class AddDataSourceCallback extends DataSourceProcessorCallback { class AddDataSourceCallback extends DataSourceProcessorCallback {
private final Case caseForJob; private final Case caseForJob;
private final DataSource dataSourceInfo; private final AutoIngestDataSource dataSourceInfo;
private final UUID taskId; private final UUID taskId;
private final Object lock; private final Object lock;
@ -48,7 +48,7 @@ class AddDataSourceCallback extends DataSourceProcessorCallback {
* @param dataSourceInfo The data source * @param dataSourceInfo The data source
* @param taskId The task id to associate with ingest job events. * @param taskId The task id to associate with ingest job events.
*/ */
AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId, Object lock) { AddDataSourceCallback(Case caseForJob, AutoIngestDataSource dataSourceInfo, UUID taskId, Object lock) {
this.caseForJob = caseForJob; this.caseForJob = caseForJob;
this.dataSourceInfo = dataSourceInfo; this.dataSourceInfo = dataSourceInfo;
this.taskId = taskId; this.taskId = taskId;

View File

@ -18,13 +18,15 @@
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.experimental.autoingest;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders; import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
@ -35,13 +37,12 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
* add data source wizard. It also provides a run method overload to allow it to * add data source wizard. It also provides a run method overload to allow it to
* be used independently of the wizard. * be used independently of the wizard.
*/ */
//@ServiceProviders(value={ @ServiceProviders(value={
// @ServiceProvider(service=DataSourceProcessor.class), @ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
// @ServiceProvider(service=AutoIngestDataSourceProcessor.class)} )
//)
@NbBundle.Messages({ @NbBundle.Messages({
"ArchiveDSP.dsType.text=Archive file"}) "ArchiveDSP.dsType.text=Archive file"})
public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIngestDataSourceProcessor { public class ArchiveExtractorDSProcessor implements AutoIngestDataSourceProcessor {
private final static String DATA_SOURCE_TYPE = Bundle.ArchiveDSP_dsType_text(); private final static String DATA_SOURCE_TYPE = Bundle.ArchiveDSP_dsType_text();
@ -50,6 +51,8 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
private String archivePath; private String archivePath;
private boolean setDataSourceOptionsCalled; private boolean setDataSourceOptionsCalled;
private final ExecutorService jobProcessingExecutor;
private static final String ARCHIVE_DSP_THREAD_NAME = "Archive-DSP-%d";
private AddArchiveTask addArchiveTask; private AddArchiveTask addArchiveTask;
/** /**
@ -60,6 +63,7 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
*/ */
public ArchiveExtractorDSProcessor() { public ArchiveExtractorDSProcessor() {
configPanel = ArchiveFilePanel.createInstance(ArchiveExtractorDSProcessor.class.getName(), ArchiveUtil.getArchiveFilters()); configPanel = ArchiveFilePanel.createInstance(ArchiveExtractorDSProcessor.class.getName(), ArchiveUtil.getArchiveFilters());
jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(ARCHIVE_DSP_THREAD_NAME).build());
} }
@Override @Override
@ -151,21 +155,15 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
*/ */
public void run(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { public void run(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addArchiveTask = new AddArchiveTask(deviceId, archivePath, progressMonitor, callback); addArchiveTask = new AddArchiveTask(deviceId, archivePath, progressMonitor, callback);
new Thread(addArchiveTask).start(); jobProcessingExecutor.submit(addArchiveTask);
} }
/** /**
* Requests cancellation of the background task that adds a data source to * This DSP is a service to AutoIngestDataSourceProcessor only. Hence it is
* the case database, after the task is started using the run method. This * only used by AIM. AIM currently doesn't support DSP cancellation.
* 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 @Override
public void cancel() { public void cancel() {
if (null != addArchiveTask) {
addArchiveTask.cancelTask();
}
} }
@Override @Override
@ -175,50 +173,4 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
configPanel.reset(); configPanel.reset();
setDataSourceOptionsCalled = false; setDataSourceOptionsCalled = false;
} }
/**
* Extracts the contents of a ZIP archive submitted as a data source to a
* subdirectory of the auto ingest module output directory.
*
* @throws IOException if there is a problem extracting the data source from
* the archive.
private static Path extractDataSource(Path outputDirectoryPath, Path dataSourcePath) throws IOException {
String dataSourceFileNameNoExt = FilenameUtils.removeExtension(dataSourcePath.getFileName().toString());
Path destinationFolder = Paths.get(outputDirectoryPath.toString(),
AUTO_INGEST_MODULE_OUTPUT_DIR,
dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
Files.createDirectories(destinationFolder);
int BUFFER_SIZE = 524288; // Read/write 500KB at a time
File sourceZipFile = dataSourcePath.toFile();
ZipFile zipFile;
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
Enumeration<? extends ZipEntry> zipFileEntries = zipFile.entries();
try {
while (zipFileEntries.hasMoreElements()) {
ZipEntry entry = zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(destinationFolder.toString(), currentEntry);
destFile = new File(destinationFolder.toString(), destFile.getName());
File destinationParent = destFile.getParentFile();
destinationParent.mkdirs();
if (!entry.isDirectory()) {
BufferedInputStream is = new BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
byte data[] = new byte[BUFFER_SIZE];
try (FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
currentByte = is.read(data, 0, BUFFER_SIZE);
while (currentByte != -1) {
dest.write(data, 0, currentByte);
currentByte = is.read(data, 0, BUFFER_SIZE);
}
}
}
}
} finally {
zipFile.close();
}
return destinationFolder;
} */
} }

View File

@ -214,10 +214,11 @@ final class ArchiveUtil {
* @param destinationFolder Path to directory where results will be * @param destinationFolder Path to directory where results will be
* extracted to. * extracted to.
* *
* @return List of file names contained within archive
* @throws * @throws
* ArchiveExtractionException * ArchiveExtractionException
*/ */
static void unpackArchiveFile(String archiveFilePath, String destinationFolder) throws ArchiveExtractionException { static List<String> unpackArchiveFile(String archiveFilePath, String destinationFolder) throws ArchiveExtractionException {
if (!SevenZip.isInitializedSuccessfully() && (SevenZip.getLastInitializationException() == null)) { if (!SevenZip.isInitializedSuccessfully() && (SevenZip.getLastInitializationException() == null)) {
try { try {
SevenZip.initSevenZipFromPlatformJAR(); SevenZip.initSevenZipFromPlatformJAR();
@ -225,6 +226,7 @@ final class ArchiveUtil {
throw new ArchiveExtractionException("Unable to initialize 7Zip libraries", ex); throw new ArchiveExtractionException("Unable to initialize 7Zip libraries", ex);
} }
} }
List<String> files = new ArrayList<>();
ISevenZipInArchive inArchive = null; ISevenZipInArchive inArchive = null;
try { try {
RandomAccessFile randomAccessFile = new RandomAccessFile(new File(archiveFilePath), "r"); RandomAccessFile randomAccessFile = new RandomAccessFile(new File(archiveFilePath), "r");
@ -251,6 +253,8 @@ final class ArchiveUtil {
} }
} }
} }
// keep track of extracted files
files.add(fullPath.toString());
} }
} catch (Exception ex) { } catch (Exception ex) {
throw new ArchiveExtractionException("Exception while unpacking archive contents", ex); throw new ArchiveExtractionException("Exception while unpacking archive contents", ex);
@ -263,6 +267,7 @@ final class ArchiveUtil {
throw new ArchiveExtractionException("Exception while closing the archive", ex); throw new ArchiveExtractionException("Exception while closing the archive", ex);
} }
} }
return files;
} }
/** /**

View File

@ -1,108 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Level;
/**
* Utility for creating and checking for the existence of an automated ingest
* alert file. The purpose of the file is to put a marker in the case directory
* when an error or warning occurs in connection with an automated ingest job.
*/
final class AutoIngestAlertFile {
private static final String ERROR_FILE_NAME = "autoingest.alert";
/**
* Checks whether an automated ingest alert file exists in a case directory.
*
* @param caseDirectoryPath The case directory path.
*
* @return True or false.
*/
static boolean exists(Path caseDirectoryPath) {
return caseDirectoryPath.resolve(ERROR_FILE_NAME).toFile().exists();
}
/**
* Creates an automated ingest alert file in a case directory if such a file
* does not already exist.
*
* @param caseDirectoryPath The case directory path.
*
* @return True or false.
*/
static void create(Path caseDirectoryPath) throws AutoIngestAlertFileException {
try {
Files.createFile(caseDirectoryPath.resolve(ERROR_FILE_NAME));
} catch (FileAlreadyExistsException ignored) {
/*
* The file already exists, the exception is not exceptional.
*/
} catch (IOException ex) {
/*
* FileAlreadyExistsException implementation is optional, so check
* for that case.
*/
if (!exists(caseDirectoryPath)) {
throw new AutoIngestAlertFileException(String.format("Error creating automated ingest alert file in %s", caseDirectoryPath), ex);
}
}
}
/**
* Exception thrown when there is a problem creating an alert file.
*/
final static class AutoIngestAlertFileException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception to throw when there is a problem creating an
* alert file.
*
* @param message The exception message.
*/
private AutoIngestAlertFileException(String message) {
super(message);
}
/**
* Constructs an exception to throw when there is a problem creating an
* alert file.
*
* @param message The exception message.
* @param cause The cause of the exception, if it was an exception.
*/
private AutoIngestAlertFileException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* Prevents instantiation of this utility class.
*/
private AutoIngestAlertFile() {
}
}

View File

@ -17,46 +17,22 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="pendingScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="bnPrioritizeCase" max="32767" attributes="0"/>
<Component id="bnPrioritizeJob" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="bnPause" linkSize="1" min="-2" max="-2" attributes="0"/> <Component id="bnPause" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnRefresh" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnOptions" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnOpenLogDir" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="bnExit" linkSize="1" min="-2" pref="94" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="runningScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0"> <Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
<Component id="bnCancelJob" linkSize="1" pref="117" max="32767" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnShowProgress" linkSize="1" pref="116" max="32767" attributes="0"/> <Component id="bnOptions" min="-2" max="-2" attributes="0"/>
<Component id="bnCancelModule" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnDeleteCase" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/> <Component id="bnOpenLogDir" min="-2" max="-2" attributes="0"/>
<Component id="bnShowCaseLog" max="32767" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnReprocessJob" alignment="0" max="32767" attributes="0"/> <Component id="bnClusterMetrics" min="-2" max="-2" attributes="0"/>
</Group> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnExit" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="lbStatus" min="-2" max="-2" attributes="0"/> <Component id="lbStatus" min="-2" max="-2" attributes="0"/>
@ -73,8 +49,36 @@
</Group> </Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="runningScrollPane" min="-2" pref="1021" max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="1021" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="bnCancelJob" linkSize="1" max="32767" attributes="0"/>
<Component id="bnShowProgress" linkSize="1" max="32767" attributes="0"/>
<Component id="bnCancelModule" linkSize="1" alignment="0" max="32767" attributes="0"/>
<Component id="bnDeleteCase" linkSize="1" alignment="0" max="32767" attributes="0"/>
<Component id="bnShowCaseLog" max="32767" attributes="0"/>
<Component id="bnReprocessJob" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="pendingScrollPane" min="-2" pref="1021" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="bnPrioritizeCase" max="32767" attributes="0"/>
<Component id="bnPrioritizeJob" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -99,9 +103,9 @@
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="82" max="-2" attributes="0"/> <EmptySpace min="-2" pref="82" max="-2" attributes="0"/>
<Component id="bnPrioritizeCase" min="-2" max="-2" attributes="0"/> <Component id="bnPrioritizeCase" linkSize="2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="bnPrioritizeJob" min="-2" max="-2" attributes="0"/> <Component id="bnPrioritizeJob" linkSize="2" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -135,16 +139,13 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="completedScrollPane" min="-2" pref="179" max="-2" attributes="0"/> <Component id="completedScrollPane" min="-2" pref="179" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0"> <Component id="bnPause" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnExit" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="bnRefresh" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnOpenLogDir" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="bnOptions" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> <Component id="bnOpenLogDir" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Component id="bnClusterMetrics" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnPause" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="bnExit" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnRefresh" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnOptions" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -169,6 +170,7 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.pendingTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.pendingTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<Property name="rowHeight" type="int" value="20" postCode="pendingTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == pendingTable.getSelectedRow()) {&#xa; pendingTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/> <Property name="rowHeight" type="int" value="20" postCode="pendingTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == pendingTable.getSelectedRow()) {&#xa; pendingTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -192,6 +194,7 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.runningTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.runningTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<Property name="rowHeight" type="int" value="20" postCode="runningTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == runningTable.getSelectedRow()) {&#xa; runningTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/> <Property name="rowHeight" type="int" value="20" postCode="runningTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == runningTable.getSelectedRow()) {&#xa; runningTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -215,6 +218,7 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.completedTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.completedTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="autoResizeMode" type="int" value="4"/>
<Property name="rowHeight" type="int" value="20" postCode="completedTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == completedTable.getSelectedRow()) {&#xa; completedTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/> <Property name="rowHeight" type="int" value="20" postCode="completedTable.setSelectionModel(new DefaultListSelectionModel() {&#xa; private static final long serialVersionUID = 1L;&#xa; @Override&#xa; public void setSelectionInterval(int index0, int index1) {&#xa; if (index0 == completedTable.getSelectedRow()) {&#xa; completedTable.clearSelection();&#xa; } else {&#xa; super.setSelectionInterval(index0, index1);&#xa; }&#xa; }&#xa;});"/>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/> <JTableSelectionModel selectionMode="0"/>
@ -231,6 +235,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnCancelJob.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnCancelJob.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelJobActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelJobActionPerformed"/>
@ -244,6 +257,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnDeleteCase.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnDeleteCase.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnDeleteCaseActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnDeleteCaseActionPerformed"/>
@ -287,6 +309,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnRefresh.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnRefresh.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnRefreshActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnRefreshActionPerformed"/>
@ -300,6 +331,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnCancelModule.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnCancelModule.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelModuleActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelModuleActionPerformed"/>
@ -313,6 +353,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnExit.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnExit.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnExitActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnExitActionPerformed"/>
@ -327,6 +376,15 @@
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnOptions.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnOptions.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOptionsActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOptionsActionPerformed"/>
@ -340,6 +398,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnShowProgress.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnShowProgress.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowProgressActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowProgressActionPerformed"/>
@ -353,6 +420,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPause.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPause.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPauseActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPauseActionPerformed"/>
@ -366,6 +442,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPrioritizeCase.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPrioritizeCase.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPrioritizeCaseActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPrioritizeCaseActionPerformed"/>
@ -379,6 +464,15 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnShowCaseLog.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnShowCaseLog.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowCaseLogActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnShowCaseLogActionPerformed"/>
@ -419,6 +513,15 @@
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPrioritizeJob.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnPrioritizeJob.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPrioritizeJobActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnPrioritizeJobActionPerformed"/>
@ -453,20 +556,57 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnOpenLogDir.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnOpenLogDir.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOpenLogDirActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOpenLogDirActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JButton" name="bnClusterMetrics">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnClusterMetrics.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnClusterMetricsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="bnReprocessJob"> <Component class="javax.swing.JButton" name="bnReprocessJob">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnReprocessJob.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnReprocessJob.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[162, 23]"/>
</Property>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnReprocessJobActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnReprocessJobActionPerformed"/>
</Events> </Events>
</Component> </Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -73,6 +73,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
* one such panel per node. * one such panel per node.
*/ */
@Messages({ @Messages({
"AutoIngestControlPanel.bnClusterMetrics.text=Cluster Metrics",
"AutoIngestControlPanel.bnPause.text=Pause", "AutoIngestControlPanel.bnPause.text=Pause",
"AutoIngestControlPanel.bnPause.paused=Paused", "AutoIngestControlPanel.bnPause.paused=Paused",
"AutoIngestControlPanel.bnPause.running=Running", "AutoIngestControlPanel.bnPause.running=Running",
@ -116,7 +117,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
"AutoIngestControlPanel.bnPrioritizeJob.actionCommand=<AutoIngestControlPanel.bnPrioritizeJob.text>", "AutoIngestControlPanel.bnPrioritizeJob.actionCommand=<AutoIngestControlPanel.bnPrioritizeJob.text>",
"AutoIngestControlPanel.lbServicesStatus.text=Services Status:", "AutoIngestControlPanel.lbServicesStatus.text=Services Status:",
"AutoIngestControlPanel.tbServicesStatusMessage.text=", "AutoIngestControlPanel.tbServicesStatusMessage.text=",
"AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Directory", "AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Folder",
"AutoIngestControlPanel.bnReprocessJob.text=Reprocess Job", "AutoIngestControlPanel.bnReprocessJob.text=Reprocess Job",
"AutoIngestControlPanel.bnPrioritizeFolder.label=<AutoIngestControlPanel.bnPrioritizeJob.text>", "AutoIngestControlPanel.bnPrioritizeFolder.label=<AutoIngestControlPanel.bnPrioritizeJob.text>",
"AutoIngestControlPanel.Cancelling=Cancelling...", "AutoIngestControlPanel.Cancelling=Cancelling...",
@ -1198,10 +1199,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
lbServicesStatus = new javax.swing.JLabel(); lbServicesStatus = new javax.swing.JLabel();
tbServicesStatusMessage = new javax.swing.JTextField(); tbServicesStatusMessage = new javax.swing.JTextField();
bnOpenLogDir = new javax.swing.JButton(); bnOpenLogDir = new javax.swing.JButton();
bnClusterMetrics = new javax.swing.JButton();
bnReprocessJob = new javax.swing.JButton(); bnReprocessJob = new javax.swing.JButton();
pendingTable.setModel(pendingTableModel); pendingTable.setModel(pendingTableModel);
pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.pendingTable.toolTipText")); // NOI18N pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.pendingTable.toolTipText")); // NOI18N
pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
pendingTable.setRowHeight(20); pendingTable.setRowHeight(20);
pendingTable.setSelectionModel(new DefaultListSelectionModel() { pendingTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -1219,6 +1222,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
runningTable.setModel(runningTableModel); runningTable.setModel(runningTableModel);
runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.runningTable.toolTipText")); // NOI18N runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.runningTable.toolTipText")); // NOI18N
runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
runningTable.setRowHeight(20); runningTable.setRowHeight(20);
runningTable.setSelectionModel(new DefaultListSelectionModel() { runningTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -1236,6 +1240,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
completedTable.setModel(completedTableModel); completedTable.setModel(completedTableModel);
completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.completedTable.toolTipText")); // NOI18N completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.completedTable.toolTipText")); // NOI18N
completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
completedTable.setRowHeight(20); completedTable.setRowHeight(20);
completedTable.setSelectionModel(new DefaultListSelectionModel() { completedTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -1253,6 +1258,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnCancelJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnCancelJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.text")); // NOI18N
bnCancelJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.toolTipText")); // NOI18N bnCancelJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelJob.toolTipText")); // NOI18N
bnCancelJob.setMaximumSize(new java.awt.Dimension(162, 23));
bnCancelJob.setMinimumSize(new java.awt.Dimension(162, 23));
bnCancelJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnCancelJob.addActionListener(new java.awt.event.ActionListener() { bnCancelJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelJobActionPerformed(evt); bnCancelJobActionPerformed(evt);
@ -1261,6 +1269,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnDeleteCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnDeleteCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.text")); // NOI18N
bnDeleteCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.toolTipText")); // NOI18N bnDeleteCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnDeleteCase.toolTipText")); // NOI18N
bnDeleteCase.setMaximumSize(new java.awt.Dimension(162, 23));
bnDeleteCase.setMinimumSize(new java.awt.Dimension(162, 23));
bnDeleteCase.setPreferredSize(new java.awt.Dimension(162, 23));
bnDeleteCase.addActionListener(new java.awt.event.ActionListener() { bnDeleteCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnDeleteCaseActionPerformed(evt); bnDeleteCaseActionPerformed(evt);
@ -1278,6 +1289,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.text")); // NOI18N
bnRefresh.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.toolTipText")); // NOI18N bnRefresh.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnRefresh.toolTipText")); // NOI18N
bnRefresh.setMaximumSize(new java.awt.Dimension(162, 23));
bnRefresh.setMinimumSize(new java.awt.Dimension(162, 23));
bnRefresh.setPreferredSize(new java.awt.Dimension(162, 23));
bnRefresh.addActionListener(new java.awt.event.ActionListener() { bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt); bnRefreshActionPerformed(evt);
@ -1286,6 +1300,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnCancelModule, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnCancelModule, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.text")); // NOI18N
bnCancelModule.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.toolTipText")); // NOI18N bnCancelModule.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnCancelModule.toolTipText")); // NOI18N
bnCancelModule.setMaximumSize(new java.awt.Dimension(162, 23));
bnCancelModule.setMinimumSize(new java.awt.Dimension(162, 23));
bnCancelModule.setPreferredSize(new java.awt.Dimension(162, 23));
bnCancelModule.addActionListener(new java.awt.event.ActionListener() { bnCancelModule.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelModuleActionPerformed(evt); bnCancelModuleActionPerformed(evt);
@ -1294,6 +1311,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnExit, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnExit, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.text")); // NOI18N
bnExit.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.toolTipText")); // NOI18N bnExit.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnExit.toolTipText")); // NOI18N
bnExit.setMaximumSize(new java.awt.Dimension(162, 23));
bnExit.setMinimumSize(new java.awt.Dimension(162, 23));
bnExit.setPreferredSize(new java.awt.Dimension(162, 23));
bnExit.addActionListener(new java.awt.event.ActionListener() { bnExit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnExitActionPerformed(evt); bnExitActionPerformed(evt);
@ -1303,6 +1323,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnOptions, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnOptions, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.text")); // NOI18N
bnOptions.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.toolTipText")); // NOI18N bnOptions.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.toolTipText")); // NOI18N
bnOptions.setEnabled(false); bnOptions.setEnabled(false);
bnOptions.setMaximumSize(new java.awt.Dimension(162, 23));
bnOptions.setMinimumSize(new java.awt.Dimension(162, 23));
bnOptions.setPreferredSize(new java.awt.Dimension(162, 23));
bnOptions.addActionListener(new java.awt.event.ActionListener() { bnOptions.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOptionsActionPerformed(evt); bnOptionsActionPerformed(evt);
@ -1311,6 +1334,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnShowProgress, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnShowProgress, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.text")); // NOI18N
bnShowProgress.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.toolTipText")); // NOI18N bnShowProgress.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowProgress.toolTipText")); // NOI18N
bnShowProgress.setMaximumSize(new java.awt.Dimension(162, 23));
bnShowProgress.setMinimumSize(new java.awt.Dimension(162, 23));
bnShowProgress.setPreferredSize(new java.awt.Dimension(162, 23));
bnShowProgress.addActionListener(new java.awt.event.ActionListener() { bnShowProgress.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowProgressActionPerformed(evt); bnShowProgressActionPerformed(evt);
@ -1319,6 +1345,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPause, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnPause, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.text")); // NOI18N
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipText")); // NOI18N bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipText")); // NOI18N
bnPause.setMaximumSize(new java.awt.Dimension(162, 23));
bnPause.setMinimumSize(new java.awt.Dimension(162, 23));
bnPause.setPreferredSize(new java.awt.Dimension(162, 23));
bnPause.addActionListener(new java.awt.event.ActionListener() { bnPause.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPauseActionPerformed(evt); bnPauseActionPerformed(evt);
@ -1327,6 +1356,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeCase, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.text")); // NOI18N
bnPrioritizeCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.toolTipText")); // NOI18N bnPrioritizeCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeCase.toolTipText")); // NOI18N
bnPrioritizeCase.setMaximumSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.setMinimumSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.setPreferredSize(new java.awt.Dimension(162, 23));
bnPrioritizeCase.addActionListener(new java.awt.event.ActionListener() { bnPrioritizeCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeCaseActionPerformed(evt); bnPrioritizeCaseActionPerformed(evt);
@ -1335,6 +1367,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnShowCaseLog, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnShowCaseLog, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.text")); // NOI18N
bnShowCaseLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.toolTipText")); // NOI18N bnShowCaseLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnShowCaseLog.toolTipText")); // NOI18N
bnShowCaseLog.setMaximumSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.setMinimumSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.setPreferredSize(new java.awt.Dimension(162, 23));
bnShowCaseLog.addActionListener(new java.awt.event.ActionListener() { bnShowCaseLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowCaseLogActionPerformed(evt); bnShowCaseLogActionPerformed(evt);
@ -1352,6 +1387,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.text")); // NOI18N
bnPrioritizeJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.toolTipText")); // NOI18N bnPrioritizeJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.toolTipText")); // NOI18N
bnPrioritizeJob.setActionCommand(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.actionCommand")); // NOI18N bnPrioritizeJob.setActionCommand(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPrioritizeJob.actionCommand")); // NOI18N
bnPrioritizeJob.setMaximumSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.setMinimumSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnPrioritizeJob.addActionListener(new java.awt.event.ActionListener() { bnPrioritizeJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeJobActionPerformed(evt); bnPrioritizeJobActionPerformed(evt);
@ -1367,13 +1405,29 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
tbServicesStatusMessage.setBorder(null); tbServicesStatusMessage.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(bnOpenLogDir, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOpenLogDir.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnOpenLogDir, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOpenLogDir.text")); // NOI18N
bnOpenLogDir.setMaximumSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.setMinimumSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.setPreferredSize(new java.awt.Dimension(162, 23));
bnOpenLogDir.addActionListener(new java.awt.event.ActionListener() { bnOpenLogDir.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOpenLogDirActionPerformed(evt); bnOpenLogDirActionPerformed(evt);
} }
}); });
org.openide.awt.Mnemonics.setLocalizedText(bnClusterMetrics, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnClusterMetrics.text")); // NOI18N
bnClusterMetrics.setMaximumSize(new java.awt.Dimension(162, 23));
bnClusterMetrics.setMinimumSize(new java.awt.Dimension(162, 23));
bnClusterMetrics.setPreferredSize(new java.awt.Dimension(162, 23));
bnClusterMetrics.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnClusterMetricsActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnReprocessJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnReprocessJob.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnReprocessJob, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnReprocessJob.text")); // NOI18N
bnReprocessJob.setMaximumSize(new java.awt.Dimension(162, 23));
bnReprocessJob.setMinimumSize(new java.awt.Dimension(162, 23));
bnReprocessJob.setPreferredSize(new java.awt.Dimension(162, 23));
bnReprocessJob.addActionListener(new java.awt.event.ActionListener() { bnReprocessJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnReprocessJobActionPerformed(evt); bnReprocessJobActionPerformed(evt);
@ -1387,38 +1441,20 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(bnPause) .addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(bnOptions)
.addGap(18, 18, 18)
.addComponent(bnOpenLogDir)
.addGap(18, 18, 18)
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 116, Short.MAX_VALUE) .addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) .addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(lbStatus) .addComponent(lbStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
@ -1429,11 +1465,32 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addComponent(lbServicesStatus) .addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE))
.addContainerGap()) .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbPending)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnDeleteCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 1021, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
); );
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPause, bnRefresh, bnShowProgress}); layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnShowProgress});
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1453,48 +1510,47 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(82, 82, 82) .addGap(82, 82, 82)
.addComponent(bnPrioritizeCase) .addComponent(bnPrioritizeCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnPrioritizeJob))) .addComponent(bnPrioritizeJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbRunning) .addComponent(lbRunning)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(34, 34, 34) .addGap(34, 34, 34)
.addComponent(bnShowProgress) .addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnCancelJob) .addComponent(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnCancelModule)) .addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(68, 68, 68) .addGap(68, 68, 68)
.addComponent(bnReprocessJob) .addComponent(bnReprocessJob, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnDeleteCase) .addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnShowCaseLog)) .addComponent(bnShowCaseLog, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbCompleted) .addComponent(lbCompleted)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnExit) .addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnOpenLogDir)) .addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnPause) .addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnRefresh) .addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addComponent(bnOptions)))))
.addContainerGap()) .addContainerGap())
); );
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnRefresh, bnShowProgress}); layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnClusterMetrics, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPrioritizeCase, bnPrioritizeJob, bnRefresh, bnShowProgress});
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -1790,9 +1846,18 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor()); AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor());
}//GEN-LAST:event_bnReprocessJobActionPerformed }//GEN-LAST:event_bnReprocessJobActionPerformed
private void bnClusterMetricsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnClusterMetricsActionPerformed
try {
new AutoIngestMetricsDialog(this.getTopLevelAncestor());
} catch (AutoIngestMetricsDialog.AutoIngestMetricsDialogException ex) {
MessageNotifyUtil.Message.error(ex.getMessage());
}
}//GEN-LAST:event_bnClusterMetricsActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnCancelJob; private javax.swing.JButton bnCancelJob;
private javax.swing.JButton bnCancelModule; private javax.swing.JButton bnCancelModule;
private javax.swing.JButton bnClusterMetrics;
private javax.swing.JButton bnDeleteCase; private javax.swing.JButton bnDeleteCase;
private javax.swing.JButton bnExit; private javax.swing.JButton bnExit;
private javax.swing.JButton bnOpenLogDir; private javax.swing.JButton bnOpenLogDir;

View File

@ -873,7 +873,11 @@ final class AutoIngestDashboard extends JPanel implements Observer {
}//GEN-LAST:event_prioritizeCaseButtonActionPerformed }//GEN-LAST:event_prioritizeCaseButtonActionPerformed
private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed private void clusterMetricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clusterMetricsButtonActionPerformed
new AutoIngestMetricsDialog(this.getTopLevelAncestor(), autoIngestMonitor); try {
new AutoIngestMetricsDialog(this.getTopLevelAncestor());
} catch (AutoIngestMetricsDialog.AutoIngestMetricsDialogException ex) {
MessageNotifyUtil.Message.error(ex.getMessage());
}
}//GEN-LAST:event_clusterMetricsButtonActionPerformed }//GEN-LAST:event_clusterMetricsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables

View File

@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
@ThreadSafe @ThreadSafe
class DataSource { class AutoIngestDataSource {
private final String deviceId; private final String deviceId;
private final Path path; private final Path path;
@ -34,7 +34,7 @@ class DataSource {
private List<String> errorMessages; private List<String> errorMessages;
private List<Content> content; private List<Content> content;
DataSource(String deviceId, Path path) { AutoIngestDataSource(String deviceId, Path path) {
this.deviceId = deviceId; this.deviceId = deviceId;
this.path = path; this.path = path;
} }

View File

@ -64,6 +64,7 @@ import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails; import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
@ -78,7 +79,6 @@ import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException; import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException; import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException;
@ -113,7 +113,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleError;
* The activities of the auto ingest nodes in a cluster are coordinated by way * The activities of the auto ingest nodes in a cluster are coordinated by way
* of a coordination service and the nodes communicate via event messages. * of a coordination service and the nodes communicate via event messages.
*/ */
public final class AutoIngestManager extends Observable implements PropertyChangeListener { final class AutoIngestManager extends Observable implements PropertyChangeListener {
private static final int NUM_INPUT_SCAN_SCHEDULING_THREADS = 1; private static final int NUM_INPUT_SCAN_SCHEDULING_THREADS = 1;
private static final String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d"; private static final String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d";
@ -555,9 +555,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
++maxPriority; ++maxPriority;
for (AutoIngestJob job : prioritizedJobs) { for (AutoIngestJob job : prioritizedJobs) {
int oldPriority = job.getPriority(); int oldPriority = job.getPriority();
job.setPriority(maxPriority); job.setPriority(maxPriority);
try { try {
this.updateCoordinationServiceNode(job); this.updateCoordinationServiceManifestNode(job);
} catch (CoordinationServiceException | InterruptedException ex) { } catch (CoordinationServiceException | InterruptedException ex) {
job.setPriority(oldPriority); job.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating case priority", ex); throw new AutoIngestManagerException("Error updating case priority", ex);
@ -605,15 +605,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/* /*
* Bump the priority by one and update the coordination service node * Bump the priority by one and update the coordination service
* data for the job. * manifest node data for the job.
*/ */
if (null != prioritizedJob) { if (null != prioritizedJob) {
++maxPriority; ++maxPriority;
int oldPriority = prioritizedJob.getPriority(); int oldPriority = prioritizedJob.getPriority();
prioritizedJob.setPriority(maxPriority); prioritizedJob.setPriority(maxPriority);
try { try {
this.updateCoordinationServiceNode(prioritizedJob); this.updateCoordinationServiceManifestNode(prioritizedJob);
} catch (CoordinationServiceException | InterruptedException ex) { } catch (CoordinationServiceException | InterruptedException ex) {
prioritizedJob.setPriority(oldPriority); prioritizedJob.setPriority(oldPriority);
throw new AutoIngestManagerException("Error updating job priority", ex); throw new AutoIngestManagerException("Error updating job priority", ex);
@ -654,7 +654,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
/* /*
* Add the job to the pending jobs queue and update the coordination * Add the job to the pending jobs queue and update the coordination
* service node data for the job. * service manifest node data for the job.
*/ */
if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) { if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) {
try { try {
@ -666,7 +666,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
completedJob.setCompletedDate(new Date(0)); completedJob.setCompletedDate(new Date(0));
completedJob.setProcessingStatus(PENDING); completedJob.setProcessingStatus(PENDING);
completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now())); completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now()));
updateCoordinationServiceNode(completedJob); updateCoordinationServiceManifestNode(completedJob);
pendingJobs.add(completedJob); pendingJobs.add(completedJob);
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while reprocessing %s", manifestPath), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while reprocessing %s", manifestPath), ex);
@ -760,7 +760,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString())); AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
AutoIngestJob deletedJob = new AutoIngestJob(nodeData); AutoIngestJob deletedJob = new AutoIngestJob(nodeData);
deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED); deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED);
this.updateCoordinationServiceNode(deletedJob); this.updateCoordinationServiceManifestNode(deletedJob);
} catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) { } catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) {
SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex); SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex);
return CaseDeletionResult.PARTIALLY_DELETED; return CaseDeletionResult.PARTIALLY_DELETED;
@ -870,21 +870,37 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/** /**
* Sets the coordination service node data for an auto ingest job. * Sets the coordination service manifest node.
* *
* Note that a new auto ingest node data object will be created from the job * Note that a new auto ingest job node data object will be created from the
* passed in. Thus, if the data version of the node has changed, the node * job passed in. Thus, if the data version of the node has changed, the
* will be "upgraded" as well as updated. * node will be "upgraded" as well as updated.
* *
* @param job The auto ingest job. * @param job The auto ingest job.
*/ */
void updateCoordinationServiceNode(AutoIngestJob job) throws CoordinationServiceException, InterruptedException { void updateCoordinationServiceManifestNode(AutoIngestJob job) throws CoordinationServiceException, InterruptedException {
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(job); AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(job);
String manifestNodePath = job.getManifest().getFilePath().toString(); String manifestNodePath = job.getManifest().getFilePath().toString();
byte[] rawData = nodeData.toArray(); byte[] rawData = nodeData.toArray();
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, rawData); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, rawData);
} }
/**
* Sets the error flag for case node data given a case directory path.
*
* @param caseDirectoryPath The case directory path.
*
* @throws CoordinationService.CoordinationServiceException
* @throws InterruptedException
* @throws CaseNodeData.InvalidDataException
*/
private void setCaseNodeDataErrorsOccurred(Path caseDirectoryPath) throws CoordinationServiceException, InterruptedException, CaseNodeData.InvalidDataException {
CaseNodeData caseNodeData = new CaseNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString()));
caseNodeData.setErrorsOccurred(true);
byte[] rawData = caseNodeData.toArray();
coordinationService.setNodeData(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString(), rawData);
}
/** /**
* A task that submits an input directory scan task to the input directory * A task that submits an input directory scan task to the input directory
* scan task executor. * scan task executor.
@ -1152,8 +1168,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
/* /*
* Try to upgrade/update the coordination service node data for * Try to upgrade/update the coordination service manifest node
* the job. * data for the job.
* *
* An exclusive lock is obtained before doing so because another * An exclusive lock is obtained before doing so because another
* host may have already found the job, obtained an exclusive * host may have already found the job, obtained an exclusive
@ -1166,7 +1182,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) { if (null != manifestLock) {
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
@ -1191,9 +1207,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
private void addNewPendingJob(Manifest manifest) throws InterruptedException, AutoIngestJobException { private void addNewPendingJob(Manifest manifest) throws InterruptedException, AutoIngestJobException {
/* /*
* Create the coordination service node data for the job. Note that * Create the coordination service manifest node data for the job.
* getting the lock will create the node for the job (with no data) * Note that getting the lock will create the node for the job (with
* if it does not already exist. * no data) if it does not already exist.
* *
* An exclusive lock is obtained before creating the node data * An exclusive lock is obtained before creating the node data
* because another host may have already found the job, obtained an * because another host may have already found the job, obtained an
@ -1207,7 +1223,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) { if (null != manifestLock) {
AutoIngestJob job = new AutoIngestJob(manifest); AutoIngestJob job = new AutoIngestJob(manifest);
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
newPendingJobsList.add(job); newPendingJobsList.add(job);
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
@ -1223,15 +1239,17 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* the node that was processing the job crashed and the processing * the node that was processing the job crashed and the processing
* status was not updated. * status was not updated.
* *
* @param manifest The manifest for upgrading the node. * @param manifest The manifest for upgrading the node.
* @param nodeData The node data. * @param jobNodeData The auto ingest job node data.
* *
* @throws InterruptedException if the thread running the input * @throws InterruptedException if the thread running the input
* directory scan task is interrupted while * directory scan task is interrupted
* blocked, i.e., if auto ingest is * while blocked, i.e., if auto ingest is
* shutting down. * shutting down.
* @throws AutoIngestJobException if there is an issue creating a new
* AutoIngestJob object.
*/ */
private void doRecoveryIfCrashed(Manifest manifest, AutoIngestJobNodeData nodeData) throws InterruptedException, AutoIngestJobException { private void doRecoveryIfCrashed(Manifest manifest, AutoIngestJobNodeData jobNodeData) throws InterruptedException, AutoIngestJobException {
/* /*
* Try to get an exclusive lock on the coordination service node for * Try to get an exclusive lock on the coordination service node for
* the job. If the lock cannot be obtained, another host in the auto * the job. If the lock cannot be obtained, another host in the auto
@ -1243,11 +1261,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath); SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath);
try { try {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
/* /*
* Create the recovery job. * Create the recovery job.
*/ */
AutoIngestJob job = new AutoIngestJob(nodeData); AutoIngestJob job = new AutoIngestJob(jobNodeData);
int numberOfCrashes = job.getNumberOfCrashes(); int numberOfCrashes = job.getNumberOfCrashes();
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
++numberOfCrashes; ++numberOfCrashes;
@ -1263,17 +1281,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setCaseDirectoryPath(caseDirectoryPath); job.setCaseDirectoryPath(caseDirectoryPath);
job.setErrorsOccurred(true); job.setErrorsOccurred(true);
try { try {
/* setCaseNodeDataErrorsOccurred(caseDirectoryPath);
* Write the alert file and do the logging. } catch (CaseNodeData.InvalidDataException ex) {
*/ SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex);
AutoIngestAlertFile.create(caseDirectoryPath);
} catch (AutoIngestAlertFileException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error creating alert file for crashed job for %s", manifestPath), ex);
} }
} else { } else {
job.setErrorsOccurred(false); job.setErrorsOccurred(false);
} }
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
@ -1299,18 +1314,18 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* this fails, leave the recovery to another host. * this fails, leave the recovery to another host.
*/ */
try { try {
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex);
return; return;
} }
nodeData = new AutoIngestJobNodeData(job); jobNodeData = new AutoIngestJobNodeData(job);
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
newPendingJobsList.add(job); newPendingJobsList.add(job);
} else { } else {
newCompletedJobsList.add(new AutoIngestJob(nodeData)); newCompletedJobsList.add(new AutoIngestJob(jobNodeData));
} }
} finally { } finally {
@ -1366,15 +1381,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
/* /*
* Try to upgrade/update the coordination service node data * Try to upgrade/update the coordination service manifest
* for the job. It is possible that two hosts will both try * node data for the job. It is possible that two hosts will
* to obtain the lock to do the upgrade operation at the * both try to obtain the lock to do the upgrade operation
* same time. If this happens, the host that is holding the * at the same time. If this happens, the host that is
* lock will complete the upgrade operation. * holding the lock will complete the upgrade operation.
*/ */
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
if (null != manifestLock) { if (null != manifestLock) {
updateCoordinationServiceNode(job); updateCoordinationServiceManifestNode(job);
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex);
@ -1521,8 +1536,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
errorState = ErrorState.ANALYSIS_STARTUP_ERROR; errorState = ErrorState.ANALYSIS_STARTUP_ERROR;
} else if (ex instanceof FileExportException) { } else if (ex instanceof FileExportException) {
errorState = ErrorState.FILE_EXPORT_ERROR; errorState = ErrorState.FILE_EXPORT_ERROR;
} else if (ex instanceof AutoIngestAlertFileException) {
errorState = ErrorState.ALERT_FILE_ERROR;
} else if (ex instanceof AutoIngestJobLoggerException) { } else if (ex instanceof AutoIngestJobLoggerException) {
errorState = ErrorState.JOB_LOGGER_ERROR; errorState = ErrorState.JOB_LOGGER_ERROR;
} else if (ex instanceof AutoIngestDataSourceProcessorException) { } else if (ex instanceof AutoIngestDataSourceProcessorException) {
@ -1705,9 +1718,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an * @throws FileExportException if there is an
* error exporting * error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an
* error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an * @throws AutoIngestJobLoggerException if there is an
* error writing to * error writing to
* the auto ingest * the auto ingest
@ -1724,7 +1734,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node * auto ingest node
* data objects. * data objects.
*/ */
private void processJobs() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException { private void processJobs() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException, CaseNodeData.InvalidDataException {
SYS_LOGGER.log(Level.INFO, "Started processing pending jobs queue"); SYS_LOGGER.log(Level.INFO, "Started processing pending jobs queue");
Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob(); Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob();
while (null != manifestLock) { while (null != manifestLock) {
@ -1904,9 +1914,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws FileExportException if there is an * @throws FileExportException if there is an
* error exporting * error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an
* error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an * @throws AutoIngestJobLoggerException if there is an
* error writing to * error writing to
* the auto ingest * the auto ingest
@ -1923,13 +1930,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* auto ingest node * auto ingest node
* data objects. * data objects.
*/ */
private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeData.InvalidDataException { private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
Path manifestPath = currentJob.getManifest().getFilePath(); Path manifestPath = currentJob.getManifest().getFilePath();
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath); SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING); currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING);
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now())); currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now()));
currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME); currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME);
updateCoordinationServiceNode(currentJob); updateCoordinationServiceManifestNode(currentJob);
setChanged(); setChanged();
notifyObservers(Event.JOB_STARTED); notifyObservers(Event.JOB_STARTED);
eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob)); eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob));
@ -1953,14 +1960,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
} }
currentJob.setProcessingHostName(""); currentJob.setProcessingHostName("");
updateCoordinationServiceNode(currentJob); updateCoordinationServiceManifestNode(currentJob);
boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted()); boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted());
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry}); SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
if (currentJob.isCanceled()) { if (currentJob.isCanceled()) {
Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, currentJob.getManifest().getDataSourceFileName(), caseDirectoryPath);
jobLogger.logJobCancelled(); jobLogger.logJobCancelled();
} }
@ -2008,7 +2015,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* i.e., if auto ingest is * i.e., if auto ingest is
* shutting down. * shutting down.
*/ */
private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
updateConfiguration(); updateConfiguration();
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return; return;
@ -2173,8 +2180,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules. * level ingest modules.
* @throws FileExportException if there is an error exporting * @throws FileExportException if there is an error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2183,7 +2188,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void runIngestForJob(Case caseForJob) throws CoordinationServiceException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void runIngestForJob(Case caseForJob) throws CoordinationServiceException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException {
try { try {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return; return;
@ -2211,8 +2216,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* level ingest modules. * level ingest modules.
* @throws FileExportException if there is an error exporting * @throws FileExportException if there is an error exporting
* files. * files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2221,12 +2224,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void ingestDataSource(Case caseForJob) throws AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void ingestDataSource(Case caseForJob) throws AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
return; return;
} }
DataSource dataSource = identifyDataSource(); AutoIngestDataSource dataSource = identifyDataSource();
if (null == dataSource) { if (null == dataSource) {
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now())); currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now()));
return; return;
@ -2269,8 +2272,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @return A data source object. * @return A data source object.
* *
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2279,7 +2280,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* interrupted while blocked, i.e., * interrupted while blocked, i.e.,
* if auto ingest is shutting down. * if auto ingest is shutting down.
*/ */
private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private AutoIngestDataSource identifyDataSource() throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath);
@ -2291,22 +2292,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!dataSource.exists()) { if (!dataSource.exists()) {
SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath); SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logMissingDataSource(); jobLogger.logMissingDataSource();
return null; return null;
} }
String deviceId = manifest.getDeviceId(); String deviceId = manifest.getDeviceId();
return new DataSource(deviceId, dataSourcePath); return new AutoIngestDataSource(deviceId, dataSourcePath);
} }
/** /**
* Passes the data source for the current job through a data source * Passes the data source for the current job through a data source
* processor that adds it to the case database. * processor that adds it to the case database.
* *
* @param dataSource The data source. * @param dataSource The data source.
* *
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2315,23 +2314,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void runDataSourceProcessor(Case caseForJob, DataSource dataSource) throws InterruptedException, AutoIngestAlertFileException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { private void runDataSourceProcessor(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath); SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now())); currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now()));
UUID taskId = UUID.randomUUID();
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor(); DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
try { try {
caseForJob.notifyAddingDataSource(taskId);
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap; // Get an ordered list of data source processors to try
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
try { try {
// lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(dataSource.getPath());
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
SYS_LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath()); SYS_LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
// rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause.
@ -2339,24 +2335,22 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
// did we find a data source processor that can process the data source // did we find a data source processor that can process the data source
if (validDataSourceProcessorsMap.isEmpty()) { if (validDataSourceProcessors.isEmpty()) {
// This should never happen. We should add all unsupported data sources as logical files. // This should never happen. We should add all unsupported data sources as logical files.
AutoIngestAlertFile.create(caseDirectoryPath); setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
jobLogger.logFailedToIdentifyDataSource(); jobLogger.logFailedToIdentifyDataSource();
SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS
return; return;
} }
// Get an ordered list of data source processors to try
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
.sorted(Map.Entry.<AutoIngestDataSourceProcessor, Integer>comparingByValue().reversed())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
synchronized (ingestLock) { synchronized (ingestLock) {
// Try each DSP in decreasing order of confidence // Try each DSP in decreasing order of confidence
for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) { for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
UUID taskId = UUID.randomUUID();
caseForJob.notifyAddingDataSource(taskId);
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
caseForJob.notifyAddingDataSource(taskId);
jobLogger.logDataSourceProcessorSelected(selectedProcessor.getDataSourceType()); jobLogger.logDataSourceProcessorSelected(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()}); SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()});
try { try {
@ -2367,7 +2361,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
// Log that the current DSP failed and set the error flag. We consider it an error // Log that the current DSP failed and set the error flag. We consider it an error
// if a DSP fails even if a later one succeeds since we expected to be able to process // if a DSP fails even if a later one succeeds since we expected to be able to process
// the data source which each DSP on the list. // the data source which each DSP on the list.
AutoIngestAlertFile.create(caseDirectoryPath); setCaseNodeDataErrorsOccurred(caseDirectoryPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType()); jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()}); SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()});
@ -2391,8 +2385,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @param dataSource The data source. * @param dataSource The data source.
* *
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2401,7 +2393,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void logDataSourceProcessorResult(DataSource dataSource) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private void logDataSourceProcessorResult(AutoIngestDataSource dataSource) throws AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
@ -2413,7 +2405,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded(); jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) { if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent(); jobLogger.logNoDataSourceContent();
} }
break; break;
@ -2425,7 +2417,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceAdded(); jobLogger.logDataSourceAdded();
if (dataSource.getContent().isEmpty()) { if (dataSource.getContent().isEmpty()) {
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logNoDataSourceContent(); jobLogger.logNoDataSourceContent();
} }
break; break;
@ -2435,7 +2427,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage}); SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage});
} }
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFailedToAddDataSource(); jobLogger.logFailedToAddDataSource();
break; break;
} }
@ -2449,7 +2441,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath); SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logDataSourceProcessorCancelled(); jobLogger.logDataSourceProcessorCancelled();
} }
} }
@ -2463,8 +2455,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @throws AnalysisStartupException if there is an error analyzing * @throws AnalysisStartupException if there is an error analyzing
* the data source. * the data source.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2473,7 +2463,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void analyze(DataSource dataSource) throws AnalysisStartupException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private void analyze(AutoIngestDataSource dataSource) throws AnalysisStartupException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath); SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath);
@ -2505,7 +2495,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (!cancelledModules.isEmpty()) { if (!cancelledModules.isEmpty()) {
SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath)); SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath));
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
for (String module : snapshot.getCancelledDataSourceIngestModules()) { for (String module : snapshot.getCancelledDataSourceIngestModules()) {
SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath)); SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath));
jobLogger.logIngestModuleCancelled(module); jobLogger.logIngestModuleCancelled(module);
@ -2515,7 +2505,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} else { } else {
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now())); currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now()));
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisCancelled(); jobLogger.logAnalysisCancelled();
CancellationReason cancellationReason = snapshot.getCancellationReason(); CancellationReason cancellationReason = snapshot.getCancellationReason();
if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) { if (CancellationReason.NOT_CANCELLED != cancellationReason && CancellationReason.USER_CANCELLED != cancellationReason) {
@ -2528,13 +2518,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), manifestPath), error.getThrowable()); SYS_LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), manifestPath), error.getThrowable());
} }
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestModuleStartupErrors(); jobLogger.logIngestModuleStartupErrors();
throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath)); throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath));
} else { } else {
SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException()); SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException());
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logAnalysisStartupError(); jobLogger.logAnalysisStartupError();
throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException()); throw new AnalysisStartupException("Ingest manager error starting job", ingestJobStartResult.getStartupException());
} }
@ -2543,7 +2533,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{manifestPath, warning}); SYS_LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{manifestPath, warning});
} }
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logIngestJobSettingsErrors(); jobLogger.logIngestJobSettingsErrors();
throw new AnalysisStartupException("Error(s) in ingest job settings"); throw new AnalysisStartupException("Error(s) in ingest job settings");
} }
@ -2562,8 +2552,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* *
* @throws FileExportException if there is an error exporting * @throws FileExportException if there is an error exporting
* the files. * the files.
* @throws AutoIngestAlertFileException if there is an error creating an
* alert file.
* @throws AutoIngestJobLoggerException if there is an error writing to * @throws AutoIngestJobLoggerException if there is an error writing to
* the auto ingest log for the * the auto ingest log for the
* case. * case.
@ -2572,7 +2560,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* while blocked, i.e., if auto * while blocked, i.e., if auto
* ingest is shutting down. * ingest is shutting down.
*/ */
private void exportFiles(DataSource dataSource) throws FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { private void exportFiles(AutoIngestDataSource dataSource) throws FileExportException, AutoIngestJobLoggerException, InterruptedException, CaseNodeData.InvalidDataException, CoordinationServiceException {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
Path manifestPath = manifest.getFilePath(); Path manifestPath = manifest.getFilePath();
SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath); SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath);
@ -2588,11 +2576,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} catch (FileExportException ex) { } catch (FileExportException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex);
currentJob.setErrorsOccurred(true); currentJob.setErrorsOccurred(true);
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log setCaseNodeDataErrorsOccurred(caseDirectoryPath);
jobLogger.logFileExportError(); jobLogger.logFileExportError();
} }
} }
/** /**
* A data source processor progress monitor does nothing. There is * A data source processor progress monitor does nothing. There is
* currently no mechanism for showing or recording data source processor * currently no mechanism for showing or recording data source processor
@ -2754,7 +2742,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
currentJob.getProcessingStageDetails(); currentJob.getProcessingStageDetails();
setChanged(); setChanged();
notifyObservers(Event.JOB_STATUS_UPDATED); notifyObservers(Event.JOB_STATUS_UPDATED);
updateCoordinationServiceNode(currentJob); updateCoordinationServiceManifestNode(currentJob);
eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob)); eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob));
} }
@ -2857,7 +2845,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
CASE_MANAGEMENT_ERROR("Case management error"), CASE_MANAGEMENT_ERROR("Case management error"),
ANALYSIS_STARTUP_ERROR("Analysis startup error"), ANALYSIS_STARTUP_ERROR("Analysis startup error"),
FILE_EXPORT_ERROR("File export error"), FILE_EXPORT_ERROR("File export error"),
ALERT_FILE_ERROR("Alert file error"),
JOB_LOGGER_ERROR("Job logger error"), JOB_LOGGER_ERROR("Job logger error"),
DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"), DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"),
UNEXPECTED_EXCEPTION("Unknown error"); UNEXPECTED_EXCEPTION("Unknown error");
@ -2932,7 +2919,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
PARTIALLY_DELETED, PARTIALLY_DELETED,
FULLY_DELETED FULLY_DELETED
} }
static final class AutoIngestManagerException extends Exception { static final class AutoIngestManagerException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -2947,4 +2934,4 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
} }

View File

@ -0,0 +1,160 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Collects metrics for an auto ingest cluster.
*/
final class AutoIngestMetricsCollector {
private static final Logger LOGGER = Logger.getLogger(AutoIngestMetricsCollector.class.getName());
private CoordinationService coordinationService;
/**
* Creates an instance of the AutoIngestMetricsCollector.
*
* @throws AutoIngestMetricsCollector.AutoIngestMetricsCollectorException
*/
AutoIngestMetricsCollector() throws AutoIngestMetricsCollectorException {
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationServiceException ex) {
throw new AutoIngestMetricsCollectorException("Failed to get coordination service", ex); //NON-NLS
}
}
/**
* Gets a new metrics snapshot from the coordination service for an auto
* ingest cluster.
*
* @return The metrics snapshot.
*/
MetricsSnapshot queryCoordinationServiceForMetrics() {
try {
MetricsSnapshot newMetricsSnapshot = new MetricsSnapshot();
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS);
for (String node : nodeList) {
try {
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node));
if (nodeData.getVersion() < 1) {
/*
* Ignore version '0' nodes that have not been
* "upgraded" since they don't carry enough data.
*/
continue;
}
AutoIngestJob job = new AutoIngestJob(nodeData);
AutoIngestJob.ProcessingStatus processingStatus = nodeData.getProcessingStatus();
switch (processingStatus) {
case PENDING:
case PROCESSING:
case DELETED:
/*
* These are not jobs we care about for metrics, so
* we will ignore them.
*/
break;
case COMPLETED:
newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate());
break;
default:
LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus");
break;
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex);
} catch (AutoIngestJobNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex);
} catch (AutoIngestJob.AutoIngestJobException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
}
}
return newMetricsSnapshot;
} catch (CoordinationService.CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new MetricsSnapshot();
}
}
/**
* A snapshot of metrics for an auto ingest cluster.
*/
static final class MetricsSnapshot {
private final List<Long> completedJobDates = new ArrayList<>();
/**
* Gets a list of completed job dates, formatted in milliseconds.
*
* @return The completed job dates, formatted in milliseconds.
*/
List<Long> getCompletedJobDates() {
return new ArrayList<>(completedJobDates);
}
/**
* Adds a new date to the list of completed job dates.
*
* @param date The date to be added.
*/
void addCompletedJobDate(java.util.Date date) {
completedJobDates.add(date.getTime());
}
}
/**
* Exception type thrown when there is an error completing an auto ingest
* metrics collector operation.
*/
static final class AutoIngestMetricsCollectorException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest metrics collector operation.
*
* @param message The exception message.
*/
private AutoIngestMetricsCollectorException(String message) {
super(message);
}
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest metrics collector operation.
*
* @param message The exception message.
* @param cause A Throwable cause for the error.
*/
private AutoIngestMetricsCollectorException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@ -29,27 +29,30 @@ import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
/** /**
* Display basic metrics for a cluster. * Displays auto ingest metrics for a cluster.
*/ */
final class AutoIngestMetricsDialog extends javax.swing.JDialog { final class AutoIngestMetricsDialog extends javax.swing.JDialog {
private final AutoIngestMonitor autoIngestMonitor; private final AutoIngestMetricsCollector autoIngestMetricsCollector;
/** /**
* Creates new form AutoIngestMetricsDialog * Creates an instance of AutoIngestMetricsDialog
* *
* @param parent The parent container. * @param parent The parent container.
* @param autoIngestMonitor The auto ingest monitor.
*/ */
@Messages({ @Messages({
"AutoIngestMetricsDialog.title.text=Auto Ingest Cluster Metrics", "AutoIngestMetricsDialog.title.text=Auto Ingest Cluster Metrics",
"AutoIngestMetricsDialog.initReportText=Select a date below and click the 'Get Metrics Since...' button to generate\na metrics report." "AutoIngestMetricsDialog.initReportText=Select a date below and click the 'Get Metrics Since...' button to generate\na metrics report."
}) })
AutoIngestMetricsDialog(Container parent, AutoIngestMonitor autoIngestMonitor) { AutoIngestMetricsDialog(Container parent) throws AutoIngestMetricsDialogException {
super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS); super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS);
try {
autoIngestMetricsCollector = new AutoIngestMetricsCollector();
} catch (AutoIngestMetricsCollector.AutoIngestMetricsCollectorException ex) {
throw new AutoIngestMetricsDialogException("Error starting up the auto ingest metrics dialog.", ex);
}
initComponents(); initComponents();
reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText")); reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText"));
this.autoIngestMonitor = autoIngestMonitor;
setModal(true); setModal(true);
setSize(getPreferredSize()); setSize(getPreferredSize());
setLocationRelativeTo(parent); setLocationRelativeTo(parent);
@ -64,7 +67,7 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog {
return; return;
} }
AutoIngestMonitor.MetricsSnapshot metricsSnapshot = autoIngestMonitor.getMetricsSnapshot(); AutoIngestMetricsCollector.MetricsSnapshot metricsSnapshot = autoIngestMetricsCollector.queryCoordinationServiceForMetrics();
Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray(); Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray();
int count = 0; int count = 0;
long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000; long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
@ -82,6 +85,37 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog {
count count
)); ));
} }
/**
* Exception type thrown when there is an error completing an auto ingest
* metrics dialog operation.
*/
static final class AutoIngestMetricsDialogException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest metrics dialog operation.
*
* @param message The exception message.
*/
private AutoIngestMetricsDialogException(String message) {
super(message);
}
/**
* Constructs an instance of the exception type thrown when there is an
* error completing an auto ingest metrics dialog operation.
*
* @param message The exception message.
* @param cause A Throwable cause for the error.
*/
private AutoIngestMetricsDialogException(String message, Throwable cause) {
super(message, cause);
}
}
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
@ -175,4 +209,4 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog {
private javax.swing.JButton metricsButton; private javax.swing.JButton metricsButton;
private javax.swing.JTextArea reportTextArea; private javax.swing.JTextArea reportTextArea;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View File

@ -23,12 +23,10 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Observable; import java.util.Observable;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
@ -282,71 +280,6 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
} }
} }
/**
* Gets a new metrics snapshot from the coordination service for an auto
* ingest cluster.
*
* @return The metrics snapshot.
*/
private MetricsSnapshot queryCoordinationServiceForMetrics() {
try {
MetricsSnapshot newMetricsSnapshot = new MetricsSnapshot();
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS);
for (String node : nodeList) {
try {
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node));
if (nodeData.getVersion() < 1) {
/*
* Ignore version '0' nodes that have not been
* "upgraded" since they don't carry enough data.
*/
continue;
}
AutoIngestJob job = new AutoIngestJob(nodeData);
ProcessingStatus processingStatus = nodeData.getProcessingStatus();
switch (processingStatus) {
case PENDING:
case PROCESSING:
case DELETED:
/*
* These are not jobs we care about for metrics, so
* we will ignore them.
*/
break;
case COMPLETED:
newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate());
break;
default:
LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus");
break;
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, String.format("Unexpected interrupt while retrieving coordination service node data for '%s'", node), ex);
} catch (AutoIngestJobNodeData.InvalidDataException ex) {
LOGGER.log(Level.SEVERE, String.format("Unable to use node data for '%s'", node), ex);
} catch (AutoIngestJob.AutoIngestJobException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex);
}
}
return newMetricsSnapshot;
} catch (CoordinationServiceException ex) {
LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex);
return new MetricsSnapshot();
}
}
/**
* Gets a new metrics snapshot. The jobs snapshot will also be updated in
* effect.
*
* @return The metrics snapshot.
*/
public MetricsSnapshot getMetricsSnapshot() {
return queryCoordinationServiceForMetrics();
}
/** /**
* Bumps the priority of all pending ingest jobs for a specified case. * Bumps the priority of all pending ingest jobs for a specified case.
* *
@ -593,32 +526,6 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
} }
/**
* A snapshot of metrics for an auto ingest cluster.
*/
public static final class MetricsSnapshot {
private final List<Long> completedJobDates = new ArrayList<>();
/**
* Gets a list of completed job dates, formatted in milliseconds.
*
* @return The completed job dates, formatted in milliseconds.
*/
List<Long> getCompletedJobDates() {
return new ArrayList<>(completedJobDates);
}
/**
* Adds a new date to the list of completed job dates.
*
* @param date The date to be added.
*/
void addCompletedJobDate(Date date) {
completedJobDates.add(date.getTime());
}
}
/** /**
* Exception type thrown when there is an error completing an auto ingest * Exception type thrown when there is an error completing an auto ingest
* monitor operation. * monitor operation.
@ -649,4 +556,4 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
} }
} }
} }

View File

@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.experimental.autoingest;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
@ -30,8 +32,8 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.
* A utility class to find Data Source Processors * A utility class to find Data Source Processors
*/ */
class DataSourceProcessorUtility { class DataSourceProcessorUtility {
private DataSourceProcessorUtility() { private DataSourceProcessorUtility() {
} }
/** /**
@ -45,11 +47,7 @@ class DataSourceProcessorUtility {
* @throws * @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException * org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/ */
static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessor(Path dataSourcePath) throws AutoIngestDataSourceProcessorException { static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
// lookup all AutomatedIngestDataSourceProcessors
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = new HashMap<>(); Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = new HashMap<>();
for (AutoIngestDataSourceProcessor processor : processorCandidates) { for (AutoIngestDataSourceProcessor processor : processorCandidates) {
int confidence = processor.canProcess(dataSourcePath); int confidence = processor.canProcess(dataSourcePath);
@ -60,4 +58,64 @@ class DataSourceProcessorUtility {
return validDataSourceProcessorsMap; return validDataSourceProcessorsMap;
} }
/**
* A utility method to find all Data Source Processors (DSP) that are able
* to process the input data source. Only the DSPs that implement
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
* data source processors. DSPs are ordered in descending order from highest
* confidence to lowest.
*
* @param dataSourcePath Full path to the data source
*
* @return Ordered list of data source processors. DSPs are ordered in
* descending order from highest confidence to lowest.
*
* @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
// lookup all AutomatedIngestDataSourceProcessors
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
return getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
}
/**
* A utility method to find all Data Source Processors (DSP) that are able
* to process the input data source. Only the DSPs that implement
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
* data source processors. DSPs are ordered in descending order from highest
* confidence to lowest.
*
* @param dataSourcePath Full path to the data source
* @param processorCandidates Collection of AutoIngestDataSourceProcessor objects to use
*
* @return Ordered list of data source processors. DSPs are ordered in
* descending order from highest confidence to lowest.
*
* @throws
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
*/
static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, processorCandidates);
return orderDataSourceProcessorsByConfidence(validDataSourceProcessorsMap);
}
/**
* A utility method to get an ordered list of data source processors. DSPs
* are ordered in descending order from highest confidence to lowest.
*
* @param validDataSourceProcessorsMap Hash map of all DSPs that can process
* the data source along with their confidence score
* @return Ordered list of data source processors
*/
static List<AutoIngestDataSourceProcessor> orderDataSourceProcessorsByConfidence(Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap) {
List<AutoIngestDataSourceProcessor> validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
.sorted(Map.Entry.<AutoIngestDataSourceProcessor, Integer>comparingByValue().reversed())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
return validDataSourceProcessors;
}
} }

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.experimental.configuration; package org.sleuthkit.autopsy.experimental.configuration;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Cursor;
import java.io.File; import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.List; import java.util.List;
@ -513,7 +514,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
} }
private void displayIngestJobSettingsPanel() { private void displayIngestJobSettingsPanel() {
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString()); IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString());
showWarnings(ingestJobSettings); showWarnings(ingestJobSettings);
IngestJobSettingsPanel ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings); IngestJobSettingsPanel ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
@ -526,6 +528,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
ingestJobSettings.save(); ingestJobSettings.save();
showWarnings(ingestJobSettings); showWarnings(ingestJobSettings);
} }
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }
private static void showWarnings(IngestJobSettings ingestJobSettings) { private static void showWarnings(IngestJobSettings ingestJobSettings) {

View File

@ -205,7 +205,13 @@ class HighlightedText implements IndexedText {
*/ */
synchronized private void loadPageInfoFromHits() { synchronized private void loadPageInfoFromHits() {
isLiteral = hits.getQuery().isLiteral(); isLiteral = hits.getQuery().isLiteral();
//organize the hits by page, filter as needed
/**
* Organize the hits by page, filter as needed.
* We process *every* keyword here because in the case of a regular
* expression search there may be multiple different keyword
* hits located in different chunks for the same file/artifact.
*/
for (Keyword k : hits.getKeywords()) { for (Keyword k : hits.getKeywords()) {
for (KeywordHit hit : hits.getResults(k)) { for (KeywordHit hit : hits.getResults(k)) {
int chunkID = hit.getChunkId(); int chunkID = hit.getChunkId();

View File

@ -38,12 +38,9 @@ class KeywordHit implements Comparable<KeywordHit> {
private static final String GET_CONTENT_ID_FROM_ARTIFACT_ID = "SELECT obj_id FROM blackboard_artifacts WHERE artifact_id = "; private static final String GET_CONTENT_ID_FROM_ARTIFACT_ID = "SELECT obj_id FROM blackboard_artifacts WHERE artifact_id = ";
private final String solrDocumentId;
private final long solrObjectId; private final long solrObjectId;
private final int chunkId; private final int chunkId;
private final String snippet; private final String snippet;
private final long contentID;
private final boolean hitOnArtifact;
private final String hit; private final String hit;
/** /**
@ -56,14 +53,10 @@ class KeywordHit implements Comparable<KeywordHit> {
* For some searches (ie substring, regex) this will be * For some searches (ie substring, regex) this will be
* different than the search term. * different than the search term.
* *
* @throws TskCoreException If there is a problem getting the underlying
* content associated with a hit on the text of an
* artifact.
*/ */
KeywordHit(String solrDocumentId, String snippet, String hit) throws TskCoreException { KeywordHit(String solrDocumentId, String snippet, String hit) {
this.snippet = StringUtils.stripToEmpty(snippet); this.snippet = StringUtils.stripToEmpty(snippet);
this.hit = hit; this.hit = hit;
this.solrDocumentId = solrDocumentId;
/* /*
* Parse the Solr document id to get the Solr object id and chunk id. * Parse the Solr document id to get the Solr object id and chunk id.
@ -83,28 +76,6 @@ class KeywordHit implements Comparable<KeywordHit> {
this.solrObjectId = Long.parseLong(split[0]); this.solrObjectId = Long.parseLong(split[0]);
this.chunkId = Integer.parseInt(split[1]); this.chunkId = Integer.parseInt(split[1]);
} }
//artifacts have negative obj ids
hitOnArtifact = this.solrObjectId < 0;
if (hitOnArtifact) {
// If the hit was in an artifact, look up the source content for the artifact.
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
try (SleuthkitCase.CaseDbQuery executeQuery =
caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
ResultSet resultSet = executeQuery.getResultSet();) {
if (resultSet.next()) {
contentID = resultSet.getLong("obj_id");
} else {
throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
}
} catch (SQLException ex) {
throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
}
} else {
//else the object id is for content.
contentID = this.solrObjectId;
}
} }
String getHit() { String getHit() {
@ -112,7 +83,7 @@ class KeywordHit implements Comparable<KeywordHit> {
} }
String getSolrDocumentId() { String getSolrDocumentId() {
return this.solrDocumentId; return Long.toString(solrObjectId) + Server.CHUNK_ID_SEPARATOR + Long.toString(chunkId);
} }
long getSolrObjectId() { long getSolrObjectId() {
@ -131,8 +102,36 @@ class KeywordHit implements Comparable<KeywordHit> {
return this.snippet; return this.snippet;
} }
long getContentID() { /**
return this.contentID; * Get the content id associated with the content underlying hit.
* For hits on files this will be the same as the object id associated
* with the file. For hits on artifacts we look up the id of the object
* that produced the artifact.
*
* @return The id of the underlying content associated with the hit.
* @throws TskCoreException If there is a problem getting the underlying
* content associated with a hit on the text of an
* artifact.
*/
long getContentID() throws TskCoreException {
if (isArtifactHit()) {
// If the hit was in an artifact, look up the source content for the artifact.
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
try (SleuthkitCase.CaseDbQuery executeQuery =
caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
ResultSet resultSet = executeQuery.getResultSet();) {
if (resultSet.next()) {
return resultSet.getLong("obj_id");
} else {
throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
}
} catch (SQLException ex) {
throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
}
} else {
//else the object id is for content.
return this.solrObjectId;
}
} }
/** /**
@ -141,7 +140,8 @@ class KeywordHit implements Comparable<KeywordHit> {
* @return * @return
*/ */
boolean isArtifactHit() { boolean isArtifactHit() {
return hitOnArtifact; // artifacts have negative obj ids
return this.solrObjectId < 0;
} }
/** /**
@ -150,7 +150,7 @@ class KeywordHit implements Comparable<KeywordHit> {
* @return The artifact whose indexed text this hit is in. * @return The artifact whose indexed text this hit is in.
*/ */
Optional<Long> getArtifactID() { Optional<Long> getArtifactID() {
if (hitOnArtifact) { if (isArtifactHit()) {
return Optional.of(solrObjectId); return Optional.of(solrObjectId);
} else { } else {
return Optional.empty(); return Optional.empty();

View File

@ -226,6 +226,8 @@ final class RegexQuery implements KeywordSearchQuery {
private List<KeywordHit> createKeywordHits(SolrDocument solrDoc) throws TskCoreException { private List<KeywordHit> createKeywordHits(SolrDocument solrDoc) throws TskCoreException {
final HashMap<String, String> keywordsFoundInThisDocument = new HashMap<>();
List<KeywordHit> hits = new ArrayList<>(); List<KeywordHit> hits = new ArrayList<>();
final String docId = solrDoc.getFieldValue(Server.Schema.ID.toString()).toString(); final String docId = solrDoc.getFieldValue(Server.Schema.ID.toString()).toString();
final Integer chunkSize = (Integer) solrDoc.getFieldValue(Server.Schema.CHUNK_SIZE.toString()); final Integer chunkSize = (Integer) solrDoc.getFieldValue(Server.Schema.CHUNK_SIZE.toString());
@ -273,6 +275,23 @@ final class RegexQuery implements KeywordSearchQuery {
hit = hit.replaceAll("[^0-9]$", ""); hit = hit.replaceAll("[^0-9]$", "");
} }
/**
* The use of String interning is an optimization to ensure
* that we reuse the same keyword hit String object across
* all hits. Even though we benefit from G1GC String
* deduplication, the overhead associated with creating a
* new String object for every KeywordHit can be significant
* when the number of hits gets large.
*/
hit = hit.intern();
// We will only create one KeywordHit instance per document for
// a given hit.
if (keywordsFoundInThisDocument.containsKey(hit)) {
continue;
}
keywordsFoundInThisDocument.put(hit, hit);
if (artifactAttributeType == null) { if (artifactAttributeType == null) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit)); hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
} else { } else {
@ -303,7 +322,7 @@ final class RegexQuery implements KeywordSearchQuery {
final String group = ccnMatcher.group("ccn"); final String group = ccnMatcher.group("ccn");
if (CreditCardValidator.isValidCCN(group)) { if (CreditCardValidator.isValidCCN(group)) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit)); hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
}; }
} }
} }
@ -316,8 +335,6 @@ final class RegexQuery implements KeywordSearchQuery {
} }
} }
} catch (TskCoreException ex) {
throw ex;
} catch (Throwable error) { } catch (Throwable error) {
/* /*
* NOTE: Matcher.find() is known to throw StackOverflowError in rare * NOTE: Matcher.find() is known to throw StackOverflowError in rare
@ -463,7 +480,7 @@ final class RegexQuery implements KeywordSearchQuery {
if (hit.isArtifactHit()) { if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS
} else { } else {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getContentID())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getSolrObjectId())); //NON-NLS
} }
return null; return null;
} }

View File

@ -381,7 +381,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
if (hit.isArtifactHit()) { if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS
} else { } else {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContentID())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getSolrObjectId())); //NON-NLS
} }
return null; return null;
} }

View File

@ -1,3 +1,6 @@
CURRENTLY NOT WORKING for NETBEANS IDE 8.2,
NETBEANS BUG REPORT: https://netbeans.org/bugzilla/show_bug.cgi?id=271811
Common NetBeans IDE settings for the Autopsy project are stored here. Common NetBeans IDE settings for the Autopsy project are stored here.
All contributors are kindly asked to use these settings. All contributors are kindly asked to use these settings.
@ -7,11 +10,11 @@ Select Options to Import dialog. Push the Browse... button to pop up a file
chooser. Select ~\autopsy\developers\netbeans_ide_formatting_settings.zip. chooser. Select ~\autopsy\developers\netbeans_ide_formatting_settings.zip.
NetBeans IDE will require a restart for the settings to take effect. Formatting NetBeans IDE will require a restart for the settings to take effect. Formatting
can be done by selecting Source, Format (Alt + Shift + F). can be done by selecting Source, Format (Alt + Shift + F).
2. To make Java code hygiene hints (lint) settings, copy the entire contents of 2. To make Java code hygiene hints (lint) settings, select Tools,
~\autopsy\developers\netbeans_ide_java_hint_settings to the hint/default Options, Editor tab, Hints tab. Push the Import... button to pop up the
subdirectory of your user settings directory for the IDE. For Windows, this is Select Options to Import dialog. Push the Browse... button to pop up a file
~\AppData\Roaming\NetBeans\8.2\config\Preferences\org\netbeans\modules\java\hints chooser. Select ~\autopsy\developers\netbeans_ide_editor_settings.zip.
\default. Restart the IDE. NetBeans IDE will require a restart for the settings to take effect

Binary file not shown.

View File

@ -1,4 +0,0 @@
catch.common=true
catch.umbrella=false
catch.umbrella.types=java.io.IOException, java.sql.SqlException
enabled=true

Some files were not shown because too many files have changed in this diff Show More