diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form index 4759f9b5d9..a8f4017e03 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.form @@ -1,4 +1,4 @@ - +
@@ -20,7 +20,7 @@ - + @@ -32,10 +32,10 @@ - - - - + + + + @@ -47,6 +47,15 @@ + + + + + + + + + @@ -68,6 +77,9 @@ + + + diff --git a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index c92deeca35..86b5e330c1 100644 --- a/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/CoreComponents/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Component; import java.io.IOException; import java.util.Arrays; +import java.util.concurrent.CancellationException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.BoxLayout; @@ -45,18 +46,20 @@ import org.sleuthkit.datamodel.TskData; * * @author dfickling */ -@ServiceProvider(service = DataContentViewer.class, position=5) +@ServiceProvider(service = DataContentViewer.class, position = 5) public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer { - private static final String[] IMAGES = new String[]{ ".jpg", ".jpeg", ".png", ".gif", ".jpe", ".bmp"}; - private static final String[] VIDEOS = new String[]{ ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg"}; - private static final String[] AUDIOS = new String[]{ ".mp3", ".wav", ".wma"}; + private static final String[] IMAGES = new String[]{".jpg", ".jpeg", ".png", ".gif", ".jpe", ".bmp"}; + private static final String[] VIDEOS = new String[]{".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg"}; + private static final String[] AUDIOS = new String[]{".mp3", ".wav", ".wma"}; private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName()); - private VideoComponent videoComponent; + private VideoComponent videoComponent; private PlayBin2 playbin2; private File currentFile; private long durationMillis = 0; private boolean autoTracking = false; // true if the slider is moving automatically + private final Object playbinLock = new Object(); // lock for synchronization of playbin2 player + /** * Creates new form DataContentViewerVideo */ @@ -64,24 +67,28 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo initComponents(); customizeComponents(); } - + private void customizeComponents() { Gst.init(); progressSlider.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent e) { - int time = progressSlider.getValue(); - if(playbin2 != null && !autoTracking) { + /** + * Should always try to synchronize any call to + * progressSlider.setValue() to avoid a different thread changing + * playbin while stateChanged() is processing + */ + @Override + public void stateChanged(ChangeEvent e) { + int time = progressSlider.getValue(); + synchronized (playbinLock) { + if (playbin2 != null && !autoTracking) { State orig = playbin2.getState(); playbin2.pause(); - playbin2.getState(); playbin2.seek(ClockTime.fromMillis(time)); playbin2.setState(orig); } } - - }); + } + }); } /** @@ -99,6 +106,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo progressLabel = new javax.swing.JLabel(); pauseButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.pauseButton.text")); // NOI18N + pauseButton.setMaximumSize(new java.awt.Dimension(45, 23)); + pauseButton.setMinimumSize(new java.awt.Dimension(45, 23)); + pauseButton.setPreferredSize(new java.awt.Dimension(45, 23)); pauseButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pauseButtonActionPerformed(evt); @@ -116,6 +126,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo .addGap(0, 242, Short.MAX_VALUE) ); + progressSlider.setValue(0); + progressLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.progressLabel.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); @@ -124,9 +136,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addComponent(pauseButton) + .addComponent(pauseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE) + .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(progressLabel) .addContainerGap()) @@ -136,26 +148,30 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(pauseButton) - .addComponent(progressLabel) - .addComponent(progressSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(pauseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) ); }// //GEN-END:initComponents private void pauseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseButtonActionPerformed - if(playbin2.getState().equals(State.PLAYING)){ - playbin2.pause(); - pauseButton.setText("►"); - } else if(playbin2.getState().equals(State.PAUSED)) { - playbin2.play(); - pauseButton.setText("||"); - } else { - ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile)); - em.execute(); + synchronized (playbinLock) { + State state = playbin2.getState(); + if (state.equals(State.PLAYING)) { + playbin2.pause(); + pauseButton.setText("►"); + playbin2.setState(State.PAUSED); + } else if (state.equals(State.PAUSED)) { + playbin2.play(); + pauseButton.setText("||"); + playbin2.setState(State.PLAYING); + } else if (state.equals(State.READY)) { + ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile)); + em.execute(); + } } }//GEN-LAST:event_pauseButtonActionPerformed - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton pauseButton; private javax.swing.JLabel progressLabel; @@ -165,48 +181,93 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo @Override public void setNode(Node selectedNode) { - pauseButton.setText("►"); - if(selectedNode == null) { - setDataView(null); + reset(); + setComponentsVisibility(false); + if (selectedNode == null) { return; } + File file = selectedNode.getLookup().lookup(File.class); - setDataView(file); - if(file == null) { + if (file == null) { return; } - boolean isVidOrAud = containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS); - pauseButton.setVisible(isVidOrAud); - progressLabel.setVisible(isVidOrAud); - progressSlider.setVisible(isVidOrAud); + + currentFile = file; + if (containsExt(file.getName(), IMAGES)) { + showImage(file); + } else if (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS)) { + setupVideo(file); + } } - private void setDataView(File file) { - if(file == null) { - setComponentsVisibility(false); - return; - } else { - setComponentsVisibility(true); - } - this.currentFile = file; - - if (containsExt(file.getName(), IMAGES)) { - java.io.File ioFile = getJFile(file); - if (!ioFile.exists()) { - try { - ContentUtils.writeToFile(file, ioFile); - } catch (IOException ex) { - logger.log(Level.WARNING, "Error buffering file", ex); - } + /** + * Initialize vars and display the image on the panel. + * + * @param file + */ + private void showImage(File file) { + java.io.File ioFile = getJFile(file); + if (!ioFile.exists()) { + try { + ContentUtils.writeToFile(file, ioFile); + } catch (IOException ex) { + logger.log(Level.WARNING, "Error buffering file", ex); } + } + + videoComponent = new VideoComponent(); + synchronized (playbinLock) { + playbin2 = new PlayBin2("ImageViewer"); + playbin2.setVideoSink(videoComponent.getElement()); + } + + videoPanel.removeAll(); + videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS)); + videoPanel.add(videoComponent); + videoPanel.revalidate(); + videoPanel.repaint(); + + synchronized (playbinLock) { playbin2.setInputFile(ioFile); playbin2.play(); } + videoPanel.setVisible(true); } + + /** + * Initialize all the necessary vars to play a video/audio file. + * + * @param file the File to play + */ + private void setupVideo(File file) { + java.io.File ioFile = getJFile(file); + + pauseButton.setText("►"); + progressSlider.setValue(0); + + videoComponent = new VideoComponent(); + synchronized (playbinLock) { + playbin2 = new PlayBin2("VideoPlayer"); + playbin2.setVideoSink(videoComponent.getElement()); + } + + videoPanel.removeAll(); + videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS)); + videoPanel.add(videoComponent); + videoPanel.revalidate(); + videoPanel.repaint(); + + synchronized (playbinLock) { + playbin2.setInputFile(ioFile); + playbin2.setState(State.READY); + } + setComponentsVisibility(true); + } + /** * To set the visibility of specific components in this class. * - * @param isVisible whether to show or hide the specific components + * @param isVisible whether to show or hide the specific components */ private void setComponentsVisibility(boolean isVisible) { pauseButton.setVisible(isVisible); @@ -237,42 +298,31 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo @Override public void resetComponent() { + // we don't want this to do anything + // because we already reset on each selected node } - - private void resetVideo() { - if(playbin2 != null) { - if(playbin2.isPlaying()) { - playbin2.stop(); + + private void reset() { + synchronized (playbinLock) { + if (playbin2 != null) { + if (playbin2.isPlaying()) { + playbin2.stop(); + } + playbin2.setState(State.NULL); +// try { +// Thread.sleep(20); // gstreamer needs to catch up +// } catch (InterruptedException ex) { } + if (playbin2.getState().equals(State.NULL)) { + playbin2.dispose(); + } + playbin2 = null; } - playbin2.setState(State.NULL); - if(playbin2.getState() == State.NULL) { - playbin2.dispose(); - } - playbin2 = null; - } - - videoComponent = null; - - playbin2 = new PlayBin2("VideoPlayer"); - videoComponent = new VideoComponent(); - playbin2.setVideoSink(videoComponent.getElement()); - - videoPanel.removeAll(); - videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS)); - videoPanel.add(videoComponent); - videoPanel.revalidate(); - videoPanel.repaint(); - } - - private void stopVideo() { - if(playbin2 != null && playbin2.isPlaying()) { - playbin2.stop(); + videoComponent = null; } } @Override public boolean isSupported(Node node) { - stopVideo(); if (node == null) { return false; } @@ -285,30 +335,29 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo if (File.dirFlagToValue(file.getDir_flags()).equals(TskData.TSK_FS_NAME_FLAG_ENUM.TSK_FS_NAME_FLAG_UNALLOC.toString())) { return false; } - - if(file.getSize() == 0) { + + if (file.getSize() == 0) { return false; } String name = file.getName().toLowerCase(); - - if(containsExt(name, IMAGES) || containsExt(name, AUDIOS) || containsExt(name, VIDEOS)) { - resetVideo(); + + if (containsExt(name, IMAGES) || containsExt(name, AUDIOS) || containsExt(name, VIDEOS)) { return true; } - + return false; } @Override public int isPreferred(Node node, boolean isSupported) { - if(isSupported) { + if (isSupported) { return 7; } else { return 0; } } - + private static boolean containsExt(String name, String[] exts) { int extStart = name.lastIndexOf("."); String ext = ""; @@ -317,7 +366,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } return Arrays.asList(exts).contains(ext); } - + private java.io.File getJFile(File file) { // Get the temp folder path of the case String tempPath = Case.getCurrentCase().getTempDirectory(); @@ -332,19 +381,23 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo java.io.File tempFile = new java.io.File(tempPath); return tempFile; } - + /* Thread that extracts and plays a file */ - private class ExtractMedia extends SwingWorker { + private class ExtractMedia extends SwingWorker { private ProgressHandle progress; boolean success = false; private File sFile; private java.io.File jFile; - - ExtractMedia(org.sleuthkit.datamodel.File sFile, java.io.File jFile){ + String duration; + String position; + + ExtractMedia(org.sleuthkit.datamodel.File sFile, java.io.File jFile) { this.sFile = sFile; this.jFile = jFile; - }; + } + + ; @Override protected Object doInBackground() throws Exception { @@ -357,9 +410,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo }); progressLabel.setText("Buffering..."); progress.start(); - progress.switchToIndeterminate(); + progress.switchToDeterminate(100); try { - ContentUtils.writeToFile(sFile, jFile); + ContentUtils.writeToFile(sFile, jFile, progress, this, true); } catch (IOException ex) { logger.log(Level.WARNING, "Error buffering file", ex); } @@ -370,9 +423,19 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo /* clean up or start the worker threads */ @Override protected void done() { - progress.finish(); - if (success) { - play(); + try { + super.get(); //block and get all exceptions thrown while doInBackground() + } catch (CancellationException ex) { + logger.log(Level.INFO, "Media buffering was canceled."); + } catch (InterruptedException ex) { + logger.log(Level.INFO, "Media buffering was interrupted."); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Fatal error during media buffering.", ex); + } finally { + progress.finish(); + if (!this.isCancelled()) { + play(); + } } } @@ -381,34 +444,49 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo progressLabel.setText("Error buffering file"); return; } - playbin2.setInputFile(jFile); - playbin2.play(); // must play, then pause and get state to get duration. - playbin2.pause(); - playbin2.getState(); - String duration = playbin2.queryDuration().toString(); - durationMillis = playbin2.queryDuration().toMillis(); - progressSlider.setMaximum((int)durationMillis); + ClockTime dur = null; + synchronized (playbinLock) { + playbin2.play(); // must play, then pause and get state to get duration. + playbin2.pause(); + playbin2.getState(); + dur = playbin2.queryDuration(); + } + duration = dur.toString(); + durationMillis = dur.toMillis(); + + progressSlider.setMaximum((int) durationMillis); progressSlider.setMinimum(0); final String finalDuration; - if(duration.length() == 8 && duration.substring(0,3).equals("00:")) { + if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { finalDuration = duration.substring(3); progressLabel.setText("00:00/" + duration); } else { finalDuration = duration; progressLabel.setText("00:00:00/" + duration); } - playbin2.play(); + synchronized (playbinLock) { + playbin2.play(); + } pauseButton.setText("||"); new Thread(new Runnable() { + private boolean isPlayBinReady() { + synchronized (playbinLock) { + return playbin2 != null && !playbin2.getState().equals(State.NULL); + } + } @Override public void run() { long positionMillis = 0; while (positionMillis < durationMillis - && playbin2 != null - && !playbin2.getState().equals(State.NULL)) { - String position = playbin2.queryPosition().toString(); - positionMillis = playbin2.queryPosition().toMillis(); + && isPlayBinReady() ) { + ClockTime pos = null; + synchronized (playbinLock) { + pos = playbin2.queryPosition(); + } + position = pos.toString(); + positionMillis = pos.toMillis(); + if (position.length() == 8) { position = position.substring(3); } @@ -426,13 +504,22 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } else { progressLabel.setText("00:00:00/" + finalDuration); } - if (playbin2 != null) { - playbin2.stop(); - playbin2.getState(); - pauseButton.setText("►"); - progressSlider.setValue(0); + // If it reached the end + if (progressSlider.getValue() == progressSlider.getMaximum()) { + restartVideo(); } } + + public void restartVideo() { + synchronized (playbinLock) { + if (playbin2 != null) { + playbin2.stop(); + playbin2.setState(State.READY); // ready to be played again + } + } + pauseButton.setText("►"); + progressSlider.setValue(0); + } }).start(); } } diff --git a/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 398a85ae26..48c71eb89c 100644 --- a/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -64,7 +64,7 @@ import org.sleuthkit.autopsy.datamodel.Views; import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent; -import org.sleuthkit.autopsy.ingest.ServiceDataEvent; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; @@ -685,7 +685,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } if (changed.equals(IngestModuleEvent.DATA.toString())) { - final ServiceDataEvent event = (ServiceDataEvent) oldValue; + final ModuleDataEvent event = (ModuleDataEvent) oldValue; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { diff --git a/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestService.java b/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java similarity index 82% rename from ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestService.java rename to ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java index 7df81dabee..5194f343ee 100644 --- a/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestService.java +++ b/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java @@ -32,11 +32,12 @@ import java.util.Collection; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; -import org.sleuthkit.autopsy.ingest.IngestManagerProxy; +import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; -import org.sleuthkit.autopsy.ingest.IngestServiceAbstract; -import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstract; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile; +import org.sleuthkit.autopsy.ingest.IngestModuleInit; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -51,29 +52,31 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; * Ingests an image file and, if available, adds it's date, latitude, longitude, * altitude, device model, and device make to a blackboard artifact. */ -public final class ExifParserFileIngestService implements IngestServiceAbstractFile { +public final class ExifParserFileIngestModule implements IngestModuleAbstractFile { + private IngestServices services; + final String MODULE_NAME = "Exif Parser"; - private static final Logger logger = Logger.getLogger(ExifParserFileIngestService.class.getName()); - private static ExifParserFileIngestService defaultInstance = null; - private IngestManagerProxy managerProxy; + private static final Logger logger = Logger.getLogger(ExifParserFileIngestModule.class.getName()); + private static ExifParserFileIngestModule defaultInstance = null; private static int messageId = 0; - //file ingest services require a private constructor + //file ingest modules require a private constructor //to ensure singleton instances - private ExifParserFileIngestService() { + private ExifParserFileIngestModule() { + } - //default instance used for service registration - public static synchronized ExifParserFileIngestService getDefault() { + //default instance used for module registration + public static synchronized ExifParserFileIngestModule getDefault() { if (defaultInstance == null) { - defaultInstance = new ExifParserFileIngestService(); + defaultInstance = new ExifParserFileIngestModule(); } return defaultInstance; } @Override - public IngestServiceAbstractFile.ProcessResult process(AbstractFile content) { + public IngestModuleAbstractFile.ProcessResult process(AbstractFile content) { if(content.getType().equals(TSK_DB_FILES_TYPE_ENUM.FS)) { FsContent fsContent = (FsContent) content; if(fsContent.isFile()) { @@ -83,10 +86,10 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF } } - return IngestServiceAbstractFile.ProcessResult.UNKNOWN; + return IngestModuleAbstractFile.ProcessResult.UNKNOWN; } - public IngestServiceAbstractFile.ProcessResult processFile(FsContent f) { + public IngestModuleAbstractFile.ProcessResult processFile(FsContent f) { InputStream in = null; BufferedInputStream bin = null; @@ -144,10 +147,10 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF bba.addAttributes(attributes); } - return IngestServiceAbstractFile.ProcessResult.OK; + return IngestModuleAbstractFile.ProcessResult.OK; } catch (TskCoreException ex) { - Logger.getLogger(ExifParserFileIngestService.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(ExifParserFileIngestModule.class.getName()).log(Level.SEVERE, null, ex); } catch (ImageProcessingException ex) { logger.log(Level.WARNING, "Failed to process the image.", ex); } catch (IOException ex) { @@ -162,7 +165,7 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF } // If we got here, there was an error - return IngestServiceAbstractFile.ProcessResult.ERROR; + return IngestModuleAbstractFile.ProcessResult.ERROR; } private boolean parsableFormat(FsContent f) { @@ -185,9 +188,9 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF logger.log(Level.INFO, "completed exif parsing " + this.toString()); final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete"); - managerProxy.postMessage(msg); + services.postMessage(msg); - //service specific cleanup due to completion here + //module specific cleanup due to completion here } @Override @@ -201,23 +204,23 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF } @Override - public void init(IngestManagerProxy managerProxy) { + public void init(IngestModuleInit initContext) { + services = IngestServices.getDefault(); logger.log(Level.INFO, "init() " + this.toString()); - this.managerProxy = managerProxy; } @Override public void stop() { logger.log(Level.INFO, "stop()"); - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped")); + services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped")); - //service specific cleanup due to interruption here + //module specific cleanup due to interruption here } @Override - public IngestServiceAbstract.ServiceType getType() { - return IngestServiceAbstract.ServiceType.AbstractFile; + public IngestModuleAbstract.ModuleType getType() { + return IngestModuleAbstract.ModuleType.AbstractFile; } @Override diff --git a/ExifParser/src/org/sleuthkit/autopsy/exifparser/layer.xml b/ExifParser/src/org/sleuthkit/autopsy/exifparser/layer.xml index 67b03b3564..c8fa4fd8aa 100644 --- a/ExifParser/src/org/sleuthkit/autopsy/exifparser/layer.xml +++ b/ExifParser/src/org/sleuthkit/autopsy/exifparser/layer.xml @@ -2,10 +2,10 @@ - - - + + + - \ No newline at end of file + diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java similarity index 81% rename from HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java rename to HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java index c7fc428a6a..7aed58ea4b 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java @@ -25,11 +25,11 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.ingest.IngestManager; -import org.sleuthkit.autopsy.ingest.IngestManagerProxy; +import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestMessage; -import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile; -import org.sleuthkit.autopsy.ingest.ServiceDataEvent; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile; +import org.sleuthkit.autopsy.ingest.IngestModuleInit; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -44,14 +44,14 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskException; -public class HashDbIngestService implements IngestServiceAbstractFile { +public class HashDbIngestModule implements IngestModuleAbstractFile { - private static HashDbIngestService instance = null; + private static HashDbIngestModule instance = null; public final static String MODULE_NAME = "Hash Lookup"; public final static String MODULE_DESCRIPTION = "Identifies known and notables files using supplied hash databases, such as a standard NSRL database."; - private static final Logger logger = Logger.getLogger(HashDbIngestService.class.getName()); + private static final Logger logger = Logger.getLogger(HashDbIngestModule.class.getName()); private Processor processor = new Processor(); - private IngestManagerProxy managerProxy; + private IngestServices services; private SleuthkitCase skCase; private static int messageId = 0; private int count; @@ -66,29 +66,24 @@ public class HashDbIngestService implements IngestServiceAbstractFile { private Map knownBadSets = new HashMap(); - private HashDbIngestService() { + private HashDbIngestModule() { count = 0; } - public static synchronized HashDbIngestService getDefault() { + public static synchronized HashDbIngestModule getDefault() { if (instance == null) { - instance = new HashDbIngestService(); + instance = new HashDbIngestModule(); } return instance; } - /** - * notification from manager that brand new processing should be initiated. - * Service loads its configuration and performs initialization - * - * @param managerProxy handle to the manager to postMessage() to - */ + @Override - public void init(IngestManagerProxy managerProxy) { + public void init(IngestModuleInit initContext) { + services = IngestServices.getDefault(); HashDbManagementPanel.getDefault().setIngestRunning(true); HashDbSimplePanel.setIngestRunning(true); - this.managerProxy = managerProxy; - this.managerProxy.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Started")); + this.services.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Started")); this.skCase = Case.getCurrentCase().getSleuthkitCase(); try { HashDbXML hdbxml = HashDbXML.getCurrent(); @@ -116,10 +111,10 @@ public class HashDbIngestService implements IngestServiceAbstractFile { } if (!nsrlIsSet) { - this.managerProxy.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No NSRL database set", "Known file search will not be executed.")); + this.services.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No NSRL database set", "Known file search will not be executed.")); } if (!knownBadIsSet) { - this.managerProxy.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No known bad database set", "Known bad file search will not be executed.")); + this.services.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No known bad database set", "Known bad file search will not be executed.")); } } catch (TskException ex) { @@ -127,10 +122,7 @@ public class HashDbIngestService implements IngestServiceAbstractFile { } } - /** - * notification from manager that there is no more content to process and all work is done. - * Service performs any clean-up, notifies viewers and may also write results to the black-board - */ + @Override public void complete() { StringBuilder detailsSb = new StringBuilder(); @@ -156,7 +148,7 @@ public class HashDbIngestService implements IngestServiceAbstractFile { } detailsSb.append(""); - managerProxy.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Hash Ingest Complete", detailsSb.toString())); + services.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Hash Ingest Complete", detailsSb.toString())); HashDbManagementPanel.getDefault().setIngestRunning(false); HashDbSimplePanel.setIngestRunning(false); @@ -173,9 +165,9 @@ public class HashDbIngestService implements IngestServiceAbstractFile { } /** - * get specific name of the service - * should be unique across services, a user-friendly name of the service shown in GUI - * @return The name of this Ingest Service + * get specific name of the module + * should be unique across modules, a user-friendly name of the module shown in GUI + * @return The name of this Ingest Module */ @Override public String getName() { @@ -199,8 +191,8 @@ public class HashDbIngestService implements IngestServiceAbstractFile { } @Override - public ServiceType getType() { - return ServiceType.AbstractFile; + public ModuleType getType() { + return ModuleType.AbstractFile; } @Override @@ -266,13 +258,13 @@ public class HashDbIngestService implements IngestServiceAbstractFile { detailsSb.append(""); - managerProxy.postMessage(IngestMessage.createDataMessage(++messageId, this, + services.postMessage(IngestMessage.createDataMessage(++messageId, this, "Notable: " + abstractFile.getName(), detailsSb.toString(), abstractFile.getName() + md5Hash, badFile)); } - IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_HASHSET_HIT, Collections.singletonList(badFile))); + services.fireModuleDataEvent(new ModuleDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_HASHSET_HIT, Collections.singletonList(badFile))); } catch (TskException ex) { logger.log(Level.WARNING, "Error creating blackboard artifact", ex); } @@ -293,11 +285,10 @@ public class HashDbIngestService implements IngestServiceAbstractFile { private ProcessResult process(FsContent fsContent) { - ProcessResult ret = ProcessResult.UNKNOWN; + ProcessResult ret = ProcessResult.OK; boolean processFile = true; if (fsContent.getSize() == 0 || fsContent.getKnown().equals(TskData.FileKnown.BAD)) { - ret = ProcessResult.OK; processFile = false; } if (processFile && (nsrlIsSet || knownBadIsSet)) { @@ -322,7 +313,6 @@ public class HashDbIngestService implements IngestServiceAbstractFile { String hashSetName = entry.getValue().getName(); processBadFile(fsContent, md5Hash, hashSetName, entry.getValue().getShowInboxMessages()); } - ret = ProcessResult.OK; } if (!foundBad && nsrlIsSet) { long lookupstart = System.currentTimeMillis(); @@ -330,17 +320,16 @@ public class HashDbIngestService implements IngestServiceAbstractFile { lookuptime += (System.currentTimeMillis()-lookupstart); if (status.equals(TskData.FileKnown.KNOWN)) { skCase.setKnown(fsContent, status); - ret = ProcessResult.COND_STOP; } } } catch (TskException ex) { logger.log(Level.WARNING, "Couldn't analyze file " + name + " - see sleuthkit log for details", ex); - managerProxy.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestService.this, "Hash Lookup Error: " + name, + services.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestModule.this, "Hash Lookup Error: " + name, "Error encountered while updating the hash values for " + name + ".")); ret = ProcessResult.ERROR; } catch (IOException ex) { logger.log(Level.WARNING, "Error reading file " + name, ex); - managerProxy.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestService.this, "Read Error: " + name, + services.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestModule.this, "Read Error: " + name, "Error encountered while calculating the hash value for " + name + ".")); ret = ProcessResult.ERROR; } @@ -357,7 +346,7 @@ public class HashDbIngestService implements IngestServiceAbstractFile { } catch (IOException ex) { logger.log(Level.WARNING, "Error reading file " + name, ex); - managerProxy.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestService.this, "Read Error: " + name, + services.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestModule.this, "Read Error: " + name, "Error encountered while calculating the hash value for " + name + " without databases.")); } } diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/layer.xml b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/layer.xml index bb8f30f38c..28e9ac47ff 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/layer.xml +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/layer.xml @@ -40,9 +40,9 @@ - - - + + + diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties index 99d6f07eec..28d381ebd3 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -7,14 +7,14 @@ HINT_IngestTopComponent=Ingest window OpenIDE-Module-Name=Ingest IngestTopComponent.messageFrame.title=Messages IngestTopComponent.ingestProgressLabel.text=File Ingest Progress -IngestControlPanel.topLable.text=Image ingest services +IngestControlPanel.topLable.text=Image ingest modules IngestControlPanel.startButton.text=Start -IngestDialogPanel.ingestServicesLabel.text=Image Ingest Services +IngestDialogPanel.ingestServicesLabel.text=Image Ingest Modules IngestDialogForm2.okButton.text=OK IngestDialogForm2.cancelButton.text=Cancel IngestDialogForm.cancelButton.text=Cancel IngestDialogForm.startButton.text=Start -IngestDialogForm.jLabel1.text=Ingest Services +IngestDialogForm.jLabel1.text=Ingest Modules IngestTopComponent.refreshFreqLabel.text=Refresh frequency IngestMessageDetailsPanel.backButton.text= IngestMessageDetailsPanel.viewArtifactButton.text=Go to Result diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.form b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.form index c66e78dca8..1ed953087e 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.form +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.form @@ -28,7 +28,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -58,7 +58,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -180,17 +180,10 @@ - - - - - - - - - - - + + + + diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java index e5440189aa..1cc0419ecd 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java @@ -44,15 +44,15 @@ import org.sleuthkit.autopsy.ingest.IngestManager.UpdateFrequency; import org.sleuthkit.datamodel.Image; /** - * main configuration panel for all ingest services, reusable JPanel component + * main configuration panel for all ingest modules, reusable JPanel component */ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfigurator { private IngestManager manager = null; - private List services; - private IngestServiceAbstract currentService; - private Map serviceStates; - private ServicesTableModel tableModel; + private List modules; + private IngestModuleAbstract currentModule; + private Map moduleStates; + private ModulesTableModel tableModel; private static final Logger logger = Logger.getLogger(IngestDialogPanel.class.getName()); // The image that's just been added to the database private Image image; @@ -60,9 +60,9 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi /** Creates new form IngestDialogPanel */ private IngestDialogPanel() { - tableModel = new ServicesTableModel(); - services = new ArrayList(); - serviceStates = new HashMap(); + tableModel = new ModulesTableModel(); + modules = new ArrayList(); + moduleStates = new HashMap(); initComponents(); customizeComponents(); } @@ -75,15 +75,15 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi } private void customizeComponents() { - servicesTable.setModel(tableModel); + modulesTable.setModel(tableModel); this.manager = IngestManager.getDefault(); - Collection imageServices = IngestManager.enumerateImageServices(); - for (final IngestServiceImage service : imageServices) { - addService(service); + Collection imageModules = IngestManager.enumerateImageModules(); + for (final IngestModuleImage module : imageModules) { + addModule(module); } - Collection fsServices = IngestManager.enumerateAbstractFileServices(); - for (final IngestServiceAbstractFile service : fsServices) { - addService(service); + Collection fsModules = IngestManager.enumerateAbstractFileModules(); + for (final IngestModuleAbstractFile module : fsModules) { + addModule(module); } //time setting @@ -113,17 +113,17 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi // } - servicesTable.setTableHeader(null); - servicesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + modulesTable.setTableHeader(null); + modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //custom renderer for tooltips - ServiceTableRenderer renderer = new ServiceTableRenderer(); + ModulesTableRenderer renderer = new ModulesTableRenderer(); //customize column witdhs - final int width = servicesScrollPane.getPreferredSize().width; + final int width = modulesScrollPane.getPreferredSize().width; TableColumn column = null; - for (int i = 0; i < servicesTable.getColumnCount(); i++) { - column = servicesTable.getColumnModel().getColumn(i); + for (int i = 0; i < modulesTable.getColumnCount(); i++) { + column = modulesTable.getColumnModel().getColumn(i); if (i == 0) { column.setPreferredWidth(((int) (width * 0.15))); } else { @@ -132,7 +132,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi } } - servicesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + modulesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { @@ -140,11 +140,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi if (!listSelectionModel.isSelectionEmpty()) { save(); int index = listSelectionModel.getMinSelectionIndex(); - currentService = services.get(index); + currentModule = modules.get(index); reloadSimpleConfiguration(); - advancedButton.setEnabled(currentService.hasAdvancedConfiguration()); + advancedButton.setEnabled(currentModule.hasAdvancedConfiguration()); } else { - currentService = null; + currentModule = null; } } }); @@ -176,10 +176,10 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi } } - private void addService(IngestServiceAbstract service) { - final String serviceName = service.getName(); - services.add(service); - serviceStates.put(serviceName, true); + private void addModule(IngestModuleAbstract module) { + final String moduleName = module.getName(); + modules.add(module); + moduleStates.put(moduleName, true); } /** This method is called from within the constructor to @@ -192,8 +192,8 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi private void initComponents() { timeGroup = new javax.swing.ButtonGroup(); - servicesScrollPane = new javax.swing.JScrollPane(); - servicesTable = new javax.swing.JTable(); + modulesScrollPane = new javax.swing.JScrollPane(); + modulesTable = new javax.swing.JTable(); jPanel1 = new javax.swing.JPanel(); advancedButton = new javax.swing.JButton(); jSeparator2 = new javax.swing.JSeparator(); @@ -209,11 +209,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi setPreferredSize(new java.awt.Dimension(522, 257)); - servicesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160))); - servicesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160)); + modulesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160))); + modulesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160)); - servicesTable.setBackground(new java.awt.Color(240, 240, 240)); - servicesTable.setModel(new javax.swing.table.DefaultTableModel( + modulesTable.setBackground(new java.awt.Color(240, 240, 240)); + modulesTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { }, @@ -221,9 +221,9 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi } )); - servicesTable.setShowHorizontalLines(false); - servicesTable.setShowVerticalLines(false); - servicesScrollPane.setViewportView(servicesTable); + modulesTable.setShowHorizontalLines(false); + modulesTable.setShowVerticalLines(false); + modulesScrollPane.setViewportView(modulesTable); jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160))); jPanel1.setPreferredSize(new java.awt.Dimension(338, 257)); @@ -290,14 +290,10 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi .addGroup(timePanelLayout.createSequentialGroup() .addContainerGap() .addGroup(timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(timePanelLayout.createSequentialGroup() - .addGap(0, 0, 0) - .addComponent(timeRadioButton1)) - .addGroup(timePanelLayout.createSequentialGroup() - .addGroup(timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(timeLabel) - .addComponent(timeRadioButton2) - .addComponent(timeRadioButton3)))) + .addComponent(timeRadioButton1) + .addComponent(timeLabel) + .addComponent(timeRadioButton2) + .addComponent(timeRadioButton3)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); timePanelLayout.setVerticalGroup( @@ -347,7 +343,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(servicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(timePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(processUnallocPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -361,7 +357,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addComponent(servicesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(processUnallocPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -377,11 +373,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi @Override public void actionPerformed(ActionEvent e) { dialog.close(); - currentService.saveAdvancedConfiguration(); + currentModule.saveAdvancedConfiguration(); reloadSimpleConfiguration(); } }); - dialog.display(currentService.getAdvancedConfiguration()); + dialog.display(currentModule.getAdvancedConfiguration()); }//GEN-LAST:event_advancedButtonActionPerformed private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton1ActionPerformed @@ -397,10 +393,10 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JSeparator jSeparator2; + private javax.swing.JScrollPane modulesScrollPane; + private javax.swing.JTable modulesTable; private javax.swing.JCheckBox processUnallocCheckbox; private javax.swing.JPanel processUnallocPanel; - private javax.swing.JScrollPane servicesScrollPane; - private javax.swing.JTable servicesTable; private javax.swing.JPanel simplePanel; private javax.swing.ButtonGroup timeGroup; private javax.swing.JLabel timeLabel; @@ -410,11 +406,11 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// private javax.swing.JRadioButton timeRadioButton3; // End of variables declaration//GEN-END:variables - private class ServicesTableModel extends AbstractTableModel { + private class ModulesTableModel extends AbstractTableModel { @Override public int getRowCount() { - return services.size(); + return modules.size(); } @Override @@ -424,9 +420,9 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// @Override public Object getValueAt(int rowIndex, int columnIndex) { - String name = services.get(rowIndex).getName(); + String name = modules.get(rowIndex).getName(); if (columnIndex == 0) { - return serviceStates.get(name); + return moduleStates.get(name); } else { return name; } @@ -440,7 +436,7 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (columnIndex == 0) { - serviceStates.put((String) getValueAt(rowIndex, 1), (Boolean) aValue); + moduleStates.put((String) getValueAt(rowIndex, 1), (Boolean) aValue); } } @@ -451,15 +447,15 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// } } - List getServicesToStart() { - List servicesToStart = new ArrayList(); - for (IngestServiceAbstract service : services) { - boolean serviceEnabled = serviceStates.get(service.getName()); - if (serviceEnabled) { - servicesToStart.add(service); + List getModulesToStart() { + List modulesToStart = new ArrayList(); + for (IngestModuleAbstract module : modules) { + boolean moduleEnabled = moduleStates.get(module.getName()); + if (moduleEnabled) { + modulesToStart.add(module); } } - return servicesToStart; + return modulesToStart; } private boolean timeSelectionEnabled() { @@ -482,8 +478,8 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// private void reloadSimpleConfiguration() { simplePanel.removeAll(); - if (currentService.hasSimpleConfiguration()) { - simplePanel.add(currentService.getSimpleConfiguration()); + if (currentModule.hasSimpleConfiguration()) { + simplePanel.add(currentModule.getSimpleConfiguration()); } simplePanel.revalidate(); simplePanel.repaint(); @@ -495,8 +491,8 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// */ @Override public void save() { - if (currentService != null && currentService.hasSimpleConfiguration()) { - currentService.saveSimpleConfiguration(); + if (currentModule != null && currentModule.hasSimpleConfiguration()) { + currentModule.saveSimpleConfiguration(); } } @@ -512,11 +508,11 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// @Override public void start() { - //pick the services - List servicesToStart = getServicesToStart(); + //pick the modules + List modulesToStart = getModulesToStart(); - if (!servicesToStart.isEmpty()) { - manager.execute(servicesToStart, image); + if (!modulesToStart.isEmpty()) { + manager.execute(modulesToStart, image); } //update ingest freq. refresh @@ -537,9 +533,9 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// /** - * Custom cell renderer for tooltips with service description + * Custom cell renderer for tooltips with module description */ - private class ServiceTableRenderer extends DefaultTableCellRenderer { + private class ModulesTableRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent( @@ -550,10 +546,10 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {// super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (column == 1) { - //String serviceName = (String) table.getModel().getValueAt(row, column); - IngestServiceAbstract service = services.get(row); - String serviceDescr = service.getDescription(); - setToolTipText(serviceDescr); + //String moduleName = (String) table.getModel().getValueAt(row, column); + IngestModuleAbstract module = modules.get(row); + String moduleDescr = module.getDescription(); + setToolTipText(moduleDescr); } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageThread.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageThread.java index 6dc856df47..9934aff955 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageThread.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageThread.java @@ -31,42 +31,42 @@ import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent; import org.sleuthkit.datamodel.Image; /** - * worker for every ingest image service there is a separate instance per image - * / service pair + * worker for every ingest image module there is a separate instance per image + * / module pair */ public class IngestImageThread extends SwingWorker { private Logger logger = Logger.getLogger(IngestImageThread.class.getName()); private ProgressHandle progress; private Image image; - private IngestServiceImage service; + private IngestModuleImage module; private IngestImageWorkerController controller; private IngestManager manager; - IngestImageThread(IngestManager manager, Image image, IngestServiceImage service) { + IngestImageThread(IngestManager manager, Image image, IngestModuleImage module) { this.manager = manager; this.image = image; - this.service = service; + this.module = module; } Image getImage() { return image; } - IngestServiceImage getService() { - return service; + IngestModuleImage getModule() { + return module; } @Override protected Object doInBackground() throws Exception { - logger.log(Level.INFO, "Starting processing of service: " + service.getName()); + logger.log(Level.INFO, "Starting processing of module: " + module.getName()); - final String displayName = service.getName() + " image id:" + image.getId(); + final String displayName = module.getName() + " image id:" + image.getId(); progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override public boolean cancel() { - logger.log(Level.INFO, "Image ingest service " + service.getName() + " cancelled by user."); + logger.log(Level.INFO, "Image ingest module " + module.getName() + " cancelled by user."); if (progress != null) { progress.setDisplayName(displayName + " (Cancelling...)"); } @@ -80,18 +80,18 @@ public class IngestImageThread extends SwingWorker { controller = new IngestImageWorkerController(this, progress); if (isCancelled()) { - logger.log(Level.INFO, "Terminating image ingest service " + service.getName() + " due to cancellation."); + logger.log(Level.INFO, "Terminating image ingest module " + module.getName() + " due to cancellation."); return null; } final StopWatch timer = new StopWatch(); timer.start(); try { - service.process(image, controller); + module.process(image, controller); } catch (Exception e) { - logger.log(Level.WARNING, "Exception in service: " + service.getName() + " image: " + image.getName(), e); + logger.log(Level.WARNING, "Exception in module: " + module.getName() + " image: " + image.getName(), e); } finally { timer.stop(); - logger.log(Level.INFO, "Done processing of service: " + service.getName() + logger.log(Level.INFO, "Done processing of module: " + module.getName() + " took " + timer.getElapsedTimeSecs() + " secs. to process()" ); EventQueue.invokeLater(new Runnable() { @@ -102,27 +102,27 @@ public class IngestImageThread extends SwingWorker { }); - //cleanup queues (worker and image/service) + //cleanup queues (worker and image/module) manager.removeImageIngestWorker(this); if (!this.isCancelled()) { - logger.log(Level.INFO, "Service " + service.getName() + " completed"); + logger.log(Level.INFO, "Module " + module.getName() + " completed"); try { - service.complete(); + module.complete(); } catch (Exception e) { - logger.log(Level.INFO, "Error completing the service " + service.getName(), e); + logger.log(Level.INFO, "Error completing the module " + module.getName(), e); } - IngestManager.fireServiceEvent(IngestModuleEvent.COMPLETED.toString(), service.getName()); + IngestManager.fireModuleEvent(IngestModuleEvent.COMPLETED.toString(), module.getName()); } else { - logger.log(Level.INFO, "Service " + service.getName() + " stopped"); + logger.log(Level.INFO, "Module " + module.getName() + " stopped"); try { - service.stop(); + module.stop(); } catch (Exception e) { - logger.log(Level.INFO, "Error stopping the service" + service.getName(), e); + logger.log(Level.INFO, "Error stopping the module" + module.getName(), e); } - IngestManager.fireServiceEvent(IngestModuleEvent.STOPPED.toString(), service.getName()); + IngestManager.fireModuleEvent(IngestModuleEvent.STOPPED.toString(), module.getName()); } } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageWorkerController.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageWorkerController.java index 0e7dbd7c21..cc3c217e93 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageWorkerController.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestImageWorkerController.java @@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.ingest; import org.netbeans.api.progress.ProgressHandle; /** - * Controller for image level ingest services - * Used by services to check task status and to post progress to + * Controller for image level ingest modules + * Used by modules to check task status and to post progress to */ public class IngestImageWorkerController { @@ -40,8 +40,8 @@ public class IngestImageWorkerController { } /** - * Check if the task has been cancelled. This should be polled by the service periodically - * And the service needs to act, i.e. break out of its processing loop and call its stop() to cleanup + * Check if the task has been cancelled. This should be polled by the module periodically + * And the module needs to act, i.e. break out of its processing loop and call its stop() to cleanup * * @return true if the task has been cancelled, false otherwise */ @@ -70,7 +70,7 @@ public class IngestImageWorkerController { /** * Update the progress bar with the number of work units performed, if in the determinate mode - * @param workUnits number of work units performed so far by the service + * @param workUnits number of work units performed so far by the module */ public void progress(int workUnits) { if (progress != null) { diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 55d0d8107a..e238483858 100755 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2012 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,15 +50,18 @@ import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.TskData; /** - * IngestManager sets up and manages ingest services runs them in a background - * thread notifies services when work is complete or should be interrupted - * processes messages from services via messenger proxy and posts them to GUI. + * IngestManager sets up and manages ingest modules runs them in a background + * thread notifies modules when work is complete or should be interrupted + * processes messages from modules via messenger proxy and posts them to GUI. * * This runs as a singleton and you can access it using the getDefault() method. * */ public class IngestManager { + /** + * @Deprecated individual modules are be responsible for maintaining such settings + */ enum UpdateFrequency { FAST(20), @@ -66,10 +69,16 @@ public class IngestManager { SLOW(5); private final int time; + /** + * @Deprecated individual modules are be responsible for maintaining such settings + */ UpdateFrequency(int time) { this.time = time; } + /** + * @Deprecated individual modules are be responsible for maintaining such settings + */ int getTime() { return time; } @@ -79,20 +88,18 @@ public class IngestManager { private volatile UpdateFrequency updateFrequency = UpdateFrequency.AVG; private boolean processUnallocSpace = true; //queues - private final ImageQueue imageQueue = new ImageQueue(); // list of services and images to analyze + private final ImageQueue imageQueue = new ImageQueue(); // list of modules and images to analyze private final AbstractFileQueue abstractFileQueue = new AbstractFileQueue(); private final Object queuesLock = new Object(); //workers private IngestAbstractFileThread abstractFileIngester; private List imageIngesters; private SwingWorker queueWorker; - //services - private final List imageServices = enumerateImageServices(); - private final List abstractFileServices = enumerateAbstractFileServices(); - // service return values - private final Map abstractFileServiceResults = new HashMap(); - //manager proxy - final IngestManagerProxy managerProxy = new IngestManagerProxy(this); + //modules + private List imageModules; + private final List abstractFileModules; + // module return values + private final Map abstractFileModulesRetValues = new HashMap(); //notifications private final static PropertyChangeSupport pcs = new PropertyChangeSupport(IngestManager.class); //monitor @@ -128,20 +135,32 @@ public class IngestManager { STOPPED, /** * Event sent when ingest module has new data. Second argument of the - * property change fired contains ServiceDataEvent object and third + * property change fired contains ModuleDataEvent object and third * argument is null. The object can contain encapsulated new data - * created by the service. Listener can also query new data as needed. + * created by the module. Listener can also query new data as needed. * */ DATA }; //ui - private IngestUI ui = null; + //Initialized by Installer in AWT thread once the Window System is ready + private volatile IngestUI ui; // = null; //IngestMessageTopComponent.findInstance(); //singleton - private static IngestManager instance; + private static volatile IngestManager instance; private IngestManager() { imageIngesters = new ArrayList(); + abstractFileModules = enumerateAbstractFileModules(); + imageModules = enumerateImageModules(); + } + + /** + * called by Installer in AWT thread once the Window System is ready + */ + void initUI() { + if (this.ui == null) { + this.ui = IngestMessageTopComponent.findInstance(); + } } /** @@ -157,9 +176,6 @@ public class IngestManager { return instance; } - void initUI() { - ui = IngestMessageTopComponent.findInstance(); - } /** * Add property change listener to listen to ingest events @@ -170,78 +186,80 @@ public class IngestManager { pcs.addPropertyChangeListener(l); } - static synchronized void fireServiceEvent(String eventType, String serviceName) { - pcs.firePropertyChange(eventType, serviceName, null); + static synchronized void fireModuleEvent(String eventType, String moduleName) { + pcs.firePropertyChange(eventType, moduleName, null); } - static synchronized void fireServiceDataEvent(ServiceDataEvent serviceDataEvent) { - pcs.firePropertyChange(IngestModuleEvent.DATA.toString(), serviceDataEvent, null); + static synchronized void fireModuleDataEvent(ModuleDataEvent moduleDataEvent) { + pcs.firePropertyChange(IngestModuleEvent.DATA.toString(), moduleDataEvent, null); } /** * Returns the return value from a previously run module on the file being - * curently analyzed. + * currently analyzed. * - * @param serviceName Name of module. + * @param moduleName Name of module. * @returns Return value from that module if it was previously run. */ - IngestServiceAbstractFile.ProcessResult getAbstractFileServiceResult(String serviceName) { - synchronized (abstractFileServiceResults) { - if (abstractFileServiceResults.containsKey(serviceName)) { - return abstractFileServiceResults.get(serviceName); + IngestModuleAbstractFile.ProcessResult getAbstractFileModuleResult(String moduleName) { + synchronized (abstractFileModulesRetValues) { + if (abstractFileModulesRetValues.containsKey(moduleName)) { + return abstractFileModulesRetValues.get(moduleName); } else { - return IngestServiceAbstractFile.ProcessResult.UNKNOWN; + return IngestModuleAbstractFile.ProcessResult.UNKNOWN; } } } /** * Multiple image version of execute, enqueues multiple images and - * associated services at once + * associated modules at once * - * @param services services to execute on every image - * @param images images to execute services on + * @param modules modules to execute on every image + * @param images images to execute modules on */ - void execute(final List services, final List images) { - logger.log(Level.INFO, "Will enqueue number of images: " + images.size() + " to " + services.size() + " services."); + void execute(final List modules, final List images) { + logger.log(Level.INFO, "Will enqueue number of images: " + images.size() + " to " + modules.size() + " modules."); - if (!isIngestRunning()) { + if (!isIngestRunning() && ui != null) { ui.clearMessages(); } - queueWorker = new EnqueueWorker(services, images); + queueWorker = new EnqueueWorker(modules, images); queueWorker.execute(); - ui.restoreMessages(); + if (ui != null) { + ui.restoreMessages(); + } //logger.log(Level.INFO, "Queues: " + imageQueue.toString() + " " + AbstractFileQueue.toString()); } /** * IngestManager entry point, enqueues image to be processed. Spawns * background thread which enumerates all sorted files and executes chosen - * services per file in a pre-determined order. Notifies services when work + * modules per file in a pre-determined order. Notifies modules when work * is complete or should be interrupted using complete() and stop() calls. * Does not block and can be called multiple times to enqueue more work to * already running background process. * - * @param services services to execute on the image - * @param image image to execute services on + * @param modules modules to execute on the image + * @param image image to execute modules on */ - void execute(final List services, final Image image) { + void execute(final List modules, final Image image) { List images = new ArrayList(); images.add(image); logger.log(Level.INFO, "Will enqueue image: " + image.getName()); - execute(services, images); + execute(modules, images); } /** * Starts the needed worker threads. * - * if AbstractFile service is still running, do nothing and allow it to + * if AbstractFile module is still running, do nothing and allow it to * consume queue otherwise start /restart AbstractFile worker * - * image workers run per (service,image). Check if one for the - * (service,image) is already running otherwise start/restart the worker + * image workers run per (module,image). Check if one for the + * (module,image) is already running otherwise start/restart the worker */ private synchronized void startAll() { logger.log(Level.INFO, "Image queue: " + this.imageQueue.toString()); @@ -255,38 +273,38 @@ public class IngestManager { // cycle through each image in the queue while (hasNextImage()) { //dequeue - // get next image and set of services - final Map.Entry> qu = + // get next image and set of modules + final Map.Entry> qu = this.getNextImage(); - // check if each service for this image is already running + // check if each module for this image is already running //synchronized (this) { - for (IngestServiceImage quService : qu.getValue()) { + for (IngestModuleImage quModule : qu.getValue()) { boolean alreadyRunning = false; for (IngestImageThread worker : imageIngesters) { // ignore threads that are on different images if (!worker.getImage().equals(qu.getKey())) { continue; //check next worker } - //same image, check service (by name, not id, since different instances) - if (worker.getService().getName().equals(quService.getName())) { + //same image, check module (by name, not id, since different instances) + if (worker.getModule().getName().equals(quModule.getName())) { alreadyRunning = true; - logger.log(Level.INFO, "Image Ingester <" + qu.getKey() + ", " + quService.getName() + "> is already running"); + logger.log(Level.INFO, "Image Ingester <" + qu.getKey() + ", " + quModule.getName() + "> is already running"); break; } } //checked all workers if (alreadyRunning == false) { - logger.log(Level.INFO, "Starting new image Ingester <" + qu.getKey() + ", " + quService.getName() + ">"); - IngestImageThread newImageWorker = new IngestImageThread(this, qu.getKey(), quService); + logger.log(Level.INFO, "Starting new image Ingester <" + qu.getKey() + ", " + quModule.getName() + ">"); + IngestImageThread newImageWorker = new IngestImageThread(this, qu.getKey(), quModule); imageIngesters.add(newImageWorker); - //image services are now initialized per instance - quService.init(managerProxy); + //image modules are now initialized per instance + quModule.init(new IngestModuleInit() ); newImageWorker.execute(); - IngestManager.fireServiceEvent(IngestModuleEvent.STARTED.toString(), quService.getName()); + IngestManager.fireModuleEvent(IngestModuleEvent.STARTED.toString(), quModule.getName()); } } } @@ -312,9 +330,9 @@ public class IngestManager { if (startAbstractFileIngester) { stats = new IngestManagerStats(); abstractFileIngester = new IngestAbstractFileThread(); - //init all fs services, everytime new worker starts - for (IngestServiceAbstractFile s : abstractFileServices) { - s.init(managerProxy); + //init all fs modules, everytime new worker starts + for (IngestModuleAbstractFile s : abstractFileModules) { + s.init(new IngestModuleInit() ); } abstractFileIngester.execute(); } @@ -334,15 +352,15 @@ public class IngestManager { emptyAbstractFiles(); emptyImages(); - //stop service workers + //stop module workers if (abstractFileIngester != null) { - //send signals to all file services - for (IngestServiceAbstractFile s : this.abstractFileServices) { - if (isServiceRunning(s)) { + //send signals to all file modules + for (IngestModuleAbstractFile s : this.abstractFileModules) { + if (isModuleRunning(s)) { try { s.stop(); } catch (Exception e) { - logger.log(Level.WARNING, "Exception while stopping service: " + s.getName(), e); + logger.log(Level.WARNING, "Exception while stopping module: " + s.getName(), e); } } @@ -361,20 +379,20 @@ public class IngestManager { for (IngestImageThread imageWorker : toStop) { - IngestServiceImage s = imageWorker.getService(); + IngestModuleImage s = imageWorker.getModule(); //stop the worker thread if thread is running boolean cancelled = imageWorker.cancel(true); if (!cancelled) { - logger.log(Level.INFO, "Unable to cancel image ingest worker for service: " + imageWorker.getService().getName() + " img: " + imageWorker.getImage().getName()); + logger.log(Level.INFO, "Unable to cancel image ingest worker for module: " + imageWorker.getModule().getName() + " img: " + imageWorker.getImage().getName()); } - //stop notification to service to cleanup resources - if (isServiceRunning(s)) { + //stop notification to module to cleanup resources + if (isModuleRunning(s)) { try { - imageWorker.getService().stop(); + imageWorker.getModule().stop(); } catch (Exception e) { - logger.log(Level.WARNING, "Exception while stopping service: " + s.getName(), e); + logger.log(Level.WARNING, "Exception while stopping module: " + s.getName(), e); } } @@ -402,18 +420,18 @@ public class IngestManager { } /** - * Test is any file ingest services are running. + * Test is any file ingest modules are running. * - * @return true if any ingest services are running, false otherwise + * @return true if any ingest modules are running, false otherwise */ - public synchronized boolean areServicesRunning() { - for (IngestServiceAbstract serv : abstractFileServices) { + public synchronized boolean areModulesRunning() { + for (IngestModuleAbstract serv : abstractFileModules) { if(serv.hasBackgroundJobsRunning()) { return true; } } for (IngestImageThread thread : imageIngesters) { - if(isServiceRunning(thread.getService())) { + if(isModuleRunning(thread.getModule())) { return false; } } @@ -464,34 +482,34 @@ public class IngestManager { } /** - * check if the service is running (was started and not yet + * check if the module is running (was started and not yet * complete/stopped) give a complete answer, i.e. it's already consumed all * files but it might have background threads running * */ - public boolean isServiceRunning(final IngestServiceAbstract service) { + public boolean isModuleRunning(final IngestModuleAbstract module) { - if (service.getType() == IngestServiceAbstract.ServiceType.AbstractFile) { + if (module.getType() == IngestModuleAbstract.ModuleType.AbstractFile) { synchronized (queuesLock) { - if (abstractFileQueue.hasServiceEnqueued((IngestServiceAbstractFile) service)) { + if (abstractFileQueue.hasModuleEnqueued((IngestModuleAbstractFile) module)) { //has work enqueued, so running return true; } else { //not in the queue, but could still have bkg work running - return service.hasBackgroundJobsRunning(); + return module.hasBackgroundJobsRunning(); } } } else { - //image service + //image module synchronized (this) { if (imageIngesters.isEmpty()) { return false; } IngestImageThread imt = null; for (IngestImageThread ii : imageIngesters) { - if (ii.getService().equals(service)) { + if (ii.getModule().equals(module)) { imt = ii; break; } @@ -514,7 +532,7 @@ public class IngestManager { } /** - * returns the current minimal update frequency setting in minutes Services + * returns the current minimal update frequency setting in minutes Modules * should call this at init() to get current setting and use the setting to * change notification and data refresh intervals */ @@ -523,7 +541,7 @@ public class IngestManager { } /** - * set new minimal update frequency services should use + * set new minimal update frequency modules should use * * @param frequency to use in minutes */ @@ -557,9 +575,9 @@ public class IngestManager { } /** - * Service publishes message using InegestManager handle Does not block. The + * Module publishes message using InegestManager handle Does not block. The * message gets enqueued in the GUI thread and displayed in a widget - * IngestService should make an attempt not to publish the same message + * IngestModule should make an attempt not to publish the same message * multiple times. Viewer will attempt to identify duplicate messages and * filter them out (slower) */ @@ -571,66 +589,68 @@ public class IngestManager { stats.addError(message.getSource()); } } - ui.displayMessage(message); + if (ui != null) { + ui.displayMessage(message); + } } /** - * helper to return all image services managed (using Lookup API) sorted in + * helper to return all image modules managed (using Lookup API) sorted in * Lookup position order */ - public static List enumerateImageServices() { - List ret = new ArrayList(); - for (IngestServiceImage list : Lookup.getDefault().lookupAll(IngestServiceImage.class)) { + public static List enumerateImageModules() { + List ret = new ArrayList(); + for (IngestModuleImage list : Lookup.getDefault().lookupAll(IngestModuleImage.class)) { ret.add(list); } return ret; } /** - * helper to return all file/dir services managed (using Lookup API) sorted + * helper to return all file/dir modules managed (using Lookup API) sorted * in Lookup position order */ - public static List enumerateAbstractFileServices() { - List ret = new ArrayList(); - for (IngestServiceAbstractFile list : Lookup.getDefault().lookupAll(IngestServiceAbstractFile.class)) { + public static List enumerateAbstractFileModules() { + List ret = new ArrayList(); + for (IngestModuleAbstractFile list : Lookup.getDefault().lookupAll(IngestModuleAbstractFile.class)) { ret.add(list); } return ret; } /** - * Queue up an image to be processed by a given service. + * Queue up an image to be processed by a given module. * - * @param service Service to analyze image + * @param module Module to analyze image * @param image Image to analyze */ - private void addImage(IngestServiceImage service, Image image) { + private void addImage(IngestModuleImage module, Image image) { synchronized (queuesLock) { - imageQueue.enqueue(image, service); + imageQueue.enqueue(image, module); } } /** - * Queue up an image to be processed by a given File service. + * Queue up an image to be processed by a given File module. * - * @param service service for which to enqueue the files + * @param module module for which to enqueue the files * @param abstractFiles files to enqueue */ - private void addAbstractFile(IngestServiceAbstractFile service, Collection abstractFiles) { + private void addAbstractFile(IngestModuleAbstractFile module, Collection abstractFiles) { synchronized (queuesLock) { for (AbstractFile abstractFile : abstractFiles) { - abstractFileQueue.enqueue(abstractFile, service); + abstractFileQueue.enqueue(abstractFile, module); } } } /** - * get next file/dir and associated list of services to process the queue of + * get next file/dir and associated list of modules to process the queue of * AbstractFile to process is maintained internally and could be dynamically * sorted as data comes in */ - private Map.Entry> getNextAbstractFile() { - Map.Entry> ret = null; + private Map.Entry> getNextAbstractFile() { + Map.Entry> ret = null; synchronized (queuesLock) { ret = abstractFileQueue.dequeue(); } @@ -666,11 +686,11 @@ public class IngestManager { } /** - * get next Image/Service pair to process the queue of Images to process is + * get next Image/Module pair to process the queue of Images to process is * maintained internally and could be dynamically sorted as data comes in */ - private Map.Entry> getNextImage() { - Map.Entry> ret = null; + private Map.Entry> getNextImage() { + Map.Entry> ret = null; synchronized (queuesLock) { ret = imageQueue.dequeue(); } @@ -767,7 +787,7 @@ public class IngestManager { /** * manages queue of pending AbstractFile and list of associated - * IngestServiceAbstractFile to use on that content sorted based on + * IngestModuleAbstractFile to use on that content sorted based on * AbstractFilePriotity */ private class AbstractFileQueue { @@ -785,26 +805,26 @@ public class IngestManager { } }; - final TreeMap> AbstractFileUnits = new TreeMap>(sorter); + final TreeMap> AbstractFileUnits = new TreeMap>(sorter); - void enqueue(AbstractFile AbstractFile, IngestServiceAbstractFile service) { - //AbstractFileUnits.put(AbstractFile, Collections.singletonList(service)); - List services = AbstractFileUnits.get(AbstractFile); - if (services == null) { - services = new ArrayList(); - AbstractFileUnits.put(AbstractFile, services); + void enqueue(AbstractFile AbstractFile, IngestModuleAbstractFile module) { + //AbstractFileUnits.put(AbstractFile, Collections.singletonList(module)); + List modules = AbstractFileUnits.get(AbstractFile); + if (modules == null) { + modules = new ArrayList(); + AbstractFileUnits.put(AbstractFile, modules); } - services.add(service); + modules.add(module); } - void enqueue(AbstractFile AbstractFile, List services) { + void enqueue(AbstractFile AbstractFile, List modules) { - List oldServices = AbstractFileUnits.get(AbstractFile); - if (oldServices == null) { - oldServices = new ArrayList(); - AbstractFileUnits.put(AbstractFile, oldServices); + List oldModules = AbstractFileUnits.get(AbstractFile); + if (oldModules == null) { + oldModules = new ArrayList(); + AbstractFileUnits.put(AbstractFile, oldModules); } - oldServices.addAll(services); + oldModules.addAll(modules); } boolean hasNext() { @@ -820,11 +840,11 @@ public class IngestManager { } /** - * Returns next AbstractFile and list of associated services + * Returns next AbstractFile and list of associated modules * * @return */ - Map.Entry> dequeue() { + Map.Entry> dequeue() { if (!hasNext()) { throw new UnsupportedOperationException("AbstractFile processing queue is empty"); } @@ -834,14 +854,14 @@ public class IngestManager { } /** - * checks if the service has any work enqueued + * checks if the module has any work enqueued * - * @param service to check for - * @return true if the service is enqueued to do work + * @param module to check for + * @return true if the module is enqueued to do work */ - boolean hasServiceEnqueued(IngestServiceAbstractFile service) { - for (List list : AbstractFileUnits.values()) { - if (list.contains(service)) { + boolean hasModuleEnqueued(IngestModuleAbstractFile module) { + for (List list : AbstractFileUnits.values()) { + if (list.contains(module)) { return true; } } @@ -855,7 +875,7 @@ public class IngestManager { public String printQueue() { StringBuilder sb = new StringBuilder(); - /*for (QueueUnit u : AbstractFileUnits) { + /*for (QueueUnit u : AbstractFileUnits) { sb.append(u.toString()); sb.append("\n"); }*/ @@ -864,9 +884,9 @@ public class IngestManager { } /** - * manages queue of pending Images and IngestServiceImage to use on that - * image. image / service pairs are added one at a time and internally, it - * keeps track of all services for a given image. + * manages queue of pending Images and IngestModuleImage to use on that + * image. image / module pairs are added one at a time and internally, it + * keeps track of all modules for a given image. */ private class ImageQueue { @@ -877,24 +897,24 @@ public class IngestManager { } }; - private TreeMap> imageUnits = new TreeMap>(sorter); + private TreeMap> imageUnits = new TreeMap>(sorter); - void enqueue(Image image, IngestServiceImage service) { - List services = imageUnits.get(image); - if (services == null) { - services = new ArrayList(); - imageUnits.put(image, services); + void enqueue(Image image, IngestModuleImage module) { + List modules = imageUnits.get(image); + if (modules == null) { + modules = new ArrayList(); + imageUnits.put(image, modules); } - services.add(service); + modules.add(module); } - void enqueue(Image image, List services) { - List oldServices = imageUnits.get(image); - if (oldServices == null) { - oldServices = new ArrayList(); - imageUnits.put(image, oldServices); + void enqueue(Image image, List modules) { + List oldModules = imageUnits.get(image); + if (oldModules == null) { + oldModules = new ArrayList(); + imageUnits.put(image, oldModules); } - oldServices.addAll(services); + oldModules.addAll(modules); } boolean hasNext() { @@ -910,12 +930,12 @@ public class IngestManager { } /** - * Return a QueueUnit that contains an image and set of services to run + * Return a QueueUnit that contains an image and set of modules to run * on it. * * @return */ - Map.Entry> dequeue() { + Map.Entry> dequeue() { if (!hasNext()) { throw new UnsupportedOperationException("Image processing queue is empty"); } @@ -937,55 +957,55 @@ public class IngestManager { private Date startTime; private Date endTime; private int errorsTotal; - private Map errors; + private Map errors; private final DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private final StopWatch timer = new StopWatch(); - private IngestServiceAbstract currentServiceForTimer; - //file service timing stats, image service timers are logged in IngestImageThread class - private final Map fileServiceTimers = new HashMap(); + private IngestModuleAbstract currentModuleForTimer; + //file module timing stats, image module timers are logged in IngestImageThread class + private final Map fileModuleTimers = new HashMap(); IngestManagerStats() { - errors = new HashMap(); + errors = new HashMap(); } /** - * records start time of the file process for the service must be - * followed by logFileServiceEndProcess for the same service + * records start time of the file process for the module must be + * followed by logFileModuleEndProcess for the same module * - * @param service to record start time for processing a file + * @param module to record start time for processing a file */ - void logFileServiceStartProcess(IngestServiceAbstract service) { + void logFileModuleStartProcess(IngestModuleAbstract module) { timer.reset(); timer.start(); - currentServiceForTimer = service; + currentModuleForTimer = module; } /** - * records stop time of the file process for the service must be - * preceded by logFileServiceStartProcess for the same service + * records stop time of the file process for the module must be + * preceded by logFileModuleStartProcess for the same module * - * @param service to record stop time for processing a file + * @param module to record stop time for processing a file */ - void logFileServiceEndProcess(IngestServiceAbstract service) { + void logFileModuleEndProcess(IngestModuleAbstract module) { timer.stop(); - if (service != currentServiceForTimer) { - logger.log(Level.WARNING, "Invalid service passed in to record stop processing: " + service.getName() - + ", expected: " + currentServiceForTimer.getName()); + if (module != currentModuleForTimer) { + logger.log(Level.WARNING, "Invalid module passed in to record stop processing: " + module.getName() + + ", expected: " + currentModuleForTimer.getName()); } else { final long elapsed = timer.getElapsedTime(); - final long current = fileServiceTimers.get(service.getName()); - fileServiceTimers.put(service.getName(), elapsed + current); + final long current = fileModuleTimers.get(module.getName()); + fileModuleTimers.put(module.getName(), elapsed + current); } - currentServiceForTimer = null; + currentModuleForTimer = null; } - String getFileServiceStats() { + String getFileModuleStats() { StringBuilder sb = new StringBuilder(); - for (final String serviceName : fileServiceTimers.keySet()) { - sb.append(serviceName).append(" took: ") - .append(fileServiceTimers.get(serviceName) / 1000) + for (final String moduleName : fileModuleTimers.keySet()) { + sb.append(moduleName).append(" took: ") + .append(fileModuleTimers.get(moduleName) / 1000) .append(" secs. to process()").append('\n'); } return sb.toString(); @@ -1004,10 +1024,10 @@ public class IngestManager { sb.append("Total ingest time: ").append(getTotalTimeString()).append(EOL); sb.append("Total errors: ").append(errorsTotal).append(EOL); if (errorsTotal > 0) { - sb.append("Errors per service:"); - for (IngestServiceAbstract service : errors.keySet()) { - final int errorsService = errors.get(service); - sb.append("\t").append(service.getName()).append(": ").append(errorsService).append(EOL); + sb.append("Errors per module:"); + for (IngestModuleAbstract module : errors.keySet()) { + final int errorsModule = errors.get(module); + sb.append("\t").append(module.getName()).append(": ").append(errorsModule).append(EOL); } } return sb.toString(); @@ -1021,10 +1041,10 @@ public class IngestManager { sb.append("Total errors: ").append(errorsTotal).append("
"); /* if (errorsTotal > 0) { - sb.append("Errors per service:"); - for (IngestServiceAbstract service : errors.keySet()) { - final int errorsService = errors.get(service); - sb.append("\t").append(service.getName()).append(": ").append(errorsService).append("
"); + sb.append("Errors per module:"); + for (IngestModuleAbstract module : errors.keySet()) { + final int errorsModule = errors.get(module); + sb.append("\t").append(module.getName()).append(": ").append(errorsModule).append("
"); } } * */ @@ -1036,8 +1056,8 @@ public class IngestManager { void start() { startTime = new Date(); - for (IngestServiceAbstractFile service : abstractFileServices) { - fileServiceTimers.put(service.getName(), 0L); + for (IngestModuleAbstractFile module : abstractFileModules) { + fileModuleTimers.put(module.getName(), 0L); } } @@ -1072,13 +1092,13 @@ public class IngestManager { return sb.toString(); } - synchronized void addError(IngestServiceAbstract source) { + synchronized void addError(IngestModuleAbstract source) { ++errorsTotal; - Integer curServiceErrorI = errors.get(source); - if (curServiceErrorI == null) { + Integer curModuleErrorI = errors.get(source); + if (curModuleErrorI == null) { errors.put(source, 1); } else { - errors.put(source, curServiceErrorI + 1); + errors.put(source, curModuleErrorI + 1); } } } @@ -1097,9 +1117,9 @@ public class IngestManager { logger.log(Level.INFO, "Starting background processing"); stats.start(); - //notify main thread services started - for (IngestServiceAbstractFile s : abstractFileServices) { - IngestManager.fireServiceEvent(IngestModuleEvent.STARTED.toString(), s.getName()); + //notify main thread modules started + for (IngestModuleAbstractFile s : abstractFileModules) { + IngestManager.fireModuleEvent(IngestModuleEvent.STARTED.toString(), s.getName()); } final String displayName = "File Ingest"; @@ -1121,18 +1141,18 @@ public class IngestManager { int processedFiles = 0; //process AbstractFiles queue while (hasNextAbstractFile()) { - Map.Entry> unit = getNextAbstractFile(); - //clear return values from services for last file - synchronized (abstractFileServiceResults) { - abstractFileServiceResults.clear(); + Map.Entry> unit = getNextAbstractFile(); + //clear return values from modules for last file + synchronized (abstractFileModulesRetValues) { + abstractFileModulesRetValues.clear(); } final AbstractFile fileToProcess = unit.getKey(); progress.progress(fileToProcess.getName(), processedFiles); - for (IngestServiceAbstractFile service : unit.getValue()) { - //process the file with every file service + for (IngestModuleAbstractFile module : unit.getValue()) { + //process the file with every file module if (isCancelled()) { logger.log(Level.INFO, "Terminating file ingest due to cancellation."); return null; @@ -1140,23 +1160,18 @@ public class IngestManager { try { - stats.logFileServiceStartProcess(service); - IngestServiceAbstractFile.ProcessResult result = service.process(fileToProcess); - stats.logFileServiceEndProcess(service); - //handle unconditional stop - if (result == IngestServiceAbstractFile.ProcessResult.STOP) { - break; - //will skip other services and start to process next file - } + stats.logFileModuleStartProcess(module); + IngestModuleAbstractFile.ProcessResult result = module.process(fileToProcess); + stats.logFileModuleEndProcess(module); - //store the result for subsequent services for this file - synchronized (abstractFileServiceResults) { - abstractFileServiceResults.put(service.getName(), result); + //store the result for subsequent modules for this file + synchronized (abstractFileModulesRetValues) { + abstractFileModulesRetValues.put(module.getName(), result); } } catch (Exception e) { - logger.log(Level.WARNING, "Exception from service: " + service.getName(), e); - stats.addError(service); + logger.log(Level.WARNING, "Exception from module: " + module.getName(), e); + stats.addError(module); } } int newAbstractFiles = getNumAbstractFiles(); @@ -1177,11 +1192,11 @@ public class IngestManager { protected void done() { try { super.get(); //block and get all exceptions thrown while doInBackground() - //notify services of completion + //notify modules of completion if (!this.isCancelled()) { - for (IngestServiceAbstractFile s : abstractFileServices) { + for (IngestModuleAbstractFile s : abstractFileModules) { s.complete(); - IngestManager.fireServiceEvent(IngestModuleEvent.COMPLETED.toString(), s.getName()); + IngestManager.fireModuleEvent(IngestModuleEvent.COMPLETED.toString(), s.getName()); } } @@ -1204,9 +1219,11 @@ public class IngestManager { if (!this.isCancelled()) { logger.log(Level.INFO, "Summary Report: " + stats.toString()); - logger.log(Level.INFO, "File service timings: " + stats.getFileServiceStats()); - logger.log(Level.INFO, "Ingest messages count: " + ui.getMessagesCount()); - //ui.displayReport(stats.toHtmlString()); + logger.log(Level.INFO, "File module timings: " + stats.getFileModuleStats()); + if (ui != null) { + logger.log(Level.INFO, "Ingest messages count: " + ui.getMessagesCount()); + } + IngestManager.this.postMessage(IngestMessage.createManagerMessage("File Ingest Complete", stats.toHtmlString())); } } @@ -1214,30 +1231,30 @@ public class IngestManager { } private void handleInterruption() { - for (IngestServiceAbstractFile s : abstractFileServices) { - if (isServiceRunning(s)) { + for (IngestModuleAbstractFile s : abstractFileModules) { + if (isModuleRunning(s)) { try { s.stop(); } catch (Exception e) { - logger.log(Level.WARNING, "Exception while stopping service: " + s.getName(), e); + logger.log(Level.WARNING, "Exception while stopping module: " + s.getName(), e); } } - IngestManager.fireServiceEvent(IngestModuleEvent.STOPPED.toString(), s.getName()); + IngestManager.fireModuleEvent(IngestModuleEvent.STOPPED.toString(), s.getName()); } //empty queues emptyAbstractFiles(); } } - /* Thread that adds image/file and service pairs to queues */ + /* Thread that adds image/file and module pairs to queues */ private class EnqueueWorker extends SwingWorker { - List services; + List modules; final List images; int total; - EnqueueWorker(final List services, final List images) { - this.services = services; + EnqueueWorker(final List modules, final List images) { + this.modules = modules; this.images = images; } private ProgressHandle progress; @@ -1257,10 +1274,10 @@ public class IngestManager { } }); - total = services.size() * images.size(); + total = modules.size() * images.size(); progress.start(total); //progress.switchToIndeterminate(); - queueAll(services, images); + queueAll(modules, images); return null; } @@ -1294,32 +1311,32 @@ public class IngestManager { } } - private void queueAll(List services, final List images) { + private void queueAll(List modules, final List images) { int processed = 0; for (Image image : images) { final String imageName = image.getName(); Collection files = null; - for (IngestServiceAbstract service : services) { + for (IngestModuleAbstract module : modules) { if (isCancelled()) { logger.log(Level.INFO, "Terminating ingest queueing due to cancellation."); return; } - final String serviceName = service.getName(); - progress.progress(serviceName + " " + imageName, processed); - switch (service.getType()) { + final String moduleName = module.getName(); + progress.progress(moduleName + " " + imageName, processed); + switch (module.getType()) { case Image: - //enqueue a new instance of image service + //enqueue a new instance of image module try { - final IngestServiceImage newServiceInstance = (IngestServiceImage) (service.getClass()).newInstance(); - addImage(newServiceInstance, image); - logger.log(Level.INFO, "Added image " + image.getName() + " with service " + service.getName()); + final IngestModuleImage newModuleInstance = (IngestModuleImage) (module.getClass()).newInstance(); + addImage(newModuleInstance, image); + logger.log(Level.INFO, "Added image " + image.getName() + " with module " + module.getName()); } catch (InstantiationException e) { - logger.log(Level.SEVERE, "Cannot instantiate service: " + service.getName(), e); + logger.log(Level.SEVERE, "Cannot instantiate module: " + module.getName(), e); } catch (IllegalAccessException e) { - logger.log(Level.SEVERE, "Cannot instantiate service: " + service.getName(), e); + logger.log(Level.SEVERE, "Cannot instantiate module: " + module.getName(), e); } - //addImage((IngestServiceImage) service, image); + //addImage((IngestModuleImage) module, image); break; case AbstractFile: if (files == null) { @@ -1327,14 +1344,14 @@ public class IngestManager { files = new GetAllFilesContentVisitor(processUnallocSpace).visit(image); logger.info("Get all files took " + (System.currentTimeMillis() - start) + "ms"); } - //enqueue the same singleton AbstractFile service - logger.log(Level.INFO, "Adding image " + image.getName() + " with " + files.size() + " number of AbstractFile to service " + service.getName()); - addAbstractFile((IngestServiceAbstractFile) service, files); + //enqueue the same singleton AbstractFile module + logger.log(Level.INFO, "Adding image " + image.getName() + " with " + files.size() + " number of AbstractFile to module " + module.getName()); + addAbstractFile((IngestModuleAbstractFile) module, files); break; default: - logger.log(Level.SEVERE, "Unexpected service type: " + service.getType().name()); + logger.log(Level.SEVERE, "Unexpected module type: " + module.getType().name()); } - progress.progress(serviceName + " " + imageName, ++processed); + progress.progress(moduleName + " " + imageName, ++processed); } if (files != null) { files.clear(); diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManagerProxy.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManagerProxy.java deleted file mode 100644 index 145039b50a..0000000000 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManagerProxy.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 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.ingest; - - -/** - * Ingest manager facade used by ingest services - * - * Facility for services to interact with the ingest manager - * for sending data events, ingest messages, getting configuration, such as - * update frequency configuration - * - */ -public class IngestManagerProxy { - - private IngestManager manager; - - IngestManagerProxy(IngestManager manager) { - this.manager = manager; - } - - /** - * Post ingest message - * @param message ingest message to be posted by ingest service - */ - public void postMessage(final IngestMessage message) { - manager.postMessage(message); - } - - /** - * Fire service event to notify registered service event listeners - * @param eventType the event type, defined in IngestManager.IngestManagerEvents - * @param serviceName the service name - */ - public static void fireServiceEvent(String eventType, String serviceName) { - IngestManager.fireServiceEvent(eventType, serviceName); - } - - - /** - * Fire service data event to notify registered service data event listeners - * @param serviceDataEvent service data event, encapsulating blackboard artifact data - */ - public static void fireServiceDataEvent(ServiceDataEvent serviceDataEvent) { - IngestManager.fireServiceDataEvent(serviceDataEvent);; - } - - - /** - * Facility for the service to query the currently set recommended data update frequency in minutes - * Services that post data in controlled time intervals, should obey this setting - * - * @return max. number of minutes before service posts new data, if data is available - */ - public int getUpdateFrequency() { - return manager.getUpdateFrequency().getTime(); - } - - - /** - * Facility for a file ingest service to check a return value from another file ingest service - * that executed for the same file earlier in the file ingest pipeline - * The service return value can be used as a guideline to skip processing the file - * - * @param serviceName registered service name of the service to check the return value of - * @return the return value of the previously executed service for the currently processed file in the file ingest pipeline - */ - public IngestServiceAbstractFile.ProcessResult getAbstractFileServiceResult(String serviceName) { - return manager.getAbstractFileServiceResult(serviceName); - } - - - - - -} diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java index 46bdc12aa3..87b24efe3b 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java @@ -24,7 +24,7 @@ import org.sleuthkit.autopsy.datamodel.KeyValue; import org.sleuthkit.datamodel.BlackboardArtifact; /** - * Representation of subject posted by ingest services + * Representation of subject posted by ingest modules * * Message should have a unique ID within context of originating source * @@ -37,7 +37,7 @@ public class IngestMessage { }; private long ID; private MessageType messageType; - private IngestServiceAbstract source; + private IngestModuleAbstract source; private String subject; private String detailsHtml; private String uniqueKey; @@ -46,7 +46,7 @@ public class IngestMessage { private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static int managerMessageId = 0; - private IngestMessage(long ID, MessageType messageType, IngestServiceAbstract source, String subject, String detailsHtml, String uniqueKey) { + private IngestMessage(long ID, MessageType messageType, IngestModuleAbstract source, String subject, String detailsHtml, String uniqueKey) { this.ID = ID; this.source = source; this.messageType = messageType; @@ -63,7 +63,7 @@ public class IngestMessage { return ID; } - public IngestServiceAbstract getSource() { + public IngestModuleAbstract getSource() { return source; } @@ -163,12 +163,12 @@ public class IngestMessage { * Create a simple message with a subject only * @param ID ID of the message, unique in the context of module that generated it * @param messageType message type - * @param source originating service + * @param source originating module * @param subject message subject to be displayed * @param details message details to be displayed, or null * @return */ - public static IngestMessage createMessage(long ID, MessageType messageType, IngestServiceAbstract source, String subject, String details) { + public static IngestMessage createMessage(long ID, MessageType messageType, IngestModuleAbstract source, String subject, String details) { if (messageType == null || source == null || subject == null) { throw new IllegalArgumentException("message type, source and subject cannot be null"); } @@ -179,11 +179,11 @@ public class IngestMessage { * Create a simple message with a subject only * @param ID ID of the message, unique in the context of module that generated it * @param messageType message type - * @param source originating service + * @param source originating module * @param subject message subject to be displayed * @return */ - public static IngestMessage createMessage(long ID, MessageType messageType, IngestServiceAbstract source, String subject) { + public static IngestMessage createMessage(long ID, MessageType messageType, IngestModuleAbstract source, String subject) { return createMessage(ID, messageType, source, subject, null); } @@ -191,12 +191,12 @@ public class IngestMessage { /** * Create error message * @param ID ID of the message, unique in the context of module that generated it - * @param source originating service + * @param source originating module * @param subject message subject to be displayed * @param details message details to be displayed, or null * @return */ - public static IngestMessage createErrorMessage(long ID, IngestServiceAbstract source, String subject, String details) { + public static IngestMessage createErrorMessage(long ID, IngestModuleAbstract source, String subject, String details) { if (source == null || subject == null) { throw new IllegalArgumentException("source and subject cannot be null"); } @@ -206,12 +206,12 @@ public class IngestMessage { /** * Create warning message * @param ID ID of the message, unique in the context of module that generated it - * @param source originating service + * @param source originating module * @param subject message subject to be displayed * @param details message details to be displayed, or null * @return */ - public static IngestMessage createWarningMessage(long ID, IngestServiceAbstract source, String subject, String details) { + public static IngestMessage createWarningMessage(long ID, IngestModuleAbstract source, String subject, String details) { if (source == null || subject == null) { throw new IllegalArgumentException("source and subject cannot be null"); } @@ -221,14 +221,14 @@ public class IngestMessage { /** * * @param ID ID of the message, unique in the context of module that generated it - * @param source originating service + * @param source originating module * @param subject message subject to be displayed * @param detailsHtml html formatted detailed message (without leading and closing <html> tags), for instance, a human-readable representation of the data. * @param uniqueKey unique key determining uniqueness of the message, or null. Helps grouping similar messages and determine their importance. Subsequent messages with the same uniqueKey will be treated with lower priority. - * @param data data blackboard artifact associated with the message, the same as fired in ServiceDataEvent by the service + * @param data data blackboard artifact associated with the message, the same as fired in ModuleDataEvent by the module * @return */ - public static IngestMessage createDataMessage(long ID, IngestServiceAbstract source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data) { + public static IngestMessage createDataMessage(long ID, IngestModuleAbstract source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data) { if (source == null || subject == null || detailsHtml == null || data == null) { throw new IllegalArgumentException("source, subject, details and data cannot be null"); } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java index 7b178c6f3f..67c3475caf 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java @@ -45,7 +45,7 @@ import org.sleuthkit.autopsy.ingest.IngestMessage.*; import org.sleuthkit.datamodel.BlackboardArtifact; /** - * Notification window showing messages from services to user + * Notification window showing messages from modules to user * */ class IngestMessagePanel extends javax.swing.JPanel { @@ -62,7 +62,7 @@ class IngestMessagePanel extends javax.swing.JPanel { private enum COLUMN { - SUBJECT, COUNT, SERVICE + SUBJECT, COUNT, MODULE }; private static PropertyChangeSupport messagePcs = new PropertyChangeSupport(IngestMessagePanel.class); static final String MESSAGE_CHANGE_EVT = "MESSAGE_CHANGE_EVT"; //number of unread messages changed @@ -320,10 +320,10 @@ class IngestMessagePanel extends javax.swing.JPanel { //data private List messageData = new ArrayList(); - //for keeping track of messages to group, per service, by uniqness - private Map>> groupings = new HashMap>>(); + //for keeping track of messages to group, per module, by uniqness + private Map>> groupings = new HashMap>>(); private boolean chronoSort = true; //chronological sort default - private static final int MESSAGE_GROUP_THRESH = 3; //group messages after 3 messages per service with same uniqness + private static final int MESSAGE_GROUP_THRESH = 3; //group messages after 3 messages per module with same uniqness private Logger logger = Logger.getLogger(MessageTableModel.class.getName()); MessageTableModel() { @@ -331,12 +331,12 @@ class IngestMessagePanel extends javax.swing.JPanel { } private void init() { - //initialize groupings map with services - for (IngestServiceAbstract service : IngestManager.enumerateAbstractFileServices()) { - groupings.put(service, new HashMap>()); + //initialize groupings map with modules + for (IngestModuleAbstract module : IngestManager.enumerateAbstractFileModules()) { + groupings.put(module, new HashMap>()); } - for (IngestServiceAbstract service : IngestManager.enumerateImageServices()) { - groupings.put(service, new HashMap>()); + for (IngestModuleAbstract module : IngestManager.enumerateImageModules()) { + groupings.put(module, new HashMap>()); } } @@ -418,8 +418,8 @@ class IngestMessagePanel extends javax.swing.JPanel { switch (columnIndex) { case 0: - Object service = entry.messageGroup.getSource(); - if (service == null) { + Object module = entry.messageGroup.getSource(); + if (module == null) { ret = ""; } else { ret = (Object) entry.messageGroup.getSource().getName(); @@ -462,13 +462,13 @@ class IngestMessagePanel extends javax.swing.JPanel { } synchronized public void addMessage(IngestMessage m) { - //check how many messages per service with the same uniqness + //check how many messages per module with the same uniqness //and add to existing group or create a new group - IngestServiceAbstract service = m.getSource(); + IngestModuleAbstract module = m.getSource(); IngestMessageGroup messageGroup = null; - if (service != null && m.getMessageType() == IngestMessage.MessageType.DATA) { + if (module != null && m.getMessageType() == IngestMessage.MessageType.DATA) { //not a manager message, a data message, then group - final Map> groups = groupings.get(service); + final Map> groups = groupings.get(module); //groups for this uniqueness final String uniqueness = m.getUniqueKey(); List uniqGroups = groups.get(uniqueness); @@ -732,9 +732,9 @@ class IngestMessagePanel extends javax.swing.JPanel { } /* - * return source service, should be the same for all msgs + * return source module, should be the same for all msgs */ - IngestServiceAbstract getSource() { + IngestModuleAbstract getSource() { return messages.get(0).getSource(); } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java index cb24688818..71752871e7 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java @@ -280,7 +280,7 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing } /** - * Display IngestMessage from service (forwarded by IngestManager) + * Display IngestMessage from module (forwarded by IngestManager) */ @Override public void displayMessage(IngestMessage ingestMessage) { diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesAction.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesAction.java index 0939caccf8..06f31f5ffa 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesAction.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesAction.java @@ -16,17 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - package org.sleuthkit.autopsy.ingest; import java.awt.Component; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import org.openide.util.actions.Presenter; -import org.openide.windows.Mode; -import org.openide.windows.WindowManager; - //@ActionID(category = "File", //id = "org.sleuthkit.autopsy.ingest.IngestMessagesAction") @@ -36,15 +31,14 @@ import org.openide.windows.WindowManager; // @ActionReference(path = "Toolbars/File", position = 575) //}) //@Messages("CTL_IngestMessagesAction=Messages") -public final class IngestMessagesAction extends AbstractAction implements Presenter.Toolbar { - +public final class IngestMessagesAction extends AbstractAction implements Presenter.Toolbar { + @Override public void actionPerformed(ActionEvent e) { - } - + @Override public Component getToolbarPresenter() { - return new IngestMessagesToolbar(); + return IngestMessagesToolbar.getDefault(); } } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.form b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.form index e1aaaa2fc1..2ed405c3eb 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.form +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.form @@ -1,4 +1,4 @@ - + diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java index e5cf2c1069..ef4a89777d 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagesToolbar.java @@ -32,22 +32,35 @@ import org.sleuthkit.autopsy.casemodule.Case; /** * Toolbar for Ingest - * + * */ public class IngestMessagesToolbar extends javax.swing.JPanel { private IngestMessagesButton ingestMessagesButton = new IngestMessagesButton(); + private static IngestMessagesToolbar instance; - /** Creates new form IngestMessagesToolbar */ - public IngestMessagesToolbar() { + /** + * Creates new form IngestMessagesToolbar + */ + private IngestMessagesToolbar() { initComponents(); customizeComponents(); } - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. + /** + * @return the default instance IngestMessagesToolbar + */ + public static IngestMessagesToolbar getDefault() { + if (instance == null) { + instance = new IngestMessagesToolbar(); + } + return instance; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents @@ -82,7 +95,6 @@ public class IngestMessagesToolbar extends javax.swing.JPanel { ingestMessagesButton.setMinimumSize(new java.awt.Dimension(38, 24)); ingestMessagesButton.setPreferredSize(new java.awt.Dimension(38, 24)); ingestMessagesButton.addActionListener(new java.awt.event.ActionListener() { - @Override public void actionPerformed(java.awt.event.ActionEvent evt) { showIngestMessages(); @@ -94,11 +106,10 @@ public class IngestMessagesToolbar extends javax.swing.JPanel { private void customizeComponents() { customizeButton(); - + this.setBorder(null); IngestMessagePanel.addPropertyChangeSupportListener(new PropertyChangeListener() { - @Override public void propertyChange(PropertyChangeEvent evt) { final int numberMessages = (Integer) evt.getNewValue(); @@ -110,7 +121,6 @@ public class IngestMessagesToolbar extends javax.swing.JPanel { }); Case.addPropertyChangeListener(new PropertyChangeListener() { - @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(Case.CASE_CURRENT_CASE)) { @@ -140,31 +150,32 @@ public class IngestMessagesToolbar extends javax.swing.JPanel { private static class IngestMessagesButton extends JButton { - private static final int fontSize = 9; private static final Font messagesFont = new java.awt.Font("Tahoma", Font.PLAIN, fontSize); private int messages = 0; @Override - public void paint(Graphics g) { + public void paint(Graphics g) { super.paint(g); - - if (messages == 0) + + if (messages == 0) { return; + } //paint text String messageStr = Integer.toString(messages); final int len = messageStr.length(); g.setFont(messagesFont); - + int dx = len * 5 + 5; int x = getSize().width - dx; - if (x<0) + if (x < 0) { x = 0; + } g.setColor(Color.GRAY); //g.fillRect(x, 1, dx, fontSize); g.fillRoundRect(x, 1, dx, fontSize, 2, 2); g.setColor(Color.WHITE); - g.drawString(messageStr, x+2, fontSize); + g.drawString(messageStr, x + 2, fontSize); } void setMessages(int messages) { diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java similarity index 66% rename from Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java rename to Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java index fa67d53571..3d028f02a5 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java @@ -21,75 +21,77 @@ package org.sleuthkit.autopsy.ingest; /** - * Base interface for ingest services + * Base interface for ingest modules */ -public interface IngestServiceAbstract { +public interface IngestModuleAbstract { /** - * Possible service types for the implementing classes + * Possible module types for the implementing classes */ - public enum ServiceType { + public enum ModuleType { /** - * Image type service + * Image type module */ Image, /** - * AbstractFile type service + * AbstractFile type module */ AbstractFile }; /** - * Notification from manager that brand new ingest should be initiated. - * Service loads its configuration and performs initialization - * Invoked once per new worker thread, per ingest - * - * @param managerProxy manager facade that can be used by the service to communicate with the manager, e.g. - * for posting messages, getting configurations + * Notification from manager that brand new ingest should be initiated.. + * Module loads its configuration and performs initialization. + * Invoked once per new worker thread, per ingest. + * In this method initialize always IngestServices handle + * using IngestServices.getDefault() lazy-loading approach. + * NEVER initialize IngestServices handle in the member declaration, because it might result + * in multiple instances of the singleton -- different class loaders are used in different modules. + * @param initContext context used to initialize some modules */ - public void init(IngestManagerProxy managerProxy); + public void init(IngestModuleInit initContext); /** * Notification from manager that there is no more content to process and all work is done. - * Service performs any clean-up of internal resources, and finalizes processing to produce complete result - * Service also posts ingest message indicating it is done, and posts ingest stats and errors in the details of the message. + * Module performs any clean-up of internal resources, and finalizes processing to produce complete result + * Module also posts ingest message indicating it is done, and posts ingest stats and errors in the details of the message. */ public void complete(); /** * Notification from manager to stop processing due to some interruption (user, error, exception) - * Service performs any clean-up of internal resources + * Module performs any clean-up of internal resources * It may also discard any pending results, but it should ensure it is in a defined state so that ingest can be rerun later. */ public void stop(); /** - * Gets specific name of the service - * The name should be unique across services - * @return unique service name + * Gets specific name of the module + * The name should be unique across modules + * @return unique module name */ public String getName(); /** - * Gets user-friendly description of the service - * @return service description + * Gets user-friendly description of the module + * @return module description */ public String getDescription(); /** - * Returns type of the service - * @return service type + * Returns type of the module + * @return module type */ - public ServiceType getType(); + public ModuleType getType(); /** - * A service can manage and use additional threads to perform some work in the background. - * This method provides insight to the manager if the service has truly completed its work or not. + * A module can manage and use additional threads to perform some work in the background. + * This method provides insight to the manager if the module has truly completed its work or not. * * - * @return true if any background threads/workers managed by this service are still running or are pending to be run, - * false if all work has been done, or if background threads are not used/managed by this service + * @return true if any background threads/workers managed by this module are still running or are pending to be run, + * false if all work has been done, or if background threads are not used/managed by this module */ public boolean hasBackgroundJobsRunning(); @@ -98,7 +100,7 @@ public interface IngestServiceAbstract { * Used to determine if a module has implemented a simple (run-time) * configuration panel that is displayed by the ingest manager. * - * @return true if this service has a simple (run-time) configuration + * @return true if this module has a simple (run-time) configuration */ public boolean hasSimpleConfiguration(); @@ -106,7 +108,7 @@ public interface IngestServiceAbstract { * Used to determine if a module has implemented an advanced (general) * configuration that can be used for more in-depth module configuration. * - * @return true if this service has an advanced configuration + * @return true if this module has an advanced configuration */ public boolean hasAdvancedConfiguration(); diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstractFile.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstractFile.java similarity index 65% rename from Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstractFile.java rename to Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstractFile.java index 6b10fa467f..c1115adbfa 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstractFile.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstractFile.java @@ -21,25 +21,23 @@ package org.sleuthkit.autopsy.ingest; import org.sleuthkit.datamodel.AbstractFile; /** - * Ingest service interface that will be called for every file in the image + * Ingest module interface that will be called for every file in the image */ -public interface IngestServiceAbstractFile extends IngestServiceAbstract { +public interface IngestModuleAbstractFile extends IngestModuleAbstract { /** * Return value resulting from processing AbstractFile - * Can be used by IngestManager to stop processing the file, or by subsequent module + * If ERROR, can be used subsequent module * in the pipeline as a hint to stop processing the file */ public enum ProcessResult { OK, ///< Indicates that processing was successful (including if the file was largely ignored by the module) - COND_STOP, ///< Indicates that the module thinks that the pipeline could stop processing, but it is up to the IngestManager to decide. Use this, for example, if a hash lookup detects that a file is known to be good and can be ignored. - STOP, ///< Indicates that the module thinks that the pipeline processing should be stopped unconditionally for the current file (this should be used sparingly for critical system errors and could be removed in future version) ERROR, ///< Indicates that an error was encountered while processing the file, hint for later modules that depend on this module to skip processing the file due to error condition (such as file could not be read) - UNKNOWN ///< Indicates that a return value for the module is not known. This should not be returned directly by modules, but is used when modules want to learn about a return value from a previously run module. + UNKNOWN ///< Indicates that a return value for the module is not known. This should not be returned directly by modules, but is used to indicate the module has not set its return value (e.g. it never ran) }; /** - * Entry point to process file / directory by the service. See \ref ingestmodule_making for details + * Entry point to process file / directory by the module. See \ref ingestmodule_making for details * on what modules are responsible for doing. * * @param abstractFile file to process diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceImage.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleImage.java similarity index 70% rename from Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceImage.java rename to Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleImage.java index 25058c8853..024bc6c16f 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceImage.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleImage.java @@ -22,26 +22,26 @@ import org.sleuthkit.datamodel.Image; /** * - * Ingest service that acts on entire image - * Image ingest services run each in its own background thread + * Ingest module that acts on entire image + * Image ingest modules run each in its own background thread * in parallel to the file processing ingest pipeline and other image ingest modules */ -public interface IngestServiceImage extends IngestServiceAbstract { +public interface IngestModuleImage extends IngestModuleAbstract { /** - * Entry point to process the image by the service. + * Entry point to process the image by the module. * - * Service does all the processing work in this method. + * Module does all the processing work in this method. * It is responsible for extracting content of interest from the image (i.e. using DataModel API) and processing it. * Results of processing, such as extracted data or analysis results, should be posted to the blackboard. * - * The service notifies the ingest inbox of interesting events (data, errors, warnings, infos) + * The module notifies the ingest inbox of interesting events (data, errors, warnings, infos) * by posting ingest messages - * The service notifies data viewers by firing events using IngestManager.fireServiceDataEvent + * The module notifies data viewers by firing events using IngestManagerProxy.fireModuleDataEvent * - * The service is responsible for posting progress to controller - * And to periodically check controller if it should break out of the processing loop because task has been cancelled + * The module is responsible for posting progress to controller + * And to periodically check controller if it should break out of the processing loop because task has been canceled * * @param image to process * @param controller to post progress to and to use for checking if cancellation has occurred diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleInit.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleInit.java new file mode 100644 index 0000000000..e4dd6aee71 --- /dev/null +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestModuleInit.java @@ -0,0 +1,49 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2012 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.ingest; + +/** + * + * Context passed to a module at initialization time. + * It may contain module configuration required to initialize some modules. + */ +public class IngestModuleInit { + + private String moduleArgs; + + /** + * Get module arguments + * @return module args string, used by some modules + */ + public String getModuleArgs() { + return moduleArgs; + } + + /** + * Sets module args. string (only used by module pipeline) + * @param moduleArgs arguments to set for the module + */ + void setModuleArgs(String moduleArgs) { + this.moduleArgs = moduleArgs; + } + + + + +} diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServices.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServices.java new file mode 100644 index 0000000000..85e6cf58a1 --- /dev/null +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServices.java @@ -0,0 +1,107 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 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.ingest; + + +/** + * Services available to ingest modules via singleton instance, + * e.g. for interacting with the ingest manager + * for sending data events, ingest messages, getting configurations, etc. + * + */ +public class IngestServices { + + private IngestManager manager; + + private static IngestServices instance; + + private IngestServices() { + this.manager = IngestManager.getDefault(); + } + + /** + * Get handle to module services + * @return the services handle + */ + public static synchronized IngestServices getDefault() { + if (instance == null) { + instance = new IngestServices(); + } + return instance; + } + + /** + * Post ingest message + * @param message ingest message to be posted by ingest module + */ + public void postMessage(final IngestMessage message) { + manager.postMessage(message); + } + + /** + * Fire module event to notify registered module event listeners + * @param eventType the event type, defined in IngestManager.IngestManagerEvents + * @param moduleName the module name + */ + public void fireModuleEvent(String eventType, String moduleName) { + IngestManager.fireModuleEvent(eventType, moduleName); + } + + + /** + * Fire module data event to notify registered module data event listeners + * @param moduleDataEvent module data event, encapsulating blackboard artifact data + */ + public void fireModuleDataEvent(ModuleDataEvent moduleDataEvent) { + IngestManager.fireModuleDataEvent(moduleDataEvent); + } + + + /** + * Facility for the module to query the currently set recommended data update frequency in minutes + * Modules that post data in controlled time intervals, should obey this setting + * + * @return max. number of minutes before module posts new data, if data is available + * + * @Deprecated individual modules are be responsible for maintaining such settings + */ + public int getUpdateFrequency() { + return manager.getUpdateFrequency().getTime(); + } + + + /** + * Facility for a file ingest module to check a return value from another file ingest module + * that executed for the same file earlier in the file ingest pipeline + * The module return value can be used as a guideline to skip processing the file + * + * @param moduleName registered module name of the module to check the return value of + * @return the return value of the previously executed module for the currently processed file in the file ingest pipeline + */ + public IngestModuleAbstractFile.ProcessResult getAbstractFileModuleResult(String moduleName) { + return manager.getAbstractFileModuleResult(moduleName); + } + + + + + +} diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/Installer.java b/Ingest/src/org/sleuthkit/autopsy/ingest/Installer.java index 754069dd30..cb24aa4ff4 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/Installer.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/Installer.java @@ -38,6 +38,7 @@ public class Installer extends ModuleInstall { @Override public void run() { + //at this point UI top component is present for sure, ensure manager has it manager.initUI(); //force ingest inbox closed, even if previous state was open //IngestMessageTopComponent.findInstance().close(); diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/ServiceDataEvent.java b/Ingest/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java similarity index 79% rename from Ingest/src/org/sleuthkit/autopsy/ingest/ServiceDataEvent.java rename to Ingest/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java index a044422b16..7da0c9d126 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/ServiceDataEvent.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java @@ -32,33 +32,33 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; * The object wraps a collection of blackboard artifacts and their associated attributes that are to be reported as the new data to listeners. * Passing the data as part of the event reduces memory footprint and decreases number of garbage collections of the blackboard artifacts and attributes objects (the objects are expected to be reused by the data event listeners). * - * If a service does not pass the data as part of ServiceDataEvent (ServiceDataEvent.getArtifacts() returns null) - it is an indication that the service + * If a module does not pass the data as part of ModuleDataEvent (ModuleDataEvent.getArtifacts() returns null) - it is an indication that the module * has new data but it does not implement new data tracking. The listener can then perform a blackboard query to get the latest data of interest (e.g. by artifact type). * * By design, only a single type of artifacts can be contained in a single data event. */ -public class ServiceDataEvent { +public class ModuleDataEvent { - private String serviceName; + private String moduleName; private ARTIFACT_TYPE artifactType; private Collection artifactIDs; /** - * @param serviceName Module name + * @param moduleName Module name * @param artifactType Type of artifact that was posted to blackboard */ - public ServiceDataEvent(String serviceName, ARTIFACT_TYPE artifactType) { - this.serviceName = serviceName; + public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType) { + this.moduleName = moduleName; this.artifactType = artifactType; } /** - * @param serviceName Module name + * @param moduleName Module name * @param artifactType Type of artifact that was posted to blackboard * @param artifactIDs List of specific artifact ID values that were added to blackboard */ - public ServiceDataEvent(String serviceName, ARTIFACT_TYPE artifactType, Collection artifactIDs) { - this(serviceName, artifactType); + public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType, Collection artifactIDs) { + this(moduleName, artifactType); this.artifactIDs = artifactIDs; } @@ -79,11 +79,11 @@ public class ServiceDataEvent { } /** - * get service name that created the artifacts and fired the event + * get module name that created the artifacts and fired the event * @return */ - public String getServiceName() { - return serviceName; + public String getModuleName() { + return moduleName; } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleAbstractFileIngestService.java b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleAbstractFileIngestModule.java similarity index 59% rename from Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleAbstractFileIngestService.java rename to Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleAbstractFileIngestModule.java index 405e2a00e2..91917c13d8 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleAbstractFileIngestService.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleAbstractFileIngestModule.java @@ -18,45 +18,45 @@ */ package org.sleuthkit.autopsy.ingest.example; -import java.beans.PropertyChangeListener; import java.util.logging.Level; import java.util.logging.Logger; -import org.sleuthkit.autopsy.ingest.IngestManagerProxy; +import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; -import org.sleuthkit.autopsy.ingest.IngestServiceAbstract.ServiceType; -import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstract.ModuleType; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile; +import org.sleuthkit.autopsy.ingest.IngestModuleInit; import org.sleuthkit.datamodel.AbstractFile; /** - * Example implementation of a fscontent image ingest service + * Example implementation of a file ingest module * */ -public class ExampleAbstractFileIngestService implements IngestServiceAbstractFile { +public class ExampleAbstractFileIngestModule implements IngestModuleAbstractFile { - private static final Logger logger = Logger.getLogger(ExampleAbstractFileIngestService.class.getName()); - private static ExampleAbstractFileIngestService instance = null; - private IngestManagerProxy managerProxy; + private static final Logger logger = Logger.getLogger(ExampleAbstractFileIngestModule.class.getName()); + private static ExampleAbstractFileIngestModule instance = null; + private IngestServices services; private static int messageId = 0; - //file ingest services require a private constructor + //file ingest modules require a private constructor //to ensure singleton instances - private ExampleAbstractFileIngestService() { + private ExampleAbstractFileIngestModule() { } - public static synchronized ExampleAbstractFileIngestService getDefault() { + public static synchronized ExampleAbstractFileIngestModule getDefault() { if (instance == null) { - instance = new ExampleAbstractFileIngestService(); + instance = new ExampleAbstractFileIngestModule(); } return instance; } @Override public ProcessResult process(AbstractFile fsContent) { - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName())); + services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName())); - //service specific AbstractFile processing code here + //module specific AbstractFile processing code here try { Thread.sleep(100); } catch (InterruptedException e) { @@ -68,42 +68,42 @@ public class ExampleAbstractFileIngestService implements IngestServiceAbstractFi @Override public void complete() { logger.log(Level.INFO, "complete()"); - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete")); + services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete")); - //service specific cleanup due completion here + //module specific cleanup due completion here } @Override public String getName() { - return "Example AbstractFile Service"; + return "Example AbstractFile Module"; } @Override public String getDescription() { - return "Example AbstractFile Service description"; + return "Example AbstractFile Module description"; } @Override - public void init(IngestManagerProxy managerProxy) { + public void init(IngestModuleInit initContext) { logger.log(Level.INFO, "init()"); - this.managerProxy = managerProxy; + services = IngestServices.getDefault(); - //service specific initialization here + //module specific initialization here } @Override public void stop() { logger.log(Level.INFO, "stop()"); - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped")); + services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped")); - //service specific cleanup due interruption here + //module specific cleanup due interruption here } @Override - public ServiceType getType() { - return ServiceType.AbstractFile; + public ModuleType getType() { + return ModuleType.AbstractFile; } @Override diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestModule.java similarity index 76% rename from Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java rename to Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestModule.java index c1c1950672..018a2172cd 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestModule.java @@ -18,36 +18,36 @@ */ package org.sleuthkit.autopsy.ingest.example; -import java.beans.PropertyChangeListener; import java.util.logging.Level; import java.util.logging.Logger; import org.sleuthkit.autopsy.ingest.IngestImageWorkerController; -import org.sleuthkit.autopsy.ingest.IngestManagerProxy; +import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; -import org.sleuthkit.autopsy.ingest.IngestServiceImage; +import org.sleuthkit.autopsy.ingest.IngestModuleImage; +import org.sleuthkit.autopsy.ingest.IngestModuleInit; import org.sleuthkit.datamodel.Image; /** * Example implementation of an image ingest service * */ -public final class ExampleImageIngestService implements IngestServiceImage { +public final class ExampleImageIngestModule implements IngestModuleImage { - private static final Logger logger = Logger.getLogger(ExampleImageIngestService.class.getName()); - private static ExampleImageIngestService defaultInstance = null; - private IngestManagerProxy managerProxy; + private static final Logger logger = Logger.getLogger(ExampleImageIngestModule.class.getName()); + private static ExampleImageIngestModule defaultInstance = null; + private IngestServices services; private static int messageId = 0; //public constructor is required //as multiple instances are created for processing multiple images simultenously - public ExampleImageIngestService() { + public ExampleImageIngestModule() { } //default instance used for service registration - public static synchronized ExampleImageIngestService getDefault() { + public static synchronized ExampleImageIngestModule getDefault() { if (defaultInstance == null) { - defaultInstance = new ExampleImageIngestService(); + defaultInstance = new ExampleImageIngestModule(); } return defaultInstance; } @@ -56,7 +56,7 @@ public final class ExampleImageIngestService implements IngestServiceImage { public void process(Image image, IngestImageWorkerController controller) { logger.log(Level.INFO, "process() " + this.toString()); - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + image.getName())); + services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + image.getName())); //service specific Image processing code here //example: @@ -76,7 +76,7 @@ public final class ExampleImageIngestService implements IngestServiceImage { //do the work Thread.sleep(500); //post message to user if found something interesting - managerProxy.postMessage(IngestMessage.createMessage(processedFiles, MessageType.INFO, this, "Processed " + image.getName() + ": " + Integer.toString(processedFiles))); + services.postMessage(IngestMessage.createMessage(processedFiles, MessageType.INFO, this, "Processed " + image.getName() + ": " + Integer.toString(processedFiles))); //update progress controller.progress(++processedFiles); @@ -92,7 +92,7 @@ public final class ExampleImageIngestService implements IngestServiceImage { logger.log(Level.INFO, "complete() " + this.toString()); final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete"); - managerProxy.postMessage(msg); + services.postMessage(msg); //service specific cleanup due to completion here } @@ -108,9 +108,9 @@ public final class ExampleImageIngestService implements IngestServiceImage { } @Override - public void init(IngestManagerProxy managerProxy) { + public void init(IngestModuleInit initContext) { logger.log(Level.INFO, "init() " + this.toString()); - this.managerProxy = managerProxy; + services = IngestServices.getDefault(); //service specific initialization here @@ -119,14 +119,14 @@ public final class ExampleImageIngestService implements IngestServiceImage { @Override public void stop() { logger.log(Level.INFO, "stop()"); - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped")); + services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped")); //service specific cleanup due to interruption here } @Override - public ServiceType getType() { - return ServiceType.Image; + public ModuleType getType() { + return ModuleType.Image; } @Override diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/layer.xml b/Ingest/src/org/sleuthkit/autopsy/ingest/layer.xml index 142910fafc..eae2ad2d6c 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/layer.xml +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/layer.xml @@ -14,17 +14,17 @@ --> - + diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/package.dox b/Ingest/src/org/sleuthkit/autopsy/ingest/package.dox index 450b890dfe..d31618364d 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/package.dox +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/package.dox @@ -5,7 +5,7 @@ The package provides the ingest module framework. Ingest modules perform data analysis in a multi-threaded approach. -\section ingestmodue_contents Package Contents +\section ingestmodule_contents Package Contents The following are important classes in this package: - IngestManager @@ -31,17 +31,17 @@ Refer to org.sleuthkit.autopsy.ingest.example for sample source code. \subsection ingestmodule_making_api Module Interface -The first step is to choose the correct module type. Image-level modules will implement the IngestServiceImage interface and file-level modules will implement the IngestServiceAbstractFile interface. +The first step is to choose the correct module type. Image-level modules will implement the IngestModuleImage interface and file-level modules will implement the IngestModuleAbstractFile interface. -There is a static getDefault() method that is not part of the interface, that every module (whether an image or a file service) needs to implement to return the registered static instance of the service. Refer to example code in example.ExampleAbstractFileIngestService.getDefault() +There is a static getDefault() method that is not part of the interface, that every module (whether an image or a file module) needs to implement to return the registered static instance of the module. Refer to example code in example.ExampleAbstractFileIngestModule.getDefault() -File-level modules need to be singleton (only a single instance at a time). To ensure this, make the constructor private. Ensure the default public file service constructor is overridden with the private one. Image-level modules require a public constructor. +File-level modules need to be singleton (only a single instance at a time). To ensure this, make the constructor private. Ensure the default public file module constructor is overridden with the private one. Image-level modules require a public constructor. The interfaces have several standard methods that need to be implemented. See the interface methods for details. -- IngestServiceAbstract.init() is invoked every time an ingest session starts. A module should support multiple invocations of init() throughout the application life-cycle. -- IngestServiceAbstract.complete() is invoked when an ingest session completes. The module should perform any resource (files, handles, caches) cleanup in this method and submit final results and post a final ingest inbox message. -- IngestServiceAbstract.stop() is invoked on a module when an ingest session is interrupted by the user or by the system. -The method implementation should be similar to complete() in that the service should perform any cleanup work. If there is pending data to be processed or pending results to be reported by the service then the results should be rejected and ignored if stop() is invoked and the module should terminate as early as possible. +- IngestModuleAbstract.init() is invoked every time an ingest session starts. A module should support multiple invocations of init() throughout the application life-cycle. +- IngestModuleAbstract.complete() is invoked when an ingest session completes. The module should perform any resource (files, handles, caches) cleanup in this method and submit final results and post a final ingest inbox message. +- IngestModuleAbstract.stop() is invoked on a module when an ingest session is interrupted by the user or by the system. +The method implementation should be similar to complete() in that the module should perform any cleanup work. If there is pending data to be processed or pending results to be reported by the module then the results should be rejected and ignored if stop() is invoked and the module should terminate as early as possible. - process() method is invoked to analyze the data. The specific method depends on the module type. @@ -55,7 +55,7 @@ Module developers are encouraged to use the standard java.util.logging.Logger in \subsection ingestmodule_making_process Process Method The process method is where the work is done in each type of module. Some notes: -- File-level modules will be called on each file in an order determined by the IngestManager. Each module is free to quickly ignore a file based on name, signature, etc. If a module wants to know the return value from a previously run module, it should use the IngestManagerProxy.getAbstractFileServiceResult() method. +- File-level modules will be called on each file in an order determined by the IngestManager. Each module is free to quickly ignore a file based on name, signature, etc. If a module wants to know the return value from a previously run module, it should use the IngestServices.getAbstractFileModuleResult() method. - Image-level modules are expected not passed in specific files and are expected to query the database to find the files that they are interested in. @@ -65,9 +65,9 @@ Ingest modules need to be registered using the Netbeans Lookup infrastructure in An example Image-level module is: \verbatim - - - + + + \endverbatim @@ -75,16 +75,16 @@ An example Image-level module is: An example file-level module is: \verbatim - - - + + + \endverbatim Note the "position" attribute. The attribute determines the ordering of the module in the ingest pipeline. -Services with lower position attribute will execute earlier. -Use high numbers (higher than 1000) for non-core services. If your module depends on results from another module, use a higher position attribute to enforce the dependency. +Modules with lower position attribute will execute earlier. +Use high numbers (higher than 1000) for non-core modules. If your module depends on results from another module, use a higher position attribute to enforce the dependency. Note: we plan to implement a more flexible and robust module dependency system in future versions of the Autopsy ingest framework. @@ -97,11 +97,11 @@ Users will see the results from ingest modules in one of two ways: - Results are posted to the blackboard and will be displayed in the navigation tree - Messages are sent to the Ingest Inbox to notify a user of what has recently been found. -See the Blackboard (REFERENCE) documentation for posting results to it. Modules are free to immediately post results when they find them or they can wait. The IngestManagerProxy.getUpdateFrequency() method returns the maximum amount of time that a module can wait before it posts its results. +See the Blackboard (REFERENCE) documentation for posting results to it. Modules are free to immediately post results when they find them or they can wait. The IngestServices.getUpdateFrequency() method returns the maximum amount of time that a module can wait before it posts its results. An example of waiting to post results is the keyword search module. It is resource intensive to commit the keyword index and do a keyword search. Therefore, when its process() method is invoked, it checks if it is close to the getUpdateFrequency() since the last time it did a keyword search. If it is, then it commits the index and performs the search. -When they add data to the blackboard, modules should notify listeners of the new data by periodically invoking IngestManagerProxy.fireServiceDataEvent() method. This allows other modules (and the main UI) to know when to query the blackboard for the latest data. +When they add data to the blackboard, modules should notify listeners of the new data by periodically invoking IngestServices.fireModuleDataEvent() method. This allows other modules (and the main UI) to know when to query the blackboard for the latest data. Modules should post messages to the inbox when interesting data is found. The messages includes the module name, message subject, message details, a unique message id (in the context of the originating module), and a uniqueness attribute. The uniqueness attribute is used to group similar messages together and to determine the overall importance priority of the message (if the same message is seen repeatedly, it is considered lower priority). @@ -111,7 +111,7 @@ Ingest messages have different types: there are info messages, warning messages, The data messages contain encapsulated blackboard artifacts and attributes. The passed in data is used by the ingest inbox GUI widget to navigate to the artifact view in the directory tree, if requested by the user. Ingest message API is defined in IngestMessage class. The class also contains factory methods to create new messages. -Messages are posted using IngestManagerProxy.postMessage() method, which accepts a message object created using one of the factory methods. +Messages are posted using IngestServices.postMessage() method, which accepts a message object created using one of the factory methods. Modules should post inbox messages to the user when stop() or complete() is invoked (refer to the examples). It is recommended to populate the description field of the complete inbox message to provide feedback to the user @@ -134,13 +134,13 @@ Module configuration is decentralized and module-specific; every module maintain own configuration state and is responsible for implementing the graphical interface. The run-time configuration (also called simple configuration), is achieved by each -ingest module providing a JPanel. The IngestServiceAbstract.hasSimpleConfiguration(), -IngestServiceAbstract.getSimpleConfiguration(), and IngestServiceAbstract.saveSimpleConfiguration() +ingest module providing a JPanel. The IngestModuleAbstract.hasSimpleConfiguration(), +IngestModuleAbstract.getSimpleConfiguration(), and IngestModuleAbstract.saveSimpleConfiguration() methods should be used for run-time configuration. The general configuration is also achieved by the module returning a JPanel. A link will be provided to the general configuration from the ingest manager if it exists. -The IngestServiceAbstract.hasAdvancedConfiguration(), -IngestServiceAbstract.getAdvancedConfiguration(), and IngestServiceAbstract.saveAdvancedConfiguration() +The IngestModuleAbstract.hasAdvancedConfiguration(), +IngestModuleAbstract.getAdvancedConfiguration(), and IngestModuleAbstract.saveAdvancedConfiguration() methods should be used for general configuration. @@ -152,14 +152,14 @@ methods should be used for general configuration. Other modules and core Autopsy classes may want to get the status of the ingest manager. The IngestManager provides access to this data with the sleuthkit.autopsy.ingest.IngestManager.isIngestRunning() method. -External modules can also register themselves as ingest service event listeners and receive event notifications (when a module is started, stopped, completed or has new data). -Use the IngestManager.addPropertyChangeListener() method to register a service event listener. +External modules can also register themselves as ingest module event listeners and receive event notifications (when a module is started, stopped, completed or has new data). +Use the IngestManager.addPropertyChangeListener() method to register a module event listener. Events types received are defined in IngestManager.IngestModuleEvent enum. At the end of the ingest, IngestManager itself will notify all listeners of IngestModuleEvent.COMPLETED event. The event is an indication for listeners to perform the final data refresh by quering the blackboard. Module developers are encouraged to generate periodic IngestModuleEvent.DATA -ServiceDataEvent events when they post data to the blackboard, +ModuleDataEvent events when they post data to the blackboard, but the IngestManager will make a final event to handle scenarios where the module did not notify listeners while it was running. */ diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileHtmlExtract.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileHtmlExtract.java index f871826185..c0289935f9 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileHtmlExtract.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileHtmlExtract.java @@ -43,7 +43,7 @@ public class AbstractFileHtmlExtract implements AbstractFileExtract { private static final int SINGLE_READ_CHARS = 1024; private static final int EXTRA_CHARS = 128; //for whitespace private static final char[] TEXT_CHUNK_BUF = new char[MAX_EXTR_TEXT_CHARS]; - private KeywordSearchIngestService service; + private KeywordSearchIngestModule module; private Ingester ingester; private AbstractFile sourceFile; private int numChunks = 0; @@ -53,7 +53,7 @@ public class AbstractFileHtmlExtract implements AbstractFileExtract { }; AbstractFileHtmlExtract() { - this.service = KeywordSearchIngestService.getDefault(); + this.module = KeywordSearchIngestModule.getDefault(); ingester = Server.getIngester(); } @@ -161,7 +161,7 @@ public class AbstractFileHtmlExtract implements AbstractFileExtract { //check if need invoke commit/search between chunks //not to delay commit if timer has gone off - service.checkRunCommitSearch(); + module.checkRunCommitSearch(); } } catch (IOException ex) { logger.log(Level.WARNING, "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName(), ex); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileStringExtract.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileStringExtract.java index 0ac22999f5..6f67028656 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileStringExtract.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileStringExtract.java @@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.AbstractFile; */ class AbstractFileStringExtract implements AbstractFileExtract { - private KeywordSearchIngestService service; + private KeywordSearchIngestModule module; private Ingester ingester; private int numChunks; private static final Logger logger = Logger.getLogger(AbstractFileStringExtract.class.getName()); @@ -61,7 +61,7 @@ class AbstractFileStringExtract implements AbstractFileExtract { } public AbstractFileStringExtract() { - this.service = KeywordSearchIngestService.getDefault(); + this.module = KeywordSearchIngestModule.getDefault(); this.ingester = Server.getIngester(); this.extractScripts.add(DEFAULT_SCRIPT); } @@ -122,7 +122,7 @@ class AbstractFileStringExtract implements AbstractFileExtract { //check if need invoke commit/search between chunks //not to delay commit if timer has gone off - service.checkRunCommitSearch(); + module.checkRunCommitSearch(); //debug.close(); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileTikaTextExtract.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileTikaTextExtract.java index 000d1fd257..76ae4844e9 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileTikaTextExtract.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractFileTikaTextExtract.java @@ -32,7 +32,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; -import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ReadContentInputStream; import org.apache.tika.Tika; @@ -52,7 +52,7 @@ import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException; */ public class AbstractFileTikaTextExtract implements AbstractFileExtract { - private static final Logger logger = Logger.getLogger(IngestServiceAbstractFile.class.getName()); + private static final Logger logger = Logger.getLogger(IngestModuleAbstractFile.class.getName()); private static final Logger tikaLogger = KeywordSearch.getTikaLogger(); private static final Charset OUTPUT_CHARSET = Server.DEFAULT_INDEXED_TEXT_CHARSET; static final int MAX_EXTR_TEXT_CHARS = 512 * 1024; @@ -60,7 +60,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract { private static final int EXTRA_CHARS = 128; //for whitespace private static final char[] TEXT_CHUNK_BUF = new char[MAX_EXTR_TEXT_CHARS]; //private Tika tika; - private KeywordSearchIngestService service; + private KeywordSearchIngestModule module; private static Ingester ingester; private AbstractFile sourceFile; //currently processed file private int numChunks = 0; @@ -74,7 +74,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract { "pst", "xml", "class", "dwg", "eml", "emlx", "mbox", "mht"}; AbstractFileTikaTextExtract() { - this.service = KeywordSearchIngestService.getDefault(); + this.module = KeywordSearchIngestModule.getDefault(); ingester = Server.getIngester(); } @@ -216,7 +216,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract { //check if need invoke commit/search between chunks //not to delay commit if timer has gone off - service.checkRunCommitSearch(); + module.checkRunCommitSearch(); } } catch (IOException ex) { final String msg = "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java index 77033795e6..fe5cec511e 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java @@ -79,8 +79,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme return; } - //check if keyword search service ingest is running (indexing, etc) - if (IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault())) { + //check if keyword search module ingest is running (indexing, etc) + if (IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault())) { if (KeywordSearchUtil.displayConfirmDialog("Keyword Search Ingest in Progress", "Keyword Search Ingest is currently running.
" + "Not all files have been indexed and this search might yield incomplete results.
" diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchAction.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchAction.java index e05edb48d1..68b730b550 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchAction.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchAction.java @@ -31,6 +31,6 @@ public final class KeywordSearchAction extends AbstractAction implements Present @Override public Component getToolbarPresenter() { - return new KeywordSearchPanel(); + return KeywordSearchPanel.getDefault(); } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java index 2696d70436..289e2307ee 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel2.java @@ -59,10 +59,10 @@ public class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel { } private void activateWidgets() { - final KeywordSearchIngestService service = KeywordSearchIngestService.getDefault(); + final KeywordSearchIngestModule service = KeywordSearchIngestModule.getDefault(); skipNSRLCheckBox.setSelected(service.getSkipKnown()); boolean enable = !IngestManager.getDefault().isIngestRunning() - && ! IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault()); + && ! IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault()); skipNSRLCheckBox.setEnabled(enable); } @@ -139,7 +139,7 @@ public class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel { }//
//GEN-END:initComponents private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipNSRLCheckBoxActionPerformed - KeywordSearchIngestService.getDefault().setSkipKnown(skipNSRLCheckBox.isSelected()); + KeywordSearchIngestModule.getDefault().setSkipKnown(skipNSRLCheckBox.isSelected()); }//GEN-LAST:event_skipNSRLCheckBoxActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel chunksLabel; @@ -152,7 +152,7 @@ private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {// // End of variables declaration//GEN-END:variables private void customizeComponents() { - this.skipNSRLCheckBox.setSelected(KeywordSearchIngestService.getDefault().getSkipKnown()); + this.skipNSRLCheckBox.setSelected(KeywordSearchIngestModule.getDefault().getSkipKnown()); try { filesIndexedValue.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedFiles())); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java index f74cc9384d..904b62748a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel3.java @@ -64,7 +64,7 @@ public class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel { toUpdate.add(s); } } - KeywordSearchIngestService.getDefault().setStringExtractScripts(toUpdate); + KeywordSearchIngestModule.getDefault().setStringExtractScripts(toUpdate); } }; @@ -104,7 +104,7 @@ public class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel { } private void reloadScriptsCheckBoxes() { - final KeywordSearchIngestService service = KeywordSearchIngestService.getDefault(); + final KeywordSearchIngestModule service = KeywordSearchIngestModule.getDefault(); final List