diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java index 069b13ef2e..7da8839a43 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java @@ -26,6 +26,9 @@ import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import org.openide.util.Lookup; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceFactory; import org.sleuthkit.datamodel.SleuthkitCase; /** @@ -42,6 +45,7 @@ public class Services implements Closeable { // services private FileManager fileManager; private TagsManager tagsManager; + private KeywordSearchService keywordSearchService; public Services(SleuthkitCase tskCase) { this.tskCase = tskCase; @@ -51,6 +55,8 @@ public class Services implements Closeable { tagsManager = new TagsManager(tskCase); services.add(tagsManager); + + loadKeywordSearchService(); } public FileManager getFileManager() { @@ -61,6 +67,10 @@ public class Services implements Closeable { return tagsManager; } + public KeywordSearchService getKeywordSearchService() { + return keywordSearchService; + } + @Override public void close() throws IOException { // close all services @@ -68,4 +78,10 @@ public class Services implements Closeable { service.close(); } } + + private void loadKeywordSearchService() { + KeywordSearchServiceFactory factory = Lookup.getDefault().lookup(KeywordSearchServiceFactory.class); + keywordSearchService = factory.createKeywordSearchService(); + services.add(keywordSearchService); + } } diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java new file mode 100644 index 0000000000..c14adbb0bb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java @@ -0,0 +1,38 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 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.keywordsearchservice; + +import java.io.Closeable; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + */ +public interface KeywordSearchService extends Closeable { + + /** + * Takes a Blackboard artifact and adds all of its attributes to the keyword + * search index. + * + * @param artifact + * @throws org.sleuthkit.datamodel.TskCoreException + */ + public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException; +} diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchServiceFactory.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchServiceFactory.java new file mode 100644 index 0000000000..8a81ed3870 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchServiceFactory.java @@ -0,0 +1,30 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 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.keywordsearchservice; + +/** + * Factory interface for creating new instances of a KeywordSearchService. + */ +public interface KeywordSearchServiceFactory { + /** + * Creates a Keyword Search Service instance. + * @return + */ + public KeywordSearchService createKeywordSearchService(); +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java index d79db1277e..fd8dd8e90f 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java @@ -34,6 +34,7 @@ import java.util.Collection; import java.util.Date; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.FileIngestModule; @@ -41,6 +42,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -156,6 +158,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule { if (!attributes.isEmpty()) { BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF); bba.addAttributes(attributes); + indexArtifact(bba); filesToFire = true; } @@ -196,6 +199,19 @@ public final class ExifParserFileIngestModule implements FileIngestModule { return ImageUtils.isJpegFileHeader(f); } + /** + * + * @param artifact + */ + private void indexArtifact(BlackboardArtifact artifact) throws TskCoreException { + Case currentCase = Case.getCurrentCase(); + + if (currentCase != null) { + KeywordSearchService kwsService = currentCase.getServices().getKeywordSearchService(); + if (kwsService != null) + kwsService.indexArtifact(artifact); + } + } @Override public void shutDown() { // We only need to check for this final event on the last module per job diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java index be03c48a24..d575775a18 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java @@ -268,7 +268,7 @@ class Ingester { * @param size * @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException */ - private void ingest(ContentStream cs, Map fields, final long size) throws IngesterException { + void ingest(ContentStream cs, Map fields, final long size) throws IngesterException { if (fields.get(Server.Schema.IMAGE_ID.toString()) == null) { //skip the file, image id unknown diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java new file mode 100644 index 0000000000..a8f7e3e0a2 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -0,0 +1,92 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 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.keywordsearch; + +import java.io.IOException; +import java.util.HashMap; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; +import org.apache.solr.common.util.ContentStreamBase.StringStream; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.SleuthkitCase; + +/** + * An implementation of the KeywordSearchService interface that uses + * Solr for text indexing and search. + */ +public class SolrSearchService implements KeywordSearchService { + @Override + public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException { + if (artifact == null) + return; + + Case currentCase = Case.getCurrentCase(); + if (currentCase == null) + return; + + SleuthkitCase sleuthkitCase = currentCase.getSleuthkitCase(); + if (sleuthkitCase == null) + return; + + AbstractFile abstractFile = sleuthkitCase.getAbstractFileById(artifact.getObjectID()); + if (abstractFile == null) + return; + + Content dataSource = abstractFile.getDataSource(); + if (dataSource == null) + return; + + // Concatenate the string values of all attributes into a single + // "content" string to be indexed. + String artifactContents = ""; + + for (BlackboardAttribute attribute : artifact.getAttributes()) { + artifactContents += attribute.getDisplayString(); + artifactContents += " "; + } + + if (artifactContents.isEmpty()) + return; + + // Set the ID field for the document. We distinguish artifact + // content from file content by prepending "art-" to the + // artifact object id. + HashMap solrFields = new HashMap<>(); + solrFields.put(Server.Schema.ID.toString(), "art-" + artifact.getArtifactID()); + + // Set the IMAGE_ID field. + solrFields.put(Server.Schema.IMAGE_ID.toString(), Long.toString(dataSource.getId())); + + StringStream contentStream = new StringStream(artifactContents); + + try { + Ingester.getDefault().ingest(contentStream, solrFields, contentStream.getSize()); + } + catch (Ingester.IngesterException ex) { + } + } + + @Override + public void close() throws IOException { + } +} diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchServiceFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchServiceFactory.java new file mode 100644 index 0000000000..731eb67dc6 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchServiceFactory.java @@ -0,0 +1,34 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 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.keywordsearch; + +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceFactory; + +/** + * A factory class that creates a new KeywordSearchService instance. + */ +@ServiceProvider(service = KeywordSearchServiceFactory.class) +public class SolrSearchServiceFactory implements KeywordSearchServiceFactory { + @Override + public KeywordSearchService createKeywordSearchService() { + return new SolrSearchService(); + } +}