From 8d75a118135cb060a9043151714f2e64e29ce957 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 27 May 2021 15:05:18 -0400 Subject: [PATCH 01/16] First cut --- .../autoingest/AutoIngestAdminActions.java | 48 ++++++++++ .../autoingest/AutoIngestJobNodeData.java | 39 +++++++- .../autoingest/AutoIngestJobsNode.java | 3 + .../autoingest/AutoIngestManager.java | 31 +++++- .../autoingest/AutoIngestMonitor.java | 48 +++++++++- .../autoingest/AutoIngestOcrEnabledEvent.java | 95 +++++++++++++++++++ .../autoingest/PrioritizationAction.java | 2 +- 7 files changed, 260 insertions(+), 6 deletions(-) create mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java index a881a96fb2..994d2f91a0 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java @@ -157,6 +157,54 @@ final class AutoIngestAdminActions { } } } + + @NbBundle.Messages({"AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case", + "AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case \"%s\"."}) + static final class EnableOCR extends AbstractAction { + + private static final long serialVersionUID = 1L; + private final AutoIngestJob job; + + EnableOCR(AutoIngestJob job) { + super(Bundle.AutoIngestAdminActions_enableOCR_title()); + this.job = job; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (job == null) { + return; + } + + final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); + if (tc == null) { + return; + } + + AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); + if (dashboard != null) { + dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + EventQueue.invokeLater(() -> { + try { + dashboard.getMonitor().enableOcrForCase(job.getManifest().getCaseName()); + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); // ELTODO + } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { + String errorMessage = String.format(Bundle.AutoIngestAdminActions_enableOCR_error(), job.getManifest().getCaseName()); + logger.log(Level.SEVERE, errorMessage, ex); + MessageNotifyUtil.Message.error(errorMessage); + } finally { + dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor()); + } + }); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } @NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"}) static final class ProgressDialogAction extends AbstractAction { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index f367fdf553..a70e341c79 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,7 @@ import javax.lang.model.type.TypeKind; */ final class AutoIngestJobNodeData { - private static final int CURRENT_VERSION = 2; + private static final int CURRENT_VERSION = 3; private static final int DEFAULT_PRIORITY = 0; /* @@ -47,7 +47,7 @@ final class AutoIngestJobNodeData { * data. This avoids the need to continuously enlarge the buffer. Once the * buffer has all the necessary data, it will be resized as appropriate. */ - private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131637; + private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131641; /* * Version 0 fields. @@ -78,6 +78,11 @@ final class AutoIngestJobNodeData { * Version 2 fields. */ private long dataSourceSize; + + /* + * Version 3 fields. + */ + private boolean ocrEnabled; /** * Gets the current version of the auto ingest job coordination service node @@ -115,6 +120,7 @@ final class AutoIngestJobNodeData { setProcessingStageStartDate(job.getProcessingStageStartDate()); setProcessingStageDetails(job.getProcessingStageDetails()); setDataSourceSize(job.getDataSourceSize()); + setOcrEnabled(false); // ELTODO } /** @@ -150,6 +156,7 @@ final class AutoIngestJobNodeData { this.processingStageDetailsDescription = ""; this.processingStageDetailsStartDate = 0L; this.dataSourceSize = 0L; + this.ocrEnabled = false; /* * Get fields from node data. @@ -192,6 +199,14 @@ final class AutoIngestJobNodeData { */ this.dataSourceSize = buffer.getLong(); } + + if (buffer.hasRemaining()) { + /* + * Get version 3 fields. + */ + int ocrFlag = buffer.getInt(); + this.ocrEnabled = (1 == ocrFlag); + } } catch (BufferUnderflowException ex) { throw new InvalidDataException("Node data is incomplete", ex); @@ -234,6 +249,24 @@ final class AutoIngestJobNodeData { void setPriority(int priority) { this.priority = priority; } + + /** + * Gets the OCR flag for the job. + * + * @return Flag whether OCR is enabled/disabled. + */ + boolean getOcrEnabled() { + return this.ocrEnabled; + } + + /** + * Sets the OCR enabled/disabled flag for the job. + * + * @param enabled Flag whether OCR is enabled/disabled. + */ + void setOcrEnabled(boolean enabled) { + this.ocrEnabled = enabled; + } /** * Gets the number of times the job has crashed during processing. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index ffe8e19f01..a81e0d2157 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -364,6 +364,9 @@ final class AutoIngestJobsNode extends AbstractNode { PrioritizationAction.DeprioritizeCaseAction deprioritizeCaseAction = new PrioritizationAction.DeprioritizeCaseAction(jobWrapper.getJob()); deprioritizeCaseAction.setEnabled(jobWrapper.getPriority() > 0); actions.add(deprioritizeCaseAction); + + // ELTODO enable/disable based on current state + actions.add(new AutoIngestAdminActions.EnableOCR(jobWrapper.getJob())); break; case RUNNING_JOB: actions.add(new AutoIngestAdminActions.ProgressDialogAction(jobWrapper.getJob())); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index e3cace62fc..beaaffffb0 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -470,6 +470,34 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen setChanged(); notifyObservers(Event.CASE_PRIORITIZED); } + + /** + * Processes a case OCR enabled/disabled event from another node. + * + * @param event OCR enabled/disabled event from another auto ingest node. + */ + private void handleRemoteOcrEvent(AutoIngestOcrEnabledEvent event) { + // ELTODO + switch (event.getEventType()) { + case OCR_ENABLED: + sysLogger.log(Level.INFO, "Received OCR enabled event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + break; + case OCR_DISABLED: + sysLogger.log(Level.INFO, "Received OCR disabled event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + break; + default: + sysLogger.log(Level.WARNING, "Received invalid OCR enabled/disabled event from user {0} on machine {1}", + new Object[]{event.getUserName(), event.getNodeName()}); + break; + } + + String hostName = event.getNodeName(); + hostNamesToLastMsgTime.put(hostName, Instant.now()); + setChanged(); + notifyObservers(Event.OCR_STATE_CHANGE); // ELTODO + } /** * Processes a case deletion event from another node by triggering an @@ -3150,7 +3178,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen REPORT_STATE, CANCEL_JOB, REPROCESS_JOB, - GENERATE_THREAD_DUMP_RESPONSE + GENERATE_THREAD_DUMP_RESPONSE, + OCR_STATE_CHANGE } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index fbca3f50ee..23ac9b6b6f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -84,7 +84,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen AutoIngestManager.Event.SHUTTING_DOWN.toString(), AutoIngestManager.Event.SHUTDOWN.toString(), AutoIngestManager.Event.RESUMED.toString(), - AutoIngestManager.Event.GENERATE_THREAD_DUMP_RESPONSE.toString()})); + AutoIngestManager.Event.GENERATE_THREAD_DUMP_RESPONSE.toString(), + AutoIngestManager.Event.OCR_STATE_CHANGE.toString()})); private final AutopsyEventPublisher eventPublisher; private CoordinationService coordinationService; private final ScheduledThreadPoolExecutor coordSvcQueryExecutor; @@ -427,6 +428,51 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen return new JobsSnapshot(); } } + + /** + * Enables OCR for all pending ingest jobs for a specified case. + * + * @param caseName The name of the case to enable OCR. + * + * @throws AutoIngestMonitorException If there is an error enabling OCR for the jobs for the case. + * + */ + void enableOcrForCase(final String caseName) throws AutoIngestMonitorException { + List jobsToPrioritize = new ArrayList<>(); + synchronized (jobsLock) { + for (AutoIngestJob pendingJob : getPendingJobs()) { + if (pendingJob.getManifest().getCaseName().equals(caseName)) { + jobsToPrioritize.add(pendingJob); + } + } + if (!jobsToPrioritize.isEmpty()) { + for (AutoIngestJob job : jobsToPrioritize) { + String manifestNodePath = job.getManifest().getFilePath().toString(); + try { + AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath)); + nodeData.setOcrEnabled(true); + coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); + } catch (AutoIngestJobNodeData.InvalidDataException | CoordinationServiceException | InterruptedException ex) { + throw new AutoIngestMonitorException("Error enabling OCR for job " + job.toString(), ex); + } + job.enableOcr(true); // ELTODO + + /** + * Update job object in pending jobs queue + */ + jobsSnapshot.addOrReplacePendingJob(job); + } + + /* + * Publish the OCR enabled event. + */ + new Thread(() -> { + eventPublisher.publishRemotely(new AutoIngestOcrEnabledEvent(LOCAL_HOST_NAME, caseName, + AutoIngestManager.getSystemUserNameProperty(), AutoIngestOcrEnabledEvent.EventType.OCR_ENABLED)); + }).start(); + } + } + } /** * Removes the priority (set to zero) of all pending ingest jobs for a diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java new file mode 100755 index 0000000000..1489112ade --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java @@ -0,0 +1,95 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.experimental.autoingest; + +import java.io.Serializable; +import org.sleuthkit.autopsy.events.AutopsyEvent; + +/** + * Event published when an automated ingest manager enables or disables OCR on a case. + */ +public final class AutoIngestOcrEnabledEvent extends AutopsyEvent implements Serializable { + + /** + * Possible event types + */ + enum EventType { + OCR_ENABLED, + OCR_DISABLED + } + + private static final long serialVersionUID = 1L; + private final String caseName; + private final String nodeName; + private final String userName; + private final EventType eventType; + + /** + * Constructs an event published when an automated ingest manager + * enables or disables OCR on a case. + * + * @param caseName The name of the case. + * @param nodeName The host name of the node that enabled/disabled OCR. + * @param userName The logged in user + * @param eventType The type of OCR enabled/disabled event + */ + public AutoIngestOcrEnabledEvent(String nodeName, String caseName, String userName, EventType eventType) { + super(AutoIngestManager.Event.CASE_PRIORITIZED.toString(), null, null); + this.caseName = caseName; + this.nodeName = nodeName; + this.userName = userName; + this.eventType = eventType; + } + + /** + * Gets the name of the prioritized case. + * + * @return The case name. + */ + public String getCaseName() { + return caseName; + } + + /** + * Gets the host name of the node that prioritized the case. + * + * @return The host name of the node. + */ + public String getNodeName() { + return nodeName; + } + + /** + * Gets the user logged in to the node that prioritized the case. + * + * @return The user name + */ + String getUserName() { + return userName; + } + + /** + * Gets the type of prioritization + * + * @return The type + */ + EventType getEventType() { + return eventType; + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java index 006dc3e580..97ad2cee63 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java @@ -193,7 +193,7 @@ abstract class PrioritizationAction extends AbstractAction { * AutoIngestJob is a part of. */ @Messages({"PrioritizationAction.prioritizeCaseAction.title=Prioritize Case", - "PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case \"%s\"."}) + "PrioritizationAction.prioritizeCaseAction.error=Failed to prioritize case \"%s\"."}) static final class PrioritizeCaseAction extends PrioritizationAction { private static final long serialVersionUID = 1L; From f43d18a7b630d27b56b2f3bc3243f38491f02a5d Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 28 May 2021 15:00:35 -0400 Subject: [PATCH 02/16] Added some UI components --- .../autoingest/AutoIngestControlPanel.java | 26 +++++-- .../autoingest/AutoIngestJob.java | 32 ++++++++- .../autoingest/AutoIngestJobNodeData.java | 2 +- .../autoingest/AutoIngestJobsNode.java | 3 +- .../autoingest/AutoIngestJobsPanel.java | 3 +- .../autoingest/AutoIngestMonitor.java | 4 +- .../autoingest/AutoIngestOcrEnabledEvent.java | 2 +- .../autoingest/Bundle.properties-MERGED | 8 ++- .../autoingest/OcrIconCellRenderer.java | 72 +++++++++++++++++++ 9 files changed, 138 insertions(+), 14 deletions(-) create mode 100755 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 0e25ca655f..bdc32a4d40 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -179,7 +179,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status=Status", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder=Case Folder", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob= Local Job?", - "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path" + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path", + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR Enabled" }) private enum JobsTableModelColumns { @@ -195,7 +196,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")), IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")), MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")), - PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")); + PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")), + OCR(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR")); private final String header; private JobsTableModelColumns(String header) { @@ -219,7 +221,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { CASE_DIRECTORY_PATH.getColumnHeader(), IS_LOCAL_JOB.getColumnHeader(), MANIFEST_FILE_PATH.getColumnHeader(), - PRIORITY.getColumnHeader()}; + PRIORITY.getColumnHeader(), + OCR.getColumnHeader()}; } /** @@ -406,6 +409,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); + + // ELTODO + column = pendingTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); + column.setCellRenderer(new OcrIconCellRenderer()); + column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);// ELTODO + column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);// ELTODO + column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);// ELTODO /** * Allow sorting when a column header is clicked. @@ -457,6 +467,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); + runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader())); + /* * Set up a column to display the cases associated with the jobs. */ @@ -553,6 +565,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); + completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader())); // ELTODO ? + /* * Set up a column to display the cases associated with the jobs. */ @@ -882,6 +896,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { }); break; case CASE_PRIORITIZED: + case OCR_STATE_CHANGE: updateExecutor.submit(new UpdatePendingJobsTableTask()); break; case JOB_STATUS_UPDATED: @@ -1193,7 +1208,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB job.getManifest().getFilePath(), // MANIFEST_FILE_PATH - job.getPriority()}); // PRIORITY + job.getPriority(), // PRIORITY + job.getOcrEnabled()}); // OCR FLAG } } catch (Exception ex) { sysLogger.log(Level.SEVERE, "Dashboard error refreshing table", ex); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index 68487d0fcb..a1ce23b917 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,7 +46,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotProvider; final class AutoIngestJob implements Comparable, IngestProgressSnapshotProvider, Serializable { private static final long serialVersionUID = 1L; - private static final int CURRENT_VERSION = 3; + private static final int CURRENT_VERSION = 4; private static final int DEFAULT_PRIORITY = 0; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); @@ -100,6 +100,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn private List ingestThreadsSnapshot; private List ingestJobsSnapshot; private Map moduleRunTimesSnapshot; + + /* + * Version 4 fields. + */ + private boolean ocrEnabled; /** * Constructs a new automated ingest job. All job state not specified in the @@ -194,6 +199,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn this.ingestJobsSnapshot = Collections.emptyList(); this.moduleRunTimesSnapshot = Collections.emptyMap(); + /* + * Version 4 fields + */ + this.ocrEnabled = nodeData.getOcrEnabled(); + } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -253,6 +263,24 @@ final class AutoIngestJob implements Comparable, IngestProgressSn synchronized Integer getPriority() { return this.priority; } + + /** + * Gets the OCR flag for the job. + * + * @return Flag whether OCR is enabled/disabled. + */ + synchronized boolean getOcrEnabled() { + return this.ocrEnabled; + } + + /** + * Sets the OCR enabled/disabled flag for the job. + * + * @param enabled Flag whether OCR is enabled/disabled. + */ + synchronized void setOcrEnabled(boolean enabled) { + this.ocrEnabled = enabled; + } /** * Sets the processing stage of the job. The start date/time for the stage diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index a70e341c79..7078cda1d7 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -120,7 +120,7 @@ final class AutoIngestJobNodeData { setProcessingStageStartDate(job.getProcessingStageStartDate()); setProcessingStageDetails(job.getProcessingStageDetails()); setDataSourceSize(job.getDataSourceSize()); - setOcrEnabled(false); // ELTODO + setOcrEnabled(job.getOcrEnabled()); } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index a81e0d2157..5fd6eb2a6e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -57,7 +57,8 @@ final class AutoIngestJobsNode extends AbstractNode { "AutoIngestJobsNode.jobCreated.text=Job Created", "AutoIngestJobsNode.jobCompleted.text=Job Completed", "AutoIngestJobsNode.priority.text=Prioritized", - "AutoIngestJobsNode.status.text=Status" + "AutoIngestJobsNode.status.text=Status", + "AutoIngestJobsNode.ocr.text=OCR Enabled" }) /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index 6962057541..0488e1b309 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -81,7 +81,8 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa case PENDING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), - Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text()); + Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), + Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text()); indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text()); if (indexOfColumn != INVALID_INDEX) { outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 23ac9b6b6f..dc07b1d599 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -455,7 +455,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen } catch (AutoIngestJobNodeData.InvalidDataException | CoordinationServiceException | InterruptedException ex) { throw new AutoIngestMonitorException("Error enabling OCR for job " + job.toString(), ex); } - job.enableOcr(true); // ELTODO + job.setOcrEnabled(true); /** * Update job object in pending jobs queue @@ -472,7 +472,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen }).start(); } } - } + } /** * Removes the priority (set to zero) of all pending ingest jobs for a diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java index 1489112ade..cea16ad024 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java @@ -50,7 +50,7 @@ public final class AutoIngestOcrEnabledEvent extends AutopsyEvent implements Ser * @param eventType The type of OCR enabled/disabled event */ public AutoIngestOcrEnabledEvent(String nodeName, String caseName, String userName, EventType eventType) { - super(AutoIngestManager.Event.CASE_PRIORITIZED.toString(), null, null); + super(AutoIngestManager.Event.OCR_STATE_CHANGE.toString(), null, null); this.caseName = caseName; this.nodeName = nodeName; this.userName = userName; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index d74f98b5a7..07bc2404f5 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -10,6 +10,8 @@ AinStatusNode.status.title=Status AinStatusNode.status.unknown=Unknown AutoIngestAdminActions.cancelJobAction.title=Cancel Job AutoIngestAdminActions.cancelModuleAction.title=Cancel Module +AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case "%s". +AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case AutoIngestAdminActions.getThreadDump.title=Generate Thread Dump AutoIngestAdminActions.pause.title=Pause Node AutoIngestAdminActions.progressDialogAction.title=Ingest Progress @@ -71,6 +73,7 @@ AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob=\ Local Job? AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath=\ Manifest File Path +AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR Enabled AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized AutoIngestControlPanel.JobsTableModel.ColumnHeader.Stage=Stage AutoIngestControlPanel.JobsTableModel.ColumnHeader.StageTime=Time in Stage @@ -130,6 +133,7 @@ AutoIngestJobsNode.dataSource.text=Data Source AutoIngestJobsNode.hostName.text=Host Name AutoIngestJobsNode.jobCompleted.text=Job Completed AutoIngestJobsNode.jobCreated.text=Job Created +AutoIngestJobsNode.ocr.text=OCR Enabled AutoIngestJobsNode.prioritized.false=No AutoIngestJobsNode.prioritized.true=Yes AutoIngestJobsNode.priority.text=Prioritized @@ -222,6 +226,8 @@ DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordin DeleteOrphanManifestNodesTask.progress.lookingForOrphanedManifestFileZnodes=Looking for orphaned manifest file znodes DeleteOrphanManifestNodesTask.progress.startMessage=Starting orphaned manifest file znode cleanup HINT_CasesDashboardTopComponent=This is an adminstrative dashboard for multi-user cases +OcrIconCellRenderer.disabled.tooltiptext=This job does not have OCR enabled. +OcrIconCellRenderer.enabled.tooltiptext=This job has OCR enabled. OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted. OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details. OpenAutoIngestLogAction.menuItemText=Open Auto Ingest Log File @@ -331,7 +337,7 @@ PrioritizationAction.deprioritizeCaseAction.error=Failed to deprioritize case "% PrioritizationAction.deprioritizeCaseAction.title=Deprioritize Case PrioritizationAction.deprioritizeJobAction.error=Failed to deprioritize job "%s". PrioritizationAction.deprioritizeJobAction.title=Deprioritize Job -PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case "%s". +PrioritizationAction.prioritizeCaseAction.error=Failed to prioritize case "%s". PrioritizationAction.prioritizeCaseAction.title=Prioritize Case PrioritizationAction.prioritizeJobAction.error=Failed to prioritize job "%s". PrioritizationAction.prioritizeJobAction.title=Prioritize Job diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java new file mode 100755 index 0000000000..4c5874349f --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java @@ -0,0 +1,72 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.experimental.autoingest; + +import java.awt.Component; +import java.lang.reflect.InvocationTargetException; +import javax.swing.ImageIcon; +import javax.swing.JTable; +import static javax.swing.SwingConstants.CENTER; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer; +import org.sleuthkit.autopsy.datamodel.NodeProperty; + +/** + * A JTable and Outline view cell renderer that represents whether OCR is enabled for the job. + */ +class OcrIconCellRenderer extends GrayableCellRenderer { + + @Messages({ + "OcrIconCellRenderer.enabled.tooltiptext=This job has OCR enabled.", + "OcrIconCellRenderer.disabled.tooltiptext=This job does not have OCR enabled." + }) + private static final long serialVersionUID = 1L; + static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false)); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + setHorizontalAlignment(CENTER); + Object switchValue = null; + if ((value instanceof NodeProperty)) { + //The Outline view has properties in the cell, the value contained in the property is what we want + try { + switchValue = ((Node.Property) value).getValue(); + } catch (IllegalAccessException | InvocationTargetException ignored) { + //Unable to get the value from the NodeProperty no Icon will be displayed + } + } else { + //JTables contain the value we want directly in the cell + switchValue = value; + } + if (switchValue instanceof Integer && (int) switchValue != 0) { + setIcon(checkedIcon); + setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.enabled.tooltiptext")); + } else { + setIcon(null); + if (switchValue instanceof Integer) { + setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.disabled.tooltiptext")); + } + } + grayCellIfTableNotEnabled(table, isSelected); + + return this; + } +} From 77a93b98ace9d5b7887a6df8236ab161da46dbb7 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 1 Jun 2021 15:36:11 -0400 Subject: [PATCH 03/16] UI work --- .../experimental/autoingest/AutoIngestJobsNode.java | 11 +++++++++-- .../experimental/autoingest/AutoIngestJobsPanel.java | 9 +++++++-- .../experimental/autoingest/OcrIconCellRenderer.java | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index 5fd6eb2a6e..30b4847edf 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -124,11 +124,12 @@ final class AutoIngestJobsNode extends AbstractNode { AutoIngestJob thisJob = this.autoIngestJob; AutoIngestJob otherJob = ((AutoIngestJobWrapper) other).autoIngestJob; - // Only equal if the manifest paths and processing stage details are the same. + // Only equal if the manifest paths, processing stage details, priority, and OCR flag are the same. return thisJob.getManifest().getFilePath().equals(otherJob.getManifest().getFilePath()) && jobStage.equals(((AutoIngestJobWrapper) other).jobStage) && jobSnapshot.equals(((AutoIngestJobWrapper) other).jobSnapshot) - && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority); + && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority) + && (thisJob.getOcrEnabled() == otherJob.getOcrEnabled()); } @Override @@ -172,6 +173,10 @@ final class AutoIngestJobsNode extends AbstractNode { Integer getPriority() { return autoIngestJob.getPriority(); } + + boolean getOcrEnabled() { + return autoIngestJob.getOcrEnabled(); + } } /** @@ -328,6 +333,8 @@ final class AutoIngestJobsNode extends AbstractNode { jobWrapper.getManifest().getDateFileCreated())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), jobWrapper.getPriority())); + ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), + jobWrapper.getOcrEnabled())); break; case RUNNING_JOB: AutoIngestJob.StageDetails status = jobWrapper.getProcessingStageDetails(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index 0488e1b309..838d83febb 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,7 +42,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa private static final long serialVersionUID = 1L; private static final int INITIAL_CASENAME_WIDTH = 170; private static final int INITIAL_DATASOURCE_WIDTH = 270; - private static final int INITIAL_PRIORITIZED_WIDTH = 20; + private static final int INITIAL_PRIORITIZED_WIDTH = 20; // ELTODO private static final int INITIAL_STATUS_WIDTH = 20; private static final int INVALID_INDEX = -1; private final org.openide.explorer.view.OutlineView outlineView; @@ -88,6 +88,11 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new PrioritizedIconCellRenderer()); } + indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); + if (indexOfColumn != INVALID_INDEX) { + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); + } break; case RUNNING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java index 4c5874349f..e90754adf8 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java @@ -56,12 +56,12 @@ class OcrIconCellRenderer extends GrayableCellRenderer { //JTables contain the value we want directly in the cell switchValue = value; } - if (switchValue instanceof Integer && (int) switchValue != 0) { + if (switchValue instanceof Boolean && (boolean) switchValue == true) { setIcon(checkedIcon); setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.enabled.tooltiptext")); } else { setIcon(null); - if (switchValue instanceof Integer) { + if (switchValue instanceof Boolean) { setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.disabled.tooltiptext")); } } From 44afaa7b28e8a007e0b96dc12d5d4e97f88b06b9 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 2 Jun 2021 15:11:53 -0400 Subject: [PATCH 04/16] Integrated with KWS service --- .../KeywordSearchService.java | 12 +++++++- .../autoingest/AutoIngestControlPanel.java | 9 +++--- .../autoingest/AutoIngestJobsNode.java | 2 +- .../autoingest/AutoIngestJobsPanel.java | 7 +++-- .../autoingest/AutoIngestManager.java | 30 ++++++++++++++----- .../autoingest/AutoIngestMonitor.java | 4 +-- ...ava => AutoIngestOcrStateChangeEvent.java} | 4 +-- .../keywordsearch/Bundle.properties-MERGED | 3 +- .../keywordsearch/SolrSearchService.java | 11 +++++++ 9 files changed, 60 insertions(+), 22 deletions(-) rename Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/{AutoIngestOcrEnabledEvent.java => AutoIngestOcrStateChangeEvent.java} (92%) diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java index 981abe05de..7d197a4d11 100644 --- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2019 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.keywordsearchservice; +import com.google.common.annotations.Beta; import java.io.Closeable; import java.io.IOException; import org.sleuthkit.autopsy.casemodule.CaseMetadata; @@ -105,5 +106,14 @@ public interface KeywordSearchService extends Closeable { * @throws KeywordSearchServiceException if unable to delete. */ void deleteDataSource(Long dataSourceId) throws KeywordSearchServiceException; + + /** + * A flag to enable or disable OCR on all future text indexing. + * + * @param state Boolean flag to enable/disable OCR. Set to True to enable + * OCR, or False to disable it. + */ + @Beta + void changeOcrState(boolean state); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index bdc32a4d40..6b90a01fc4 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -122,6 +122,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; + private static final int OCR_COLUMN_PREFERRED_WIDTH = 60; + private static final int OCR_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; @@ -410,12 +412,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); - // ELTODO column = pendingTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); column.setCellRenderer(new OcrIconCellRenderer()); - column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH);// ELTODO - column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);// ELTODO - column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH);// ELTODO + column.setMaxWidth(OCR_COLUMN_MAX_WIDTH); + column.setPreferredWidth(OCR_COLUMN_PREFERRED_WIDTH); + column.setWidth(OCR_COLUMN_PREFERRED_WIDTH); /** * Allow sorting when a column header is clicked. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index 30b4847edf..c5f5d75ab2 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index 838d83febb..d063c7a4f4 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -42,7 +42,8 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa private static final long serialVersionUID = 1L; private static final int INITIAL_CASENAME_WIDTH = 170; private static final int INITIAL_DATASOURCE_WIDTH = 270; - private static final int INITIAL_PRIORITIZED_WIDTH = 20; // ELTODO + private static final int INITIAL_PRIORITIZED_WIDTH = 20; + private static final int INITIAL_OCR_WIDTH = 20; private static final int INITIAL_STATUS_WIDTH = 20; private static final int INVALID_INDEX = -1; private final org.openide.explorer.view.OutlineView outlineView; @@ -90,9 +91,9 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa } indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); if (indexOfColumn != INVALID_INDEX) { - outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_OCR_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); - } + } break; case RUNNING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index beaaffffb0..968e61ae60 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -55,6 +55,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import javax.annotation.concurrent.GuardedBy; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -105,6 +106,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleError; import org.sleuthkit.autopsy.ingest.IngestStream; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchModuleException; import org.sleuthkit.autopsy.keywordsearch.Server; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; @@ -144,7 +146,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen ControlEventType.SHUTDOWN.toString(), ControlEventType.GENERATE_THREAD_DUMP_REQUEST.toString(), Event.CANCEL_JOB.toString(), - Event.REPROCESS_JOB.toString()})); + Event.REPROCESS_JOB.toString(), + Event.OCR_STATE_CHANGE.toString()})); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10; private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d"; @@ -308,6 +311,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen handleRemoteJobCancelEvent((AutoIngestJobCancelEvent) event); } else if (event instanceof AutoIngestJobReprocessEvent) { handleRemoteJobReprocessEvent((AutoIngestJobReprocessEvent) event); + } else if (event instanceof AutoIngestOcrStateChangeEvent) { + handleRemoteOcrEvent((AutoIngestOcrStateChangeEvent) event); } } } @@ -476,8 +481,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * * @param event OCR enabled/disabled event from another auto ingest node. */ - private void handleRemoteOcrEvent(AutoIngestOcrEnabledEvent event) { - // ELTODO + private void handleRemoteOcrEvent(AutoIngestOcrStateChangeEvent event) { switch (event.getEventType()) { case OCR_ENABLED: sysLogger.log(Level.INFO, "Received OCR enabled event for case {0} from user {1} on machine {2}", @@ -495,9 +499,13 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); + + // update all pending jobs and get latest ZK manifest node contents for those jobs + scanInputDirsNow(); + setChanged(); - notifyObservers(Event.OCR_STATE_CHANGE); // ELTODO - } + notifyObservers(Event.OCR_STATE_CHANGE); + } /** * Processes a case deletion event from another node by triggering an @@ -2084,10 +2092,11 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } iterator.remove(); - currentJob = job; + // create a new job object based on latest ZK node data (i.e. instead of potentially stale local pending AutoIngestJob). + currentJob = new AutoIngestJob(nodeData); break; - } catch (AutoIngestJobNodeData.InvalidDataException ex) { + } catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) { sysLogger.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex); } } @@ -2269,7 +2278,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /** * Updates the ingest system settings by downloading the latest version - * of the settings if using shared configuration. + * of the settings if using shared configuration. Also updates the OCR + * setting. * * @throws SharedConfigurationException if there is an error downloading * shared configuration. @@ -2285,6 +2295,10 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen currentJob.setProcessingStage(AutoIngestJob.Stage.UPDATING_SHARED_CONFIG, Date.from(Instant.now())); new SharedConfiguration().downloadConfiguration(); } + + // update the OCR enabled/disabled setting + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); + kwsService.changeOcrState(currentJob.getOcrEnabled()); } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index dc07b1d599..8e58828c04 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -467,8 +467,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen * Publish the OCR enabled event. */ new Thread(() -> { - eventPublisher.publishRemotely(new AutoIngestOcrEnabledEvent(LOCAL_HOST_NAME, caseName, - AutoIngestManager.getSystemUserNameProperty(), AutoIngestOcrEnabledEvent.EventType.OCR_ENABLED)); + eventPublisher.publishRemotely(new AutoIngestOcrStateChangeEvent(LOCAL_HOST_NAME, caseName, + AutoIngestManager.getSystemUserNameProperty(), AutoIngestOcrStateChangeEvent.EventType.OCR_ENABLED)); }).start(); } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java similarity index 92% rename from Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java rename to Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java index cea16ad024..63b4fa324c 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrEnabledEvent.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java @@ -24,7 +24,7 @@ import org.sleuthkit.autopsy.events.AutopsyEvent; /** * Event published when an automated ingest manager enables or disables OCR on a case. */ -public final class AutoIngestOcrEnabledEvent extends AutopsyEvent implements Serializable { +public final class AutoIngestOcrStateChangeEvent extends AutopsyEvent implements Serializable { /** * Possible event types @@ -49,7 +49,7 @@ public final class AutoIngestOcrEnabledEvent extends AutopsyEvent implements Ser * @param userName The logged in user * @param eventType The type of OCR enabled/disabled event */ - public AutoIngestOcrEnabledEvent(String nodeName, String caseName, String userName, EventType eventType) { + public AutoIngestOcrStateChangeEvent(String nodeName, String caseName, String userName, EventType eventType) { super(AutoIngestManager.Event.OCR_STATE_CHANGE.toString(), null, null); this.caseName = caseName; this.nodeName = nodeName; diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index c60c34bade..8a30223f6b 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -5,6 +5,7 @@ AccountsText.nextPage.exception.msg=No next page. AccountsText.previousItem.exception.msg=No previous item. AccountsText.previousPage.exception.msg=No previous page. CannotRunFileTypeDetection=Unable to run file type detection. +Collection.unableToIndexData.error=Unable to add data to text index. All future text indexing for the current case will be skipped. DropdownListSearchPanel.selected=Ad Hoc Search data source filter is selected DropdownSingleTermSearchPanel.selected=Ad Hoc Search data source filter is selected DropdownSingleTermSearchPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,] @@ -51,7 +52,7 @@ KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 218be24de8..7567725b0c 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -462,4 +462,15 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { } } + /** + * A flag to enable or disable OCR on all future text indexing. + * + * @param state Boolean flag to enable/disable OCR. Set to True to enable + * OCR, or False to disable it. + */ + @Override + public void changeOcrState(boolean state) { + KeywordSearchSettings.setOcrOption(state); + } + } From 63ad845a7984affb51633bb03e81d197d782f185 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 10:02:43 -0400 Subject: [PATCH 05/16] More work --- .../autoingest/AutoIngestAdminActions.java | 50 ++++++++++++++++++- .../autoingest/AutoIngestJobsNode.java | 1 + .../autoingest/AutoIngestMonitor.java | 8 +-- .../AutoIngestNodeRefreshEvents.java | 2 +- .../AutoIngestOcrStateChangeEvent.java | 10 ++-- .../autoingest/Bundle.properties-MERGED | 2 + 6 files changed, 64 insertions(+), 9 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java index 994d2f91a0..c44ef22e23 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java @@ -187,7 +187,7 @@ final class AutoIngestAdminActions { dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); EventQueue.invokeLater(() -> { try { - dashboard.getMonitor().enableOcrForCase(job.getManifest().getCaseName()); + dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), true); dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); // ELTODO } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { String errorMessage = String.format(Bundle.AutoIngestAdminActions_enableOCR_error(), job.getManifest().getCaseName()); @@ -200,6 +200,54 @@ final class AutoIngestAdminActions { } } + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } + + @NbBundle.Messages({"AutoIngestAdminActions.disableOCR.title=Disable OCR For This Case", + "AutoIngestAdminActions.disableOCR.error=Failed to disable OCR for case \"%s\"."}) + static final class DisableOCR extends AbstractAction { + + private static final long serialVersionUID = 1L; + private final AutoIngestJob job; + + DisableOCR(AutoIngestJob job) { + super(Bundle.AutoIngestAdminActions_disableOCR_title()); + this.job = job; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (job == null) { + return; + } + + final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); + if (tc == null) { + return; + } + + AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); + if (dashboard != null) { + dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + EventQueue.invokeLater(() -> { + try { + dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), false); + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); // ELTODO + } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { + String errorMessage = String.format(Bundle.AutoIngestAdminActions_disableOCR_error(), job.getManifest().getCaseName()); + logger.log(Level.SEVERE, errorMessage, ex); + MessageNotifyUtil.Message.error(errorMessage); + } finally { + dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor()); + } + }); + } + } + @Override public Object clone() throws CloneNotSupportedException { return super.clone(); //To change body of generated methods, choose Tools | Templates. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index c5f5d75ab2..9f6f70f3e9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -375,6 +375,7 @@ final class AutoIngestJobsNode extends AbstractNode { // ELTODO enable/disable based on current state actions.add(new AutoIngestAdminActions.EnableOCR(jobWrapper.getJob())); + actions.add(new AutoIngestAdminActions.DisableOCR(jobWrapper.getJob())); break; case RUNNING_JOB: actions.add(new AutoIngestAdminActions.ProgressDialogAction(jobWrapper.getJob())); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 8e58828c04..f9033f3235 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -437,7 +437,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen * @throws AutoIngestMonitorException If there is an error enabling OCR for the jobs for the case. * */ - void enableOcrForCase(final String caseName) throws AutoIngestMonitorException { + void changeOcrStateForCase(final String caseName, final boolean ocrState) throws AutoIngestMonitorException { List jobsToPrioritize = new ArrayList<>(); synchronized (jobsLock) { for (AutoIngestJob pendingJob : getPendingJobs()) { @@ -450,12 +450,12 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen String manifestNodePath = job.getManifest().getFilePath().toString(); try { AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath)); - nodeData.setOcrEnabled(true); + nodeData.setOcrEnabled(ocrState); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); } catch (AutoIngestJobNodeData.InvalidDataException | CoordinationServiceException | InterruptedException ex) { throw new AutoIngestMonitorException("Error enabling OCR for job " + job.toString(), ex); } - job.setOcrEnabled(true); + job.setOcrEnabled(ocrState); /** * Update job object in pending jobs queue @@ -468,7 +468,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen */ new Thread(() -> { eventPublisher.publishRemotely(new AutoIngestOcrStateChangeEvent(LOCAL_HOST_NAME, caseName, - AutoIngestManager.getSystemUserNameProperty(), AutoIngestOcrStateChangeEvent.EventType.OCR_ENABLED)); + AutoIngestManager.getSystemUserNameProperty(), ocrState)); }).start(); } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java index 338bce31c7..be7cc2408f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java @@ -69,7 +69,7 @@ class AutoIngestNodeRefreshEvents { private final String caseName; /** - * Contructs a RefreshCaseEvent + * Constructs a RefreshCaseEvent * * @param monitor The monitor that will provide access to the current state of the jobs lists. * @param name The name of the case whose nodes should be refreshed. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java index 63b4fa324c..682ad711eb 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java @@ -47,14 +47,18 @@ public final class AutoIngestOcrStateChangeEvent extends AutopsyEvent implements * @param caseName The name of the case. * @param nodeName The host name of the node that enabled/disabled OCR. * @param userName The logged in user - * @param eventType The type of OCR enabled/disabled event + * @param ocrState Flag whether OCR is enabled/disabled */ - public AutoIngestOcrStateChangeEvent(String nodeName, String caseName, String userName, EventType eventType) { + public AutoIngestOcrStateChangeEvent(String nodeName, String caseName, String userName, boolean ocrState) { super(AutoIngestManager.Event.OCR_STATE_CHANGE.toString(), null, null); this.caseName = caseName; this.nodeName = nodeName; this.userName = userName; - this.eventType = eventType; + if (ocrState == true) { + this.eventType = EventType.OCR_ENABLED; + } else { + this.eventType = EventType.OCR_DISABLED; + } } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index 07bc2404f5..1eba0a4194 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -10,6 +10,8 @@ AinStatusNode.status.title=Status AinStatusNode.status.unknown=Unknown AutoIngestAdminActions.cancelJobAction.title=Cancel Job AutoIngestAdminActions.cancelModuleAction.title=Cancel Module +AutoIngestAdminActions.disableOCR.error=Failed to disable OCR for case "%s". +AutoIngestAdminActions.disableOCR.title=Disable OCR For This Case AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case "%s". AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case AutoIngestAdminActions.getThreadDump.title=Generate Thread Dump From 8c9001ef6d6088b81bb3a7042c7efdefecf2801e Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 15:16:31 -0400 Subject: [PATCH 06/16] Fixes --- .../experimental/autoingest/AutoIngestJobsNode.java | 1 + .../experimental/autoingest/AutoIngestMonitor.java | 11 +++++++++++ .../experimental/autoingest/Bundle.properties-MERGED | 2 -- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index 9f6f70f3e9..6f8ae886c1 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -139,6 +139,7 @@ final class AutoIngestJobsNode extends AbstractNode { hash = 23 * hash + Objects.hashCode(this.jobStage); hash = 23 * hash + Objects.hashCode(this.jobSnapshot); hash = 23 * hash + Objects.hashCode(this.jobPriority); + hash = 23 * hash + Objects.hashCode(this.autoIngestJob.getOcrEnabled()); return hash; } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index f9033f3235..0022cf6609 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -167,6 +167,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen handleAutoIngestNodeStateEvent((AutoIngestNodeStateEvent) event); } else if (event instanceof ThreadDumpResponseEvent) { handleRemoteThreadDumpResponseEvent((ThreadDumpResponseEvent) event); + } else if (event instanceof AutoIngestOcrStateChangeEvent) { + handleOcrStateChangeEvent((AutoIngestOcrStateChangeEvent) event); } } @@ -229,6 +231,15 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen } } + /** + * Handles an OCR state change event. + * + * @param event OCR state change event. + */ + private void handleOcrStateChangeEvent(AutoIngestOcrStateChangeEvent event) { + coordSvcQueryExecutor.submit(new StateRefreshTask()); + } + /** * Handles an auto ingest job/case prioritization event. * diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index 5e32707834..1eba0a4194 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -212,9 +212,7 @@ DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}... DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}... DeleteCaseTask.progress.startMessage=Starting deletion... DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes -# {0} - item count DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0} -# {0} - item count DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0} DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service # {0} - node path From 86035a633618b182e63e501b856eb45aee857267 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 19:44:38 -0400 Subject: [PATCH 07/16] Bug fixes --- .../experimental/autoingest/AutoIngestJobNodeData.java | 6 +++++- .../autopsy/experimental/autoingest/AutoIngestJobsNode.java | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index 7078cda1d7..5e9ab8955d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -134,7 +134,7 @@ final class AutoIngestJobNodeData { if (null == nodeData || nodeData.length == 0) { throw new InvalidDataException(null == nodeData ? "Null nodeData byte array" : "Zero-length nodeData byte array"); } - + /* * Set default values for all fields. */ @@ -600,6 +600,10 @@ final class AutoIngestJobNodeData { if (this.version >= 2) { buffer.putLong(this.dataSourceSize); } + + if (this.version >= 3) { + buffer.putInt(this.ocrEnabled ? 1 : 0); + } } // Prepare the array diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index 6f8ae886c1..00a39914a9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -99,12 +99,14 @@ final class AutoIngestJobsNode extends AbstractNode { private final Stage jobStage; private final List jobSnapshot; private final Integer jobPriority; + private final Boolean ocrFlag; AutoIngestJobWrapper(AutoIngestJob job) { autoIngestJob = job; jobStage = job.getProcessingStage(); jobSnapshot = job.getIngestJobSnapshots(); jobPriority = job.getPriority(); + ocrFlag = job.getOcrEnabled(); } AutoIngestJob getJob() { @@ -129,7 +131,7 @@ final class AutoIngestJobsNode extends AbstractNode { && jobStage.equals(((AutoIngestJobWrapper) other).jobStage) && jobSnapshot.equals(((AutoIngestJobWrapper) other).jobSnapshot) && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority) - && (thisJob.getOcrEnabled() == otherJob.getOcrEnabled()); + && ocrFlag.equals(((AutoIngestJobWrapper) other).ocrFlag); } @Override @@ -139,7 +141,7 @@ final class AutoIngestJobsNode extends AbstractNode { hash = 23 * hash + Objects.hashCode(this.jobStage); hash = 23 * hash + Objects.hashCode(this.jobSnapshot); hash = 23 * hash + Objects.hashCode(this.jobPriority); - hash = 23 * hash + Objects.hashCode(this.autoIngestJob.getOcrEnabled()); + hash = 23 * hash + Objects.hashCode(this.ocrFlag); return hash; } From e71633b495bdb2cd05efbc6113a37c03ea130908 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 19:59:07 -0400 Subject: [PATCH 08/16] Bug fix --- .../org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 7567725b0c..3a51c69494 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -471,6 +471,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { @Override public void changeOcrState(boolean state) { KeywordSearchSettings.setOcrOption(state); + KeywordSearchSettings.setLimitedOcrOption(state); } } From 5b38d899c3099c7a18d968a7fbf7de484715a50a Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 20:28:32 -0400 Subject: [PATCH 09/16] Added OCR column to completed jobs table --- .../autoingest/AutoIngestControlPanel.java | 14 +++++++++++--- .../autoingest/AutoIngestJobsNode.java | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 6b90a01fc4..763d41c027 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -122,7 +122,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; - private static final int OCR_COLUMN_PREFERRED_WIDTH = 60; + private static final int OCR_COLUMN_PREFERRED_WIDTH = 80; private static final int OCR_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; @@ -566,7 +566,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); - completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader())); // ELTODO ? /* * Set up a column to display the cases associated with the jobs. @@ -618,6 +617,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH); + + /* + * Set up a column to display OCR enabled/disabled flag. + */ + column = completedTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); + column.setCellRenderer(new OcrIconCellRenderer()); + column.setMaxWidth(OCR_COLUMN_MAX_WIDTH); + column.setPreferredWidth(OCR_COLUMN_PREFERRED_WIDTH); + column.setWidth(OCR_COLUMN_PREFERRED_WIDTH); /* * Allow sorting when a column header is clicked. @@ -871,6 +879,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { case JOB_COMPLETED: case CASE_DELETED: case REPROCESS_JOB: + case OCR_STATE_CHANGE: updateExecutor.submit(new UpdateAllJobsTablesTask()); break; case PAUSED_BY_USER_REQUEST: @@ -897,7 +906,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { }); break; case CASE_PRIORITIZED: - case OCR_STATE_CHANGE: updateExecutor.submit(new UpdatePendingJobsTableTask()); break; case JOB_STATUS_UPDATED: diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index 00a39914a9..e68a1f79f6 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -355,6 +355,8 @@ final class AutoIngestJobsNode extends AbstractNode { jobWrapper.getCompletedDate())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), jobWrapper.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK)); + ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), + jobWrapper.getOcrEnabled())); break; default: } From 8a4bd4548a9d0b192894bcaf26525dc80f53ae47 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 20:48:35 -0400 Subject: [PATCH 10/16] Minor --- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- .../autopsy/experimental/autoingest/AutoIngestManager.java | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 763d41c027..0fcf8490f9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -122,7 +122,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; - private static final int OCR_COLUMN_PREFERRED_WIDTH = 80; + private static final int OCR_COLUMN_PREFERRED_WIDTH = 50; private static final int OCR_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; @@ -182,7 +182,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder=Case Folder", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob= Local Job?", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path", - "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR Enabled" + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR" }) private enum JobsTableModelColumns { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 968e61ae60..7f72a02fd9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -2297,6 +2297,11 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } // update the OCR enabled/disabled setting + if (currentJob.getOcrEnabled()) { + sysLogger.log(Level.INFO, "Enabling OCR for job {0}", currentJob.getManifest().getFilePath()); + } else { + sysLogger.log(Level.INFO, "Disabling OCR for job {0}", currentJob.getManifest().getFilePath()); + } KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); kwsService.changeOcrState(currentJob.getOcrEnabled()); } From a3d0fd3a675afdbf1d6d0ea28534a984a2c90051 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 3 Jun 2021 21:32:02 -0400 Subject: [PATCH 11/16] Minor --- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 0fcf8490f9..656b98b278 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -135,9 +135,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int ACTIVITY_COL_MIN_WIDTH = 70; private static final int ACTIVITY_COL_MAX_WIDTH = 2000; private static final int ACTIVITY_COL_PREFERRED_WIDTH = 300; - private static final int STATUS_COL_MIN_WIDTH = 55; + private static final int STATUS_COL_MIN_WIDTH = 50; private static final int STATUS_COL_MAX_WIDTH = 250; - private static final int STATUS_COL_PREFERRED_WIDTH = 55; + private static final int STATUS_COL_PREFERRED_WIDTH = 50; private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30; private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000; private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280; From bc871232606ec0322c8550a4a17ea0a459cd7840 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 4 Jun 2021 09:46:15 -0400 Subject: [PATCH 12/16] Minor --- .../experimental/autoingest/AutoIngestAdminActions.java | 4 ++-- .../autopsy/experimental/autoingest/AutoIngestJobsNode.java | 5 +++-- .../autopsy/experimental/autoingest/Bundle.properties-MERGED | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java index c44ef22e23..6680074a17 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java @@ -188,7 +188,7 @@ final class AutoIngestAdminActions { EventQueue.invokeLater(() -> { try { dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), true); - dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); // ELTODO + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { String errorMessage = String.format(Bundle.AutoIngestAdminActions_enableOCR_error(), job.getManifest().getCaseName()); logger.log(Level.SEVERE, errorMessage, ex); @@ -236,7 +236,7 @@ final class AutoIngestAdminActions { EventQueue.invokeLater(() -> { try { dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), false); - dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); // ELTODO + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { String errorMessage = String.format(Bundle.AutoIngestAdminActions_disableOCR_error(), job.getManifest().getCaseName()); logger.log(Level.SEVERE, errorMessage, ex); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index e68a1f79f6..ac3f64c847 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -378,9 +378,10 @@ final class AutoIngestJobsNode extends AbstractNode { deprioritizeCaseAction.setEnabled(jobWrapper.getPriority() > 0); actions.add(deprioritizeCaseAction); - // ELTODO enable/disable based on current state actions.add(new AutoIngestAdminActions.EnableOCR(jobWrapper.getJob())); - actions.add(new AutoIngestAdminActions.DisableOCR(jobWrapper.getJob())); + AutoIngestAdminActions.DisableOCR disableOCRAction = new AutoIngestAdminActions.DisableOCR(jobWrapper.getJob()); + disableOCRAction.setEnabled(jobWrapper.getOcrEnabled() == true); + actions.add(disableOCRAction); break; case RUNNING_JOB: actions.add(new AutoIngestAdminActions.ProgressDialogAction(jobWrapper.getJob())); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index 1eba0a4194..cf4d447b0a 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -75,7 +75,7 @@ AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob=\ Local Job? AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath=\ Manifest File Path -AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR Enabled +AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized AutoIngestControlPanel.JobsTableModel.ColumnHeader.Stage=Stage AutoIngestControlPanel.JobsTableModel.ColumnHeader.StageTime=Time in Stage From 46eee0b0152d5c3eff33f25d3db0e254ecf41fa0 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 4 Jun 2021 09:53:45 -0400 Subject: [PATCH 13/16] Minor --- .../autopsy/experimental/autoingest/AutoIngestJobsNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index ac3f64c847..24a1e57fb9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -58,7 +58,7 @@ final class AutoIngestJobsNode extends AbstractNode { "AutoIngestJobsNode.jobCompleted.text=Job Completed", "AutoIngestJobsNode.priority.text=Prioritized", "AutoIngestJobsNode.status.text=Status", - "AutoIngestJobsNode.ocr.text=OCR Enabled" + "AutoIngestJobsNode.ocr.text=OCR" }) /** From ebd776b1f196578c7ece77a692cdef10389a34f8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 4 Jun 2021 10:20:48 -0400 Subject: [PATCH 14/16] Minor --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 6 +++--- .../experimental/autoingest/Bundle.properties-MERGED | 2 +- .../sleuthkit/autopsy/keywordsearch/SolrSearchService.java | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 7f72a02fd9..118ff453c6 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -55,7 +55,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import javax.annotation.concurrent.GuardedBy; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -471,6 +470,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); + // currently the only way to the get latest ZK manifest node contents is to do an input directory scan scanInputDirsNow(); setChanged(); notifyObservers(Event.CASE_PRIORITIZED); @@ -500,7 +500,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); - // update all pending jobs and get latest ZK manifest node contents for those jobs + // currently the only way to the get latest ZK manifest node contents is to do an input directory scan scanInputDirsNow(); setChanged(); @@ -2092,7 +2092,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } iterator.remove(); - // create a new job object based on latest ZK node data (i.e. instead of potentially stale local pending AutoIngestJob). + // create a new job object based on latest ZK node data (i.e. instead of re-using potentially stale local pending AutoIngestJob object). currentJob = new AutoIngestJob(nodeData); break; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index cf4d447b0a..2a1e361537 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -135,7 +135,7 @@ AutoIngestJobsNode.dataSource.text=Data Source AutoIngestJobsNode.hostName.text=Host Name AutoIngestJobsNode.jobCompleted.text=Job Completed AutoIngestJobsNode.jobCreated.text=Job Created -AutoIngestJobsNode.ocr.text=OCR Enabled +AutoIngestJobsNode.ocr.text=OCR AutoIngestJobsNode.prioritized.false=No AutoIngestJobsNode.prioritized.true=Yes AutoIngestJobsNode.priority.text=Prioritized diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 3a51c69494..09460a0788 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -463,7 +463,8 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { } /** - * A flag to enable or disable OCR on all future text indexing. + * A flag to enable or disable OCR on all future text indexing. Also sets the + * the "Limited OCR" functionality accordingly. * * @param state Boolean flag to enable/disable OCR. Set to True to enable * OCR, or False to disable it. From 557f4e85e8bfeca89fbd5403bee0a7bac60c9938 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 4 Jun 2021 13:21:17 -0400 Subject: [PATCH 15/16] Bug fixes --- .../experimental/autoingest/AutoIngestJobsPanel.java | 8 +++++++- .../experimental/autoingest/AutoIngestManager.java | 9 ++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index d063c7a4f4..d335a35430 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -109,7 +109,8 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), - Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text()); + Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), + Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text()); indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_jobCompleted_text()); if (indexOfColumn != INVALID_INDEX) { outline.setColumnSorted(indexOfColumn, false, 1); @@ -119,6 +120,11 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new StatusIconCellRenderer()); } + indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); + if (indexOfColumn != INVALID_INDEX) { + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_OCR_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); + } break; default: } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 118ff453c6..f40fa6d189 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -2251,21 +2251,20 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * auto ingest job. */ private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, IOException, JobMetricsCollectionException { - updateConfiguration(); - if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { - return; - } verifyRequiredSevicesAreRunning(); if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { return; } Case caseForJob = openCase(); try { + if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { + return; + } + updateConfiguration(); if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { return; } runIngestForJob(caseForJob); - } finally { try { Case.closeCurrentCase(); From c26efab04dbda2dc0b94d29b51a524238f687ebe Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 9 Jun 2021 15:45:13 -0400 Subject: [PATCH 16/16] change in analysis results header attributes --- .../AnalysisResultsContentPanel.java | 69 ++++++++++++++----- .../AnalysisResultsViewModel.java | 23 ++++++- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java index 3a5a670f49..f365e8392e 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java @@ -26,20 +26,22 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.NodeResults; import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.ResultDisplayAttributes; import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Score; /** * Displays a list of analysis results in a panel. */ public class AnalysisResultsContentPanel extends javax.swing.JPanel { - + private static final long serialVersionUID = 1L; - + private static final String EMPTY_HTML = ""; // Anchors are inserted into the navigation so that the viewer can navigate to a selection. @@ -80,27 +82,18 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { * * @param nodeResults The analysis results data to display. */ - @NbBundle.Messages("AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score") void displayResults(NodeResults nodeResults) { Document document = Jsoup.parse(EMPTY_HTML); Element body = document.getElementsByTag("body").first(); - // if there is an aggregate score, append a section with the value - Optional aggregateScore = nodeResults.getAggregateScore(); - if (aggregateScore.isPresent()) { - appendSection(body, - MessageFormat.format("{0}: {1}", - Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(), - aggregateScore.get().getSignificance().getDisplayName()), - Optional.empty()); - } + Optional panelHeader = appendPanelHeader(body, nodeResults.getContent(), nodeResults.getAggregateScore()); // for each analysis result item, display the data. List displayAttributes = nodeResults.getAnalysisResults(); for (int idx = 0; idx < displayAttributes.size(); idx++) { AnalysisResultsViewModel.ResultDisplayAttributes resultAttrs = displayAttributes.get(idx); Element sectionDiv = appendResult(body, idx, resultAttrs); - if (idx > 0 || aggregateScore.isPresent()) { + if (idx > 0 || panelHeader.isPresent()) { sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); } } @@ -119,6 +112,48 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { } } + /** + * Appends the header to the panel. + * + * @param parent The parent html element. + * @param content The content whose name will be added if present. + * @param score The aggregate score whose significance will be added if + * present. + * + * @return The html element. + */ + @Messages({ + "AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score", + "AnalysisResultsContentPanel_content_displayKey=Item" + }) + private Optional appendPanelHeader(Element parent, Optional content, Optional score) { + if (!content.isPresent() || !score.isPresent()) { + return Optional.empty(); + } + + Element container = parent.appendElement("div"); + + // if there is content append the name + content.ifPresent((c) -> { + container.appendElement("p") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(MessageFormat.format("{0}: {1}", + Bundle.AnalysisResultsContentPanel_content_displayKey(), + c.getName())); + }); + + // if there is an aggregate score, append the value + score.ifPresent((s) -> { + container.appendElement("p") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(MessageFormat.format("{0}: {1}", + Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(), + s.getSignificance().getDisplayName())); + }); + + return Optional.ofNullable(container); + } + /** * Returns the anchor id to use with the analysis result (based on the id). * @@ -151,7 +186,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { // create a table Element table = sectionDiv.appendElement("table"); table.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); - + Element tableBody = table.appendElement("tbody"); // append a row for each item @@ -160,7 +195,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { String keyString = keyVal.getKey() == null ? "" : keyVal.getKey() + ":"; Element keyTd = row.appendElement("td") .attr("class", ContentViewerHtmlStyles.getTextClassName()); - + keyTd.appendElement("span") .text(keyString) .attr("class", ContentViewerHtmlStyles.getKeyColumnClassName()); @@ -170,7 +205,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { .text(valueString) .attr("class", ContentViewerHtmlStyles.getTextClassName()); } - + return sectionDiv; } @@ -199,7 +234,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { header = (anchorEl == null) ? sectionDiv.appendElement("h1") : anchorEl.appendElement("h1"); - + header.text(headerText); header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); header.attr("style", "display: inline-block"); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java index 8ba7308eb4..00cc170b14 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java @@ -94,6 +94,7 @@ public class AnalysisResultsViewModel { private final List analysisResults; private final Optional selectedResult; private final Optional aggregateScore; + private final Optional content; /** * Constructor. @@ -102,11 +103,13 @@ public class AnalysisResultsViewModel { * @param selectedResult The selected analysis result or empty if none * selected. * @param aggregateScore The aggregate score or empty if no score. + * @param content The content associated with these results. */ - NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore) { + NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore, Optional content) { this.analysisResults = analysisResults; this.selectedResult = selectedResult; this.aggregateScore = aggregateScore; + this.content = content; } /** @@ -135,6 +138,17 @@ public class AnalysisResultsViewModel { Optional getAggregateScore() { return aggregateScore; } + + /** + * Returns the content associated with these results or empty if not + * present. + * + * @return The content associated with these results or empty if not + * present. + */ + Optional getContent() { + return content; + } } /** @@ -221,10 +235,11 @@ public class AnalysisResultsViewModel { */ NodeResults getAnalysisResults(Node node) { if (node == null) { - return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty()); + return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty(), Optional.empty()); } Optional aggregateScore = Optional.empty(); + Optional nodeContent = Optional.empty(); // maps id of analysis result to analysis result to prevent duplication Map allAnalysisResults = new HashMap<>(); Optional selectedResult = Optional.empty(); @@ -236,6 +251,8 @@ public class AnalysisResultsViewModel { } try { + nodeContent = Optional.of(content); + // get the aggregate score of that content aggregateScore = Optional.ofNullable(content.getAggregateScore()); @@ -273,6 +290,6 @@ public class AnalysisResultsViewModel { // get view model representation List displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values()); - return new NodeResults(displayAttributes, selectedResult, aggregateScore); + return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent); } }