From 7c1da35b33b6b8843efa39e4e7da446d510b709e Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 2 Jul 2015 14:42:04 -0400 Subject: [PATCH 01/44] Created ServicesMonitor and refactored CollaborationMonitor --- .../casemodule/CollaborationMonitor.java | 93 +--------- .../autopsy/core/ServicesMonitor.java | 166 ++++++++++++++++++ 2 files changed, 169 insertions(+), 90 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java index 254d404c4e..aa1bd3a474 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java @@ -22,7 +22,6 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.Serializable; -import java.net.URISyntaxException; import java.net.UnknownHostException; import java.time.Duration; import java.time.Instant; @@ -36,45 +35,35 @@ import java.util.UUID; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import javax.jms.Connection; -import javax.jms.JMSException; -import org.apache.activemq.ActiveMQConnectionFactory; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent; import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; -import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; -import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisStartedEvent; -import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; -import org.sleuthkit.datamodel.CaseDbConnectionInfo; /** * A collaboration monitor listens to local events and translates them into - * collaboration tasks that are broadcast to collaborating nodes, informs the - * user of collaboration tasks on other nodes using progress bars, and monitors - * the health of key collaboration services. + * collaboration tasks that are broadcast to collaborating nodes and informs the + * user of collaboration tasks on other nodes using progress bars. */ final class CollaborationMonitor { private static final String EVENT_CHANNEL_NAME = "%s-Collaboration-Monitor-Events"; private static final String COLLABORATION_MONITOR_EVENT = "COLLABORATION_MONITOR_EVENT"; private static final Set CASE_EVENTS_OF_INTEREST = new HashSet<>(Arrays.asList(new String[]{Case.Events.ADDING_DATA_SOURCE.toString(), Case.Events.DATA_SOURCE_ADDED.toString(), Case.Events.ADDING_DATA_SOURCE_FAILED.toString()})); - private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 3; + private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 2; private static final String PERIODIC_TASK_THREAD_NAME = "collab-monitor-periodic-tasks-%d"; private static final long HEARTBEAT_INTERVAL_MINUTES = 1; private static final long MAX_MISSED_HEARTBEATS = 5; private static final long STALE_TASKS_DETECTION_INTERVAL_MINUTES = 2; - private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; private static final long EXECUTOR_TERMINATION_WAIT_SECS = 30; private static final Logger logger = Logger.getLogger(CollaborationMonitor.class.getName()); private final String hostName; @@ -129,12 +118,10 @@ final class CollaborationMonitor { * * 1. Send heartbeats to collaboration monitors on other nodes.
* 2. Check for stale remote tasks.
- * 3. Check the availability of key collaboration services.
*/ periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build()); periodicTasksExecutor.scheduleAtFixedRate(new HeartbeatTask(), HEARTBEAT_INTERVAL_MINUTES, HEARTBEAT_INTERVAL_MINUTES, TimeUnit.MINUTES); periodicTasksExecutor.scheduleAtFixedRate(new StaleTaskDetectionTask(), STALE_TASKS_DETECTION_INTERVAL_MINUTES, STALE_TASKS_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); - periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } /** @@ -514,80 +501,6 @@ final class CollaborationMonitor { } } - /** - * A Runnable task that periodically checks the availability of - * collaboration resources (PostgreSQL server, Solr server, Active MQ - * message broker) and reports status to the user in case of a gap in - * service. - */ - private final static class CrashDetectionTask implements Runnable { - - private static boolean dbServerIsRunning = true; - private static boolean solrServerIsRunning = true; - private static boolean messageServerIsRunning = true; - private static final Object lock = new Object(); - - /** - * Monitor the availability of collaboration resources - */ - @Override - public void run() { - synchronized (lock) { - CaseDbConnectionInfo dbInfo = UserPreferences.getDatabaseConnectionInfo(); - if (dbInfo.canConnect()) { - if (!dbServerIsRunning) { - dbServerIsRunning = true; - logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); - } - } else { - if (dbServerIsRunning) { - dbServerIsRunning = false; - logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); - } - } - - KeywordSearchService kwsService = Case.getCurrentCase().getServices().getKeywordSearchService(); - - if (kwsService.canConnectToRemoteSolrServer()) { - if (!solrServerIsRunning) { - solrServerIsRunning = true; - logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); - } - } - else { - if (solrServerIsRunning) { - solrServerIsRunning = false; - logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); - } - } - - MessageServiceConnectionInfo msgInfo = UserPreferences.getMessageServiceConnectionInfo(); - try { - ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(msgInfo.getUserName(), msgInfo.getPassword(), msgInfo.getURI()); - Connection connection = connectionFactory.createConnection(); - connection.start(); - connection.close(); - if (!messageServerIsRunning) { - messageServerIsRunning = true; - logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); - } - } catch (URISyntaxException | JMSException ex) { - if (messageServerIsRunning) { - messageServerIsRunning = false; - logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); - } - } - } - } - - } - /** * An Autopsy event to be sent in event messages to the collaboration * monitors on other Autopsy nodes. diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java new file mode 100644 index 0000000000..48b3bd1e6e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -0,0 +1,166 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013-2015 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.net.URISyntaxException; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import javax.jms.Connection; +import javax.jms.JMSException; +import org.apache.activemq.ActiveMQConnectionFactory; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.events.AutopsyEventPublisher; +import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; +import org.sleuthkit.datamodel.CaseDbConnectionInfo; + +/** + * This class periodically checks availability of collaboration resources + * (PostgreSQL server, Solr server, Active MQ message broker) and reports status + * to the user in case of a gap in service. + */ +public class ServicesMonitor { + + private AutopsyEventPublisher eventPublisher; + private static final Logger logger = Logger.getLogger(ServicesMonitor.class.getName()); + private static ServicesMonitor instance; + private final ScheduledThreadPoolExecutor periodicTasksExecutor; + + private static final String PERIODIC_TASK_THREAD_NAME = "services-monitor-periodic-task-%d"; + private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1; + private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; + + /** + * List of services that are being monitored. + */ + public enum Service { + + /** + * Property change event fired when ....TODO.... The old value of the + * PropertyChangeEvent object is set to the ingest job id, and the new + * value is set to null. + */ + REMOTE_CASE_DATABASE, + REMOTE_KEYWORD_SEARCH, + MESSAGING + }; + + enum ServiceStatus { + + UP, + DOWN + }; + + public synchronized static ServicesMonitor getInstance() { + if (instance == null) { + instance = new ServicesMonitor(); + } + return instance; + } + + private ServicesMonitor() { + + this.eventPublisher = new AutopsyEventPublisher(); + + /** + * Start periodic task that check the availability of key collaboration + * services. + */ + periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build()); + periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); + } + + /** + * A Runnable task that periodically checks the availability of + * collaboration resources (PostgreSQL server, Solr server, Active MQ + * message broker) and reports status to the user in case of a gap in + * service. + */ + private final static class CrashDetectionTask implements Runnable { + + private static boolean dbServerIsRunning = true; + private static boolean solrServerIsRunning = true; + private static boolean messageServerIsRunning = true; + private static final Object lock = new Object(); + + /** + * Monitor the availability of collaboration resources + */ + @Override + public void run() { + synchronized (lock) { + CaseDbConnectionInfo dbInfo = UserPreferences.getDatabaseConnectionInfo(); + if (dbInfo.canConnect()) { + if (!dbServerIsRunning) { + dbServerIsRunning = true; + logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS + //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); + } + } else { + if (dbServerIsRunning) { + dbServerIsRunning = false; + logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS + //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); + } + } + + KeywordSearchService kwsService = Case.getCurrentCase().getServices().getKeywordSearchService(); + + if (kwsService.canConnectToRemoteSolrServer()) { + if (!solrServerIsRunning) { + solrServerIsRunning = true; + logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS + //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); + } + } else { + if (solrServerIsRunning) { + solrServerIsRunning = false; + logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS + //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); + } + } + + MessageServiceConnectionInfo msgInfo = UserPreferences.getMessageServiceConnectionInfo(); + try { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(msgInfo.getUserName(), msgInfo.getPassword(), msgInfo.getURI()); + Connection connection = connectionFactory.createConnection(); + connection.start(); + connection.close(); + if (!messageServerIsRunning) { + messageServerIsRunning = true; + logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS + //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); + } + } catch (URISyntaxException | JMSException ex) { + if (messageServerIsRunning) { + messageServerIsRunning = false; + logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS + //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); + } + } + } + } + + } +} From 090cd8f10d28a099288e03b2b2a26c4ee56f7899 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 2 Jul 2015 15:07:29 -0400 Subject: [PATCH 02/44] Added support for small set of subscription and notification events --- .../autopsy/core/ServicesMonitor.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 48b3bd1e6e..4de214c6cb 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -19,10 +19,14 @@ package org.sleuthkit.autopsy.core; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.beans.PropertyChangeListener; import java.net.URISyntaxException; +import java.util.Set; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.jms.Connection; import javax.jms.JMSException; import org.apache.activemq.ActiveMQConnectionFactory; @@ -30,6 +34,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; @@ -50,6 +55,10 @@ public class ServicesMonitor { private static final String PERIODIC_TASK_THREAD_NAME = "services-monitor-periodic-task-%d"; private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1; private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; + + private static final Set serviceNames = Stream.of(ServicesMonitor.Service.values()) + .map(ServicesMonitor.Service::toString) + .collect(Collectors.toSet()); /** * List of services that are being monitored. @@ -91,6 +100,44 @@ public class ServicesMonitor { periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } + // Subscribes to all events + void addSubscriber(PropertyChangeListener subscriber) { + eventPublisher.addSubscriber(serviceNames, subscriber); + } + + + void addSubscriber(Set eventNames, PropertyChangeListener subscriber) { + } + + + void addSubscriber(String eventName, PropertyChangeListener subscriber) { + + } + + + void removeSubscriber(Set eventNames, PropertyChangeListener subscriber) { + + } + + + void removeSubscriber(String eventName, PropertyChangeListener subscriber) { + + } + + // Unsubscribes from all events + void removeSubscriber(PropertyChangeListener subscriber) { + eventPublisher.removeSubscriber(serviceNames, subscriber); + } + + /** + * Fire an event signifying change in remote database (e.g. PostgreSQL) service status. + */ + void fireRemoteDatabaseStatusChange(ServiceStatus status) { + AutopsyEvent event = new AutopsyEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status); + eventPublisher.publish(event); + } + + /** * A Runnable task that periodically checks the availability of * collaboration resources (PostgreSQL server, Solr server, Active MQ From ea249393657e8fd4a8623ee0cf5de7c3b303d857 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 2 Jul 2015 15:13:36 -0400 Subject: [PATCH 03/44] Changed CrashDetectionTask to be able to properly interract with ServicesMonitor --- .../org/sleuthkit/autopsy/core/ServicesMonitor.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 4de214c6cb..cdde92f07e 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -144,12 +144,12 @@ public class ServicesMonitor { * message broker) and reports status to the user in case of a gap in * service. */ - private final static class CrashDetectionTask implements Runnable { + private final class CrashDetectionTask implements Runnable { - private static boolean dbServerIsRunning = true; - private static boolean solrServerIsRunning = true; - private static boolean messageServerIsRunning = true; - private static final Object lock = new Object(); + private boolean dbServerIsRunning = true; + private boolean solrServerIsRunning = true; + private boolean messageServerIsRunning = true; + private final Object lock = new Object(); /** * Monitor the availability of collaboration resources @@ -163,12 +163,14 @@ public class ServicesMonitor { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); + fireRemoteDatabaseStatusChange(ServiceStatus.UP); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); + fireRemoteDatabaseStatusChange(ServiceStatus.DOWN); } } From a50fbe5f0d1e2528b8aa6a7cd77395488c07faa5 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 2 Jul 2015 15:18:22 -0400 Subject: [PATCH 04/44] Obtaining KWS service via lookup instead of Case.getCurrentCase().getServices().getKeywordSearchService() --- Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index cdde92f07e..d60c3ce162 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -30,8 +30,8 @@ import java.util.stream.Stream; import javax.jms.Connection; import javax.jms.JMSException; import org.apache.activemq.ActiveMQConnectionFactory; +import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.events.AutopsyEvent; @@ -174,7 +174,8 @@ public class ServicesMonitor { } } - KeywordSearchService kwsService = Case.getCurrentCase().getServices().getKeywordSearchService(); + //KeywordSearchService kwsService = Case.getCurrentCase().getServices().getKeywordSearchService(); + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); if (kwsService.canConnectToRemoteSolrServer()) { if (!solrServerIsRunning) { From 8983c34683b884cd990dd6d473c85997d3e02836 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 2 Jul 2015 15:46:20 -0400 Subject: [PATCH 05/44] Added ServiceEvent class --- .../sleuthkit/autopsy/core/ServiceEvent.java | 41 +++++++++++++++++++ .../autopsy/core/ServicesMonitor.java | 9 ++-- 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java diff --git a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java new file mode 100644 index 0000000000..85fa984dd2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java @@ -0,0 +1,41 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013-2015 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +import java.io.Serializable; +import org.sleuthkit.autopsy.events.AutopsyEvent; + +/** + * + * @author elivis + */ +public final class ServiceEvent extends AutopsyEvent implements Serializable { + + private static final long serialVersionUID = 1L; + private final String service; + private final String status; + private final String details; + + public ServiceEvent(String service, String status, String details) { + super(service, null, status); + this.service = service; + this.status = status; + this.details = details; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index d60c3ce162..1cbabeab3a 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -133,10 +133,12 @@ public class ServicesMonitor { * Fire an event signifying change in remote database (e.g. PostgreSQL) service status. */ void fireRemoteDatabaseStatusChange(ServiceStatus status) { - AutopsyEvent event = new AutopsyEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status); - eventPublisher.publish(event); + eventPublisher.publish(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); } + void setServiceStatus(String service, String status, String details) { + eventPublisher.publishLocally(new ServiceEvent(service, status, details)); + } /** * A Runnable task that periodically checks the availability of @@ -174,9 +176,8 @@ public class ServicesMonitor { } } - //KeywordSearchService kwsService = Case.getCurrentCase().getServices().getKeywordSearchService(); KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); - + // TODO - do I need to check for kwsService == null? if (kwsService.canConnectToRemoteSolrServer()) { if (!solrServerIsRunning) { solrServerIsRunning = true; From 6542faf1e0402dd2781123d1228ea4854772218f Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 2 Jul 2015 16:01:38 -0400 Subject: [PATCH 06/44] Added getters to ServiceEvent class --- .../sleuthkit/autopsy/core/ServiceEvent.java | 21 +++++++++++++------ .../autopsy/core/ServicesMonitor.java | 1 - .../autopsy/events/AutopsyEvent.java | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java index 85fa984dd2..3592190fd3 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java @@ -28,14 +28,23 @@ import org.sleuthkit.autopsy.events.AutopsyEvent; public final class ServiceEvent extends AutopsyEvent implements Serializable { private static final long serialVersionUID = 1L; - private final String service; - private final String status; + //private final String service; + //private final String status; private final String details; - public ServiceEvent(String service, String status, String details) { - super(service, null, status); - this.service = service; - this.status = status; + public ServiceEvent(String serviceName, String status, String details) { + super(serviceName, null, status); + //this.service = service; + //this.status = status; this.details = details; } + + /** + * Gets details string passed as input to ServiceEvent constructor. + * + * @return String Details of the event. + */ + public String getDetails() { + return details; + } } diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 1cbabeab3a..a99b37cc79 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -34,7 +34,6 @@ import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; diff --git a/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java b/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java index fb011a1484..d099fa2a65 100644 --- a/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java +++ b/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java @@ -62,7 +62,7 @@ public class AutopsyEvent extends PropertyChangeEvent implements Serializable { /** * Gets the source type (local or remote). * - * @param sourceType The source type of the event, local or remote. + * @return SourceType The source type of the event, local or remote. */ public SourceType getSourceType() { return sourceType; From bd39e37ddee69341848a8260f0e390eb4c37c498 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 6 Jul 2015 11:08:20 -0400 Subject: [PATCH 07/44] First cut at integration with ingest manager --- .../autopsy/core/ServicesMonitor.java | 18 +++++------ .../autopsy/ingest/IngestManager.java | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index a99b37cc79..ef5f16e16c 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -74,7 +74,7 @@ public class ServicesMonitor { MESSAGING }; - enum ServiceStatus { + public enum ServiceStatus { UP, DOWN @@ -100,31 +100,31 @@ public class ServicesMonitor { } // Subscribes to all events - void addSubscriber(PropertyChangeListener subscriber) { + public void addSubscriber(PropertyChangeListener subscriber) { eventPublisher.addSubscriber(serviceNames, subscriber); } - void addSubscriber(Set eventNames, PropertyChangeListener subscriber) { + public void addSubscriber(Set eventNames, PropertyChangeListener subscriber) { } - void addSubscriber(String eventName, PropertyChangeListener subscriber) { + public void addSubscriber(String eventName, PropertyChangeListener subscriber) { } - void removeSubscriber(Set eventNames, PropertyChangeListener subscriber) { + public void removeSubscriber(Set eventNames, PropertyChangeListener subscriber) { } - void removeSubscriber(String eventName, PropertyChangeListener subscriber) { + public void removeSubscriber(String eventName, PropertyChangeListener subscriber) { } // Unsubscribes from all events - void removeSubscriber(PropertyChangeListener subscriber) { + public void removeSubscriber(PropertyChangeListener subscriber) { eventPublisher.removeSubscriber(serviceNames, subscriber); } @@ -132,10 +132,10 @@ public class ServicesMonitor { * Fire an event signifying change in remote database (e.g. PostgreSQL) service status. */ void fireRemoteDatabaseStatusChange(ServiceStatus status) { - eventPublisher.publish(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); + eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); } - void setServiceStatus(String service, String status, String details) { + public void setServiceStatus(String service, String status, String details) { eventPublisher.publishLocally(new ServiceEvent(service, status, details)); } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 3ee3267d8a..91e30cfdda 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -44,6 +44,8 @@ import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.util.Cancellable; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.core.ServiceEvent; +import org.sleuthkit.autopsy.core.ServicesMonitor; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.coreutils.Logger; @@ -150,6 +152,12 @@ public class IngestManager { * is the default. */ private volatile boolean runInteractively; + + /** + * Ingest manager subscribes to service outage notifications. If key services are down, + * ingest manager cancels all ingest jobs in progress. + */ + private final ServicesMonitor servicesMonitor; /** * Ingest job events. @@ -264,6 +272,9 @@ public class IngestManager { this.nextThreadId = new AtomicLong(0L); this.jobsById = new ConcurrentHashMap<>(); this.ingestJobStarters = new ConcurrentHashMap<>(); + + this.servicesMonitor = ServicesMonitor.getInstance(); + subscribeToServiceMonitorEvents(); this.startDataSourceIngestThread(); @@ -313,6 +324,26 @@ public class IngestManager { } }); } + + /** + * Subscribe ingest manager to service monitor events. + */ + private void subscribeToServiceMonitorEvents() { + PropertyChangeListener propChangeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String eventType = evt.getPropertyName(); + if (eventType.equals(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) { + if (evt.getNewValue() == ServicesMonitor.ServiceStatus.DOWN) { + // cancel ingest if running + cancelAllIngestJobs(); + } + } + } + }; + // TODO: sunscribe to all events? + this.servicesMonitor.addSubscriber(propChangeListener); + } synchronized void handleCaseOpened() { this.jobCreationIsEnabled = true; From 50708fc2112ad85d23050abc6923b51c5ec131f5 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 6 Jul 2015 12:30:20 -0400 Subject: [PATCH 08/44] Updated javadocs --- .../autopsy/core/ServicesMonitor.java | 68 +++++++++++++++---- .../autopsy/events/AutopsyEventPublisher.java | 2 +- .../autopsy/ingest/IngestManager.java | 3 + 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index ef5f16e16c..785d7fda49 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -99,43 +99,83 @@ public class ServicesMonitor { periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } - // Subscribes to all events + /** + * Adds an event subscriber to this publisher. Subscriber will be subscribed + * to all events from this publisher. + * + * @param subscriber The subscriber to add. + */ public void addSubscriber(PropertyChangeListener subscriber) { eventPublisher.addSubscriber(serviceNames, subscriber); } - + /** + * Adds an event subscriber to this publisher. + * + * @param eventNames The events the subscriber is interested in. + * @param subscriber The subscriber to add. + */ public void addSubscriber(Set eventNames, PropertyChangeListener subscriber) { + eventPublisher.addSubscriber(eventNames, subscriber); } - + /** + * Adds an event subscriber to this publisher. + * + * @param eventName The event the subscriber is interested in. + * @param subscriber The subscriber to add. + */ public void addSubscriber(String eventName, PropertyChangeListener subscriber) { - + eventPublisher.addSubscriber(eventName, 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. + */ public void removeSubscriber(Set eventNames, PropertyChangeListener subscriber) { - + eventPublisher.removeSubscriber(eventNames, subscriber); } - + /** + * Removes an event subscriber from this publisher. + * + * @param eventName The event the subscriber is no longer interested in. + * @param subscriber The subscriber to remove. + */ public void removeSubscriber(String eventName, PropertyChangeListener subscriber) { - + eventPublisher.removeSubscriber(eventName, subscriber); } - // Unsubscribes from all events + /** + * Removes an event subscriber to this publisher. Subscriber will be removed + * from all event notifications from this publisher. + * + * @param subscriber The subscriber to remove. + */ public void removeSubscriber(PropertyChangeListener subscriber) { eventPublisher.removeSubscriber(serviceNames, subscriber); } /** - * Fire an event signifying change in remote database (e.g. PostgreSQL) service status. + * Publish an event signifying change in remote database (e.g. PostgreSQL) service status. + * + * @param status Updated status for the event. */ - void fireRemoteDatabaseStatusChange(ServiceStatus status) { + void publishRemoteDatabaseStatusChange(ServiceStatus status) { eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); } - public void setServiceStatus(String service, String status, String details) { + /** + * Publish a custom event. + * + * @param service Name of the service. + * @param status Updated status for the event. + * @param details Details of the event. + */ + public void publishServiceStatus(String service, String status, String details) { eventPublisher.publishLocally(new ServiceEvent(service, status, details)); } @@ -164,14 +204,14 @@ public class ServicesMonitor { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); - fireRemoteDatabaseStatusChange(ServiceStatus.UP); + publishRemoteDatabaseStatusChange(ServiceStatus.UP); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); - fireRemoteDatabaseStatusChange(ServiceStatus.DOWN); + publishRemoteDatabaseStatusChange(ServiceStatus.DOWN); } } diff --git a/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java b/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java index df2b21674a..eca2f8dfb6 100644 --- a/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java +++ b/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java @@ -120,7 +120,7 @@ public final class AutopsyEventPublisher { /** * Removes an event subscriber from this publisher. * - * @param eventNames The event the subscriber is no longer interested in. + * @param eventName The event the subscriber is no longer interested in. * @param subscriber The subscriber to remove. */ public void removeSubscriber(String eventName, PropertyChangeListener subscriber) { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 91e30cfdda..04421de603 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -335,6 +335,9 @@ public class IngestManager { String eventType = evt.getPropertyName(); if (eventType.equals(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) { if (evt.getNewValue() == ServicesMonitor.ServiceStatus.DOWN) { + + // TODO - display notification + // cancel ingest if running cancelAllIngestJobs(); } From 01e19c3bc3f388eb37534ad0da3a53066273bac6 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 6 Jul 2015 14:16:30 -0400 Subject: [PATCH 09/44] Added publishing of KWS and messaging events --- .../autopsy/core/ServicesMonitor.java | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 785d7fda49..131d2ba79d 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -40,9 +40,9 @@ import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.CaseDbConnectionInfo; /** - * This class periodically checks availability of collaboration resources - * (PostgreSQL server, Solr server, Active MQ message broker) and reports status - * to the user in case of a gap in service. + * This class periodically checks availability of collaboration resources - + * remote database, remote keyword search server, messaging service - and + * reports status updates to the user in case of a gap in service. */ public class ServicesMonitor { @@ -54,7 +54,7 @@ public class ServicesMonitor { private static final String PERIODIC_TASK_THREAD_NAME = "services-monitor-periodic-task-%d"; private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1; private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; - + private static final Set serviceNames = Stream.of(ServicesMonitor.Service.values()) .map(ServicesMonitor.Service::toString) .collect(Collectors.toSet()); @@ -100,11 +100,11 @@ public class ServicesMonitor { } /** - * Adds an event subscriber to this publisher. Subscriber will be subscribed + * Adds an event subscriber to this publisher. Subscriber will be subscribed * to all events from this publisher. * * @param subscriber The subscriber to add. - */ + */ public void addSubscriber(PropertyChangeListener subscriber) { eventPublisher.addSubscriber(serviceNames, subscriber); } @@ -114,7 +114,7 @@ public class ServicesMonitor { * * @param eventNames The events the subscriber is interested in. * @param subscriber The subscriber to add. - */ + */ public void addSubscriber(Set eventNames, PropertyChangeListener subscriber) { eventPublisher.addSubscriber(eventNames, subscriber); } @@ -124,7 +124,7 @@ public class ServicesMonitor { * * @param eventName The event the subscriber is interested in. * @param subscriber The subscriber to add. - */ + */ public void addSubscriber(String eventName, PropertyChangeListener subscriber) { eventPublisher.addSubscriber(eventName, subscriber); } @@ -150,31 +150,52 @@ public class ServicesMonitor { } /** - * Removes an event subscriber to this publisher. Subscriber will be removed + * Removes an event subscriber to this publisher. Subscriber will be removed * from all event notifications from this publisher. * * @param subscriber The subscriber to remove. - */ + */ public void removeSubscriber(PropertyChangeListener subscriber) { eventPublisher.removeSubscriber(serviceNames, subscriber); } - + /** - * Publish an event signifying change in remote database (e.g. PostgreSQL) service status. - * + * Publish an event signifying change in remote database (e.g. PostgreSQL) + * service status. + * * @param status Updated status for the event. */ - void publishRemoteDatabaseStatusChange(ServiceStatus status) { + private void publishRemoteDatabaseStatusChange(ServiceStatus status) { eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); - } + } + + /** + * Publish an event signifying change in remote database (e.g. PostgreSQL) + * service status. + * + * @param status Updated status for the event. + */ + private void publishRemoteKeywordSearchStatusChange(ServiceStatus status) { + eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); + } + + /** + * Publish an event signifying change in remote database (e.g. PostgreSQL) + * service status. + * + * @param status Updated status for the event. + */ + private void publishMessagingStatusChange(ServiceStatus status) { + eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); + } /** * Publish a custom event. - * + * * @param service Name of the service. * @param status Updated status for the event. * @param details Details of the event. - */ + */ public void publishServiceStatus(String service, String status, String details) { eventPublisher.publishLocally(new ServiceEvent(service, status, details)); } @@ -222,12 +243,14 @@ public class ServicesMonitor { solrServerIsRunning = true; logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); + publishRemoteKeywordSearchStatusChange(ServiceStatus.UP); } } else { if (solrServerIsRunning) { solrServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); + publishRemoteKeywordSearchStatusChange(ServiceStatus.DOWN); } } @@ -241,12 +264,14 @@ public class ServicesMonitor { messageServerIsRunning = true; logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); + publishMessagingStatusChange(ServiceStatus.UP); } } catch (URISyntaxException | JMSException ex) { if (messageServerIsRunning) { messageServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); + publishMessagingStatusChange(ServiceStatus.DOWN); } } } From 041f2644ee95588cb448a163902ef1e7cea48e81 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 6 Jul 2015 15:12:41 -0400 Subject: [PATCH 10/44] Changed how service status updates are set and obtained --- .../autopsy/core/ServicesMonitor.java | 132 +++++++++++------- 1 file changed, 81 insertions(+), 51 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 131d2ba79d..f8b4f4d205 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeListener; import java.net.URISyntaxException; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -58,6 +59,11 @@ public class ServicesMonitor { private static final Set serviceNames = Stream.of(ServicesMonitor.Service.values()) .map(ServicesMonitor.Service::toString) .collect(Collectors.toSet()); + + /** + * The service monitor maintains a mapping of each service to it's last status update. + */ + private final ConcurrentHashMap statusByService; /** * List of services that are being monitored. @@ -65,18 +71,37 @@ public class ServicesMonitor { public enum Service { /** - * Property change event fired when ....TODO.... The old value of the - * PropertyChangeEvent object is set to the ingest job id, and the new - * value is set to null. + * Property change event fired when remote case database status changes. + * New value is set to updated ServiceStatus, old value is null. */ REMOTE_CASE_DATABASE, + + /** + * Property change event fired when remote keyword search service status changes. + * New value is set to updated ServiceStatus, old value is null. + */ REMOTE_KEYWORD_SEARCH, + + /** + * Property change event fired when messaging service status changes. + * New value is set to updated ServiceStatus, old value is null. + */ MESSAGING }; + /** + * List of possible service statuses. + */ public enum ServiceStatus { + /** + * Service is currently up. + */ UP, + + /** + * Service is currently down. + */ DOWN }; @@ -90,6 +115,7 @@ public class ServicesMonitor { private ServicesMonitor() { this.eventPublisher = new AutopsyEventPublisher(); + this.statusByService = new ConcurrentHashMap<>(); /** * Start periodic task that check the availability of key collaboration @@ -98,6 +124,49 @@ public class ServicesMonitor { periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build()); periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } + + /** + * Store and publish service status update. + * + * @param service Name of the service. + * @param status Updated status for the service. + */ + private void setServiceStatus(Service service, ServiceStatus status){ + this.statusByService.put(service, status); + publishServiceStatusUpdate(service, status); + } + + /** + * Get last status update for a service. + * + * @param service Name of the service. + * @return ServiceStatus Status for the service. + */ + public ServiceStatus getServiceStatus(Service service){ + // Services are assumed to be "UP" by default. See CrashDetectionTask class for more info. + return this.statusByService.getOrDefault(service, ServiceStatus.UP); + } + + /** + * Publish an event signifying change in service status. Event is published locally. + * + * @param service Name of the service. + * @param status Updated status for the event. + */ + private void publishServiceStatusUpdate(Service service, ServiceStatus status) { + eventPublisher.publishLocally(new ServiceEvent(service.toString(), status.toString(), "")); + } + + /** + * Publish a custom event. Event is published locally. + * + * @param service Name of the service. + * @param status Updated status for the event. + * @param details Details of the event. + */ + public void publishCustomServiceStatus(String service, String status, String details) { + eventPublisher.publishLocally(new ServiceEvent(service, status, details)); + } /** * Adds an event subscriber to this publisher. Subscriber will be subscribed @@ -159,47 +228,6 @@ public class ServicesMonitor { eventPublisher.removeSubscriber(serviceNames, subscriber); } - /** - * Publish an event signifying change in remote database (e.g. PostgreSQL) - * service status. - * - * @param status Updated status for the event. - */ - private void publishRemoteDatabaseStatusChange(ServiceStatus status) { - eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); - } - - /** - * Publish an event signifying change in remote database (e.g. PostgreSQL) - * service status. - * - * @param status Updated status for the event. - */ - private void publishRemoteKeywordSearchStatusChange(ServiceStatus status) { - eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); - } - - /** - * Publish an event signifying change in remote database (e.g. PostgreSQL) - * service status. - * - * @param status Updated status for the event. - */ - private void publishMessagingStatusChange(ServiceStatus status) { - eventPublisher.publishLocally(new ServiceEvent(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString(), null, status.toString())); - } - - /** - * Publish a custom event. - * - * @param service Name of the service. - * @param status Updated status for the event. - * @param details Details of the event. - */ - public void publishServiceStatus(String service, String status, String details) { - eventPublisher.publishLocally(new ServiceEvent(service, status, details)); - } - /** * A Runnable task that periodically checks the availability of * collaboration resources (PostgreSQL server, Solr server, Active MQ @@ -208,9 +236,12 @@ public class ServicesMonitor { */ private final class CrashDetectionTask implements Runnable { + // Services are assumed to be "UP" by default. Change default value in getServiceStatus() + // if this assumption changes. private boolean dbServerIsRunning = true; private boolean solrServerIsRunning = true; private boolean messageServerIsRunning = true; + private final Object lock = new Object(); /** @@ -225,14 +256,14 @@ public class ServicesMonitor { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); - publishRemoteDatabaseStatusChange(ServiceStatus.UP); + setServiceStatus(Service.REMOTE_CASE_DATABASE, ServiceStatus.UP); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); - publishRemoteDatabaseStatusChange(ServiceStatus.DOWN); + setServiceStatus(Service.REMOTE_CASE_DATABASE, ServiceStatus.DOWN); } } @@ -243,14 +274,14 @@ public class ServicesMonitor { solrServerIsRunning = true; logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); - publishRemoteKeywordSearchStatusChange(ServiceStatus.UP); + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH, ServiceStatus.UP); } } else { if (solrServerIsRunning) { solrServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); - publishRemoteKeywordSearchStatusChange(ServiceStatus.DOWN); + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH, ServiceStatus.DOWN); } } @@ -264,18 +295,17 @@ public class ServicesMonitor { messageServerIsRunning = true; logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); - publishMessagingStatusChange(ServiceStatus.UP); + setServiceStatus(Service.MESSAGING, ServiceStatus.UP); } } catch (URISyntaxException | JMSException ex) { if (messageServerIsRunning) { messageServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); - publishMessagingStatusChange(ServiceStatus.DOWN); + setServiceStatus(Service.MESSAGING, ServiceStatus.DOWN); } } } } - } } From 4bd8356fa8e84b5ca16ecf2b21c7c80690006c54 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 6 Jul 2015 15:56:09 -0400 Subject: [PATCH 11/44] Modified HashMap to operate on strings, added UnknownServiceException --- .../autopsy/core/ServicesMonitor.java | 46 +++++++++++++------ .../autopsy/core/UnknownServiceException.java | 33 +++++++++++++ 2 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index f8b4f4d205..583f3b1cd1 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -63,7 +63,7 @@ public class ServicesMonitor { /** * The service monitor maintains a mapping of each service to it's last status update. */ - private final ConcurrentHashMap statusByService; + private final ConcurrentHashMap statusByService; /** * List of services that are being monitored. @@ -116,6 +116,11 @@ public class ServicesMonitor { this.eventPublisher = new AutopsyEventPublisher(); this.statusByService = new ConcurrentHashMap<>(); + + // Services are assumed to be "UP" by default. See CrashDetectionTask class for more info. + for (String serviceName : serviceNames) { + this.statusByService.put(serviceName, ServiceStatus.UP.toString()); + } /** * Start periodic task that check the availability of key collaboration @@ -131,7 +136,7 @@ public class ServicesMonitor { * @param service Name of the service. * @param status Updated status for the service. */ - private void setServiceStatus(Service service, ServiceStatus status){ + private void setServiceStatus(String service, String status){ this.statusByService.put(service, status); publishServiceStatusUpdate(service, status); } @@ -141,10 +146,21 @@ public class ServicesMonitor { * * @param service Name of the service. * @return ServiceStatus Status for the service. + * @throws org.sleuthkit.autopsy.core.UnknownServiceException */ - public ServiceStatus getServiceStatus(Service service){ - // Services are assumed to be "UP" by default. See CrashDetectionTask class for more info. - return this.statusByService.getOrDefault(service, ServiceStatus.UP); + public String getServiceStatus(String service) throws UnknownServiceException { + + if (service == null){ + // TODO NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.existNotDir")); + throw new UnknownServiceException("Requested service name is null"); + } + + String status = this.statusByService.get(service); + if (status == null){ + // no such service + throw new UnknownServiceException("Requested service name " + service + " is unknown"); + } + return status; } /** @@ -153,8 +169,8 @@ public class ServicesMonitor { * @param service Name of the service. * @param status Updated status for the event. */ - private void publishServiceStatusUpdate(Service service, ServiceStatus status) { - eventPublisher.publishLocally(new ServiceEvent(service.toString(), status.toString(), "")); + private void publishServiceStatusUpdate(String service, String status) { + eventPublisher.publishLocally(new ServiceEvent(service, status, "")); } /** @@ -236,8 +252,8 @@ public class ServicesMonitor { */ private final class CrashDetectionTask implements Runnable { - // Services are assumed to be "UP" by default. Change default value in getServiceStatus() - // if this assumption changes. + // Services are assumed to be "UP" by default. Change default value in ServicesMonitor() + // constructor if this assumption changes. private boolean dbServerIsRunning = true; private boolean solrServerIsRunning = true; private boolean messageServerIsRunning = true; @@ -256,14 +272,14 @@ public class ServicesMonitor { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); - setServiceStatus(Service.REMOTE_CASE_DATABASE, ServiceStatus.UP); + setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); - setServiceStatus(Service.REMOTE_CASE_DATABASE, ServiceStatus.DOWN); + setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); } } @@ -274,14 +290,14 @@ public class ServicesMonitor { solrServerIsRunning = true; logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH, ServiceStatus.UP); + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); } } else { if (solrServerIsRunning) { solrServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH, ServiceStatus.DOWN); + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); } } @@ -295,14 +311,14 @@ public class ServicesMonitor { messageServerIsRunning = true; logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); - setServiceStatus(Service.MESSAGING, ServiceStatus.UP); + setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.UP.toString()); } } catch (URISyntaxException | JMSException ex) { if (messageServerIsRunning) { messageServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); - setServiceStatus(Service.MESSAGING, ServiceStatus.DOWN); + setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString()); } } } diff --git a/Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java b/Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java new file mode 100644 index 0000000000..ace8b7aecd --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java @@ -0,0 +1,33 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2012 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +/** + * Exception thrown when service status query results in an error. + */ +public class UnknownServiceException extends Exception { + + public UnknownServiceException(String message) { + super(message); + } + + public UnknownServiceException(String message, Throwable cause) { + super(message, cause); + } +} From 9bb0a4d8bd03e433aea7c41eedf16f2c99392bc2 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 6 Jul 2015 17:01:07 -0400 Subject: [PATCH 12/44] Ingest manager cancels ingest jobs upon service outage events --- .../autopsy/ingest/IngestManager.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 04421de603..1f8d89e00d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -332,20 +333,34 @@ public class IngestManager { PropertyChangeListener propChangeListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - String eventType = evt.getPropertyName(); - if (eventType.equals(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) { - if (evt.getNewValue() == ServicesMonitor.ServiceStatus.DOWN) { - - // TODO - display notification - - // cancel ingest if running - cancelAllIngestJobs(); + String serviceName = evt.getPropertyName(); + if (evt.getNewValue() == ServicesMonitor.ServiceStatus.DOWN.toString()) { + // one of the services we subscribed for went down + + logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceName); //NON-NLS + + // display notification if running interactively + if (isRunningInteractively()){ + // TODO + //MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr"), + // NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr.msg"), + // MessageNotifyUtil.MessageType.ERROR); + MessageNotifyUtil.Notify.show("Service " + serviceName + " is down!", + "Service " + serviceName + " is down!", + MessageNotifyUtil.MessageType.ERROR); } + + // cancel ingest if running + cancelAllIngestJobs(); } } }; - // TODO: sunscribe to all events? - this.servicesMonitor.addSubscriber(propChangeListener); + + // subscribe to services of interest + Set servicesList = new HashSet<>(); + servicesList.add(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()); + servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()); + this.servicesMonitor.addSubscriber(servicesList, propChangeListener); } synchronized void handleCaseOpened() { @@ -395,6 +410,7 @@ public class IngestManager { * The ingest manager can be directed to forgo use of message boxes, the * ingest message box, NetBeans progress handles, etc. Running interactively * is the default. + * @return true if running interactively, false otherwise. */ public boolean isRunningInteractively() { return this.runInteractively; From a99d4eed114ef7e9feac4074c9d454d84ee3b0c7 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 7 Jul 2015 09:51:50 -0400 Subject: [PATCH 13/44] Using NbBundle.getMessage for error dialogs --- .../sleuthkit/autopsy/casemodule/Bundle.properties | 8 -------- .../src/org/sleuthkit/autopsy/core/Bundle.properties | 8 ++++++++ .../org/sleuthkit/autopsy/core/ServicesMonitor.java | 12 ++++++------ .../org/sleuthkit/autopsy/ingest/Bundle.properties | 2 ++ .../org/sleuthkit/autopsy/ingest/IngestManager.java | 11 ++++------- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 28b49a15c1..195edab760 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -242,13 +242,5 @@ LocalFilesPanel.errorLabel.text=Error Label NewCaseVisualPanel1.errorLabel.text=Error Label CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source CollaborationMonitor.analyzingDataSourceStatus.msg={0} analyzing {1} -CollaborationMonitor.failedService.notify.title=Collaboration Service Failed -CollaborationMonitor.failedDbService.notify.msg=Lost connection to database server -CollaborationMonitor.failedSolrService.notify.msg=Lost connection to keyword search server -CollaborationMonitor.failedMessageService.notify.msg=Lost connection to messaging server -CollaborationMonitor.restoredService.notify.title=Collaboration Service Restored -CollaborationMonitor.restoredDbService.notify.msg=Connection to database server restored -CollaborationMonitor.restoredSolrService.notify.msg=Connection to keyword search server restored -CollaborationMonitor.restoredMessageService.notify.msg=Connection to messaging server restored MissingImageDialog.lbWarning.text= MissingImageDialog.lbWarning.toolTipText= diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index ff08a90d89..ce42cbc6e8 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -12,3 +12,11 @@ org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xm Services/AutoupdateType/org_sleuthkit_autopsy_core_update_center.settings=Autopsy Update Center Installer.errorInitJavafx.msg=Error initializing JavaFX. Installer.errorInitJavafx.details=\ Some features will not be available. Check that you have the right JRE installed (Oracle JRE > 1.7.10). +ServicesMonitor.failedService.notify.title=Collaboration Service Failed +ServicesMonitor.failedDbService.notify.msg=Lost connection to remote database server +ServicesMonitor.failedSolrService.notify.msg=Lost connection to remote keyword search server +ServicesMonitor.failedMessageService.notify.msg=Lost connection to messaging server +ServicesMonitor.restoredService.notify.title=Collaboration Service Restored +ServicesMonitor.restoredDbService.notify.msg=Connection to remote database server restored +ServicesMonitor.restoredSolrService.notify.msg=Connection to remote keyword search server restored +ServicesMonitor.restoredMessageService.notify.msg=Connection to messaging server restored \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 583f3b1cd1..3e91465f83 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -271,14 +271,14 @@ public class ServicesMonitor { if (!dbServerIsRunning) { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS - //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredDbService.notify.msg")); setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS - //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedDbService.notify.msg")); setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); } } @@ -289,14 +289,14 @@ public class ServicesMonitor { if (!solrServerIsRunning) { solrServerIsRunning = true; logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS - //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredSolrService.notify.msg")); setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); } } else { if (solrServerIsRunning) { solrServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS - //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedSolrService.notify.msg")); setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); } } @@ -310,14 +310,14 @@ public class ServicesMonitor { if (!messageServerIsRunning) { messageServerIsRunning = true; logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS - //MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredMessageService.notify.msg")); setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.UP.toString()); } } catch (URISyntaxException | JMSException ex) { if (messageServerIsRunning) { messageServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS - //MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedMessageService.notify.msg")); setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString()); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index cfea3bd790..b82d4bb4d3 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -103,3 +103,5 @@ IngestJobSettingsPanel.jButtonSelectAll.text=Select All IngestJobSettingsPanel.jButtonDeselectAll.text=Deselect All IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=Processes unallocated space, such as deleted files. Produces more complete results, but it may take longer to process on large images. IngestJobSettingsPanel.processUnallocCheckbox.text=Process Unallocated Space +IngestManager.cancellingIngest.msgDlg.text=Cancelling all currently running ingest jobs +IngestManager.serviceIsDown.msgDlg.text=Service {0} is down diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 1f8d89e00d..b6d73b2109 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -341,13 +341,10 @@ public class IngestManager { // display notification if running interactively if (isRunningInteractively()){ - // TODO - //MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr"), - // NbBundle.getMessage(this.getClass(), "LocalDiskPanel.moduleErr.msg"), - // MessageNotifyUtil.MessageType.ERROR); - MessageNotifyUtil.Notify.show("Service " + serviceName + " is down!", - "Service " + serviceName + " is down!", - MessageNotifyUtil.MessageType.ERROR); + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "IngestManager.cancellingIngest.msgDlg.text"), + NbBundle.getMessage(this.getClass(), "IngestManager.serviceIsDown.msgDlg.text", serviceName), + JOptionPane.ERROR_MESSAGE); } // cancel ingest if running From f4bc81f93efd6ac37d1f9b591dc9f85e4388c4b3 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 7 Jul 2015 13:53:27 -0400 Subject: [PATCH 14/44] Minor changes --- .../autopsy/core/ServicesMonitor.java | 22 ++++++++++--------- .../autopsy/ingest/IngestManager.java | 14 ++++++------ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 3e91465f83..b054672ccf 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -56,8 +56,8 @@ public class ServicesMonitor { private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1; private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; - private static final Set serviceNames = Stream.of(ServicesMonitor.Service.values()) - .map(ServicesMonitor.Service::toString) + private static final Set serviceNames = Stream.of(ServicesMonitor.ServiceName.values()) + .map(ServicesMonitor.ServiceName::toString) .collect(Collectors.toSet()); /** @@ -66,9 +66,11 @@ public class ServicesMonitor { private final ConcurrentHashMap statusByService; /** - * List of services that are being monitored. + * List of services that are being monitored. The service names should be + * representative of the service functionality and readable as they get + * logged when service outage occurs. */ - public enum Service { + public enum ServiceName { /** * Property change event fired when remote case database status changes. @@ -272,14 +274,14 @@ public class ServicesMonitor { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredDbService.notify.msg")); - setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedDbService.notify.msg")); - setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); } } @@ -290,14 +292,14 @@ public class ServicesMonitor { solrServerIsRunning = true; logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredSolrService.notify.msg")); - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); } } else { if (solrServerIsRunning) { solrServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedSolrService.notify.msg")); - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); } } @@ -311,14 +313,14 @@ public class ServicesMonitor { messageServerIsRunning = true; logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredMessageService.notify.msg")); - setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.UP.toString()); + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString()); } } catch (URISyntaxException | JMSException ex) { if (messageServerIsRunning) { messageServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedMessageService.notify.msg")); - setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString()); + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index b6d73b2109..dfa23be866 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -327,16 +327,16 @@ public class IngestManager { } /** - * Subscribe ingest manager to service monitor events. + * Subscribe ingest manager to service monitor events. Cancels ingest + * if one of services it's subscribed to goes down. */ private void subscribeToServiceMonitorEvents() { PropertyChangeListener propChangeListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - String serviceName = evt.getPropertyName(); - if (evt.getNewValue() == ServicesMonitor.ServiceStatus.DOWN.toString()) { - // one of the services we subscribed for went down - + if (evt.getNewValue().equals(ServicesMonitor.ServiceStatus.DOWN.toString())) { + // one of the services we subscribed to went down + String serviceName = evt.getPropertyName(); logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceName); //NON-NLS // display notification if running interactively @@ -355,8 +355,8 @@ public class IngestManager { // subscribe to services of interest Set servicesList = new HashSet<>(); - servicesList.add(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()); - servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()); + servicesList.add(ServicesMonitor.ServiceName.REMOTE_CASE_DATABASE.toString()); + servicesList.add(ServicesMonitor.ServiceName.REMOTE_KEYWORD_SEARCH.toString()); this.servicesMonitor.addSubscriber(servicesList, propChangeListener); } From c9f2863e27323e54788f483ba8db14ddcdebd5b9 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 7 Jul 2015 16:38:56 -0400 Subject: [PATCH 15/44] Refactored service monitor to perform on-demand checks when service status is unknown --- .../autopsy/core/ServicesMonitor.java | 242 +++++++++++------- 1 file changed, 150 insertions(+), 92 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index b054672ccf..d2e157e9a1 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -38,7 +38,6 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; -import org.sleuthkit.datamodel.CaseDbConnectionInfo; /** * This class periodically checks availability of collaboration resources - @@ -59,52 +58,55 @@ public class ServicesMonitor { private static final Set serviceNames = Stream.of(ServicesMonitor.ServiceName.values()) .map(ServicesMonitor.ServiceName::toString) .collect(Collectors.toSet()); - - /** - * The service monitor maintains a mapping of each service to it's last status update. - */ - private final ConcurrentHashMap statusByService; /** - * List of services that are being monitored. The service names should be - * representative of the service functionality and readable as they get + * The service monitor maintains a mapping of each service to it's last + * status update. + */ + private final ConcurrentHashMap statusByService; + + /** + * List of services that are being monitored. The service names should be + * representative of the service functionality and readable as they get * logged when service outage occurs. */ public enum ServiceName { /** - * Property change event fired when remote case database status changes. + * Property change event fired when remote case database status changes. * New value is set to updated ServiceStatus, old value is null. */ REMOTE_CASE_DATABASE, - /** - * Property change event fired when remote keyword search service status changes. - * New value is set to updated ServiceStatus, old value is null. - */ + * Property change event fired when remote keyword search service status + * changes. New value is set to updated ServiceStatus, old value is + * null. + */ REMOTE_KEYWORD_SEARCH, - /** * Property change event fired when messaging service status changes. * New value is set to updated ServiceStatus, old value is null. - */ + */ MESSAGING }; /** * List of possible service statuses. - */ + */ public enum ServiceStatus { /** * Service is currently up. */ UP, - /** * Service is currently down. */ - DOWN + DOWN, + /** + * Service status is unknown. + */ + UNKNOWN, }; public synchronized static ServicesMonitor getInstance() { @@ -118,10 +120,8 @@ public class ServicesMonitor { this.eventPublisher = new AutopsyEventPublisher(); this.statusByService = new ConcurrentHashMap<>(); - - // Services are assumed to be "UP" by default. See CrashDetectionTask class for more info. for (String serviceName : serviceNames) { - this.statusByService.put(serviceName, ServiceStatus.UP.toString()); + this.statusByService.put(serviceName, ServiceStatus.UNKNOWN.toString()); } /** @@ -131,42 +131,86 @@ public class ServicesMonitor { periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build()); periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } - + /** - * Store and publish service status update. - * + * Store and publish service status update. + * * @param service Name of the service. * @param status Updated status for the service. */ - private void setServiceStatus(String service, String status){ + private void setServiceStatus(String service, String status) { this.statusByService.put(service, status); publishServiceStatusUpdate(service, status); } - + /** * Get last status update for a service. - * + * * @param service Name of the service. * @return ServiceStatus Status for the service. * @throws org.sleuthkit.autopsy.core.UnknownServiceException */ public String getServiceStatus(String service) throws UnknownServiceException { - - if (service == null){ + + if (service == null) { // TODO NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.existNotDir")); throw new UnknownServiceException("Requested service name is null"); } - + String status = this.statusByService.get(service); - if (status == null){ + if (status == null) { // no such service throw new UnknownServiceException("Requested service name " + service + " is unknown"); + + } else if (status.equals(ServiceStatus.UNKNOWN.toString())) { + // status for the service is not known. This is likely because we haven't + // checked it's status yet. Perform an on-demand check of the service status. + status = checkServiceStatusStatus(service); } return status; } - + /** - * Publish an event signifying change in service status. Event is published locally. + * Performs on-demand check of service availability. + * + * @param service Name of the service. + * @return String Status for the service. + */ + private String checkServiceStatusStatus(String service) { + + if (service.equals(ServiceName.REMOTE_CASE_DATABASE.toString())) { + if (canConnectToRemoteDb()) { + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); + return ServiceStatus.DOWN.toString(); + } + } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())){ + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); + // TODO - do I need to check for kwsService == null? + if (kwsService.canConnectToRemoteSolrServer()) { + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); + return ServiceStatus.DOWN.toString(); + } + } else if (service.equals(ServiceName.MESSAGING.toString())) { + if (canConnectToMessagingService()) { + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString()); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); + return ServiceStatus.DOWN.toString(); + } + } + return ServiceStatus.UNKNOWN.toString(); + } + + /** + * Publish an event signifying change in service status. Event is published + * locally. * * @param service Name of the service. * @param status Updated status for the event. @@ -184,7 +228,7 @@ public class ServicesMonitor { */ public void publishCustomServiceStatus(String service, String status, String details) { eventPublisher.publishLocally(new ServiceEvent(service, status, details)); - } + } /** * Adds an event subscriber to this publisher. Subscriber will be subscribed @@ -246,20 +290,41 @@ public class ServicesMonitor { eventPublisher.removeSubscriber(serviceNames, subscriber); } + /** + * Verifies connection to remote database. + * + * @return True if connection can be established, false otherwise. + */ + private boolean canConnectToRemoteDb() { + return UserPreferences.getDatabaseConnectionInfo().canConnect(); + } + + /** + * Verifies connection to messaging service. + * + * @return True if connection can be established, false otherwise. + */ + private boolean canConnectToMessagingService() { + MessageServiceConnectionInfo msgInfo = UserPreferences.getMessageServiceConnectionInfo(); + try { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(msgInfo.getUserName(), msgInfo.getPassword(), msgInfo.getURI()); + Connection connection = connectionFactory.createConnection(); + connection.start(); + connection.close(); + return true; + } catch (URISyntaxException | JMSException ex) { + return false; + } + } + /** * A Runnable task that periodically checks the availability of - * collaboration resources (PostgreSQL server, Solr server, Active MQ + * collaboration resources (remote database, remote keyword search service, * message broker) and reports status to the user in case of a gap in * service. */ private final class CrashDetectionTask implements Runnable { - // Services are assumed to be "UP" by default. Change default value in ServicesMonitor() - // constructor if this assumption changes. - private boolean dbServerIsRunning = true; - private boolean solrServerIsRunning = true; - private boolean messageServerIsRunning = true; - private final Object lock = new Object(); /** @@ -268,60 +333,53 @@ public class ServicesMonitor { @Override public void run() { synchronized (lock) { - CaseDbConnectionInfo dbInfo = UserPreferences.getDatabaseConnectionInfo(); - if (dbInfo.canConnect()) { - if (!dbServerIsRunning) { - dbServerIsRunning = true; - logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredDbService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); - } - } else { - if (dbServerIsRunning) { - dbServerIsRunning = false; - logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedDbService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); - } - } - - KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); - // TODO - do I need to check for kwsService == null? - if (kwsService.canConnectToRemoteSolrServer()) { - if (!solrServerIsRunning) { - solrServerIsRunning = true; - logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredSolrService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); - } - } else { - if (solrServerIsRunning) { - solrServerIsRunning = false; - logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedSolrService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); - } - } - - MessageServiceConnectionInfo msgInfo = UserPreferences.getMessageServiceConnectionInfo(); try { - ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(msgInfo.getUserName(), msgInfo.getPassword(), msgInfo.getURI()); - Connection connection = connectionFactory.createConnection(); - connection.start(); - connection.close(); - if (!messageServerIsRunning) { - messageServerIsRunning = true; - logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredMessageService.notify.msg")); - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString()); + if (canConnectToRemoteDb()) { + if (!getServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString()).equals(ServiceStatus.UP.toString())) { + logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredDbService.notify.msg")); + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); + } + } else { + if (!getServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString()).equals(ServiceStatus.DOWN.toString())) { + logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedDbService.notify.msg")); + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); + } } - } catch (URISyntaxException | JMSException ex) { - if (messageServerIsRunning) { - messageServerIsRunning = false; - logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedMessageService.notify.msg")); - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); + + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); + // TODO - do I need to check for kwsService == null? + if (kwsService.canConnectToRemoteSolrServer()) { + if (!getServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString()).equals(ServiceStatus.UP.toString())) { + logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredSolrService.notify.msg")); + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); + } + } else { + if (!getServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString()).equals(ServiceStatus.DOWN.toString())) { + logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedSolrService.notify.msg")); + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); + } } + + if (canConnectToMessagingService()) { + if (!getServiceStatus(ServiceName.MESSAGING.toString()).equals(ServiceStatus.UP.toString())) { + logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredMessageService.notify.msg")); + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString()); + } + } else { + if (!getServiceStatus(ServiceName.MESSAGING.toString()).equals(ServiceStatus.DOWN.toString())) { + logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server"); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedMessageService.notify.msg")); + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); + } + } + + } catch (UnknownServiceException ex) { + logger.log(Level.SEVERE, "Exception while checking current service status", ex); //NON-NLS } } } From b47a3a05adf2769cf2e7ab74d05597456ac1b8ca Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 7 Jul 2015 16:48:44 -0400 Subject: [PATCH 16/44] Exception texts via NbBundle.getMessage --- Core/src/org/sleuthkit/autopsy/core/Bundle.properties | 4 +++- Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index ce42cbc6e8..becba527a5 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -19,4 +19,6 @@ ServicesMonitor.failedMessageService.notify.msg=Lost connection to messaging ser ServicesMonitor.restoredService.notify.title=Collaboration Service Restored ServicesMonitor.restoredDbService.notify.msg=Connection to remote database server restored ServicesMonitor.restoredSolrService.notify.msg=Connection to remote keyword search server restored -ServicesMonitor.restoredMessageService.notify.msg=Connection to messaging server restored \ No newline at end of file +ServicesMonitor.restoredMessageService.notify.msg=Connection to messaging server restored +ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null +ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index d2e157e9a1..0331107d3a 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -153,14 +153,13 @@ public class ServicesMonitor { public String getServiceStatus(String service) throws UnknownServiceException { if (service == null) { - // TODO NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.existNotDir")); - throw new UnknownServiceException("Requested service name is null"); + throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); } String status = this.statusByService.get(service); if (status == null) { // no such service - throw new UnknownServiceException("Requested service name " + service + " is unknown"); + throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt")); } else if (status.equals(ServiceStatus.UNKNOWN.toString())) { // status for the service is not known. This is likely because we haven't From e28ec27c36c2bf6eca1e5dba832bd9e9229fcbad Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 8 Jul 2015 11:30:58 -0400 Subject: [PATCH 17/44] Refactroed service monitor for better code reuse --- .../sleuthkit/autopsy/core/Bundle.properties | 8 +- .../autopsy/core/ServicesMonitor.java | 83 +++++++------------ 2 files changed, 31 insertions(+), 60 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index becba527a5..8f1455637e 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -13,12 +13,8 @@ Services/AutoupdateType/org_sleuthkit_autopsy_core_update_center.settings=Autops Installer.errorInitJavafx.msg=Error initializing JavaFX. Installer.errorInitJavafx.details=\ Some features will not be available. Check that you have the right JRE installed (Oracle JRE > 1.7.10). ServicesMonitor.failedService.notify.title=Collaboration Service Failed -ServicesMonitor.failedDbService.notify.msg=Lost connection to remote database server -ServicesMonitor.failedSolrService.notify.msg=Lost connection to remote keyword search server -ServicesMonitor.failedMessageService.notify.msg=Lost connection to messaging server +ServicesMonitor.failedService.notify.msg=Lost connection to {0} ServicesMonitor.restoredService.notify.title=Collaboration Service Restored -ServicesMonitor.restoredDbService.notify.msg=Connection to remote database server restored -ServicesMonitor.restoredSolrService.notify.msg=Connection to remote keyword search server restored -ServicesMonitor.restoredMessageService.notify.msg=Connection to messaging server restored +ServicesMonitor.restoredService.notify.msg=Connection to {0} restored ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 0331107d3a..567711fcde 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -104,7 +104,8 @@ public class ServicesMonitor { */ DOWN, /** - * Service status is unknown. + * Service status is unknown. This is the initial status for all + * services. */ UNKNOWN, }; @@ -133,13 +134,32 @@ public class ServicesMonitor { } /** - * Store and publish service status update. + * Updates service status and publishes the service status update if it is + * different from previous status. Logs status changes. * * @param service Name of the service. * @param status Updated status for the service. */ private void setServiceStatus(String service, String status) { - this.statusByService.put(service, status); + + // verify that status has changed + if (status.equals(statusByService.get(service))) { + return; + } + + // status has changed + if (status.equals(ServiceStatus.UP.toString())) { + logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg")); + } else if (status.equals(ServiceStatus.DOWN.toString())) { + logger.log(Level.SEVERE, "Failed to connect to {0}", service); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg")); + } + + // update and publish new status + statusByService.put(service, status); publishServiceStatusUpdate(service, status); } @@ -156,7 +176,7 @@ public class ServicesMonitor { throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); } - String status = this.statusByService.get(service); + String status = statusByService.get(service); if (status == null) { // no such service throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt")); @@ -185,7 +205,7 @@ public class ServicesMonitor { setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); return ServiceStatus.DOWN.toString(); } - } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())){ + } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())) { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); // TODO - do I need to check for kwsService == null? if (kwsService.canConnectToRemoteSolrServer()) { @@ -202,7 +222,7 @@ public class ServicesMonitor { } else { setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); return ServiceStatus.DOWN.toString(); - } + } } return ServiceStatus.UNKNOWN.toString(); } @@ -332,54 +352,9 @@ public class ServicesMonitor { @Override public void run() { synchronized (lock) { - try { - if (canConnectToRemoteDb()) { - if (!getServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString()).equals(ServiceStatus.UP.toString())) { - logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredDbService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); - } - } else { - if (!getServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString()).equals(ServiceStatus.DOWN.toString())) { - logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedDbService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); - } - } - - KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); - // TODO - do I need to check for kwsService == null? - if (kwsService.canConnectToRemoteSolrServer()) { - if (!getServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString()).equals(ServiceStatus.UP.toString())) { - logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredSolrService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); - } - } else { - if (!getServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString()).equals(ServiceStatus.DOWN.toString())) { - logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedSolrService.notify.msg")); - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); - } - } - - if (canConnectToMessagingService()) { - if (!getServiceStatus(ServiceName.MESSAGING.toString()).equals(ServiceStatus.UP.toString())) { - logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredMessageService.notify.msg")); - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString()); - } - } else { - if (!getServiceStatus(ServiceName.MESSAGING.toString()).equals(ServiceStatus.DOWN.toString())) { - logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedMessageService.notify.msg")); - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); - } - } - - } catch (UnknownServiceException ex) { - logger.log(Level.SEVERE, "Exception while checking current service status", ex); //NON-NLS - } + checkServiceStatusStatus(ServiceName.REMOTE_CASE_DATABASE.toString()); + checkServiceStatusStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString()); + checkServiceStatusStatus(ServiceName.MESSAGING.toString()); } } } From cfc7cf33e23660efe4e48daa553fc9c2680401ef Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 8 Jul 2015 13:29:05 -0400 Subject: [PATCH 18/44] Synchronization for status setting, immediate execution of first services check --- Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 567711fcde..4f88c0f916 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -127,10 +127,10 @@ public class ServicesMonitor { /** * Start periodic task that check the availability of key collaboration - * services. + * services. First check is triggered immediately. */ periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build()); - periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); + periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), 0, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } /** @@ -140,7 +140,7 @@ public class ServicesMonitor { * @param service Name of the service. * @param status Updated status for the service. */ - private void setServiceStatus(String service, String status) { + private synchronized void setServiceStatus(String service, String status) { // verify that status has changed if (status.equals(statusByService.get(service))) { From ad5a0219f1e63fe594e25bfadc29f36153d5d87d Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 8 Jul 2015 13:40:22 -0400 Subject: [PATCH 19/44] Removed unused imports, cleanup --- Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java | 4 ---- Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java | 1 - 2 files changed, 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java index 3592190fd3..0bbdf5a743 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java @@ -28,14 +28,10 @@ import org.sleuthkit.autopsy.events.AutopsyEvent; public final class ServiceEvent extends AutopsyEvent implements Serializable { private static final long serialVersionUID = 1L; - //private final String service; - //private final String status; private final String details; public ServiceEvent(String serviceName, String status, String details) { super(serviceName, null, status); - //this.service = service; - //this.status = status; this.details = details; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index dfa23be866..c4cd42b93f 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -45,7 +45,6 @@ import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.util.Cancellable; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.core.ServiceEvent; import org.sleuthkit.autopsy.core.ServicesMonitor; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.events.AutopsyEvent; From 4f35fa0ce70d9239129e49edf6b44808ef6511c7 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 8 Jul 2015 13:46:44 -0400 Subject: [PATCH 20/44] Added comments --- Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java index 0bbdf5a743..e1ed6f75ff 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java @@ -22,8 +22,11 @@ import java.io.Serializable; import org.sleuthkit.autopsy.events.AutopsyEvent; /** - * - * @author elivis + * A class for events to be published to registered subscribers of Service + * Monitor on this Autopsy node. The class extends PropertyChangeEvent (via + * AutopsyEvent) to integrate with legacy use of JavaBeans PropertyChangeEvents + * and PropertyChangeListeners as an application event system, and implements + * Serializable to allow it to be published over a network in serialized form. */ public final class ServiceEvent extends AutopsyEvent implements Serializable { From 182d88a87cb0f1006b37cc68ec78e0834993ed19 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 8 Jul 2015 16:23:17 -0400 Subject: [PATCH 21/44] Removed notification for first services scan, bug fix --- .../org/sleuthkit/autopsy/core/ServicesMonitor.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 4f88c0f916..774ac8b8da 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -149,13 +149,16 @@ public class ServicesMonitor { // status has changed if (status.equals(ServiceStatus.UP.toString())) { - logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), - NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg")); + // do not send notification to UI for initial check + if (!statusByService.get(service).equals(ServiceStatus.UNKNOWN.toString())) { + logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg", service)); + } } else if (status.equals(ServiceStatus.DOWN.toString())) { logger.log(Level.SEVERE, "Failed to connect to {0}", service); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), - NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg")); + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg", service)); } // update and publish new status From bdc7ca047f296cb60f2ae361dfe9e2d95e02a8bc Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 10 Jul 2015 15:55:00 -0400 Subject: [PATCH 22/44] Only display notification if there are currently running ingest jobs --- Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index c4cd42b93f..3704e3f5a2 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -339,7 +339,7 @@ public class IngestManager { logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceName); //NON-NLS // display notification if running interactively - if (isRunningInteractively()){ + if (isIngestRunning() && isRunningInteractively()){ JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "IngestManager.cancellingIngest.msgDlg.text"), NbBundle.getMessage(this.getClass(), "IngestManager.serviceIsDown.msgDlg.text", serviceName), From b9db444e6dc2f40a739f3d4583c5c413444473f7 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 15 Jul 2015 12:23:16 -0400 Subject: [PATCH 23/44] Moving event publishing off the EDT --- .../AddBlackboardArtifactTagAction.java | 38 +++-- .../autopsy/actions/AddContentTagAction.java | 154 ++++++++++-------- .../DeleteBlackboardArtifactTagAction.java | 37 +++-- .../actions/DeleteContentTagAction.java | 35 ++-- .../AddImageWizardIngestConfigPanel.java | 22 ++- .../DirectoryTreeTopComponent.java | 6 +- .../autopsy/events/RemoteEventPublisher.java | 4 +- 7 files changed, 170 insertions(+), 126 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java index 2568ba2936..91dc25193c 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.actions; import java.util.Collection; import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.util.Utilities; @@ -61,21 +62,26 @@ public class AddBlackboardArtifactTagAction extends AddTagAction { @Override protected void addTag(TagName tagName, String comment) { - Collection selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class); - for (BlackboardArtifact artifact : selectedArtifacts) { - try { - Case.getCurrentCase().getServices().getTagsManager().addBlackboardArtifactTag(artifact, tagName, comment); - } - catch (TskCoreException ex) { - Logger.getLogger(AddBlackboardArtifactTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "AddBlackboardArtifactTagAction.unableToTag.msg", - artifact.getDisplayName()), - NbBundle.getMessage(this.getClass(), - "AddBlackboardArtifactTagAction.taggingErr"), - JOptionPane.ERROR_MESSAGE); - } - } + final Collection selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class); + + new Thread(() -> { + for (BlackboardArtifact artifact : selectedArtifacts) { + try { + Case.getCurrentCase().getServices().getTagsManager().addBlackboardArtifactTag(artifact, tagName, comment); + } + catch (TskCoreException ex) { + Logger.getLogger(AddBlackboardArtifactTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AddBlackboardArtifactTagAction.unableToTag.msg", + artifact.getDisplayName()), + NbBundle.getMessage(this.getClass(), + "AddBlackboardArtifactTagAction.taggingErr"), + JOptionPane.ERROR_MESSAGE); + }); + } + } + }).start(); } } diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java index cff35af7c1..6f1b493ecf 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.List; import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.util.Utilities; @@ -64,81 +65,98 @@ public class AddContentTagAction extends AddTagAction { @Override protected void addTag(TagName tagName, String comment) { - Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); - for (AbstractFile file : selectedFiles) { - try { - // Handle the special cases of current (".") and parent ("..") directory entries. - if (file.getName().equals(".")) { - Content parentFile = file.getParent(); - if (parentFile instanceof AbstractFile) { - file = (AbstractFile)parentFile; - } - else { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.unableToTag.msg", - parentFile.getName()), - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.cannotApplyTagErr"), - JOptionPane.WARNING_MESSAGE); - continue; - } - } - else if (file.getName().equals("..")) { - Content parentFile = file.getParent(); - if (parentFile instanceof AbstractFile) { - parentFile = (AbstractFile)((AbstractFile)parentFile).getParent(); + final Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); + + new Thread(() -> { + for (AbstractFile file : selectedFiles) { + try { + // Handle the special cases of current (".") and parent ("..") directory entries. + if (file.getName().equals(".")) { + Content parentFile = file.getParent(); if (parentFile instanceof AbstractFile) { file = (AbstractFile)parentFile; } else { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.unableToTag.msg", - parentFile.getName()), - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.cannotApplyTagErr"), - JOptionPane.WARNING_MESSAGE); + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.unableToTag.msg", + parentFile.getName()), + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.cannotApplyTagErr"), + JOptionPane.WARNING_MESSAGE); + }); continue; } } - else { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.unableToTag.msg", - parentFile.getName()), - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.cannotApplyTagErr"), - JOptionPane.WARNING_MESSAGE); - continue; - } - } - // check if the same tag is being added for the same abstract file. - TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); - List contentTagList = tagsManager.getContentTagsByContent(file); - for (ContentTag contentTag : contentTagList) { - if (contentTag.getName().getDisplayName().equals(tagName.getDisplayName())) { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.tagExists", - file.getName(), tagName.getDisplayName()), - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.cannotApplyTagErr"), - JOptionPane.WARNING_MESSAGE); - return; + else if (file.getName().equals("..")) { + Content parentFile = file.getParent(); + if (parentFile instanceof AbstractFile) { + parentFile = (AbstractFile)((AbstractFile)parentFile).getParent(); + if (parentFile instanceof AbstractFile) { + file = (AbstractFile)parentFile; + } + else { + final Content parentFileCopy = parentFile; + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.unableToTag.msg", + parentFileCopy.getName()), + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.cannotApplyTagErr"), + JOptionPane.WARNING_MESSAGE); + }); + continue; + } + } + else { + final Content parentFileCopy = parentFile; + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.unableToTag.msg", + parentFileCopy.getName()), + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.cannotApplyTagErr"), + JOptionPane.WARNING_MESSAGE); + }); + continue; + } } + // check if the same tag is being added for the same abstract file. + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + List contentTagList = tagsManager.getContentTagsByContent(file); + for (ContentTag contentTag : contentTagList) { + if (contentTag.getName().getDisplayName().equals(tagName.getDisplayName())) { + AbstractFile fileCopy = file; + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.tagExists", + fileCopy.getName(), tagName.getDisplayName()), + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.cannotApplyTagErr"), + JOptionPane.WARNING_MESSAGE); + }); + return; + } + } + tagsManager.addContentTag(file, tagName, comment); } - tagsManager.addContentTag(file, tagName, comment); - } - catch (TskCoreException ex) { - Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "AddContentTagAction.unableToTag.msg2", - file.getName()), - NbBundle.getMessage(this.getClass(), "AddContentTagAction.taggingErr"), - JOptionPane.ERROR_MESSAGE); - } - } - } + catch (TskCoreException ex) { + Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS + AbstractFile fileCopy = file; + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AddContentTagAction.unableToTag.msg2", + fileCopy.getName()), + NbBundle.getMessage(this.getClass(), "AddContentTagAction.taggingErr"), + JOptionPane.ERROR_MESSAGE); + }); + } + } + }).start(); + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java index ac9e29fe59..51482c0928 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; @@ -55,22 +56,26 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction { @Override public void actionPerformed(ActionEvent event) { - Collection selectedTags = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactTag.class); - for (BlackboardArtifactTag tag : selectedTags) { - try { - Case.getCurrentCase().getServices().getTagsManager().deleteBlackboardArtifactTag(tag); - } - catch (TskCoreException ex) { - Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "DeleteBlackboardArtifactTagAction.unableToDelTag.msg", - tag.getName()), - NbBundle.getMessage(this.getClass(), - "DeleteBlackboardArtifactTagAction.tagDelErr"), - JOptionPane.ERROR_MESSAGE); - } - } + final Collection selectedTags = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactTag.class); + new Thread(() -> { + for (BlackboardArtifactTag tag : selectedTags) { + try { + Case.getCurrentCase().getServices().getTagsManager().deleteBlackboardArtifactTag(tag); + } + catch (TskCoreException ex) { + Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "DeleteBlackboardArtifactTagAction.unableToDelTag.msg", + tag.getName()), + NbBundle.getMessage(this.getClass(), + "DeleteBlackboardArtifactTagAction.tagDelErr"), + JOptionPane.ERROR_MESSAGE); + }); + } + } + }).start(); } } diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java index c716311eea..f215df8a40 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; @@ -55,20 +56,24 @@ public class DeleteContentTagAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { - Collection selectedTags = Utilities.actionsGlobalContext().lookupAll(ContentTag.class); - for (ContentTag tag : selectedTags) { - try { - Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(tag); - } - catch (TskCoreException ex) { - Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "DeleteContentTagAction.unableToDelTag.msg", - tag.getName()), - NbBundle.getMessage(this.getClass(), "DeleteContentTagAction.tagDelErr"), - JOptionPane.ERROR_MESSAGE); - } - } + final Collection selectedTags = Utilities.actionsGlobalContext().lookupAll(ContentTag.class); + new Thread(() -> { + for (ContentTag tag : selectedTags) { + try { + Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(tag); + } + catch (TskCoreException ex) { + Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "DeleteContentTagAction.unableToDelTag.msg", + tag.getName()), + NbBundle.getMessage(this.getClass(), "DeleteContentTagAction.tagDelErr"), + JOptionPane.ERROR_MESSAGE); + }); + } + } + }).start(); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index d9479c5a6d..2633d0f74e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -238,7 +238,9 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { + Case.getCurrentCase().notifyAddingNewDataSource(dataSourceId); + }).start(); DataSourceProcessorCallback cbObj = new DataSourceProcessorCallback () { @Override public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List errList, List contents) { @@ -258,8 +260,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { + Case.getCurrentCase().notifyFailedAddingNewDataSource(dataSourceId); + }).start(); + dsProcessor.cancel(); } /* @@ -307,11 +311,13 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { + if (!newContents.isEmpty()) { + Case.getCurrentCase().notifyNewDataSource(newContents.get(0), dataSourceId); + } else { + Case.getCurrentCase().notifyFailedAddingNewDataSource(dataSourceId); + } + }).start(); // Start ingest if we can diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 791272d57b..d93f3d1ba8 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -567,8 +567,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat */ try { Case.getCurrentCase(); - CoreComponentControl.openCoreWindows(); - SwingUtilities.invokeLater(this::componentOpened); + SwingUtilities.invokeLater(() -> { + CoreComponentControl.openCoreWindows(); + componentOpened(); + }); } catch (IllegalStateException notUsed) { /** * Case is closed, do nothing. diff --git a/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java b/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java index dde382e397..01e47342ae 100644 --- a/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java +++ b/Core/src/org/sleuthkit/autopsy/events/RemoteEventPublisher.java @@ -169,7 +169,9 @@ final class RemoteEventPublisher { if (object instanceof AutopsyEvent) { AutopsyEvent event = (AutopsyEvent) object; event.setSourceType(AutopsyEvent.SourceType.REMOTE); - localPublisher.publish(event); + new Thread(() -> { + localPublisher.publish(event); + }).start(); } } } catch (Exception ex) { From 43e23bb00eb309f27c251babfb455fb1e1bc2fad Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 15 Jul 2015 16:26:57 -0400 Subject: [PATCH 24/44] First scan is done in constructor, removed UNKNOWN service status --- .../autopsy/core/ServicesMonitor.java | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 774ac8b8da..b3c8877a89 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -48,7 +48,7 @@ public class ServicesMonitor { private AutopsyEventPublisher eventPublisher; private static final Logger logger = Logger.getLogger(ServicesMonitor.class.getName()); - private static ServicesMonitor instance; + private static ServicesMonitor instance = new ServicesMonitor(); private final ScheduledThreadPoolExecutor periodicTasksExecutor; private static final String PERIODIC_TASK_THREAD_NAME = "services-monitor-periodic-task-%d"; @@ -102,12 +102,7 @@ public class ServicesMonitor { /** * Service is currently down. */ - DOWN, - /** - * Service status is unknown. This is the initial status for all - * services. - */ - UNKNOWN, + DOWN }; public synchronized static ServicesMonitor getInstance() { @@ -121,16 +116,16 @@ public class ServicesMonitor { this.eventPublisher = new AutopsyEventPublisher(); this.statusByService = new ConcurrentHashMap<>(); - for (String serviceName : serviceNames) { - this.statusByService.put(serviceName, ServiceStatus.UNKNOWN.toString()); - } + + // First check is triggered immediately on current thread. + checkAllServices(); /** * Start periodic task that check the availability of key collaboration - * services. First check is triggered immediately. + * services. */ periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build()); - periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), 0, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); + periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } /** @@ -149,12 +144,9 @@ public class ServicesMonitor { // status has changed if (status.equals(ServiceStatus.UP.toString())) { - // do not send notification to UI for initial check - if (!statusByService.get(service).equals(ServiceStatus.UNKNOWN.toString())) { - logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), - NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg", service)); - } + logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg", service)); } else if (status.equals(ServiceStatus.DOWN.toString())) { logger.log(Level.SEVERE, "Failed to connect to {0}", service); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), @@ -183,11 +175,6 @@ public class ServicesMonitor { if (status == null) { // no such service throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt")); - - } else if (status.equals(ServiceStatus.UNKNOWN.toString())) { - // status for the service is not known. This is likely because we haven't - // checked it's status yet. Perform an on-demand check of the service status. - status = checkServiceStatusStatus(service); } return status; } @@ -210,8 +197,7 @@ public class ServicesMonitor { } } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())) { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); - // TODO - do I need to check for kwsService == null? - if (kwsService.canConnectToRemoteSolrServer()) { + if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); return ServiceStatus.UP.toString(); } else { @@ -227,7 +213,10 @@ public class ServicesMonitor { return ServiceStatus.DOWN.toString(); } } - return ServiceStatus.UNKNOWN.toString(); + + // can't check for any other services, treat them as "down" + setServiceStatus(service, ServiceStatus.DOWN.toString()); + return ServiceStatus.DOWN.toString(); } /** @@ -338,6 +327,15 @@ public class ServicesMonitor { return false; } } + + /** + * Verifies connectivity to all services. + */ + private void checkAllServices() { + for (String serviceName : serviceNames) { + checkServiceStatusStatus(serviceName); + } + } /** * A Runnable task that periodically checks the availability of @@ -347,18 +345,12 @@ public class ServicesMonitor { */ private final class CrashDetectionTask implements Runnable { - private final Object lock = new Object(); - /** * Monitor the availability of collaboration resources */ @Override public void run() { - synchronized (lock) { - checkServiceStatusStatus(ServiceName.REMOTE_CASE_DATABASE.toString()); - checkServiceStatusStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString()); - checkServiceStatusStatus(ServiceName.MESSAGING.toString()); - } + checkAllServices(); } } } From f720e91aa3298fa8720218171ae04cc9882566e4 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 15 Jul 2015 17:23:24 -0400 Subject: [PATCH 25/44] Fist services check done in constructor, refactored setServiceStatus() --- .../sleuthkit/autopsy/core/Bundle.properties | 1 + .../autopsy/core/ServicesMonitor.java | 115 +++++++++--------- 2 files changed, 57 insertions(+), 59 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index 8f1455637e..44d90ee138 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -17,4 +17,5 @@ ServicesMonitor.failedService.notify.msg=Lost connection to {0} ServicesMonitor.restoredService.notify.title=Collaboration Service Restored ServicesMonitor.restoredService.notify.msg=Connection to {0} restored ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null +ServicesMonitor.nullStatusOrDetails.excepton.txt=Status or details string is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index b3c8877a89..f62cd0c8fb 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -31,6 +31,7 @@ import java.util.stream.Stream; import javax.jms.Connection; import javax.jms.JMSException; import org.apache.activemq.ActiveMQConnectionFactory; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; @@ -48,7 +49,6 @@ public class ServicesMonitor { private AutopsyEventPublisher eventPublisher; private static final Logger logger = Logger.getLogger(ServicesMonitor.class.getName()); - private static ServicesMonitor instance = new ServicesMonitor(); private final ScheduledThreadPoolExecutor periodicTasksExecutor; private static final String PERIODIC_TASK_THREAD_NAME = "services-monitor-periodic-task-%d"; @@ -58,13 +58,19 @@ public class ServicesMonitor { private static final Set serviceNames = Stream.of(ServicesMonitor.ServiceName.values()) .map(ServicesMonitor.ServiceName::toString) .collect(Collectors.toSet()); - + /** * The service monitor maintains a mapping of each service to it's last * status update. */ private final ConcurrentHashMap statusByService; + /** + * Call constructor on start-up so that the first check of services is + * done as soon as possible. + */ + private static ServicesMonitor instance = new ServicesMonitor(); + /** * List of services that are being monitored. The service names should be * representative of the service functionality and readable as they get @@ -130,19 +136,29 @@ public class ServicesMonitor { /** * Updates service status and publishes the service status update if it is - * different from previous status. Logs status changes. + * different from previous status. Event is published locally. Logs status changes. * * @param service Name of the service. * @param status Updated status for the service. + * @param details Details of the event. + * @throws org.sleuthkit.autopsy.core.UnknownServiceException Thrown if either of input parameters is null */ - private synchronized void setServiceStatus(String service, String status) { + public void setServiceStatus(String service, String status, String details) throws UnknownServiceException { - // verify that status has changed + if (service == null) { + throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); + } + + if (status == null || details == null){ + throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullStatusOrDetails.excepton.txt")); + } + + // if the status update is for an existing service who's status hasn't changed - do nothing. if (status.equals(statusByService.get(service))) { return; } - // status has changed + // new service or status has changed if (status.equals(ServiceStatus.UP.toString())) { logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), @@ -155,7 +171,7 @@ public class ServicesMonitor { // update and publish new status statusByService.put(service, status); - publishServiceStatusUpdate(service, status); + eventPublisher.publishLocally(new ServiceEvent(service, status, details)); } /** @@ -185,62 +201,43 @@ public class ServicesMonitor { * @param service Name of the service. * @return String Status for the service. */ - private String checkServiceStatusStatus(String service) { + private String checkServiceStatus(String service) { + try { + if (service.equals(ServiceName.REMOTE_CASE_DATABASE.toString())) { + if (canConnectToRemoteDb()) { + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString(), ""); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString(), ""); + return ServiceStatus.DOWN.toString(); + } + } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())) { + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); + if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString(), ""); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), ""); + return ServiceStatus.DOWN.toString(); + } + } else if (service.equals(ServiceName.MESSAGING.toString())) { + if (canConnectToMessagingService()) { + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString(), ""); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString(), ""); + return ServiceStatus.DOWN.toString(); + } + } - if (service.equals(ServiceName.REMOTE_CASE_DATABASE.toString())) { - if (canConnectToRemoteDb()) { - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString()); - return ServiceStatus.UP.toString(); - } else { - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString()); - return ServiceStatus.DOWN.toString(); - } - } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())) { - KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); - if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString()); - return ServiceStatus.UP.toString(); - } else { - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString()); - return ServiceStatus.DOWN.toString(); - } - } else if (service.equals(ServiceName.MESSAGING.toString())) { - if (canConnectToMessagingService()) { - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString()); - return ServiceStatus.UP.toString(); - } else { - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString()); - return ServiceStatus.DOWN.toString(); - } + // can't check for any other services, treat them as "down" + setServiceStatus(service, ServiceStatus.DOWN.toString(), ""); + } catch (UnknownServiceException ex) { + logger.log(Level.SEVERE, "Exception while checking status of service " + service, ex); //NON-NLS } - - // can't check for any other services, treat them as "down" - setServiceStatus(service, ServiceStatus.DOWN.toString()); return ServiceStatus.DOWN.toString(); } - /** - * Publish an event signifying change in service status. Event is published - * locally. - * - * @param service Name of the service. - * @param status Updated status for the event. - */ - private void publishServiceStatusUpdate(String service, String status) { - eventPublisher.publishLocally(new ServiceEvent(service, status, "")); - } - - /** - * Publish a custom event. Event is published locally. - * - * @param service Name of the service. - * @param status Updated status for the event. - * @param details Details of the event. - */ - public void publishCustomServiceStatus(String service, String status, String details) { - eventPublisher.publishLocally(new ServiceEvent(service, status, details)); - } - /** * Adds an event subscriber to this publisher. Subscriber will be subscribed * to all events from this publisher. @@ -333,7 +330,7 @@ public class ServicesMonitor { */ private void checkAllServices() { for (String serviceName : serviceNames) { - checkServiceStatusStatus(serviceName); + checkServiceStatus(serviceName); } } From ef48080439fade438bfbe994b883a1be5d970e5d Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 16 Jul 2015 09:32:08 -0400 Subject: [PATCH 26/44] UnknownServiceException an inner class of ServicesMonitor --- .../autopsy/core/ServicesMonitor.java | 14 ++++++++ .../autopsy/core/UnknownServiceException.java | 33 ------------------- 2 files changed, 14 insertions(+), 33 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index f62cd0c8fb..322a649a79 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -350,4 +350,18 @@ public class ServicesMonitor { checkAllServices(); } } + + /** + * Exception thrown when service status query results in an error. + */ + public class UnknownServiceException extends Exception { + + public UnknownServiceException(String message) { + super(message); + } + + public UnknownServiceException(String message, Throwable cause) { + super(message, cause); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java b/Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java deleted file mode 100644 index ace8b7aecd..0000000000 --- a/Core/src/org/sleuthkit/autopsy/core/UnknownServiceException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2012 Basis Technology Corp. - * Contact: carrier sleuthkit 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; - -/** - * Exception thrown when service status query results in an error. - */ -public class UnknownServiceException extends Exception { - - public UnknownServiceException(String message) { - super(message); - } - - public UnknownServiceException(String message, Throwable cause) { - super(message, cause); - } -} From ba8dd33a062abb14857cad0dba39a491977ea2d9 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 16 Jul 2015 09:42:05 -0400 Subject: [PATCH 27/44] Added canConnect() method to the MessageServiceConnectionInfo class --- .../autopsy/core/ServicesMonitor.java | 31 ++----------------- .../events/MessageServiceConnectionInfo.java | 20 ++++++++++++ 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 322a649a79..526a1ee274 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -204,7 +204,7 @@ public class ServicesMonitor { private String checkServiceStatus(String service) { try { if (service.equals(ServiceName.REMOTE_CASE_DATABASE.toString())) { - if (canConnectToRemoteDb()) { + if (UserPreferences.getDatabaseConnectionInfo().canConnect()) { setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString(), ""); return ServiceStatus.UP.toString(); } else { @@ -221,7 +221,7 @@ public class ServicesMonitor { return ServiceStatus.DOWN.toString(); } } else if (service.equals(ServiceName.MESSAGING.toString())) { - if (canConnectToMessagingService()) { + if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString(), ""); return ServiceStatus.UP.toString(); } else { @@ -297,33 +297,6 @@ public class ServicesMonitor { public void removeSubscriber(PropertyChangeListener subscriber) { eventPublisher.removeSubscriber(serviceNames, subscriber); } - - /** - * Verifies connection to remote database. - * - * @return True if connection can be established, false otherwise. - */ - private boolean canConnectToRemoteDb() { - return UserPreferences.getDatabaseConnectionInfo().canConnect(); - } - - /** - * Verifies connection to messaging service. - * - * @return True if connection can be established, false otherwise. - */ - private boolean canConnectToMessagingService() { - MessageServiceConnectionInfo msgInfo = UserPreferences.getMessageServiceConnectionInfo(); - try { - ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(msgInfo.getUserName(), msgInfo.getPassword(), msgInfo.getURI()); - Connection connection = connectionFactory.createConnection(); - connection.start(); - connection.close(); - return true; - } catch (URISyntaxException | JMSException ex) { - return false; - } - } /** * Verifies connectivity to all services. diff --git a/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java b/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java index 8bebf16f0d..2e26d3a04c 100644 --- a/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java @@ -21,6 +21,10 @@ package org.sleuthkit.autopsy.events; import java.net.URI; import java.net.URISyntaxException; import javax.annotation.concurrent.Immutable; +import javax.jms.Connection; +import javax.jms.JMSException; +import org.apache.activemq.ActiveMQConnectionFactory; +import org.sleuthkit.autopsy.core.UserPreferences; /** * Connection info for a Java Message Service (JMS) provider. Thread-safe. @@ -99,4 +103,20 @@ public final class MessageServiceConnectionInfo { return new URI(String.format(MESSAGE_SERVICE_URI, host, port)); } + /** + * Verifies connection to messaging service. + * + * @return True if connection can be established, false otherwise. + */ + public boolean canConnect() { + try { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(getUserName(), getPassword(), getURI()); + Connection connection = connectionFactory.createConnection(); + connection.start(); + connection.close(); + return true; + } catch (URISyntaxException | JMSException ex) { + return false; + } + } } From 775b1d9ee669b33a884a1306d8ffa48ce9c50c76 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 16 Jul 2015 09:55:02 -0400 Subject: [PATCH 28/44] Added ability to set display name for services --- .../autopsy/core/ServicesMonitor.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 526a1ee274..2aa3ace63a 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.core; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeListener; -import java.net.URISyntaxException; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -28,16 +27,11 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.jms.Connection; -import javax.jms.JMSException; -import org.apache.activemq.ActiveMQConnectionFactory; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; -import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; /** @@ -82,18 +76,28 @@ public class ServicesMonitor { * Property change event fired when remote case database status changes. * New value is set to updated ServiceStatus, old value is null. */ - REMOTE_CASE_DATABASE, + REMOTE_CASE_DATABASE("Remote Case Database"), /** * Property change event fired when remote keyword search service status * changes. New value is set to updated ServiceStatus, old value is * null. */ - REMOTE_KEYWORD_SEARCH, + REMOTE_KEYWORD_SEARCH("Remote Keyword Search"), /** * Property change event fired when messaging service status changes. * New value is set to updated ServiceStatus, old value is null. */ - MESSAGING + MESSAGING("Messaging Service"); + + private final String displayName; + + private ServiceName(String displayName) { + this.displayName = displayName; + } + + public String getName() { + return displayName; + } }; /** @@ -141,7 +145,7 @@ public class ServicesMonitor { * @param service Name of the service. * @param status Updated status for the service. * @param details Details of the event. - * @throws org.sleuthkit.autopsy.core.UnknownServiceException Thrown if either of input parameters is null + * @throws org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown if either of input parameters is null */ public void setServiceStatus(String service, String status, String details) throws UnknownServiceException { @@ -179,7 +183,7 @@ public class ServicesMonitor { * * @param service Name of the service. * @return ServiceStatus Status for the service. - * @throws org.sleuthkit.autopsy.core.UnknownServiceException + * @throws org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown if service name is null or service doesn't exist. */ public String getServiceStatus(String service) throws UnknownServiceException { @@ -203,29 +207,29 @@ public class ServicesMonitor { */ private String checkServiceStatus(String service) { try { - if (service.equals(ServiceName.REMOTE_CASE_DATABASE.toString())) { + if (service.equals(ServiceName.REMOTE_CASE_DATABASE.getName())) { if (UserPreferences.getDatabaseConnectionInfo().canConnect()) { - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString(), ""); + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.getName(), ServiceStatus.UP.toString(), ""); return ServiceStatus.UP.toString(); } else { - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString(), ""); + setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.getName(), ServiceStatus.DOWN.toString(), ""); return ServiceStatus.DOWN.toString(); } - } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.toString())) { + } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.getName())) { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString(), ""); + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.UP.toString(), ""); return ServiceStatus.UP.toString(); } else { - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), ""); + setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.DOWN.toString(), ""); return ServiceStatus.DOWN.toString(); } - } else if (service.equals(ServiceName.MESSAGING.toString())) { + } else if (service.equals(ServiceName.MESSAGING.getName())) { if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.UP.toString(), ""); + setServiceStatus(ServiceName.MESSAGING.getName(), ServiceStatus.UP.toString(), ""); return ServiceStatus.UP.toString(); } else { - setServiceStatus(ServiceName.MESSAGING.toString(), ServiceStatus.DOWN.toString(), ""); + setServiceStatus(ServiceName.MESSAGING.getName(), ServiceStatus.DOWN.toString(), ""); return ServiceStatus.DOWN.toString(); } } From 39c3c557eb68666e2c11ab006ef5d8be2886a630 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 16 Jul 2015 10:47:00 -0400 Subject: [PATCH 29/44] Bug fixes, using service display names --- .../autopsy/core/ServicesMonitor.java | 91 ++++++++++--------- .../autopsy/ingest/IngestManager.java | 4 +- 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 2aa3ace63a..12f14b4d42 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -49,8 +49,7 @@ public class ServicesMonitor { private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1; private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; - private static final Set serviceNames = Stream.of(ServicesMonitor.ServiceName.values()) - .map(ServicesMonitor.ServiceName::toString) + private static final Set servicesList = Stream.of(ServicesMonitor.Service.values()) .collect(Collectors.toSet()); /** @@ -70,7 +69,7 @@ public class ServicesMonitor { * representative of the service functionality and readable as they get * logged when service outage occurs. */ - public enum ServiceName { + public enum Service { /** * Property change event fired when remote case database status changes. @@ -91,7 +90,7 @@ public class ServicesMonitor { private final String displayName; - private ServiceName(String displayName) { + private Service(String displayName) { this.displayName = displayName; } @@ -194,52 +193,50 @@ public class ServicesMonitor { String status = statusByService.get(service); if (status == null) { // no such service - throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt")); + throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service)); } return status; } /** - * Performs on-demand check of service availability. + * Performs service availability status lookup. * * @param service Name of the service. * @return String Status for the service. + * @throws org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown if no method exists to check service status. */ - private String checkServiceStatus(String service) { - try { - if (service.equals(ServiceName.REMOTE_CASE_DATABASE.getName())) { - if (UserPreferences.getDatabaseConnectionInfo().canConnect()) { - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.getName(), ServiceStatus.UP.toString(), ""); - return ServiceStatus.UP.toString(); - } else { - setServiceStatus(ServiceName.REMOTE_CASE_DATABASE.getName(), ServiceStatus.DOWN.toString(), ""); - return ServiceStatus.DOWN.toString(); - } - } else if (service.equals(ServiceName.REMOTE_KEYWORD_SEARCH.getName())) { - KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); - if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.UP.toString(), ""); - return ServiceStatus.UP.toString(); - } else { - setServiceStatus(ServiceName.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.DOWN.toString(), ""); - return ServiceStatus.DOWN.toString(); - } - } else if (service.equals(ServiceName.MESSAGING.getName())) { - if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { - setServiceStatus(ServiceName.MESSAGING.getName(), ServiceStatus.UP.toString(), ""); - return ServiceStatus.UP.toString(); - } else { - setServiceStatus(ServiceName.MESSAGING.getName(), ServiceStatus.DOWN.toString(), ""); - return ServiceStatus.DOWN.toString(); - } + private String checkServiceStatus(String service) throws UnknownServiceException { + if (service.equals(Service.REMOTE_CASE_DATABASE.getName())) { + if (UserPreferences.getDatabaseConnectionInfo().canConnect()) { + setServiceStatus(Service.REMOTE_CASE_DATABASE.getName(), ServiceStatus.UP.toString(), ""); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(Service.REMOTE_CASE_DATABASE.getName(), ServiceStatus.DOWN.toString(), ""); + return ServiceStatus.DOWN.toString(); + } + } else if (service.equals(Service.REMOTE_KEYWORD_SEARCH.getName())) { + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); + if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.UP.toString(), ""); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.DOWN.toString(), ""); + return ServiceStatus.DOWN.toString(); + } + } else if (service.equals(Service.MESSAGING.getName())) { + if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { + setServiceStatus(Service.MESSAGING.getName(), ServiceStatus.UP.toString(), ""); + return ServiceStatus.UP.toString(); + } else { + setServiceStatus(Service.MESSAGING.getName(), ServiceStatus.DOWN.toString(), ""); + return ServiceStatus.DOWN.toString(); } - - // can't check for any other services, treat them as "down" - setServiceStatus(service, ServiceStatus.DOWN.toString(), ""); - } catch (UnknownServiceException ex) { - logger.log(Level.SEVERE, "Exception while checking status of service " + service, ex); //NON-NLS } - return ServiceStatus.DOWN.toString(); + + // no method to check any other services + setServiceStatus(service, ServiceStatus.DOWN.toString(), ""); + logger.log(Level.SEVERE, "No method exists to check status of service {0}", service); //NON-NLS + throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service)); } /** @@ -249,7 +246,9 @@ public class ServicesMonitor { * @param subscriber The subscriber to add. */ public void addSubscriber(PropertyChangeListener subscriber) { - eventPublisher.addSubscriber(serviceNames, subscriber); + for (Service service : servicesList) { + eventPublisher.addSubscriber(service.getName(), subscriber); + } } /** @@ -299,15 +298,21 @@ public class ServicesMonitor { * @param subscriber The subscriber to remove. */ public void removeSubscriber(PropertyChangeListener subscriber) { - eventPublisher.removeSubscriber(serviceNames, subscriber); + for (Service service : servicesList) { + eventPublisher.removeSubscriber(service.getName(), subscriber); + } } /** * Verifies connectivity to all services. */ private void checkAllServices() { - for (String serviceName : serviceNames) { - checkServiceStatus(serviceName); + for (Service service : servicesList) { + try { + checkServiceStatus(service.getName()); + } catch (UnknownServiceException ex) { + logger.log(Level.SEVERE, "Exception while checking status of service " + service, ex); //NON-NLS + } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 3704e3f5a2..0fc50b53cf 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -354,8 +354,8 @@ public class IngestManager { // subscribe to services of interest Set servicesList = new HashSet<>(); - servicesList.add(ServicesMonitor.ServiceName.REMOTE_CASE_DATABASE.toString()); - servicesList.add(ServicesMonitor.ServiceName.REMOTE_KEYWORD_SEARCH.toString()); + servicesList.add(ServicesMonitor.Service.REMOTE_CASE_DATABASE.getName()); + servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.getName()); this.servicesMonitor.addSubscriber(servicesList, propChangeListener); } From 8b1dc36fa18475e2ca652736b92820425563c8ae Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 16 Jul 2015 10:48:02 -0400 Subject: [PATCH 30/44] Minor fix --- Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 12f14b4d42..f013258565 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -234,7 +234,6 @@ public class ServicesMonitor { } // no method to check any other services - setServiceStatus(service, ServiceStatus.DOWN.toString(), ""); logger.log(Level.SEVERE, "No method exists to check status of service {0}", service); //NON-NLS throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service)); } From dec241a2782c4815ecb4016ffef05dbea8b4ae29 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 17 Jul 2015 09:15:27 -0400 Subject: [PATCH 31/44] Move case opening and closing off the EDT --- .../sleuthkit/autopsy/casemodule/Case.java | 59 +++++++----- .../autopsy/casemodule/CaseCloseAction.java | 23 ++++- .../autopsy/casemodule/CaseOpenAction.java | 56 +++++++++++- .../casemodule/NewCaseWizardAction.java | 87 +++++++++++++++++- .../casemodule/NewCaseWizardPanel2.java | 7 +- .../casemodule/OpenRecentCasePanel.java | 89 +++++++++++++------ .../autopsy/casemodule/RecentItems.java | 44 ++++++++- .../autopsy/corecomponents/Installer.java | 49 +++++++--- 8 files changed, 342 insertions(+), 72 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 1ac03b2859..4bb658d222 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -44,6 +44,7 @@ import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.SystemAction; @@ -523,20 +524,24 @@ public class Case { String dbPath = caseDir + File.separator + "autopsy.db"; //NON-NLS db = SleuthkitCase.openCase(dbPath); if (null != db.getBackupDatabasePath()) { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", - db.getBackupDatabasePath()), - NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), - JOptionPane.INFORMATION_MESSAGE); + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", + db.getBackupDatabasePath()), + NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), + JOptionPane.INFORMATION_MESSAGE); + }); } } else { db = SleuthkitCase.openCase(xmlcm.getDatabaseName(), UserPreferences.getDatabaseConnectionInfo(), caseDir); if (null != db.getBackupDatabasePath()) { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", - db.getBackupDatabasePath()), - NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), - JOptionPane.INFORMATION_MESSAGE); + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", + db.getBackupDatabasePath()), + NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), + JOptionPane.INFORMATION_MESSAGE); + }); } } @@ -786,7 +791,9 @@ public class Case { name = newCaseName; // change the local value RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case eventPublisher.publish(new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName)); - updateMainWindowTitle(newCaseName); + SwingUtilities.invokeLater(() -> { + updateMainWindowTitle(newCaseName); + }); } catch (Exception e) { throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseName.exception.msg"), e); } @@ -1474,25 +1481,35 @@ public class Case { if (toChangeTo.hasData()) { // open all top components - CoreComponentControl.openCoreWindows(); + SwingUtilities.invokeLater(() -> { + CoreComponentControl.openCoreWindows(); + }); } else { // close all top components - CoreComponentControl.closeCoreWindows(); + SwingUtilities.invokeLater(() -> { + CoreComponentControl.closeCoreWindows(); + }); } } if (IngestManager.getInstance().isRunningInteractively()) { - updateMainWindowTitle(currentCase.name); + SwingUtilities.invokeLater(() -> { + updateMainWindowTitle(currentCase.name); + }); } else { - Frame f = WindowManager.getDefault().getMainWindow(); - f.setTitle(Case.getAppName()); // set the window name to just application name + SwingUtilities.invokeLater(() -> { + Frame f = WindowManager.getDefault().getMainWindow(); + f.setTitle(Case.getAppName()); // set the window name to just application name + }); } } else { // case is closed if (IngestManager.getInstance().isRunningInteractively()) { // close all top components first - CoreComponentControl.closeCoreWindows(); - + SwingUtilities.invokeLater(() -> { + CoreComponentControl.closeCoreWindows(); + }); + // disable these menus CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu @@ -1503,8 +1520,10 @@ public class Case { //clear pending notifications MessageNotifyUtil.Notify.clear(); - Frame f = WindowManager.getDefault().getMainWindow(); - f.setTitle(Case.getAppName()); // set the window name to just application name + SwingUtilities.invokeLater(() -> { + Frame f = WindowManager.getDefault().getMainWindow(); + f.setTitle(Case.getAppName()); // set the window name to just application name + }); //try to force gc to happen System.gc(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java index ad0b4cc952..efb5a5ca27 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java @@ -27,6 +27,7 @@ import java.util.logging.Level;import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JButton; +import javax.swing.SwingWorker; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; @@ -70,6 +71,26 @@ import org.openide.util.actions.Presenter; return; } + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + try{ + Case result = Case.getCurrentCase(); + result.closeCase(); + } catch (CaseActionException | IllegalStateException ex){ + Logger.getLogger(CaseCloseAction.class.getName()).log(Level.SEVERE, "Error closing case.", ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + StartupWindowProvider.getInstance().open(); + } + }.execute(); + + /* Case result = Case.getCurrentCase(); try { result.closeCase(); @@ -82,7 +103,7 @@ import org.openide.util.actions.Presenter; public void run() { StartupWindowProvider.getInstance().open(); } - }); + });*/ } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index f767efcf09..fc70b02d7e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -23,9 +23,12 @@ import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JFileChooser; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import org.openide.util.NbBundle; @@ -76,7 +79,7 @@ public final class CaseOpenAction implements ActionListener { int retval = fc.showOpenDialog(WindowManager.getDefault().getMainWindow()); if (retval == JFileChooser.APPROVE_OPTION) { - String path = fc.getSelectedFile().getPath(); + final String path = fc.getSelectedFile().getPath(); String dirPath = fc.getSelectedFile().getParent(); ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator))); // check if the file exists @@ -96,6 +99,55 @@ public final class CaseOpenAction implements ActionListener { // no need to show the error message to the user. logger.log(Level.WARNING, "Error closing startup window.", ex); //NON-NLS } + + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + // Create case. + try{ + Case.open(path); + } catch (CaseActionException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.msg", path, + ex.getMessage()), + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + + + StartupWindowProvider.getInstance().open(); + }); + logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + try { + get(); + } catch (ExecutionException | InterruptedException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.msg", path, + ex.getMessage()), + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + + + StartupWindowProvider.getInstance().open(); + }); + logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS + } + } + }.execute(); + + /* try { Case.open(path); // open the case } catch (CaseActionException ex) { @@ -109,7 +161,7 @@ public final class CaseOpenAction implements ActionListener { logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS StartupWindowProvider.getInstance().open(); - } + }*/ } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index bc9cdea275..a6c9335da3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -24,7 +24,10 @@ import java.awt.Dialog; import java.io.File; import java.text.MessageFormat; import java.util.logging.Level; +import java.util.concurrent.ExecutionException; import javax.swing.JComponent; +import javax.swing.SwingWorker; +import javax.swing.SwingUtilities; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; @@ -81,7 +84,7 @@ import org.sleuthkit.datamodel.TskData.DbType; * The method to perform new case creation */ private void newCaseAction() { - WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); + final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels()); // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName() wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text")); @@ -89,7 +92,73 @@ import org.sleuthkit.datamodel.TskData.DbType; dialog.setVisible(true); dialog.toFront(); + if(wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION){ + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + // Create case. + + String caseNumber = (String) wizardDescriptor.getProperty("caseNumber"); //NON-NLS + String examiner = (String) wizardDescriptor.getProperty("caseExaminer"); //NON-NLS + final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS + String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS + CaseType caseType = CaseType.values()[(int)wizardDescriptor.getProperty("caseType")]; //NON-NLS + + try { + Case.create(createdDirectory, caseName, caseNumber, examiner, caseType); + } catch (Exception ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), + "CaseCreateAction.msgDlg.cantCreateCase.msg")+" "+caseName, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + } + return null; + } + + @Override + protected void done() { + try { + get(); + CaseType currentCaseType = CaseType.values()[(int)wizardDescriptor.getProperty("caseType")]; //NON-NLS + CaseDbConnectionInfo info = UserPreferences.getDatabaseConnectionInfo(); + if ((currentCaseType==CaseType.SINGLE_USER_CASE) || ((info.getDbType() != DbType.SQLITE) && info.canConnect())) { + AddImageAction addImageAction = SystemAction.get(AddImageAction.class); + addImageAction.actionPerformed(null); + } else { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.databaseProblem1.text"), + NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.databaseProblem2.text"), + JOptionPane.ERROR_MESSAGE); + doFailedCaseCleanup(wizardDescriptor); + } + + + } catch (ExecutionException | InterruptedException ex) { + final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), + "CaseCreateAction.msgDlg.cantCreateCase.msg")+" "+caseName, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + doFailedCaseCleanup(wizardDescriptor); + } + } + }.execute(); + + + } else { + new Thread(() -> { + doFailedCaseCleanup(wizardDescriptor); + }).start(); + } + + /* boolean finished = wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION; // check if it finishes (it's not cancelled) boolean isCancelled = wizardDescriptor.getValue() == WizardDescriptor.CANCEL_OPTION; // check if the "Cancel" button is pressed @@ -125,8 +194,22 @@ import org.sleuthkit.datamodel.TskData.DbType; Case.deleteCaseDirectory(new File(createdDirectory)); } } - panels = null; // reset the panel + panels = null; // reset the panel*/ } + + private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor){ + String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS + // if there's case opened, close the case + if (Case.existsCurrentCase()) { + // close the previous case if there's any + CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class); + closeCase.actionPerformed(null); + } + if (createdDirectory != null) { + logger.log(Level.INFO, "Deleting a created case directory due to isCancelled set, dir: " + createdDirectory); //NON-NLS + Case.deleteCaseDirectory(new File(createdDirectory)); + } + } /** * Initialize panels representing individual wizard's steps and sets diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java index 98a972a5af..30a96650f6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java @@ -171,11 +171,14 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel() { + + @Override + protected Void doInBackground() throws Exception { + // Create case. + try{ + Case.open(casePath); + } catch (CaseActionException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.msg", caseName, + ex.getMessage()), + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + try { + get(); + } catch (ExecutionException | InterruptedException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.msg", caseName, + ex.getMessage()), + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS + } + } + }.execute(); } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java index 43de7bbb7f..43ed9cf134 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java @@ -23,9 +23,12 @@ import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; @@ -35,8 +38,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; */ class RecentItems implements ActionListener { - String caseName; - String casePath; + final String caseName; + final String casePath; private JPanel caller; // for error handling /** the constructor */ @@ -76,6 +79,41 @@ class RecentItems implements ActionListener { } } else { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + // Create case. + try{ + Case.open(casePath); + } catch (CaseActionException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.msg", casePath, + ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case at " + casePath, ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + try { + get(); + } catch (ExecutionException | InterruptedException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.msg", casePath, + ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error opening recent case. ", ex); //NON-NLS + } + } + }.execute(); + /* try { Case.open(casePath); // open the case } catch (CaseActionException ex) { @@ -84,7 +122,7 @@ class RecentItems implements ActionListener { ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), JOptionPane.ERROR_MESSAGE); Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case at " + casePath, ex); //NON-NLS - } + }*/ } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index d38e58525e..95c7422f28 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -24,10 +24,12 @@ import java.util.Collection; import java.util.Map; import java.util.TreeMap; import java.util.logging.Level; +import java.util.concurrent.ExecutionException; import javax.swing.BorderFactory; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.SwingWorker; import org.netbeans.spi.sendopts.OptionProcessor; import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.openide.modules.ModuleInstall; @@ -74,13 +76,32 @@ public class Installer extends ModuleInstall { for (OptionProcessor processor : processors) { if (processor instanceof OpenFromArguments) { OpenFromArguments argsProcessor = (OpenFromArguments) processor; - String caseFile = argsProcessor.getDefaultArg(); + final String caseFile = argsProcessor.getDefaultArg(); if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(".aut") && new File(caseFile).exists()) { //NON-NLS - try { - Case.open(caseFile); - return; - } catch (Exception e) { - } + + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + // Create case. + try{ + Case.open(caseFile); + } catch(Exception ex){ + logger.log(Level.WARNING, "Error opening case. ", ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + try { + get(); + } catch (ExecutionException | InterruptedException ex) { + logger.log(Level.WARNING, "Error opening case. ", ex); //NON-NLS + } + } + }.execute(); + return; } } } @@ -99,13 +120,15 @@ public class Installer extends ModuleInstall { @Override public void close() { - try { - if (Case.isCaseOpen()) - Case.getCurrentCase().closeCase(); - } - catch (CaseActionException ex) { - logger.log(Level.WARNING, "Error closing case. ", ex); //NON-NLS - } + new Thread(() -> { + try { + if (Case.isCaseOpen()) + Case.getCurrentCase().closeCase(); + } + catch (CaseActionException | IllegalStateException ex) { + logger.log(Level.WARNING, "Error closing case. ", ex); //NON-NLS + } + }).start(); } private void setupLAF() { From 47124626ff594b6280a1f69be9957ea2dd43dbac Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 17 Jul 2015 12:21:59 -0400 Subject: [PATCH 32/44] Added notes about not calling the Case notification methods from the EDT. --- .../org/sleuthkit/autopsy/casemodule/Case.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 4bb658d222..f2075592ff 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -650,6 +650,8 @@ public class Case { /** * Notifies case event subscribers (property change listeners) that a data * source is being added to the case database. + * + * This should not be called from the event dispatch thread (EDT) * * @param dataSourceId A unique identifier for the data source. This UUID * should be used to call notifyNewDataSource() after the @@ -662,6 +664,8 @@ public class Case { /** * Notifies case event subscribers (property change listeners) that a data * source failed to be added to the case database. + * + * This should not be called from the event dispatch thread (EDT) * * @param dataSourceId A unique identifier for the data source. */ @@ -672,6 +676,8 @@ public class Case { /** * Notifies case event subscribers (property change listeners) that a data * source is being added to the case database. + * + * This should not be called from the event dispatch thread (EDT) * * @param newDataSource New data source added. * @param dataSourceId A unique identifier for the data source. Should be @@ -684,6 +690,8 @@ public class Case { /** * Notifies the UI that a new ContentTag has been added. + * + * This should not be called from the event dispatch thread (EDT) * * @param newTag new ContentTag added */ @@ -693,6 +701,8 @@ public class Case { /** * Notifies the UI that a ContentTag has been deleted. + * + * This should not be called from the event dispatch thread (EDT) * * @param deletedTag ContentTag deleted */ @@ -702,6 +712,8 @@ public class Case { /** * Notifies the UI that a new BlackboardArtifactTag has been added. + * + * This should not be called from the event dispatch thread (EDT) * * @param newTag new BlackboardArtifactTag added */ @@ -710,7 +722,9 @@ public class Case { } /** - * Notifies the UI that a BlackboardArtifactTag has been. + * Notifies the UI that a BlackboardArtifactTag has been deleted. + * + * This should not be called from the event dispatch thread (EDT) * * @param deletedTag BlackboardArtifactTag deleted */ From df362549532368a79b410f48b0234bac3c68df3a Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 17 Jul 2015 12:26:23 -0400 Subject: [PATCH 33/44] Cleanup --- .../autopsy/casemodule/CaseCloseAction.java | 15 -------- .../autopsy/casemodule/CaseOpenAction.java | 16 -------- .../casemodule/NewCaseWizardAction.java | 38 ------------------- .../autopsy/casemodule/RecentItems.java | 10 ----- 4 files changed, 79 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java index efb5a5ca27..702162b987 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java @@ -89,21 +89,6 @@ import org.openide.util.actions.Presenter; StartupWindowProvider.getInstance().open(); } }.execute(); - - /* - Case result = Case.getCurrentCase(); - try { - result.closeCase(); - } catch (Exception ex) { - Logger.getLogger(CaseCloseAction.class.getName()).log(Level.SEVERE, "Error closing case.", ex); //NON-NLS - } - - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - StartupWindowProvider.getInstance().open(); - } - });*/ } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index fc70b02d7e..83eb3cbd8a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -146,22 +146,6 @@ public final class CaseOpenAction implements ActionListener { } } }.execute(); - - /* - try { - Case.open(path); // open the case - } catch (CaseActionException ex) { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.msg", path, - ex.getMessage()), - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS - - StartupWindowProvider.getInstance().open(); - }*/ } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index a6c9335da3..ebc5b2835f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -157,44 +157,6 @@ import org.sleuthkit.datamodel.TskData.DbType; doFailedCaseCleanup(wizardDescriptor); }).start(); } - - /* - boolean finished = wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION; // check if it finishes (it's not cancelled) - boolean isCancelled = wizardDescriptor.getValue() == WizardDescriptor.CANCEL_OPTION; // check if the "Cancel" button is pressed - - // if the finish button is pressed (not cancelled) - if (finished) { - // now start the 'Add Image' wizard - //TODO fix for local - CaseType currentCaseType = CaseType.fromString(ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, ModuleSettings.CURRENT_CASE_TYPE)); - CaseDbConnectionInfo info = UserPreferences.getDatabaseConnectionInfo(); - if ((currentCaseType==CaseType.SINGLE_USER_CASE) || ((info.getDbType() != DbType.SQLITE) && info.canConnect())) { - AddImageAction addImageAction = SystemAction.get(AddImageAction.class); - addImageAction.actionPerformed(null); - } else { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.databaseProblem1.text"), - NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.databaseProblem2.text"), - JOptionPane.ERROR_MESSAGE); - isCancelled = true; - } - } - - // if Cancel button is pressed - if (isCancelled) { - String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS - // if there's case opened, close the case - if (Case.existsCurrentCase()) { - // close the previous case if there's any - CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class); - closeCase.actionPerformed(null); - } - if (createdDirectory != null) { - logger.log(Level.INFO, "Deleting a created case directory due to isCancelled set, dir: " + createdDirectory); //NON-NLS - Case.deleteCaseDirectory(new File(createdDirectory)); - } - } - panels = null; // reset the panel*/ } private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor){ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java index 43ed9cf134..fcee2450ec 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java @@ -113,16 +113,6 @@ class RecentItems implements ActionListener { } } }.execute(); - /* - try { - Case.open(casePath); // open the case - } catch (CaseActionException ex) { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.msg", casePath, - ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case at " + casePath, ex); //NON-NLS - }*/ } } } From 42ef9c5a8b625f3152abef7a80bc6e44b1d9a67a Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 17 Jul 2015 13:47:42 -0400 Subject: [PATCH 34/44] Cleanup --- .../casemodule/NewCaseWizardPanel2.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java index 30a96650f6..f3edbe0370 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel2.java @@ -178,29 +178,5 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel Date: Mon, 20 Jul 2015 10:13:33 -0400 Subject: [PATCH 35/44] Made setServiceStatus private again --- .../autopsy/core/ServicesMonitor.java | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index f013258565..8cbc3d3dce 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -144,17 +144,8 @@ public class ServicesMonitor { * @param service Name of the service. * @param status Updated status for the service. * @param details Details of the event. - * @throws org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown if either of input parameters is null */ - public void setServiceStatus(String service, String status, String details) throws UnknownServiceException { - - if (service == null) { - throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); - } - - if (status == null || details == null){ - throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullStatusOrDetails.excepton.txt")); - } + private void setServiceStatus(String service, String status, String details) { // if the status update is for an existing service who's status hasn't changed - do nothing. if (status.equals(statusByService.get(service))) { @@ -199,43 +190,41 @@ public class ServicesMonitor { } /** - * Performs service availability status lookup. + * Performs service availability status check. * * @param service Name of the service. - * @return String Status for the service. - * @throws org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown if no method exists to check service status. */ - private String checkServiceStatus(String service) throws UnknownServiceException { + private void checkServiceStatus(String service) { if (service.equals(Service.REMOTE_CASE_DATABASE.getName())) { if (UserPreferences.getDatabaseConnectionInfo().canConnect()) { setServiceStatus(Service.REMOTE_CASE_DATABASE.getName(), ServiceStatus.UP.toString(), ""); - return ServiceStatus.UP.toString(); + return; } else { setServiceStatus(Service.REMOTE_CASE_DATABASE.getName(), ServiceStatus.DOWN.toString(), ""); - return ServiceStatus.DOWN.toString(); + return; } } else if (service.equals(Service.REMOTE_KEYWORD_SEARCH.getName())) { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.UP.toString(), ""); - return ServiceStatus.UP.toString(); + return; } else { setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.DOWN.toString(), ""); - return ServiceStatus.DOWN.toString(); + return; } } else if (service.equals(Service.MESSAGING.getName())) { if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { setServiceStatus(Service.MESSAGING.getName(), ServiceStatus.UP.toString(), ""); - return ServiceStatus.UP.toString(); + return; } else { setServiceStatus(Service.MESSAGING.getName(), ServiceStatus.DOWN.toString(), ""); - return ServiceStatus.DOWN.toString(); + return; } } // no method to check any other services logger.log(Level.SEVERE, "No method exists to check status of service {0}", service); //NON-NLS - throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service)); + setServiceStatus(service, ServiceStatus.DOWN.toString(), ""); } /** @@ -307,11 +296,7 @@ public class ServicesMonitor { */ private void checkAllServices() { for (Service service : servicesList) { - try { - checkServiceStatus(service.getName()); - } catch (UnknownServiceException ex) { - logger.log(Level.SEVERE, "Exception while checking status of service " + service, ex); //NON-NLS - } + checkServiceStatus(service.getName()); } } From 1637b75ca8aa285a898ddac8a19aac23fed6bd67 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 20 Jul 2015 10:15:30 -0400 Subject: [PATCH 36/44] Getter Service.getName() matches property name --- Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 8cbc3d3dce..30af422335 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -88,14 +88,14 @@ public class ServicesMonitor { */ MESSAGING("Messaging Service"); - private final String displayName; + private final String serviceName; private Service(String displayName) { - this.displayName = displayName; + this.serviceName = displayName; } public String getName() { - return displayName; + return serviceName; } }; From a2ef14a82f5dcc455b8a9b7617892da4ec7890c8 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 20 Jul 2015 11:14:00 -0400 Subject: [PATCH 37/44] Minor fixes for EDT changes. --- .../sleuthkit/autopsy/casemodule/Case.java | 51 ++++++++++----- .../autopsy/casemodule/CaseOpenAction.java | 62 ++++++------------- .../casemodule/NewCaseWizardAction.java | 23 ++----- .../casemodule/OpenRecentCasePanel.java | 57 +++++------------ .../autopsy/casemodule/RecentItems.java | 48 +++++--------- .../autopsy/corecomponents/Installer.java | 28 +++------ 6 files changed, 94 insertions(+), 175 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index f2075592ff..f3d037bd0c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -329,7 +329,9 @@ public class Case { currentCase = newCase; Logger.setLogDirectory(currentCase.getLogDirectoryPath()); doCaseChange(currentCase); - RecentCases.getInstance().addRecentCase(currentCase.name, currentCase.configFilePath); // update the recent cases + SwingUtilities.invokeLater(() -> { + RecentCases.getInstance().addRecentCase(currentCase.name, currentCase.configFilePath); // update the recent cases + }); if (CaseType.MULTI_USER_CASE == newCase.getCaseType()) { try { /** @@ -793,6 +795,8 @@ public class Case { /** * Updates the case name. + * + * This should not be called from the EDT. * * @param oldCaseName the old case name that wants to be updated * @param oldPath the old path that wants to be updated @@ -803,10 +807,14 @@ public class Case { try { xmlcm.setCaseName(newCaseName); // set the case name = newCaseName; // change the local value - RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case eventPublisher.publish(new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName)); SwingUtilities.invokeLater(() -> { - updateMainWindowTitle(newCaseName); + try{ + RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case + updateMainWindowTitle(newCaseName); + } catch (Exception e) { + Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", e); //NON-NLS + } }); } catch (Exception e) { throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseName.exception.msg"), e); @@ -815,6 +823,8 @@ public class Case { /** * Updates the case examiner + * + * This should not be called from the EDT. * * @param oldExaminer the old examiner * @param newExaminer the new examiner @@ -831,6 +841,8 @@ public class Case { /** * Updates the case number + * + * This should not be called from the EDT. * * @param oldCaseNumber the old case number * @param newCaseNumber the new case number @@ -1488,10 +1500,12 @@ public class Case { if (IngestManager.getInstance().isRunningInteractively()) { // enable these menus - CallableSystemAction.get(AddImageAction.class).setEnabled(true); - CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); - CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true); - CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu + SwingUtilities.invokeLater(() -> { + CallableSystemAction.get(AddImageAction.class).setEnabled(true); + CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); + CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true); + CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu + }); if (toChangeTo.hasData()) { // open all top components @@ -1519,20 +1533,23 @@ public class Case { } else { // case is closed if (IngestManager.getInstance().isRunningInteractively()) { - // close all top components first - SwingUtilities.invokeLater(() -> { - CoreComponentControl.closeCoreWindows(); - }); - // disable these menus - CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu - CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu - CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu - CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu + SwingUtilities.invokeLater(() -> { + // close all top components first + CoreComponentControl.closeCoreWindows(); + + // disable these menus + CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu + CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu + CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu + CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu + }); } //clear pending notifications - MessageNotifyUtil.Notify.clear(); + SwingUtilities.invokeLater(() -> { + MessageNotifyUtil.Notify.clear(); + }); SwingUtilities.invokeLater(() -> { Frame f = WindowManager.getDefault().getMainWindow(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java index 83eb3cbd8a..5bae094395 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java @@ -100,52 +100,26 @@ public final class CaseOpenAction implements ActionListener { logger.log(Level.WARNING, "Error closing startup window.", ex); //NON-NLS } - new SwingWorker() { + new Thread(() -> { + // Create case. + try{ + Case.open(path); + } catch (CaseActionException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.msg", path, + ex.getMessage()), + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); - @Override - protected Void doInBackground() throws Exception { - // Create case. - try{ - Case.open(path); - } catch (CaseActionException ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.msg", path, - ex.getMessage()), - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - - StartupWindowProvider.getInstance().open(); - }); - logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS - } - return null; - } - - @Override - protected void done() { - try { - get(); - } catch (ExecutionException | InterruptedException ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.msg", path, - ex.getMessage()), - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - - - StartupWindowProvider.getInstance().open(); - }); - logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS - } - } - }.execute(); + StartupWindowProvider.getInstance().open(); + }); + logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS + } + }).start(); } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index ebc5b2835f..aad75a51c0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -105,17 +105,7 @@ import org.sleuthkit.datamodel.TskData.DbType; String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS CaseType caseType = CaseType.values()[(int)wizardDescriptor.getProperty("caseType")]; //NON-NLS - try { - Case.create(createdDirectory, caseName, caseNumber, examiner, caseType); - } catch (Exception ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), - "CaseCreateAction.msgDlg.cantCreateCase.msg")+" "+caseName, - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - }); - } + Case.create(createdDirectory, caseName, caseNumber, examiner, caseType); return null; } @@ -137,7 +127,7 @@ import org.sleuthkit.datamodel.TskData.DbType; } - } catch (ExecutionException | InterruptedException ex) { + } catch (Exception ex) { final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), @@ -161,14 +151,9 @@ import org.sleuthkit.datamodel.TskData.DbType; private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor){ String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS - // if there's case opened, close the case - if (Case.existsCurrentCase()) { - // close the previous case if there's any - CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class); - closeCase.actionPerformed(null); - } + if (createdDirectory != null) { - logger.log(Level.INFO, "Deleting a created case directory due to isCancelled set, dir: " + createdDirectory); //NON-NLS + logger.log(Level.INFO, "Deleting a created case directory due to an error, dir: " + createdDirectory); //NON-NLS Case.deleteCaseDirectory(new File(createdDirectory)); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java index 8e29e4ea40..aafbdc31ef 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java @@ -217,46 +217,23 @@ class OpenRecentCasePanel extends javax.swing.JPanel { } } else { - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - // Create case. - try{ - Case.open(casePath); - } catch (CaseActionException ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.msg", caseName, - ex.getMessage()), - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - }); - logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS - } - return null; - } - - @Override - protected void done() { - try { - get(); - } catch (ExecutionException | InterruptedException ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.msg", caseName, - ex.getMessage()), - NbBundle.getMessage(this.getClass(), - "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - }); - logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS - } - } - }.execute(); + new Thread(() -> { + // Create case. + try{ + Case.open(casePath); + } catch (CaseActionException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.msg", caseName, + ex.getMessage()), + NbBundle.getMessage(this.getClass(), + "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS + } + }).start(); } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java index fcee2450ec..763dfe59d2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java @@ -79,40 +79,20 @@ class RecentItems implements ActionListener { } } else { - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - // Create case. - try{ - Case.open(casePath); - } catch (CaseActionException ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.msg", casePath, - ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - }); - Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case at " + casePath, ex); //NON-NLS - } - return null; - } - - @Override - protected void done() { - try { - get(); - } catch (ExecutionException | InterruptedException ex) { - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.msg", casePath, - ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), - JOptionPane.ERROR_MESSAGE); - }); - Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error opening recent case. ", ex); //NON-NLS - } - } - }.execute(); + new Thread(() -> { + // Create case. + try{ + Case.open(casePath); + } catch (CaseActionException ex) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.msg", casePath, + ex.getMessage()), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), + JOptionPane.ERROR_MESSAGE); + }); + Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case at " + casePath, ex); //NON-NLS + } + }).start(); } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java index 95c7422f28..14da528efc 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java @@ -79,28 +79,14 @@ public class Installer extends ModuleInstall { final String caseFile = argsProcessor.getDefaultArg(); if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(".aut") && new File(caseFile).exists()) { //NON-NLS - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - // Create case. - try{ - Case.open(caseFile); - } catch(Exception ex){ - logger.log(Level.WARNING, "Error opening case. ", ex); //NON-NLS - } - return null; + new Thread(() -> { + // Create case. + try{ + Case.open(caseFile); + } catch(Exception ex){ + logger.log(Level.WARNING, "Error opening case. ", ex); //NON-NLS } - - @Override - protected void done() { - try { - get(); - } catch (ExecutionException | InterruptedException ex) { - logger.log(Level.WARNING, "Error opening case. ", ex); //NON-NLS - } - } - }.execute(); + }).start(); return; } } From 2d4b7899202b7a6cfc5f3bbcf9ca4bb146731e31 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 20 Jul 2015 11:35:30 -0400 Subject: [PATCH 38/44] Renamed services, added popup message for custom service status changes --- .../sleuthkit/autopsy/core/Bundle.properties | 2 + .../autopsy/core/ServicesMonitor.java | 46 +++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index 44d90ee138..986f0d4f3d 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -16,6 +16,8 @@ ServicesMonitor.failedService.notify.title=Collaboration Service Failed ServicesMonitor.failedService.notify.msg=Lost connection to {0} ServicesMonitor.restoredService.notify.title=Collaboration Service Restored ServicesMonitor.restoredService.notify.msg=Connection to {0} restored +ServicesMonitor.statusChange.notify.title=Collaboration Service Status Change +ServicesMonitor.statusChange.notify.msg=Status for {0} changed to {1} ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null ServicesMonitor.nullStatusOrDetails.excepton.txt=Status or details string is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 30af422335..cd72ac087b 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -51,7 +51,7 @@ public class ServicesMonitor { private static final Set servicesList = Stream.of(ServicesMonitor.Service.values()) .collect(Collectors.toSet()); - + /** * The service monitor maintains a mapping of each service to it's last * status update. @@ -59,11 +59,11 @@ public class ServicesMonitor { private final ConcurrentHashMap statusByService; /** - * Call constructor on start-up so that the first check of services is - * done as soon as possible. + * Call constructor on start-up so that the first check of services is done + * as soon as possible. */ private static ServicesMonitor instance = new ServicesMonitor(); - + /** * List of services that are being monitored. The service names should be * representative of the service functionality and readable as they get @@ -72,31 +72,32 @@ public class ServicesMonitor { public enum Service { /** - * Property change event fired when remote case database status changes. - * New value is set to updated ServiceStatus, old value is null. + * Property change event fired when remote case database service status + * changes. New value is set to updated ServiceStatus, old value is + * null. */ - REMOTE_CASE_DATABASE("Remote Case Database"), + REMOTE_CASE_DATABASE("multi-user case database service"), /** * Property change event fired when remote keyword search service status * changes. New value is set to updated ServiceStatus, old value is * null. */ - REMOTE_KEYWORD_SEARCH("Remote Keyword Search"), + REMOTE_KEYWORD_SEARCH("multi-user keyword search service"), /** * Property change event fired when messaging service status changes. * New value is set to updated ServiceStatus, old value is null. */ - MESSAGING("Messaging Service"); - + MESSAGING("messaging service"); + private final String serviceName; - private Service(String displayName) { - this.serviceName = displayName; + private Service(String name) { + this.serviceName = name; } public String getName() { return serviceName; - } + } }; /** @@ -125,7 +126,7 @@ public class ServicesMonitor { this.eventPublisher = new AutopsyEventPublisher(); this.statusByService = new ConcurrentHashMap<>(); - + // First check is triggered immediately on current thread. checkAllServices(); @@ -139,15 +140,16 @@ public class ServicesMonitor { /** * Updates service status and publishes the service status update if it is - * different from previous status. Event is published locally. Logs status changes. + * different from previous status. Event is published locally. Logs status + * changes. * * @param service Name of the service. * @param status Updated status for the service. * @param details Details of the event. */ private void setServiceStatus(String service, String status, String details) { - - // if the status update is for an existing service who's status hasn't changed - do nothing. + + // if the status update is for an existing service who's status hasn't changed - do nothing. if (status.equals(statusByService.get(service))) { return; } @@ -161,6 +163,10 @@ public class ServicesMonitor { logger.log(Level.SEVERE, "Failed to connect to {0}", service); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg", service)); + } else { + logger.log(Level.INFO, "Connection status for {0} changed to {1}", new Object[]{service, status}); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.title"), + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.msg", new Object[]{service, status})); } // update and publish new status @@ -173,7 +179,9 @@ public class ServicesMonitor { * * @param service Name of the service. * @return ServiceStatus Status for the service. - * @throws org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown if service name is null or service doesn't exist. + * @throws + * org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown + * if service name is null or service doesn't exist. */ public String getServiceStatus(String service) throws UnknownServiceException { @@ -290,7 +298,7 @@ public class ServicesMonitor { eventPublisher.removeSubscriber(service.getName(), subscriber); } } - + /** * Verifies connectivity to all services. */ From 67523bcdf6a3dcb2281f5275ce2430e2eed1bfe4 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 20 Jul 2015 13:12:40 -0400 Subject: [PATCH 39/44] Moved ServiceMonitor to separate package --- Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java | 1 + .../org/sleuthkit/autopsy/core/{ => events}/ServiceEvent.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename Core/src/org/sleuthkit/autopsy/core/{ => events}/ServiceEvent.java (97%) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index cd72ac087b..dafd001972 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.core; +import org.sleuthkit.autopsy.core.events.ServiceEvent; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeListener; import java.util.Set; diff --git a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java b/Core/src/org/sleuthkit/autopsy/core/events/ServiceEvent.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java rename to Core/src/org/sleuthkit/autopsy/core/events/ServiceEvent.java index e1ed6f75ff..057d9cd563 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServiceEvent.java +++ b/Core/src/org/sleuthkit/autopsy/core/events/ServiceEvent.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.core; +package org.sleuthkit.autopsy.core.events; import java.io.Serializable; import org.sleuthkit.autopsy.events.AutopsyEvent; From 87d71870aa47ff4c3c31d5ab5f554a30a535b82d Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 20 Jul 2015 15:54:51 -0400 Subject: [PATCH 40/44] setServiceStatus() is public again, changes based on review --- .../sleuthkit/autopsy/core/Bundle.properties | 8 +- .../autopsy/core/ServicesMonitor.java | 123 +++++++++++------- .../autopsy/ingest/IngestManager.java | 27 ++-- 3 files changed, 98 insertions(+), 60 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index 986f0d4f3d..8d0d3087ce 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -12,12 +12,12 @@ org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xm Services/AutoupdateType/org_sleuthkit_autopsy_core_update_center.settings=Autopsy Update Center Installer.errorInitJavafx.msg=Error initializing JavaFX. Installer.errorInitJavafx.details=\ Some features will not be available. Check that you have the right JRE installed (Oracle JRE > 1.7.10). -ServicesMonitor.failedService.notify.title=Collaboration Service Failed +ServicesMonitor.failedService.notify.title=Service Failed ServicesMonitor.failedService.notify.msg=Lost connection to {0} -ServicesMonitor.restoredService.notify.title=Collaboration Service Restored +ServicesMonitor.restoredService.notify.title=Service Restored ServicesMonitor.restoredService.notify.msg=Connection to {0} restored -ServicesMonitor.statusChange.notify.title=Collaboration Service Status Change -ServicesMonitor.statusChange.notify.msg=Status for {0} changed to {1} +ServicesMonitor.statusChange.notify.title=Service Status Update +ServicesMonitor.statusChange.notify.msg=Status for {0} is {1} ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null ServicesMonitor.nullStatusOrDetails.excepton.txt=Status or details string is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index dafd001972..a61522d617 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -50,7 +50,8 @@ public class ServicesMonitor { private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1; private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; - private static final Set servicesList = Stream.of(ServicesMonitor.Service.values()) + private static final Set servicesList = Stream.of(ServicesMonitor.Service.values()) + .map(Service::toString) .collect(Collectors.toSet()); /** @@ -90,14 +91,14 @@ public class ServicesMonitor { */ MESSAGING("messaging service"); - private final String serviceName; + private final String displayName; private Service(String name) { - this.serviceName = name; + this.displayName = name; } - public String getName() { - return serviceName; + public String getDisplayName() { + return displayName; } }; @@ -147,11 +148,24 @@ public class ServicesMonitor { * @param service Name of the service. * @param status Updated status for the service. * @param details Details of the event. + * @throws + * org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException + * Thrown if either of input parameters is null. */ - private void setServiceStatus(String service, String status, String details) { + public void setServiceStatus(String service, String status, String details) throws ServicesMonitorException { + + if (service == null) { + logger.log(Level.SEVERE, "Call to setServiceStatus() with null service name"); //NON-NLS + throw new ServicesMonitorException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); + } + + if (status == null || details == null) { + logger.log(Level.SEVERE, "Call to setServiceStatus() with null status or details"); //NON-NLS + throw new ServicesMonitorException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullStatusOrDetails.excepton.txt")); + } // if the status update is for an existing service who's status hasn't changed - do nothing. - if (status.equals(statusByService.get(service))) { + if (statusByService.containsKey(service) && status.equals(statusByService.get(service))) { return; } @@ -165,7 +179,7 @@ public class ServicesMonitor { MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg", service)); } else { - logger.log(Level.INFO, "Connection status for {0} changed to {1}", new Object[]{service, status}); //NON-NLS + logger.log(Level.INFO, "Status for {0} is {1}", new Object[]{service, status}); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.title"), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.msg", new Object[]{service, status})); } @@ -181,19 +195,19 @@ public class ServicesMonitor { * @param service Name of the service. * @return ServiceStatus Status for the service. * @throws - * org.sleuthkit.autopsy.core.ServicesMonitor.UnknownServiceException Thrown - * if service name is null or service doesn't exist. + * org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException + * Thrown if service name is null or service doesn't exist. */ - public String getServiceStatus(String service) throws UnknownServiceException { + public String getServiceStatus(String service) throws ServicesMonitorException { if (service == null) { - throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); + throw new ServicesMonitorException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt")); } String status = statusByService.get(service); if (status == null) { // no such service - throw new UnknownServiceException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service)); + throw new ServicesMonitorException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service)); } return status; } @@ -204,36 +218,59 @@ public class ServicesMonitor { * @param service Name of the service. */ private void checkServiceStatus(String service) { - if (service.equals(Service.REMOTE_CASE_DATABASE.getName())) { + if (service.equals(Service.REMOTE_CASE_DATABASE.toString())) { + checkDatabaseConnectionStatus(); + } else if (service.equals(Service.REMOTE_KEYWORD_SEARCH.toString())) { + checkKeywordSearchServerConnectionStatus(); + } else if (service.equals(Service.MESSAGING.toString())) { + checkMessagingServerConnectionStatus(); + } + } + + /** + * Performs case database service availability status check. + */ + private void checkDatabaseConnectionStatus() { + try { if (UserPreferences.getDatabaseConnectionInfo().canConnect()) { - setServiceStatus(Service.REMOTE_CASE_DATABASE.getName(), ServiceStatus.UP.toString(), ""); - return; + setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString(), ""); } else { - setServiceStatus(Service.REMOTE_CASE_DATABASE.getName(), ServiceStatus.DOWN.toString(), ""); - return; + setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString(), ""); } - } else if (service.equals(Service.REMOTE_KEYWORD_SEARCH.getName())) { + } catch (ServicesMonitorException ex) { + logger.log(Level.SEVERE, "Exception while checking database connection status", ex); //NON-NLS + } + } + + /** + * Performs keyword search service availability status check. + */ + private void checkKeywordSearchServerConnectionStatus() { + try { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); if (kwsService != null && kwsService.canConnectToRemoteSolrServer()) { - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.UP.toString(), ""); - return; + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString(), ""); } else { - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.getName(), ServiceStatus.DOWN.toString(), ""); - return; - } - } else if (service.equals(Service.MESSAGING.getName())) { - if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { - setServiceStatus(Service.MESSAGING.getName(), ServiceStatus.UP.toString(), ""); - return; - } else { - setServiceStatus(Service.MESSAGING.getName(), ServiceStatus.DOWN.toString(), ""); - return; + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), ""); } + } catch (ServicesMonitorException ex) { + logger.log(Level.SEVERE, "Exception while checking keyword search server connection status", ex); //NON-NLS } + } - // no method to check any other services - logger.log(Level.SEVERE, "No method exists to check status of service {0}", service); //NON-NLS - setServiceStatus(service, ServiceStatus.DOWN.toString(), ""); + /** + * Performs messaging service availability status check. + */ + private void checkMessagingServerConnectionStatus() { + try { + if (UserPreferences.getMessageServiceConnectionInfo().canConnect()) { + setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.UP.toString(), ""); + } else { + setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString(), ""); + } + } catch (ServicesMonitorException ex) { + logger.log(Level.SEVERE, "Exception while checking messaging server connection status", ex); //NON-NLS + } } /** @@ -243,9 +280,7 @@ public class ServicesMonitor { * @param subscriber The subscriber to add. */ public void addSubscriber(PropertyChangeListener subscriber) { - for (Service service : servicesList) { - eventPublisher.addSubscriber(service.getName(), subscriber); - } + eventPublisher.addSubscriber(servicesList, subscriber); } /** @@ -295,17 +330,15 @@ public class ServicesMonitor { * @param subscriber The subscriber to remove. */ public void removeSubscriber(PropertyChangeListener subscriber) { - for (Service service : servicesList) { - eventPublisher.removeSubscriber(service.getName(), subscriber); - } + eventPublisher.removeSubscriber(servicesList, subscriber); } /** * Verifies connectivity to all services. */ private void checkAllServices() { - for (Service service : servicesList) { - checkServiceStatus(service.getName()); + for (String service : servicesList) { + checkServiceStatus(service); } } @@ -329,13 +362,13 @@ public class ServicesMonitor { /** * Exception thrown when service status query results in an error. */ - public class UnknownServiceException extends Exception { + public class ServicesMonitorException extends Exception { - public UnknownServiceException(String message) { + public ServicesMonitorException(String message) { super(message); } - public UnknownServiceException(String message, Throwable cause) { + public ServicesMonitorException(String message, Throwable cause) { super(message, cause); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 0fc50b53cf..c21920c7c2 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -335,27 +335,32 @@ public class IngestManager { public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue().equals(ServicesMonitor.ServiceStatus.DOWN.toString())) { // one of the services we subscribed to went down - String serviceName = evt.getPropertyName(); - logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceName); //NON-NLS + String serviceDisplayName = ServicesMonitor.Service.valueOf(evt.getPropertyName()).getDisplayName(); + logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceDisplayName); //NON-NLS // display notification if running interactively - if (isIngestRunning() && isRunningInteractively()){ - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "IngestManager.cancellingIngest.msgDlg.text"), - NbBundle.getMessage(this.getClass(), "IngestManager.serviceIsDown.msgDlg.text", serviceName), - JOptionPane.ERROR_MESSAGE); + if (isIngestRunning() && isRunningInteractively()) { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "IngestManager.cancellingIngest.msgDlg.text"), + NbBundle.getMessage(this.getClass(), "IngestManager.serviceIsDown.msgDlg.text", serviceDisplayName), + JOptionPane.ERROR_MESSAGE); + } + }); } - + // cancel ingest if running cancelAllIngestJobs(); } } }; - + // subscribe to services of interest Set servicesList = new HashSet<>(); - servicesList.add(ServicesMonitor.Service.REMOTE_CASE_DATABASE.getName()); - servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.getName()); + servicesList.add(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()); + servicesList.add(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString()); this.servicesMonitor.addSubscriber(servicesList, propChangeListener); } From bbb42447f2236854511cfe83e62c16ab2304de8f Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 20 Jul 2015 16:21:53 -0400 Subject: [PATCH 41/44] Using service display name for UI notifications --- .../autopsy/core/ServicesMonitor.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index a61522d617..b02cfbea3c 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -169,19 +169,27 @@ public class ServicesMonitor { return; } - // new service or status has changed + // new service or status has changed - identify service's display name + String serviceDisplayName; + try { + serviceDisplayName = ServicesMonitor.Service.valueOf(service).getDisplayName(); + } catch (IllegalArgumentException ignore) { + // custom service that is not listed in ServicesMonitor.Service enum. Use service name as display name. + serviceDisplayName = service; + } + if (status.equals(ServiceStatus.UP.toString())) { - logger.log(Level.INFO, "Connection to {0} restored", service); //NON-NLS + logger.log(Level.INFO, "Connection to {0} restored", serviceDisplayName); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"), - NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg", service)); + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg", serviceDisplayName)); } else if (status.equals(ServiceStatus.DOWN.toString())) { - logger.log(Level.SEVERE, "Failed to connect to {0}", service); //NON-NLS + logger.log(Level.SEVERE, "Failed to connect to {0}", serviceDisplayName); //NON-NLS MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"), - NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg", service)); + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg", serviceDisplayName)); } else { - logger.log(Level.INFO, "Status for {0} is {1}", new Object[]{service, status}); //NON-NLS + logger.log(Level.INFO, "Status for {0} is {1}", new Object[]{serviceDisplayName, status}); //NON-NLS MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.title"), - NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.msg", new Object[]{service, status})); + NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.msg", new Object[]{serviceDisplayName, status})); } // update and publish new status @@ -336,7 +344,7 @@ public class ServicesMonitor { /** * Verifies connectivity to all services. */ - private void checkAllServices() { + private void checkAllServices() { for (String service : servicesList) { checkServiceStatus(service); } From f17853daa0407586d6f699d92bff7a11a0a5dfd9 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 20 Jul 2015 16:47:04 -0400 Subject: [PATCH 42/44] Display changes --- Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index b82d4bb4d3..9cf8cdc91c 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -104,4 +104,4 @@ IngestJobSettingsPanel.jButtonDeselectAll.text=Deselect All IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=Processes unallocated space, such as deleted files. Produces more complete results, but it may take longer to process on large images. IngestJobSettingsPanel.processUnallocCheckbox.text=Process Unallocated Space IngestManager.cancellingIngest.msgDlg.text=Cancelling all currently running ingest jobs -IngestManager.serviceIsDown.msgDlg.text=Service {0} is down +IngestManager.serviceIsDown.msgDlg.text={0} is down From 818edd6212843d82800980b47f080ed4adff9a78 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 21 Jul 2015 11:49:41 -0400 Subject: [PATCH 43/44] Only cancel ingest for single user cases, additional settings checks for KWS --- .../org/sleuthkit/autopsy/core/ServicesMonitor.java | 12 ++++++------ .../org/sleuthkit/autopsy/ingest/IngestManager.java | 11 +++++++++++ .../autopsy/keywordsearch/SolrSearchService.java | 11 +++++++++-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index b02cfbea3c..9fb7389fb5 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -78,18 +78,18 @@ public class ServicesMonitor { * changes. New value is set to updated ServiceStatus, old value is * null. */ - REMOTE_CASE_DATABASE("multi-user case database service"), + REMOTE_CASE_DATABASE("Multi-user case database service"), /** * Property change event fired when remote keyword search service status * changes. New value is set to updated ServiceStatus, old value is * null. */ - REMOTE_KEYWORD_SEARCH("multi-user keyword search service"), + REMOTE_KEYWORD_SEARCH("Multi-user keyword search service"), /** * Property change event fired when messaging service status changes. * New value is set to updated ServiceStatus, old value is null. */ - MESSAGING("messaging service"); + MESSAGING("Messaging service"); private final String displayName; @@ -245,7 +245,7 @@ public class ServicesMonitor { } else { setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString(), ""); } - } catch (ServicesMonitorException ex) { + } catch (Exception ex) { logger.log(Level.SEVERE, "Exception while checking database connection status", ex); //NON-NLS } } @@ -261,7 +261,7 @@ public class ServicesMonitor { } else { setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), ""); } - } catch (ServicesMonitorException ex) { + } catch (Exception ex) { logger.log(Level.SEVERE, "Exception while checking keyword search server connection status", ex); //NON-NLS } } @@ -276,7 +276,7 @@ public class ServicesMonitor { } else { setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString(), ""); } - } catch (ServicesMonitorException ex) { + } catch (Exception ex) { logger.log(Level.SEVERE, "Exception while checking messaging server connection status", ex); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index c21920c7c2..68d8863b17 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -334,6 +334,17 @@ public class IngestManager { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue().equals(ServicesMonitor.ServiceStatus.DOWN.toString())) { + + // check whether a milti-user case is currently being processed + try { + if (!Case.isCaseOpen() || Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) { + return; + } + } catch (IllegalStateException ignore) { + // thorown by Case.getCurrentCase() when no case is open + return; + } + // one of the services we subscribed to went down String serviceDisplayName = ServicesMonitor.Service.valueOf(evt.getPropertyName()).getDisplayName(); logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceDisplayName); //NON-NLS diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index c047e67009..2f492f46a2 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -53,9 +53,13 @@ public class SolrSearchService implements KeywordSearchService { if (artifactId > 0) return; - Case currentCase = Case.getCurrentCase(); - if (currentCase == null) + Case currentCase; + try { + currentCase = Case.getCurrentCase(); + } catch (IllegalStateException ignore) { + // thorown by Case.getCurrentCase() if currentCase is null return; + } SleuthkitCase sleuthkitCase = currentCase.getSleuthkitCase(); if (sleuthkitCase == null) @@ -153,6 +157,9 @@ public class SolrSearchService implements KeywordSearchService { try { String host = UserPreferences.getIndexingServerHost(); String port = UserPreferences.getIndexingServerPort(); + if (host.isEmpty() || port.isEmpty()){ + return false; + } HttpSolrServer solrServer = new HttpSolrServer("http://" + host + ":" + port + "/solr"); //NON-NLS; KeywordSearch.getServer().connectToSolrServer(solrServer); } From 04cc65a5323001a7372d42eed2d8088c4e9444e6 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 21 Jul 2015 15:10:27 -0400 Subject: [PATCH 44/44] Make core.events package publicly accessible in Core NBM --- Core/nbproject/project.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 0e8ae6bc76..7f52ec6b25 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -188,6 +188,7 @@ org.sleuthkit.autopsy.casemodule.services org.sleuthkit.autopsy.contentviewers org.sleuthkit.autopsy.core + org.sleuthkit.autopsy.core.events org.sleuthkit.autopsy.corecomponentinterfaces org.sleuthkit.autopsy.corecomponents org.sleuthkit.autopsy.coreutils