pass controller to DrawableTagsManager constructor, ImageGalleryController keeps reference to Case object

This commit is contained in:
millmanorama 2018-09-04 09:46:10 +02:00
parent 76668f53ec
commit 8df6dfb8f7
2 changed files with 145 additions and 135 deletions

View File

@ -99,7 +99,7 @@ import org.sleuthkit.datamodel.TskData;
* control. * control.
*/ */
public final class ImageGalleryController { public final class ImageGalleryController {
private static final Logger logger = Logger.getLogger(ImageGalleryController.class.getName()); private static final Logger logger = Logger.getLogger(ImageGalleryController.class.getName());
private static ImageGalleryController instance; private static ImageGalleryController instance;
@ -108,24 +108,24 @@ public final class ImageGalleryController {
* not listen to speed up ingest * not listen to speed up ingest
*/ */
private final SimpleBooleanProperty listeningEnabled = new SimpleBooleanProperty(false); private final SimpleBooleanProperty listeningEnabled = new SimpleBooleanProperty(false);
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private final ReadOnlyBooleanWrapper stale = new ReadOnlyBooleanWrapper(false); private final ReadOnlyBooleanWrapper stale = new ReadOnlyBooleanWrapper(false);
private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false); private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false);
private final ReadOnlyDoubleWrapper thumbnailSize = new ReadOnlyDoubleWrapper(100); private final ReadOnlyDoubleWrapper thumbnailSize = new ReadOnlyDoubleWrapper(100);
private final ReadOnlyBooleanWrapper regroupDisabled = new ReadOnlyBooleanWrapper(false); private final ReadOnlyBooleanWrapper regroupDisabled = new ReadOnlyBooleanWrapper(false);
private final ReadOnlyIntegerWrapper dbTaskQueueSize = new ReadOnlyIntegerWrapper(0); private final ReadOnlyIntegerWrapper dbTaskQueueSize = new ReadOnlyIntegerWrapper(0);
private final FileIDSelectionModel selectionModel = new FileIDSelectionModel(this); private final FileIDSelectionModel selectionModel = new FileIDSelectionModel(this);
private final History<GroupViewState> historyManager = new History<>(); private final History<GroupViewState> historyManager = new History<>();
private final UndoRedoManager undoManager = new UndoRedoManager(); private final UndoRedoManager undoManager = new UndoRedoManager();
private final GroupManager groupManager = new GroupManager(this); private final GroupManager groupManager = new GroupManager(this);
private final HashSetManager hashSetManager = new HashSetManager(); private final HashSetManager hashSetManager = new HashSetManager();
private final CategoryManager categoryManager = new CategoryManager(this); private final CategoryManager categoryManager = new CategoryManager(this);
private DrawableTagsManager tagsManager; private DrawableTagsManager tagsManager;
private Runnable showTree; private Runnable showTree;
private Toolbar toolbar; private Toolbar toolbar;
private StackPane fullUIStackPane; private StackPane fullUIStackPane;
@ -137,12 +137,17 @@ public final class ImageGalleryController {
setOpacity(.4); setOpacity(.4);
} }
}; };
private ListeningExecutorService dbExecutor; private ListeningExecutorService dbExecutor;
private Case autopsyCase;
public Case getAutopsyCase() {
return autopsyCase;
}
private SleuthkitCase sleuthKitCase; private SleuthkitCase sleuthKitCase;
private DrawableDB db; private DrawableDB db;
public static synchronized ImageGalleryController getDefault() { public static synchronized ImageGalleryController getDefault() {
if (instance == null) { if (instance == null) {
try { try {
@ -153,71 +158,71 @@ public final class ImageGalleryController {
} }
return instance; return instance;
} }
public ReadOnlyBooleanProperty getMetaDataCollapsed() { public ReadOnlyBooleanProperty getMetaDataCollapsed() {
return metaDataCollapsed.getReadOnlyProperty(); return metaDataCollapsed.getReadOnlyProperty();
} }
public void setMetaDataCollapsed(Boolean metaDataCollapsed) { public void setMetaDataCollapsed(Boolean metaDataCollapsed) {
this.metaDataCollapsed.set(metaDataCollapsed); this.metaDataCollapsed.set(metaDataCollapsed);
} }
public ReadOnlyDoubleProperty thumbnailSizeProperty() { public ReadOnlyDoubleProperty thumbnailSizeProperty() {
return thumbnailSize.getReadOnlyProperty(); return thumbnailSize.getReadOnlyProperty();
} }
public GroupViewState getViewState() { public GroupViewState getViewState() {
return historyManager.getCurrentState(); return historyManager.getCurrentState();
} }
public ReadOnlyBooleanProperty regroupDisabled() { public ReadOnlyBooleanProperty regroupDisabled() {
return regroupDisabled.getReadOnlyProperty(); return regroupDisabled.getReadOnlyProperty();
} }
public ReadOnlyObjectProperty<GroupViewState> viewState() { public ReadOnlyObjectProperty<GroupViewState> viewState() {
return historyManager.currentState(); return historyManager.currentState();
} }
public FileIDSelectionModel getSelectionModel() { public FileIDSelectionModel getSelectionModel() {
return selectionModel; return selectionModel;
} }
public GroupManager getGroupManager() { public GroupManager getGroupManager() {
return groupManager; return groupManager;
} }
synchronized public DrawableDB getDatabase() { synchronized public DrawableDB getDatabase() {
return db; return db;
} }
public void setListeningEnabled(boolean enabled) { public void setListeningEnabled(boolean enabled) {
synchronized (listeningEnabled) { synchronized (listeningEnabled) {
listeningEnabled.set(enabled); listeningEnabled.set(enabled);
} }
} }
boolean isListeningEnabled() { boolean isListeningEnabled() {
synchronized (listeningEnabled) { synchronized (listeningEnabled) {
return listeningEnabled.get(); return listeningEnabled.get();
} }
} }
@ThreadConfined(type = ThreadConfined.ThreadType.ANY) @ThreadConfined(type = ThreadConfined.ThreadType.ANY)
void setStale(Boolean b) { void setStale(Boolean b) {
Platform.runLater(() -> { Platform.runLater(() -> {
stale.set(b); stale.set(b);
}); });
} }
public ReadOnlyBooleanProperty stale() { public ReadOnlyBooleanProperty stale() {
return stale.getReadOnlyProperty(); return stale.getReadOnlyProperty();
} }
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
boolean isStale() { boolean isStale() {
return stale.get(); return stale.get();
} }
private ImageGalleryController() { private ImageGalleryController() {
// listener for the boolean property about when IG is listening / enabled // listener for the boolean property about when IG is listening / enabled
@ -231,40 +236,40 @@ public final class ImageGalleryController {
//populate the db //populate the db
this.rebuildDB(); this.rebuildDB();
} }
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Exception while getting open case.", ex); logger.log(Level.WARNING, "Exception while getting open case.", ex);
} }
}); });
groupManager.getAnalyzedGroups().addListener((Observable o) -> checkForGroups()); groupManager.getAnalyzedGroups().addListener((Observable o) -> checkForGroups());
viewState().addListener((Observable observable) -> { viewState().addListener((Observable observable) -> {
//when the viewed group changes, clear the selection and the undo/redo history //when the viewed group changes, clear the selection and the undo/redo history
selectionModel.clearSelection(); selectionModel.clearSelection();
undoManager.clear(); undoManager.clear();
}); });
regroupDisabled.addListener(observable -> checkForGroups()); regroupDisabled.addListener(observable -> checkForGroups());
IngestManager ingestManager = IngestManager.getInstance(); IngestManager ingestManager = IngestManager.getInstance();
PropertyChangeListener ingestEventHandler PropertyChangeListener ingestEventHandler
= propertyChangeEvent -> Platform.runLater(this::updateRegroupDisabled); = propertyChangeEvent -> Platform.runLater(this::updateRegroupDisabled);
ingestManager.addIngestModuleEventListener(ingestEventHandler); ingestManager.addIngestModuleEventListener(ingestEventHandler);
ingestManager.addIngestJobEventListener(ingestEventHandler); ingestManager.addIngestJobEventListener(ingestEventHandler);
dbTaskQueueSize.addListener(obs -> this.updateRegroupDisabled()); dbTaskQueueSize.addListener(obs -> this.updateRegroupDisabled());
} }
public ReadOnlyBooleanProperty getCanAdvance() { public ReadOnlyBooleanProperty getCanAdvance() {
return historyManager.getCanAdvance(); return historyManager.getCanAdvance();
} }
public ReadOnlyBooleanProperty getCanRetreat() { public ReadOnlyBooleanProperty getCanRetreat() {
return historyManager.getCanRetreat(); return historyManager.getCanRetreat();
} }
@ThreadConfined(type = ThreadConfined.ThreadType.ANY) @ThreadConfined(type = ThreadConfined.ThreadType.ANY)
public void advance(GroupViewState newState, boolean forceShowTree) { public void advance(GroupViewState newState, boolean forceShowTree) {
if (forceShowTree && showTree != null) { if (forceShowTree && showTree != null) {
@ -272,15 +277,15 @@ public final class ImageGalleryController {
} }
historyManager.advance(newState); historyManager.advance(newState);
} }
public GroupViewState advance() { public GroupViewState advance() {
return historyManager.advance(); return historyManager.advance();
} }
public GroupViewState retreat() { public GroupViewState retreat() {
return historyManager.retreat(); return historyManager.retreat();
} }
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private void updateRegroupDisabled() { private void updateRegroupDisabled() {
regroupDisabled.set((dbTaskQueueSize.get() > 0) || IngestManager.getInstance().isIngestRunning()); regroupDisabled.set((dbTaskQueueSize.get() > 0) || IngestManager.getInstance().isIngestRunning());
@ -313,7 +318,7 @@ public final class ImageGalleryController {
replaceNotification(fullUIStackPane, replaceNotification(fullUIStackPane,
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg1())); new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg1()));
} }
} else if (dbTaskQueueSize.get() > 0) { } else if (dbTaskQueueSize.get() > 0) {
replaceNotification(fullUIStackPane, replaceNotification(fullUIStackPane,
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg3(), new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg3(),
@ -333,18 +338,18 @@ public final class ImageGalleryController {
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error counting files in drawable db.", ex); logger.log(Level.SEVERE, "Error counting files in drawable db.", ex);
} }
} else if (false == groupManager.isRegrouping()) { } else if (false == groupManager.isRegrouping()) {
replaceNotification(centralStackPane, replaceNotification(centralStackPane,
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg6())); new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg6()));
} }
} else { } else {
Platform.runLater(this::clearNotification); Platform.runLater(this::clearNotification);
} }
} }
} }
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private void clearNotification() { private void clearNotification() {
//remove the ingest spinner //remove the ingest spinner
@ -356,11 +361,11 @@ public final class ImageGalleryController {
centralStackPane.getChildren().remove(infoOverlay); centralStackPane.getChildren().remove(infoOverlay);
} }
} }
private void replaceNotification(StackPane stackPane, Node newNode) { private void replaceNotification(StackPane stackPane, Node newNode) {
Platform.runLater(() -> { Platform.runLater(() -> {
clearNotification(); clearNotification();
infoOverlay = new StackPane(infoOverLayBackground, newNode); infoOverlay = new StackPane(infoOverLayBackground, newNode);
if (stackPane != null) { if (stackPane != null) {
stackPane.getChildren().add(infoOverlay); stackPane.getChildren().add(infoOverlay);
@ -379,9 +384,10 @@ public final class ImageGalleryController {
if (null == theNewCase) { if (null == theNewCase) {
reset(); reset();
} else { } else {
this.autopsyCase = theNewCase;
this.sleuthKitCase = theNewCase.getSleuthkitCase(); this.sleuthKitCase = theNewCase.getSleuthkitCase();
this.db = DrawableDB.getDrawableDB(ImageGalleryModule.getModuleOutputDir(theNewCase), this); this.db = DrawableDB.getDrawableDB(ImageGalleryModule.getModuleOutputDir(theNewCase), this);
setListeningEnabled(ImageGalleryModule.isEnabledforCase(theNewCase)); setListeningEnabled(ImageGalleryModule.isEnabledforCase(theNewCase));
setStale(ImageGalleryModule.isDrawableDBStale(theNewCase)); setStale(ImageGalleryModule.isDrawableDBStale(theNewCase));
@ -396,7 +402,7 @@ public final class ImageGalleryController {
tagsManager.unregisterListener(groupManager); tagsManager.unregisterListener(groupManager);
tagsManager.unregisterListener(categoryManager); tagsManager.unregisterListener(categoryManager);
} }
tagsManager = new DrawableTagsManager(theNewCase.getServices().getTagsManager()); tagsManager = new DrawableTagsManager(this);
tagsManager.registerListener(groupManager); tagsManager.registerListener(groupManager);
tagsManager.registerListener(categoryManager); tagsManager.registerListener(categoryManager);
shutDownDBExecutor(); shutDownDBExecutor();
@ -420,21 +426,22 @@ public final class ImageGalleryController {
*/ */
public synchronized void reset() { public synchronized void reset() {
logger.info("resetting ImageGalleryControler to initial state."); //NON-NLS logger.info("resetting ImageGalleryControler to initial state."); //NON-NLS
autopsyCase = null;
selectionModel.clearSelection(); selectionModel.clearSelection();
setListeningEnabled(false); setListeningEnabled(false);
ThumbnailCache.getDefault().clearCache(); ThumbnailCache.getDefault().clearCache();
historyManager.clear(); historyManager.clear();
groupManager.reset(); groupManager.reset();
tagsManager.unregisterListener(groupManager); tagsManager.unregisterListener(groupManager);
tagsManager.unregisterListener(categoryManager); tagsManager.unregisterListener(categoryManager);
tagsManager = null; tagsManager = null;
shutDownDBExecutor(); shutDownDBExecutor();
if (toolbar != null) { if (toolbar != null) {
toolbar.reset(); toolbar.reset();
} }
if (db != null) { if (db != null) {
db.closeDBCon(); db.closeDBCon();
} }
@ -460,17 +467,17 @@ public final class ImageGalleryController {
* @return list of data source object ids that are stale. * @return list of data source object ids that are stale.
*/ */
Set<Long> getStaleDataSourceIds() { Set<Long> getStaleDataSourceIds() {
Set<Long> staleDataSourceIds = new HashSet<>(); Set<Long> staleDataSourceIds = new HashSet<>();
// no current case open to check // no current case open to check
if ((null == getDatabase()) || (null == getSleuthKitCase())) { if ((null == getDatabase()) || (null == getSleuthKitCase())) {
return staleDataSourceIds; return staleDataSourceIds;
} }
try { try {
Map<Long, DrawableDbBuildStatusEnum> knownDataSourceIds = getDatabase().getDataSourceDbBuildStatus(); Map<Long, DrawableDbBuildStatusEnum> knownDataSourceIds = getDatabase().getDataSourceDbBuildStatus();
List<DataSource> dataSources = getSleuthKitCase().getDataSources(); List<DataSource> dataSources = getSleuthKitCase().getDataSources();
Set<Long> caseDataSourceIds = new HashSet<>(); Set<Long> caseDataSourceIds = new HashSet<>();
dataSources.forEach((dataSource) -> { dataSources.forEach((dataSource) -> {
@ -491,15 +498,15 @@ public final class ImageGalleryController {
staleDataSourceIds.add(id); staleDataSourceIds.add(id);
} }
}); });
return staleDataSourceIds; return staleDataSourceIds;
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Image Gallery failed to check if datasources table is stale.", ex); logger.log(Level.SEVERE, "Image Gallery failed to check if datasources table is stale.", ex);
return staleDataSourceIds; return staleDataSourceIds;
} }
} }
synchronized private void shutDownDBExecutor() { synchronized private void shutDownDBExecutor() {
if (dbExecutor != null) { if (dbExecutor != null) {
dbExecutor.shutdownNow(); dbExecutor.shutdownNow();
@ -510,7 +517,7 @@ public final class ImageGalleryController {
} }
} }
} }
private static ListeningExecutorService getNewDBExecutor() { private static ListeningExecutorService getNewDBExecutor() {
return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor( return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat("DB-Worker-Thread-%d").build())); new ThreadFactoryBuilder().setNameFormat("DB-Worker-Thread-%d").build()));
@ -527,17 +534,17 @@ public final class ImageGalleryController {
} }
incrementQueueSize(); incrementQueueSize();
dbExecutor.submit(bgTask).addListener(this::decrementQueueSize, MoreExecutors.directExecutor()); dbExecutor.submit(bgTask).addListener(this::decrementQueueSize, MoreExecutors.directExecutor());
} }
private void incrementQueueSize() { private void incrementQueueSize() {
Platform.runLater(() -> dbTaskQueueSize.set(dbTaskQueueSize.get() + 1)); Platform.runLater(() -> dbTaskQueueSize.set(dbTaskQueueSize.get() + 1));
} }
private void decrementQueueSize() { private void decrementQueueSize() {
Platform.runLater(() -> dbTaskQueueSize.set(dbTaskQueueSize.get() - 1)); Platform.runLater(() -> dbTaskQueueSize.set(dbTaskQueueSize.get() - 1));
} }
@Nullable @Nullable
synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException { synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException {
if (Objects.isNull(db)) { if (Objects.isNull(db)) {
@ -546,13 +553,13 @@ public final class ImageGalleryController {
} }
return db.getFileFromID(fileID); return db.getFileFromID(fileID);
} }
public void setStacks(StackPane fullUIStack, StackPane centralStack) { public void setStacks(StackPane fullUIStack, StackPane centralStack) {
fullUIStackPane = fullUIStack; fullUIStackPane = fullUIStack;
this.centralStackPane = centralStack; this.centralStackPane = centralStack;
Platform.runLater(this::checkForGroups); Platform.runLater(this::checkForGroups);
} }
public synchronized void setToolbar(Toolbar toolbar) { public synchronized void setToolbar(Toolbar toolbar) {
if (this.toolbar != null) { if (this.toolbar != null) {
throw new IllegalStateException("Can not set the toolbar a second time!"); throw new IllegalStateException("Can not set the toolbar a second time!");
@ -562,7 +569,7 @@ public final class ImageGalleryController {
// RAMAN TBD: bind filterByDataSourceId to the data source dropdown in the toolbar. // RAMAN TBD: bind filterByDataSourceId to the data source dropdown in the toolbar.
} }
public ReadOnlyDoubleProperty regroupProgress() { public ReadOnlyDoubleProperty regroupProgress() {
return groupManager.regroupProgress(); return groupManager.regroupProgress();
} }
@ -579,34 +586,34 @@ public final class ImageGalleryController {
IngestManager.getInstance().addIngestModuleEventListener(new IngestModuleEventListener()); IngestManager.getInstance().addIngestModuleEventListener(new IngestModuleEventListener());
Case.addPropertyChangeListener(new CaseEventListener()); Case.addPropertyChangeListener(new CaseEventListener());
} }
public HashSetManager getHashSetManager() { public HashSetManager getHashSetManager() {
return hashSetManager; return hashSetManager;
} }
public CategoryManager getCategoryManager() { public CategoryManager getCategoryManager() {
return categoryManager; return categoryManager;
} }
public DrawableTagsManager getTagsManager() { public DrawableTagsManager getTagsManager() {
return tagsManager; return tagsManager;
} }
public void setShowTree(Runnable showTree) { public void setShowTree(Runnable showTree) {
this.showTree = showTree; this.showTree = showTree;
} }
public UndoRedoManager getUndoManager() { public UndoRedoManager getUndoManager() {
return undoManager; return undoManager;
} }
public ReadOnlyIntegerProperty getDBTasksQueueSizeProperty() { public ReadOnlyIntegerProperty getDBTasksQueueSizeProperty() {
return dbTaskQueueSize.getReadOnlyProperty(); return dbTaskQueueSize.getReadOnlyProperty();
} }
public synchronized SleuthkitCase getSleuthKitCase() { public synchronized SleuthkitCase getSleuthKitCase() {
return sleuthKitCase; return sleuthKitCase;
} }
/** /**
@ -615,56 +622,56 @@ public final class ImageGalleryController {
@NbBundle.Messages({"ImageGalleryController.InnerTask.progress.name=progress", @NbBundle.Messages({"ImageGalleryController.InnerTask.progress.name=progress",
"ImageGalleryController.InnerTask.message.name=status"}) "ImageGalleryController.InnerTask.message.name=status"})
static public abstract class BackgroundTask implements Runnable, Cancellable { static public abstract class BackgroundTask implements Runnable, Cancellable {
private final SimpleObjectProperty<Worker.State> state = new SimpleObjectProperty<>(Worker.State.READY); private final SimpleObjectProperty<Worker.State> state = new SimpleObjectProperty<>(Worker.State.READY);
private final SimpleDoubleProperty progress = new SimpleDoubleProperty(this, Bundle.ImageGalleryController_InnerTask_progress_name()); private final SimpleDoubleProperty progress = new SimpleDoubleProperty(this, Bundle.ImageGalleryController_InnerTask_progress_name());
private final SimpleStringProperty message = new SimpleStringProperty(this, Bundle.ImageGalleryController_InnerTask_message_name()); private final SimpleStringProperty message = new SimpleStringProperty(this, Bundle.ImageGalleryController_InnerTask_message_name());
protected BackgroundTask() { protected BackgroundTask() {
} }
public double getProgress() { public double getProgress() {
return progress.get(); return progress.get();
} }
public final void updateProgress(Double workDone) { public final void updateProgress(Double workDone) {
this.progress.set(workDone); this.progress.set(workDone);
} }
public String getMessage() { public String getMessage() {
return message.get(); return message.get();
} }
public final void updateMessage(String Status) { public final void updateMessage(String Status) {
this.message.set(Status); this.message.set(Status);
} }
public SimpleDoubleProperty progressProperty() { public SimpleDoubleProperty progressProperty() {
return progress; return progress;
} }
public SimpleStringProperty messageProperty() { public SimpleStringProperty messageProperty() {
return message; return message;
} }
public Worker.State getState() { public Worker.State getState() {
return state.get(); return state.get();
} }
public ReadOnlyObjectProperty<Worker.State> stateProperty() { public ReadOnlyObjectProperty<Worker.State> stateProperty() {
return new ReadOnlyObjectWrapper<>(state.get()); return new ReadOnlyObjectWrapper<>(state.get());
} }
@Override @Override
public synchronized boolean cancel() { public synchronized boolean cancel() {
updateState(Worker.State.CANCELLED); updateState(Worker.State.CANCELLED);
return true; return true;
} }
protected void updateState(Worker.State newState) { protected void updateState(Worker.State newState) {
state.set(newState); state.set(newState);
} }
protected synchronized boolean isCancelled() { protected synchronized boolean isCancelled() {
return getState() == Worker.State.CANCELLED; return getState() == Worker.State.CANCELLED;
} }
@ -674,18 +681,18 @@ public final class ImageGalleryController {
* Abstract base class for tasks associated with a file in the database * Abstract base class for tasks associated with a file in the database
*/ */
static abstract class FileTask extends BackgroundTask { static abstract class FileTask extends BackgroundTask {
private final AbstractFile file; private final AbstractFile file;
private final DrawableDB taskDB; private final DrawableDB taskDB;
public DrawableDB getTaskDB() { public DrawableDB getTaskDB() {
return taskDB; return taskDB;
} }
public AbstractFile getFile() { public AbstractFile getFile() {
return file; return file;
} }
public FileTask(AbstractFile f, DrawableDB taskDB) { public FileTask(AbstractFile f, DrawableDB taskDB) {
super(); super();
this.file = f; this.file = f;
@ -697,7 +704,7 @@ public final class ImageGalleryController {
* task that updates one file in database with results from ingest * task that updates one file in database with results from ingest
*/ */
static private class UpdateFileTask extends FileTask { static private class UpdateFileTask extends FileTask {
UpdateFileTask(AbstractFile f, DrawableDB taskDB) { UpdateFileTask(AbstractFile f, DrawableDB taskDB) {
super(f, taskDB); super(f, taskDB);
} }
@ -724,7 +731,7 @@ public final class ImageGalleryController {
* task that updates one file in database with results from ingest * task that updates one file in database with results from ingest
*/ */
static private class RemoveFileTask extends FileTask { static private class RemoveFileTask extends FileTask {
RemoveFileTask(AbstractFile f, DrawableDB taskDB) { RemoveFileTask(AbstractFile f, DrawableDB taskDB) {
super(f, taskDB); super(f, taskDB);
} }
@ -745,7 +752,7 @@ public final class ImageGalleryController {
} }
} }
} }
@NbBundle.Messages({"BulkTask.committingDb.status=committing image/video database", @NbBundle.Messages({"BulkTask.committingDb.status=committing image/video database",
"BulkTask.stopCopy.status=Stopping copy to drawable db task.", "BulkTask.stopCopy.status=Stopping copy to drawable db task.",
"BulkTask.errPopulating.errMsg=There was an error populating Image Gallery database."}) "BulkTask.errPopulating.errMsg=There was an error populating Image Gallery database."})
@ -754,36 +761,36 @@ public final class ImageGalleryController {
* a given data source, into the Image gallery DB. * a given data source, into the Image gallery DB.
*/ */
abstract static private class BulkTransferTask extends BackgroundTask { abstract static private class BulkTransferTask extends BackgroundTask {
static private final String FILE_EXTENSION_CLAUSE static private final String FILE_EXTENSION_CLAUSE
= "(extension LIKE '" //NON-NLS = "(extension LIKE '" //NON-NLS
+ String.join("' OR extension LIKE '", FileTypeUtils.getAllSupportedExtensions()) //NON-NLS + String.join("' OR extension LIKE '", FileTypeUtils.getAllSupportedExtensions()) //NON-NLS
+ "') "; + "') ";
static private final String MIMETYPE_CLAUSE static private final String MIMETYPE_CLAUSE
= "(mime_type LIKE '" //NON-NLS = "(mime_type LIKE '" //NON-NLS
+ String.join("' OR mime_type LIKE '", FileTypeUtils.getAllSupportedMimeTypes()) //NON-NLS + String.join("' OR mime_type LIKE '", FileTypeUtils.getAllSupportedMimeTypes()) //NON-NLS
+ "') "; + "') ";
final String DRAWABLE_QUERY; final String DRAWABLE_QUERY;
final String DATASOURCE_CLAUSE; final String DATASOURCE_CLAUSE;
final ImageGalleryController controller; final ImageGalleryController controller;
final DrawableDB taskDB; final DrawableDB taskDB;
final SleuthkitCase tskCase; final SleuthkitCase tskCase;
final long dataSourceObjId; final long dataSourceObjId;
ProgressHandle progressHandle; ProgressHandle progressHandle;
private boolean taskCompletionStatus; private boolean taskCompletionStatus;
BulkTransferTask(long dataSourceObjId, ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) { BulkTransferTask(long dataSourceObjId, ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) {
this.controller = controller; this.controller = controller;
this.taskDB = taskDB; this.taskDB = taskDB;
this.tskCase = tskCase; this.tskCase = tskCase;
this.dataSourceObjId = dataSourceObjId; this.dataSourceObjId = dataSourceObjId;
DATASOURCE_CLAUSE = " (data_source_obj_id = " + dataSourceObjId + ") "; DATASOURCE_CLAUSE = " (data_source_obj_id = " + dataSourceObjId + ") ";
DRAWABLE_QUERY DRAWABLE_QUERY
= DATASOURCE_CLAUSE = DATASOURCE_CLAUSE
+ " AND ( " + " AND ( "
@ -811,24 +818,24 @@ public final class ImageGalleryController {
List<AbstractFile> getFiles() throws TskCoreException { List<AbstractFile> getFiles() throws TskCoreException {
return tskCase.findAllFilesWhere(DRAWABLE_QUERY); return tskCase.findAllFilesWhere(DRAWABLE_QUERY);
} }
abstract void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) throws TskCoreException; abstract void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) throws TskCoreException;
@Override @Override
public void run() { public void run() {
progressHandle = getInitialProgressHandle(); progressHandle = getInitialProgressHandle();
progressHandle.start(); progressHandle.start();
updateMessage(Bundle.CopyAnalyzedFiles_populatingDb_status()); updateMessage(Bundle.CopyAnalyzedFiles_populatingDb_status());
DrawableDB.DrawableTransaction drawableDbTransaction = null; DrawableDB.DrawableTransaction drawableDbTransaction = null;
CaseDbTransaction caseDbTransaction = null; CaseDbTransaction caseDbTransaction = null;
try { try {
//grab all files with supported extension or detected mime types //grab all files with supported extension or detected mime types
final List<AbstractFile> files = getFiles(); final List<AbstractFile> files = getFiles();
progressHandle.switchToDeterminate(files.size()); progressHandle.switchToDeterminate(files.size());
taskDB.insertOrUpdateDataSource(dataSourceObjId, DrawableDB.DrawableDbBuildStatusEnum.IN_PROGRESS); taskDB.insertOrUpdateDataSource(dataSourceObjId, DrawableDB.DrawableDbBuildStatusEnum.IN_PROGRESS);
updateProgress(0.0); updateProgress(0.0);
taskCompletionStatus = true; taskCompletionStatus = true;
int workDone = 0; int workDone = 0;
@ -841,27 +848,27 @@ public final class ImageGalleryController {
logger.log(Level.WARNING, "Task cancelled or interrupted: not all contents may be transfered to drawable database."); //NON-NLS logger.log(Level.WARNING, "Task cancelled or interrupted: not all contents may be transfered to drawable database."); //NON-NLS
taskCompletionStatus = false; taskCompletionStatus = false;
progressHandle.finish(); progressHandle.finish();
break; break;
} }
processFile(f, drawableDbTransaction, caseDbTransaction); processFile(f, drawableDbTransaction, caseDbTransaction);
workDone++; workDone++;
progressHandle.progress(f.getName(), workDone); progressHandle.progress(f.getName(), workDone);
updateProgress(workDone - 1 / (double) files.size()); updateProgress(workDone - 1 / (double) files.size());
updateMessage(f.getName()); updateMessage(f.getName());
} }
progressHandle.finish(); progressHandle.finish();
progressHandle = ProgressHandle.createHandle(Bundle.BulkTask_committingDb_status()); progressHandle = ProgressHandle.createHandle(Bundle.BulkTask_committingDb_status());
updateMessage(Bundle.BulkTask_committingDb_status()); updateMessage(Bundle.BulkTask_committingDb_status());
updateProgress(1.0); updateProgress(1.0);
progressHandle.start(); progressHandle.start();
caseDbTransaction.commit(); caseDbTransaction.commit();
taskDB.commitTransaction(drawableDbTransaction, true); taskDB.commitTransaction(drawableDbTransaction, true);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
if (null != drawableDbTransaction) { if (null != drawableDbTransaction) {
taskDB.rollbackTransaction(drawableDbTransaction); taskDB.rollbackTransaction(drawableDbTransaction);
@ -889,9 +896,9 @@ public final class ImageGalleryController {
} }
cleanup(taskCompletionStatus); cleanup(taskCompletionStatus);
} }
abstract ProgressHandle getInitialProgressHandle(); abstract ProgressHandle getInitialProgressHandle();
protected void setTaskCompletionStatus(boolean status) { protected void setTaskCompletionStatus(boolean status) {
taskCompletionStatus = status; taskCompletionStatus = status;
} }
@ -908,26 +915,26 @@ public final class ImageGalleryController {
"CopyAnalyzedFiles.stopCopy.status=Stopping copy to drawable db task.", "CopyAnalyzedFiles.stopCopy.status=Stopping copy to drawable db task.",
"CopyAnalyzedFiles.errPopulating.errMsg=There was an error populating Image Gallery database."}) "CopyAnalyzedFiles.errPopulating.errMsg=There was an error populating Image Gallery database."})
private class CopyAnalyzedFiles extends BulkTransferTask { private class CopyAnalyzedFiles extends BulkTransferTask {
CopyAnalyzedFiles(long dataSourceObjId, ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) { CopyAnalyzedFiles(long dataSourceObjId, ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) {
super(dataSourceObjId, controller, taskDB, tskCase); super(dataSourceObjId, controller, taskDB, tskCase);
} }
@Override @Override
protected void cleanup(boolean success) { protected void cleanup(boolean success) {
// at the end of the task, set the stale status based on the // at the end of the task, set the stale status based on the
// cumulative status of all data sources // cumulative status of all data sources
controller.setStale(isDataSourcesTableStale()); controller.setStale(isDataSourcesTableStale());
} }
@Override @Override
void processFile(AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDbTransaction) throws TskCoreException { void processFile(AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDbTransaction) throws TskCoreException {
final boolean known = f.getKnown() == TskData.FileKnown.KNOWN; final boolean known = f.getKnown() == TskData.FileKnown.KNOWN;
if (known) { if (known) {
taskDB.removeFile(f.getId(), tr); //remove known files taskDB.removeFile(f.getId(), tr); //remove known files
} else { } else {
try { try {
//supported mimetype => analyzed //supported mimetype => analyzed
if (null != f.getMIMEType() && FileTypeUtils.hasDrawableMIMEType(f)) { if (null != f.getMIMEType() && FileTypeUtils.hasDrawableMIMEType(f)) {
@ -947,7 +954,7 @@ public final class ImageGalleryController {
} }
} }
} }
@Override @Override
@NbBundle.Messages({"CopyAnalyzedFiles.populatingDb.status=populating analyzed image/video database",}) @NbBundle.Messages({"CopyAnalyzedFiles.populatingDb.status=populating analyzed image/video database",})
ProgressHandle getInitialProgressHandle() { ProgressHandle getInitialProgressHandle() {
@ -973,25 +980,25 @@ public final class ImageGalleryController {
PrePopulateDataSourceFiles(long dataSourceObjId, ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) { PrePopulateDataSourceFiles(long dataSourceObjId, ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) {
super(dataSourceObjId, controller, taskDB, tskCase); super(dataSourceObjId, controller, taskDB, tskCase);
} }
@Override @Override
protected void cleanup(boolean success) { protected void cleanup(boolean success) {
} }
@Override @Override
void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) { void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) {
taskDB.insertFile(DrawableFile.create(f, false, false), tr, caseDBTransaction); taskDB.insertFile(DrawableFile.create(f, false, false), tr, caseDBTransaction);
} }
@Override @Override
@NbBundle.Messages({"PrePopulateDataSourceFiles.prepopulatingDb.status=prepopulating image/video database",}) @NbBundle.Messages({"PrePopulateDataSourceFiles.prepopulatingDb.status=prepopulating image/video database",})
ProgressHandle getInitialProgressHandle() { ProgressHandle getInitialProgressHandle() {
return ProgressHandle.createHandle(Bundle.PrePopulateDataSourceFiles_prepopulatingDb_status(), this); return ProgressHandle.createHandle(Bundle.PrePopulateDataSourceFiles_prepopulatingDb_status(), this);
} }
} }
private class IngestModuleEventListener implements PropertyChangeListener { private class IngestModuleEventListener implements PropertyChangeListener {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (RuntimeProperties.runningWithGUI() == false) { if (RuntimeProperties.runningWithGUI() == false) {
@ -1022,7 +1029,7 @@ public final class ImageGalleryController {
* getOldValue has fileID getNewValue has * getOldValue has fileID getNewValue has
* {@link Abstractfile} * {@link Abstractfile}
*/ */
AbstractFile file = (AbstractFile) evt.getNewValue(); AbstractFile file = (AbstractFile) evt.getNewValue();
// only process individual files in realtime on the node that is running the ingest // only process individual files in realtime on the node that is running the ingest
@ -1053,9 +1060,9 @@ public final class ImageGalleryController {
} }
} }
} }
private class CaseEventListener implements PropertyChangeListener { private class CaseEventListener implements PropertyChangeListener {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (RuntimeProperties.runningWithGUI() == false) { if (RuntimeProperties.runningWithGUI() == false) {
@ -1092,7 +1099,7 @@ public final class ImageGalleryController {
} }
} }
break; break;
case CONTENT_TAG_ADDED: case CONTENT_TAG_ADDED:
final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) evt; final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) evt;
if (getDatabase().isInDB(tagAddedEvent.getAddedTag().getContent().getId())) { if (getDatabase().isInDB(tagAddedEvent.getAddedTag().getContent().getId())) {
@ -1113,7 +1120,7 @@ public final class ImageGalleryController {
* Listener for Ingest Job events. * Listener for Ingest Job events.
*/ */
private class IngestJobEventListener implements PropertyChangeListener { private class IngestJobEventListener implements PropertyChangeListener {
@NbBundle.Messages({ @NbBundle.Messages({
"ImageGalleryController.dataSourceAnalyzed.confDlg.msg= A new data source was added and finished ingest.\n" "ImageGalleryController.dataSourceAnalyzed.confDlg.msg= A new data source was added and finished ingest.\n"
+ "The image / video database may be out of date. " + "The image / video database may be out of date. "
@ -1128,15 +1135,15 @@ public final class ImageGalleryController {
// A remote node added a new data source and just finished ingest on it. // A remote node added a new data source and just finished ingest on it.
//drawable db is stale, and if ImageGallery is open, ask user what to do //drawable db is stale, and if ImageGallery is open, ask user what to do
setStale(true); setStale(true);
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
if (isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) { if (isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) {
int answer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(), int answer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(), Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(), Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
switch (answer) { switch (answer) {
case JOptionPane.YES_OPTION: case JOptionPane.YES_OPTION:
rebuildDB(); rebuildDB();

View File

@ -34,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
@ -58,7 +59,7 @@ public final class DrawableTagsManager {
private final TagName bookmarkTagName; private final TagName bookmarkTagName;
/** /**
* Used to distribute {@link TagsChangeEvent}s * Used to distribute TagsChangeEvents
*/ */
private final EventBus tagsEventBus private final EventBus tagsEventBus
= new AsyncEventBus( = new AsyncEventBus(
@ -70,10 +71,10 @@ public final class DrawableTagsManager {
}) })
.build())); .build()));
public DrawableTagsManager(TagsManager autopsyTagsManager) throws TskCoreException { public DrawableTagsManager(ImageGalleryController controller) throws TskCoreException {
this.autopsyTagsManager = autopsyTagsManager; this.autopsyTagsManager = controller.getAutopsyCase().getServices().getTagsManager();
followUpTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.followUp")); followUpTagName = getTagName(Bundle.DrawableTagsManager_followUp());
bookmarkTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.bookMark")); bookmarkTagName = getTagName(Bundle.DrawableTagsManager_bookMark());
} }
/** /**
@ -125,6 +126,8 @@ public final class DrawableTagsManager {
* *
* @return All the TagNames that are not categories, in alphabetical order * @return All the TagNames that are not categories, in alphabetical order
* by displayName. * by displayName.
*
* @throws org.sleuthkit.datamodel.TskCoreException
*/ */
public List<TagName> getNonCategoryTagNames() throws TskCoreException { public List<TagName> getNonCategoryTagNames() throws TskCoreException {