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
 
  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)
TSK_GPS_LAST_KNOWN_LOCATION
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)