Merge pull request #1315 from sidheshenator/python_module_reload_and_logging

Python module reload and logging
This commit is contained in:
Brian Carrier 2015-06-05 13:16:16 -04:00
commit fd70adfc55
4 changed files with 47 additions and 36 deletions

View File

@ -70,6 +70,7 @@ public final class JythonModuleLoader {
private static <T> List<T> getInterfaceImplementations(LineFilter filter, Class<T> interfaceClass) { private static <T> List<T> getInterfaceImplementations(LineFilter filter, Class<T> interfaceClass) {
List<T> objects = new ArrayList<>(); List<T> objects = new ArrayList<>();
Set<File> pythonModuleDirs = new HashSet<>(); Set<File> pythonModuleDirs = new HashSet<>();
PythonInterpreter interpreter = new PythonInterpreter();
// add python modules from 'autospy/build/cluster/InternalPythonModules' folder // add python modules from 'autospy/build/cluster/InternalPythonModules' folder
// which are copied from 'autopsy/*/release/InternalPythonModules' folders. // which are copied from 'autopsy/*/release/InternalPythonModules' folders.
@ -90,7 +91,7 @@ public final class JythonModuleLoader {
if (line.startsWith("class ") && filter.accept(line)) { //NON-NLS if (line.startsWith("class ") && filter.accept(line)) { //NON-NLS
String className = line.substring(6, line.indexOf("(")); String className = line.substring(6, line.indexOf("("));
try { try {
objects.add( createObjectFromScript(script, className, interfaceClass)); objects.add( createObjectFromScript(interpreter, script, className, interfaceClass));
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, String.format("Failed to load %s from %s", className, script.getAbsolutePath()), ex); //NON-NLS logger.log(Level.SEVERE, String.format("Failed to load %s from %s", className, script.getAbsolutePath()), ex); //NON-NLS
// NOTE: using ex.toString() because the current version is always returning null for ex.getMessage(). // NOTE: using ex.toString() because the current version is always returning null for ex.getMessage().
@ -112,21 +113,21 @@ public final class JythonModuleLoader {
return objects; return objects;
} }
private static <T> T createObjectFromScript(File script, String className, Class<T> interfaceClass) { private static <T> T createObjectFromScript(PythonInterpreter interpreter, File script, String className, Class<T> interfaceClass) {
// Make a "fresh" interpreter every time to avoid name collisions, etc.
PythonInterpreter interpreter = new PythonInterpreter();
// Add the directory where the Python script resides to the Python // Add the directory where the Python script resides to the Python
// module search path to allow the script to use other scripts bundled // module search path to allow the script to use other scripts bundled
// with it. // with it.
interpreter.exec("import sys"); //NON-NLS interpreter.exec("import sys"); //NON-NLS
String path = Matcher.quoteReplacement(script.getParent()); String path = Matcher.quoteReplacement(script.getParent());
interpreter.exec("sys.path.append('" + path + "')"); //NON-NLS interpreter.exec("sys.path.append('" + path + "')"); //NON-NLS
String moduleName = script.getName().replaceAll(".py", ""); //NON-NLS
// reload the module so that the changes made to it can be loaded.
interpreter.exec("import " + moduleName); //NON-NLS
interpreter.exec("reload(" + moduleName + ")"); //NON-NLS
// Execute the script and create an instance of the desired class.
interpreter.execfile(script.getAbsolutePath());
// Importing the appropriate class from the Py Script which contains multiple classes. // Importing the appropriate class from the Py Script which contains multiple classes.
interpreter.exec("from " + script.getName().replaceAll(".py", "") + " import " + className); interpreter.exec("from " + moduleName + " import " + className);
interpreter.exec("obj = " + className + "()"); //NON-NLS interpreter.exec("obj = " + className + "()"); //NON-NLS
T obj = interpreter.get("obj", interfaceClass); //NON-NLS T obj = interpreter.get("obj", interfaceClass); //NON-NLS

View File

@ -32,6 +32,7 @@
# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation # See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation
import jarray import jarray
import inspect
from java.lang import System from java.lang import System
from java.util.logging import Level from java.util.logging import Level
from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import SleuthkitCase
@ -82,6 +83,11 @@ class SampleJythonDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
# TODO: Rename this to something more specific. Could just remove "Factory" from above name. # TODO: Rename this to something more specific. Could just remove "Factory" from above name.
class SampleJythonDataSourceIngestModule(DataSourceIngestModule): class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
_logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName)
def log(self, level, msg):
self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
def __init__(self): def __init__(self):
self.context = None self.context = None
@ -94,7 +100,6 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up # Throw an IngestModule.IngestModuleException exception if there was a problem setting up
# raise IngestModuleException(IngestModule(), "Oh No!") # raise IngestModuleException(IngestModule(), "Oh No!")
# Where the analysis is done. # Where the analysis is done.
# The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content. # The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content.
# See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html
@ -105,8 +110,6 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
if self.context.isJobCancelled(): if self.context.isJobCancelled():
return IngestModule.ProcessResult.OK return IngestModule.ProcessResult.OK
logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName)
# we don't know how much work there is yet # we don't know how much work there is yet
progressBar.switchToIndeterminate() progressBar.switchToIndeterminate()
@ -121,7 +124,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
files = fileManager.findFiles(dataSource, "%test%") files = fileManager.findFiles(dataSource, "%test%")
numFiles = len(files) numFiles = len(files)
logger.logp(Level.INFO, SampleJythonDataSourceIngestModule.__name__, "process", "found " + str(numFiles) + " files") self.log(Level.INFO, "found " + str(numFiles) + " files")
progressBar.switchToDeterminate(numFiles) progressBar.switchToDeterminate(numFiles)
fileCount = 0; fileCount = 0;
for file in files: for file in files:
@ -130,7 +133,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
if self.context.isJobCancelled(): if self.context.isJobCancelled():
return IngestModule.ProcessResult.OK return IngestModule.ProcessResult.OK
logger.logp(Level.INFO, SampleJythonDataSourceIngestModule.__name__, "process", "Processing file: " + file.getName()) self.log(Level.INFO, "Processing file: " + file.getName())
fileCount += 1 fileCount += 1
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of

View File

@ -32,6 +32,7 @@
# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation # See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation
import jarray import jarray
import inspect
from java.lang import System from java.lang import System
from java.util.logging import Level from java.util.logging import Level
from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import SleuthkitCase
@ -84,12 +85,16 @@ class SampleJythonFileIngestModuleFactory(IngestModuleFactoryAdapter):
# Looks at the attributes of the passed in file. # Looks at the attributes of the passed in file.
class SampleJythonFileIngestModule(FileIngestModule): class SampleJythonFileIngestModule(FileIngestModule):
_logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName)
def log(self, level, msg):
self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
# Where any setup and configuration is done # Where any setup and configuration is done
# 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext.
# See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html
# TODO: Add any setup code that you need here. # TODO: Add any setup code that you need here.
def startUp(self, context): def startUp(self, context):
self.logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName)
self.filesFound = 0 self.filesFound = 0
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up # Throw an IngestModule.IngestModuleException exception if there was a problem setting up
@ -101,7 +106,6 @@ class SampleJythonFileIngestModule(FileIngestModule):
# See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html
# TODO: Add your analysis code in here. # TODO: Add your analysis code in here.
def process(self, file): def process(self, file):
# Skip non-files # Skip non-files
if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)):
return IngestModule.ProcessResult.OK return IngestModule.ProcessResult.OK
@ -109,7 +113,7 @@ class SampleJythonFileIngestModule(FileIngestModule):
# For an example, we will flag files with .txt in the name and make a blackboard artifact. # For an example, we will flag files with .txt in the name and make a blackboard artifact.
if file.getName().find(".txt") != -1: if file.getName().find(".txt") != -1:
self.logger.logp(Level.INFO, SampleJythonFileIngestModule.__name__, "process", "Found a text file: " + file.getName()) self.log(Level.INFO, "Found a text file: " + file.getName())
self.filesFound+=1 self.filesFound+=1
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
@ -125,7 +129,7 @@ class SampleJythonFileIngestModule(FileIngestModule):
for artifact in artifactList: for artifact in artifactList:
attributeList = artifact.getAttributes(); attributeList = artifact.getAttributes();
for attrib in attributeList: for attrib in attributeList:
self.logger.logp(Level.INFO, SampleJythonFileIngestModule.__name__, "process", attrib.toString()) self.log(Level.INFO, attrib.toString())
# To further the example, this code will read the contents of the file and count the number of bytes # To further the example, this code will read the contents of the file and count the number of bytes
inputStream = ReadContentInputStream(file) inputStream = ReadContentInputStream(file)

View File

@ -39,6 +39,7 @@
import jarray import jarray
import inspect
from java.lang import System from java.lang import System
from java.util.logging import Level from java.util.logging import Level
from javax.swing import JCheckBox from javax.swing import JCheckBox
@ -109,6 +110,11 @@ class SampleFileIngestModuleWithUIFactory(IngestModuleFactoryAdapter):
# Looks at the attributes of the passed in file. # Looks at the attributes of the passed in file.
class SampleFileIngestModuleWithUI(FileIngestModule): class SampleFileIngestModuleWithUI(FileIngestModule):
_logger = Logger.getLogger(SampleFileIngestModuleWithUIFactory.moduleName)
def log(self, level, msg):
self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
# Autopsy will pass in the settings from the UI panel # Autopsy will pass in the settings from the UI panel
def __init__(self, settings): def __init__(self, settings):
self.local_settings = settings self.local_settings = settings
@ -117,13 +123,11 @@ class SampleFileIngestModuleWithUI(FileIngestModule):
# Where any setup and configuration is done # Where any setup and configuration is done
# TODO: Add any setup code that you need here. # TODO: Add any setup code that you need here.
def startUp(self, context): def startUp(self, context):
self.logger = Logger.getLogger(SampleFileIngestModuleWithUIFactory.moduleName)
# As an example, determine if user configured a flag in UI # As an example, determine if user configured a flag in UI
if self.local_settings.getFlag(): if self.local_settings.getFlag():
self.logger.logp(Level.INFO, SampleFileIngestModuleWithUI.__name__, "startUp", "flag is set") self.log(Level.INFO, "flag is set")
else: else:
self.logger.logp(Level.INFO, SampleFileIngestModuleWithUI.__name__, "startUp", "flag is not set") self.log(Level.INFO, "flag is not set")
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up # Throw an IngestModule.IngestModuleException exception if there was a problem setting up
# raise IngestModuleException(IngestModule(), "Oh No!") # raise IngestModuleException(IngestModule(), "Oh No!")
@ -201,4 +205,3 @@ class SampleFileIngestModuleWithUISettingsPanel(IngestModuleIngestJobSettingsPan
def getSettings(self): def getSettings(self):
return self.local_settings return self.local_settings