Add local/remote event support for Case events

This commit is contained in:
Richard Cordovano 2015-04-28 13:58:08 -04:00
parent c1a505b9f1
commit 23344ce98b
8 changed files with 211 additions and 226 deletions

View File

@ -45,6 +45,7 @@ import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent;
import org.sleuthkit.autopsy.casemodule.services.Services;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
@ -53,6 +54,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.datamodel.*;
@ -75,11 +77,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
*/
public static final String propStartup = "LBL_StartupDialog"; //NON-NLS
// RJCTODO: Replace PropertyChangeSupport with AutopsyEventPublisher.
private static final PropertyChangeSupport pcs = new PropertyChangeSupport(Case.class);
private static final Set<String> eventNames = Stream.of(Events.values())
.map(Events::toString)
.collect(Collectors.toSet());
private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher();
/**
@ -90,12 +87,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
/**
* Property name that indicates the name of the current case has
* changed. When a case is opened, "old name" is empty string and "new
* name" is the name. When a case is closed, "old name" is the case name
* and "new name" is empty string. When a case is renamed, "old name"
* has the original name and "new name" has the new name.
* changed. The old value is the old case name, the new value is the new
* case name.
*/
// @@@ BC: I propose that this is no longer called for case open/close.
NAME,
/**
* Property name that indicates the number of the current case has
@ -205,16 +199,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
this.caseType = type;
this.db = db;
this.services = new Services(db);
if (CaseType.MULTI_USER_CASE == this.caseType) {
try {
eventPublisher.openRemoteEventChannel(name);
} catch (AutopsyEventException ex) {
logger.log(Level.SEVERE, "Failed to start remote event publisher", ex);
MessageNotifyUtil.Message.error(NbBundle.getMessage(Case.class,
"Case.OpenEventChannel.ErrMsg",
name));
}
}
}
/**
@ -261,58 +245,30 @@ public class Case implements SleuthkitCase.ErrorObserver {
Case oldCase = Case.currentCase;
Case.currentCase = null;
if (oldCase != null) {
doCaseChange(null); //closes windows, etc
try {
pcs.firePropertyChange(Events.CURRENT_CASE.toString(), oldCase, null);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
NbBundle.getMessage(Case.class,
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
doCaseNameChange("");
try {
pcs.firePropertyChange(Events.NAME.toString(), oldCase.name, "");
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
NbBundle.getMessage(Case.class,
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
doCaseChange(null); //closes windows, etc
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), oldCase, null));
if (CaseType.MULTI_USER_CASE == oldCase.getCaseType()) {
eventPublisher.closeRemoteEventChannel();
}
}
if (newCase != null) {
currentCase = newCase;
Logger.setLogDirectory(currentCase.getLogDirectoryPath());
try {
pcs.firePropertyChange(Events.CURRENT_CASE.toString(), null, currentCase);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
NbBundle.getMessage(Case.class,
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
doCaseChange(currentCase);
try {
pcs.firePropertyChange(Events.NAME.toString(), "", currentCase.name);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
NbBundle.getMessage(Case.class,
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
doCaseNameChange(currentCase.name);
updateMainWindowTitle(currentCase.name);
RecentCases.getInstance().addRecentCase(currentCase.name, currentCase.configFilePath); // update the recent cases
if (CaseType.MULTI_USER_CASE == newCase.getCaseType()) {
try {
eventPublisher.openRemoteEventChannel(newCase.getName());
} catch (AutopsyEventException ex) {
logger.log(Level.SEVERE, "Failed to start remote event publisher", ex);
MessageNotifyUtil.Message.error(NbBundle.getMessage(Case.class,
"Case.OpenEventChannel.ErrMsg",
newCase.getName()));
}
}
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase));
} else {
Logger.setLogDirectory(PlatformUtil.getLogDirectory());
}
@ -525,25 +481,14 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @param imgPaths the paths of the image that being added
* @param imgId the ID of the image that being added
* @param timeZone the timeZone of the image where it's added
* @deprecated Use notifyNewDataSource() instead.
*/
@Deprecated
public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException {
logger.log(Level.INFO, "Adding image to Case. imgPath: {0} ID: {1} TimeZone: {2}", new Object[]{imgPath, imgId, timeZone}); //NON-NLS
try {
Image newImage = db.getImageById(imgId);
try {
pcs.firePropertyChange(Events.DATA_SOURCE_ADDED.toString(), null, newImage); // the new value is the instance of the image
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
NbBundle.getMessage(this.getClass(),
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
CoreComponentControl.openCoreWindows();
return newImage;
Image newDataSource = db.getImageById(imgId);
notifyNewDataSource(newDataSource);
return newDataSource;
} catch (Exception ex) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.addImg.exception.msg"), ex);
}
@ -554,6 +499,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* reopens windows if needed.
*
* @param newDataSource new data source added
* @deprecated Use notifyNewDataSource() instead.
*/
@Deprecated
void addLocalDataSource(Content newDataSource) {
@ -563,20 +509,10 @@ public class Case implements SleuthkitCase.ErrorObserver {
/**
* Notifies the UI that a new data source has been added.
*
*
* @param newDataSource new data source added
*/
void notifyNewDataSource(Content newDataSource) {
try {
pcs.firePropertyChange(Events.DATA_SOURCE_ADDED.toString(), null, newDataSource);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
NbBundle.getMessage(this.getClass(),
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
eventPublisher.publish(new DataSourceAddedEvent(newDataSource));
CoreComponentControl.openCoreWindows();
}
@ -603,9 +539,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
public void closeCase() throws CaseActionException {
changeCase(null);
try {
if (CaseType.MULTI_USER_CASE == this.caseType) {
eventPublisher.closeRemoteEventChannel();
}
services.close();
this.xmlcm.close(); // close the xmlcm
this.db.close();
@ -655,17 +588,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
xmlcm.setCaseName(newCaseName); // set the case
name = newCaseName; // change the local value
RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case
try {
pcs.firePropertyChange(Events.NAME.toString(), oldCaseName, newCaseName);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
NbBundle.getMessage(this.getClass(),
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
doCaseNameChange(newCaseName);
eventPublisher.publish(new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName));
updateMainWindowTitle(newCaseName);
} catch (Exception e) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseName.exception.msg"), e);
}
@ -681,15 +605,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
try {
xmlcm.setCaseExaminer(newExaminer); // set the examiner
examiner = newExaminer;
try {
pcs.firePropertyChange(Events.EXAMINER.toString(), oldExaminer, newExaminer);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
NbBundle.getMessage(this.getClass(),
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
eventPublisher.publish(new AutopsyEvent(Events.EXAMINER.toString(), oldExaminer, newExaminer));
} catch (Exception e) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateExaminer.exception.msg"), e);
}
@ -705,16 +621,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
try {
xmlcm.setCaseNumber(newCaseNumber); // set the case number
number = newCaseNumber;
try {
pcs.firePropertyChange(Events.NUMBER.toString(), oldCaseNumber, newCaseNumber);
} catch (Exception e) {
logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
NbBundle.getMessage(this.getClass(),
"Case.changeCase.errListenToCaseUpdates.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
eventPublisher.publish(new AutopsyEvent(Events.NUMBER.toString(), oldCaseNumber, newCaseNumber));
} catch (Exception e) {
throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseNum.exception.msg"), e);
}
@ -917,12 +824,14 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
/**
* get the PropertyChangeSupport of this class
* Gets a new PropertyChangeSupport object.
*
* @return PropertyChangeSupport
* @return A new PropertyChangeSupport object with source set to null.
* @deprecated Do not use.
*/
@Deprecated
public static PropertyChangeSupport getPropertyChangeSupport() {
return pcs;
return new PropertyChangeSupport(null);
}
/**
@ -958,20 +867,35 @@ public class Case implements SleuthkitCase.ErrorObserver {
return timezones;
}
// RJCTODO: Deprecate in favor of addEventSubscriber() and remove use of PropertyChangeSupport
/**
* Adds a subscriber to all case events from this Autopsy node and other
* Autopsy nodes. To subscribe to only specific events, use one of the
* overloads of addEventSubscriber().
*
* @param listener The subscriber to add.
*/
public static synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
// eventPublisher.addSubscriber(eventNames, listener);
}
// RJCTODO: Deprecate in favor of removeEventSubscriber() and remove use of PropertyChangeSupport
public static synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
// eventPublisher.removeSubscriber(eventNames, listener);
addEventSubscriber(Stream.of(Events.values())
.map(Events::toString)
.collect(Collectors.toSet()), listener);
}
/**
* Adds a subscriber to events from this Autopsy node and other Autopsy nodes.
* Removes a subscriber from all case events from this Autopsy node and
* other Autopsy nodes. To remove a subscription to only specific events,
* use one of the overloads of removeEventSubscriber().
*
* @param listener The subscriber to add.
*/
public static synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
removeEventSubscriber(Stream.of(Events.values())
.map(Events::toString)
.collect(Collectors.toSet()), listener);
}
/**
* Adds a subscriber to events from this Autopsy node and other Autopsy
* nodes.
*
* @param eventNames The events the subscriber is interested in.
* @param subscriber The subscriber to add.
@ -981,7 +905,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
/**
* Adds a subscriber to events from this Autopsy node and other Autopsy nodes.
* Adds a subscriber to events from this Autopsy node and other Autopsy
* nodes.
*
* @param eventNames The event the subscriber is interested in.
* @param subscriber The subscriber to add.
@ -991,7 +916,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
/**
* Adds a subscriber to events from this Autopsy node and other Autopsy nodes.
* Adds a subscriber to events from this Autopsy node and other Autopsy
* nodes.
*
* @param eventName The event the subscriber is no longer interested in.
* @param subscriber The subscriber to add.
@ -1001,7 +927,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
/**
* Removes a subscriber to events from this Autopsy node and other Autopsy nodes.
* Removes a subscriber to events from this Autopsy node and other Autopsy
* nodes.
*
* @param eventNames The event the subscriber is no longer interested in.
* @param subscriber The subscriber to add.
@ -1301,7 +1228,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
//case name change helper
private static void doCaseNameChange(String newCaseName) {
private static void updateMainWindowTitle(String newCaseName) {
// update case name
if (!newCaseName.equals("")) {
Frame f = WindowManager.getDefault().getMainWindow();
@ -1309,15 +1236,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
}
//delete image helper
private void doDeleteImage() {
// no more image left in this case
if (currentCase.hasData()) {
// close all top components
CoreComponentControl.closeCoreWindows();
}
}
@Override
public void receiveError(String context, String errorMessage) {
MessageNotifyUtil.Notify.error(context, errorMessage);
@ -1336,12 +1254,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
*/
public void addReport(String localPath, String srcModuleName, String reportName) throws TskCoreException {
Report report = this.db.addReport(localPath, srcModuleName, reportName);
try {
Case.pcs.firePropertyChange(Events.REPORT_ADDED.toString(), null, report);
} catch (Exception ex) {
String errorMessage = String.format("A Case %s listener threw an exception", Events.REPORT_ADDED.toString()); //NON-NLS
logger.log(Level.SEVERE, errorMessage, ex);
}
eventPublisher.publish(new AutopsyEvent(Events.REPORT_ADDED.toString(), null, report));
}
public List<Report> getAllReports() throws TskCoreException {

View File

@ -0,0 +1,82 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 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.casemodule.events;
import java.io.Serializable;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Event published when a data source is added to a case.
*/
public final class DataSourceAddedEvent extends AutopsyEvent implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DataSourceAddedEvent.class.getName());
private transient Content dataSource;
/**
* Constructs an event published when a data source is added to a case.
*
* @param dataSource The data source that was added.
*/
public DataSourceAddedEvent(Content dataSource) {
/**
* Putting the object id of the data source into newValue to allow for
* lazy loading of the Content object. This bypasses the issues related
* to the serialization and de-serialization of Content objects when the
* event is published over a network.
*/
super(Case.Events.DATA_SOURCE_ADDED.toString(), null, dataSource.getId());
this.dataSource = dataSource;
}
/**
* Gets the data source that was added.
*
* @return The data source.
*/
@Override
public Object getNewValue() {
/**
* The dataSource field is set in the constructor, but it is transient
* so it will become null when the event is serialized for publication
* over a network. Doing a lazy load of the Content object bypasses the
* issues related to the serialization and de-serialization of Content
* objects and may also save database round trips from other nodes since
* subscribers to this event are often not interested in the event data.
*/
if (null != dataSource) {
return dataSource;
}
try {
long id = (Long) super.getOldValue();
dataSource = Case.getCurrentCase().getSleuthkitCase().getContentById(id);
return dataSource;
} catch (IllegalStateException | TskCoreException ex) {
logger.log(Level.SEVERE, "Error doing lazy load for remote event", ex);
return null;
}
}
}

View File

@ -27,6 +27,7 @@ import java.beans.PropertyVetoException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
@ -117,7 +118,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
subscribeToChangeEvents();
associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
this.pcs = new PropertyChangeSupport(this);
// set the back & forward list and also disable the back & forward button
@ -144,7 +144,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
}
}
});
Case.addPropertyChangeListener(this);
Case.addEventSubscriber(new HashSet<>(Arrays.asList(Case.Events.CURRENT_CASE.toString(), Case.Events.DATA_SOURCE_ADDED.toString())), this);
this.em.addPropertyChangeListener(this);
IngestManager.getInstance().addIngestJobEventListener(this);
IngestManager.getInstance().addIngestModuleEventListener(this);
@ -245,9 +245,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
forwardList.addLast(currentNodePath);
forwardButton.setEnabled(true);
/* We peek instead of poll because we use its existence
* in the list later on so that we do not reset the forward list
* after the selection occurs. */
/*
* We peek instead of poll because we use its existence in the list
* later on so that we do not reset the forward list after the selection
* occurs.
*/
String[] newCurrentNodePath = backList.peekLast();
// enable / disable the back and forward button
@ -388,7 +390,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
root = new DirectoryTreeFilterNode(root, true);
em.setRootContext(root);
em.getRootContext().setName(currentCase.getName());
em.getRootContext().setDisplayName(currentCase.getName());
@ -407,7 +408,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
tree.expandNode(resultsChilds.findChild(KeywordHits.NAME));
tree.expandNode(resultsChilds.findChild(ExtractedContent.NAME));
Node views = childNodes.findChild(ViewsNode.NAME);
Children viewsChilds = views.getChildren();
for (Node n : viewsChilds.getNodes()) {
@ -421,7 +421,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
dataResult.open(); // open the data result top component as well when the directory tree is opened
}
// select the first image node, if there is one
// (this has to happen after dataResult is opened, because the event
// of changing the selected node fires a handler that tries to make
@ -534,22 +533,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
String changed = evt.getPropertyName();
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
// change in the case name
if (changed.equals(Case.Events.NAME.toString())) {
// set the main title of the window
String oldCaseName = oldValue.toString();
String newCaseName = newValue.toString();
// update the case name
if ((!oldCaseName.equals("")) && (!newCaseName.equals(""))) {
// change the root name and display name
em.getRootContext().setName(newCaseName);
em.getRootContext().setDisplayName(newCaseName);
}
} // changed current case
else if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case
// When a case is closed, the old value of this property is the
// closed Case object and the new value is null. When a case is
// opened, the old value is null and the new value is the new Case
@ -563,7 +547,13 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
Node emptyNode = new AbstractNode(Children.LEAF);
em.setRootContext(emptyNode);
} else if (newValue != null) {
// A new case has been opened. Reset the forward and back
// A new case has been opened. Reset the ExplorerManager.
Case newCase = (Case) newValue;
String newCaseName = newCase.getName();
em.getRootContext().setName(newCaseName);
em.getRootContext().setDisplayName(newCaseName);
// Reset the forward and back
// buttons. Note that a call to CoreComponentControl.openCoreWindows()
// by the new Case object will lead to a componentOpened() call
// that will repopulate the tree.
@ -574,12 +564,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
} // if the image is added to the case
else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
componentOpened();
}
// change in node selection
} // change in node selection
else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
respondSelection((Node[]) oldValue, (Node[]) newValue);
}
else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
} else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
// nothing to do here.
// all nodes should be listening for these events and update accordingly.
} else if (changed.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
@ -615,7 +603,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
return;
}
// Some lock that prevents certain Node operations is set during the
// ExplorerManager selection-change, so we must handle changes after the
// selection-change event is processed.
@ -630,7 +617,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// make sure dataResult is open, redundant?
//dataResult.open();
Node treeNode = DirectoryTreeTopComponent.this.getSelectedNode();
if (treeNode != null) {
DirectoryTreeFilterNode.OriginalNode origin = treeNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
@ -687,10 +673,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
Node selectedNode = selectedNodes[0];
String selectedNodeName = selectedNode.getName();
/* get the previous entry to make sure we don't duplicate it.
* Motivation for this is also that if we used the back button,
* then we already added the 'current' node to 'back' and we will
* detect that and not reset the forward list.
/*
* get the previous entry to make sure we don't duplicate it. Motivation
* for this is also that if we used the back button, then we already
* added the 'current' node to 'back' and we will detect that and not
* reset the forward list.
*/
String[] currentLast = backList.peekLast();
String lastNodeName = null;
@ -783,7 +770,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
//final TreeView tree = getTree();
//tree.expandNode(imagesNode);
setSelectedNode(selectedPath, DataSourcesNode.NAME);
}
@ -838,7 +824,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// //@@@ setSelectedNode(selectedPath, ResultsNode.NAME);
//
// }
/**
* Set the selected node using a path to a previously selected node.
*
@ -975,11 +960,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
}
treeNode = extractedChilds.findChild(type.getLabel());
}
if (treeNode == null) {
return;
}
try {
em.setExploredContextAndSelection(treeNode, new Node[]{treeNode});
} catch (PropertyVetoException ex) {
@ -1025,7 +1010,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
logger.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
NbBundle.getMessage(this.getClass(),
"DirectoryTreeTopComponent.moduleErr.msg"),
"DirectoryTreeTopComponent.moduleErr.msg"),
MessageNotifyUtil.MessageType.ERROR);
}
}

View File

@ -125,18 +125,28 @@ public final class AutopsyEventPublisher {
}
/**
* Publishes an event.
* Publishes an event to this Autopsy node and other Autopsy nodes.
*
* @param event The event to publish.
* @throws JMSException
*/
synchronized public void publish(AutopsyEvent event) throws JMSException {
event.setSourceType(AutopsyEvent.SourceType.LOCAL);
localPublisher.publish(event);
synchronized public void publish(AutopsyEvent event) {
publishLocally(event);
if (null != remotePublisher) {
event.setSourceType(AutopsyEvent.SourceType.REMOTE);
remotePublisher.send(event);
try {
remotePublisher.publish(event);
} catch (JMSException ex) {
logger.log(Level.SEVERE, String.format("Failed to publish %s event remotely", event.getPropertyName()), ex); //NON-NLS
}
}
}
/**
* Publishes an event to this Autopsy node only.
*
* @param event The event to publish.
*/
synchronized public void publishLocally(AutopsyEvent event) {
localPublisher.publish(event);
}
}

View File

@ -74,7 +74,7 @@ final class RemoteEventPublisher {
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(eventChannelName);
producer = session.createProducer(topic);
MessageConsumer consumer = session.createConsumer(topic, "events = '" + ALL_MESSAGE_SELECTOR + "'", true);
MessageConsumer consumer = session.createConsumer(topic, "events = '" + ALL_MESSAGE_SELECTOR + "'", true); // RJCTODO: Can I use the empty string?
receiver = new MessageReceiver();
consumer.setMessageListener(receiver);
} catch (URISyntaxException | JMSException ex) {
@ -102,9 +102,9 @@ final class RemoteEventPublisher {
/**
* Sends an event message to the message service.
*
* @param event The event to send.
* @param event The event to publish.
*/
synchronized void send(AutopsyEvent event) throws JMSException {
synchronized void publish(AutopsyEvent event) throws JMSException {
ObjectMessage message = session.createObjectMessage();
message.setStringProperty("events", ALL_MESSAGE_SELECTOR);
message.setObject(event);
@ -131,6 +131,7 @@ final class RemoteEventPublisher {
Object object = objectMessage.getObject();
if (object instanceof AutopsyEvent) {
AutopsyEvent event = (AutopsyEvent) object;
event.setSourceType(AutopsyEvent.SourceType.REMOTE);
localPublisher.publish(event);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -160,7 +160,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
private static List<String> createTimeZoneList() {
List<String> timeZones = new ArrayList<String>();
List<String> timeZones = new ArrayList<>();
if (Case.existsCurrentCase()) {
// get the latest case
@ -241,7 +241,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
if (changed.equals(Case.Events.CURRENT_CASE.toString().toString())) {
if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
// create or open a case
if (newValue != null) {
DateSearchFilter.this.updateTimeZoneList();

View File

@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.jms.JMSException;
import javax.swing.JOptionPane;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
@ -283,15 +282,13 @@ public class IngestManager {
* Subscribes this ingest manager to local and remote case-related events.
*/
private void subscribeToCaseEvents() {
Case.addPropertyChangeListener(new PropertyChangeListener() {
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
if (event.getNewValue() != null) {
handleCaseOpened();
} else {
handleCaseClosed();
}
if (event.getNewValue() != null) {
handleCaseOpened();
} else {
handleCaseClosed();
}
}
});
@ -309,16 +306,16 @@ public class IngestManager {
} catch (AutopsyEventException ex) {
logger.log(Level.SEVERE, "Failed to open remote job events channel", ex); //NON-NLS
MessageNotifyUtil.Message.error(NbBundle.getMessage(IngestManager.class,
"IngestManager.OpenEventChannel.ErrMsg",
caseName));
"IngestManager.OpenEventChannel.ErrMsg",
caseName));
}
try {
moduleEventPublisher.openRemoteEventChannel(String.format(MODULE_EVENT_CHANNEL_NAME, caseName));
} catch (AutopsyEventException ex) {
logger.log(Level.SEVERE, "Failed to open remote module events channel", ex); //NON-NLS
MessageNotifyUtil.Message.error(NbBundle.getMessage(IngestManager.class,
"IngestManager.OpenEventChannel.ErrMsg",
caseName));
"IngestManager.OpenEventChannel.ErrMsg",
caseName));
}
}
} catch (IllegalStateException ex) {
@ -889,11 +886,7 @@ public class IngestManager {
*/
@Override
public void run() {
try {
publisher.publish(event);
} catch (JMSException ex) {
logger.log(Level.SEVERE, String.format("Failed to publish %s event to remote subscribers", event.getPropertyName()), ex);
}
publisher.publish(event);
}
}

View File

@ -52,6 +52,7 @@ public final class FileAnalyzedEvent extends AutopsyEvent implements Serializabl
* event is published over a network.
*/
super(IngestManager.IngestModuleEvent.FILE_DONE.toString(), file.getId(), null);
this.file = file;
}
/**