mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 11:07:43 +00:00
Merge pull request #1198 from rcordovano/msg_infrastructure
Add messaging/event infrastructure
This commit is contained in:
commit
a68f6be8fb
@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import org.sleuthkit.autopsy.core.messenger.Messenger;
|
||||
import org.sleuthkit.autopsy.messaging.Messenger;
|
||||
import java.awt.Frame;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
@ -26,8 +26,12 @@ import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
@ -37,6 +41,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import javax.jms.JMSException;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.Lookup;
|
||||
@ -46,6 +51,7 @@ import org.openide.util.actions.SystemAction;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.services.Services;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
|
||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -54,6 +60,8 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.sleuthkit.datamodel.*;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventSubscriber;
|
||||
|
||||
/**
|
||||
* Stores all information for a given case. Only a single case can currently be
|
||||
@ -176,7 +184,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
private final SleuthkitCase db;
|
||||
// Track the current case (only set with changeCase() method)
|
||||
private static Case currentCase = null;
|
||||
private CaseType caseType;
|
||||
private final CaseType caseType;
|
||||
private final Services services;
|
||||
private static final Logger logger = Logger.getLogger(Case.class.getName());
|
||||
static final String CASE_EXTENSION = "aut"; //NON-NLS
|
||||
@ -185,7 +193,23 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
// we cache if the case has data in it yet since a few places ask for it and we dont' need to keep going to DB
|
||||
private boolean hasData = false;
|
||||
|
||||
private Messenger messenger;
|
||||
/**
|
||||
* Multi-user cases send and receiveEvent event messages from other Autopsy
|
||||
* nodes using a Messenger and publish remote events using a
|
||||
* AutopsyEventPublisher. The AutopsyEventPublisher is static to allow
|
||||
* subscribers to register once for all cases.
|
||||
*/
|
||||
private static final Collection<String> REMOTE_EVENT_NAMES = new ArrayList<>(Arrays.asList(
|
||||
Events.NAME.toString(),
|
||||
Events.NUMBER.toString(),
|
||||
Events.EXAMINER.toString(),
|
||||
Events.DATA_SOURCE_ADDED.toString(),
|
||||
Events.DATA_SOURCE_ADDED.toString(),
|
||||
Events.DATA_SOURCE_DELETED.toString(),
|
||||
Events.REPORT_ADDED.toString()));
|
||||
private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher();
|
||||
private final EventSubscriber eventSubscriber;
|
||||
private final Messenger messenger;
|
||||
|
||||
/**
|
||||
* Constructor for the Case class
|
||||
@ -199,7 +223,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
this.caseType = type;
|
||||
this.db = db;
|
||||
this.services = new Services(db);
|
||||
// messenger = new Messenger(this.name);
|
||||
this.eventSubscriber = new EventSubscriber();
|
||||
this.messenger = new Messenger(this.name, eventPublisher);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,6 +233,16 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
*/
|
||||
private void init() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,7 +386,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
String indexName = caseName + "_" + dateFormat.format(date);
|
||||
|
||||
String dbName = null;
|
||||
|
||||
|
||||
// figure out the database name and index name for text extraction
|
||||
if (caseType == CaseType.SINGLE_USER_CASE) {
|
||||
dbName = caseDir + File.separator + "autopsy.db"; //NON-NLS
|
||||
@ -381,7 +416,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
*/
|
||||
Case newCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db, caseType);
|
||||
newCase.init();
|
||||
// newCase.messenger.start();
|
||||
|
||||
changeCase(newCase);
|
||||
}
|
||||
@ -442,7 +476,6 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
*/
|
||||
Case openedCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db, caseType);
|
||||
openedCase.init();
|
||||
// openedCase.messenger.start();
|
||||
|
||||
changeCase(openedCase);
|
||||
|
||||
@ -591,8 +624,11 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
public void closeCase() throws CaseActionException {
|
||||
changeCase(null);
|
||||
|
||||
Case.eventPublisher.removeSubscriber(REMOTE_EVENT_NAMES, eventSubscriber);
|
||||
try {
|
||||
// messenger.stop();
|
||||
if (CaseType.MULTI_USER_CASE == this.caseType) {
|
||||
messenger.stop();
|
||||
}
|
||||
services.close();
|
||||
this.xmlcm.close(); // close the xmlcm
|
||||
this.db.close();
|
||||
@ -797,12 +833,13 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
|
||||
/**
|
||||
* Get the case type.
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public CaseType getCaseType() {
|
||||
return this.caseType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the full path to the temp directory of this case
|
||||
*
|
||||
@ -952,6 +989,50 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
pcs.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an subscriber to events from other Autopsy nodes when a multi-user
|
||||
* case is open.
|
||||
*
|
||||
* @param eventNames The events the subscriber is interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public static void addRemoteEventSubscriber(Collection<String> eventNames, AutopsyEventSubscriber subscriber) {
|
||||
eventPublisher.addSubscriber(eventNames, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an subscriber to events from other Autopsy nodes when a multi-user
|
||||
* case is open.
|
||||
*
|
||||
* @param eventNames The event the subscriber is interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public static void addRemoteEventSubscriber(String eventName, AutopsyEventSubscriber subscriber) {
|
||||
eventPublisher.addSubscriber(eventName, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a subscriber to events from other Autopsy nodes when a multi-user
|
||||
* case is open.
|
||||
*
|
||||
* @param eventName The event the subscriber is no longer interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public static void removeRemoteEventSubscriber(String eventName, AutopsyEventSubscriber subscriber) {
|
||||
eventPublisher.removeSubscriber(eventName, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a subscriber to events from other Autopsy nodes when a multi-user
|
||||
* case is open.
|
||||
*
|
||||
* @param eventNames The event the subscriber is no longer interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public static void removeRemoteEventSubscriber(Collection<String> eventNames, AutopsyEventSubscriber subscriber) {
|
||||
eventPublisher.removeSubscriber(eventNames, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if image from the given image path exists.
|
||||
*
|
||||
@ -1305,4 +1386,16 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
}
|
||||
return hasData;
|
||||
}
|
||||
|
||||
private final class EventSubscriber implements AutopsyEventSubscriber {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void receiveEvent(AutopsyEvent event) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.core;
|
||||
|
||||
import org.sleuthkit.autopsy.core.messenger.MessageServiceConnectionInfo;
|
||||
import org.sleuthkit.autopsy.messaging.MessageServiceConnectionInfo;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import java.util.prefs.Preferences;
|
||||
import org.openide.util.NbPreferences;
|
||||
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-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.core.messenger;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.logging.Level;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.ObjectMessage;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
public final class Messenger implements MessageListener {
|
||||
|
||||
private static final String ALL_MESSAGE_SELECTOR = "All";
|
||||
private static final Logger logger = Logger.getLogger(Messenger.class.getName());
|
||||
private final String caseName;
|
||||
private Connection connection;
|
||||
private Session session;
|
||||
private MessageProducer producer;
|
||||
|
||||
Messenger(String caseName) {
|
||||
this.caseName = caseName;
|
||||
}
|
||||
|
||||
void start(MessageServiceConnectionInfo info) {
|
||||
try {
|
||||
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);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Startup error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
try {
|
||||
session.close();
|
||||
connection.close();
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Shutdown error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(PropertyChangeEvent event) {
|
||||
try {
|
||||
ObjectMessage message = session.createObjectMessage();
|
||||
message.setStringProperty("events", ALL_MESSAGE_SELECTOR);
|
||||
message.setObject(event);
|
||||
producer.send(message);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Publishing error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
if (message instanceof ObjectMessage) {
|
||||
ObjectMessage objMessage = (ObjectMessage) message;
|
||||
String event = (String) objMessage.getObject();
|
||||
logger.log(Level.INFO, "Received {0}", event);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Publishing error", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -15,7 +15,7 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.TskData.DbType;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.core.messenger.MessageServiceConnectionInfo;
|
||||
import org.sleuthkit.autopsy.messaging.MessageServiceConnectionInfo;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
public final class MultiUserSettingsPanel extends javax.swing.JPanel {
|
||||
|
57
Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java
Normal file
57
Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-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.events;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A base class for events that can be published locally as well as to other
|
||||
* Autopsy nodes when a multi-user case is open. It extends PropertyChangeEvent
|
||||
* to integrate with the legacy use of JavaBeans PropertyChangeEvents and
|
||||
* PropertyChangeListeners as a local event system.
|
||||
*/
|
||||
public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Events have a source field set to local or remote to allow event
|
||||
* subscribers to filter events by source type.
|
||||
*/
|
||||
public enum SourceType {
|
||||
|
||||
Local,
|
||||
Remote
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
}
|
||||
|
||||
}
|
112
Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java
Normal file
112
Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Provides thread-safe support for publishing events to registered subscribers.
|
||||
*/
|
||||
public class AutopsyEventPublisher {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AutopsyEventPublisher.class.getName());
|
||||
private final Map<String, Set<AutopsyEventSubscriber>> subscribersByEvent;
|
||||
|
||||
/**
|
||||
* Constructs an object for publishing events to registered subscribers.
|
||||
*/
|
||||
public AutopsyEventPublisher() {
|
||||
subscribersByEvent = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event subscriber to this publisher.
|
||||
*
|
||||
* @param eventNames The events the subscriber is interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
synchronized public void addSubscriber(Collection<String> eventNames, AutopsyEventSubscriber subscriber) {
|
||||
for (String eventName : eventNames) {
|
||||
addSubscriber(eventName, subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event subscriber to this publisher.
|
||||
*
|
||||
* @param eventName The event the subscriber is interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
synchronized public void addSubscriber(String eventName, AutopsyEventSubscriber subscriber) {
|
||||
subscribersByEvent.putIfAbsent(eventName, new HashSet<>());
|
||||
Set<AutopsyEventSubscriber> subscribers = subscribersByEvent.get(eventName);
|
||||
subscribers.add(subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event subscriber from this publisher.
|
||||
*
|
||||
* @param eventNames The events the subscriber is no longer interested in.
|
||||
* @param subscriber The subscriber to remove.
|
||||
*/
|
||||
synchronized public void removeSubscriber(Collection<String> eventNames, AutopsyEventSubscriber subscriber) {
|
||||
for (String eventName : eventNames) {
|
||||
removeSubscriber(eventName, subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event subscriber from this publisher.
|
||||
*
|
||||
* @param eventNames The event the subscriber is no longer interested in.
|
||||
* @param subscriber The subscriber to remove.
|
||||
*/
|
||||
synchronized public void removeSubscriber(String eventName, AutopsyEventSubscriber subscriber) {
|
||||
Set<AutopsyEventSubscriber> subscribers = subscribersByEvent.getOrDefault(eventName, null);
|
||||
if (null != subscribers) {
|
||||
subscribers.remove(subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes an event to all registered subscribers, even if a subscriber
|
||||
* throws an exception.
|
||||
*
|
||||
* @param event The event to be published.
|
||||
*/
|
||||
synchronized public void publish(AutopsyEvent event) {
|
||||
Set<AutopsyEventSubscriber> subscribers = subscribersByEvent.getOrDefault(event.getPropertyName(), null);
|
||||
if (null != subscribers) {
|
||||
for (AutopsyEventSubscriber subscriber : subscribers) {
|
||||
try {
|
||||
subscriber.receiveEvent(event);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Exception thrown by subscriber", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-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.events;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by classes that want to register to receiveEvent
|
||||
events.
|
||||
*/
|
||||
public interface AutopsyEventSubscriber {
|
||||
|
||||
/**
|
||||
* Receives a subscribed event.
|
||||
*
|
||||
* @param event The event.
|
||||
*/
|
||||
void receiveEvent(AutopsyEvent event);
|
||||
}
|
@ -24,6 +24,7 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@ -43,6 +44,8 @@ import org.openide.util.Cancellable;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventSubscriber;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -268,6 +271,9 @@ public class IngestManager {
|
||||
ingestThreadActivitySnapshots.put(threadId, new IngestThreadActivitySnapshot(threadId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes this ingest manager to local and remote case-related events.
|
||||
*/
|
||||
private void subscribeToCaseEvents() {
|
||||
Case.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
@ -281,8 +287,23 @@ public class IngestManager {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Collection<String> remoteEventNames = new ArrayList<>(Arrays.asList(
|
||||
IngestJobEvent.STARTED.toString(),
|
||||
IngestJobEvent.COMPLETED.toString(),
|
||||
IngestJobEvent.CANCELLED.toString(),
|
||||
IngestModuleEvent.DATA_ADDED.toString(),
|
||||
IngestModuleEvent.CONTENT_CHANGED.toString(),
|
||||
IngestModuleEvent.FILE_DONE.toString()));
|
||||
Case.addRemoteEventSubscriber(remoteEventNames, new AutopsyEventSubscriber() {
|
||||
|
||||
@Override
|
||||
public void receiveEvent(AutopsyEvent event) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
synchronized void handleCaseOpened() {
|
||||
this.jobCreationIsEnabled = true;
|
||||
clearIngestMessageBox();
|
||||
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.core.messenger;
|
||||
package org.sleuthkit.autopsy.messaging;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
@ -33,7 +33,7 @@ public final class MessageServiceConnectionInfo {
|
||||
private final String port;
|
||||
|
||||
/**
|
||||
* Constructs an object containing the connection info for a Java Message
|
||||
* Constructs an object containing connection info for a Java Message
|
||||
* Service (JMS) provider.
|
||||
*
|
||||
* @param userName The user name to use for a message service connection.
|
130
Core/src/org/sleuthkit/autopsy/messaging/Messenger.java
Normal file
130
Core/src/org/sleuthkit/autopsy/messaging/Messenger.java
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-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.messaging;
|
||||
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.logging.Level;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.ObjectMessage;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
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.
|
||||
*/
|
||||
public final class Messenger implements MessageListener {
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Creates 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this messenger, causing it to disconnect from the message service.
|
||||
*/
|
||||
public void stop() {
|
||||
try {
|
||||
session.close();
|
||||
connection.close();
|
||||
} catch (JMSException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to close connection to message service", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an event message via the message service.
|
||||
*
|
||||
* @param event The event to send.
|
||||
*/
|
||||
public void send(AutopsyEvent event) throws JMSException {
|
||||
ObjectMessage message = session.createObjectMessage();
|
||||
message.setStringProperty("events", ALL_MESSAGE_SELECTOR);
|
||||
message.setObject(event);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives an event message via the message service and publishes it
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Error receiving message", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Wed, 15 Apr 2015 18:11:08 -0400
|
||||
#Thu, 16 Apr 2015 17:09:30 -0400
|
||||
LBL_splash_window_title=Starting Autopsy
|
||||
SPLASH_HEIGHT=314
|
||||
SPLASH_WIDTH=538
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Wed, 15 Apr 2015 18:11:08 -0400
|
||||
#Thu, 16 Apr 2015 17:09:30 -0400
|
||||
|
||||
CTL_MainWindow_Title=Autopsy 3.1.2
|
||||
CTL_MainWindow_Title_No_Project=Autopsy 3.1.2
|
||||
|
Loading…
x
Reference in New Issue
Block a user