19package org.sleuthkit.autopsy.geolocation;
21import java.awt.BorderLayout;
22import java.awt.Component;
23import java.awt.event.ActionEvent;
24import java.awt.event.ActionListener;
25import java.beans.PropertyChangeEvent;
26import java.beans.PropertyChangeListener;
28import java.io.IOException;
29import java.text.DateFormat;
30import java.text.SimpleDateFormat;
32import java.util.EnumSet;
33import java.util.LinkedHashSet;
35import java.util.Locale;
37import java.util.logging.Level;
38import javax.swing.JOptionPane;
39import javax.swing.SwingUtilities;
40import javax.swing.SwingWorker;
41import org.openide.filesystems.FileUtil;
42import org.openide.util.NbBundle.Messages;
43import org.openide.windows.RetainLocation;
44import org.openide.windows.TopComponent;
45import org.openide.windows.WindowManager;
46import org.sleuthkit.autopsy.casemodule.Case;
47import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE;
48import org.sleuthkit.autopsy.coreutils.Logger;
49import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
50import org.sleuthkit.autopsy.coreutils.ThreadConfined;
51import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
52import org.sleuthkit.autopsy.ingest.IngestManager;
53import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
54import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
55import org.sleuthkit.autopsy.report.ReportProgressPanel;
56import org.sleuthkit.autopsy.report.modules.kml.KMLReport;
57import org.sleuthkit.datamodel.BlackboardArtifact;
63@TopComponent.Description(preferredID =
"GeolocationTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
64@TopComponent.Registration(mode =
"geolocation", openAtStartup =
false)
65@RetainLocation(
"geolocation")
66@SuppressWarnings(
"PMD.SingularField")
79 final RefreshPanel refreshPanel =
new RefreshPanel();
81 private static final String
REPORT_PATH_FMT_STR =
"%s" + File.separator +
"%s %s %s" + File.separator;
84 private static final String
REPORT_KML =
"ReportKML.kml";
89 "GLTopComponent_name=Geolocation",
90 "GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete.",
91 "GLTopComponent_No_dataSource_message=There are no data sources with Geolocation artifacts found.",
92 "GLTopComponent_No_dataSource_Title=No Geolocation artifacts found"
99 @SuppressWarnings(
"deprecation")
103 setName(Bundle.GLTopComponent_name());
105 this.ingestListener = pce -> {
106 String eventType = pce.getPropertyName();
107 if (eventType.equals(DATA_ADDED.toString())) {
110 if (
null != eventData
113 || eventData.
getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID()
125 this.caseEventListener = pce -> {
127 if (pce.getNewValue() !=
null) {
132 refreshPanel.addCloseActionListener(
new ActionListener() {
134 public void actionPerformed(ActionEvent e) {
139 refreshPanel.addRefreshActionListner(
new ActionListener() {
141 public void actionPerformed(ActionEvent e) {
152 public void actionPerformed(ActionEvent e) {
157 geoFilterPanel.addPropertyChangeListener(GeoFilterPanel.INITPROPERTY,
new PropertyChangeListener() {
159 public void propertyChange(PropertyChangeEvent evt) {
164 setWaypointLoading(
false);
166 Bundle.GLTopComponent_No_dataSource_message(),
167 Bundle.GLTopComponent_No_dataSource_Title(),
168 JOptionPane.ERROR_MESSAGE);
174 mapPanel.addPropertyChangeListener(
MapPanel.CURRENT_MOUSE_GEOPOSITION,
new PropertyChangeListener() {
176 public void propertyChange(PropertyChangeEvent evt) {
178 Object newValue = evt.getNewValue();
179 if (newValue !=
null) {
180 label = newValue.toString();
198 super.removeNotify();
205 super.componentOpened();
206 WindowManager.getDefault().setTopComponentFloating(
this,
true);
217 if (filter ==
null) {
221 if (this.isOpened()) {
230 "GeolocationTC_connection_failure_message=Failed to connect to map title source.\nPlease review map source in Options dialog.",
231 "GeolocationTC_connection_failure_message_title=Connection Failure"
243 JOptionPane.showMessageDialog(
this,
244 Bundle.GeolocationTC_connection_failure_message(),
245 Bundle.GeolocationTC_connection_failure_message_title(),
246 JOptionPane.ERROR_MESSAGE);
248 Bundle.GeolocationTC_connection_failure_message_title(),
249 Bundle.GeolocationTC_connection_failure_message());
250 logger.log(Level.SEVERE, ex.getMessage(), ex);
258 mapPanel.setWaypoints(
new LinkedHashSet<>());
268 SwingUtilities.invokeLater(
new Runnable() {
271 boolean isShowing =
false;
272 Component[] comps =
mapPanel.getComponents();
273 for (Component comp : comps) {
274 if (comp.equals(refreshPanel)) {
279 if (show && !isShowing) {
280 mapPanel.add(refreshPanel, BorderLayout.NORTH);
282 }
else if (!show && isShowing) {
296 "GeoTopComponent_no_waypoints_returned_mgs=Applied filter failed to find waypoints that matched criteria.\nRevise filter options and try again.",
297 "GeoTopComponent_no_waypoints_returned_Title=No Waypoints Found",
298 "GeoTopComponent_filter_exception_msg=Exception occurred during waypoint filtering.",
299 "GeoTopComponent_filter_exception_Title=Filter Failure",
300 "GeoTopComponent_filer_data_invalid_msg=Unable to run waypoint filter.\nPlease select one or more data sources.",
301 "GeoTopComponent_filer_data_invalid_Title=Filter Failure"
310 JOptionPane.showMessageDialog(
this,
312 Bundle.GeoTopComponent_filer_data_invalid_Title(),
313 JOptionPane.INFORMATION_MESSAGE);
317 setWaypointLoading(
true);
320 Thread thread =
new Thread(
new Runnable() {
326 logger.log(Level.SEVERE,
"Failed to filter waypoints.", ex);
327 SwingUtilities.invokeLater(
new Runnable() {
331 Bundle.GeoTopComponent_filter_exception_Title(),
332 Bundle.GeoTopComponent_filter_exception_msg(),
333 JOptionPane.ERROR_MESSAGE);
335 setWaypointLoading(
false);
352 void addWaypointsToMap(Set<MapWaypoint> waypointList, List<Set<MapWaypoint>> tracks, List<Set<MapWaypoint>> areas) {
353 SwingUtilities.invokeLater(
new Runnable() {
357 if (waypointList ==
null || waypointList.isEmpty()) {
358 mapPanel.clearWaypoints();
360 Bundle.GeoTopComponent_no_waypoints_returned_Title(),
361 Bundle.GeoTopComponent_no_waypoints_returned_mgs(),
362 JOptionPane.INFORMATION_MESSAGE);
363 setWaypointLoading(
false);
364 geoFilterPanel.setEnabled(
true);
367 mapPanel.clearWaypoints();
368 mapPanel.setWaypoints(waypointList);
369 mapPanel.setTracks(tracks);
370 mapPanel.setAreas(areas);
371 mapPanel.initializePainter();
372 setWaypointLoading(
false);
373 geoFilterPanel.setEnabled(
true);
383 void setWaypointLoading(
boolean loading) {
384 progressBar.setEnabled(
true);
385 progressBar.setVisible(loading);
386 progressBar.setString(
"Loading Waypoints");
403 DateFormat dateFormat =
new SimpleDateFormat(
"MM-dd-yyyy-HH-mm-ss", Locale.US);
404 Date date =
new Date();
405 String dateNoTime = dateFormat.format(date);
409 FileUtil.createFolder(
new File(reportPath));
410 }
catch (IOException ex) {
411 throw new IOException(
"Failed to make report folder, unable to generate reports.", ex);
421 @SuppressWarnings(
"unchecked")
424 java.awt.GridBagConstraints gridBagConstraints;
426 filterPane =
new org.sleuthkit.autopsy.geolocation.HidingPane();
431 mapPanel =
new org.sleuthkit.autopsy.geolocation.MapPanel();
433 setLayout(
new java.awt.BorderLayout());
436 statusBar.setLayout(
new java.awt.GridBagLayout());
438 org.openide.awt.Mnemonics.setLocalizedText(
reportButton, org.openide.util.NbBundle.getMessage(
GeolocationTopComponent.class,
"GeolocationTopComponent.reportButton.text"));
439 reportButton.addActionListener(
new java.awt.event.ActionListener() {
440 public void actionPerformed(java.awt.event.ActionEvent evt) {
441 reportButtonActionPerformed(evt);
444 gridBagConstraints =
new java.awt.GridBagConstraints();
445 gridBagConstraints.gridx = 2;
446 gridBagConstraints.gridy = 0;
447 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
448 gridBagConstraints.insets =
new java.awt.Insets(5, 5, 5, 5);
449 statusBar.add(reportButton, gridBagConstraints);
451 progressBar.setIndeterminate(
true);
452 gridBagConstraints =
new java.awt.GridBagConstraints();
453 gridBagConstraints.gridx = 1;
454 gridBagConstraints.gridy = 0;
455 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
456 statusBar.add(progressBar, gridBagConstraints);
458 org.openide.awt.Mnemonics.setLocalizedText(coordLabel, org.openide.util.NbBundle.getMessage(
GeolocationTopComponent.class,
"GeolocationTopComponent.coordLabel.text"));
459 gridBagConstraints =
new java.awt.GridBagConstraints();
460 gridBagConstraints.gridx = 0;
461 gridBagConstraints.gridy = 0;
462 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
463 gridBagConstraints.weightx = 1.0;
464 gridBagConstraints.insets =
new java.awt.Insets(5, 5, 5, 0);
465 statusBar.add(coordLabel, gridBagConstraints);
467 add(statusBar, java.awt.BorderLayout.SOUTH);
468 add(mapPanel, java.awt.BorderLayout.CENTER);
472 "GeolocationTC_empty_waypoint_message=Unable to generate KML report due to a lack of waypoints.\nPlease make sure there are waypoints visible before generating the KML report",
473 "GeolocationTC_KML_report_title=KML Report",
474 "GeolocationTC_report_progress_title=KML Report Progress"
477 List<MapWaypoint> visiblePoints =
mapPanel.getVisibleWaypoints();
478 if (visiblePoints.isEmpty()) {
479 JOptionPane.showConfirmDialog(
this, Bundle.GeolocationTC_empty_waypoint_message(), Bundle.GeolocationTC_KML_report_title(), JOptionPane.OK_OPTION, JOptionPane.INFORMATION_MESSAGE);
489 SwingWorker<Void, Void> worker =
new SwingWorker<Void, Void>() {
491 protected Void doInBackground()
throws Exception {
497 JOptionPane.showConfirmDialog(
this, progressPanel, Bundle.GeolocationTC_report_progress_title(), JOptionPane.CLOSED_OPTION, JOptionPane.PLAIN_MESSAGE);
498 }
catch (IOException ex) {
499 logger.log(Level.WARNING,
"Unable to create KML report", ex);
518 "GeolocationTopComponent.WaypointFetcher.onErrorTitle=Error gathering GPS Track Data",
519 "GeolocationTopComponent.WaypointFetcher.onErrorDescription=There was an error gathering some GPS Track Data. Some results have been excluded."
529 List<Set<MapWaypoint>> areas,
boolean wasEntirelySuccessful) {
530 addWaypointsToMap(mapWaypoints, tracks, areas);
533 if (!wasEntirelySuccessful) {
535 Bundle.GeolocationTopComponent_WaypointFetcher_onErrorDescription(),
536 Bundle.GeolocationTopComponent_WaypointFetcher_onErrorTitle(),
537 JOptionPane.ERROR_MESSAGE);
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static Case getCurrentCase()
String getReportDirectory()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
synchronized static Logger getLogger(String name)
static void error(String title, String message)
AbstractWaypointFetcher(GeoFilter filters)
void handleFilteredWaypointSet(Set< MapWaypoint > mapWaypoints, List< Set< MapWaypoint > > tracks, List< Set< MapWaypoint > > areas, boolean wasEntirelySuccessful)
GeolocationTopComponent()
void setFilterState(GeoFilter filter)
static final String REPORT_PATH_FMT_STR
void showRefreshPanel(boolean show)
javax.swing.JButton reportButton
final PropertyChangeListener caseEventListener
static final long serialVersionUID
static final Logger logger
javax.swing.JProgressBar progressBar
static final String REPORT_KML
static String createReportDirectory()
org.sleuthkit.autopsy.geolocation.MapPanel mapPanel
javax.swing.JLabel coordLabel
final GeoFilterPanel geoFilterPanel
javax.swing.JPanel statusBar
final PropertyChangeListener ingestListener
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
void reportButtonActionPerformed(java.awt.event.ActionEvent evt)
org.sleuthkit.autopsy.geolocation.HidingPane filterPane
static synchronized IngestManager getInstance()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
void addIngestModuleEventListener(final PropertyChangeListener listener)
BlackboardArtifact.Type getBlackboardArtifactType()
final void setLabels(String reportName, String reportPath)
void generateReport(String baseReportDir, ReportProgressPanel progressPanel, List< Waypoint > waypointList)
static synchronized KMLReport getDefault()