From 8ca30ecef586917cddd2f1ffa5a35fe49ffd6066 Mon Sep 17 00:00:00 2001 From: jmillman Date: Wed, 18 Nov 2015 15:29:24 -0500 Subject: [PATCH] comments, cleanup, bundlization --- .../autopsy/timeline/PromptDialogManager.java | 87 ++++++++++++------- .../autopsy/timeline/TimeLineController.java | 56 ++++++------ 2 files changed, 81 insertions(+), 62 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java b/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java index 24b1d98bda..ef249ff1e8 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2015 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.timeline; @@ -27,24 +40,30 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** - * + * Manager for the various prompts Timeline shows the user related to rebuilding + * the database. */ public class PromptDialogManager { private static final Logger LOGGER = Logger.getLogger(PromptDialogManager.class.getName()); - private static final ButtonType SHOW_TIMELINE = new ButtonType("Show Timeline", ButtonBar.ButtonData.OK_DONE); - private static final ButtonType CONTINUE_NO_UPDATE = new ButtonType("Continue Without Updating", ButtonBar.ButtonData.CANCEL_CLOSE); - private static final ButtonType UPDATE = new ButtonType("Update", ButtonBar.ButtonData.OK_DONE); + @NbBundle.Messages("PrompDialogManager.buttonType.showTimeline=Show Timeline") + private static final ButtonType SHOW_TIMELINE = new ButtonType(Bundle.PrompDialogManager_buttonType_showTimeline(), ButtonBar.ButtonData.OK_DONE); + + @NbBundle.Messages("PrompDialogManager.buttonType.continueNoUpdate=Continue Without Updating") + private static final ButtonType CONTINUE_NO_UPDATE = new ButtonType(Bundle.PrompDialogManager_buttonType_continueNoUpdate(), ButtonBar.ButtonData.CANCEL_CLOSE); + + @NbBundle.Messages("PrompDialogManager.buttonType.update=Update") + private static final ButtonType UPDATE = new ButtonType(Bundle.PrompDialogManager_buttonType_update(), ButtonBar.ButtonData.OK_DONE); private static final Image LOGO; static { Image x = null; try { - x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); + x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NOI18N } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); + LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); //NOI18N } LOGO = x; } @@ -65,26 +84,24 @@ public class PromptDialogManager { return false; } - @ThreadConfined(type = ThreadConfined.ThreadType.JFX) @NbBundle.Messages({"PromptDialogManager.progressDialog.title=Populating Timeline Data"}) + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) public void showProgressDialog(CancellationProgressTask task) { - currentDialog = new ProgressDialog(task); - currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title()); currentDialog.headerTextProperty().bind(task.titleProperty()); + setDialogIcons(currentDialog); + currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title()); DialogPane dialogPane = currentDialog.getDialogPane(); - dialogPane.setPrefWidth(400); + dialogPane.setPrefSize(400, 200); //override autosizing which fails for some reason - dialogPane.setPrefHeight(200); + //co-ordinate task cancelation and dialog hiding. task.setOnCancelled(cancelled -> currentDialog.close()); task.setOnSucceeded(succeeded -> currentDialog.close()); - dialogPane.getButtonTypes().setAll(ButtonType.CANCEL); final Node cancelButton = dialogPane.lookupButton(ButtonType.CANCEL); cancelButton.disableProperty().bind(task.cancellableProperty().not()); currentDialog.setOnCloseRequest(closeRequest -> { - if (task.isRunning()) { closeRequest.consume(); } @@ -93,43 +110,49 @@ public class PromptDialogManager { } }); - Stage stage = (Stage) dialogPane.getScene().getWindow(); - stage.getIcons().setAll(LOGO); currentDialog.show(); } + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) + static private void setDialogIcons(Dialog dialog) { + Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow(); + stage.getIcons().setAll(LOGO); + } + + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) + static private void setDialogTitle(Dialog dialog) { + Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow(); + stage.setTitle(Bundle.Timeline_confirmation_dialogs_title()); + } + /** * prompt the user that ingest is running and the db may not end up * complete. * * @return true if they want to continue anyways */ - @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - @NbBundle.Messages({"PromptDialogManager.confirmDuringIngest.headerText=You are trying to generate a timeline before ingest has been completed." - + "\nThe timeline may be incomplete.", + @NbBundle.Messages({"PromptDialogManager.confirmDuringIngest.headerText=You are trying to show a timeline before ingest has been completed.\nThe timeline may be incomplete.", "PromptDialogManager.confirmDuringIngest.contentText=Do you want to continue?"}) - synchronized boolean confirmDuringIngest() { + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) + boolean confirmDuringIngest() { currentDialog = new Alert(Alert.AlertType.CONFIRMATION, Bundle.PromptDialogManager_confirmDuringIngest_contentText(), SHOW_TIMELINE, ButtonType.CANCEL); currentDialog.initModality(Modality.APPLICATION_MODAL); currentDialog.setHeaderText(Bundle.PromptDialogManager_confirmDuringIngest_headerText()); - brandDialog(); + setDialogIcons(currentDialog); + setDialogTitle(currentDialog); + return currentDialog.showAndWait().map(SHOW_TIMELINE::equals).orElse(false); } - private void brandDialog() { - Stage stage = (Stage) currentDialog.getDialogPane().getScene().getWindow(); - stage.setTitle(Bundle.Timeline_confirmation_dialogs_title()); - stage.getIcons().setAll(LOGO); - } - - @NbBundle.Messages({"PromptDialogManager.rebuildPrompt.headerText=The Timeline database is incomplete and/or out of date." - + "\nSome events may be missing or inaccurate and some features may be unavailable.", + @NbBundle.Messages({"PromptDialogManager.rebuildPrompt.headerText=The Timeline database is incomplete and/or out of date.\nSome events may be missing or inaccurate and some features may be unavailable.", "PromptDialogManager.rebuildPrompt.details=Details:"}) + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) boolean confirmRebuild(ArrayList rebuildReasons) { currentDialog = new Alert(Alert.AlertType.CONFIRMATION, Bundle.TimeLinecontroller_updateNowQuestion(), UPDATE, CONTINUE_NO_UPDATE); currentDialog.initModality(Modality.APPLICATION_MODAL); currentDialog.setHeaderText(Bundle.PromptDialogManager_rebuildPrompt_headerText()); - brandDialog(); + setDialogIcons(currentDialog); + setDialogTitle(currentDialog); DialogPane dialogPane = currentDialog.getDialogPane(); ListView listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons)); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index b2abdef96f..f8f4f029e2 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -119,7 +119,7 @@ public class TimeLineController { } public static DateTimeFormatter getZonedFormatter() { - return DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss").withZone(getJodaTimeZone()); // NON-NLS + return DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss").withZone(getJodaTimeZone()); // NON-NLS //NOI18N } public static DateTimeZone getJodaTimeZone() { @@ -420,7 +420,7 @@ public class TimeLineController { } } catch (HeadlessException | MissingResourceException ex) { - LOGGER.log(Level.SEVERE, "Unexpected error when generating timeline, ", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Unexpected error when generating timeline, ", ex); // NON-NLS //NOI18N } }); } @@ -444,30 +444,34 @@ public class TimeLineController { } @ThreadConfined(type = ThreadConfined.ThreadType.ANY) + @NbBundle.Messages({"TimeLineController.errorTitle=Timeline error.", + "TimeLineController.outOfDate.errorMessage=Error determing if the timeline is out of date. We will assume it should be updated. See the logs for more details.", + "TimeLineController.rebuildReasons.outOfDateError=Could not determine if the timeline data is out of date.", + "TimeLineController.rebuildReasons.outOfDate=The event data is out of date: Not all events will be visible.", + "TimeLineController.rebuildReasons.ingestWasRunning=The Timeline events database was previously populated while ingest was running: Some events may be missing, incomplete, or inaccurate.", + "TimeLineController.rebuildReasons.incompleteOldSchema=The Timeline events database was previously populated without incomplete information: Some features may be unavailable or non-functional unless you update the events database."}) private ArrayList getRebuildReasons() { ArrayList rebuildReasons = new ArrayList<>(); //if ingest was running during last rebuild, prompt to rebuild if (eventsRepository.getWasIngestRunning()) { - rebuildReasons.add("The Timeline events database was previously populated while ingest was running:" - + " Some events may be missing, incomplete, or inaccurate"); + rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning()); } final SleuthkitCase sleuthkitCase = autoCase.getSleuthkitCase(); try { //if the last artifact and object ids don't match between skc and tldb, prompt to rebuild if (sleuthkitCase.getLastObjectId() != eventsRepository.getLastObjID() || getCaseLastArtifactID(sleuthkitCase) != eventsRepository.getLastArtfactID()) { - rebuildReasons.add("The event data is out of date: Not all events will be visible."); + rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDate()); } } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error determing last object id from sleutkit case. We will assume the timeline is out of date.", ex); // NON-NLS - MessageNotifyUtil.Notify.error("Timeline error.", - "Error determing if the timeline is out of date. We will assume it should be updated. See the logs for more details."); - rebuildReasons.add("Could not determine if the timeline data is out of date."); + LOGGER.log(Level.SEVERE, "Error determing last object id from sleutkit case. We will assume the timeline is out of date.", ex); // NON-NLS + MessageNotifyUtil.Notify.error(Bundle.TimeLineController_errorTitle(), + Bundle.TimeLineController_outOfDate_errorMessage()); + rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDateError()); } // if the TLDB schema has been upgraded since last time TL ran, prompt for rebuild if (eventsRepository.hasNewColumns() == false) { - rebuildReasons.add("The Timeline events database was previously populated without incomplete information:" - + " Some features may be unavailable or non-functional unless you update the events database."); + rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_incompleteOldSchema()); } return rebuildReasons; } @@ -475,14 +479,14 @@ public class TimeLineController { public static long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase) { //TODO: push this into sleuthkitCase long caseLastArtfId = -1; - String query = "select Max(artifact_id) as max_id from blackboard_artifacts"; // NON-NLS + String query = "select Max(artifact_id) as max_id from blackboard_artifacts"; // NON-NLS //NOI18N try (CaseDbQuery dbQuery = sleuthkitCase.executeQuery(query)) { ResultSet resultSet = dbQuery.getResultSet(); while (resultSet.next()) { - caseLastArtfId = resultSet.getLong("max_id"); // NON-NLS + caseLastArtfId = resultSet.getLong("max_id"); // NON-NLS //NOI18N } } catch (TskCoreException | SQLException ex) { - LOGGER.log(Level.SEVERE, "Error getting last artifact id: ", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error getting last artifact id: ", ex); // NON-NLS //NOI18N } return caseLastArtfId; } @@ -523,7 +527,7 @@ public class TimeLineController { } public void selectEventIDs(Collection events) { - final LoggedTask selectEventIDsTask = new LoggedTask("Select Event IDs", true) { // NON-NLS + final LoggedTask selectEventIDsTask = new LoggedTask("Select Event IDs", true) { // NON-NLS //NOI18N @Override protected Interval call() throws Exception { return filteredEvents.getSpanningInterval(events); @@ -538,12 +542,8 @@ public class TimeLineController { selectedEventIDs.setAll(events); } - } catch (InterruptedException ex) { - Logger.getLogger(FilteredEventsModel.class - .getName()).log(Level.SEVERE, getTitle() + " interrupted unexpectedly", ex); // NON-NLS - } catch (ExecutionException ex) { - Logger.getLogger(FilteredEventsModel.class - .getName()).log(Level.SEVERE, getTitle() + " unexpectedly threw " + ex.getCause(), ex); // NON-NLS + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, getTitle() + " Unexpected error", ex); // NON-NLS //NOI18N } } }; @@ -587,8 +587,7 @@ public class TimeLineController { } @NbBundle.Messages({"# {0} - the number of events", - "Timeline.pushDescrLOD.confdlg.msg=You are about to show details for {0} events." - + " This might be very slow or even crash Autopsy.\n\nDo you want to continue?", + "Timeline.pushDescrLOD.confdlg.msg=You are about to show details for {0} events. This might be very slow or even crash Autopsy.\n\nDo you want to continue?", "Timeline.pushDescrLOD.confdlg.title=Change description level of detail?"}) synchronized public boolean pushDescrLOD(DescriptionLoD newLOD) { Map eventCounts = filteredEvents.getEventCounts(filteredEvents.zoomParametersProperty().get().getTimeRange()); @@ -655,7 +654,7 @@ public class TimeLineController { public void selectTimeAndType(Interval interval, EventType type) { final Interval timeRange = filteredEvents.getSpanningInterval().overlap(interval); - final LoggedTask> selectTimeAndTypeTask = new LoggedTask>("Select Time and Type", true) { // NON-NLS + final LoggedTask> selectTimeAndTypeTask = new LoggedTask>("Select Time and Type", true) { // NON-NLS //NOI18N @Override protected Collection< Long> call() throws Exception { synchronized (TimeLineController.this) { @@ -672,12 +671,8 @@ public class TimeLineController { selectedEventIDs.setAll(get()); } - } catch (InterruptedException ex) { - Logger.getLogger(FilteredEventsModel.class - .getName()).log(Level.SEVERE, getTitle() + " interrupted unexpectedly", ex);// NON-NLS - } catch (ExecutionException ex) { - Logger.getLogger(FilteredEventsModel.class - .getName()).log(Level.SEVERE, getTitle() + " unexpectedly threw " + ex.getCause(), ex);// NON-NLS + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, getTitle() + " Unexpected error", ex); // NON-NLS //NOI18N } } }; @@ -692,6 +687,7 @@ public class TimeLineController { * @param task */ synchronized public void monitorTask(final Task task) { + //TODO: refactor this to use JavaFX Service? -jm if (task != null) { Platform.runLater(() -> {