diff --git a/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java b/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java index 82f2b3bfc4..fcedf212b2 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java @@ -38,7 +38,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog; lazy=false ) @ActionReference(path = "Menu/Help", position = 1125) -@Messages("CTL_ShowIngestProgressSnapshotAction=Get Ingest Progress Snapshot") +@Messages("CTL_ShowIngestProgressSnapshotAction=Ingest Status Details") public final class ShowIngestProgressSnapshotAction extends SystemAction implements ActionListener { private static final String ACTION_NAME = NbBundle.getMessage(ShowIngestProgressSnapshotAction.class, "ShowIngestProgressSnapshotAction.actionName.text"); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 44ae49269c..8b0d0c9cc8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -37,6 +37,7 @@ import java.util.TimeZone; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; @@ -786,50 +787,17 @@ public class Case implements SleuthkitCase.ErrorObserver { public static PropertyChangeSupport getPropertyChangeSupport() { return pcs; } - - String getImagePaths(Long imgID) { - return getImagePaths(db).get(imgID); - } - - /** - * get all the image id in this case - * - * @return imageIDs - */ - public Long[] getImageIDs() { - Set ids = getImagePaths(db).keySet(); - hasData = (ids.size() > 0); - return ids.toArray(new Long[ids.size()]); - } - - public List getImages() throws TskCoreException { - List list = db.getImages(); - hasData = (list.size() > 0); - return list; - } - - /** - * Count the root objects. - * - * @return The number of total root objects in this case. - */ - public int getRootObjectsCount() { - return getRootObjects().size(); - } - + /** * Get the data model Content objects in the root of this case's hierarchy. * * @return a list of the root objects + * @throws org.sleuthkit.datamodel.TskCoreException */ - public List getRootObjects() { - try { - List list = db.getRootObjects(); - hasData = (list.size() > 0); - return list; - } catch (TskException ex) { - throw new RuntimeException(NbBundle.getMessage(this.getClass(), "Case.exception.errGetRootObj"), ex); - } + public List getDataSources() throws TskCoreException { + List list = db.getRootObjects(); + hasData = (list.size() > 0); + return list; } /** @@ -838,16 +806,17 @@ public class Case implements SleuthkitCase.ErrorObserver { * @return time zones the set of time zones */ public Set getTimeZone() { - Set timezones = new HashSet(); - for (Content c : getRootObjects()) { - try { - final Image image = c.getImage(); - if (image != null) { + Set timezones = new HashSet<>(); + try { + for (Content c : getDataSources()) { + final Content dataSource = c.getDataSource(); + if ((dataSource != null) && (dataSource instanceof Image)) { + Image image = (Image)dataSource; timezones.add(TimeZone.getTimeZone(image.getTimeZone())); } - } catch (TskException ex) { - logger.log(Level.INFO, "Error getting time zones", ex); //NON-NLS } + } catch (TskCoreException ex) { + logger.log(Level.INFO, "Error getting time zones", ex); //NON-NLS } return timezones; } @@ -1209,7 +1178,10 @@ public class Case implements SleuthkitCase.ErrorObserver { public boolean hasData() { // false is also the initial value, so make the DB trip if it is still false if (!hasData) { - hasData = (getRootObjectsCount() > 0); + try { + hasData = (getDataSources().size() > 0); + } catch (TskCoreException ex) { + } } return hasData; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java index a6a9e4f645..7254112e85 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java @@ -67,11 +67,9 @@ import org.sleuthkit.autopsy.coreutils.Logger; // get the information that needed Case currentCase = Case.getCurrentCase(); - String caseName = currentCase.getName(); String crDate = currentCase.getCreatedDate(); String caseDir = currentCase.getCaseDirectory(); - int totalImage = currentCase.getRootObjectsCount(); - + // put the image paths information into hashmap Map imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase()); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.form index d529361ded..961034106d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.form @@ -24,10 +24,9 @@ - - - - + + + @@ -43,17 +42,15 @@ - - - - - - + + + + + + - - - + @@ -61,7 +58,7 @@ - + @@ -70,18 +67,9 @@ - + - - - - - - - - - @@ -96,11 +84,11 @@ + - @@ -120,8 +108,8 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java index deecdb0b4f..2cbfe57e78 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java @@ -51,7 +51,7 @@ public class AboutWindowPanel extends JPanel implements HyperlinkListener { public AboutWindowPanel() { about = new ImageIcon(org.netbeans.core.startup.Splash.loadContent(true)); initComponents(); - jLabel1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + logoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); description.setText(org.openide.util.NbBundle.getMessage(AboutWindowPanel.class, "LBL_Description", new Object[]{getProductVersionValue(), getJavaValue(), getVMValue(), getOperatingSystemValue(), getEncodingValue(), getSystemLocaleValue(), getUserDirValue(), getSleuthKitVersionValue(), Version.getNetbeansBuild(), Version.getBuildType().toString()})); @@ -67,8 +67,7 @@ public class AboutWindowPanel extends JPanel implements HyperlinkListener { // //GEN-BEGIN:initComponents private void initComponents() { - jLabel1 = new javax.swing.JLabel(); - jPanel1 = new javax.swing.JPanel(); + logoLabel = new javax.swing.JLabel(); jScrollPane3 = new javax.swing.JScrollPane(); copyright = new javax.swing.JTextPane(); jScrollPane2 = new javax.swing.JScrollPane(); @@ -78,23 +77,20 @@ public class AboutWindowPanel extends JPanel implements HyperlinkListener { setBackground(new java.awt.Color(255, 255, 255)); - jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - jLabel1.setIcon(about); - jLabel1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - jLabel1.addMouseListener(new java.awt.event.MouseAdapter() { + logoLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + logoLabel.setIcon(about); + logoLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + logoLabel.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { - jLabel1MouseClicked(evt); + logoLabelMouseClicked(evt); } }); - jPanel1.setBackground(new java.awt.Color(255, 255, 255)); - jPanel1.setLayout(new java.awt.GridBagLayout()); - jScrollPane3.setBorder(null); - copyright.setBorder(null); - copyright.setContentType("text/html"); // NOI18N NON-NLS copyright.setEditable(false); + copyright.setBorder(null); + copyright.setContentType("text/html"); // NOI18N copyright.setText(org.openide.util.NbBundle.getBundle(AboutWindowPanel.class).getString("LBL_Copyright")); // NOI18N copyright.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { @@ -103,12 +99,12 @@ public class AboutWindowPanel extends JPanel implements HyperlinkListener { }); jScrollPane3.setViewportView(copyright); - description.setContentType("text/html"); // NOI18N NON-NLS description.setEditable(false); + description.setContentType("text/html"); // NOI18N jScrollPane2.setViewportView(description); verboseLoggingButton.setBackground(new java.awt.Color(255, 255, 255)); - verboseLoggingButton.setText(NbBundle.getMessage(this.getClass(), "AboutWindowPanel.actVerboseLogging.text")); + verboseLoggingButton.setText("Activate verbose logging"); verboseLoggingButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { activateVerboseLogging(evt); @@ -130,10 +126,9 @@ public class AboutWindowPanel extends JPanel implements HyperlinkListener { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) - .addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) - .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 486, Short.MAX_VALUE) + .addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 486, Short.MAX_VALUE) + .addComponent(logoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 486, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -145,15 +140,13 @@ public class AboutWindowPanel extends JPanel implements HyperlinkListener { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE) - .addGap(32, 32, 32) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 96, Short.MAX_VALUE) + .addComponent(logoLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 139, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, Short.MAX_VALUE) .addComponent(verboseLoggingButton) - .addGap(0, 0, 0) - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(jButton2) .addContainerGap()) @@ -168,7 +161,7 @@ private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS closeDialog(); }//GEN-LAST:event_jButton2ActionPerformed -private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabel1MouseClicked +private void logoLabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_logoLabelMouseClicked try { url = new URL(NbBundle.getMessage(AboutWindowPanel.class, "URL_ON_IMG")); // NOI18N showUrl(); @@ -176,7 +169,7 @@ private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:eve //ignore } url = null; -}//GEN-LAST:event_jLabel1MouseClicked +}//GEN-LAST:event_logoLabelMouseClicked private void activateVerboseLogging(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_activateVerboseLogging startVerboseLogging(); @@ -186,10 +179,9 @@ private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:eve private javax.swing.JTextPane copyright; private javax.swing.JTextPane description; private javax.swing.JButton jButton2; - private javax.swing.JLabel jLabel1; - private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JLabel logoLabel; private javax.swing.JButton verboseLoggingButton; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index e4a5090dbb..752627c572 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -24,7 +24,7 @@ DataContentViewerString.pageLabel2.text=Page # Product Information panel LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
Format_OperatingSystem_Value={0} version {1} running on {2} -LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.

Copyright © 2003-2013. For more information, please visit: http\://www.sleuthkit.org.
+LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2014.
URL_ON_IMG=http://www.sleuthkit.org/ LBL_Close=Close diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 03b8b30369..ab58a9c46b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -256,6 +256,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { boolean hasChildren = false; if (selectedNode != null) { + // @@@ This just did a DB round trip to get the count and the results were not saved... hasChildren = selectedNode.getChildren().getNodesCount() > 0; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index bce7717f6c..77ca0752fb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.datamodel; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children.Keys; import org.openide.nodes.Node; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.Directory; @@ -31,6 +33,7 @@ import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.SleuthkitItemVisitor; import org.sleuthkit.datamodel.SleuthkitVisitableItem; +import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.Volume; @@ -174,8 +177,8 @@ abstract class AbstractContentChildren extends Keys { @Override public AbstractNode visit(DataSources i) { try { - return new DataSourcesNode(i.getSleuthkitCase().getRootObjects()); - } catch (TskException ex) { + return new DataSourcesNode(Case.getCurrentCase().getDataSources()); + } catch (TskCoreException ex) { return defaultVisit(i); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index b413af0f35..dd7ddd0206 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -183,24 +183,24 @@ public class BlackboardArtifactNode extends DisplayableItemNode { sourcePath)); } } else { - String dataSource = ""; + String dataSourceStr = ""; try { - Image image = associated.getImage(); - if (image != null) { - dataSource = image.getName(); + Content dataSource = associated.getDataSource(); + if (dataSource != null) { + dataSourceStr = dataSource.getName(); } else { - dataSource = getRootParentName(); + dataSourceStr = getRootParentName(); } } catch (TskCoreException ex) { logger.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS } - if (dataSource.isEmpty() == false) { + if (dataSourceStr.isEmpty() == false) { ss.put(new NodeProperty<>( NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.name"), NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.displayName"), NO_DESCR, - dataSource)); + dataSourceStr)); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java index bfcd35ad5c..a4f6e80c51 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2014 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,11 +21,18 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.FileSystem; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.VolumeSystem; /** - * Class for Children of all ContentNodes. Handles creating child ContentNodes. + * Makes the children nodes / keys for a given content object. + * Has knowledge about the structure of the directory tree and what levels + * should be ignored. * TODO consider a ContentChildren child factory */ class ContentChildren extends AbstractContentChildren { @@ -33,12 +40,59 @@ class ContentChildren extends AbstractContentChildren { private static final Logger logger = Logger.getLogger(ContentChildren.class.getName()); //private static final int MAX_CHILD_COUNT = 1000000; - private Content parent; + private final Content parent; ContentChildren(Content parent) { super(); //initialize lazy behavior this.parent = parent; } + + /** + * Get the children of the Content object based on what we want to display. + * As an example, we don't display the direct children of VolumeSystems + * or FileSystems. We hide some of the levels in the tree. This method + * takes care of that and returns the children we want to display + * + * @param parent + * @return + */ + private static List getDisplayChildren(Content parent) { + // what does the content think its children are? + List tmpChildren; + try { + tmpChildren = parent.getChildren(); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error getting Content children.", ex); //NON-NLS + tmpChildren = Collections.emptyList(); + } + + // Cycle through the list and make a new one based + // on what we actually want to display. + List children = new ArrayList<>(); + for (Content c : tmpChildren) { + if (c instanceof VolumeSystem) { + children.addAll(getDisplayChildren(c)); + } else if (c instanceof FileSystem) { + children.addAll(getDisplayChildren(c)); + } else if (c instanceof Directory) { + Directory dir = (Directory) c; + /* For root directories, we want to return their contents. + * Special case though for '.' and '..' entries, because they should + * not have children (and in fact don't in the DB). Other drs + * get treated as files and added as is. */ + if ((dir.isRoot()) && (dir.getName().equals(".") == false) + && (dir.getName().equals("..") == false)) { + children.addAll(getDisplayChildren(dir)); + } else { + children.add(c); + } + } else { + children.add(c); + } + } + return children; + } + @Override protected void addNotify() { @@ -50,18 +104,10 @@ class ContentChildren extends AbstractContentChildren { //StopWatch s2 = new StopWatch(); //s2.start(); //logger.log(Level.INFO, "GETTING CHILDREN CONTENT for parent: " + parent.getName()); - List children = ContentHierarchyVisitor.getChildren(parent); + List children = getDisplayChildren(parent); //s2.stop(); //logger.log(Level.INFO, "GOT CHILDREN CONTENTS:" + children.size() + ", took: " + s2.getElapsedTime()); - // To not display LayoutFiles -// Iterator it = children.iterator(); -// while(it.hasNext()) { -// Content child = it.next(); -// if(child instanceof LayoutFile) { -// it.remove(); -// } -// } //limit number children //setKeys(children.subList(0, Math.min(children.size(), MAX_CHILD_COUNT))); @@ -73,6 +119,5 @@ class ContentChildren extends AbstractContentChildren { protected void removeNotify() { super.removeNotify(); setKeys(new ArrayList()); - } - + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentHierarchyVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentHierarchyVisitor.java deleted file mode 100644 index ac5c9adf6d..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentHierarchyVisitor.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 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.datamodel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentVisitor; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.FileSystem; -import org.sleuthkit.datamodel.VirtualDirectory; -import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.datamodel.VolumeSystem; - - -/** - * Returns all the children of a Content object, descending the hierarchy - * past subclasses that aren't part of the exposed hierarchy (VolumeSystem, - * FileSystem, and root Directories) - */ - class ContentHierarchyVisitor extends ContentVisitor.Default> { - private static final Logger logger = Logger.getLogger(ContentHierarchyVisitor.class.getName()); - private static final ContentHierarchyVisitor INSTANCE = new ContentHierarchyVisitor(); - - private ContentHierarchyVisitor() {} - - /** - * Get the child Content objects according the the exposed hierarchy. - * @param parent - * @return - */ - public static List getChildren(Content parent) { - List keys = new ArrayList(); - - List children; - - try { - children = parent.getChildren(); - } catch (TskException ex) { - logger.log(Level.WARNING, "Error getting Content children.", ex); //NON-NLS - children = Collections.emptyList(); - } - - for (Content c : children) { - keys.addAll(c.accept(INSTANCE)); - } - - return keys; - } - - @Override - protected List defaultVisit(Content c) { - return Collections.singletonList(c); - } - - @Override - public List visit(VolumeSystem vs) { - return getChildren(vs); - } - - @Override - public List visit(FileSystem fs) { - return getChildren(fs); - } - - @Override - public List visit(Directory dir) { - if (dir.isRoot()) { - return getChildren(dir); - } else { - return Collections.singletonList(dir); - } - } - - @Override - public List visit(VirtualDirectory ldir) { - //return getChildren(ldir); - return Collections.singletonList(ldir); - } -} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentIdHierarchyVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentIdHierarchyVisitor.java deleted file mode 100644 index 9a62c60c8f..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentIdHierarchyVisitor.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2012 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.datamodel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentVisitor; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.FileSystem; -import org.sleuthkit.datamodel.VirtualDirectory; -import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.datamodel.VolumeSystem; - - -/** - * Returns all the children Ids of a Content object, descending the hierarchy - * past subclasses that aren't part of the exposed hierarchy (VolumeSystem, - * FileSystem, and root Directories) - */ - class ContentIdHierarchyVisitor extends ContentVisitor.Default> { - private static final Logger logger = Logger.getLogger(ContentHierarchyVisitor.class.getName()); - private static final ContentIdHierarchyVisitor INSTANCE = new ContentIdHierarchyVisitor(); - - private ContentIdHierarchyVisitor() {} - - /** - * Get the child Content objects according the the exposed hierarchy. - * @param parent - * @return - */ - public static List getChildren(Content parent) { - List keys = new ArrayList(); - - List children; - - try { - children = parent.getChildren(); - } catch (TskException ex) { - logger.log(Level.WARNING, "Error getting Content children.", ex); //NON-NLS - children = Collections.emptyList(); - } - - for (Content c : children) { - keys.addAll(c.accept(INSTANCE)); - } - - return keys; - } - - @Override - protected List defaultVisit(Content c) { - return Collections.singletonList(c.getId()); - } - - @Override - public List visit(VolumeSystem vs) { - return getChildren(vs); - } - - @Override - public List visit(FileSystem fs) { - return getChildren(fs); - } - - @Override - public List visit(Directory dir) { - if (dir.isRoot()) { - return getChildren(dir); - } else { - return Collections.singletonList(dir.getId()); - } - } - - @Override - public List visit(VirtualDirectory ldir) { - //return getChildren(ldir); - return Collections.singletonList(ldir.getId()); - } -} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java index 059a6367d1..3223e29382 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java @@ -130,8 +130,9 @@ public final class ContentUtils { return TimeZone.getTimeZone("GMT"); } else { - final Image image = c.getImage(); - if (image != null) { + final Content dataSource = c.getDataSource(); + if ((dataSource != null) && (dataSource instanceof Image)) { + Image image = (Image)dataSource; return TimeZone.getTimeZone(image.getTimeZone()); } else { //case such as top level VirtualDirectory diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java index 41e92b3d92..53056d7039 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java @@ -18,25 +18,17 @@ */ package org.sleuthkit.autopsy.datamodel; -import org.sleuthkit.datamodel.SleuthkitCase; /** * Images nodes support */ public class DataSources implements AutopsyVisitableItem{ - private SleuthkitCase skCase; - - public DataSources(SleuthkitCase skCase) { - this.skCase = skCase; + public DataSources() { } @Override public T accept(AutopsyItemVisitor v) { return v.visit(this); } - - public SleuthkitCase getSleuthkitCase(){ - return skCase; - } } diff --git a/Core/src/org/sleuthkit/autopsy/diagnostics/Bundle.properties b/Core/src/org/sleuthkit/autopsy/diagnostics/Bundle.properties new file mode 100755 index 0000000000..eae8c24793 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/diagnostics/Bundle.properties @@ -0,0 +1,11 @@ +PerformancePanel.jLabel1.text=Image Reading: +PerformancePanel.jLabel2.text=Database Reading: +PerformancePanel.jLabel3.text=CPU: +PerformancePanel.imgReadLabel.text=\ +PerformancePanel.dbReadLabel.text=\ +PerformancePanel.cpuTimeLabel.text=\ +PerformancePanel.startButton.text=Start +PerformancePanel.statusLabel.text=\ +PerformancePanel.jLabel4.text=File Reading: +PerformancePanel.fileReadLabel.text=\ +PerformancePanel.jLabel5.text=This panel performs a series of tests to help identify bottlenecks in the system. diff --git a/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanel.form b/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanel.form new file mode 100755 index 0000000000..7d0049cd82 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanel.form @@ -0,0 +1,184 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanel.java b/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanel.java new file mode 100755 index 0000000000..17d34d72eb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanel.java @@ -0,0 +1,504 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.sleuthkit.autopsy.diagnostics; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ExecutionException; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.openide.util.Exceptions; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +public class PerformancePanel extends javax.swing.JDialog { + + /** + * Creates new form PerformancePanel + */ + public PerformancePanel() { + super((JFrame) WindowManager.getDefault().getMainWindow(), "Performance Diagnostics", true); + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + imgReadLabel = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + dbReadLabel = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + fileReadLabel = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + cpuTimeLabel = new javax.swing.JLabel(); + startButton = new javax.swing.JButton(); + statusLabel = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(imgReadLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.imgReadLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(dbReadLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.dbReadLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel4.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(fileReadLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.fileReadLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(cpuTimeLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.cpuTimeLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(startButton, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.startButton.text")); // NOI18N + startButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + startButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(statusLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.statusLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel5.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(jLabel2) + .addComponent(jLabel3)) + .addGap(31, 31, 31) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(fileReadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(dbReadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 237, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(cpuTimeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 284, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(imgReadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 237, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel4) + .addGap(0, 0, Short.MAX_VALUE)))) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(startButton) + .addComponent(jLabel5)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(statusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 508, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(cpuTimeLabel)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(imgReadLabel) + .addComponent(jLabel1)) + .addGap(19, 19, 19) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(fileReadLabel)) + .addGap(21, 21, 21) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(dbReadLabel)) + .addGap(18, 18, 18) + .addComponent(statusLabel) + .addGap(9, 9, 9) + .addComponent(startButton) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed + // TODO add your handling code here: + startButton.setEnabled(false); + SwingWorker worker = new PerformanceTestWorker(); + worker.execute(); + + }//GEN-LAST:event_startButtonActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel cpuTimeLabel; + private javax.swing.JLabel dbReadLabel; + private javax.swing.JLabel fileReadLabel; + private javax.swing.JLabel imgReadLabel; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JButton startButton; + private javax.swing.JLabel statusLabel; + // End of variables declaration//GEN-END:variables + + class PerformanceTestWorker extends SwingWorker { + private long cpuStats; + private long imgReadStats; + private long dbStats; + private long fileReadStats; + + @Override + protected Object doInBackground() throws Exception { + setCpuLabel(""); + setImgLabel(""); + setDbLabel(""); + setFileReadLabel(""); + + doCpuTest(); + doImgTest(); + doFileReadTest(); + doDbTest(); + + return null; + } + + private void setCpuLabel(final String msg) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + cpuTimeLabel.setText(msg); + } + }); + } + + private void setImgLabel(final String msg) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + imgReadLabel.setText(msg); + } + }); + } + + private void setFileReadLabel(final String msg) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + fileReadLabel.setText(msg); + } + }); + } + + private void setDbLabel(final String msg) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + dbReadLabel.setText(msg); + } + }); + } + + private void setStatusMsg(final String msg) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + statusLabel.setText(msg); + } + }); + } + + + private void doCpuTest() { + final String msg = "Running CPU Test"; + + MessageDigest md; + long start = new Date().getTime(); + try { + md = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException ex) { + setCpuLabel("MD5 Algo not found"); + return; + } + + byte[] buf = new byte[256 * 1024]; + long bytesRead = 0; + for (int a = 0; a < 50; a++) { + if (a % 10 == 0) + setStatusMsg(msg + " " + a * 100 / 50 + "%"); + for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) { + Arrays.fill(buf, b); + md.update(buf); + bytesRead += buf.length; + } + } + md.digest(); + + long end = new Date().getTime(); + cpuStats = (bytesRead / (1024 * 1024)) / ((end - start) / 1000); + + setCpuLabel(cpuStats + " MB hashed / sec"); + setStatusMsg(""); + } + + private void doImgTest() { + imgReadStats = 0; + setStatusMsg("Running Image Reading Test"); + + Case curCase; + try { + curCase = Case.getCurrentCase(); + } + catch (Exception e) { + setImgLabel("Case Not Open"); + setStatusMsg(""); + return; + } + + List dataSources; + try { + dataSources = curCase.getDataSources(); + } catch (TskCoreException ex) { + setImgLabel("No Images In Case"); + setStatusMsg(""); + return; + } + Image image = null; + for (Content c : dataSources) { + if (c instanceof Image) { + image = (Image)c; + } + } + if (image == null) { + setImgLabel("No Images In Case"); + setStatusMsg(""); + return; + } + + long start = new Date().getTime(); + + byte[] buf = new byte[4096]; + long bytesRead = 0; + + // random starting point to prevent caching from effecting it + Random rand = new Random(); + long curOffset = rand.nextLong(); + if (curOffset < 0) { + curOffset *= -1; + } + curOffset = curOffset % (image.getSize() / 2); + curOffset = 512 * ((curOffset + 511) / 512); + + //long curOffset = 0; + while (bytesRead < 1000 * 1024 * 1024 ) { + long read; + try { + read = image.read(buf, curOffset, buf.length); + } catch (TskCoreException ex) { + break; + } + if (read <= 0) + break; + bytesRead += read; + curOffset += read; + } + long end = new Date().getTime(); + long elapsed = (end - start) / 1000; + if (elapsed > 0) + imgReadStats = (bytesRead / (1024 * 1024)) / elapsed; + else + imgReadStats = 0; + setImgLabel(imgReadStats + " MB read / sec (" + bytesRead + ")"); + setStatusMsg(""); + } + + private void doFileReadTest() { + fileReadStats = 0; + + if (true) { + setFileReadLabel("Skipped"); + } + + setStatusMsg("Running File Reading Test"); + + Case curCase; + try { + curCase = Case.getCurrentCase(); + } + catch (Exception e) { + setFileReadLabel("Case Not Open"); + setStatusMsg(""); + return; + } + + List dataSources; + try { + dataSources = curCase.getDataSources(); + } catch (TskCoreException ex) { + setFileReadLabel("No Images In Case"); + setStatusMsg(""); + return; + } + Image image = null; + for (Content c : dataSources) { + if (c instanceof Image) { + image = (Image)c; + } + } + if (image == null) { + setFileReadLabel("No Images In Case"); + setStatusMsg(""); + return; + } + + File file = new File(image.getPaths()[0]); + if (file.exists() == false) { + setFileReadLabel("Image Path Doesn't Exist"); + setStatusMsg(""); + return; + } + + FileReader fileReader; + try { + fileReader = new FileReader(file); + } catch (FileNotFoundException ex) { + setFileReadLabel("Error making file reader"); + setStatusMsg(""); + return; + } + + long start = new Date().getTime(); + // random starting point to prevent caching from effecting it + // make RandomAccessFile instad + /*Random rand = new Random(); + long curOffset = rand.nextLong(); + if (curOffset < 0) { + curOffset *= -1; + } + curOffset = curOffset % (file.length()); + curOffset = 512 * ((curOffset + 511) / 512); + try { + fileReader.skip(curOffset); + } catch (IOException ex) { + setFileReadLabel("Error seeking: " + curOffset); + return; + }*/ + + char[] buf = new char[4096]; + int bytesRead = 0; + while (bytesRead < 1000 * 1024 * 1024 ) { + long read; + try { + read = fileReader.read(buf, 0, buf.length); + } catch (IOException ex) { + break; + } + if (read <= 0) + break; + bytesRead += read; + } + long end = new Date().getTime(); + long elapsed = (end - start) / 1000; + if (elapsed > 0) + fileReadStats = (bytesRead / (1024 * 1024)) / elapsed; + else + fileReadStats = 0; + setFileReadLabel(fileReadStats + " MB read / sec (" + bytesRead + ")"); + setStatusMsg(""); + } + + private void doDbTest() { + dbStats = 0; + setStatusMsg("Running DB Test"); + + Case curCase; + try { + curCase = Case.getCurrentCase(); + } + catch (Exception e) { + setDbLabel("Case Not Open"); + return; + } + + try { + SleuthkitCase tskCase = curCase.getSleuthkitCase(); + long start = new Date().getTime(); + + List files = tskCase.findAllFilesWhere("obj_id < 50000"); + + long end = new Date().getTime(); + long elapsed = (end - start) / 1000; + if (elapsed > 0) + dbStats = files.size() / elapsed; + else + dbStats = 0; + + setDbLabel(dbStats + " records / sec"); + } catch (TskCoreException ex) { + setDbLabel("Error Performing Query"); + } + + setStatusMsg(""); + } + + @Override + protected void done() { + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + setStatusMsg("Error: " + ex.getMessage()); + } + startButton.setEnabled(true); + } + } +} + diff --git a/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanelAction.java b/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanelAction.java new file mode 100755 index 0000000000..0f962e6abf --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/diagnostics/PerformancePanelAction.java @@ -0,0 +1,46 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sleuthkit.autopsy.diagnostics; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JDialog; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; +import org.openide.util.NbBundle.Messages; + +@ActionID( + category = "Help", + id = "org.sleuthkit.autopsy.diagnostics.PerformancePanelAction" +) +@ActionRegistration( + displayName = "#CTL_PerformancePanelAction" +) +@ActionReference(path = "Menu/Help", position = 1437) +@Messages("CTL_PerformancePanelAction=Performance Diagnostics") +public final class PerformancePanelAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + JDialog dialog = new PerformancePanel(); + dialog.setVisible(true); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 06a733046e..c9b6aaf4f1 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -356,7 +356,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat // if there's at least one image, load the image and open the top component List items = new ArrayList<>(); final SleuthkitCase tskCase = currentCase.getSleuthkitCase(); - items.add(new DataSources(tskCase)); + items.add(new DataSources()); items.add(new Views(tskCase)); items.add(new Results(tskCase)); items.add(new Reports()); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java index e8aa3ede8d..c8a9f25c12 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java @@ -511,8 +511,8 @@ import org.sleuthkit.datamodel.VolumeSystem; */ UnallocStruct(Volume volu) { try { - this.ImageName = volu.getImage().getName(); - this.ImageId = volu.getImage().getId(); + this.ImageName = volu.getDataSource().getName(); + this.ImageId = volu.getDataSource().getId(); this.VolumeId = volu.getId(); } catch (TskCoreException tce) { logger.log(Level.WARNING, "Unable to properly create ExtractUnallocAction, extraction may be incomplete", tce); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/examples/SampleExecutableDataSourceIngestModule.java b/Core/src/org/sleuthkit/autopsy/examples/SampleExecutableDataSourceIngestModule.java index 507071b9d1..83641fbb93 100755 --- a/Core/src/org/sleuthkit/autopsy/examples/SampleExecutableDataSourceIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/examples/SampleExecutableDataSourceIngestModule.java @@ -60,6 +60,7 @@ import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.TskCoreException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -111,9 +112,16 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM String resultsFilePath = outputDirPath + File.separator + String.format("job_%d_results.xml", jobId); boolean haveRealExecutable = false; if (haveRealExecutable) { - String dataSourcePath = dataSource.getImage().getPaths()[0]; - ExecUtil executor = new ExecUtil(); - executor.execute("some.exe", dataSourcePath, resultsFilePath); + if (dataSource instanceof Image) { + Image image = (Image)dataSource; + String dataSourcePath = image.getPaths()[0]; + ExecUtil executor = new ExecUtil(); + executor.execute("some.exe", dataSourcePath, resultsFilePath); + } + // not a disk image + else { + return ProcessResult.OK; + } } else { generateSimulatedResults(resultsFilePath); } @@ -129,7 +137,7 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM IngestServices.getInstance().postMessage(IngestMessage.createErrorMessage(moduleName, "External Results Import Error", errorInfo.getMessage())); } progressBar.progress(2); - } catch (TskCoreException | InterruptedException | ParserConfigurationException | TransformerException | IOException ex) { + } catch (InterruptedException | ParserConfigurationException | TransformerException | IOException ex) { Logger logger = IngestServices.getInstance().getLogger(moduleName); logger.log(Level.SEVERE, "Failed to simulate analysis and results import", ex); //NON-NLS return ProcessResult.ERROR; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index 3096ff295b..35a82cda81 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -75,9 +75,8 @@ IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=Activity IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=File IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=Start Time IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=Elapsed Time (H\:M\:S) -IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text=Files/Sec: {0} IngestManager.IngestThreadActivitySnapshot.idleThread=IDLE IngestManager.IngestMessage.ErrorMessageLimitReached.subject=Maximum Errors Posted IngestManager.IngestMessage.ErrorMessageLimitReached.msg=Maximum number ({0}) of error and/or warning messages posted. See log for additional errors/warnings (Help -> Open Log Folder). IngestManager.IngestMessage.ErrorMessageLimitReached.title=Ingest Manager -IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=Found module named {0}, duplicating the name of another module, module will not be used. \ No newline at end of file +IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=Found module named {0}, duplicating the name of another module, module will not be used. diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index 4e0a84daf0..ba943a0b71 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -1,78 +1,77 @@ -CTL_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8 -HINT_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8\u30A6\u30A3\u30F3\u30C9\u30A6 -IngestDialog.closeButton.title=\u9589\u3058\u308B -IngestDialog.startButton.title=\u30B9\u30BF\u30FC\u30C8 -IngestDialog.title.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB -IngestJob.progress.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -IngestJob.progress.dataSourceIngest.displayName={1}\u306E{0} -IngestJob.progress.fileIngest.displayName={0}\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u89E3\u6790\u4E2D -IngestJobConfigurationPanel.advancedButton.actionCommand=\u30A2\u30C9\u30D0\u30F3\u30B9 -IngestJobConfigurationPanel.advancedButton.text=\u30A2\u30C9\u30D0\u30F3\u30B9 -IngestJobConfigurationPanel.processUnallocCheckbox.text=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u51E6\u7406 -IngestJobConfigurationPanel.processUnallocCheckbox.toolTipText=\u524A\u9664\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u7B49\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u3092\u51E6\u7406\u3002\u3088\u308A\u5B8C\u5168\u306A\u7D50\u679C\u304C\u51FA\u307E\u3059\u304C\u3001\u5927\u304D\u3044\u30A4\u30E1\u30FC\u30B8\u3067\u306F\u51E6\u7406\u6642\u9593\u304C\u9577\u304F\u306A\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestManager.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestManager.StartIngestJobsTask.run.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -IngestManager.StartIngestJobsTask.run.displayName=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u958B\u59CB\u4E2D -IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30BD\u30FC\u30B9\u3001\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u3001\u8A73\u7D30\u304A\u3088\u3073\u30C7\u30FC\u30BF\u306F\u30CC\u30EB\u3067\u3042\u3063\u3066\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.exception.srcSubjNotNull.msg=\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u3042\u3063\u3066\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.exception.typeSrcSubjNotNull.msg=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7\u3001\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u3042\u3063\u3066\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.toString.data.text=\ \u30C7\u30FC\u30BF\uFF1A{0} -IngestMessage.toString.date.text=\ \u65E5\u4ED8\uFF1A{0} -IngestMessage.toString.details.text=\ \u8A73\u7D30\uFF1A{0} -IngestMessage.toString.subject.text=\ \u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\uFF1A{0} -IngestMessage.toString.type.text=\u30BF\u30A4\u30D7\uFF1A{0} -IngestMessageDetailsPanel.copyMenuItem.text=\u30B3\u30D4\u30FC -IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30C6\u30AD\u30B9\u30C8\uFF0Fhtml -IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E -IngestMessageDetailsPanel.viewArtifactButton.text=\u7D50\u679C\u3078\u79FB\u52D5 -IngestMessageDetailsPanel.viewContentButton.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3078\u79FB\u52D5 -IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30D6\u30FC\u30EB\u5024\u3067\u306F\u306A\u3044\u3082\u306E\u306BBooleanRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002 -IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65E5\u4ED8\u3067\u306F\u306A\u3044\u3082\u306E\u306BDateRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002 -IngestMessagePanel.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestMessagePanel.MsgTableMod.colNames.module=\u30E2\u30B8\u30E5\u30FC\u30EB -IngestMessagePanel.MsgTableMod.colNames.new=\u65B0\u898F\uFF1F -IngestMessagePanel.MsgTableMod.colNames.num=\u756A\u53F7 -IngestMessagePanel.MsgTableMod.colNames.subject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 -IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7 -IngestMessagePanel.sortByComboBox.model.priority=\u512A\u5148\u5EA6 +CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8 +HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6 +IngestDialog.closeButton.title=\u9589\u3058\u308b +IngestDialog.startButton.title=\u30b9\u30bf\u30fc\u30c8 +IngestDialog.title.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb +IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0} +IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d +IngestJobConfigurationPanel.advancedButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9 +IngestJobConfigurationPanel.advancedButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9 +IngestJobConfigurationPanel.processUnallocCheckbox.text=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u306e\u51e6\u7406 +IngestJobConfigurationPanel.processUnallocCheckbox.toolTipText=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u7b49\u306e\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u51e6\u7406\u3002\u3088\u308a\u5b8c\u5168\u306a\u7d50\u679c\u304c\u51fa\u307e\u3059\u304c\u3001\u5927\u304d\u3044\u30a4\u30e1\u30fc\u30b8\u3067\u306f\u51e6\u7406\u6642\u9593\u304c\u9577\u304f\u306a\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3067\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestManager.StartIngestJobsTask.run.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestManager.StartIngestJobsTask.run.displayName=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u958b\u59cb\u4e2d +IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30bd\u30fc\u30b9\u3001\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u3001\u8a73\u7d30\u304a\u3088\u3073\u30c7\u30fc\u30bf\u306f\u30cc\u30eb\u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.exception.srcSubjNotNull.msg=\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.exception.typeSrcSubjNotNull.msg=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u3001\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.toString.data.text=\ \u30c7\u30fc\u30bf\uff1a{0} +IngestMessage.toString.date.text=\ \u65e5\u4ed8\uff1a{0} +IngestMessage.toString.details.text=\ \u8a73\u7d30\uff1a{0} +IngestMessage.toString.subject.text=\ \u30b5\u30d6\u30b8\u30a7\u30af\u30c8\uff1a{0} +IngestMessage.toString.type.text=\u30bf\u30a4\u30d7\uff1a{0} +IngestMessageDetailsPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30c6\u30ad\u30b9\u30c8\uff0fhtml +IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +IngestMessageDetailsPanel.viewArtifactButton.text=\u7d50\u679c\u3078\u79fb\u52d5 +IngestMessageDetailsPanel.viewContentButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u79fb\u52d5 +IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30d6\u30fc\u30eb\u5024\u3067\u306f\u306a\u3044\u3082\u306e\u306bBooleanRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002 +IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65e5\u4ed8\u3067\u306f\u306a\u3044\u3082\u306e\u306bDateRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002 +IngestMessagePanel.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3067\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestMessagePanel.MsgTableMod.colNames.module=\u30e2\u30b8\u30e5\u30fc\u30eb +IngestMessagePanel.MsgTableMod.colNames.new=\u65b0\u898f\uff1f +IngestMessagePanel.MsgTableMod.colNames.num=\u756a\u53f7 +IngestMessagePanel.MsgTableMod.colNames.subject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8 +IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7 +IngestMessagePanel.sortByComboBox.model.priority=\u512a\u5148\u5ea6 IngestMessagePanel.sortByComboBox.model.time=\u6642\u9593 -IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uFF08\u6642\u7CFB\u5217\uFF09\u307E\u305F\u306F\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u512A\u5148\u5EA6\u3067\u30BD\u30FC\u30C8 -IngestMessagePanel.sortByLabel.text=\u4E0B\u8A18\u3067\u30BD\u30FC\u30C8\uFF1A -IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8A08\uFF1A +IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uff08\u6642\u7cfb\u5217\uff09\u307e\u305f\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u512a\u5148\u5ea6\u3067\u30bd\u30fc\u30c8 +IngestMessagePanel.sortByLabel.text=\u4e0b\u8a18\u3067\u30bd\u30fc\u30c8\uff1a +IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8a08\uff1a IngestMessagePanel.totalMessagesNameVal.text=- -IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30E6\u30CB\u30FC\u30AF\uFF1A +IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30e6\u30cb\u30fc\u30af\uff1a IngestMessagePanel.totalUniqueMessagesNameVal.text=- -IngestMessagesToolbar.customizeButton.toolTipText=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E1\u30C3\u30BB\u30FC\u30B8 -IngestMessageTopComponent.displayName=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9 -IngestMessageTopComponent.displayReport.option.GenRpt=\u30EC\u30DD\u30FC\u30C8\u751F\u6210 +IngestMessagesToolbar.customizeButton.toolTipText=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8 +IngestMessageTopComponent.displayName=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9 +IngestMessageTopComponent.displayReport.option.GenRpt=\u30ec\u30dd\u30fc\u30c8\u751f\u6210 IngestMessageTopComponent.displayReport.option.OK=OK -IngestMessageTopComponent.initComponents.name=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9 -IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30EC\u30DD\u30FC\u30C8 -IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30C7\u30A3\u30B9\u30AF{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3\u306E\u305F\u3081\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3059\u3002\n\u30B1\u30FC\u30B9\u30C9\u30E9\u30A4\u30D6\u306B\u6700\u4F4E1GB\u306E\u7A7A\u304D\u9818\u57DF\u304C\u3042\u308B\u306E\u3092\u78BA\u8A8D\u3057\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u30B9\u30BF\u30FC\u30C8\u3057\u3066\u4E0B\u3055\u3044\u3002 -IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u4E2D\u6B62\u3055\u308C\u307E\u3057\u305F\u30FC{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3 -OpenIDE-Module-Name=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30A8\u30E9\u30FC\uFF1A\n{0} -IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\uFF11\u3064\u307E\u305F\u306F\u8907\u6570\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30B9\u30BF\u30FC\u30C8\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u306F\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002 -IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305F\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u7121\u52B9\u5316\u3059\u308B\u304B\u30A8\u30E9\u30FC\u3092\u89E3\u6C7A\u3057\u3001\u305D\u306E\u5F8C\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u53F3\u30AF\u30EA\u30C3\u30AF\u3057\u3001\n\u300C\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u5B9F\u884C\u300D\u3092\u9078\u629E\u3057\u3066\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30EA\u30B9\u30BF\u30FC\u30C8\u3057\u3066\u4E0B\u3055\u3044\u3002 -IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u5931\u6557 -IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u8A2D\u5B9A\u30D5\u30A9\u30EB\u30C0\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3002 -IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u521D\u671F\u5316\u306E\u5931\u6557 -IngestJobConfigurator.saveJobSettings.usermsg={0}\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -IngestJobConfigurator.saveJobSettings.usermsg.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A -IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89E3\u6790\u4E2D -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7D4C\u904E\u6642\u9593\uFF08\u6642\uFF1A\u5206\uFF1A\u79D2\uFF09 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30D5\u30A1\u30A4\u30EB -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958B\u59CB\u6642\u9593 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30B9\u30EC\u30C3\u30C9ID -IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306E\u30A8\u30E9\u30FC\u304A\u3088\u3073\u307E\u305F\u306F\u8B66\u544A\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F\u3002\u3055\u3089\u306A\u308B\u30A8\u30E9\u30FC\uFF0F\u8B66\u544A\u306F\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\uFF08\u30D8\u30EB\u30D7->\u30ED\u30B0\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u958B\u304F\uFF09 -IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306E\u30A8\u30E9\u30FC\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F -IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30DE\u30CD\u30B8\u30E3\u30FC -IngestManager.IngestThreadActivitySnapshot.idleThread=\u30A2\u30A4\u30C9\u30EB -IngestProgressSnapshotDialog.title.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30D7\u30ED\u30B0\u30EC\u30B9\u30FB\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8 -IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308B -IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text=\u30D5\u30A1\u30A4\u30EB\uFF0F\u79D2\uFF1A{0} -IngestProgressSnapshotPanel.refreshButton.text=\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3 +IngestMessageTopComponent.initComponents.name=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9 +IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30ec\u30dd\u30fc\u30c8 +IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30c7\u30a3\u30b9\u30af{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3\u306e\u305f\u3081\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u4e2d\u6b62\u3057\u307e\u3059\u3002\n\u30b1\u30fc\u30b9\u30c9\u30e9\u30a4\u30d6\u306b\u6700\u4f4e1GB\u306e\u7a7a\u304d\u9818\u57df\u304c\u3042\u308b\u306e\u3092\u78ba\u8a8d\u3057\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u30b9\u30bf\u30fc\u30c8\u3057\u3066\u4e0b\u3055\u3044\u3002 +IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u4e2d\u6b62\u3055\u308c\u307e\u3057\u305f\u30fc{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3 +OpenIDE-Module-Name=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30a8\u30e9\u30fc\uff1a\n{0} +IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\uff11\u3064\u307e\u305f\u306f\u8907\u6570\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30b9\u30bf\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002 +IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305f\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u7121\u52b9\u5316\u3059\u308b\u304b\u30a8\u30e9\u30fc\u3092\u89e3\u6c7a\u3057\u3001\u305d\u306e\u5f8c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001\n\u300c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u5b9f\u884c\u300d\u3092\u9078\u629e\u3057\u3066\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ea\u30b9\u30bf\u30fc\u30c8\u3057\u3066\u4e0b\u3055\u3044\u3002 +IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5931\u6557 +IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u8a2d\u5b9a\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 +IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u521d\u671f\u5316\u306e\u5931\u6557 +IngestJobConfigurator.saveJobSettings.usermsg={0}\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +IngestJobConfigurator.saveJobSettings.usermsg.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a +IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89e3\u6790\u4e2d +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7d4c\u904e\u6642\u9593\uff08\u6642\uff1a\u5206\uff1a\u79d2\uff09 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30d5\u30a1\u30a4\u30eb +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958b\u59cb\u6642\u9593 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30b9\u30ec\u30c3\u30c9ID +IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306e\u30a8\u30e9\u30fc\u304a\u3088\u3073\u307e\u305f\u306f\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f\u3002\u3055\u3089\u306a\u308b\u30a8\u30e9\u30fc\uff0f\u8b66\u544a\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\uff08\u30d8\u30eb\u30d7->\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u304f\uff09 +IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306e\u30a8\u30e9\u30fc\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f +IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30de\u30cd\u30b8\u30e3\u30fc +IngestManager.IngestThreadActivitySnapshot.idleThread=\u30a2\u30a4\u30c9\u30eb +IngestProgressSnapshotDialog.title.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30b0\u30ec\u30b9\u30fb\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 +IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308b +IngestProgressSnapshotPanel.refreshButton.text=\u30ea\u30d5\u30ec\u30c3\u30b7\u30e5 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java index 2752646947..aec0d9042f 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java @@ -27,14 +27,14 @@ import org.openide.util.NbBundle; import org.sleuthkit.datamodel.Content; /** - * A data source ingest pipeline composed of a sequence of data source ingest - * modules constructed from ingest module templates. + * This class manages a sequence of data source ingest modules. It starts them, + * shuts them down, and runs them in sequential order. */ final class DataSourceIngestPipeline { private static final IngestManager ingestManager = IngestManager.getInstance(); private final IngestJobContext context; - private List modules = new ArrayList<>(); + private final List modules = new ArrayList<>(); DataSourceIngestPipeline(IngestJobContext context, List moduleTemplates) { this.context = context; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java index 573cf96a06..02dd61b7c7 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java @@ -23,8 +23,8 @@ import java.util.List; import org.sleuthkit.datamodel.AbstractFile; /** - * A file ingest pipeline composed of a sequence of file ingest modules - * constructed from ingest module templates. + * This class manages a sequence of file ingest modules. It starts them, + * shuts them down, and runs a file through them. */ final class FileIngestPipeline { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java index f885b5c171..5b4d9f388d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.ingest; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; @@ -45,15 +46,20 @@ final class IngestJob { private final LinkedBlockingQueue fileIngestPipelines = new LinkedBlockingQueue<>(); private long estimatedFilesToProcess = 0L; // Guarded by this private long processedFiles = 0L; // Guarded by this + // Contains names of files that are being run. Used to keep progress bar up to date. + private final List filesInProgress = new ArrayList<>(); // Guarded by this. private DataSourceIngestPipeline dataSourceIngestPipeline; private ProgressHandle dataSourceIngestProgress; private ProgressHandle fileIngestProgress; private volatile boolean cancelled = false; + private long startTime; + IngestJob(long id, Content dataSource, boolean processUnallocatedSpace) { this.id = id; this.dataSource = dataSource; this.processUnallocatedSpace = processUnallocatedSpace; + startTime = new Date().getTime(); } long getId() { @@ -139,20 +145,14 @@ final class IngestJob { dataSourceIngestProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override public boolean cancel() { - if (dataSourceIngestProgress != null) { - dataSourceIngestProgress.setDisplayName( - NbBundle.getMessage(this.getClass(), - "IngestJob.progress.cancelling", - displayName)); - } - IngestScheduler.getInstance().cancelIngestJob(IngestJob.this); + handleCancelFromProgressBar(); return true; } }); dataSourceIngestProgress.start(); dataSourceIngestProgress.switchToIndeterminate(); } - + private void startFileIngestProgressBar() { final String displayName = NbBundle.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", @@ -160,12 +160,7 @@ final class IngestJob { fileIngestProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override public boolean cancel() { - if (fileIngestProgress != null) { - fileIngestProgress.setDisplayName( - NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling", - displayName)); - } - IngestScheduler.getInstance().cancelIngestJob(IngestJob.this); + handleCancelFromProgressBar(); return true; } }); @@ -173,6 +168,34 @@ final class IngestJob { fileIngestProgress.start(); fileIngestProgress.switchToDeterminate((int) estimatedFilesToProcess); } + + /** + * Common steps to cancel a job, regardless of what progress bar was + * used to cancel the job. + */ + private void handleCancelFromProgressBar() { + cancel(); + + if (fileIngestProgress != null) { + final String displayName = NbBundle.getMessage(this.getClass(), + "IngestJob.progress.fileIngest.displayName", + dataSource.getName()); + fileIngestProgress.setDisplayName( + NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling", + displayName)); + } + + if (dataSourceIngestProgress != null) { + final String displayName = NbBundle.getMessage(this.getClass(), + "IngestJob.progress.dataSourceIngest.initialDisplayName", + dataSource.getName()); + dataSourceIngestProgress.setDisplayName( + NbBundle.getMessage(this.getClass(), + "IngestJob.progress.cancelling", + displayName)); + } + IngestScheduler.getInstance().cancelIngestJob(IngestJob.this); + } /** * Check to see if the job has a data source ingest pipeline. @@ -192,6 +215,11 @@ final class IngestJob { return (fileIngestPipelines.peek().isEmpty() == false); } + /** + * Executes the data source ingest module pipeline for the data source in the task + * @param task + * @throws InterruptedException + */ void process(DataSourceIngestTask task) throws InterruptedException { try { if (!isCancelled() && !dataSourceIngestPipeline.isEmpty()) { @@ -201,6 +229,8 @@ final class IngestJob { logIngestModuleErrors(errors); } } + + // all data source ingest jobs are done for this task, so shut down progress bar if (null != dataSourceIngestProgress) { dataSourceIngestProgress.finish(); // This is safe because this method will be called at most once per @@ -215,6 +245,12 @@ final class IngestJob { } } + + /** + * Executes the file ingest module pipeline for the file in the task + * @param task + * @throws InterruptedException + */ void process(FileIngestTask task) throws InterruptedException { try { if (!isCancelled()) { @@ -228,12 +264,25 @@ final class IngestJob { } else { fileIngestProgress.progress(file.getName(), (int) estimatedFilesToProcess); } + filesInProgress.add(file.getName()); } + List errors = new ArrayList<>(); errors.addAll(pipeline.process(task)); if (!errors.isEmpty()) { logIngestModuleErrors(errors); } + + // update the progress bar in case this file was being displayed + synchronized (this) { + filesInProgress.remove(file.getName()); + if (filesInProgress.size() > 0) { + fileIngestProgress.progress(filesInProgress.get(0)); + } + else { + fileIngestProgress.progress(""); + } + } } fileIngestPipelines.put(pipeline); } @@ -243,6 +292,10 @@ final class IngestJob { } } + /** + * Shutdown pipelines and progress bars + * + */ void finish() { List errors = new ArrayList<>(); while (!fileIngestPipelines.isEmpty()) { @@ -252,9 +305,13 @@ final class IngestJob { if (!errors.isEmpty()) { logIngestModuleErrors(errors); } + + // NOTE: Nothing to do for datasource ingest modules -- no shutdown method + if (dataSourceIngestProgress != null) { dataSourceIngestProgress.finish(); - } + } + if (fileIngestProgress != null) { fileIngestProgress.finish(); } @@ -273,4 +330,63 @@ final class IngestJob { void cancel() { cancelled = true; } + + /** + * Stores basic info for a given ingest job. + */ + class IngestJobStats { + private final long startTime; + private final long processedFiles; + private final long estimatedFilesToProcess; + private final long snapShotTime; + + IngestJobStats () { + synchronized (IngestJob.this) { + this.startTime = IngestJob.this.startTime; + this.processedFiles = IngestJob.this.processedFiles; + this.estimatedFilesToProcess = IngestJob.this.estimatedFilesToProcess; + snapShotTime = new Date().getTime(); + } + } + + /** + * Get files per second throughput since job started + * @return + */ + double getSpeed() { + return (double)processedFiles / ((snapShotTime - startTime)/1000); + } + + long getStartTime() { + return startTime; + } + + /** + * Get time these stats were collected + * @return + */ + long getSnapshotTime() { + return snapShotTime; + } + + /** + * Number of files processed by job so far + * @return + */ + long getFilesProcessed() { + return processedFiles; + } + + long getFilesEstimated() { + return estimatedFilesToProcess; + } + } + + /** + * Get some basic performance stats on this job + * @return + */ + IngestJobStats getStats() { + return new IngestJobStats(); + } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobContext.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobContext.java index 5eeaa6e70e..05283ece58 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobContext.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobContext.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; /** * Provides an instance of an ingest module with services specific to the ingest @@ -34,6 +35,14 @@ public final class IngestJobContext { IngestJobContext(IngestJob ingestJob) { this.ingestJob = ingestJob; } + + /** + * + * @return The data source that this ingest job is associated with. + */ + public Content getDataSource() { + return ingestJob.getDataSource(); + } /** * Gets the identifier of the ingest job associated with this context. diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index a4393c55fe..b34f9870c9 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -23,7 +23,9 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -65,6 +67,7 @@ public class IngestManager { private final ConcurrentHashMap> startIngestJobsTasks = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles. private final AtomicLong ingestErrorMessagePosts = new AtomicLong(0L); private final ConcurrentHashMap ingestThreadActivitySnapshots = new ConcurrentHashMap<>(); // Maps ingest thread ids to progress ingestThreadActivitySnapshots. + private final ConcurrentHashMap ingestModuleRunTimes = new ConcurrentHashMap<>(); private final Object processedFilesSnapshotLock = new Object(); private ProcessedFilesSnapshot processedFilesSnapshot = new ProcessedFilesSnapshot(); private volatile IngestMessageTopComponent ingestMessageBox; @@ -197,37 +200,91 @@ public class IngestManager { return IngestScheduler.getInstance().ingestJobsAreRunning(); } + + /** + * Called each time a module in a data source pipeline starts + * @param task + * @param ingestModuleDisplayName + */ void setIngestTaskProgress(DataSourceIngestTask task, String ingestModuleDisplayName) { - ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId(), ingestModuleDisplayName, task.getDataSource())); + ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId(), task.getIngestJob().getId(), ingestModuleDisplayName, task.getDataSource())); } + /** + * Called each time a module in a file ingest pipeline starts + * @param task + * @param ingestModuleDisplayName + */ void setIngestTaskProgress(FileIngestTask task, String ingestModuleDisplayName) { - ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId(), ingestModuleDisplayName, task.getDataSource(), task.getFile())); + IngestThreadActivitySnapshot prevSnap = ingestThreadActivitySnapshots.get(task.getThreadId()); + IngestThreadActivitySnapshot newSnap = new IngestThreadActivitySnapshot(task.getThreadId(), task.getIngestJob().getId(), ingestModuleDisplayName, task.getDataSource(), task.getFile()); + ingestThreadActivitySnapshots.put(task.getThreadId(), newSnap); + + incrementModuleRunTime(prevSnap.getActivity(), newSnap.getStartTime().getTime() - prevSnap.getStartTime().getTime()); } + /** + * Called each time a data source ingest task completes + * @param task + */ void setIngestTaskProgressCompleted(DataSourceIngestTask task) { ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId())); } + /** + * Called when a file ingest pipeline is complete for a given file + * @param task + */ void setIngestTaskProgressCompleted(FileIngestTask task) { - ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId())); + IngestThreadActivitySnapshot prevSnap = ingestThreadActivitySnapshots.get(task.getThreadId()); + IngestThreadActivitySnapshot newSnap = new IngestThreadActivitySnapshot(task.getThreadId()); + ingestThreadActivitySnapshots.put(task.getThreadId(), newSnap); synchronized (processedFilesSnapshotLock) { processedFilesSnapshot.incrementProcessedFilesCount(); } + + incrementModuleRunTime(prevSnap.getActivity(), newSnap.getStartTime().getTime() - prevSnap.getStartTime().getTime()); + } + + /** + * Internal method to update the times associated with each module. + * @param moduleName + * @param duration + */ + private void incrementModuleRunTime(String moduleName, Long duration) { + if (moduleName.equals("IDLE")) + return; + + synchronized (ingestModuleRunTimes) { + Long prevTimeL = ingestModuleRunTimes.get(moduleName); + long prevTime = 0; + if (prevTimeL != null) { + prevTime = prevTimeL; + } + prevTime += duration; + ingestModuleRunTimes.put(moduleName, prevTime); + } + } + + /** + * Return the list of run times for each module + * @return Map of module name to run time (in milliseconds) + */ + Map getModuleRunTimes() { + synchronized (ingestModuleRunTimes) { + Map times = new HashMap<>(ingestModuleRunTimes); + return times; + } } + /** + * Get the stats on current state of each thread + * @return + */ List getIngestThreadActivitySnapshots() { return new ArrayList(ingestThreadActivitySnapshots.values()); } - ProcessedFilesSnapshot getProcessedFilesSnapshot() { - ProcessedFilesSnapshot snapshot; - synchronized (processedFilesSnapshotLock) { - snapshot = processedFilesSnapshot; - processedFilesSnapshot = new ProcessedFilesSnapshot(); - } - return snapshot; - } public void cancelAllIngestJobs() { // Stop creating new ingest jobs. @@ -617,31 +674,42 @@ public class IngestManager { private final String activity; private final String dataSourceName; private final String fileName; + private final long jobId; + // nothing is running on the thread IngestThreadActivitySnapshot(long threadId) { this.threadId = threadId; startTime = new Date(); this.activity = NbBundle.getMessage(this.getClass(), "IngestManager.IngestThreadActivitySnapshot.idleThread"); this.dataSourceName = ""; this.fileName = ""; + this.jobId = 0; } - IngestThreadActivitySnapshot(long threadId, String activity, Content dataSource) { + // data souce thread + IngestThreadActivitySnapshot(long threadId, long jobId, String activity, Content dataSource) { this.threadId = threadId; + this.jobId = jobId; startTime = new Date(); this.activity = activity; this.dataSourceName = dataSource.getName(); - this.fileName = ""; + this.fileName = ""; } - - IngestThreadActivitySnapshot(long threadId, String activity, Content dataSource, AbstractFile file) { + + // file ingest thread + IngestThreadActivitySnapshot(long threadId, long jobId, String activity, Content dataSource, AbstractFile file) { this.threadId = threadId; + this.jobId = jobId; startTime = new Date(); this.activity = activity; this.dataSourceName = dataSource.getName(); this.fileName = file.getName(); } + long getJobId() { + return jobId; + } + long getThreadId() { return threadId; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form index bef05de400..5c0c3dbc16 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form @@ -21,12 +21,13 @@ - - + + + @@ -36,12 +37,15 @@ - + + + + + - @@ -71,6 +75,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -91,12 +117,27 @@ - - - - - - - + + + + + + + + + + +
+ + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java index 601e95f887..dff5c2c856 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java @@ -18,28 +18,39 @@ */ package org.sleuthkit.autopsy.ingest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Map; import javax.swing.JDialog; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import org.apache.commons.lang3.time.DurationFormatUtils; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.ingest.IngestScheduler.IngestJobSchedulerStats; public class IngestProgressSnapshotPanel extends javax.swing.JPanel { private final JDialog parent; private final IngestThreadActivitySnapshotsTableModel threadActivityTableModel; + private final IngestJobTableModel jobTableModel; + private final ModuleTableModel moduleTableModel; IngestProgressSnapshotPanel(JDialog parent) { this.parent = parent; threadActivityTableModel = new IngestThreadActivitySnapshotsTableModel(); + jobTableModel = new IngestJobTableModel(); + moduleTableModel = new ModuleTableModel(); initComponents(); customizeComponents(); } private void customizeComponents() { threadActivitySnapshotsTable.setModel(threadActivityTableModel); + jobTable.setModel(jobTableModel); + moduleTable.setModel(moduleTableModel); int width = snapshotsScrollPane.getPreferredSize().width; for (int i = 0; i < threadActivitySnapshotsTable.getColumnCount(); ++i) { @@ -67,16 +78,13 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } threadActivitySnapshotsTable.setFillsViewportHeight(true); - - fileProcessedPerSecondLabel.setText(NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text", 0)); } private class IngestThreadActivitySnapshotsTableModel extends AbstractTableModel { private final String[] columnNames = {NbBundle.getMessage(this.getClass(), "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID"), - NbBundle.getMessage(this.getClass(), + NbBundle.getMessage(this.getClass(), "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity"), NbBundle.getMessage(this.getClass(), "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource"), @@ -85,7 +93,8 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { NbBundle.getMessage(this.getClass(), "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime"), NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime")}; + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime"), + "Job ID"}; private List snapshots; private IngestThreadActivitySnapshotsTableModel() { @@ -137,6 +146,176 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { long elapsedTime = now.getTime() - snapshot.getStartTime().getTime(); cellValue = DurationFormatUtils.formatDurationHMS(elapsedTime); break; + case 6: + cellValue = snapshot.getJobId(); + break; + default: + cellValue = null; + break; + } + return cellValue; + } + } + + private class IngestJobTableModel extends AbstractTableModel { + + private final String[] columnNames = {"Job ID", + "Data Source", "Start", "Num Processed", "Files/Sec", "In Progress", "Files Queued", "Dir Queued", "Root Queued", "DS Queued"}; + private List schedStats; + + private IngestJobTableModel() { + refresh(); + } + + private void refresh() { + schedStats = IngestScheduler.getInstance().getJobStats(); + fireTableDataChanged(); + } + + @Override + public int getRowCount() { + return schedStats.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public String getColumnName(int col) { + return columnNames[col]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + IngestJobSchedulerStats schedStat = schedStats.get(rowIndex); + Object cellValue; + switch (columnIndex) { + case 0: + cellValue = schedStat.getJobId(); + break; + case 1: + cellValue = schedStat.getDataSource(); + break; + case 2: + SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + cellValue = dateFormat.format(new Date(schedStat.getIngestJobStats().getStartTime())); + break; + case 3: + cellValue = schedStat.getIngestJobStats().getFilesProcessed(); + break; + case 4: + cellValue = schedStat.getIngestJobStats().getSpeed(); + break; + case 5: + cellValue = schedStat.getRunningListSize(); + break; + case 6: + cellValue = schedStat.getFileQueueSize(); + break; + case 7: + cellValue = schedStat.getDirQueueSize(); + break; + case 8: + cellValue = schedStat.getRootQueueSize(); + break; + case 9: + cellValue = schedStat.getDsQueueSize(); + break; + default: + cellValue = null; + break; + } + return cellValue; + } + } + + private class ModuleTableModel extends AbstractTableModel { + + private class ModuleStats implements Comparable { + private final String name; + private final long duration; + ModuleStats(String name, long duration) { + this.name = name; + this.duration = duration; + } + + /** + * @return the name + */ + protected String getName() { + return name; + } + + /** + * @return the duration + */ + protected long getDuration() { + return duration; + } + + @Override + public int compareTo(ModuleStats o) { + if (duration > o.getDuration()) { + return -1; + } + else if (duration == o.getDuration()) { + return 0; + } + else { + return 1; + } + } + + } + private final String[] columnNames = {"Module", "Duration"}; + private final List moduleStats = new ArrayList<>(); + private long totalTime; + + private ModuleTableModel() { + refresh(); + } + + private void refresh() { + MapmoduleStatMap = IngestManager.getInstance().getModuleRunTimes(); + moduleStats.clear(); + totalTime = 0; + for (String k : moduleStatMap.keySet()) { + moduleStats.add(new ModuleStats(k, moduleStatMap.get(k))); + totalTime += moduleStatMap.get(k); + } + Collections.sort(moduleStats); + fireTableDataChanged(); + } + + @Override + public int getRowCount() { + return moduleStats.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public String getColumnName(int col) { + return columnNames[col]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + ModuleStats moduleStat = moduleStats.get(rowIndex); + Object cellValue; + switch (columnIndex) { + case 0: + cellValue = moduleStat.getName(); + break; + case 1: + cellValue = DurationFormatUtils.formatDurationHMS(moduleStat.getDuration()) + " (" + (moduleStat.getDuration() * 100) / totalTime + "%)"; + break; + default: cellValue = null; break; @@ -156,9 +335,12 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { snapshotsScrollPane = new javax.swing.JScrollPane(); threadActivitySnapshotsTable = new javax.swing.JTable(); + jobScrollPane = new javax.swing.JScrollPane(); + jobTable = new javax.swing.JTable(); refreshButton = new javax.swing.JButton(); closeButton = new javax.swing.JButton(); - fileProcessedPerSecondLabel = new javax.swing.JLabel(); + moduleScrollPane = new javax.swing.JScrollPane(); + moduleTable = new javax.swing.JTable(); threadActivitySnapshotsTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { @@ -170,6 +352,16 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { )); snapshotsScrollPane.setViewportView(threadActivitySnapshotsTable); + jobTable.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + + } + )); + jobScrollPane.setViewportView(jobTable); + org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(IngestProgressSnapshotPanel.class, "IngestProgressSnapshotPanel.refreshButton.text")); // NOI18N refreshButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -184,7 +376,15 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } }); - org.openide.awt.Mnemonics.setLocalizedText(fileProcessedPerSecondLabel, org.openide.util.NbBundle.getMessage(IngestProgressSnapshotPanel.class, "IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text")); // NOI18N + moduleTable.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + + } + )); + moduleScrollPane.setViewportView(moduleTable); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -195,11 +395,12 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(snapshotsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 881, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addComponent(fileProcessedPerSecondLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, Short.MAX_VALUE) .addComponent(refreshButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(closeButton))) + .addComponent(closeButton)) + .addComponent(jobScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 881, Short.MAX_VALUE) + .addComponent(moduleScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 881, Short.MAX_VALUE)) .addContainerGap()) ); @@ -209,12 +410,15 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(snapshotsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE) + .addComponent(snapshotsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jobScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(moduleScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(refreshButton) - .addComponent(closeButton) - .addComponent(fileProcessedPerSecondLabel)) + .addComponent(closeButton)) .addContainerGap()) ); @@ -228,16 +432,15 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed threadActivityTableModel.refresh(); - IngestManager.ProcessedFilesSnapshot snapshot = IngestManager.getInstance().getProcessedFilesSnapshot(); - Date now = new Date(); - long elapsedTime = now.getTime() - snapshot.getStartTime().getTime(); - double filesPerSecond = (double) snapshot.getProcessedFilesCount() / (double) elapsedTime * 1000.0; - fileProcessedPerSecondLabel.setText(NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text", filesPerSecond)); + jobTableModel.refresh(); + moduleTableModel.refresh(); }//GEN-LAST:event_refreshButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton closeButton; - private javax.swing.JLabel fileProcessedPerSecondLabel; + private javax.swing.JScrollPane jobScrollPane; + private javax.swing.JTable jobTable; + private javax.swing.JScrollPane moduleScrollPane; + private javax.swing.JTable moduleTable; private javax.swing.JButton refreshButton; private javax.swing.JScrollPane snapshotsScrollPane; private javax.swing.JTable threadActivitySnapshotsTable; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java index b5338cd773..021f797d1b 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.ingest; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; @@ -32,13 +33,14 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.IngestJob.IngestJobStats; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.autopsy.coreutils.Logger; /** * Creates ingest jobs and their constituent ingest tasks, enabled the tasks for @@ -364,6 +366,12 @@ final class IngestScheduler { return !ingestJobsById.isEmpty(); } + /** + * Clears the queues for the job. If job is complete, finish it up. Otherwise, + * this will exit and the last worker thread will finish / clean up. + * + * @param job + */ synchronized void cancelIngestJob(IngestJob job) { long jobId = job.getId(); removeAllPendingTasksForJob(pendingRootDirectoryTasks, jobId); @@ -376,6 +384,25 @@ final class IngestScheduler { } } + /** + * Return the number of tasks in the queue for the given job ID + * @param + * @param queue + * @param jobId + * @return + */ + int countJobsInCollection(Collection queue, long jobId) { + Iterator iterator = queue.iterator(); + int count = 0; + while (iterator.hasNext()) { + IngestTask task = (IngestTask) iterator.next(); + if (task.getIngestJob().getId() == jobId) { + count++; + } + } + return count; + } + synchronized private void removeAllPendingTasksForJob(Collection taskQueue, long jobId) { Iterator iterator = taskQueue.iterator(); while (iterator.hasNext()) { @@ -433,6 +460,10 @@ final class IngestScheduler { return true; } + /** + * Called after all work is completed to free resources. + * @param job + */ private void finishIngestJob(IngestJob job) { job.finish(); long jobId = job.getId(); @@ -559,4 +590,73 @@ final class IngestScheduler { return task; } } + + /** + * Stores basic stats for a given job + */ + class IngestJobSchedulerStats { + private final IngestJobStats ingestJobStats; + private final long jobId; + private final String dataSource; + private final long rootQueueSize; + private final long dirQueueSize; + private final long fileQueueSize; + private final long dsQueueSize; + private final long runningListSize; + + IngestJobSchedulerStats(IngestJob job) { + ingestJobStats = job.getStats(); + jobId = job.getId(); + dataSource = job.getDataSource().getName(); + rootQueueSize = countJobsInCollection(pendingRootDirectoryTasks, jobId); + dirQueueSize = countJobsInCollection(pendingDirectoryTasks, jobId); + fileQueueSize = countJobsInCollection(pendingFileTasks, jobId); + dsQueueSize = countJobsInCollection(pendingDataSourceTasks, jobId); + runningListSize = countJobsInCollection(tasksInProgressAndPending, jobId) - fileQueueSize - dsQueueSize; + } + + protected long getJobId() { + return jobId; + } + + protected String getDataSource() { + return dataSource; + } + + protected long getRootQueueSize() { + return rootQueueSize; + } + + protected long getDirQueueSize() { + return dirQueueSize; + } + + protected long getFileQueueSize() { + return fileQueueSize; + } + + protected long getDsQueueSize() { + return dsQueueSize; + } + + protected long getRunningListSize() { + return runningListSize; + } + + protected IngestJobStats getIngestJobStats() { + return ingestJobStats; + } + } + + /** + * Get basic performance / stats on all running jobs + * @return + */ + synchronized List getJobStats() { + List stats = new ArrayList<>(); + for (IngestJob job : Collections.list(ingestJobsById.elements())) { + stats.add(new IngestJobSchedulerStats(job)); + } + return stats; + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/e01verify/E01VerifyIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/e01verify/E01VerifyIngestModule.java index 4d52d57cae..b22ea555a6 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/e01verify/E01VerifyIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/e01verify/E01VerifyIngestModule.java @@ -45,8 +45,7 @@ public class E01VerifyIngestModule implements DataSourceIngestModule { private static final Logger logger = Logger.getLogger(E01VerifyIngestModule.class.getName()); private static final long DEFAULT_CHUNK_SIZE = 32 * 1024; private static final IngestServices services = IngestServices.getInstance(); - private Image img; - private String imgName; + private MessageDigest messageDigest; private boolean verified = false; private boolean skipped = false; @@ -61,42 +60,33 @@ public class E01VerifyIngestModule implements DataSourceIngestModule { public void startUp(IngestJobContext context) throws IngestModuleException { this.context = context; verified = false; - img = null; - imgName = ""; storedHash = ""; calculatedHash = ""; - if (messageDigest == null) { - try { - messageDigest = MessageDigest.getInstance("MD5"); //NON-NLS - } catch (NoSuchAlgorithmException ex) { - logger.log(Level.WARNING, "Error getting md5 algorithm", ex); //NON-NLS - throw new RuntimeException( - NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.startUp.exception.failGetMd5")); - } - } else { - messageDigest.reset(); + try { + messageDigest = MessageDigest.getInstance("MD5"); //NON-NLS + } catch (NoSuchAlgorithmException ex) { + logger.log(Level.WARNING, "Error getting md5 algorithm", ex); //NON-NLS + throw new RuntimeException( + NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.startUp.exception.failGetMd5")); } } @Override public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) { - imgName = dataSource.getName(); - try { - img = dataSource.getImage(); - } catch (TskCoreException ex) { - img = null; - logger.log(Level.SEVERE, "Failed to get image from Content.", ex); //NON-NLS - services.postMessage(IngestMessage.createMessage( MessageType.ERROR, E01VerifierModuleFactory.getModuleName(), + String imgName = dataSource.getName(); + if (!(dataSource instanceof Image)) { + logger.log(Level.INFO, "Skipping disk image image {0}", imgName); //NON-NLS + services.postMessage(IngestMessage.createMessage( MessageType.INFO, E01VerifierModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), - "EwfVerifyIngestModule.process.errProcImg", + "EwfVerifyIngestModule.process.skipNonEwf", imgName))); - return ProcessResult.ERROR; + return ProcessResult.OK; } + Image img = (Image)dataSource; // Skip images that are not E01 - if (img == null || img.getType() != TskData.TSK_IMG_TYPE_ENUM.TSK_IMG_TYPE_EWF_EWF) { - img = null; + if (img.getType() != TskData.TSK_IMG_TYPE_ENUM.TSK_IMG_TYPE_EWF_EWF) { logger.log(Level.INFO, "Skipping non-ewf image {0}", imgName); //NON-NLS services.postMessage(IngestMessage.createMessage( MessageType.INFO, E01VerifierModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index 087328ab1e..d788e5782f 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.logging.Level; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -341,7 +342,13 @@ import org.sleuthkit.datamodel.TskCoreException; row = sheet.createRow(rowIndex); row.setRowStyle(setStyle); row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.numImages")); - row.createCell(1).setCellValue(currentCase.getImageIDs().length); + int numImages; + try { + numImages = currentCase.getDataSources().size(); + } catch (TskCoreException ex) { + numImages = 0; + } + row.createCell(1).setCellValue(numImages); ++rowIndex; sheet.autoSizeColumn(0); diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 7411b33659..9e1160c428 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -959,7 +959,12 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; String caseName = currentCase.getName(); String caseNumber = currentCase.getNumber(); String examiner = currentCase.getExaminer(); - int imagecount = currentCase.getImageIDs().length; + int imagecount; + try { + imagecount = currentCase.getDataSources().size(); + } catch (TskCoreException ex) { + imagecount = 0; + } StringBuilder summary = new StringBuilder(); boolean running = false; @@ -1005,22 +1010,22 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; summary.append(NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.imageInfoHeading")); summary.append("
\n"); //NON-NLS try { - Image[] images = new Image[imagecount]; - for(int i=0; i").append(img.getName()).append("

\n"); //NON-NLS - summary.append("
\n"); //NON-NLS - summary.append("\n"); //NON-NLS - for(String imgPath : img.getPaths()) { + for (Content c : currentCase.getDataSources()) { + summary.append("

").append(c.getName()).append("

\n"); //NON-NLS + if (c instanceof Image) { + Image img = (Image) c; + + summary.append("
").append( //NON-NLS - NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.timezone")) - .append("").append(img.getTimeZone()).append("
\n"); //NON-NLS summary.append("\n"); //NON-NLS + NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.timezone")) + .append("\n"); //NON-NLS + for(String imgPath : img.getPaths()) { + summary.append("\n"); //NON-NLS + } + summary.append("
").append( //NON-NLS - NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.path")) - .append("").append(imgPath).append("
").append(img.getTimeZone()).append("
").append( //NON-NLS + NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.path")) + .append("").append(imgPath).append("
\n"); //NON-NLS } - summary.append("\n"); //NON-NLS } } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get image information for the HTML report."); //NON-NLS diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.form index acd2304cae..54e3cdee7f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.form +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.form @@ -142,6 +142,7 @@ + @@ -152,7 +153,6 @@ - diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.java index f15329d81e..21daa2c8ba 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownSingleTermSearchPanel.java @@ -151,7 +151,7 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel { org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.selectAllMenuItem.text")); // NOI18N rightClickMenu.add(selectAllMenuItem); - keywordTextField.setFont(keywordTextField.getFont().deriveFont(Font.PLAIN, 14)); + keywordTextField.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N keywordTextField.setText(org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.keywordTextField.text")); // NOI18N keywordTextField.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(192, 192, 192), 1, true)); keywordTextField.setMinimumSize(new java.awt.Dimension(2, 25)); @@ -167,7 +167,7 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel { } }); - searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N NON-NLS + searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.searchButton.text")); // NOI18N searchButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -176,10 +176,10 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel { }); queryTypeButtonGroup.add(exactRadioButton); + exactRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(exactRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.exactRadioButton.text")); // NOI18N queryTypeButtonGroup.add(substringRadioButton); - substringRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(substringRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.substringRadioButton.text")); // NOI18N queryTypeButtonGroup.add(regexRadioButton); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.form index 83675f4797..366415f49d 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.form +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.form @@ -263,6 +263,7 @@
+ diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java index 70bbd11286..bc8989670e 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalEditListPanel.java @@ -277,6 +277,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); + ingestMessagesCheckbox.setSelected(true); ingestMessagesCheckbox.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.text")); // NOI18N ingestMessagesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText")); // NOI18N ingestMessagesCheckbox.addActionListener(new java.awt.event.ActionListener() { @@ -291,13 +292,13 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis listOptionsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.listOptionsLabel.text")); // NOI18N - deleteListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N NON-NLS + deleteListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N deleteListButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteListButton.text")); // NOI18N - saveListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/save16.png"))); // NOI18N NON-NLS + saveListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/save16.png"))); // NOI18N saveListButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.saveListButton.text")); // NOI18N - exportButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/export16.png"))); // NOI18N NON-NLS + exportButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/export16.png"))); // NOI18N exportButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.exportButton.text")); // NOI18N exportButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java index d6b2a3e724..be03c48a24 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java @@ -240,7 +240,7 @@ class Ingester { params.put(Server.Schema.ID.toString(), Long.toString(af.getId())); long dataSourceId = -1; try { - dataSourceId = Case.getCurrentCase().getSleuthkitCase().getFileDataSource(af); + dataSourceId = af.getDataSource().getId(); params.put(Server.Schema.IMAGE_ID.toString(), Long.toString(dataSourceId)); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Could not get data source id to properly index the file " + af.getId()); //NON-NLS diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index 3b9af7aa77..94a9d7b7a7 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -132,7 +132,8 @@ public final class KeywordSearchIngestModule implements FileIngestModule { public void startUp(IngestJobContext context) throws IngestModuleException { logger.log(Level.INFO, "Initializing instance {0}", instanceNum); //NON-NLS initialized = false; - jobId = context.getJobId(); + jobId = context.getJobId(); + dataSourceId = context.getDataSource().getId(); caseHandle = Case.getCurrentCase().getSleuthkitCase(); tikaFormatDetector = new Tika(); ingester = Server.getIngester(); @@ -212,13 +213,6 @@ public final class KeywordSearchIngestModule implements FileIngestModule { putIngestStatus(jobId, abstractFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING); return ProcessResult.OK; } - try { - //add data source id of the file to the set, keeping track of images being ingested - dataSourceId = caseHandle.getFileDataSource(abstractFile); - - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting image id of file processed by keyword search: " + abstractFile.getName(), ex); //NON-NLS - } if (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { //skip indexing of virtual dirs (no content, no real name) - will index children files @@ -484,6 +478,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { return; } + // @@@ Could use Blackboard instead of doing this again //use Tika to detect the format String detectedFormat = null; InputStream is = null; @@ -503,10 +498,6 @@ public final class KeywordSearchIngestModule implements FileIngestModule { } } - // @@@ Add file type signature to blackboard here - - //logger.log(Level.INFO, "Detected format: " + aFile.getName() + " " + detectedFormat); - // we skip archive formats that are opened by the archive module. // @@@ We could have a check here to see if the archive module was enabled though... if (TextExtractor.ARCHIVE_MIME_TYPES.contains(detectedFormat)) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java index 4bd84e3983..e71c935ef4 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchList.java @@ -318,8 +318,7 @@ abstract class KeywordSearchList { } boolean addList(String name, List newList) { - boolean isLocked = this.lockedLists.contains(name); - return addList(name, newList, true, isLocked); + return addList(name, newList, true, true); } boolean addList(KeywordList list) {