19 package org.sleuthkit.autopsy.geolocation;
21 import java.awt.BorderLayout;
22 import java.awt.Component;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.beans.PropertyChangeEvent;
26 import java.beans.PropertyChangeListener;
28 import java.io.IOException;
29 import java.text.DateFormat;
30 import java.text.SimpleDateFormat;
31 import java.util.Date;
32 import java.util.EnumSet;
33 import java.util.LinkedHashSet;
34 import java.util.List;
35 import java.util.Locale;
37 import java.util.logging.Level;
38 import javax.swing.JOptionPane;
39 import javax.swing.SwingUtilities;
40 import javax.swing.SwingWorker;
41 import org.openide.filesystems.FileUtil;
42 import org.openide.util.NbBundle.Messages;
43 import org.openide.windows.RetainLocation;
44 import org.openide.windows.TopComponent;
45 import org.openide.windows.WindowManager;
63 @TopComponent.Description(preferredID =
"GeolocationTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
64 @TopComponent.Registration(mode =
"geolocation", openAtStartup =
false)
65 @RetainLocation(
"geolocation")
66 @SuppressWarnings(
"PMD.SingularField")
69 private static final long serialVersionUID = 1L;
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";
86 private boolean mapInitalized =
false;
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()
120 showRefreshPanel(
true);
125 this.caseEventListener = pce -> {
126 mapPanel.clearWaypoints();
127 if (pce.getNewValue() != null) {
132 refreshPanel.addCloseActionListener(
new ActionListener() {
134 public void actionPerformed(ActionEvent e) {
135 showRefreshPanel(
false);
139 refreshPanel.addRefreshActionListner(
new ActionListener() {
141 public void actionPerformed(ActionEvent e) {
142 geoFilterPanel.updateDataSourceList();
143 mapPanel.clearWaypoints();
144 showRefreshPanel(
false);
148 geoFilterPanel =
new GeoFilterPanel();
149 filterPane.setPanel(geoFilterPanel);
150 geoFilterPanel.addActionListener(
new ActionListener() {
152 public void actionPerformed(ActionEvent e) {
157 geoFilterPanel.addPropertyChangeListener(GeoFilterPanel.INITPROPERTY,
new PropertyChangeListener() {
159 public void propertyChange(PropertyChangeEvent evt) {
160 if (geoFilterPanel.hasDataSources()) {
163 geoFilterPanel.setEnabled(
false);
164 setWaypointLoading(
false);
165 JOptionPane.showMessageDialog(GeolocationTopComponent.this,
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();
183 coordLabel.setText(label);
198 super.removeNotify();
205 super.componentOpened();
206 WindowManager.getDefault().setTopComponentFloating(
this,
true);
217 if (filter == null) {
221 if (this.isOpened()) {
222 geoFilterPanel.setupFilter(filter);
225 geoFilterPanel.setInitialFilterState(filter);
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"
238 if (!mapInitalized) {
241 mapInitalized =
true;
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);
255 mapPanel.clearWaypoints();
256 geoFilterPanel.clearDataSourceList();
257 geoFilterPanel.updateDataSourceList();
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);
281 mapPanel.revalidate();
282 }
else if (!show && isShowing) {
283 mapPanel.remove(refreshPanel);
284 mapPanel.revalidate();
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"
308 filters = geoFilterPanel.getFilterState();
310 JOptionPane.showMessageDialog(
this,
312 Bundle.GeoTopComponent_filer_data_invalid_Title(),
313 JOptionPane.INFORMATION_MESSAGE);
317 setWaypointLoading(
true);
318 geoFilterPanel.setEnabled(
false);
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")
423 private
void initComponents() {
424 java.awt.GridBagConstraints gridBagConstraints;
427 statusBar =
new javax.swing.JPanel();
428 reportButton =
new javax.swing.JButton();
429 progressBar =
new javax.swing.JProgressBar();
430 coordLabel =
new javax.swing.JLabel();
433 setLayout(
new java.awt.BorderLayout());
434 add(filterPane, java.awt.BorderLayout.WEST);
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);
485 String reportBaseDir = createReportDirectory();
487 progressPanel.
setLabels(REPORT_KML, reportBaseDir);
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);
final void setLabels(String reportName, String reportPath)
BlackboardArtifact.Type getBlackboardArtifactType()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static String createReportDirectory()
static synchronized IngestManager getInstance()
void showRefreshPanel(boolean show)
javax.swing.JButton reportButton
String getReportDirectory()
org.sleuthkit.autopsy.geolocation.MapPanel mapPanel
final PropertyChangeListener caseEventListener
javax.swing.JProgressBar progressBar
javax.swing.JLabel coordLabel
final GeoFilterPanel geoFilterPanel
void reportButtonActionPerformed(java.awt.event.ActionEvent evt)
static synchronized KMLReport getDefault()
final PropertyChangeListener ingestListener
void generateReport(String baseReportDir, ReportProgressPanel progressPanel, List< Waypoint > waypointList)
static void error(String title, String message)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
org.sleuthkit.autopsy.geolocation.HidingPane filterPane
void handleFilteredWaypointSet(Set< MapWaypoint > mapWaypoints, List< Set< MapWaypoint >> tracks, List< Set< MapWaypoint >> areas, boolean wasEntirelySuccessful)
javax.swing.JPanel statusBar
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
void setFilterState(GeoFilter filter)