1
0
mirror of https://github.com/elisspace/autopsy.git synced 2026-09-06 02:24:30 +00:00

comments, cleanup, bundlization

This commit is contained in:
jmillman
2015-11-18 15:29:24 -05:00
parent 3d5592a994
commit 8ca30ecef5
2 changed files with 81 additions and 62 deletions

View File

@@ -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 <at> sleuthkit <dot> 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<String> 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<String> listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons));

View File

@@ -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<String> getRebuildReasons() {
ArrayList<String> 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<Long> events) {
final LoggedTask<Interval> selectEventIDsTask = new LoggedTask<Interval>("Select Event IDs", true) { // NON-NLS
final LoggedTask<Interval> selectEventIDsTask = new LoggedTask<Interval>("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<EventType, Long> 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<Collection<Long>> selectTimeAndTypeTask = new LoggedTask<Collection<Long>>("Select Time and Type", true) { // NON-NLS
final LoggedTask<Collection<Long>> selectTimeAndTypeTask = new LoggedTask<Collection<Long>>("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(() -> {