mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-30 14:29:51 +00:00
active listeners for tag and other events
This commit is contained in:
@@ -644,8 +644,11 @@ public final class FilteredEventsModel {
|
||||
return updatedEventIDs;
|
||||
}
|
||||
|
||||
synchronized Set<Long> setFileStatus(AbstractFile file) throws TskCoreException {
|
||||
Set<Long> updatedEventIDs = eventManager.setFileStatus(file);
|
||||
synchronized public Set<Long> setHashHit(Collection<BlackboardArtifact> artifacts, boolean hasHashHit) throws TskCoreException {
|
||||
Set<Long> updatedEventIDs = new HashSet<>();
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
updatedEventIDs.addAll(eventManager.setEventsHashed(artifact.getObjectID(), hasHashHit));
|
||||
}
|
||||
if (!updatedEventIDs.isEmpty()) {
|
||||
invalidateCaches(updatedEventIDs);
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.timeline;
|
||||
|
||||
/**
|
||||
* The org.openide.modules.OnStart annotation tells NetBeans to invoke this
|
||||
* class's run method.
|
||||
*/
|
||||
@org.openide.modules.OnStart
|
||||
public class OnStart implements Runnable {
|
||||
|
||||
/**
|
||||
* This method is invoked by virtue of the OnStart annotation on the this
|
||||
* class
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
TimeLineModule.onStart();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,19 +60,10 @@ public final class OpenTimelineAction extends CallableSystemAction {
|
||||
private static final Logger logger = Logger.getLogger(OpenTimelineAction.class.getName());
|
||||
private static final int FILE_LIMIT = 6_000_000;
|
||||
|
||||
private static TimeLineController timeLineController;
|
||||
|
||||
private final JMenuItem menuItem;
|
||||
private final JButton toolbarButton = new JButton(getName(),
|
||||
new ImageIcon(getClass().getResource("images/btn_icon_timeline_colorized_26.png"))); //NON-NLS
|
||||
|
||||
/**
|
||||
* Invalidate the reference to the controller so that a new one will be
|
||||
* instantiated the next time this action is invoked
|
||||
*/
|
||||
synchronized static void invalidateController() {
|
||||
timeLineController = null;
|
||||
}
|
||||
|
||||
public OpenTimelineAction() {
|
||||
toolbarButton.addActionListener(actionEvent -> performAction());
|
||||
@@ -95,11 +86,6 @@ public final class OpenTimelineAction extends CallableSystemAction {
|
||||
public void performAction() {
|
||||
if (tooManyFiles()) {
|
||||
Platform.runLater(PromptDialogManager::showTooManyFiles);
|
||||
synchronized (OpenTimelineAction.this) {
|
||||
if (timeLineController != null) {
|
||||
timeLineController.shutDownTimeLine();
|
||||
}
|
||||
}
|
||||
setEnabled(false);
|
||||
} else if ("false".equals(ModuleSettings.getConfigSetting("timeline", "enable_timeline"))) {
|
||||
Platform.runLater(PromptDialogManager::showTimeLineDisabledMessage);
|
||||
@@ -125,13 +111,8 @@ public final class OpenTimelineAction extends CallableSystemAction {
|
||||
logger.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS
|
||||
return;
|
||||
}
|
||||
if (timeLineController == null) {
|
||||
timeLineController = new TimeLineController(currentCase);
|
||||
} else if (timeLineController.getAutopsyCase() != currentCase) {
|
||||
timeLineController.shutDownTimeLine();
|
||||
timeLineController = new TimeLineController(currentCase);
|
||||
}
|
||||
timeLineController.showTimeLine(file, artifact);
|
||||
TimeLineController controller = TimeLineModule.getController();
|
||||
controller.showTimeLine(file, artifact);
|
||||
} catch (NoCurrentCaseException e) {
|
||||
//there is no case... Do nothing.
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.autopsy.timeline.events.ViewInTimelineRequestedEvent;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.DetailViewEvent;
|
||||
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState;
|
||||
@@ -86,6 +87,7 @@ import org.sleuthkit.datamodel.timeline.EventType;
|
||||
import org.sleuthkit.datamodel.timeline.EventTypeZoomLevel;
|
||||
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.TimeUnits;
|
||||
import org.sleuthkit.datamodel.TimelineManager;
|
||||
import org.sleuthkit.datamodel.timeline.TimelineFilter.DescriptionFilter;
|
||||
import org.sleuthkit.datamodel.timeline.TimelineFilter.TypeFilter;
|
||||
|
||||
@@ -194,9 +196,6 @@ public class TimeLineController {
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
private boolean listeningToAutopsy = false;
|
||||
|
||||
private final PropertyChangeListener caseListener = new AutopsyCaseListener();
|
||||
private final PropertyChangeListener ingestModuleListener = new AutopsyIngestModuleListener();
|
||||
|
||||
@GuardedBy("this")
|
||||
private final ReadOnlyObjectWrapper<ViewMode> viewMode = new ReadOnlyObjectWrapper<>(ViewMode.COUNTS);
|
||||
|
||||
@@ -280,7 +279,7 @@ public class TimeLineController {
|
||||
return viewMode.get();
|
||||
}
|
||||
|
||||
public TimeLineController(Case autoCase) throws TskCoreException {
|
||||
TimeLineController(Case autoCase) throws TskCoreException {
|
||||
this.autoCase = autoCase;
|
||||
filteredEvents = new FilteredEventsModel(autoCase, currentParams.getReadOnlyProperty());
|
||||
/*
|
||||
@@ -383,14 +382,10 @@ public class TimeLineController {
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
public void shutDownTimeLine() {
|
||||
listeningToAutopsy = false;
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener);
|
||||
Case.removePropertyChangeListener(caseListener);
|
||||
if (topComponent != null) {
|
||||
topComponent.close();
|
||||
topComponent = null;
|
||||
}
|
||||
OpenTimelineAction.invalidateController();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,12 +398,6 @@ public class TimeLineController {
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void showTimeLine(AbstractFile file, BlackboardArtifact artifact) {
|
||||
// listen for case changes (specifically images being added, and case changes).
|
||||
if (Case.isCaseOpen() && !listeningToAutopsy) {
|
||||
IngestManager.getInstance().addIngestModuleEventListener(ingestModuleListener);
|
||||
Case.addPropertyChangeListener(caseListener);
|
||||
listeningToAutopsy = true;
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
//if there is an existing prompt or progressdialog,...
|
||||
if (promptDialogManager.bringCurrentDialogToFront()) {
|
||||
@@ -726,14 +715,8 @@ public class TimeLineController {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for IngestManager.IngestModuleEvents.
|
||||
*/
|
||||
@Immutable
|
||||
private class AutopsyIngestModuleListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
void handleIngestModuleEvent(PropertyChangeEvent evt) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
@@ -746,30 +729,39 @@ public class TimeLineController {
|
||||
// Case is closed, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore remote events. The node running the ingest should update the Case DB
|
||||
// @@@ We should signal though that there is more data and flush caches...
|
||||
if (((AutopsyEvent) evt).getSourceType() == AutopsyEvent.SourceType.REMOTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
|
||||
case CONTENT_CHANGED:
|
||||
// new files were already added to the events table from SleuthkitCase.
|
||||
break;
|
||||
case DATA_ADDED:
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
executor.submit(() -> filteredEvents.setHashHit(eventData.getArtifacts(), true));
|
||||
}
|
||||
break;
|
||||
case FILE_DONE:
|
||||
/*
|
||||
* Since the known state or hash hit state may have changed
|
||||
* invalidate caches.
|
||||
*/
|
||||
executor.submit(filteredEvents::invalidateAllCaches);
|
||||
//@@@ This causes HUGE slow downs during ingest when TL is open.
|
||||
// executor.submit(filteredEvents::invalidateAllCaches);
|
||||
|
||||
// known state should have been udpated automatically via SleuthkitCase.setKnown();
|
||||
// hashes should have been updated from event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for Case.Events
|
||||
*/
|
||||
@Immutable
|
||||
private class AutopsyCaseListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
||||
|
||||
void handleCaseEvent(PropertyChangeEvent evt) {
|
||||
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
||||
case BLACKBOARD_ARTIFACT_TAG_ADDED:
|
||||
executor.submit(() -> filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt));
|
||||
break;
|
||||
@@ -793,6 +785,6 @@ public class TimeLineController {
|
||||
executor.submit(filteredEvents::invalidateAllCaches);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.timeline;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javafx.application.Platform;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
|
||||
/**
|
||||
* Manages listeners and the controller.
|
||||
*
|
||||
*/
|
||||
public class TimeLineModule {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TimeLineModule.class.getName());
|
||||
|
||||
private static final Object controllerLock = new Object();
|
||||
private static TimeLineController controller;
|
||||
|
||||
/**
|
||||
* provides static utilities, can not be instantiated
|
||||
*/
|
||||
private TimeLineModule() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance of the controller for the current case
|
||||
* @return
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
public static TimeLineController getController() throws NoCurrentCaseException {
|
||||
synchronized (controllerLock) {
|
||||
if (controller == null) {
|
||||
try {
|
||||
controller = new TimeLineController(Case.getCurrentCaseThrows());
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
throw new NoCurrentCaseException("Error getting TimeLineController for the current case.", ex);
|
||||
}
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked by virtue of the OnStart annotation on the OnStart
|
||||
* class class
|
||||
*/
|
||||
static void onStart() {
|
||||
Platform.setImplicitExit(false);
|
||||
logger.info("Setting up TimeLine listeners"); //NON-NLS
|
||||
|
||||
IngestManager.getInstance().addIngestModuleEventListener(new IngestModuleEventListener());
|
||||
Case.addPropertyChangeListener(new CaseEventListener());
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for case events.
|
||||
*/
|
||||
static private class CaseEventListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
try {
|
||||
TimeLineController tlController = getController();
|
||||
tlController.handleCaseEvent(evt);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
||||
case CURRENT_CASE:
|
||||
// we care only about case closing here
|
||||
if (evt.getNewValue() != null) {
|
||||
break;
|
||||
}
|
||||
synchronized (controllerLock) {
|
||||
if (controller != null) {
|
||||
controller.shutDownTimeLine();
|
||||
}
|
||||
controller = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for IngestModuleEvents
|
||||
*/
|
||||
static private class IngestModuleEventListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
try {
|
||||
TimeLineController tlController = getController();
|
||||
tlController.handleIngestModuleEvent(evt);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* A TagsUpdatedEvent for tags that have been added to events.
|
||||
* NOTE: This event is internal to timeline components
|
||||
*/
|
||||
public class TagsAddedEvent extends TagsUpdatedEvent {
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* A TagsUpdatedEvent for tags that have been removed from events.
|
||||
* NOTE: This event is internal to timeline components
|
||||
*/
|
||||
public class TagsDeletedEvent extends TagsUpdatedEvent {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user