- added class ServiceDataEvent - services can notify listeners of new data while they are still processing, and send artifact type, and optionally IDs of all new artifacts (dir tree can refresh more efficiently)

- keyword search now sending the new event
This commit is contained in:
adam-m 2012-02-10 16:11:46 -05:00
parent 55735bafcb
commit ff136f5c3b
4 changed files with 130 additions and 55 deletions

View File

@ -94,7 +94,7 @@ public class IngestImageThread extends SwingWorker {
//notify services of completion //notify services of completion
if (!this.isCancelled()) { if (!this.isCancelled()) {
service.complete(); service.complete();
IngestManager.firePropertyChange(IngestManager.SERVICE_COMPLETED_EVT, service.getName()); IngestManager.fireServiceEvent(IngestManager.SERVICE_COMPLETED_EVT, service.getName());
} }
} catch (CancellationException e) { } catch (CancellationException e) {
//task was cancelled //task was cancelled
@ -117,6 +117,6 @@ public class IngestImageThread extends SwingWorker {
private void handleInterruption() { private void handleInterruption() {
service.stop(); service.stop();
IngestManager.firePropertyChange(IngestManager.SERVICE_STOPPED_EVT, service.getName()); IngestManager.fireServiceEvent(IngestManager.SERVICE_STOPPED_EVT, service.getName());
} }
} }

View File

@ -102,8 +102,12 @@ public class IngestManager {
pcs.addPropertyChangeListener(l); pcs.addPropertyChangeListener(l);
} }
public static synchronized void firePropertyChange(String property, String serviceName) { public static synchronized void fireServiceEvent(String eventType, String serviceName) {
pcs.firePropertyChange(property, serviceName, null); pcs.firePropertyChange(eventType, serviceName, null);
}
public static synchronized void fireServiceDataEvent(ServiceDataEvent serviceDataEvent) {
pcs.firePropertyChange(SERVICE_HAS_DATA_EVT, serviceDataEvent, null);
} }
/** /**
@ -112,19 +116,19 @@ public class IngestManager {
* @param images images to execute services on * @param images images to execute services on
*/ */
void execute(final Collection<IngestServiceAbstract> services, final Collection<Image> images) { void execute(final Collection<IngestServiceAbstract> services, final Collection<Image> images) {
logger.log(Level.INFO, "Will enqueue number of images: " + images.size() ); logger.log(Level.INFO, "Will enqueue number of images: " + images.size());
/*if (!initialized) { /*if (!initialized) {
//one time initialization of services //one time initialization of services
//image services are now initialized per instance //image services are now initialized per instance
//for (IngestServiceImage s : imageServices) { //for (IngestServiceImage s : imageServices) {
// s.init(this); // s.init(this);
//} //}
for (IngestServiceFsContent s : fsContentServices) { for (IngestServiceFsContent s : fsContentServices) {
s.init(this); s.init(this);
} }
initialized = true; initialized = true;
}*/ }*/
tc.enableStartButton(false); tc.enableStartButton(false);
@ -146,7 +150,7 @@ public class IngestManager {
void execute(final Collection<IngestServiceAbstract> services, final Image image) { void execute(final Collection<IngestServiceAbstract> services, final Image image) {
Collection<Image> images = new ArrayList<Image>(); Collection<Image> images = new ArrayList<Image>();
images.add(image); images.add(image);
logger.log(Level.INFO, "Will enqueue image: " + image.getName() ); logger.log(Level.INFO, "Will enqueue image: " + image.getName());
execute(services, images); execute(services, images);
} }
@ -174,34 +178,34 @@ public class IngestManager {
// check if each service for this image is already running // check if each service for this image is already running
//synchronized (this) { //synchronized (this) {
for (IngestServiceImage quService : qu.services) { for (IngestServiceImage quService : qu.services) {
boolean alreadyRunning = false; boolean alreadyRunning = false;
for (IngestImageThread worker : imageIngesters) { for (IngestImageThread worker : imageIngesters) {
// ignore threads that are on different images // ignore threads that are on different images
if (!worker.getImage().equals(qu.content)) { if (!worker.getImage().equals(qu.content)) {
continue; //check next worker continue; //check next worker
}
//same image, check service (by name, not id, since different instances)
if (worker.getService().getName().equals(quService.getName())) {
alreadyRunning = true;
logger.log(Level.INFO, "Image Ingester <" + qu.content + ", " + quService.getName() + "> is already running");
break;
}
} }
//checked all workers //same image, check service (by name, not id, since different instances)
if (alreadyRunning == false) { if (worker.getService().getName().equals(quService.getName())) {
logger.log(Level.INFO, "Starting new image Ingester <" + qu.content + ", " + quService.getName() + ">"); alreadyRunning = true;
IngestImageThread newImageWorker = new IngestImageThread(this, qu.content, quService); logger.log(Level.INFO, "Image Ingester <" + qu.content + ", " + quService.getName() + "> is already running");
break;
imageIngesters.add(newImageWorker);
//image services are now initialized per instance
quService.init(managerProxy);
newImageWorker.execute();
IngestManager.firePropertyChange(SERVICE_STARTED_EVT, quService.getName());
} }
} }
//checked all workers
if (alreadyRunning == false) {
logger.log(Level.INFO, "Starting new image Ingester <" + qu.content + ", " + quService.getName() + ">");
IngestImageThread newImageWorker = new IngestImageThread(this, qu.content, quService);
imageIngesters.add(newImageWorker);
//image services are now initialized per instance
quService.init(managerProxy);
newImageWorker.execute();
IngestManager.fireServiceEvent(SERVICE_STARTED_EVT, quService.getName());
}
} }
}
//} //}
@ -302,7 +306,7 @@ public class IngestManager {
* IngestService should make an attempt not to publish the same message multiple times. * IngestService should make an attempt not to publish the same message multiple times.
* Viewer will attempt to identify duplicate messages and filter them out (slower) * Viewer will attempt to identify duplicate messages and filter them out (slower)
*/ */
synchronized void postMessage(final IngestMessage message) { synchronized void postMessage(final IngestMessage message) {
if (stats != null) { if (stats != null) {
//record the error for stats, if stats are running //record the error for stats, if stats are running
@ -750,8 +754,7 @@ public class IngestManager {
Integer curServiceErrorI = errors.get(source); Integer curServiceErrorI = errors.get(source);
if (curServiceErrorI == null) { if (curServiceErrorI == null) {
errors.put(source, 1); errors.put(source, 1);
} } else {
else {
errors.put(source, curServiceErrorI + 1); errors.put(source, curServiceErrorI + 1);
} }
} }
@ -777,7 +780,7 @@ public class IngestManager {
@Override @Override
public void run() { public void run() {
for (IngestServiceFsContent s : fsContentServices) { for (IngestServiceFsContent s : fsContentServices) {
IngestManager.firePropertyChange(SERVICE_STARTED_EVT, s.getName()); IngestManager.fireServiceEvent(SERVICE_STARTED_EVT, s.getName());
} }
} }
}); });
@ -835,7 +838,7 @@ public class IngestManager {
if (!this.isCancelled()) { if (!this.isCancelled()) {
for (IngestServiceFsContent s : fsContentServices) { for (IngestServiceFsContent s : fsContentServices) {
s.complete(); s.complete();
IngestManager.firePropertyChange(SERVICE_COMPLETED_EVT, s.getName()); IngestManager.fireServiceEvent(SERVICE_COMPLETED_EVT, s.getName());
} }
} }
@ -868,7 +871,7 @@ public class IngestManager {
private void handleInterruption() { private void handleInterruption() {
for (IngestServiceFsContent s : fsContentServices) { for (IngestServiceFsContent s : fsContentServices) {
s.stop(); s.stop();
IngestManager.firePropertyChange(SERVICE_STOPPED_EVT, s.getName()); IngestManager.fireServiceEvent(SERVICE_STOPPED_EVT, s.getName());
} }
//empty queues //empty queues
emptyFsContents(); emptyFsContents();

View File

@ -0,0 +1,71 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.ingest;
import java.util.Collection;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
/**
* representation of an event fired off by services when they have posted new data
* of specific type
* additionally, new artifact ids can be provided
*/
public class ServiceDataEvent {
private String serviceName;
private ARTIFACT_TYPE artifactType;
private Collection<Long> artifactIDs;
public ServiceDataEvent(String serviceName, ARTIFACT_TYPE artifactType) {
this.serviceName = serviceName;
this.artifactType = artifactType;
}
public ServiceDataEvent(String serviceName, ARTIFACT_TYPE artifactType, Collection<Long> artifactIDs) {
this(serviceName, artifactType);
this.artifactIDs = artifactIDs;
}
/**
* get new artifact IDs associated with the event
* @return Collection of artifact ids or null if not provided
*/
public Collection<Long> getArtifactIDs() {
return artifactIDs;
}
/**
* get artifact type of the new artifacts associated with the event
* @return
*/
public ARTIFACT_TYPE getArtifactType() {
return artifactType;
}
/**
* get service name that created the artifacts and fired the event
* @return
*/
public String getServiceName() {
return serviceName;
}
}

View File

@ -18,7 +18,6 @@
*/ */
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -40,6 +39,7 @@ import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
import org.sleuthkit.autopsy.ingest.IngestServiceFsContent; import org.sleuthkit.autopsy.ingest.IngestServiceFsContent;
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException; import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
@ -443,12 +443,14 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, instance, sb.toString())); managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, instance, sb.toString()));
//write results to BB //write results to BB
Collection<Long> newArtifacts = new ArrayList<Long>(); //new artifacts to report
for (FsContent hitFile : newResults) { for (FsContent hitFile : newResults) {
Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>(); Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
if (query.isLiteral()) { if (query.isLiteral()) {
BlackboardArtifact bba = null; BlackboardArtifact bba = null;
try { try {
bba = hitFile.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT); bba = hitFile.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifacts.add(bba.getArtifactID());
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.INFO, "Error adding bb artifact for keyword hit", e); logger.log(Level.INFO, "Error adding bb artifact for keyword hit", e);
continue; continue;
@ -510,6 +512,7 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
BlackboardArtifact bba = null; BlackboardArtifact bba = null;
try { try {
bba = hitFile.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT); bba = hitFile.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifacts.add(bba.getArtifactID());
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.INFO, "Error adding bb artifact for keyword hit", e); logger.log(Level.INFO, "Error adding bb artifact for keyword hit", e);
continue; continue;
@ -546,9 +549,7 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
} //for each file hit } //for each file hit
//update artifact browser //update artifact browser
//TODO use has data evt IngestManager.fireServiceDataEvent(new ServiceDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, newArtifacts));
IngestManager.firePropertyChange(IngestManager.SERVICE_STARTED_EVT, MODULE_NAME);
IngestManager.firePropertyChange(IngestManager.SERVICE_HAS_DATA_EVT, MODULE_NAME);
} }
progress.progress(queryStr, ++numSearched); progress.progress(queryStr, ++numSearched);
} }