diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/FileContentProvider.java b/Core/src/org/sleuthkit/autopsy/casemodule/AutopsyContentProvider.java similarity index 74% rename from Core/src/org/sleuthkit/autopsy/casemodule/FileContentProvider.java rename to Core/src/org/sleuthkit/autopsy/casemodule/AutopsyContentProvider.java index 46ae23dcd6..f894ce8a34 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/FileContentProvider.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AutopsyContentProvider.java @@ -19,24 +19,29 @@ package org.sleuthkit.autopsy.casemodule; import java.util.Map; -import org.sleuthkit.datamodel.ContentStream.ContentProvider; +import org.sleuthkit.datamodel.ContentStreamProvider; /** - * A factory that generates a TSK ContentProvider. + * Interface that modules can implement to provide their own The Sleuth Kit + * ContentProvider implementations */ -public interface FileContentProvider { +public interface AutopsyContentProvider { /** * Attempts to create a ContentProvider given the specified args. Returns * null if arguments are invalid for this custom content provider. * - * @param args The key value pair of arguments loaded from the .aut xml file. + * @param args The key value pair of arguments loaded from the .aut xml + * file. * @return The created content provider or null if arguments are invalid. */ - ContentProvider load(Map args); - + ContentStreamProvider load(Map args); + /** - * Returns the uniquely identifying name of this FileContentProvider. + * Returns the uniquely identifying name of this FileContentProvider. This + * name will be stored in the .AUT file and used for lookup when the case is + * opened. + * * @return The unique name. */ String getName(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 037719606b..1305f3248d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -143,7 +143,7 @@ import org.sleuthkit.autopsy.timeline.events.TimelineEventAddedEvent; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentStream.ContentProvider; +import org.sleuthkit.datamodel.ContentStreamProvider; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.FileSystem; @@ -186,7 +186,6 @@ public class Case { private static volatile Frame mainFrame; private static volatile Case currentCase; private final CaseMetadata metadata; - private final ContentProvider contentProvider; private volatile ExecutorService caseActionExecutor; private CoordinationService.Lock caseLock; private SleuthkitCase caseDb; @@ -2070,10 +2069,9 @@ public class Case { */ private Case(CaseMetadata caseMetaData) { metadata = caseMetaData; - this.contentProvider = caseMetaData.getContentProvider(); sleuthkitEventListener = new SleuthkitEventListener(); } - + /** * Performs a case action that involves creating or opening a case. If the * case is a multi-user case, the action is done after acquiring a @@ -2737,15 +2735,20 @@ public class Case { progressIndicator.progress(Bundle.Case_progressMessage_openingCaseDatabase()); try { String databaseName = metadata.getCaseDatabaseName(); + + ContentStreamProvider contentProvider = loadContentProvider( + metadata.getContentProviderName(), + metadata.getContentProviderArgs()); + if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) { // only prefix with metadata directory if databaseName is a relative path String fullDatabasePath = (new File(databaseName).isAbsolute()) ? databaseName : Paths.get(metadata.getCaseDirectory(), databaseName).toString(); - caseDb = SleuthkitCase.openCase(fullDatabasePath, this.contentProvider); + caseDb = SleuthkitCase.openCase(fullDatabasePath, contentProvider); } else if (UserPreferences.getIsMultiUserModeEnabled()) { - caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory(), this.contentProvider); + caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory(), contentProvider); } else { throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled()); } @@ -2758,6 +2761,36 @@ public class Case { throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(ex.getLocalizedMessage()), ex); } } + + + /** + * Attempts to load a content provider for the provided arguments. Returns + * null if no content provider for the arguments can be identified. + * + * @param providerName The name of the content provider. + * @param args The arguments. + * @return The content provider or null if no content provider can be + * provisioned for the arguments + */ + private static ContentStreamProvider loadContentProvider(String providerName, Map args) { + Collection customContentProviders = Lookup.getDefault().lookupAll(AutopsyContentProvider.class); + if (customContentProviders != null) { + for (AutopsyContentProvider customProvider : customContentProviders) { + // ensure the provider matches the name + if (customProvider == null || !StringUtils.equalsIgnoreCase(providerName, customProvider.getName())) { + continue; + } + + ContentStreamProvider contentProvider = customProvider.load(args); + if (contentProvider != null) { + return contentProvider; + } + } + } + + return null; + } + /** * Opens the case-level services: the files manager, tags manager and diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 34b6cf280a..d8f0146beb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -55,7 +55,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.openide.util.Lookup; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.XMLUtil; -import org.sleuthkit.datamodel.ContentStream.ContentProvider; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -143,7 +142,6 @@ public final class CaseMetadata { private String createdDate; private String createdByVersion; private CaseMetadata originalMetadata = null; // For portable cases - private ContentProvider contentProvider; private String contentProviderName; private Map contentProviderArgs; @@ -201,7 +199,7 @@ public final class CaseMetadata { createdByVersion = Version.getVersion(); createdDate = CaseMetadata.DATE_FORMAT.format(new Date()); this.originalMetadata = originalMetadata; - this.contentProvider = originalMetadata == null ? null : originalMetadata.contentProvider; + this.contentProviderName = originalMetadata == null ? null : originalMetadata.contentProviderName; this.contentProviderArgs = originalMetadata == null ? null : originalMetadata.contentProviderArgs; } @@ -241,11 +239,19 @@ public final class CaseMetadata { } /** - * @return The custom provider for content byte data or null if no custom - * provider. + * @return The custom provider name for content byte data or null if no + * custom provider. */ - public ContentProvider getContentProvider() { - return contentProvider; + public String getContentProviderName() { + return this.contentProviderName; + } + + /** + * @return The arguments for the custom provider for content byte data or + * null if no custom provider. + */ + public Map getContentProviderArgs() { + return contentProviderArgs; } /** @@ -604,11 +610,9 @@ public final class CaseMetadata { this.contentProviderArgs = (contentProviderArgs instanceof Map) ? (Map) contentProviderArgs : Collections.singletonMap(CONTENT_PROVIDER_ARG_DEFAULT_KEY, contentProviderArgs); - this.contentProvider = loadContentProvider(contentProviderName, this.contentProviderArgs); } else { this.contentProviderArgs = null; this.contentProviderName = null; - this.contentProvider = null; } /* @@ -774,34 +778,6 @@ public final class CaseMetadata { el.setTextContent(arg.toString()); } } - - /** - * Attempts to load a content provider for the provided arguments. Returns - * null if no content provider for the arguments can be identified. - * - * @param providerName The name of the content provider. - * @param args The arguments. - * @return The content provider or null if no content provider can be - * provisioned for the arguments - */ - private ContentProvider loadContentProvider(String providerName, Map args) { - Collection customContentProviders = Lookup.getDefault().lookupAll(FileContentProvider.class); - if (customContentProviders != null) { - for (FileContentProvider customProvider : customContentProviders) { - // ensure the provider matches the name - if (customProvider == null || !StringUtils.equalsIgnoreCase(providerName, customProvider.getName())) { - continue; - } - - ContentProvider contentProvider = customProvider.load(args); - if (contentProvider != null) { - return contentProvider; - } - } - } - - return null; - } /** * Gets the text content of an XML element.