- 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
if (!this.isCancelled()) {
service.complete();
IngestManager.firePropertyChange(IngestManager.SERVICE_COMPLETED_EVT, service.getName());
IngestManager.fireServiceEvent(IngestManager.SERVICE_COMPLETED_EVT, service.getName());
}
} catch (CancellationException e) {
//task was cancelled
@ -117,6 +117,6 @@ public class IngestImageThread extends SwingWorker {
private void handleInterruption() {
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);
}
public static synchronized void firePropertyChange(String property, String serviceName) {
pcs.firePropertyChange(property, serviceName, null);
public static synchronized void fireServiceEvent(String eventType, String serviceName) {
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
*/
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) {
//one time initialization of services
//image services are now initialized per instance
//for (IngestServiceImage s : imageServices) {
// s.init(this);
//}
for (IngestServiceFsContent s : fsContentServices) {
s.init(this);
}
initialized = true;
//one time initialization of services
//image services are now initialized per instance
//for (IngestServiceImage s : imageServices) {
// s.init(this);
//}
for (IngestServiceFsContent s : fsContentServices) {
s.init(this);
}
initialized = true;
}*/
tc.enableStartButton(false);
@ -146,7 +150,7 @@ public class IngestManager {
void execute(final Collection<IngestServiceAbstract> services, final Image image) {
Collection<Image> images = new ArrayList<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);
}
@ -162,7 +166,7 @@ public class IngestManager {
private synchronized void startAll() {
logger.log(Level.INFO, "Image queue: " + this.imageQueue.toString());
logger.log(Level.INFO, "File queue: " + this.fsContentQueue.toString());
//image ingesters
// cycle through each image in the queue
while (hasNextImage()) {
@ -170,38 +174,38 @@ public class IngestManager {
// get next image and set of services
final QueueUnit<Image, IngestServiceImage> qu =
this.getNextImage();
// check if each service for this image is already running
//synchronized (this) {
for (IngestServiceImage quService : qu.services) {
boolean alreadyRunning = false;
for (IngestImageThread worker : imageIngesters) {
// ignore threads that are on different images
if (!worker.getImage().equals(qu.content)) {
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;
}
for (IngestServiceImage quService : qu.services) {
boolean alreadyRunning = false;
for (IngestImageThread worker : imageIngesters) {
// ignore threads that are on different images
if (!worker.getImage().equals(qu.content)) {
continue; //check next worker
}
//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.firePropertyChange(SERVICE_STARTED_EVT, quService.getName());
//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
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());
}
}
}
//}
@ -268,7 +272,7 @@ public class IngestManager {
}
}
logger.log(Level.INFO, "stopped all");
logger.log(Level.INFO, "stopped all");
}
/**
@ -302,7 +306,7 @@ public class IngestManager {
* 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)
*/
synchronized void postMessage(final IngestMessage message) {
synchronized void postMessage(final IngestMessage message) {
if (stats != null) {
//record the error for stats, if stats are running
@ -750,8 +754,7 @@ public class IngestManager {
Integer curServiceErrorI = errors.get(source);
if (curServiceErrorI == null) {
errors.put(source, 1);
}
else {
} else {
errors.put(source, curServiceErrorI + 1);
}
}
@ -777,7 +780,7 @@ public class IngestManager {
@Override
public void run() {
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()) {
for (IngestServiceFsContent s : fsContentServices) {
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() {
for (IngestServiceFsContent s : fsContentServices) {
s.stop();
IngestManager.firePropertyChange(SERVICE_STOPPED_EVT, s.getName());
IngestManager.fireServiceEvent(SERVICE_STOPPED_EVT, s.getName());
}
//empty queues
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;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
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.MessageType;
import org.sleuthkit.autopsy.ingest.IngestServiceFsContent;
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
import org.sleuthkit.datamodel.BlackboardArtifact;
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()));
//write results to BB
Collection<Long> newArtifacts = new ArrayList<Long>(); //new artifacts to report
for (FsContent hitFile : newResults) {
Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
if (query.isLiteral()) {
BlackboardArtifact bba = null;
try {
bba = hitFile.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifacts.add(bba.getArtifactID());
} catch (Exception e) {
logger.log(Level.INFO, "Error adding bb artifact for keyword hit", e);
continue;
@ -510,6 +512,7 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
BlackboardArtifact bba = null;
try {
bba = hitFile.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifacts.add(bba.getArtifactID());
} catch (Exception e) {
logger.log(Level.INFO, "Error adding bb artifact for keyword hit", e);
continue;
@ -546,9 +549,7 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
} //for each file hit
//update artifact browser
//TODO use has data evt
IngestManager.firePropertyChange(IngestManager.SERVICE_STARTED_EVT, MODULE_NAME);
IngestManager.firePropertyChange(IngestManager.SERVICE_HAS_DATA_EVT, MODULE_NAME);
IngestManager.fireServiceDataEvent(new ServiceDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, newArtifacts));
}
progress.progress(queryStr, ++numSearched);
}