From cb3679c0dfa60036333e473c5f632504475cf0db Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 11 Sep 2013 12:07:12 -0400 Subject: [PATCH 1/4] Workaround for undesirable interaction between viewers in keyword search results --- .../sleuthkit/autopsy/corecomponents/DataResultPanel.java | 7 ++++++- .../autopsy/corecomponents/DataResultViewerTable.java | 1 - .../autopsy/corecomponents/DataResultViewerThumbnail.java | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 18a13ec560..755f2d01d9 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -189,7 +189,12 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C // to better handle the ExplorerManager sharing implemented to support actions that operate on // multiple selected nodes. addDataResultViewer(new DataResultViewerTable(this.explorerManager)); - addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); + + // @@@ Temporary fix until unintended interaction between DataResultViewerTable and DataResultViewerThumbnail + // via the shared ExplorerManager in a Keyword Search Result window is resolved. + if (isMain) { + addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); + } // Find all DataResultViewer service providers and add them to the tabbed pane. for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 36ccb8715d..1da346f00c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -78,7 +78,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.setAllowedDragActions(DnDConstants.ACTION_NONE); ov.setAllowedDropActions(DnDConstants.ACTION_NONE); - // only allow one item to be selected at a time ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // don't show the root node diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index 9c4fd31609..a9a70152df 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -85,7 +85,6 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { private void initialize() { initComponents(); - // only allow one item to be selected at a time ((IconView) thumbnailScrollPanel).setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); curPage = -1; From 58dd29d382e0c59ecaaf59b3134c69bcfa51cb5e Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 12 Sep 2013 15:33:41 -0400 Subject: [PATCH 2/4] Flattened keyword search results listing node hierarchy for DataResultViewers --- .../corecomponents/DataResultPanel.java | 9 +-- .../AbstractKeywordSearchPerformer.java | 11 +-- .../KeywordSearchQueryManager.java | 22 +++--- .../KeywordSearchResultFactory.java | 73 ++++++++++--------- 4 files changed, 54 insertions(+), 61 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 755f2d01d9..3497b8f274 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -188,13 +188,8 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C // as DataResultViewer service providers when DataResultViewers are updated // to better handle the ExplorerManager sharing implemented to support actions that operate on // multiple selected nodes. - addDataResultViewer(new DataResultViewerTable(this.explorerManager)); - - // @@@ Temporary fix until unintended interaction between DataResultViewerTable and DataResultViewerThumbnail - // via the shared ExplorerManager in a Keyword Search Result window is resolved. - if (isMain) { - addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); - } + addDataResultViewer(new DataResultViewerTable(this.explorerManager)); + addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); // Find all DataResultViewer service providers and add them to the tabbed pane. for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java index 1cfdae3774..436c069698 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,9 +21,6 @@ package org.sleuthkit.autopsy.keywordsearch; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; -import java.util.logging.Level; -import org.apache.solr.client.solrj.SolrServerException; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation; @@ -35,7 +32,6 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentatio abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface { protected int filesIndexed; - private static final Logger logger = Logger.getLogger(AbstractKeywordSearchPerformer.class.getName()); AbstractKeywordSearchPerformer() { initListeners(); @@ -47,7 +43,6 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme @Override public void propertyChange(PropertyChangeEvent evt) { String changed = evt.getPropertyName(); - Object oldValue = evt.getOldValue(); Object newValue = evt.getNewValue(); if (changed.equals(KeywordSearch.NUM_FILES_CHANGE_EVT)) { @@ -114,7 +109,7 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme KeywordSearchUtil.displayDialog("Keyword Search Error", "Keyword list is empty, please add at least one keyword to the list", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); return; } - man = new KeywordSearchQueryManager(keywords, Presentation.COLLAPSE); + man = new KeywordSearchQueryManager(keywords, Presentation.FLAT); } else { QueryType queryType = null; @@ -128,7 +123,7 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme KeywordSearchUtil.displayDialog("Keyword Search Error", "Please enter a keyword to search for", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); return; } - man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.COLLAPSE); + man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.FLAT); } if (man.validate()) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java index f11838f90e..c95a270952 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.windows.TopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.datamodel.KeyValue; import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType; @@ -41,7 +40,7 @@ public class KeywordSearchQueryManager { // how to display the results public enum Presentation { - COLLAPSE, DETAIL + FLAT, COLLAPSE, DETAIL }; private List keywords; @@ -70,7 +69,7 @@ public class KeywordSearchQueryManager { * @param presentation Presentation Layout */ public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) { - keywords = new ArrayList(); + keywords = new ArrayList<>(); keywords.add(new Keyword(query, qt == QueryType.REGEX ? false : true)); this.presentation = presentation; queryType = qt; @@ -84,7 +83,7 @@ public class KeywordSearchQueryManager { * @param presentation Presentation layout */ public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) { - keywords = new ArrayList(); + keywords = new ArrayList<>(); keywords.add(new Keyword(query, isLiteral)); this.presentation = presentation; queryType = isLiteral ? QueryType.WORD : QueryType.REGEX; @@ -96,7 +95,7 @@ public class KeywordSearchQueryManager { * Create a list of queries to later run */ private void init() { - queryDelegates = new ArrayList(); + queryDelegates = new ArrayList<>(); for (Keyword keyword : keywords) { KeywordSearchQuery query = null; switch (queryType) { @@ -137,18 +136,17 @@ public class KeywordSearchQueryManager { // } else { //Collapsed view - Collection things = new ArrayList(); + Collection things = new ArrayList<>(); int queryID = 0; StringBuilder queryConcat = new StringBuilder(); // concatenation of all query strings for (KeywordSearchQuery q : queryDelegates) { - Map kvs = new LinkedHashMap(); + Map kvs = new LinkedHashMap<>(); final String queryStr = q.getQueryString(); queryConcat.append(queryStr).append(" "); things.add(new KeyValueQuery(queryStr, kvs, ++queryID, q)); } - Node rootNode = null; - + Node rootNode; String queryConcatStr = queryConcat.toString(); final int queryConcatStrLen = queryConcatStr.length(); final String queryStrShort = queryConcatStrLen > 15 ? queryConcatStr.substring(0, 14) + "..." : queryConcatStr; @@ -156,7 +154,7 @@ public class KeywordSearchQueryManager { DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle); if (things.size() > 0) { Children childThingNodes = - Children.create(new KeywordSearchResultFactory(keywords, things, Presentation.COLLAPSE, searchResultWin), true); + Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin), true); rootNode = new AbstractNode(childThingNodes); } else { @@ -179,7 +177,7 @@ public class KeywordSearchQueryManager { boolean allValid = true; for (KeywordSearchQuery tcq : queryDelegates) { if (!tcq.validate()) { - logger.log(Level.WARNING, "Query has invalid syntax: " + tcq.getQueryString()); + logger.log(Level.WARNING, "Query has invalid syntax: {0}", tcq.getQueryString()); allValid = false; break; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index d616b0361e..e595307b65 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,6 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.util.Cancellable; -import org.openide.util.Lookup; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; @@ -109,7 +108,7 @@ public class KeywordSearchResultFactory extends ChildFactory { } KeywordSearchResultFactory(Keyword query, Collection things, Presentation presentation, DataResultTopComponent viewer) { - queries = new ArrayList(); + queries = new ArrayList<>(); queries.add(query); this.presentation = presentation; this.things = things; @@ -134,7 +133,6 @@ public class KeywordSearchResultFactory extends ChildFactory { for (int i = 0; i < FS_PROPS_LEN; ++i) { toSet.put(fsTypes[i].toString(), ""); } - } public static void setCommonProperty(Map toSet, CommonPropertyTypes type, String value) { @@ -150,10 +148,21 @@ public class KeywordSearchResultFactory extends ChildFactory { @Override protected boolean createKeys(List toPopulate) { int id = 0; - if (presentation == Presentation.DETAIL) { + if (presentation == Presentation.FLAT) { + for (KeyValueQuery thing : things) { + Map map = thing.getMap(); + initCommonProperties(map); + final String query = thing.getName(); + setCommonProperty(map, CommonPropertyTypes.KEYWORD, query); + setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped())); + ResultCollapsedChildFactory childFactory = new ResultCollapsedChildFactory(thing); + childFactory.createKeysForFlatNodes(toPopulate); + } + } + else if (presentation == Presentation.DETAIL) { Iterator it = things.iterator(); for (Keyword keyword : queries) { - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); final String query = keyword.getQuery(); initCommonProperties(map); setCommonProperty(map, CommonPropertyTypes.KEYWORD, query); @@ -166,25 +175,26 @@ public class KeywordSearchResultFactory extends ChildFactory { } } else { for (KeyValueQuery thing : things) { - //Map map = new LinkedHashMap(); Map map = thing.getMap(); initCommonProperties(map); final String query = thing.getName(); setCommonProperty(map, CommonPropertyTypes.KEYWORD, query); setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped())); - //toPopulate.add(new KeyValue(query, map, ++id)); toPopulate.add(thing); } } - + return true; } @Override protected Node createNodeForKey(KeyValueQuery thing) { - ChildFactory childFactory = null; - - if (presentation == Presentation.COLLAPSE) { + ChildFactory childFactory; + if (presentation == Presentation.FLAT) { + ResultCollapsedChildFactory factory = new ResultCollapsedChildFactory(thing); + return factory.createFlatNodeForKey(thing); + } + else if (presentation == Presentation.COLLAPSE) { childFactory = new ResultCollapsedChildFactory(thing); final Node ret = new KeyValueNode(thing, Children.create(childFactory, true)); SwingUtilities.invokeLater(new Runnable() { @@ -199,7 +209,6 @@ public class KeywordSearchResultFactory extends ChildFactory { }); return ret; } else { - childFactory = new ResulTermsMatchesChildFactory(things); return new KeyValueNode(thing, Children.create(childFactory, true)); } @@ -218,9 +227,13 @@ public class KeywordSearchResultFactory extends ChildFactory { this.queryThing = queryThing; } + // @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient. + public boolean createKeysForFlatNodes(List toPopulate) { + return createKeys(toPopulate); + } + @Override protected boolean createKeys(List toPopulate) { - //final String origQuery = queryThing.getName(); final KeyValueQuery queryThingQuery = queryThing; final KeywordSearchQuery tcq = queryThingQuery.getQuery(); @@ -252,7 +265,7 @@ public class KeywordSearchResultFactory extends ChildFactory { for (final AbstractFile f : hitContents.keySet()) { final int previewChunk = hitContents.get(f); //get unique match result files - Map resMap = new LinkedHashMap(); + Map resMap = new LinkedHashMap<>(); setCommonProperty(resMap, CommonPropertyTypes.MATCH, f.getName()); try { @@ -306,12 +319,11 @@ public class KeywordSearchResultFactory extends ChildFactory { //whereas in bb we write every hit per file separately new ResultWriter(tcqRes, tcq, listName).execute(); - return true; } private String getHighlightQuery(KeywordSearchQuery tcq, boolean literal_query, Map> tcqRes, AbstractFile f) { - String highlightQueryEscaped = null; + String highlightQueryEscaped; if (literal_query) { //literal, treat as non-regex, non-term component query highlightQueryEscaped = tcq.getQueryString(); @@ -326,7 +338,7 @@ public class KeywordSearchResultFactory extends ChildFactory { highlightQuery.append(term); } else { //find terms for this file hit - List hitTerms = new ArrayList(); + List hitTerms = new ArrayList<>(); for (String term : tcqRes.keySet()) { List hitList = tcqRes.get(term); @@ -363,10 +375,13 @@ public class KeywordSearchResultFactory extends ChildFactory { return highlightQueryEscaped; } + // @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient. + public Node createFlatNodeForKey(KeyValueQuery thing) { + return createNodeForKey(thing); + } + @Override protected Node createNodeForKey(KeyValueQuery thing) { - //return new KeyValueNode(thing, Children.LEAF); - //return new KeyValueNode(thing, Children.create(new ResultFilesChildFactory(thing), true)); final KeyValueQueryContent thingContent = (KeyValueQueryContent) thing; final Content content = thingContent.getContent(); final String queryStr = thingContent.getQueryStr(); @@ -377,7 +392,6 @@ public class KeywordSearchResultFactory extends ChildFactory { //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, queryStr, !thingContent.getQuery().isEscaped(), false, hits); return new KeywordSearchFilterNode(highlights, kvNode, queryStr, previewChunk); - } } @@ -438,12 +452,11 @@ public class KeywordSearchResultFactory extends ChildFactory { for (final AbstractFile f : uniqueMatches.keySet()) { final int previewChunkId = uniqueMatches.get(f); - Map resMap = new LinkedHashMap(); + Map resMap = new LinkedHashMap<>(); if (f.getType() == TSK_DB_FILES_TYPE_ENUM.FS) { AbstractFsContentNode.fillPropertyMap(resMap, (FsContent) f); } toPopulate.add(new KeyValueQueryContent(f.getName(), resMap, ++resID, f, keywordQuery, thing.getQuery(), previewChunkId, matchesRes)); - } //write to bb new ResultWriter(matchesRes, origQuery, "").execute(); @@ -459,7 +472,6 @@ public class KeywordSearchResultFactory extends ChildFactory { final int previewChunk = thingContent.getPreviewChunk(); final Map> hits = thingContent.getHits(); - Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content)); //wrap in KeywordSearchFilterNode for the markup content HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, query, !thingContent.getQuery().isEscaped(), hits); @@ -475,7 +487,6 @@ public class KeywordSearchResultFactory extends ChildFactory { private Content content; private String queryStr; - private KeywordSearchQuery query; private int previewChunk; private Map> hits; @@ -510,7 +521,7 @@ public class KeywordSearchResultFactory extends ChildFactory { */ static class ResultWriter extends SwingWorker { - private static List writers = new ArrayList(); + private static List writers = new ArrayList<>(); //lock utilized to enqueue writers and limit execution to 1 at a time private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy //private static final Lock writerLock = rwLock.writeLock(); @@ -518,14 +529,13 @@ public class KeywordSearchResultFactory extends ChildFactory { private KeywordSearchQuery query; private String listName; private Map> hits; - final Collection na = new ArrayList(); + final Collection na = new ArrayList<>(); private static final int QUERY_DISPLAY_LEN = 40; ResultWriter(Map> hits, KeywordSearchQuery query, String listName) { this.hits = hits; this.query = query; this.listName = listName; - } protected void finalizeWorker() { @@ -539,7 +549,6 @@ public class KeywordSearchResultFactory extends ChildFactory { } }); - if (!this.isCancelled() && !na.isEmpty()) { IngestServices.getDefault().fireModuleDataEvent(new ModuleDataEvent(KeywordSearchIngestModule.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na)); } @@ -573,7 +582,7 @@ public class KeywordSearchResultFactory extends ChildFactory { for (AbstractFile f : flattened.keySet()) { int chunkId = flattened.get(f); final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hit); - String snippet = null; + String snippet; try { snippet = LuceneQuery.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true); } catch (NoOpenCoreException e) { @@ -591,15 +600,11 @@ public class KeywordSearchResultFactory extends ChildFactory { } } } - } } finally { - //writerLock.unlock(); finalizeWorker(); } - - return null; } From e50da488f929aae79c5d685f101e50c2d2ef4577 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Thu, 12 Sep 2013 16:12:59 -0400 Subject: [PATCH 3/4] Added comment to new enum about display types --- .../autopsy/keywordsearch/KeywordSearchQueryManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java index c95a270952..eec153c0d8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java @@ -40,7 +40,9 @@ public class KeywordSearchQueryManager { // how to display the results public enum Presentation { - FLAT, COLLAPSE, DETAIL + FLAT, // all results are in a single level (even if multiple keywords and reg-exps are used). We made this because we were having problems with multiple-levels of nodes and the thumbnail and table view sharing an ExplorerManager. IconView seemed to change EM so that it did not allow lower levels to be selected. + COLLAPSE, // two levels. Keywords on top, files on bottom. + DETAIL // not currently used, but seems like it has three levels of nodes }; private List keywords; From ebb7c2e28a911ce0049486b250e647515b6bb87d Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Thu, 12 Sep 2013 16:13:38 -0400 Subject: [PATCH 4/4] Added comment about needing package name to be same as NBM name --- Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java index 5c7a504af1..69701ac033 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java @@ -475,6 +475,9 @@ public final class IngestModuleLoader { for (final ModuleInfo moduleInfo : moduleInfos) { if (moduleInfo.isEnabled()) { + /* NOTE: We have an assumption here that the modules in an NBM will + * have the same package name as the NBM name. This means that + * an NBM can have only one package with modules in it. */ String basePackageName = moduleInfo.getCodeNameBase(); // skip the standard ones