Add subclasses of AutopsyEvent for ingest module events

This commit is contained in:
Richard Cordovano 2015-04-17 14:34:11 -04:00
parent a68f6be8fb
commit 1ba6f617ed
5 changed files with 116 additions and 68 deletions

View File

@ -209,7 +209,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
Events.REPORT_ADDED.toString()));
private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher();
private final EventSubscriber eventSubscriber;
private final Messenger messenger;
private Messenger messenger;
/**
* Constructor for the Case class
@ -224,7 +224,14 @@ public class Case implements SleuthkitCase.ErrorObserver {
this.db = db;
this.services = new Services(db);
this.eventSubscriber = new EventSubscriber();
this.messenger = new Messenger(this.name, eventPublisher);
if (CaseType.MULTI_USER_CASE == this.caseType) {
try {
this.messenger = new Messenger(this.name, eventPublisher, UserPreferences.getMessageServiceConnectionInfo());
} catch (URISyntaxException | JMSException ex) {
// RJCTODO: Add some sort of notification to user.
logger.log(Level.SEVERE, "Failed to start messenger", ex);
}
}
}
/**
@ -232,17 +239,12 @@ public class Case implements SleuthkitCase.ErrorObserver {
* constructor.
*/
private void init() {
/**
* With an API change, this could be better done using an inner class,
* allowing the two-stage initialization to be replaced. Or we could go
* ahead with removing SleuthkitCase.ErrorObserver.
*/
db.addErrorObserver(this);
if (CaseType.MULTI_USER_CASE == this.caseType) {
addRemoteEventSubscriber(REMOTE_EVENT_NAMES, eventSubscriber);
try {
messenger.start(UserPreferences.getMessageServiceConnectionInfo());
} catch (URISyntaxException | JMSException ex) {
// RJCTODO: Add some sort of notification to user.
logger.log(Level.SEVERE, "Failed to start messenger", ex);
}
}
}
/**
@ -577,7 +579,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
*/
@Deprecated
void addLocalDataSource(Content newDataSource) {
notifyNewDataSource(newDataSource);
}
@ -1033,6 +1034,21 @@ public class Case implements SleuthkitCase.ErrorObserver {
eventPublisher.removeSubscriber(eventNames, subscriber);
}
/**
* Sends an event to other Autopsy nodes when a multi-user case is open.
*
* @param event The event to send.
*/
public void sendEventMessage(AutopsyEvent event) {
if (CaseType.MULTI_USER_CASE == this.caseType && null != messenger) {
try {
messenger.send(event);
} catch (JMSException ex) {
logger.log(Level.SEVERE, String.format("Failed to send %s event message", event.getPropertyName()), ex);
}
}
}
/**
* Check if image from the given image path exists.
*

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.events;
import java.beans.PropertyChangeEvent;
import java.io.Serializable;
import javax.annotation.concurrent.Immutable;
/**
* A base class for events that can be published locally as well as to other
@ -27,6 +28,7 @@ import java.io.Serializable;
* to integrate with the legacy use of JavaBeans PropertyChangeEvents and
* PropertyChangeListeners as a local event system.
*/
@Immutable
public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
private static final long serialVersionUID = 1L;
@ -45,13 +47,13 @@ public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
* Constructs an event that can be published locally and to other Autopsy
* nodes when a multi-user case is open.
*
* @param source The source of the event, local or remote.
* @param sourceType The source type of the event, local or remote.
* @param eventName The event name.
* @param oldValue The "old" value to associate with the event. May be null.
* @param newValue The "new" value to associate with the event. May be null.
*/
AutopsyEvent(SourceType source, String eventName, Object oldValue, Object newValue) {
super(source, eventName, oldValue, newValue);
public AutopsyEvent(SourceType sourceType, String eventName, Object oldValue, Object newValue) {
super(sourceType, eventName, oldValue, newValue);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2015 Basis Technology Corp.
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -22,7 +22,8 @@ import javax.swing.event.ChangeEvent;
import org.sleuthkit.datamodel.Content;
/**
* Event data that are fired off by ingest modules when they changed or added new content.
* Event data that are fired off by ingest modules when they changed or added
* new content.
*/
public class ModuleContentEvent extends ChangeEvent {
@ -30,15 +31,27 @@ public class ModuleContentEvent extends ChangeEvent {
/**
* Create a new event passing content that has changed
* @param content
*
* @param content
*/
public ModuleContentEvent(Content content) {
super(content);
super(content);
}
/**
* get module name that changed the content and fired the event
* @return
* Create a new event passing content that has changed
*
* @param content
*/
public ModuleContentEvent(String moduleName, Content content) {
super(content);
this.moduleName = moduleName;
}
/**
* Gets the module name that changed the content and fired the event.
*
* @return The module name as a string. May be empty.
*/
public String getModuleName() {
return moduleName;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2015 Basis Technology Corp.
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import java.net.URISyntaxException;
import java.util.logging.Level;
import javax.annotation.concurrent.Immutable;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
@ -36,58 +37,66 @@ import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Uses a message service to send and receives event messages between Autopsy
* nodes when a multi-user case is open.
* nodes when a multi-user case is open. Thread-safe.
*/
public final class Messenger implements MessageListener {
@Immutable
public final class Messenger {
private static final Logger logger = Logger.getLogger(Messenger.class.getName());
private static final String ALL_MESSAGE_SELECTOR = "All";
private final String caseName;
private final AutopsyEventPublisher eventPublisher;
private Connection connection;
private Session session;
private MessageProducer producer;
private final Connection connection;
private final Session session;
private final MessageProducer producer;
private final MessageReceiver receiver;
/**
* Creates a messenger to send and receive event messages between Autopsy
* nodes when a multi-user case is open.
* Creates and starts a messenger to send and receive event messages between
* Autopsy nodes when a multi-user case is open.
*
* @param caseName The name of the multi-user case.
* @param eventPublisher An event publisher that will be used to publish
* remote events locally.
*/
public Messenger(String caseName, AutopsyEventPublisher eventPublisher) {
this.caseName = caseName;
this.eventPublisher = eventPublisher;
}
/**
* Starts this messenger, causing it to connect to the message service.
*
* @param info Connection info for the message service.
* @throws URISyntaxException if the URI in the connection info is
* malformed.
* @throws JMSException if the connection to the message service cannot be
* made.
*/
public void start(MessageServiceConnectionInfo info) throws URISyntaxException, JMSException {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(info.getUserName(), info.getPassword(), info.getURI());
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(caseName);
producer = session.createProducer(topic);
MessageConsumer consumer = session.createConsumer(topic, "events = '" + ALL_MESSAGE_SELECTOR + "'", true);
consumer.setMessageListener(this);
public Messenger(String caseName, AutopsyEventPublisher eventPublisher, MessageServiceConnectionInfo info) throws URISyntaxException, JMSException {
try {
this.eventPublisher = eventPublisher;
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(info.getUserName(), info.getPassword(), info.getURI());
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(caseName);
producer = session.createProducer(topic);
MessageConsumer consumer = session.createConsumer(topic, "events = '" + ALL_MESSAGE_SELECTOR + "'", true);
receiver = new MessageReceiver();
consumer.setMessageListener(receiver);
} catch (URISyntaxException | JMSException ex) {
logger.log(Level.SEVERE, "Failed to start", ex);
stop();
throw ex;
}
}
/**
* Stops this messenger, causing it to disconnect from the message service.
*/
public void stop() {
synchronized public void stop() {
try {
session.close();
connection.close();
if (null != session) {
session.close();
}
} catch (JMSException ex) {
logger.log(Level.SEVERE, "Failed to close message service session", ex);
}
try {
if (null != connection) {
connection.close();
}
} catch (JMSException ex) {
logger.log(Level.SEVERE, "Failed to close connection to message service", ex);
}
@ -98,7 +107,7 @@ public final class Messenger implements MessageListener {
*
* @param event The event to send.
*/
public void send(AutopsyEvent event) throws JMSException {
synchronized public void send(AutopsyEvent event) throws JMSException {
ObjectMessage message = session.createObjectMessage();
message.setStringProperty("events", ALL_MESSAGE_SELECTOR);
message.setObject(event);
@ -106,25 +115,33 @@ public final class Messenger implements MessageListener {
}
/**
* Receives an event message via the message service and publishes it
* Receives event messages via the message service and publishes them
* locally.
*
* @param message The message.
*/
@Override
public void onMessage(Message message) {
try {
if (message instanceof ObjectMessage) {
ObjectMessage objectMessage = (ObjectMessage) message;
Object object = objectMessage.getObject();
if (object instanceof AutopsyEvent) {
AutopsyEvent event = (AutopsyEvent) object;
eventPublisher.publish(event);
private final class MessageReceiver implements MessageListener {
/**
* Receives an event message via the message service and publishes it
* locally. Called by a JMS thread.
*
* @param message The message.
*/
@Override
public void onMessage(Message message) {
try {
if (message instanceof ObjectMessage) {
ObjectMessage objectMessage = (ObjectMessage) message;
Object object = objectMessage.getObject();
if (object instanceof AutopsyEvent) {
AutopsyEvent event = (AutopsyEvent) object;
eventPublisher.publish(event);
}
}
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error receiving message", ex);
}
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error receiving message", ex);
}
}
}