19 package org.sleuthkit.autopsy.modules.hashdatabase;
 
   21 import java.beans.PropertyChangeEvent;
 
   23 import java.io.IOException;
 
   24 import java.util.ArrayList;
 
   25 import java.util.HashSet;
 
   26 import java.util.List;
 
   28 import javax.swing.JFileChooser;
 
   29 import javax.swing.filechooser.FileNameExtensionFilter;
 
   30 import javax.xml.parsers.DocumentBuilder;
 
   31 import javax.xml.parsers.DocumentBuilderFactory;
 
   32 import javax.xml.parsers.ParserConfigurationException;
 
   33 import org.openide.util.NbBundle;
 
   36 import org.w3c.dom.Document;
 
   37 import org.w3c.dom.Element;
 
   38 import org.w3c.dom.NodeList;
 
   39 import java.beans.PropertyChangeListener;
 
   40 import java.beans.PropertyChangeSupport;
 
   41 import java.util.concurrent.ExecutionException;
 
   42 import java.util.logging.Level;
 
   43 import javax.swing.JOptionPane;
 
   44 import javax.swing.SwingWorker;
 
   45 import org.apache.commons.io.FilenameUtils;
 
   46 import org.apache.commons.io.FileUtils;
 
   47 import org.netbeans.api.progress.ProgressHandle;
 
   48 import org.netbeans.api.progress.ProgressHandleFactory;
 
   76     private static final String 
ENCODING = 
"UTF-8"; 
 
   84     PropertyChangeSupport changeSupport = 
new PropertyChangeSupport(
HashDbManager.class);
 
   94         DB_ADDED, DB_DELETED, DB_INDEXED
 
  101         if (instance == null) {
 
  108         changeSupport.addPropertyChangeListener(listener);
 
  122     static String getHashDatabaseFileExtension() {
 
  153             addExistingHashDatabaseInternal(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
 
  155             throw new HashDbManagerException(ex.getMessage());
 
  160             throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(), 
"HashDbManager.saveErrorExceptionMsg"));
 
  186         if (!
new File(path).exists()) {
 
  187             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.hashDbDoesNotExistExceptionMsg", path));
 
  190         if (hashSetPaths.contains(path)) {
 
  191             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
 
  194         if (hashSetNames.contains(hashSetName)) {
 
  195             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
 
  198         return addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
 
  222             hashDb = addNewHashDatabaseInternal(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
 
  223         } 
catch (TskCoreException ex) {
 
  224             throw new HashDbManagerException(ex.getMessage());
 
  229             throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(), 
"HashDbManager.saveErrorExceptionMsg"));
 
  253     synchronized HashDb addNewHashDatabaseInternal(String hashSetName, String path, 
boolean searchDuringIngest, 
boolean sendIngestMessages, 
HashDb.
KnownFilesType knownFilesType) throws HashDbManagerException, TskCoreException {
 
  254         File file = 
new File(path);
 
  256             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.hashDbFileExistsExceptionMsg", path));
 
  258         if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
 
  259             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.illegalHashDbFileNameExtensionMsg",
 
  260                     getHashDatabaseFileExtension()));
 
  263         if (hashSetPaths.contains(path)) {
 
  264             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
 
  267         if (hashSetNames.contains(hashSetName)) {
 
  268             throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class, 
"HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
 
  271         return addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
 
  276         HashDb hashDb = 
new HashDb(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
 
  286         if (!databasePath.equals(
"None")) { 
 
  287             hashSetPaths.add(databasePath);
 
  289         if (!indexPath.equals(
"None")) { 
 
  290             hashSetPaths.add(indexPath);
 
  295             knownHashSets.add(hashDb);
 
  297             knownBadHashSets.add(hashDb);
 
  302             changeSupport.firePropertyChange(
SetEvt.
DB_ADDED.toString(), null, hashSetName);
 
  303         } 
catch (Exception e) {
 
  304             logger.log(Level.SEVERE, 
"HashDbManager listener threw exception", e); 
 
  306                     NbBundle.getMessage(
this.getClass(), 
"HashDbManager.moduleErr"),
 
  307                     NbBundle.getMessage(
this.getClass(), 
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
 
  313     synchronized void indexHashDatabase(
HashDb hashDb) {
 
  315         HashDbIndexer creator = 
new HashDbIndexer(hashDb);
 
  323             if (null != hashDb) {
 
  326                     if (!indexPath.equals(
"None")) { 
 
  327                         hashSetPaths.add(indexPath);
 
  329                 } 
catch (TskCoreException ex) {
 
  346         if (ingestIsRunning) {
 
  347             throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(), 
"HashDbManager.ingestRunningExceptionMsg"));
 
  349         removeHashDatabaseInternal(hashDb);
 
  351             throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(), 
"HashDbManager.saveErrorExceptionMsg"));
 
  363     synchronized void removeHashDatabaseInternal(
HashDb hashDb) {
 
  369         knownHashSets.remove(hashDb);
 
  370         knownBadHashSets.remove(hashDb);
 
  371         hashSetNames.remove(hashSetName);
 
  376         } 
catch (TskCoreException ex) {
 
  377             Logger.getLogger(
HashDbManager.class.getName()).log(Level.SEVERE, 
"Error getting index path of " + hashDb.
getHashSetName() + 
" hash database when removing the database", ex); 
 
  380             if (!hashDb.hasIndexOnly()) {
 
  383         } 
catch (TskCoreException ex) {
 
  384             Logger.getLogger(
HashDbManager.class.getName()).log(Level.SEVERE, 
"Error getting database path of " + hashDb.
getHashSetName() + 
" hash database when removing the database", ex); 
 
  388         } 
catch (TskCoreException ex) {
 
  389             Logger.getLogger(
HashDbManager.class.getName()).log(Level.SEVERE, 
"Error closing " + hashDb.
getHashSetName() + 
" hash database when removing the database", ex); 
 
  395             changeSupport.firePropertyChange(SetEvt.DB_DELETED.toString(), null, hashSetName);
 
  396         } 
catch (Exception e) {
 
  397             logger.log(Level.SEVERE, 
"HashDbManager listener threw exception", e); 
 
  398             MessageNotifyUtil.Notify.show(
 
  399                     NbBundle.getMessage(
this.getClass(), 
"HashDbManager.moduleErr"),
 
  400                     NbBundle.getMessage(
this.getClass(), 
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
 
  401                     MessageNotifyUtil.MessageType.ERROR);
 
  412         List<HashDb> hashDbs = 
new ArrayList<>();
 
  413         hashDbs.addAll(knownHashSets);
 
  414         hashDbs.addAll(knownBadHashSets);
 
  424         List<HashDb> hashDbs = 
new ArrayList<>();
 
  425         hashDbs.addAll(knownHashSets);
 
  435         List<HashDb> hashDbs = 
new ArrayList<>();
 
  436         hashDbs.addAll(knownBadHashSets);
 
  448         return updateableDbs;
 
  452         ArrayList<HashDb> updateableDbs = 
new ArrayList<>();
 
  453         for (
HashDb db : hashDbs) {
 
  455                 if (db.isUpdateable()) {
 
  456                     updateableDbs.add(db);
 
  458             } 
catch (TskCoreException ex) {
 
  459                 Logger.
getLogger(
HashDbManager.class.getName()).log(Level.SEVERE, 
"Error checking updateable status of " + db.getHashSetName() + 
" hash database", ex); 
 
  462         return updateableDbs;
 
  471     synchronized boolean save() {
 
  482         hashSetNames.clear();
 
  483         hashSetPaths.clear();
 
  491         for (
HashDb database : hashDatabases) {
 
  494             } 
catch (TskCoreException ex) {
 
  498         hashDatabases.clear();
 
  502         boolean success = 
false;
 
  503         DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
 
  505             DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
 
  506             Document doc = docBuilder.newDocument();
 
  507             Element rootEl = doc.createElement(ROOT_ELEMENT);
 
  508             doc.appendChild(rootEl);
 
  514         } 
catch (ParserConfigurationException ex) {
 
  521         for (
HashDb db : hashDbs) {
 
  526                 if (db.hasIndexOnly()) {
 
  527                     path = db.getIndexPath();
 
  529                     path = db.getDatabasePath();
 
  531             } 
catch (TskCoreException ex) {
 
  532                 Logger.
getLogger(
HashDbManager.class.getName()).log(Level.SEVERE, 
"Error getting path of hash database " + db.getHashSetName() + 
", discarding from hash database configuration", ex); 
 
  536             Element setElement = doc.createElement(SET_ELEMENT);
 
  537             setElement.setAttribute(SET_NAME_ATTRIBUTE, db.getHashSetName());
 
  538             setElement.setAttribute(SET_TYPE_ATTRIBUTE, db.getKnownFilesType().toString());
 
  539             setElement.setAttribute(SEARCH_DURING_INGEST_ATTRIBUTE, Boolean.toString(db.getSearchDuringIngest()));
 
  540             setElement.setAttribute(SEND_INGEST_MESSAGES_ATTRIBUTE, Boolean.toString(db.getSendIngestMessages()));
 
  541             Element pathElement = doc.createElement(PATH_ELEMENT);
 
  542             pathElement.setTextContent(path);
 
  543             setElement.appendChild(pathElement);
 
  544             rootEl.appendChild(setElement);
 
  549         File f = 
new File(configFilePath);
 
  550         return f.exists() && f.canRead() && f.canWrite();
 
  554         boolean updatedSchema = 
false;
 
  563         Element root = doc.getDocumentElement();
 
  570         NodeList setsNList = root.getElementsByTagName(SET_ELEMENT);
 
  571         int numSets = setsNList.getLength();
 
  578         String attributeErrorMessage = 
" attribute was not set for hash_set at index {0}, cannot make instance of HashDb class"; 
 
  579         String elementErrorMessage = 
" element was not set for hash_set at index {0}, cannot make instance of HashDb class"; 
 
  580         for (
int i = 0; i < numSets; ++i) {
 
  581             Element setEl = (Element) setsNList.item(i);
 
  583             String hashSetName = setEl.getAttribute(SET_NAME_ATTRIBUTE);
 
  584             if (hashSetName.isEmpty()) {
 
  590             if (hashSetNames.contains(hashSetName)) {
 
  592                 String newHashSetName;
 
  595                     newHashSetName = hashSetName + suffix;
 
  596                 } 
while (hashSetNames.contains(newHashSetName));
 
  597                 JOptionPane.showMessageDialog(null,
 
  598                         NbBundle.getMessage(
this.getClass(),
 
  599                         "HashDbManager.replacingDuplicateHashsetNameMsg",
 
  600                         hashSetName, newHashSetName),
 
  601                         NbBundle.getMessage(
this.getClass(), 
"HashDbManager.openHashDbErr"),
 
  602                         JOptionPane.ERROR_MESSAGE);
 
  603                 hashSetName = newHashSetName;
 
  606             String knownFilesType = setEl.getAttribute(SET_TYPE_ATTRIBUTE);
 
  607             if (knownFilesType.isEmpty()) {
 
  613             if (knownFilesType.equals(
"NSRL")) { 
 
  615                 updatedSchema = 
true;
 
  618             final String searchDuringIngest = setEl.getAttribute(SEARCH_DURING_INGEST_ATTRIBUTE);
 
  619             if (searchDuringIngest.isEmpty()) {
 
  623             Boolean seearchDuringIngestFlag = Boolean.parseBoolean(searchDuringIngest);
 
  625             final String sendIngestMessages = setEl.getAttribute(SEND_INGEST_MESSAGES_ATTRIBUTE);
 
  626             if (searchDuringIngest.isEmpty()) {
 
  630             Boolean sendIngestMessagesFlag = Boolean.parseBoolean(sendIngestMessages);
 
  633             NodeList pathsNList = setEl.getElementsByTagName(PATH_ELEMENT);
 
  634             if (pathsNList.getLength() > 0) {
 
  635                 Element pathEl = (Element) pathsNList.item(0); 
 
  638                 String legacyPathNumber = pathEl.getAttribute(LEGACY_PATH_NUMBER_ATTRIBUTE);
 
  639                 if (null != legacyPathNumber && !legacyPathNumber.isEmpty()) {
 
  640                     updatedSchema = 
true;
 
  643                 dbPath = pathEl.getTextContent();
 
  644                 if (dbPath.isEmpty()) {
 
  654             if (null != dbPath) {
 
  656                     addExistingHashDatabaseInternal(hashSetName, dbPath, seearchDuringIngestFlag, sendIngestMessagesFlag, 
HashDb.
KnownFilesType.valueOf(knownFilesType));
 
  657                 } 
catch (HashDbManagerException | TskCoreException ex) {
 
  659                     JOptionPane.showMessageDialog(null,
 
  660                             NbBundle.getMessage(
this.getClass(),
 
  661                             "HashDbManager.unableToOpenHashDbMsg", dbPath),
 
  662                             NbBundle.getMessage(
this.getClass(), 
"HashDbManager.openHashDbErr"),
 
  663                             JOptionPane.ERROR_MESSAGE);
 
  666                 Logger.
getLogger(
HashDbManager.class.getName()).log(Level.WARNING, 
"No valid path for hash_set at index {0}, cannot make instance of HashDb class", i); 
 
  671             String backupFilePath = configFilePath + 
".v1_backup"; 
 
  672             String messageBoxTitle = NbBundle.getMessage(this.getClass(),
 
  673                     "HashDbManager.msgBoxTitle.confFileFmtChanged");
 
  674             String baseMessage = NbBundle.getMessage(this.getClass(),
 
  675                     "HashDbManager.baseMessage.updatedFormatHashDbConfig");
 
  677                 FileUtils.copyFile(
new File(configFilePath), 
new File(backupFilePath));
 
  678                 JOptionPane.showMessageDialog(null,
 
  679                         NbBundle.getMessage(
this.getClass(),
 
  680                         "HashDbManager.savedBackupOfOldConfigMsg",
 
  681                         baseMessage, backupFilePath),
 
  683                         JOptionPane.INFORMATION_MESSAGE);
 
  684             } 
catch (IOException ex) {
 
  685                 Logger.
getLogger(
HashDbManager.class.getName()).log(Level.WARNING, 
"Failed to save backup of old format configuration file to " + backupFilePath, ex); 
 
  686                 JOptionPane.showMessageDialog(null, baseMessage, messageBoxTitle, JOptionPane.INFORMATION_MESSAGE);
 
  697         File database = 
new File(configuredPath);
 
  698         if (database.exists()) {
 
  699             return configuredPath;
 
  703         String newPath = null;
 
  704         if (JOptionPane.showConfirmDialog(null,
 
  705                 NbBundle.getMessage(
this.getClass(), 
"HashDbManager.dlgMsg.dbNotFoundAtLoc",
 
  706                 hashSetName, configuredPath),
 
  707                 NbBundle.getMessage(
this.getClass(), 
"HashDbManager.dlgTitle.MissingDb"),
 
  708                 JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
 
  710             if (null != newPath && !newPath.isEmpty()) {
 
  711                 database = 
new File(newPath);
 
  712                 if (!database.exists()) {
 
  721         String filePath = null;
 
  722         JFileChooser fc = 
new JFileChooser();
 
  723         fc.setDragEnabled(
false);
 
  724         fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
  725         String[] EXTENSION = 
new String[]{
"txt", 
"idx", 
"hash", 
"Hash", 
"kdb"}; 
 
  726         FileNameExtensionFilter filter = 
new FileNameExtensionFilter(
 
  727                 NbBundle.getMessage(
this.getClass(), 
"HashDbManager.fileNameExtensionFilter.title"), EXTENSION);
 
  728         fc.setFileFilter(filter);
 
  729         fc.setMultiSelectionEnabled(
false);
 
  730         if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
 
  731             File f = fc.getSelectedFile();
 
  733                 filePath = f.getCanonicalPath();
 
  734             } 
catch (IOException ex) {
 
  758                 this.displayName = displayName;
 
  762                 return this.displayName;
 
  781         private HashDb(
int handle, String hashSetName, 
boolean useForIngest, 
boolean sendHitMessages, 
KnownFilesType knownFilesType) {
 
  784             this.searchDuringIngest = useForIngest;
 
  785             this.sendIngestMessages = sendHitMessages;
 
  787             this.indexing = 
false;
 
  794             propertyChangeSupport.addPropertyChangeListener(pcl);
 
  801             propertyChangeSupport.removePropertyChangeListener(pcl);
 
  824         void setSearchDuringIngest(
boolean useForIngest) {
 
  825             this.searchDuringIngest = useForIngest;
 
  832         void setSendIngestMessages(
boolean showInboxMessages) {
 
  833             this.sendIngestMessages = showInboxMessages;
 
  868             if (content instanceof AbstractFile) {
 
  869                 AbstractFile file = (AbstractFile) content;
 
  882         public void addHashes(List<HashEntry> hashes) 
throws TskCoreException {
 
  893             boolean result = 
false;
 
  895             if (content instanceof AbstractFile) {
 
  896                 AbstractFile file = (AbstractFile) content;
 
  914             if (content instanceof AbstractFile) {
 
  915                 AbstractFile file = (AbstractFile) content;
 
  924         boolean hasIndex() throws TskCoreException {
 
  928         boolean hasIndexOnly() throws TskCoreException {
 
  932         boolean canBeReIndexed() throws TskCoreException {
 
  933             return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
 
  936         boolean isIndexing() {
 
  940         private void close() throws TskCoreException {
 
  962             progress = ProgressHandleFactory.createHandle(
 
  963                     NbBundle.getMessage(
this.getClass(), 
"HashDbManager.progress.indexingHashSet", hashDb.
hashSetName));
 
  965             progress.switchToIndeterminate();
 
  968             } 
catch (TskCoreException ex) {
 
  970                 JOptionPane.showMessageDialog(null,
 
  971                         NbBundle.getMessage(
this.getClass(),
 
  972                         "HashDbManager.dlgMsg.errorIndexingHashSet",
 
  974                         NbBundle.getMessage(
this.getClass(), 
"HashDbManager.hashDbIndexingErr"),
 
  975                         JOptionPane.ERROR_MESSAGE);
 
  988             } 
catch (InterruptedException | ExecutionException ex) {
 
  989                 logger.log(Level.SEVERE, 
"Error creating index", ex); 
 
  991                         NbBundle.getMessage(
this.getClass(), 
"HashDbManager.errCreatingIndex.title"),
 
  992                         NbBundle.getMessage(
this.getClass(), 
"HashDbManager.errCreatingIndex.msg", ex.getMessage()),
 
  996             catch (java.util.concurrent.CancellationException ex ) { }
 
 1001             } 
catch (Exception e) {
 
 1002                 logger.log(Level.SEVERE, 
"HashDbManager listener threw exception", e); 
 
 1004                         NbBundle.getMessage(
this.getClass(), 
"HashDbManager.moduleErr"),
 
 1005                         NbBundle.getMessage(
this.getClass(), 
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
 
boolean getSendIngestMessages()
 
Set< String > hashSetPaths
 
static String getHashDatabaseIndexPath(int dbHandle)
 
static void createLookupIndexForHashDatabase(int dbHandle)
 
static final Logger logger
 
static final String HASH_DATABASE_FILE_EXTENSON
 
static void addToHashDatabase(String filename, String md5, String sha1, String sha256, String comment, int dbHandle)
 
void addHashes(Content content, String comment)
 
static synchronized IngestManager getInstance()
 
static< T > Document loadDoc(Class< T > clazz, String xmlPath)
 
boolean getSearchDuringIngest()
 
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
 
HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
 
boolean hashSetsConfigurationFileExists()
 
HashDbManagerException(String message)
 
static final String LEGACY_PATH_NUMBER_ATTRIBUTE
 
final PropertyChangeSupport propertyChangeSupport
 
HashDb addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
 
static HashHitInfo lookupInHashDatabaseVerbose(String hash, int dbHandle)
 
boolean readHashSetsConfigurationFromDisk()
 
KnownFilesType knownFilesType
 
boolean isIngestRunning()
 
static void writeHashDbsToDisk(Document doc, Element rootEl, List< HashDb > hashDbs)
 
static final String SET_NAME_ATTRIBUTE
 
List< HashDb > getUpdateableHashSets(List< HashDb > hashDbs)
 
static final String SET_TYPE_ATTRIBUTE
 
List< HashDb > knownHashSets
 
static final String ENCODING
 
static boolean hashDatabaseIsIndexOnly(int dbHandle)
 
HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
 
boolean writeHashSetConfigurationToDisk()
 
static final String PATH_ELEMENT
 
synchronized void removeHashDatabase(HashDb hashDb)
 
KnownFilesType(String displayName)
 
void addPropertyChangeListener(PropertyChangeListener pcl)
 
List< HashDb > knownBadHashSets
 
final String configFilePath
 
synchronized List< HashDb > getKnownBadFileHashSets()
 
static HashDbManager instance
 
Set< String > hashSetNames
 
static synchronized HashDbManager getInstance()
 
static final String SEARCH_DURING_INGEST_ATTRIBUTE
 
String getValidFilePath(String hashSetName, String configuredPath)
 
void addHashes(List< HashEntry > hashes)
 
void addHashes(Content content)
 
HashHitInfo lookupMD5(Content content)
 
synchronized List< HashDb > getUpdateableHashSets()
 
synchronized List< HashDb > getAllHashSets()
 
static final String SET_ELEMENT
 
static boolean lookupInHashDatabase(String hash, int dbHandle)
 
static final String SEND_INGEST_MESSAGES_ATTRIBUTE
 
static boolean hashDatabaseHasLookupIndex(int dbHandle)
 
void propertyChange(PropertyChangeEvent event)
 
boolean sendIngestMessages
 
void closeHashDatabases(List< HashDb > hashDatabases)
 
boolean lookupMD5Quick(Content content)
 
boolean searchDuringIngest
 
synchronized void loadLastSavedConfiguration()
 
static void show(String title, String message, MessageType type, ActionListener actionListener)
 
static final String XSD_FILE_NAME
 
KnownFilesType getKnownFilesType()
 
static boolean isUpdateableHashDatabase(int dbHandle)
 
static final String CONFIG_FILE_NAME
 
static final String ROOT_ELEMENT
 
synchronized List< HashDb > getKnownFileHashSets()
 
void removePropertyChangeListener(PropertyChangeListener pcl)
 
HashDb(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType)
 
static String getHashDatabasePath(int dbHandle)
 
static Logger getLogger(String name)
 
static void closeHashDatabase(int dbHandle)
 
static< T > boolean saveDoc(Class< T > clazz, String xmlPath, String encoding, final Document doc)