diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 59e01aea6e..40f0779f7f 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -59,6 +59,7 @@ import org.sleuthkit.autopsy.coreutils.History; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager; import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewState; import org.sleuthkit.autopsy.imagegallery.gui.NoGroupsDialog; @@ -306,7 +307,8 @@ public final class ImageGalleryController { private void restartWorker() { if (dbWorkerThread != null) { - dbWorkerThread.cancelAllTasks(); + // Keep using the same worker thread if one exists + return; } dbWorkerThread = new DBWorkerThread(); @@ -504,7 +506,7 @@ public final class ImageGalleryController { try { // @@@ Could probably do something more fancy here and check if we've been canceled every now and then InnerTask it = workQueue.take(); - + if (it.cancelled == false) { it.run(); } @@ -618,8 +620,16 @@ public final class ImageGalleryController { */ @Override public void run() { - DrawableFile drawableFile = DrawableFile.create(getFile(), true); - db.updateFile(drawableFile); + try{ + DrawableFile drawableFile = DrawableFile.create(getFile(), true); + db.updateFile(drawableFile); + } catch (NullPointerException ex){ + // This is one of the places where we get many errors if the case is closed during processing. + // We don't want to print out a ton of exceptions if this is the case. + if(Case.isCaseOpen()){ + Logger.getLogger(UpdateFileTask.class.getName()).log(Level.SEVERE, "Error in UpdateFile task"); + } + } } } @@ -637,7 +647,16 @@ public final class ImageGalleryController { */ @Override public void run() { - db.removeFile(getFile().getId()); + try{ + db.removeFile(getFile().getId()); + } catch (NullPointerException ex){ + // This is one of the places where we get many errors if the case is closed during processing. + // We don't want to print out a ton of exceptions if this is the case. + if(Case.isCaseOpen()){ + Logger.getLogger(RemoveFileTask.class.getName()).log(Level.SEVERE, "Case was closed out from underneath RemoveFile task"); + } + } + } } @@ -744,7 +763,7 @@ public final class ImageGalleryController { * netbeans and ImageGallery progress/status */ class PrePopulateDataSourceFiles extends InnerTask { - private Content dataSource; + private final Content dataSource; /** * here we grab by extension but in file_done listener we look at file @@ -821,9 +840,9 @@ public final class ImageGalleryController { } catch (TskCoreException ex) { Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "failed to transfer all database contents", ex); - } catch (IllegalStateException ex) { - Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.SEVERE, "Case was closed out from underneath CopyDataSource task", ex); - } + } catch (IllegalStateException | NullPointerException ex) { + Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "Case was closed out from underneath prepopulating database"); + } progressHandle.finish(); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java index 3b4abb684c..0aab44e58c 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java @@ -233,7 +233,7 @@ public enum ThumbnailCache { } return bi; } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Could not read image: " + file.getName(), ex); + LOGGER.log(Level.WARNING, "Could not read image: " + file.getName()); return null; } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java index 2bdf08d70f..25627626d3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java @@ -84,7 +84,7 @@ public enum Category implements Comparable { listeners.remove(aThis); } } - + public KeyCode getHotKeycode() { return KeyCode.getKeyCode(Integer.toString(id)); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index b618cccb0e..4d822eae7a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -129,9 +129,9 @@ public class DrawableDB { volatile private Connection con; - private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy + private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy - private static final Lock DBLock = rwLock.writeLock(); //using exclusing lock for all db ops for now + private final Lock DBLock = rwLock.writeLock(); //using exclusing lock for all db ops for now static {//make sure sqlite driver is loaded // possibly redundant try { @@ -149,7 +149,7 @@ public class DrawableDB { * MUST always call dbWriteUnLock() as early as possible, in the same thread * where dbWriteLock() was called */ - public static void dbWriteLock() { + public void dbWriteLock() { //Logger.getLogger("LOCK").log(Level.INFO, "Locking " + rwLock.toString()); DBLock.lock(); } @@ -159,7 +159,7 @@ public class DrawableDB { * dbWriteLock(). Call in "finally" block to ensure the lock is always * released. */ - public static void dbWriteUnlock() { + public void dbWriteUnlock() { //Logger.getLogger("LOCK").log(Level.INFO, "UNLocking " + rwLock.toString()); DBLock.unlock(); } @@ -604,8 +604,12 @@ public class DrawableDB { tr.addUpdatedFile(f.getId()); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "failed to insert/update file" + f.getName(), ex); + } catch (SQLException | NullPointerException ex) { + // This is one of the places where we get an error if the case is closed during processing, + // which doesn't need to be reported here. + if(Case.isCaseOpen()){ + LOGGER.log(Level.SEVERE, "failed to insert/update file" + f.getName(), ex); + } } finally { dbWriteUnlock(); } @@ -915,7 +919,10 @@ public class DrawableDB { insertGroupStmt.setString(2, groupBy.attrName.toString()); insertGroupStmt.execute(); } catch (SQLException sQLException) { - LOGGER.log(Level.SEVERE, "Unable to insert group", sQLException); + // Don't need to report it if the case was closed + if(Case.isCaseOpen()){ + LOGGER.log(Level.SEVERE, "Unable to insert group", sQLException); + } } finally { dbWriteUnlock(); } @@ -952,7 +959,7 @@ public class DrawableDB { return DrawableFile.create(controller.getSleuthKitCase().getAbstractFileById(id), areFilesAnalyzed(Collections.singleton(id))); } catch (IllegalStateException ex) { - LOGGER.log(Level.SEVERE, "there is no case open; failed to load file with id: " + id, ex); + LOGGER.log(Level.SEVERE, "there is no case open; failed to load file with id: " + id); return null; } } @@ -1160,7 +1167,12 @@ public class DrawableDB { fireRemovedFiles(removedFiles); } } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error commiting drawable.db.", ex); + if(Case.isCaseOpen()){ + LOGGER.log(Level.SEVERE, "Error commiting drawable.db.", ex); + } + else{ + LOGGER.log(Level.WARNING, "Error commiting drawable.db - case is closed."); + } rollback(); } } @@ -1171,7 +1183,12 @@ public class DrawableDB { try { con.setAutoCommit(true); } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error setting auto-commit to true.", ex); + if(Case.isCaseOpen()){ + LOGGER.log(Level.SEVERE, "Error setting auto-commit to true.", ex); + } + else{ + LOGGER.log(Level.SEVERE, "Error setting auto-commit to true - case is closed"); + } } finally { closed = true; dbWriteUnlock(); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 71febd6449..a06fcd226c 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -174,6 +174,9 @@ public abstract class DrawableFile extends AbstractFile } catch (TskCoreException ex) { Logger.getAnonymousLogger().log(Level.WARNING, "problem looking up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName(), ex); return Collections.emptySet(); + } catch (IllegalStateException ex) { + Logger.getAnonymousLogger().log(Level.WARNING, "there is no case open; failed to look up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName()); + return Collections.emptySet(); } } @@ -282,7 +285,10 @@ public abstract class DrawableFile extends AbstractFile } } catch (TskCoreException ex) { Logger.getLogger(DrawableFile.class.getName()).log(Level.WARNING, "problem looking up category for file " + this.getName(), ex); + } catch (IllegalStateException ex){ + // We get here many times if the case is closed during ingest, so don't print out a ton of warnings. } + } public abstract Image getThumbnail(); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java index 8cf6a704d2..5586e079e8 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java @@ -563,7 +563,9 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "TSK error getting files in Category:" + category.getDisplayName(), ex); throw ex; - } + } catch(IllegalStateException ex){ + throw new TskCoreException("Case closed while getting files"); + } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/GroupPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/GroupPane.java index 9019694cb4..8d9daf1482 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/GroupPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/GroupPane.java @@ -94,6 +94,7 @@ import org.openide.util.Lookup; import org.openide.util.actions.Presenter; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; @@ -112,9 +113,9 @@ import org.sleuthkit.autopsy.imagegallery.actions.NextUnseenGroup; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; +import org.sleuthkit.autopsy.imagegallery.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewMode; import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewState; -import org.sleuthkit.autopsy.imagegallery.grouping.DrawableGroup; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -371,8 +372,13 @@ public class GroupPane extends BorderPane implements GroupView { resetHeaderString(); //and assign fileIDs to gridView if (grouping.get() == null) { - Platform.runLater(gridView.getItems()::clear); - + Platform.runLater(gridView.getItems()::clear); + // Reset the DrawableCell listeners from the old case + if(! Case.isCaseOpen()){ + for(GroupPane.DrawableCell cell:cellMap.values()){ + cell.resetItem(); + } + } } else { grouping.get().fileIds().addListener((Observable observable) -> { updateFiles(); @@ -627,6 +633,7 @@ public class GroupPane extends BorderPane implements GroupView { */ void setViewState(GroupViewState viewState) { if (viewState == null) { + this.grouping.set(null); Platform.runLater(() -> { setCenter(null); groupLabel.setText(null); @@ -655,9 +662,18 @@ public class GroupPane extends BorderPane implements GroupView { itemProperty().addListener((ObservableValue observable, Long oldValue, Long newValue) -> { if (oldValue != null) { cellMap.remove(oldValue, DrawableCell.this); + tile.setFile(null); } if (newValue != null) { + if(cellMap.containsKey(newValue)){ + if(tile != null){ + // Clear out the old value to prevent out-of-date listeners + // from activating. + cellMap.get(newValue).tile.setFile(null); + } + } cellMap.put(newValue, DrawableCell.this); + } }); @@ -669,6 +685,10 @@ public class GroupPane extends BorderPane implements GroupView { super.updateItem(item, empty); tile.setFile(item); } + + void resetItem(){ + tile.setFile(null); + } } private static final List categoryKeyCodes = Arrays.asList(KeyCode.NUMPAD0, KeyCode.NUMPAD1, KeyCode.NUMPAD2, KeyCode.NUMPAD3, KeyCode.NUMPAD4, KeyCode.NUMPAD5, diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java index 7fc20d4ec7..7ff83043af 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java @@ -359,6 +359,7 @@ public abstract class SingleDrawableViewBase extends AnchorPane implements Drawa if (Objects.equals(fileID, this.fileID) == false) { this.fileID = fileID; disposeContent(); + if (this.fileID == null || Case.isCaseOpen() == false) { Category.unregisterListener(this); TagUtils.unregisterListener(this); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java index 02106c0874..241cbc09d9 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java @@ -22,6 +22,7 @@ import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.ResourceBundle; +import java.util.logging.Level; import javafx.application.Platform; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; @@ -36,8 +37,10 @@ import javafx.scene.layout.VBox; import javafx.util.Pair; import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; +import org.sleuthkit.autopsy.imagegallery.TagUtils; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.datamodel.TskCoreException; @@ -111,7 +114,7 @@ public class SummaryTablePane extends AnchorPane implements Category.CategoryLis try { data.add(new Pair<>(cat, ImageGalleryController.getDefault().getGroupManager().countFilesWithCategory(cat))); } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + Logger.getLogger(SummaryTablePane.class.getName()).log(Level.WARNING, "Error performing category file count"); } } Platform.runLater(() -> {