diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java index 8da58193bc..69ccf2ce50 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-17 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,9 @@ import java.util.Arrays; import java.util.List; import java.util.Observable; import java.util.Observer; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javax.swing.SwingWorker; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -46,7 +48,7 @@ import org.sleuthkit.datamodel.TskData; */ public final class FileTypesByExtension implements AutopsyVisitableItem { - private static final Logger logger = Logger.getLogger(FileTypesByExtension.class.getName()); + private final static Logger logger = Logger.getLogger(FileTypesByExtension.class.getName()); private final SleuthkitCase skCase; public FileTypesByExtension(SleuthkitCase skCase) { @@ -280,9 +282,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { */ static class FileExtensionNode extends DisplayableItemNode { - FileTypesByExtension.SearchFilterInterface filter; - SleuthkitCase skCase; private final FileTypesByExtObservable notifier; + private FileTypesByExtension.SearchFilterInterface filter; + private SleuthkitCase skCase; + private long childCount = -1; /** * @@ -298,10 +301,11 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { this.notifier = o; init(); o.addObserver(new ByExtNodeObserver()); + } private void init() { - super.setName(filter.getName()); + setName(filter.getName()); updateDisplayName(); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS } @@ -316,10 +320,30 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { } private void updateDisplayName() { - final String count = notifier.shouldShowCounts(skCase) - ? " (" + Long.toString(FileExtensionNodeChildren.calculateItems(skCase, filter)) + ")" - : ""; - super.setDisplayName(filter.getDisplayName() + count); + if (notifier.shouldShowCounts(skCase)) { + setDisplayName(filter.getDisplayName() + ((childCount < 0) ? "(counting...)" + : ("(" + childCount + ")"))); + new SwingWorker() { + @Override + protected Long doInBackground() throws Exception { + return FileExtensionNodeChildren.calculateItems(skCase, filter); + } + + @Override + protected void done() { + try { + childCount = get(); + setDisplayName(filter.getDisplayName() + " (" + childCount + ")"); + } catch (InterruptedException | ExecutionException ex) { + setDisplayName(filter.getDisplayName()); + logger.log(Level.WARNING, "Failed to get count of files for filter " + filter.toString(), ex); + } + } + }.execute(); + } else { + setDisplayName(filter.getDisplayName() + ((childCount < 0) ? "" + : ("(" + childCount + "+)"))); + } } @Override @@ -628,5 +652,6 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { public String getDisplayName(); public List getFilter(); + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 2ab11bca97..a98df81967 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -28,7 +28,9 @@ import java.util.HashMap; import java.util.List; import java.util.Observable; import java.util.Observer; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javax.swing.SwingWorker; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.openide.nodes.ChildFactory; @@ -54,6 +56,7 @@ import org.sleuthkit.datamodel.TskData; */ public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { + private final static Logger logger = Logger.getLogger(FileTypesByMimeType.class.getName()); private final SleuthkitCase skCase; /** * The nodes of this tree will be determined dynamically by the mimetypes @@ -347,22 +350,21 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi } - /** - * Node which represents the media sub type in the By MIME type tree, the - * media subtype is the portion of the MIME type following the /. - */ class MediaSubTypeNode extends DisplayableItemNode implements Observer { + private long childCount = -1; + private final String mimeType; + private final String subType; + private MediaSubTypeNode(String mimeType) { super(Children.create(new MediaSubTypeNodeChildren(mimeType), true)); - addObserver(this); - init(mimeType); - } - - private void init(String mimeType) { + this.mimeType = mimeType; + this.subType = StringUtils.substringAfter(mimeType, "/"); super.setName(mimeType); - updateDisplayName(mimeType); + updateDisplayName(); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS + + addObserver(this); } /** @@ -372,10 +374,33 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi * @param mimeType - the complete MimeType, needed for accurate query * results */ - private void updateDisplayName(String mimeType) { - final long count = calculateItems(skCase, mimeType); - //only the part of the mimeType after the media type - super.setDisplayName(StringUtils.substringAfter(mimeType, "/") + " (" + count + ")"); + private void updateDisplayName() { + if (shouldShowCounts(skCase)) { + setDisplayName(subType + ((childCount < 0) ? "(counting...)" + : ("(" + childCount + ")"))); + new SwingWorker() { + @Override + protected Long doInBackground() throws Exception { + return calculateItems(skCase, mimeType); + } + + @Override + protected void done() { + try { + childCount = get(); + setDisplayName(subType + " (" + childCount + ")"); + } catch (InterruptedException | ExecutionException ex) { + setDisplayName(subType); + logger.log(Level.WARNING, "Failed to get count of files for mimetype " + mimeType, ex); + } + } + + }. + execute(); + } else { + setDisplayName(subType + ((childCount < 0) ? "" + : ("(" + childCount + "+)"))); + } } /** @@ -390,7 +415,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi } @Override - public T accept(DisplayableItemNodeVisitor v) { + public T accept(DisplayableItemNodeVisitor< T> v) { return v.visit(this); } @@ -401,7 +426,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi @Override public void update(Observable o, Object arg) { - updateDisplayName(getName()); + updateDisplayName(); } }