From a1d95a9fc9b673c5ec729e52b4ce9f646df42368 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 27 Jan 2020 17:20:59 -0500 Subject: [PATCH] Cleaned up geolocation threading --- .../geolocation/AbstractWaypointFetcher.java | 251 +++++++++++++ .../geolocation/CheckBoxListPanel.java | 4 + .../autopsy/geolocation/GeoFilterPanel.java | 122 +++++-- .../geolocation/GeolocationTopComponent.java | 338 +++++------------- .../autopsy/geolocation/MapPanel.java | 3 - 5 files changed, 441 insertions(+), 277 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java new file mode 100755 index 0000000000..a662b410e6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java @@ -0,0 +1,251 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019-2020 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.geolocation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; +import org.sleuthkit.autopsy.geolocation.datamodel.Track; +import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint; +import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder; + +/** + * The business logic for filtering waypoints. + */ +abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilterQueryCallBack { + + private static final Logger logger = Logger.getLogger(AbstractWaypointFetcher.class.getName()); + + private final GeoFilterPanel.GeoFilter filters; + + /** + * Constructs the Waypoint Runner + * + * @param filters + */ + AbstractWaypointFetcher(GeoFilterPanel.GeoFilter filters) { + this.filters = filters; + } + + /** + * Gets the waypoints based in the current GeoFilter. + * + * This function kicks off a process that will send with + * handleFilteredWaypointSet being called. Subclasses must implement + * handleFitleredWayoiintSet to get the final results. + * + * @throws GeoLocationDataException + */ + void getWaypoints() throws GeoLocationDataException { + Case currentCase = Case.getCurrentCase(); + WaypointBuilder.getAllWaypoints(currentCase.getSleuthkitCase(), + filters.getDataSources(), + filters.showAllWaypoints(), + filters.getMostRecentNumDays(), + filters.showWaypointsWithoutTimeStamp(), + this); + + } + + /** + * Called after all of the MapWaypoints are created from all of the + * TSK_GPS_XXX objects. + * + * @param mapWaypoints List of filtered MapWaypoints. + */ + abstract void handleFilteredWaypointSet(Set mapWaypoints); + + @Override + public void process(List waypoints) { + + List tracks = null; + try { + tracks = Track.getTracks(Case.getCurrentCase().getSleuthkitCase(), filters.getDataSources()); + } catch (GeoLocationDataException ex) { + logger.log(Level.WARNING, "Exception thrown while retrieving list of Tracks", ex); + } + + List completeList = createWaypointList(waypoints, tracks); + final Set pointSet = MapWaypoint.getWaypoints(completeList); + + handleFilteredWaypointSet(pointSet); + } + + /** + * Returns a complete list of waypoints including the tracks. Takes into + * account the current filters and includes waypoints as approprate. + * + * @param waypoints List of waypoints + * @param tracks List of tracks + * + * @return A list of waypoints including the tracks based on the current + * filters. + */ + private List createWaypointList(List waypoints, List tracks) { + final List completeList = new ArrayList<>(); + + if (tracks != null) { + Long timeRangeEnd; + Long timeRangeStart; + if (!filters.showAllWaypoints()) { + // Figure out what the most recent time is given the filtered + // waypoints and the tracks. + timeRangeEnd = getMostRecent(waypoints, tracks); + timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays()); + + completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints)); + completeList.addAll(getTracksInRange(timeRangeStart, timeRangeEnd, tracks)); + + } else { + completeList.addAll(waypoints); + for (Track track : tracks) { + completeList.addAll(track.getPath()); + } + } + } else { + completeList.addAll(waypoints); + } + + return completeList; + } + + /** + * Return a list of waypoints that fall into the given time range. + * + * @param timeRangeStart start timestamp of range (seconds from java epoch) + * @param timeRangeEnd start timestamp of range (seconds from java epoch) + * @param waypoints List of waypoints to filter. + * + * @return A list of waypoints that fall into the time range. + */ + private List getWaypointsInRange(Long timeRangeStart, Long timeRangeEnd, List waypoints) { + List completeList = new ArrayList<>(); + // Add all of the waypoints that fix into the time range. + if (waypoints != null) { + for (Waypoint point : waypoints) { + Long time = point.getTimestamp(); + if ((time == null && filters.showWaypointsWithoutTimeStamp()) + || (time != null && (time >= timeRangeStart && time <= timeRangeEnd))) { + + completeList.add(point); + } + } + } + return completeList; + } + + /** + * Return a list of waypoints from the given tracks that fall into for + * tracks that fall into the given time range. The track start time will + * used for determining if the whole track falls into the range. + * + * @param timeRangeStart start timestamp of range (seconds from java epoch) + * @param timeRangeEnd start timestamp of range (seconds from java epoch) + * @param tracks Track list. + * + * @return A list of waypoints that that belong to tracks that fall into the + * time range. + */ + private List getTracksInRange(Long timeRangeStart, Long timeRangeEnd, List tracks) { + List completeList = new ArrayList<>(); + if (tracks != null) { + for (Track track : tracks) { + Long trackTime = track.getStartTime(); + + if ((trackTime == null && filters.showWaypointsWithoutTimeStamp()) + || (trackTime != null && (trackTime >= timeRangeStart && trackTime <= timeRangeEnd))) { + + completeList.addAll(track.getPath()); + } + } + } + return completeList; + } + + /** + * Find the latest time stamp in the given list of waypoints. + * + * @param points List of Waypoints, required. + * + * @return The latest time stamp (seconds from java epoch) + */ + private Long findMostRecentTimestamp(List points) { + + Long mostRecent = null; + + for (Waypoint point : points) { + if (mostRecent == null) { + mostRecent = point.getTimestamp(); + } else { + mostRecent = Math.max(mostRecent, point.getTimestamp()); + } + } + + return mostRecent; + } + + /** + * Find the latest time stamp in the given list of tracks. + * + * @param tracks List of Waypoints, required. + * + * @return The latest time stamp (seconds from java epoch) + */ + private Long findMostRecentTracks(List tracks) { + Long mostRecent = null; + + for (Track track : tracks) { + if (mostRecent == null) { + mostRecent = track.getStartTime(); + } else { + mostRecent = Math.max(mostRecent, track.getStartTime()); + } + } + + return mostRecent; + } + + /** + * Returns the "most recent" timestamp amount the list of waypoints and + * track points. + * + * @param points List of Waypoints + * @param tracks List of Tracks + * + * @return Latest time stamp (seconds from java epoch) + */ + private Long getMostRecent(List points, List tracks) { + Long waypointMostRecent = findMostRecentTimestamp(points); + Long trackMostRecent = findMostRecentTracks(tracks); + + if (waypointMostRecent != null && trackMostRecent != null) { + return Math.max(waypointMostRecent, trackMostRecent); + } else if (waypointMostRecent == null && trackMostRecent != null) { + return trackMostRecent; + } else if (waypointMostRecent != null && trackMostRecent == null) { + return waypointMostRecent; + } + + return null; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java index 0942a9e528..49dfadaacb 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java @@ -67,6 +67,10 @@ final class CheckBoxListPanel extends javax.swing.JPanel { model.removeAllElements(); } + boolean isEmpty() { + return model.isEmpty(); + } + @Override public void setEnabled(boolean enabled) { checkboxList.setEnabled(enabled); diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java index 51238a033e..cce7a6f28a 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java @@ -20,14 +20,19 @@ package org.sleuthkit.autopsy.geolocation; import java.awt.GridBagConstraints; import java.awt.event.ActionListener; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javafx.util.Pair; import javax.swing.ImageIcon; import javax.swing.SpinnerNumberModel; +import javax.swing.SwingWorker; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -38,12 +43,24 @@ import org.sleuthkit.datamodel.TskCoreException; */ class GeoFilterPanel extends javax.swing.JPanel { + final static String INITPROPERTY = "FilterPanelInitCompleted"; + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(GeoFilterPanel.class.getName()); private final SpinnerNumberModel numberModel; private final CheckBoxListPanel checkboxPanel; + // Make sure to update if + private static final BlackboardArtifact.ARTIFACT_TYPE[] GPS_ARTIFACT_TYPES = { + BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK, + BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION, + BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE, + BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH, + BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK, + BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT + }; + /** * Creates new GeoFilterPanel */ @@ -73,7 +90,7 @@ class GeoFilterPanel extends javax.swing.JPanel { gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 15); add(checkboxPanel, gridBagConstraints); } - + @Override public void setEnabled(boolean enabled) { applyButton.setEnabled(enabled); @@ -84,18 +101,15 @@ class GeoFilterPanel extends javax.swing.JPanel { daysLabel.setEnabled(enabled); daysSpinner.setEnabled(enabled); } - + /** * Update the data source list with the current data sources */ void updateDataSourceList() { - try { - initCheckboxList(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Failed to initialize the CheckboxListPane", ex); //NON-NLS - } + DataSourceUpdater updater = new DataSourceUpdater(); + updater.execute(); } - + /** * Clears the data source list. */ @@ -103,6 +117,10 @@ class GeoFilterPanel extends javax.swing.JPanel { checkboxPanel.clearList(); } + boolean hasDataSources() { + return !checkboxPanel.isEmpty(); + } + /** * Adds an actionListener to listen for the filter apply action * @@ -128,26 +146,12 @@ class GeoFilterPanel extends javax.swing.JPanel { if (dataSources.isEmpty()) { throw new GeoLocationUIException(Bundle.GeoFilterPanel_empty_dataSource()); } - return new GeoFilter(allButton.isSelected(), - showWaypointsWOTSCheckBox.isSelected(), - numberModel.getNumber().intValue(), + return new GeoFilter(allButton.isSelected(), + showWaypointsWOTSCheckBox.isSelected(), + numberModel.getNumber().intValue(), dataSources); } - /** - * Initialize the checkbox list panel - * - * @throws TskCoreException - */ - private void initCheckboxList() throws TskCoreException { - final SleuthkitCase sleuthkitCase = Case.getCurrentCase().getSleuthkitCase(); - - for (DataSource dataSource : sleuthkitCase.getDataSources()) { - String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName(); - checkboxPanel.addElement(dsName, dataSource); - } - } - /** * Based on the state of mostRecent radio button Change the state of the cnt * spinner and the time stamp checkbox. @@ -376,4 +380,72 @@ class GeoFilterPanel extends javax.swing.JPanel { } } + /** + * SwingWorker for updating the list of valid data sources. + * + * doInBackground creates a list of Pair objects that contain the + * display name of the data source and the data source object. + */ + final private class DataSourceUpdater extends SwingWorker>, Void> { + + @Override + protected List> doInBackground() throws Exception { + SleuthkitCase sleuthkitCase = Case.getCurrentCase().getSleuthkitCase(); + List> validSources = new ArrayList<>(); + for (DataSource dataSource : sleuthkitCase.getDataSources()) { + if (isGPSDataSource(sleuthkitCase, dataSource)) { + String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName(); + Pair pair = new Pair<>(dsName, dataSource); + validSources.add(pair); + } + } + + return validSources; + } + + /** + * Returns whether or not the given data source has GPS artifacts. + * + * @param sleuthkitCase The current sleuthkitCase + * @param dataSource + * + * @return True if the data source as at least one TSK_GPS_XXXX + * + * @throws TskCoreException + */ + private boolean isGPSDataSource(SleuthkitCase sleuthkitCase, DataSource dataSource) throws TskCoreException { + for (BlackboardArtifact.ARTIFACT_TYPE type : GPS_ARTIFACT_TYPES) { + if (sleuthkitCase.getBlackboardArtifactsTypeCount(type.getTypeID(), dataSource.getId()) > 0) { + return true; + } + } + + return false; + } + + @Override + public void done() { + List> sources = null; + try { + sources = get(); + } catch (InterruptedException | ExecutionException ex) { + Throwable cause = ex.getCause(); + if (cause != null) { + logger.log(Level.SEVERE, cause.getMessage(), cause); + } else { + logger.log(Level.SEVERE, ex.getMessage(), ex); + } + } + + if (sources != null) { + for (Pair source : sources) { + checkboxPanel.addElement(source.getKey(), source.getValue()); + } + } + + GeoFilterPanel.this.firePropertyChange(INITPROPERTY, false, true); + } + + } + } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java index 17b5f58d34..a2f5cfe381 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java @@ -28,7 +28,6 @@ import java.io.File; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.EnumSet; import java.util.LinkedHashSet; @@ -51,10 +50,6 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.geolocation.GeoFilterPanel.GeoFilter; import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; -import org.sleuthkit.autopsy.geolocation.datamodel.Track; -import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint; -import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder; -import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder.WaypointFilterQueryCallBack; import org.sleuthkit.autopsy.ingest.IngestManager; import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; @@ -93,7 +88,9 @@ public final class GeolocationTopComponent extends TopComponent { @Messages({ "GLTopComponent_name=Geolocation", - "GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete." + "GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete.", + "GLTopComponent_No_dataSource_message=There are no data sources with Geolocation artifacts found.", + "GLTopComponent_No_dataSource_Title=No Geolocation artifacts found" }) /** @@ -143,7 +140,6 @@ public final class GeolocationTopComponent extends TopComponent { public void actionPerformed(ActionEvent e) { geoFilterPanel.updateDataSourceList(); mapPanel.clearWaypoints(); - updateWaypoints(); showRefreshPanel(false); } }); @@ -157,6 +153,24 @@ public final class GeolocationTopComponent extends TopComponent { } }); + geoFilterPanel.addPropertyChangeListener(GeoFilterPanel.INITPROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (geoFilterPanel.hasDataSources()) { + updateWaypoints(); + } else { + geoFilterPanel.setEnabled(false); + setWaypointLoading(false); + JOptionPane.showMessageDialog(GeolocationTopComponent.this, + Bundle.GLTopComponent_No_dataSource_message(), + Bundle.GLTopComponent_No_dataSource_Title(), + JOptionPane.ERROR_MESSAGE); + + } + } + + }); + mapPanel.addPropertyChangeListener(MapPanel.CURRENT_MOUSE_GEOPOSITION, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { @@ -200,9 +214,6 @@ public final class GeolocationTopComponent extends TopComponent { @Override public void open() { super.open(); - mapPanel.clearWaypoints(); - geoFilterPanel.clearDataSourceList(); - geoFilterPanel.updateDataSourceList(); // Let's make sure we only do this on the first open if (!mapInitalized) { @@ -221,8 +232,12 @@ public final class GeolocationTopComponent extends TopComponent { return; // Doen't set the waypoints. } } + + mapPanel.clearWaypoints(); + geoFilterPanel.clearDataSourceList(); + geoFilterPanel.updateDataSourceList(); mapPanel.setWaypoints(new LinkedHashSet<>()); - updateWaypoints(); + } /** @@ -236,8 +251,8 @@ public final class GeolocationTopComponent extends TopComponent { public void run() { boolean isShowing = false; Component[] comps = mapPanel.getComponents(); - for(Component comp: comps) { - if(comp.equals(refreshPanel)) { + for (Component comp : comps) { + if (comp.equals(refreshPanel)) { isShowing = true; break; } @@ -245,10 +260,10 @@ public final class GeolocationTopComponent extends TopComponent { if (show && !isShowing) { mapPanel.add(refreshPanel, BorderLayout.NORTH); mapPanel.revalidate(); - } else if(!show && isShowing){ + } else if (!show && isShowing) { mapPanel.remove(refreshPanel); mapPanel.revalidate(); - } + } } }); @@ -283,10 +298,61 @@ public final class GeolocationTopComponent extends TopComponent { setWaypointLoading(true); geoFilterPanel.setEnabled(false); - Thread thread = new Thread(new WaypointRunner(filters)); + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + try { + (new WaypointFetcher(filters)).getWaypoints(); + } catch (GeoLocationDataException ex) { + logger.log(Level.SEVERE, "Failed to filter waypoints.", ex); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(GeolocationTopComponent.this, + Bundle.GeoTopComponent_filter_exception_Title(), + Bundle.GeoTopComponent_filter_exception_msg(), + JOptionPane.ERROR_MESSAGE); + + setWaypointLoading(false); + } + }); + + } + } + + }); thread.start(); } + /** + * Add the filtered set of waypoints to the map and set the various window + * components to their proper state. + * + * @param waypointList + */ + void addWaypointsToMap(Set waypointList) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // If the list is empty, tell the user + if (waypointList == null || waypointList.isEmpty()) { + mapPanel.clearWaypoints(); + JOptionPane.showMessageDialog(GeolocationTopComponent.this, + Bundle.GeoTopComponent_no_waypoints_returned_Title(), + Bundle.GeoTopComponent_no_waypoints_returned_mgs(), + JOptionPane.INFORMATION_MESSAGE); + setWaypointLoading(false); + geoFilterPanel.setEnabled(true); + return; + } + mapPanel.clearWaypoints(); + mapPanel.setWaypoints(waypointList); + setWaypointLoading(false); + geoFilterPanel.setEnabled(true); + } + }); + } + /** * Show or hide the waypoint loading progress bar. * @@ -423,244 +489,18 @@ public final class GeolocationTopComponent extends TopComponent { // End of variables declaration//GEN-END:variables /** - * A runnable class for getting waypoints based on the current filters. + * Extends AbstractWaypointFetcher to handle the returning of + * the filters set of MapWaypoints. */ - private class WaypointRunner implements Runnable, WaypointFilterQueryCallBack { + final private class WaypointFetcher extends AbstractWaypointFetcher { - private final GeoFilter filters; - - /** - * Constructs the Waypoint Runner - * - * @param filters - */ - WaypointRunner(GeoFilter filters) { - this.filters = filters; + WaypointFetcher(GeoFilter filters) { + super(filters); } @Override - public void run() { - Case currentCase = Case.getCurrentCase(); - try { - WaypointBuilder.getAllWaypoints(currentCase.getSleuthkitCase(), - filters.getDataSources(), - filters.showAllWaypoints(), - filters.getMostRecentNumDays(), - filters.showWaypointsWithoutTimeStamp(), - this); - - } catch (GeoLocationDataException ex) { - logger.log(Level.SEVERE, "Failed to filter waypoints.", ex); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog(GeolocationTopComponent.this, - Bundle.GeoTopComponent_filter_exception_Title(), - Bundle.GeoTopComponent_filter_exception_msg(), - JOptionPane.ERROR_MESSAGE); - - setWaypointLoading(false); - } - }); - } - } - - @Override - public void process(List waypoints) { - - List tracks = null; - try { - tracks = Track.getTracks(Case.getCurrentCase().getSleuthkitCase(), filters.getDataSources()); - } catch (GeoLocationDataException ex) { - logger.log(Level.WARNING, "Exception thrown while retrieving list of Tracks", ex); - } - - List completeList = createWaypointList(waypoints, tracks); - final Set pointSet = MapWaypoint.getWaypoints(completeList); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // If the list is empty, tell the user and do not change - // the visible waypoints. - if (completeList == null || completeList.isEmpty()) { - mapPanel.clearWaypoints(); - JOptionPane.showMessageDialog(GeolocationTopComponent.this, - Bundle.GeoTopComponent_no_waypoints_returned_Title(), - Bundle.GeoTopComponent_no_waypoints_returned_mgs(), - JOptionPane.INFORMATION_MESSAGE); - setWaypointLoading(false); - geoFilterPanel.setEnabled(true); - return; - } - mapPanel.clearWaypoints(); - mapPanel.setWaypoints(pointSet); - setWaypointLoading(false); - geoFilterPanel.setEnabled(true); - } - }); - } - - /** - * Returns a complete list of waypoints including the tracks. Takes into - * account the current filters and includes waypoints as approprate. - * - * @param waypoints List of waypoints - * @param tracks List of tracks - * - * @return A list of waypoints including the tracks based on the current - * filters. - */ - private List createWaypointList(List waypoints, List tracks) { - final List completeList = new ArrayList<>(); - - if (tracks != null) { - Long timeRangeEnd; - Long timeRangeStart; - if (!filters.showAllWaypoints()) { - // Figure out what the most recent time is given the filtered - // waypoints and the tracks. - timeRangeEnd = getMostRecent(waypoints, tracks); - timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays()); - - completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints)); - completeList.addAll(getTracksInRange(timeRangeStart, timeRangeEnd, tracks)); - - } else { - completeList.addAll(waypoints); - for (Track track : tracks) { - completeList.addAll(track.getPath()); - } - } - } else { - completeList.addAll(waypoints); - } - - return completeList; - } - - /** - * Return a list of waypoints that fall into the given time range. - * - * @param timeRangeStart start timestamp of range (seconds from java - * epoch) - * @param timeRangeEnd start timestamp of range (seconds from java - * epoch) - * @param waypoints List of waypoints to filter. - * - * @return A list of waypoints that fall into the time range. - */ - private List getWaypointsInRange(Long timeRangeStart, Long timeRangeEnd, List waypoints) { - List completeList = new ArrayList<>(); - // Add all of the waypoints that fix into the time range. - if (waypoints != null) { - for (Waypoint point : waypoints) { - Long time = point.getTimestamp(); - if ((time == null && filters.showWaypointsWithoutTimeStamp()) - || (time != null && (time >= timeRangeStart && time <= timeRangeEnd))) { - - completeList.add(point); - } - } - } - return completeList; - } - - /** - * Return a list of waypoints from the given tracks that fall into for - * tracks that fall into the given time range. The track start time will - * used for determining if the whole track falls into the range. - * - * @param timeRangeStart start timestamp of range (seconds from java - * epoch) - * @param timeRangeEnd start timestamp of range (seconds from java - * epoch) - * @param tracks Track list. - * - * @return A list of waypoints that that belong to tracks that fall into - * the time range. - */ - private List getTracksInRange(Long timeRangeStart, Long timeRangeEnd, List tracks) { - List completeList = new ArrayList<>(); - if (tracks != null) { - for (Track track : tracks) { - Long trackTime = track.getStartTime(); - - if ((trackTime == null && filters.showWaypointsWithoutTimeStamp()) - || (trackTime != null && (trackTime >= timeRangeStart && trackTime <= timeRangeEnd))) { - - completeList.addAll(track.getPath()); - } - } - } - return completeList; - } - - /** - * Find the latest time stamp in the given list of waypoints. - * - * @param points List of Waypoints, required. - * - * @return The latest time stamp (seconds from java epoch) - */ - private Long findMostRecentTimestamp(List points) { - - Long mostRecent = null; - - for (Waypoint point : points) { - if (mostRecent == null) { - mostRecent = point.getTimestamp(); - } else { - mostRecent = Math.max(mostRecent, point.getTimestamp()); - } - } - - return mostRecent; - } - - /** - * Find the latest time stamp in the given list of tracks. - * - * @param tracks List of Waypoints, required. - * - * @return The latest time stamp (seconds from java epoch) - */ - private Long findMostRecentTracks(List tracks) { - Long mostRecent = null; - - for (Track track : tracks) { - if (mostRecent == null) { - mostRecent = track.getStartTime(); - } else { - mostRecent = Math.max(mostRecent, track.getStartTime()); - } - } - - return mostRecent; - } - - /** - * Returns the "most recent" timestamp amount the list of waypoints and - * track points. - * - * @param points List of Waypoints - * @param tracks List of Tracks - * - * @return Latest time stamp (seconds from java epoch) - */ - private Long getMostRecent(List points, List tracks) { - Long waypointMostRecent = findMostRecentTimestamp(points); - Long trackMostRecent = findMostRecentTracks(tracks); - - if (waypointMostRecent != null && trackMostRecent != null) { - return Math.max(waypointMostRecent, trackMostRecent); - } else if (waypointMostRecent == null && trackMostRecent != null) { - return trackMostRecent; - } else if (waypointMostRecent != null && trackMostRecent == null) { - return waypointMostRecent; - } - - return null; + void handleFilteredWaypointSet(Set mapWaypoints) { + addWaypointsToMap(mapWaypoints); } } } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java index 4d286467b8..aa528f77de 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java @@ -35,7 +35,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -58,7 +57,6 @@ import org.jxmapviewer.viewer.DefaultTileFactory; import org.jxmapviewer.viewer.GeoPosition; import org.jxmapviewer.viewer.TileFactory; import org.jxmapviewer.viewer.TileFactoryInfo; -import org.jxmapviewer.viewer.Waypoint; import org.jxmapviewer.viewer.WaypointPainter; import org.jxmapviewer.viewer.WaypointRenderer; import org.openide.util.NbBundle.Messages; @@ -69,7 +67,6 @@ import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.datamodel.TskCoreException; import javax.imageio.ImageIO; import javax.swing.SwingUtilities; -import org.jxmapviewer.viewer.DefaultWaypointRenderer; /** * The map panel. This panel contains the jxmapviewer MapViewer