mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 3198-TagPropertiesUpdate
This commit is contained in:
commit
273434f50f
@ -30,6 +30,7 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -40,7 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
final class MultiUserCaseManager {
|
||||
|
||||
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 CoordinationService coordinationService;
|
||||
|
||||
@ -82,19 +83,74 @@ final class MultiUserCaseManager {
|
||||
List<MultiUserCase> cases = new ArrayList<>();
|
||||
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
|
||||
for (String node : nodeList) {
|
||||
Path casePath = Paths.get(node);
|
||||
File caseFolder = casePath.toFile();
|
||||
if(caseFolder.exists()) {
|
||||
File[] autFiles = caseFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".aut"));
|
||||
if(autFiles != null && autFiles.length > 0) {
|
||||
try {
|
||||
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFiles[0].getAbsolutePath()));
|
||||
cases.add(new MultiUserCase(casePath, caseMetadata));
|
||||
} catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) {
|
||||
LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFiles[0].getAbsolutePath()), ex);
|
||||
Path casePath = Paths.get(node);
|
||||
File caseFolder = casePath.toFile();
|
||||
if (caseFolder.exists()) {
|
||||
/*
|
||||
* Search for '*.aut' and 'autoingest.alert' files.
|
||||
*/
|
||||
File[] fileArray = caseFolder.listFiles();
|
||||
if (fileArray == null) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -112,7 +168,7 @@ final class MultiUserCaseManager {
|
||||
*/
|
||||
Case.openAsCurrentCase(caseMetadataFilePath.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exception type thrown when there is an error completing a multi-user case
|
||||
* manager operation.
|
||||
@ -143,7 +199,7 @@ final class MultiUserCaseManager {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A representation of a multi-user case.
|
||||
*/
|
||||
@ -154,21 +210,22 @@ final class MultiUserCaseManager {
|
||||
private final String metadataFileName;
|
||||
private final Date createDate;
|
||||
private final Date lastAccessedDate;
|
||||
private CaseStatus status;
|
||||
|
||||
/**
|
||||
* Constructs a representation of a multi-user case
|
||||
*
|
||||
* @param caseDirectoryPath The case directory path.
|
||||
* @param caseMetadata The case metadata.
|
||||
*
|
||||
* @throws MultiUserCaseException If no case metadata (.aut)
|
||||
* file is found in the case
|
||||
* directory.
|
||||
* @param caseMetadata The case metadata.
|
||||
*
|
||||
* @throws MultiUserCaseException If no case metadata (.aut) file is
|
||||
* found in the case directory.
|
||||
*/
|
||||
MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata) throws MultiUserCaseException {
|
||||
MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata, CaseStatus status) throws MultiUserCaseException {
|
||||
this.caseDirectoryPath = caseDirectoryPath;
|
||||
caseDisplayName = caseMetadata.getCaseDisplayName();
|
||||
metadataFileName = caseMetadata.getFilePath().getFileName().toString();
|
||||
this.status = status;
|
||||
BasicFileAttributes fileAttrs = null;
|
||||
try {
|
||||
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
|
||||
* directory or metadata file names if a case has been renamed.
|
||||
* Gets the case display name. This may differ from the name supplied to
|
||||
* the directory or metadata file names if a case has been renamed.
|
||||
*
|
||||
* @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
|
||||
* case metadata file.
|
||||
* Gets the creation date for the case, defined as the create time of
|
||||
* the case metadata file.
|
||||
*
|
||||
* @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
|
||||
* time of the case metadata file.
|
||||
* Gets the last accessed date for the case, defined as the last
|
||||
* accessed time of the case metadata file.
|
||||
*
|
||||
* @return The last accessed date.
|
||||
*/
|
||||
@ -225,7 +282,7 @@ final class MultiUserCaseManager {
|
||||
|
||||
/**
|
||||
* Gets metadata (.aut) file name.
|
||||
*
|
||||
*
|
||||
* @return The metadata file name.
|
||||
*/
|
||||
String getMetadataFileName() {
|
||||
@ -233,17 +290,12 @@ final class MultiUserCaseManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of this case based on the auto ingest result file in the
|
||||
* case directory.
|
||||
* Gets the status of this case.
|
||||
*
|
||||
* @return See CaseStatus enum definition.
|
||||
*/
|
||||
CaseStatus getStatus() {
|
||||
if(caseDirectoryPath.resolve("autoingest.alert").toFile().exists()) {
|
||||
return CaseStatus.ALERT;
|
||||
} else {
|
||||
return CaseStatus.OK;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,7 +304,7 @@ final class MultiUserCaseManager {
|
||||
* @param caseDirectoryPath The case directory path.
|
||||
*
|
||||
* @return Case metadata.
|
||||
*
|
||||
*
|
||||
* @throws CaseMetadata.CaseMetadataException If the CaseMetadata object
|
||||
* cannot be constructed.
|
||||
* @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()));
|
||||
}
|
||||
|
||||
@ -334,14 +386,15 @@ final class MultiUserCaseManager {
|
||||
static class LastAccessedDateDescendingComparator implements Comparator<MultiUserCase> {
|
||||
|
||||
/**
|
||||
* Compares two MultiUserCase objects for order based on last accessed
|
||||
* date (descending).
|
||||
* Compares two MultiUserCase objects for order based on last
|
||||
* accessed date (descending).
|
||||
*
|
||||
* @param object The first MultiUserCase object
|
||||
* @param otherObject The second MultiUserCase object.
|
||||
*
|
||||
* @return A negative integer, zero, or a positive integer as the first
|
||||
* argument is less than, equal to, or greater than the second.
|
||||
* @return A negative integer, zero, or a positive integer as the
|
||||
* first argument is less than, equal to, or greater than
|
||||
* the second.
|
||||
*/
|
||||
@Override
|
||||
public int compare(MultiUserCase object, MultiUserCase otherObject) {
|
||||
@ -357,8 +410,8 @@ final class MultiUserCaseManager {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs an exception to throw when there is a problem creating a
|
||||
* multi-user case.
|
||||
* Constructs an exception to throw when there is a problem creating
|
||||
* a multi-user case.
|
||||
*
|
||||
* @param message The exception message.
|
||||
*/
|
||||
@ -367,11 +420,12 @@ final class MultiUserCaseManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception to throw when there is a problem creating a
|
||||
* multi-user case.
|
||||
* Constructs an exception to throw when there is a problem creating
|
||||
* a multi-user case.
|
||||
*
|
||||
* @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) {
|
||||
super(message, cause);
|
||||
|
141
Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java
Executable file
141
Core/src/org/sleuthkit/autopsy/coordinationservice/CaseNodeData.java
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
/**
|
||||
* Additional functionality of viewers supporting black board results such as
|
||||
* the directory tree
|
||||
*
|
||||
*@deprecated No longer used.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface BlackboardResultViewer {
|
||||
|
||||
public static final String FINISHED_DISPLAY_EVT = "FINISHED_DISPLAY_EVT"; //NON-NLS
|
||||
|
@ -43,9 +43,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
* or less means the data source is not supported by the
|
||||
* DataSourceProcessor. Value of 100 indicates high certainty in
|
||||
* being able to process the data source.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
|
||||
* @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException;
|
||||
|
||||
@ -65,9 +63,7 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
* background task to report progress.
|
||||
* @param callBack Callback that will be used by the background task
|
||||
* to return results.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor.AutomatedIngestDataSourceProcessorException
|
||||
* @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException;
|
||||
|
||||
|
@ -59,8 +59,6 @@ DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
|
||||
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=Open File Search by Attributes
|
||||
DirectoryTreeFilterNode.action.runIngestMods.text=Run Ingest Modules
|
||||
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
|
||||
ExplorerNodeActionVisitor.action.imgDetails.title=Image Details
|
||||
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=Extract Unallocated Space to Single Files
|
||||
|
@ -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.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.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.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
|
||||
@ -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.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
|
||||
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}
|
||||
|
@ -27,7 +27,6 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -56,13 +55,11 @@ import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ArtifactNodeSelectionInfo;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.CreditCards;
|
||||
@ -99,7 +96,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
@Messages({
|
||||
"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 static DirectoryTreeTopComponent instance;
|
||||
@ -851,7 +848,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viewArtifact(final BlackboardArtifact art) {
|
||||
int typeID = art.getArtifactTypeID();
|
||||
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
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viewArtifactContent(BlackboardArtifact art) {
|
||||
new ViewContextAction(
|
||||
NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.action.viewArtContent.text"),
|
||||
new BlackboardArtifactNode(art)).actionPerformed(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnFinishedListener(PropertyChangeListener 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[750, 500]"/>
|
||||
<Dimension value="[701, 453]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
@ -32,19 +32,24 @@
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<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>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" 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"/>
|
||||
</Group>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" 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"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -55,7 +60,7 @@
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace 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 type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
@ -81,13 +86,18 @@
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="350"/>
|
||||
<Property name="dividerLocation" type="int" value="365"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<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>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
@ -103,7 +113,7 @@
|
||||
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="159" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="47" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -114,7 +124,7 @@
|
||||
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace 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>
|
||||
</DimensionLayout>
|
||||
@ -137,6 +147,11 @@
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<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>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
@ -149,42 +164,35 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" 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="ruleListLabel" max="32767" attributes="0"/>
|
||||
<Component id="rulesScrollPane" min="-2" pref="345" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="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"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="rulesScrollPane" pref="380" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="rulesScrollPane" pref="328" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" 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="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -224,6 +232,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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>
|
||||
<Events>
|
||||
<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">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</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>
|
||||
<Events>
|
||||
<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">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</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>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/>
|
||||
|
@ -93,13 +93,17 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
editRuleButton = 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
|
||||
|
||||
jSplitPane1.setDividerLocation(350);
|
||||
jSplitPane1.setDividerLocation(365);
|
||||
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(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)
|
||||
.addComponent(exePathLabel)
|
||||
.addComponent(exePathNameLabel))
|
||||
.addContainerGap(159, Short.MAX_VALUE))
|
||||
.addContainerGap(47, Short.MAX_VALUE))
|
||||
);
|
||||
exePanelLayout.setVerticalGroup(
|
||||
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -122,17 +126,22 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addComponent(exePathLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(exePathNameLabel)
|
||||
.addContainerGap(408, Short.MAX_VALUE))
|
||||
.addContainerGap(361, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
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
|
||||
|
||||
rulesScrollPane.setViewportView(rulesList);
|
||||
|
||||
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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
deleteRuleButtonActionPerformed(evt);
|
||||
@ -162,20 +177,16 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 311, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addComponent(newRuleButton)
|
||||
.addComponent(ruleListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, rulesPanelLayout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.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)
|
||||
.addComponent(deleteRuleButton)
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
.addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
rulesPanelLayout.setVerticalGroup(
|
||||
rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -183,12 +194,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addContainerGap()
|
||||
.addComponent(ruleListLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(newRuleButton)
|
||||
.addComponent(editRuleButton)
|
||||
.addComponent(deleteRuleButton))
|
||||
.addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -202,12 +213,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE)
|
||||
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 681, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane1)
|
||||
.addContainerGap()))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
@ -215,7 +226,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(externalViewerTitleLabel)
|
||||
.addContainerGap(475, Short.MAX_VALUE))
|
||||
.addContainerGap(428, Short.MAX_VALUE))
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(32, 32, 32)
|
||||
|
@ -21,14 +21,11 @@ package org.sleuthkit.autopsy.ingest;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import javax.swing.text.html.StyleSheet;
|
||||
import org.openide.util.Lookup;
|
||||
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.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -40,7 +37,8 @@ import org.sleuthkit.datamodel.TskException;
|
||||
*/
|
||||
class IngestMessageDetailsPanel extends javax.swing.JPanel {
|
||||
|
||||
private IngestMessageMainPanel mainPanel;
|
||||
private final IngestMessageMainPanel mainPanel;
|
||||
private final DirectoryTreeTopComponent dtc = DirectoryTreeTopComponent.findInstance();
|
||||
|
||||
/**
|
||||
* 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("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
|
||||
messageDetailsPane.setComponentPopupMenu(rightClickMenu);
|
||||
ActionListener actList = new ActionListener() {
|
||||
@ -193,11 +179,27 @@ class IngestMessageDetailsPanel extends javax.swing.JPanel {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
// 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
|
||||
*
|
||||
|
@ -1,6 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<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>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -16,12 +21,12 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="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>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<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>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -29,7 +34,7 @@
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[687, 450]"/>
|
||||
<Dimension value="[718, 430]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
@ -37,36 +42,45 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="797" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="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"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<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"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="430"/>
|
||||
<Property name="dividerLocation" type="int" value="365"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<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>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
@ -76,23 +90,26 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="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"/>
|
||||
<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="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">
|
||||
<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"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="191" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -101,14 +118,14 @@
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="427" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="348" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" 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"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -142,6 +159,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTypeButtonActionPerformed"/>
|
||||
@ -166,6 +192,11 @@
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<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>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
@ -198,16 +229,16 @@
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" 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"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane3" pref="427" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane3" pref="348" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="removeExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -221,6 +252,12 @@
|
||||
<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, "{key}")"/>
|
||||
</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>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newExtButtonActionPerformed"/>
|
||||
|
@ -154,11 +154,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
removeExtButton = new javax.swing.JButton();
|
||||
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);
|
||||
|
||||
mimePanel.setPreferredSize(new java.awt.Dimension(369, 424));
|
||||
mimePanel.setRequestFocusEnabled(false);
|
||||
|
||||
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N
|
||||
|
||||
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.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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
newTypeButtonActionPerformed(evt);
|
||||
@ -188,16 +198,18 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addGroup(mimePanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel1)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 349, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(mimePanelLayout.createSequentialGroup()
|
||||
.addComponent(newTypeButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(newTypeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(removeTypeButton)))
|
||||
.addGap(0, 191, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
);
|
||||
mimePanelLayout.setVerticalGroup(
|
||||
mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -205,18 +217,22 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel1)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.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))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
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.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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
newExtButtonActionPerformed(evt);
|
||||
@ -248,7 +264,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(extHeaderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 324, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.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)
|
||||
.addComponent(removeExtButton)))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
@ -260,10 +276,10 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addContainerGap()
|
||||
.addComponent(extHeaderLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.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))
|
||||
.addContainerGap())
|
||||
);
|
||||
@ -277,27 +293,27 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 797, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(jScrollPane1)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(jScrollPane1)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
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.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
|
||||
|
||||
|
@ -18,22 +18,34 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.openide.util.Lookup;
|
||||
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 static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
|
||||
/*
|
||||
* A runnable that adds an archive data source as well as data sources
|
||||
* contained in the archive to the case database.
|
||||
* A runnable that adds an archive data source as well as data sources contained
|
||||
* in the archive to the case database.
|
||||
*/
|
||||
class AddArchiveTask implements Runnable {
|
||||
|
||||
@ -43,6 +55,7 @@ class AddArchiveTask implements Runnable {
|
||||
private final DataSourceProcessorProgressMonitor progressMonitor;
|
||||
private final DataSourceProcessorCallback callback;
|
||||
private boolean criticalErrorOccurred;
|
||||
private final Object archiveDspLock;
|
||||
|
||||
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
|
||||
* contained in the archive to the case database.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device associated
|
||||
* with the data source that is intended to be unique across multiple cases
|
||||
* (e.g., a UUID).
|
||||
* @param archivePath Path to the archive file.
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is intended
|
||||
* to be unique across multiple cases (e.g., a UUID).
|
||||
* @param archivePath Path to the archive file.
|
||||
* @param progressMonitor Progress monitor to report progress during
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
*/
|
||||
AddArchiveTask(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
this.deviceId = deviceId;
|
||||
this.archivePath = archivePath;
|
||||
this.callback = callback;
|
||||
this.progressMonitor = progressMonitor;
|
||||
this.archiveDspLock = new Object();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,39 +84,172 @@ class AddArchiveTask implements Runnable {
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
progressMonitor.setIndeterminate(true);
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
List<Content> newDataSources = new ArrayList<>();
|
||||
DataSourceProcessorCallback.DataSourceProcessorResult result;
|
||||
if (!ArchiveUtil.isArchive(Paths.get(archivePath))) {
|
||||
criticalErrorOccurred = true;
|
||||
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;
|
||||
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
|
||||
Path destinationFolder = Paths.get("");
|
||||
try {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
|
||||
// get file name without full path or extension
|
||||
String dataSourceFileNameNoExt = FilenameUtils.getBaseName(archivePath);
|
||||
|
||||
// create folder to extract archive to
|
||||
destinationFolder = Paths.get(currentCase.getModuleDirectory(), ARCHIVE_EXTRACTOR_MODULE_OUTPUT_DIR, dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp());
|
||||
destinationFolder.toFile().mkdirs();
|
||||
Path destinationFolder = createDirectoryForFile(archivePath, currentCase.getModuleDirectory());
|
||||
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
|
||||
//ArchiveUtil.unpackArchiveFile(archivePath, destinationFolder.toString());
|
||||
// extract contents of ZIP archive into destination folder
|
||||
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
|
||||
|
||||
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) {
|
||||
criticalErrorOccurred = true;
|
||||
errorMessages.add(ex.getMessage());
|
||||
logger.log(Level.SEVERE, String.format("Critical error occurred while extracting archive %s", archivePath), ex); //NON-NLS
|
||||
} finally {
|
||||
logger.log(Level.INFO, "Finished processing of archive {0}", archivePath);
|
||||
progressMonitor.setProgress(100);
|
||||
if (criticalErrorOccurred) {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import org.sleuthkit.datamodel.Content;
|
||||
class AddDataSourceCallback extends DataSourceProcessorCallback {
|
||||
|
||||
private final Case caseForJob;
|
||||
private final DataSource dataSourceInfo;
|
||||
private final AutoIngestDataSource dataSourceInfo;
|
||||
private final UUID taskId;
|
||||
private final Object lock;
|
||||
|
||||
@ -48,7 +48,7 @@ class AddDataSourceCallback extends DataSourceProcessorCallback {
|
||||
* @param dataSourceInfo The data source
|
||||
* @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.dataSourceInfo = dataSourceInfo;
|
||||
this.taskId = taskId;
|
||||
|
@ -18,13 +18,15 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.util.lookup.ServiceProviders;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
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
|
||||
* be used independently of the wizard.
|
||||
*/
|
||||
//@ServiceProviders(value={
|
||||
// @ServiceProvider(service=DataSourceProcessor.class),
|
||||
// @ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
|
||||
//)
|
||||
@ServiceProviders(value={
|
||||
@ServiceProvider(service=AutoIngestDataSourceProcessor.class)}
|
||||
)
|
||||
@NbBundle.Messages({
|
||||
"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();
|
||||
|
||||
@ -50,6 +51,8 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
|
||||
private String archivePath;
|
||||
private boolean setDataSourceOptionsCalled;
|
||||
|
||||
private final ExecutorService jobProcessingExecutor;
|
||||
private static final String ARCHIVE_DSP_THREAD_NAME = "Archive-DSP-%d";
|
||||
private AddArchiveTask addArchiveTask;
|
||||
|
||||
/**
|
||||
@ -60,6 +63,7 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
|
||||
*/
|
||||
public ArchiveExtractorDSProcessor() {
|
||||
configPanel = ArchiveFilePanel.createInstance(ArchiveExtractorDSProcessor.class.getName(), ArchiveUtil.getArchiveFilters());
|
||||
jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(ARCHIVE_DSP_THREAD_NAME).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -151,21 +155,15 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
|
||||
*/
|
||||
public void run(String deviceId, String archivePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback 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
|
||||
* the case database, after the task is started using the run method. This
|
||||
* is a "best effort" cancellation, with no guarantees that the case
|
||||
* database will be unchanged. If cancellation succeeded, the list of new
|
||||
* data sources returned by the background task will be empty.
|
||||
* This DSP is a service to AutoIngestDataSourceProcessor only. Hence it is
|
||||
* only used by AIM. AIM currently doesn't support DSP cancellation.
|
||||
*/
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (null != addArchiveTask) {
|
||||
addArchiveTask.cancelTask();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -175,50 +173,4 @@ public class ArchiveExtractorDSProcessor implements DataSourceProcessor, AutoIng
|
||||
configPanel.reset();
|
||||
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;
|
||||
} */
|
||||
}
|
||||
|
@ -214,10 +214,11 @@ final class ArchiveUtil {
|
||||
* @param destinationFolder Path to directory where results will be
|
||||
* extracted to.
|
||||
*
|
||||
* @return List of file names contained within archive
|
||||
* @throws
|
||||
* 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)) {
|
||||
try {
|
||||
SevenZip.initSevenZipFromPlatformJAR();
|
||||
@ -225,6 +226,7 @@ final class ArchiveUtil {
|
||||
throw new ArchiveExtractionException("Unable to initialize 7Zip libraries", ex);
|
||||
}
|
||||
}
|
||||
List<String> files = new ArrayList<>();
|
||||
ISevenZipInArchive inArchive = null;
|
||||
try {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
@ -17,46 +17,22 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" 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="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="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="bnPause" linkSize="1" 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>
|
||||
<Component id="bnPause" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="bnCancelJob" linkSize="1" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnShowProgress" linkSize="1" pref="116" max="32767" attributes="0"/>
|
||||
<Component id="bnCancelModule" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnDeleteCase" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnShowCaseLog" max="32767" attributes="0"/>
|
||||
<Component id="bnReprocessJob" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="bnRefresh" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="bnOptions" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="bnOpenLogDir" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="bnClusterMetrics" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="bnExit" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbStatus" min="-2" max="-2" attributes="0"/>
|
||||
@ -73,8 +49,36 @@
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</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>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -99,9 +103,9 @@
|
||||
</Group>
|
||||
<Group type="102" alignment="0" 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"/>
|
||||
<Component id="bnPrioritizeJob" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnPrioritizeJob" linkSize="2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -135,16 +139,13 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="completedScrollPane" min="-2" pref="179" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="bnExit" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnOpenLogDir" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="bnPause" 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 type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="bnPause" 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"/>
|
||||
<Component id="bnOpenLogDir" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnClusterMetrics" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnExit" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -169,6 +170,7 @@
|
||||
<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, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="autoResizeMode" type="int" value="4"/>
|
||||
<Property name="rowHeight" type="int" value="20" postCode="pendingTable.setSelectionModel(new DefaultListSelectionModel() {
 private static final long serialVersionUID = 1L;
 @Override
 public void setSelectionInterval(int index0, int index1) {
 if (index0 == pendingTable.getSelectedRow()) {
 pendingTable.clearSelection();
 } else {
 super.setSelectionInterval(index0, index1);
 }
 }
});"/>
|
||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||
<JTableSelectionModel selectionMode="0"/>
|
||||
@ -192,6 +194,7 @@
|
||||
<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, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="autoResizeMode" type="int" value="4"/>
|
||||
<Property name="rowHeight" type="int" value="20" postCode="runningTable.setSelectionModel(new DefaultListSelectionModel() {
 private static final long serialVersionUID = 1L;
 @Override
 public void setSelectionInterval(int index0, int index1) {
 if (index0 == runningTable.getSelectedRow()) {
 runningTable.clearSelection();
 } else {
 super.setSelectionInterval(index0, index1);
 }
 }
});"/>
|
||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||
<JTableSelectionModel selectionMode="0"/>
|
||||
@ -215,6 +218,7 @@
|
||||
<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, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="autoResizeMode" type="int" value="4"/>
|
||||
<Property name="rowHeight" type="int" value="20" postCode="completedTable.setSelectionModel(new DefaultListSelectionModel() {
 private static final long serialVersionUID = 1L;
 @Override
 public void setSelectionInterval(int index0, int index1) {
 if (index0 == completedTable.getSelectedRow()) {
 completedTable.clearSelection();
 } else {
 super.setSelectionInterval(index0, index1);
 }
 }
});"/>
|
||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||
<JTableSelectionModel selectionMode="0"/>
|
||||
@ -231,6 +235,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnCancelJobActionPerformed"/>
|
||||
@ -244,6 +257,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnDeleteCaseActionPerformed"/>
|
||||
@ -287,6 +309,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnRefreshActionPerformed"/>
|
||||
@ -300,6 +331,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnCancelModuleActionPerformed"/>
|
||||
@ -313,6 +353,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="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, "{key}")"/>
|
||||
</Property>
|
||||
<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>
|
||||
<Events>
|
||||
<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">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestControlPanel.bnShowProgress.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</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="bnShowProgressActionPerformed"/>
|
||||
@ -353,6 +420,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnPauseActionPerformed"/>
|
||||
@ -366,6 +442,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnPrioritizeCaseActionPerformed"/>
|
||||
@ -379,6 +464,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnShowCaseLogActionPerformed"/>
|
||||
@ -419,6 +513,15 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnPrioritizeJobActionPerformed"/>
|
||||
@ -453,20 +556,57 @@
|
||||
<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, "{key}")"/>
|
||||
</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="bnOpenLogDirActionPerformed"/>
|
||||
</Events>
|
||||
</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, "{key}")"/>
|
||||
</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">
|
||||
<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.bnReprocessJob.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</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="bnReprocessJobActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
</Form>
|
@ -73,6 +73,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
|
||||
* one such panel per node.
|
||||
*/
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.bnClusterMetrics.text=Cluster Metrics",
|
||||
"AutoIngestControlPanel.bnPause.text=Pause",
|
||||
"AutoIngestControlPanel.bnPause.paused=Paused",
|
||||
"AutoIngestControlPanel.bnPause.running=Running",
|
||||
@ -116,7 +117,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
|
||||
"AutoIngestControlPanel.bnPrioritizeJob.actionCommand=<AutoIngestControlPanel.bnPrioritizeJob.text>",
|
||||
"AutoIngestControlPanel.lbServicesStatus.text=Services Status:",
|
||||
"AutoIngestControlPanel.tbServicesStatusMessage.text=",
|
||||
"AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Directory",
|
||||
"AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Folder",
|
||||
"AutoIngestControlPanel.bnReprocessJob.text=Reprocess Job",
|
||||
"AutoIngestControlPanel.bnPrioritizeFolder.label=<AutoIngestControlPanel.bnPrioritizeJob.text>",
|
||||
"AutoIngestControlPanel.Cancelling=Cancelling...",
|
||||
@ -1198,10 +1199,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
lbServicesStatus = new javax.swing.JLabel();
|
||||
tbServicesStatusMessage = new javax.swing.JTextField();
|
||||
bnOpenLogDir = new javax.swing.JButton();
|
||||
bnClusterMetrics = new javax.swing.JButton();
|
||||
bnReprocessJob = new javax.swing.JButton();
|
||||
|
||||
pendingTable.setModel(pendingTableModel);
|
||||
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.setSelectionModel(new DefaultListSelectionModel() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -1219,6 +1222,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
|
||||
runningTable.setModel(runningTableModel);
|
||||
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.setSelectionModel(new DefaultListSelectionModel() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -1236,6 +1240,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
|
||||
completedTable.setModel(completedTableModel);
|
||||
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.setSelectionModel(new DefaultListSelectionModel() {
|
||||
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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
bnOptions.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnOptions.toolTipText")); // NOI18N
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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.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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnPrioritizeJobActionPerformed(evt);
|
||||
@ -1367,13 +1405,29 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
tbServicesStatusMessage.setBorder(null);
|
||||
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent 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
|
||||
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() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnReprocessJobActionPerformed(evt);
|
||||
@ -1387,38 +1441,20 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(bnPause)
|
||||
.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))
|
||||
.addComponent(bnPause, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 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.PREFERRED_SIZE, 117, Short.MAX_VALUE)
|
||||
.addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 116, Short.MAX_VALUE)
|
||||
.addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE)
|
||||
.addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_SIZE, 117, 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)))
|
||||
.addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.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()
|
||||
.addComponent(lbStatus)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
@ -1429,11 +1465,32 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
.addComponent(lbServicesStatus)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.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.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))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.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)
|
||||
.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)
|
||||
.addComponent(lbRunning)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.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)
|
||||
.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)
|
||||
.addComponent(bnCancelModule))
|
||||
.addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.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)
|
||||
.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)
|
||||
.addComponent(bnShowCaseLog))
|
||||
.addComponent(bnShowCaseLog, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbCompleted)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(bnExit)
|
||||
.addComponent(bnOpenLogDir))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(bnPause)
|
||||
.addComponent(bnRefresh)
|
||||
.addComponent(bnOptions)))))
|
||||
.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(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bnOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bnOpenLogDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bnClusterMetrics, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
|
||||
.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
|
||||
|
||||
@ -1790,9 +1846,18 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor());
|
||||
}//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
|
||||
private javax.swing.JButton bnCancelJob;
|
||||
private javax.swing.JButton bnCancelModule;
|
||||
private javax.swing.JButton bnClusterMetrics;
|
||||
private javax.swing.JButton bnDeleteCase;
|
||||
private javax.swing.JButton bnExit;
|
||||
private javax.swing.JButton bnOpenLogDir;
|
||||
|
@ -873,7 +873,11 @@ final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
}//GEN-LAST:event_prioritizeCaseButtonActionPerformed
|
||||
|
||||
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
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
|
@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
|
||||
@ThreadSafe
|
||||
class DataSource {
|
||||
class AutoIngestDataSource {
|
||||
|
||||
private final String deviceId;
|
||||
private final Path path;
|
||||
@ -34,7 +34,7 @@ class DataSource {
|
||||
private List<String> errorMessages;
|
||||
private List<Content> content;
|
||||
|
||||
DataSource(String deviceId, Path path) {
|
||||
AutoIngestDataSource(String deviceId, Path path) {
|
||||
this.deviceId = deviceId;
|
||||
this.path = path;
|
||||
}
|
@ -64,6 +64,7 @@ import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseDetails;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
||||
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.AutopsyEventException;
|
||||
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.FileExporter.FileExportException;
|
||||
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
|
||||
* 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 String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d";
|
||||
@ -555,9 +555,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
++maxPriority;
|
||||
for (AutoIngestJob job : prioritizedJobs) {
|
||||
int oldPriority = job.getPriority();
|
||||
job.setPriority(maxPriority);
|
||||
job.setPriority(maxPriority);
|
||||
try {
|
||||
this.updateCoordinationServiceNode(job);
|
||||
this.updateCoordinationServiceManifestNode(job);
|
||||
} catch (CoordinationServiceException | InterruptedException ex) {
|
||||
job.setPriority(oldPriority);
|
||||
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
|
||||
* data for the job.
|
||||
* Bump the priority by one and update the coordination service
|
||||
* manifest node data for the job.
|
||||
*/
|
||||
if (null != prioritizedJob) {
|
||||
++maxPriority;
|
||||
int oldPriority = prioritizedJob.getPriority();
|
||||
prioritizedJob.setPriority(maxPriority);
|
||||
try {
|
||||
this.updateCoordinationServiceNode(prioritizedJob);
|
||||
this.updateCoordinationServiceManifestNode(prioritizedJob);
|
||||
} catch (CoordinationServiceException | InterruptedException ex) {
|
||||
prioritizedJob.setPriority(oldPriority);
|
||||
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
|
||||
* service node data for the job.
|
||||
* service manifest node data for the job.
|
||||
*/
|
||||
if (null != completedJob && !completedJob.getCaseDirectoryPath().toString().isEmpty()) {
|
||||
try {
|
||||
@ -666,7 +666,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
completedJob.setCompletedDate(new Date(0));
|
||||
completedJob.setProcessingStatus(PENDING);
|
||||
completedJob.setProcessingStage(AutoIngestJob.Stage.PENDING, Date.from(Instant.now()));
|
||||
updateCoordinationServiceNode(completedJob);
|
||||
updateCoordinationServiceManifestNode(completedJob);
|
||||
pendingJobs.add(completedJob);
|
||||
} catch (CoordinationServiceException 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()));
|
||||
AutoIngestJob deletedJob = new AutoIngestJob(nodeData);
|
||||
deletedJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.DELETED);
|
||||
this.updateCoordinationServiceNode(deletedJob);
|
||||
this.updateCoordinationServiceManifestNode(deletedJob);
|
||||
} catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Invalid auto ingest job node data for %s", manifestPath), ex);
|
||||
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
|
||||
* passed in. Thus, if the data version of the node has changed, the node
|
||||
* will be "upgraded" as well as updated.
|
||||
* Note that a new auto ingest job node data object will be created from the
|
||||
* job passed in. Thus, if the data version of the node has changed, the
|
||||
* node will be "upgraded" as well as updated.
|
||||
*
|
||||
* @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);
|
||||
String manifestNodePath = job.getManifest().getFilePath().toString();
|
||||
byte[] rawData = nodeData.toArray();
|
||||
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
|
||||
* 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
|
||||
* the job.
|
||||
* Try to upgrade/update the coordination service manifest node
|
||||
* data for the job.
|
||||
*
|
||||
* An exclusive lock is obtained before doing so because another
|
||||
* 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())) {
|
||||
if (null != manifestLock) {
|
||||
updateCoordinationServiceNode(job);
|
||||
updateCoordinationServiceManifestNode(job);
|
||||
}
|
||||
} catch (CoordinationServiceException 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 {
|
||||
/*
|
||||
* Create the coordination service node data for the job. Note that
|
||||
* getting the lock will create the node for the job (with no data)
|
||||
* if it does not already exist.
|
||||
* Create the coordination service manifest node data for the job.
|
||||
* Note that getting the lock will create the node for the job (with
|
||||
* no data) if it does not already exist.
|
||||
*
|
||||
* An exclusive lock is obtained before creating the node data
|
||||
* 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())) {
|
||||
if (null != manifestLock) {
|
||||
AutoIngestJob job = new AutoIngestJob(manifest);
|
||||
updateCoordinationServiceNode(job);
|
||||
updateCoordinationServiceManifestNode(job);
|
||||
newPendingJobsList.add(job);
|
||||
}
|
||||
} 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
|
||||
* status was not updated.
|
||||
*
|
||||
* @param manifest The manifest for upgrading the node.
|
||||
* @param nodeData The node data.
|
||||
* @param manifest The manifest for upgrading the node.
|
||||
* @param jobNodeData The auto ingest job node data.
|
||||
*
|
||||
* @throws InterruptedException if the thread running the input
|
||||
* directory scan task is interrupted while
|
||||
* blocked, i.e., if auto ingest is
|
||||
* shutting down.
|
||||
* @throws InterruptedException if the thread running the input
|
||||
* directory scan task is interrupted
|
||||
* while blocked, i.e., if auto ingest is
|
||||
* 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
|
||||
* 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);
|
||||
try {
|
||||
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName());
|
||||
|
||||
|
||||
/*
|
||||
* Create the recovery job.
|
||||
*/
|
||||
AutoIngestJob job = new AutoIngestJob(nodeData);
|
||||
AutoIngestJob job = new AutoIngestJob(jobNodeData);
|
||||
int numberOfCrashes = job.getNumberOfCrashes();
|
||||
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
|
||||
++numberOfCrashes;
|
||||
@ -1263,17 +1281,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
job.setCaseDirectoryPath(caseDirectoryPath);
|
||||
job.setErrorsOccurred(true);
|
||||
try {
|
||||
/*
|
||||
* Write the alert file and do the logging.
|
||||
*/
|
||||
AutoIngestAlertFile.create(caseDirectoryPath);
|
||||
} catch (AutoIngestAlertFileException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Error creating alert file for crashed job for %s", manifestPath), ex);
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
} catch (CaseNodeData.InvalidDataException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex);
|
||||
}
|
||||
} else {
|
||||
job.setErrorsOccurred(false);
|
||||
}
|
||||
|
||||
|
||||
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
|
||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
|
||||
if (null != caseDirectoryPath) {
|
||||
@ -1299,18 +1314,18 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* this fails, leave the recovery to another host.
|
||||
*/
|
||||
try {
|
||||
updateCoordinationServiceNode(job);
|
||||
updateCoordinationServiceManifestNode(job);
|
||||
} catch (CoordinationServiceException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex);
|
||||
return;
|
||||
}
|
||||
|
||||
nodeData = new AutoIngestJobNodeData(job);
|
||||
|
||||
|
||||
jobNodeData = new AutoIngestJobNodeData(job);
|
||||
|
||||
if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) {
|
||||
newPendingJobsList.add(job);
|
||||
} else {
|
||||
newCompletedJobsList.add(new AutoIngestJob(nodeData));
|
||||
newCompletedJobsList.add(new AutoIngestJob(jobNodeData));
|
||||
}
|
||||
|
||||
} finally {
|
||||
@ -1366,15 +1381,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED);
|
||||
|
||||
/*
|
||||
* Try to upgrade/update the coordination service node data
|
||||
* for the job. It is possible that two hosts will both try
|
||||
* to obtain the lock to do the upgrade operation at the
|
||||
* same time. If this happens, the host that is holding the
|
||||
* lock will complete the upgrade operation.
|
||||
* Try to upgrade/update the coordination service manifest
|
||||
* node data for the job. It is possible that two hosts will
|
||||
* both try to obtain the lock to do the upgrade operation
|
||||
* at the same time. If this happens, the host that is
|
||||
* holding the lock will complete the upgrade operation.
|
||||
*/
|
||||
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
|
||||
if (null != manifestLock) {
|
||||
updateCoordinationServiceNode(job);
|
||||
updateCoordinationServiceManifestNode(job);
|
||||
}
|
||||
} catch (CoordinationServiceException 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;
|
||||
} else if (ex instanceof FileExportException) {
|
||||
errorState = ErrorState.FILE_EXPORT_ERROR;
|
||||
} else if (ex instanceof AutoIngestAlertFileException) {
|
||||
errorState = ErrorState.ALERT_FILE_ERROR;
|
||||
} else if (ex instanceof AutoIngestJobLoggerException) {
|
||||
errorState = ErrorState.JOB_LOGGER_ERROR;
|
||||
} else if (ex instanceof AutoIngestDataSourceProcessorException) {
|
||||
@ -1705,9 +1718,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* @throws FileExportException if there is an
|
||||
* error exporting
|
||||
* files.
|
||||
* @throws AutoIngestAlertFileException if there is an
|
||||
* error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an
|
||||
* error writing to
|
||||
* the auto ingest
|
||||
@ -1724,7 +1734,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* auto ingest node
|
||||
* 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");
|
||||
Lock manifestLock = JobProcessingTask.this.dequeueAndLockNextJob();
|
||||
while (null != manifestLock) {
|
||||
@ -1904,9 +1914,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* @throws FileExportException if there is an
|
||||
* error exporting
|
||||
* files.
|
||||
* @throws AutoIngestAlertFileException if there is an
|
||||
* error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an
|
||||
* error writing to
|
||||
* the auto ingest
|
||||
@ -1923,13 +1930,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* auto ingest node
|
||||
* 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();
|
||||
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
|
||||
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PROCESSING);
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.STARTING, Date.from(Instant.now()));
|
||||
currentJob.setProcessingHostName(AutoIngestManager.LOCAL_HOST_NAME);
|
||||
updateCoordinationServiceNode(currentJob);
|
||||
updateCoordinationServiceManifestNode(currentJob);
|
||||
setChanged();
|
||||
notifyObservers(Event.JOB_STARTED);
|
||||
eventPublisher.publishRemotely(new AutoIngestJobStartedEvent(currentJob));
|
||||
@ -1953,14 +1960,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
currentJob.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING);
|
||||
}
|
||||
currentJob.setProcessingHostName("");
|
||||
updateCoordinationServiceNode(currentJob);
|
||||
updateCoordinationServiceManifestNode(currentJob);
|
||||
|
||||
boolean retry = (!currentJob.isCanceled() && !currentJob.isCompleted());
|
||||
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
|
||||
if (currentJob.isCanceled()) {
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
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);
|
||||
jobLogger.logJobCancelled();
|
||||
}
|
||||
@ -2008,7 +2015,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* i.e., if auto ingest is
|
||||
* 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();
|
||||
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
|
||||
return;
|
||||
@ -2173,8 +2180,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* level ingest modules.
|
||||
* @throws FileExportException if there is an error exporting
|
||||
* files.
|
||||
* @throws AutoIngestAlertFileException if there is an error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing to
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2183,7 +2188,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* while blocked, i.e., if auto
|
||||
* 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 {
|
||||
if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) {
|
||||
return;
|
||||
@ -2211,8 +2216,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* level ingest modules.
|
||||
* @throws FileExportException if there is an error exporting
|
||||
* files.
|
||||
* @throws AutoIngestAlertFileException if there is an error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing to
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2221,12 +2224,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* while blocked, i.e., if auto
|
||||
* 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()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DataSource dataSource = identifyDataSource();
|
||||
AutoIngestDataSource dataSource = identifyDataSource();
|
||||
if (null == dataSource) {
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now()));
|
||||
return;
|
||||
@ -2269,8 +2272,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
*
|
||||
* @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
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2279,7 +2280,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* interrupted while blocked, i.e.,
|
||||
* 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();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
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()) {
|
||||
SYS_LOGGER.log(Level.SEVERE, "Missing data source for {0}", manifestPath);
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logMissingDataSource();
|
||||
return null;
|
||||
}
|
||||
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
|
||||
* processor that adds it to the case database.
|
||||
*
|
||||
* @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
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2315,23 +2314,20 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* while blocked, i.e., if auto
|
||||
* 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();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
|
||||
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();
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath);
|
||||
try {
|
||||
caseForJob.notifyAddingDataSource(taskId);
|
||||
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap;
|
||||
// Get an ordered list of data source processors to try
|
||||
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
|
||||
try {
|
||||
// lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source
|
||||
validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(dataSource.getPath());
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
|
||||
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
|
||||
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.
|
||||
@ -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
|
||||
if (validDataSourceProcessorsMap.isEmpty()) {
|
||||
if (validDataSourceProcessors.isEmpty()) {
|
||||
// This should never happen. We should add all unsupported data sources as logical files.
|
||||
AutoIngestAlertFile.create(caseDirectoryPath);
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
currentJob.setErrorsOccurred(true);
|
||||
jobLogger.logFailedToIdentifyDataSource();
|
||||
SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS
|
||||
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) {
|
||||
// Try each DSP in decreasing order of confidence
|
||||
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());
|
||||
SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()});
|
||||
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
|
||||
// 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.
|
||||
AutoIngestAlertFile.create(caseDirectoryPath);
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
currentJob.setErrorsOccurred(true);
|
||||
jobLogger.logDataSourceProcessorError(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.
|
||||
*
|
||||
* @throws AutoIngestAlertFileException if there is an error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing to
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2401,7 +2393,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* while blocked, i.e., if auto
|
||||
* 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();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
@ -2413,7 +2405,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
jobLogger.logDataSourceAdded();
|
||||
if (dataSource.getContent().isEmpty()) {
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logNoDataSourceContent();
|
||||
}
|
||||
break;
|
||||
@ -2425,7 +2417,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
jobLogger.logDataSourceAdded();
|
||||
if (dataSource.getContent().isEmpty()) {
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logNoDataSourceContent();
|
||||
}
|
||||
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});
|
||||
}
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logFailedToAddDataSource();
|
||||
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);
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logDataSourceProcessorCancelled();
|
||||
}
|
||||
}
|
||||
@ -2463,8 +2455,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
*
|
||||
* @throws AnalysisStartupException if there is an error analyzing
|
||||
* the data source.
|
||||
* @throws AutoIngestAlertFileException if there is an error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing to
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2473,7 +2463,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* while blocked, i.e., if auto
|
||||
* 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();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
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()) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", manifestPath));
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
for (String module : snapshot.getCancelledDataSourceIngestModules()) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, manifestPath));
|
||||
jobLogger.logIngestModuleCancelled(module);
|
||||
@ -2515,7 +2505,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
} else {
|
||||
currentJob.setProcessingStage(AutoIngestJob.Stage.CANCELLING, Date.from(Instant.now()));
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logAnalysisCancelled();
|
||||
CancellationReason cancellationReason = snapshot.getCancellationReason();
|
||||
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());
|
||||
}
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logIngestModuleStartupErrors();
|
||||
throw new AnalysisStartupException(String.format("Error(s) during ingest module startup for %s", manifestPath));
|
||||
} else {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", manifestPath), ingestJobStartResult.getStartupException());
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logAnalysisStartupError();
|
||||
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});
|
||||
}
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logIngestJobSettingsErrors();
|
||||
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
|
||||
* the files.
|
||||
* @throws AutoIngestAlertFileException if there is an error creating an
|
||||
* alert file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing to
|
||||
* the auto ingest log for the
|
||||
* case.
|
||||
@ -2572,7 +2560,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* while blocked, i.e., if auto
|
||||
* 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();
|
||||
Path manifestPath = manifest.getFilePath();
|
||||
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) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Error doing file export for %s", manifestPath), ex);
|
||||
currentJob.setErrorsOccurred(true);
|
||||
AutoIngestAlertFile.create(caseDirectoryPath); // Do this first, it is more important than the case log
|
||||
setCaseNodeDataErrorsOccurred(caseDirectoryPath);
|
||||
jobLogger.logFileExportError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A data source processor progress monitor does nothing. There is
|
||||
* currently no mechanism for showing or recording data source processor
|
||||
@ -2754,7 +2742,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
currentJob.getProcessingStageDetails();
|
||||
setChanged();
|
||||
notifyObservers(Event.JOB_STATUS_UPDATED);
|
||||
updateCoordinationServiceNode(currentJob);
|
||||
updateCoordinationServiceManifestNode(currentJob);
|
||||
eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob));
|
||||
}
|
||||
|
||||
@ -2857,7 +2845,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
CASE_MANAGEMENT_ERROR("Case management error"),
|
||||
ANALYSIS_STARTUP_ERROR("Analysis startup error"),
|
||||
FILE_EXPORT_ERROR("File export error"),
|
||||
ALERT_FILE_ERROR("Alert file error"),
|
||||
JOB_LOGGER_ERROR("Job logger error"),
|
||||
DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"),
|
||||
UNEXPECTED_EXCEPTION("Unknown error");
|
||||
@ -2932,7 +2919,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
PARTIALLY_DELETED,
|
||||
FULLY_DELETED
|
||||
}
|
||||
|
||||
|
||||
static final class AutoIngestManagerException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -2947,4 +2934,4 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -29,27 +29,30 @@ import org.openide.util.NbBundle;
|
||||
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 {
|
||||
|
||||
private final AutoIngestMonitor autoIngestMonitor;
|
||||
private final AutoIngestMetricsCollector autoIngestMetricsCollector;
|
||||
|
||||
/**
|
||||
* Creates new form AutoIngestMetricsDialog
|
||||
* Creates an instance of AutoIngestMetricsDialog
|
||||
*
|
||||
* @param parent The parent container.
|
||||
* @param autoIngestMonitor The auto ingest monitor.
|
||||
*/
|
||||
@Messages({
|
||||
"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(Container parent, AutoIngestMonitor autoIngestMonitor) {
|
||||
AutoIngestMetricsDialog(Container parent) throws AutoIngestMetricsDialogException {
|
||||
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();
|
||||
reportTextArea.setText(NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.initReportText"));
|
||||
this.autoIngestMonitor = autoIngestMonitor;
|
||||
setModal(true);
|
||||
setSize(getPreferredSize());
|
||||
setLocationRelativeTo(parent);
|
||||
@ -64,7 +67,7 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoIngestMonitor.MetricsSnapshot metricsSnapshot = autoIngestMonitor.getMetricsSnapshot();
|
||||
AutoIngestMetricsCollector.MetricsSnapshot metricsSnapshot = autoIngestMetricsCollector.queryCoordinationServiceForMetrics();
|
||||
Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray();
|
||||
int count = 0;
|
||||
long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
|
||||
@ -82,6 +85,37 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog {
|
||||
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.
|
||||
@ -175,4 +209,4 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog {
|
||||
private javax.swing.JButton metricsButton;
|
||||
private javax.swing.JTextArea reportTextArea;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
}
|
@ -23,12 +23,10 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
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.
|
||||
*
|
||||
@ -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
|
||||
* monitor operation.
|
||||
@ -649,4 +556,4 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
||||
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
|
||||
*/
|
||||
class DataSourceProcessorUtility {
|
||||
|
||||
private DataSourceProcessorUtility() {
|
||||
|
||||
private DataSourceProcessorUtility() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,11 +47,7 @@ class DataSourceProcessorUtility {
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessor(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
|
||||
|
||||
// lookup all AutomatedIngestDataSourceProcessors
|
||||
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
|
||||
|
||||
static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = new HashMap<>();
|
||||
for (AutoIngestDataSourceProcessor processor : processorCandidates) {
|
||||
int confidence = processor.canProcess(dataSourcePath);
|
||||
@ -60,4 +58,64 @@ class DataSourceProcessorUtility {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.experimental.configuration;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Cursor;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
@ -513,7 +514,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
private void displayIngestJobSettingsPanel() {
|
||||
|
||||
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
|
||||
IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString());
|
||||
showWarnings(ingestJobSettings);
|
||||
IngestJobSettingsPanel ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
|
||||
@ -526,6 +528,8 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
||||
ingestJobSettings.save();
|
||||
showWarnings(ingestJobSettings);
|
||||
}
|
||||
|
||||
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
|
||||
private static void showWarnings(IngestJobSettings ingestJobSettings) {
|
||||
|
@ -205,7 +205,13 @@ class HighlightedText implements IndexedText {
|
||||
*/
|
||||
synchronized private void loadPageInfoFromHits() {
|
||||
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 (KeywordHit hit : hits.getResults(k)) {
|
||||
int chunkID = hit.getChunkId();
|
||||
|
@ -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 final String solrDocumentId;
|
||||
private final long solrObjectId;
|
||||
private final int chunkId;
|
||||
private final String snippet;
|
||||
private final long contentID;
|
||||
private final boolean hitOnArtifact;
|
||||
private final String hit;
|
||||
|
||||
/**
|
||||
@ -56,14 +53,10 @@ class KeywordHit implements Comparable<KeywordHit> {
|
||||
* For some searches (ie substring, regex) this will be
|
||||
* 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.hit = hit;
|
||||
this.solrDocumentId = solrDocumentId;
|
||||
|
||||
/*
|
||||
* 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.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() {
|
||||
@ -112,7 +83,7 @@ class KeywordHit implements Comparable<KeywordHit> {
|
||||
}
|
||||
|
||||
String getSolrDocumentId() {
|
||||
return this.solrDocumentId;
|
||||
return Long.toString(solrObjectId) + Server.CHUNK_ID_SEPARATOR + Long.toString(chunkId);
|
||||
}
|
||||
|
||||
long getSolrObjectId() {
|
||||
@ -131,8 +102,36 @@ class KeywordHit implements Comparable<KeywordHit> {
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
Optional<Long> getArtifactID() {
|
||||
if (hitOnArtifact) {
|
||||
if (isArtifactHit()) {
|
||||
return Optional.of(solrObjectId);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
@ -226,6 +226,8 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
|
||||
private List<KeywordHit> createKeywordHits(SolrDocument solrDoc) throws TskCoreException {
|
||||
|
||||
final HashMap<String, String> keywordsFoundInThisDocument = new HashMap<>();
|
||||
|
||||
List<KeywordHit> hits = new ArrayList<>();
|
||||
final String docId = solrDoc.getFieldValue(Server.Schema.ID.toString()).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]$", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
|
||||
} else {
|
||||
@ -303,7 +322,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
final String group = ccnMatcher.group("ccn");
|
||||
if (CreditCardValidator.isValidCCN(group)) {
|
||||
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) {
|
||||
/*
|
||||
* NOTE: Matcher.find() is known to throw StackOverflowError in rare
|
||||
@ -463,7 +480,7 @@ final class RegexQuery implements KeywordSearchQuery {
|
||||
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
|
||||
} 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;
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
|
||||
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
|
||||
} 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;
|
||||
}
|
||||
|
@ -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.
|
||||
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.
|
||||
NetBeans IDE will require a restart for the settings to take effect. Formatting
|
||||
can be done by selecting Source, Format (Alt + Shift + F).
|
||||
2. To make Java code hygiene hints (lint) settings, copy the entire contents of
|
||||
~\autopsy\developers\netbeans_ide_java_hint_settings to the hint/default
|
||||
subdirectory of your user settings directory for the IDE. For Windows, this is
|
||||
~\AppData\Roaming\NetBeans\8.2\config\Preferences\org\netbeans\modules\java\hints
|
||||
\default. Restart the IDE.
|
||||
2. To make Java code hygiene hints (lint) settings, select Tools,
|
||||
Options, Editor tab, Hints tab. Push the Import... button to pop up the
|
||||
Select Options to Import dialog. Push the Browse... button to pop up a file
|
||||
chooser. Select ~\autopsy\developers\netbeans_ide_editor_settings.zip.
|
||||
NetBeans IDE will require a restart for the settings to take effect
|
||||
|
||||
|
||||
|
||||
|
BIN
developers/netbeans_ide_java_editor_settings.zip
Executable file
BIN
developers/netbeans_ide_java_editor_settings.zip
Executable file
Binary file not shown.
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=false
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1,2 +0,0 @@
|
||||
enabled=true
|
||||
groups=x, width|y, height
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1,4 +0,0 @@
|
||||
catch.common=true
|
||||
catch.umbrella=false
|
||||
catch.umbrella.types=java.io.IOException, java.sql.SqlException
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
@ -1 +0,0 @@
|
||||
enabled=true
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user