Merge pull request #4160 from millmanorama/1033-backwards-compatibility

1033 backwards compatibility
This commit is contained in:
Richard Cordovano 2018-10-01 09:41:53 -04:00 committed by GitHub
commit 7720331a0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 119 additions and 45 deletions

View File

@ -62,14 +62,10 @@ public class ImageGalleryModule {
private static final Object controllerLock = new Object(); private static final Object controllerLock = new Object();
private static ImageGalleryController controller; private static ImageGalleryController controller;
public static ImageGalleryController getController() throws NoCurrentCaseException { public static ImageGalleryController getController() throws TskCoreException, NoCurrentCaseException {
synchronized (controllerLock) { synchronized (controllerLock) {
if (controller == null) { if (controller == null) {
try { controller = new ImageGalleryController(Case.getCurrentCaseThrows());
controller = new ImageGalleryController(Case.getCurrentCaseThrows());
} catch (NoCurrentCaseException | TskCoreException ex) {
throw new NoCurrentCaseException("Error getting ImageGalleryController for the current case.", ex);
}
} }
return controller; return controller;
} }
@ -207,6 +203,8 @@ public class ImageGalleryModule {
} }
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
} }
} }
else if (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName()) == DATA_ADDED) { else if (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName()) == DATA_ADDED) {
@ -250,6 +248,9 @@ public class ImageGalleryModule {
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS
return; return;
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
return;
} }
switch (Case.Events.valueOf(evt.getPropertyName())) { switch (Case.Events.valueOf(evt.getPropertyName())) {
case CURRENT_CASE: case CURRENT_CASE:
@ -327,31 +328,32 @@ public class ImageGalleryModule {
} }
// A remote node added a new data source and just finished ingest on it. // A remote node added a new data source and just finished ingest on it.
//drawable db is stale, and if ImageGallery is open, ask user what to do //drawable db is stale, and if ImageGallery is open, ask user what to do
ImageGalleryController con;
try { try {
con = getController(); ImageGalleryController con = getController();
con.setStale(true);
if (con.isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) {
SwingUtilities.invokeLater(() -> {
int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
switch (showAnswer) {
case JOptionPane.YES_OPTION:
con.rebuildDB();
break;
case JOptionPane.NO_OPTION:
case JOptionPane.CANCEL_OPTION:
default:
break; //do nothing
}
});
}
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS
return; } catch (TskCoreException ex) {
} logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
con.setStale(true);
if (con.isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) {
SwingUtilities.invokeLater(() -> {
int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
switch (showAnswer) {
case JOptionPane.YES_OPTION:
con.rebuildDB();
break;
case JOptionPane.NO_OPTION:
case JOptionPane.CANCEL_OPTION:
default:
break; //do nothing
}
});
} }
} }
} }

View File

@ -18,21 +18,26 @@
*/ */
package org.sleuthkit.autopsy.imagegallery; package org.sleuthkit.autopsy.imagegallery;
import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* The Image/Video Gallery panel in the NetBeans provided Options Dialogs * The Image/Video Gallery panel in the NetBeans provided Options Dialogs
* accessed via Tools -> Options * accessed via Tools -> Options
* *
* Uses {@link ImageGalleryPreferences} and {@link PerCaseProperties} to persist * Uses ImageGalleryPreferences and PerCaseProperties to persist
* settings * settings
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class ImageGalleryOptionsPanel extends javax.swing.JPanel { final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(ImageGalleryOptionsPanel.class.getName());
ImageGalleryOptionsPanel(ImageGalleryOptionsPanelController controller) { ImageGalleryOptionsPanel(ImageGalleryOptionsPanelController controller) {
initComponents(); initComponents();
@ -206,6 +211,8 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
new PerCaseProperties(openCase).setConfigSetting(ImageGalleryModule.getModuleName(), PerCaseProperties.ENABLED, Boolean.toString(enabledForCaseBox.isSelected())); new PerCaseProperties(openCase).setConfigSetting(ImageGalleryModule.getModuleName(), PerCaseProperties.ENABLED, Boolean.toString(enabledForCaseBox.isSelected()));
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
// It's not an error if there's no case open // It's not an error if there's no case open
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
} }
} }

View File

@ -50,6 +50,7 @@ import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.ObjectUtils.notEqual; import static org.apache.commons.lang3.ObjectUtils.notEqual;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils; import org.openide.explorer.ExplorerUtils;
import org.openide.util.Exceptions;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
@ -154,7 +155,7 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
"ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.contentText=Data source:", "ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.contentText=Data source:",
"ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.all=All", "ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.all=All",
"ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.titleText=Image Gallery",}) "ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.titleText=Image Gallery",})
public static void openTopComponent() throws NoCurrentCaseException { public static void openTopComponent() throws NoCurrentCaseException, TskCoreException {
// This creates the top component and adds the UI widgets if it has not yet been opened // This creates the top component and adds the UI widgets if it has not yet been opened
final TopComponent topComponent = WindowManager.getDefault().findTopComponent(PREFERRED_ID); final TopComponent topComponent = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
@ -174,6 +175,7 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
ImageGalleryController controller = ImageGalleryModule.getController(); ImageGalleryController controller = ImageGalleryModule.getController();
((ImageGalleryTopComponent) topComponent).setController(controller); ((ImageGalleryTopComponent) topComponent).setController(controller);
// Display the UI so taht they can see the progress screen // Display the UI so taht they can see the progress screen
showTopComponent(topComponent); showTopComponent(topComponent);
@ -185,6 +187,7 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
logger.log(Level.SEVERE, "Unable to get data sourcecs.", tskCoreException); logger.log(Level.SEVERE, "Unable to get data sourcecs.", tskCoreException);
} }
GroupManager groupManager = controller.getGroupManager(); GroupManager groupManager = controller.getGroupManager();
synchronized (groupManager) { synchronized (groupManager) {
if (dataSources.size() <= 1 if (dataSources.size() <= 1
@ -237,10 +240,16 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
} }
} }
public ImageGalleryTopComponent() throws NoCurrentCaseException { public ImageGalleryTopComponent() {
setName(Bundle.CTL_ImageGalleryTopComponent()); setName(Bundle.CTL_ImageGalleryTopComponent());
initComponents(); initComponents();
setController(ImageGalleryModule.getController()); try {
setController(ImageGalleryModule.getController());
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
}
} }
synchronized private void setController(ImageGalleryController controller) { synchronized private void setController(ImageGalleryController controller) {

View File

@ -143,7 +143,7 @@ public final class OpenAction extends CallableSystemAction {
return; return;
} }
try { try {
ImageGalleryController controller = ImageGalleryModule.getController(); ImageGalleryController controller = ImageGalleryModule.getController();
if (controller.isDataSourcesTableStale()) { if (controller.isDataSourcesTableStale()) {
//drawable db is stale, ask what to do //drawable db is stale, ask what to do
int answer = JOptionPane.showConfirmDialog( int answer = JOptionPane.showConfirmDialog(
@ -162,9 +162,13 @@ public final class OpenAction extends CallableSystemAction {
* user may want to review images, so we rebuild the * user may want to review images, so we rebuild the
* database only when a user launches Image Gallery. * database only when a user launches Image Gallery.
*/ */
if (currentCase.getCaseType() == Case.CaseType.SINGLE_USER_CASE) { if (currentCase.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
/*
* Turning listening off is necessary in order to
* invoke the listener that will call
* controller.rebuildDB();
*/
controller.setListeningEnabled(false);
controller.setListeningEnabled(true); controller.setListeningEnabled(true);
} else { } else {
controller.rebuildDB(); controller.rebuildDB();
@ -183,8 +187,10 @@ public final class OpenAction extends CallableSystemAction {
//drawable db is not stale, just open it //drawable db is not stale, just open it
ImageGalleryTopComponent.openTopComponent(); ImageGalleryTopComponent.openTopComponent();
} }
} catch (NoCurrentCaseException noCurrentCaseException) { } catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "There was no case open when Image Gallery was opened.", noCurrentCaseException); logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
} }
} }

View File

@ -360,8 +360,10 @@ public final class DrawableDB {
} }
/** /**
* public factory method. Creates and opens a connection to a new database * * Public factory method. Creates and opens a connection to a new database *
* at the given path. * * at the given path. If there is already a db at the path, it is checked
* for compatibility, and deleted if it is incompatible, before a connection
* is opened.
* *
* @param controller * @param controller
* *
@ -370,16 +372,62 @@ public final class DrawableDB {
* @throws org.sleuthkit.datamodel.TskCoreException * @throws org.sleuthkit.datamodel.TskCoreException
*/ */
public static DrawableDB getDrawableDB(ImageGalleryController controller) throws TskCoreException { public static DrawableDB getDrawableDB(ImageGalleryController controller) throws TskCoreException {
Path dbPath = ImageGalleryModule.getModuleOutputDir(controller.getAutopsyCase()); Path dbPath = ImageGalleryModule.getModuleOutputDir(controller.getAutopsyCase()).resolve("drawable.db");
boolean hasDataSourceObjIdColumn = hasDataSourceObjIdColumn(dbPath);
try { try {
return new DrawableDB(dbPath.resolve("drawable.db"), controller); //NON-NLS if (hasDataSourceObjIdColumn == false) {
Files.deleteIfExists(dbPath);
}
} catch (IOException ex) {
throw new TskCoreException("Error deleting old database", ex); //NON-NLS
}
try {
return new DrawableDB(dbPath, controller); //NON-NLS
} catch (SQLException ex) { } catch (SQLException ex) {
throw new TskCoreException("sql error creating database connection", ex); //NON-NLS throw new TskCoreException("SQL error creating database connection", ex); //NON-NLS
} catch (IOException ex) { } catch (IOException ex) {
throw new TskCoreException("Error creating database connection", ex); //NON-NLS throw new TskCoreException("Error creating database connection", ex); //NON-NLS
} }
} }
/**
* Check if the db at the given path has the data_source_obj_id column. If
* the db doesn't exist or doesn't even have the drawable_files table, this
* method returns false.
*
* NOTE: This method makes an ad-hoc connection to db, which has the side
* effect of creating the drawable.db file if it didn't already exist.
*/
private static boolean hasDataSourceObjIdColumn(Path dbPath) throws TskCoreException {
try (Connection con = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toString()); //NON-NLS
Statement stmt = con.createStatement();) {
boolean tableExists = false;
try (ResultSet results = stmt.executeQuery("SELECT name FROM sqlite_master WHERE type='table'");) {//NON-NLS
while (results.next()) {
if ("drawable_files".equals(results.getString("name"))) {
tableExists = true;
break;
}
}
}
if (false == tableExists) {
return false;
}
try (ResultSet results = stmt.executeQuery("PRAGMA table_info('drawable_files')");) { //NON-NLS
while (results.next()) {
if ("data_source_obj_id".equals(results.getString("name"))) {
return true;
}
}
}
} catch (SQLException ex) {
throw new TskCoreException("SQL error checking database compatibility", ex); //NON-NLS
}
return false;
}
private void setPragmas() throws SQLException { private void setPragmas() throws SQLException {
//this should match Sleuthkit db setupt //this should match Sleuthkit db setupt

View File

@ -46,7 +46,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
public class DrawableGroup implements Comparable<DrawableGroup> { public class DrawableGroup implements Comparable<DrawableGroup> {
private static final Logger LOGGER = Logger.getLogger(DrawableGroup.class.getName()); private static final Logger logger = Logger.getLogger(DrawableGroup.class.getName());
public static String getBlankGroupName() { public static String getBlankGroupName() {
return "unknown"; return "unknown";
@ -128,7 +128,9 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
.filter(Boolean::booleanValue) .filter(Boolean::booleanValue)
.count()); .count());
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
LOGGER.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS logger.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS
} }
} }
return hashSetHitsCount.get(); return hashSetHitsCount.get();
@ -145,7 +147,7 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
uncatCount.set(ImageGalleryModule.getController().getDatabase().getUncategorizedCount(fileIDs)); uncatCount.set(ImageGalleryModule.getController().getDatabase().getUncategorizedCount(fileIDs));
} catch (TskCoreException | NoCurrentCaseException ex) { } catch (TskCoreException | NoCurrentCaseException ex) {
LOGGER.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS logger.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS
} }
} }