Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
GeolocationPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datasourcesummary.ui;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27 import java.util.stream.Collectors;
28 import java.util.stream.Stream;
29 import javax.swing.JButton;
30 import org.apache.commons.collections.CollectionUtils;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.commons.lang3.tuple.Pair;
33 import org.openide.util.NbBundle.Messages;
34 import org.openide.util.actions.CallableSystemAction;
35 import org.openide.windows.TopComponent;
36 import org.openide.windows.WindowManager;
55 import org.sleuthkit.datamodel.DataSource;
56 
61 @Messages({
62  "GeolocationPanel_cityColumn_title=Closest City",
63  "GeolocationPanel_countColumn_title=Count",
64  "GeolocationPanel_onNoCrIngest_message=No results will be shown because the GPX Parser was not run.",
65  "GeolocationPanel_unknownRow_title=Unknown",
66  "GeolocationPanel_mostCommon_tabName=Most Common Cities",
67  "GeolocationPanel_mostRecent_tabName=Most Recent Cities",})
68 public class GeolocationPanel extends BaseDataSourceSummaryPanel {
69 
73  private static class GeolocationViewModel {
74 
75  private final List<Pair<String, Integer>> mostRecentData;
76  private final List<Pair<String, Integer>> mostCommonData;
77 
86  GeolocationViewModel(List<Pair<String, Integer>> mostRecentData, List<Pair<String, Integer>> mostCommonData) {
87  this.mostRecentData = mostRecentData;
88  this.mostCommonData = mostCommonData;
89  }
90 
96  List<Pair<String, Integer>> getMostRecentData() {
97  return mostRecentData;
98  }
99 
105  List<Pair<String, Integer>> getMostCommonData() {
106  return mostCommonData;
107  }
108  }
109 
110  private static final long serialVersionUID = 1L;
111  private static final int DAYS_COUNT = 30;
112  private static final int MAX_COUNT = 10;
113 
114  // The column indicating the city
116  Bundle.GeolocationPanel_cityColumn_title(),
117  (pair) -> new DefaultCellModel<>(pair.getLeft()),
118  300
119  );
120 
121  // The column indicating the count of points seen close to that city
123  Bundle.GeolocationPanel_countColumn_title(),
124  (pair) -> new DefaultCellModel<>(pair.getRight()),
125  100
126  );
127 
128  private static final List<ColumnModel<Pair<String, Integer>, DefaultCellModel<?>>> DEFAULT_TEMPLATE = Arrays.asList(
129  CITY_COL,
130  COUNT_COL
131  );
132 
133  // tables displaying city and number of hits for that city
134  private final JTablePanel<Pair<String, Integer>> mostCommonTable = JTablePanel.getJTablePanel(DEFAULT_TEMPLATE)
135  .setKeyFunction((pair) -> pair.getLeft());
136 
137  private final JTablePanel<Pair<String, Integer>> mostRecentTable = JTablePanel.getJTablePanel(DEFAULT_TEMPLATE)
138  .setKeyFunction((pair) -> pair.getLeft());
139 
140  // loadable components on this tab
141  private final List<JTablePanel<?>> tables = Arrays.asList(mostCommonTable, mostRecentTable);
142 
143  private final Logger logger = Logger.getLogger(GeolocationPanel.class.getName());
144 
145  // means of fetching and displaying data
146  private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
147 
148  private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel();
149 
151 
153 
157  public GeolocationPanel() {
158  this(new GeolocationSummary());
159  }
160 
166  public GeolocationPanel(GeolocationSummary whereUsedData) {
167  super(whereUsedData);
168 
169  this.whereUsedData = whereUsedData;
170 
171  this.geolocationFetcher = (dataSource) -> convertToViewModel(whereUsedData.getCityCounts(dataSource, DAYS_COUNT, MAX_COUNT));
172 
173  // set up data acquisition methods
174  dataFetchComponents = Arrays.asList(
176  geolocationFetcher,
177  (result) -> handleData(result)));
178 
179  initComponents();
180  }
181 
189  showCityContent(DataFetchResult.getSubResult(result, (dr) -> dr.getMostCommonData()), mostCommonTable, commonViewInGeolocationBtn);
190  showCityContent(DataFetchResult.getSubResult(result, (dr) -> dr.getMostRecentData()), mostRecentTable, recentViewInGeolocationBtn);
191  }
192 
199  private static String getCityName(CityRecord record) {
200  if (record == null) {
201  return null;
202  }
203 
204  List<String> cityIdentifiers = Stream.of(record.getCityName(), record.getState(), record.getCountry())
205  .filter(StringUtils::isNotBlank)
206  .collect(Collectors.toList());
207 
208  if (cityIdentifiers.size() == 1) {
209  return cityIdentifiers.get(0);
210  } else if (cityIdentifiers.size() == 2) {
211  return String.format("%s, %s", cityIdentifiers.get(0), cityIdentifiers.get(1));
212  } else if (cityIdentifiers.size() >= 3) {
213  return String.format("%s, %s; %s", cityIdentifiers.get(0), cityIdentifiers.get(1), cityIdentifiers.get(2));
214  }
215 
216  return null;
217  }
218 
226  private Pair<String, Integer> formatRecord(CityRecordCount cityCount) {
227  if (cityCount == null) {
228  return null;
229  }
230 
231  String cityName = getCityName(cityCount.getCityRecord());
232  int count = cityCount.getCount();
233  return Pair.of(cityName, count);
234  }
235 
245  private List<Pair<String, Integer>> formatList(CityCountsList countsList) {
246  if (countsList == null) {
247  return Collections.emptyList();
248  }
249 
250  Stream<CityRecordCount> countsStream = ((countsList.getCounts() == null)
251  ? new ArrayList<CityRecordCount>()
252  : countsList.getCounts()).stream();
253 
254  Stream<Pair<String, Integer>> pairStream = countsStream.map((r) -> formatRecord(r));
255 
256  Pair<String, Integer> unknownRecord = Pair.of(Bundle.GeolocationPanel_unknownRow_title(), countsList.getOtherCount());
257 
258  return Stream.concat(pairStream, Stream.of(unknownRecord))
259  .filter((p) -> p != null && p.getRight() != null && p.getRight() > 0)
260  .sorted((a, b) -> -Integer.compare(a.getRight(), b.getRight()))
261  .limit(MAX_COUNT)
262  .collect(Collectors.toList());
263  }
264 
273  if (cityData == null) {
274  return new GeolocationViewModel(Collections.emptyList(), Collections.emptyList());
275  } else {
276  return new GeolocationViewModel(formatList(cityData.getMostRecent()), formatList(cityData.getMostCommon()));
277  }
278  }
279 
287  private void showCityContent(DataFetchResult<List<Pair<String, Integer>>> result, JTablePanel<Pair<String, Integer>> table, JButton goToGeolocation) {
288  if (result != null && result.getResultType() == DataFetchResult.ResultType.SUCCESS && CollectionUtils.isNotEmpty(result.getData())) {
289  goToGeolocation.setEnabled(true);
290  }
291 
292  table.showDataFetchResult(result);
293  }
294 
303  private void openGeolocationWindow(DataSource dataSource, Integer daysLimit) {
304  // notify dialog (if in dialog) should close.
305  notifyParentClose();
306 
307  // set the filter
308  TopComponent topComponent = WindowManager.getDefault().findTopComponent(GeolocationTopComponent.class.getSimpleName());
309  if (topComponent instanceof GeolocationTopComponent) {
310  GeolocationTopComponent geoComponent = (GeolocationTopComponent) topComponent;
311 
312  GeoFilter filter = (daysLimit == null)
313  ? new GeoFilter(true, false, 0, Arrays.asList(dataSource), whereUsedData.getGeoTypes())
314  : new GeoFilter(false, false, DAYS_COUNT, Arrays.asList(dataSource), whereUsedData.getGeoTypes());
315 
316  try {
317  geoComponent.setFilterState(filter);
318  } catch (GeoLocationUIException ex) {
319  logger.log(Level.WARNING, "There was an error setting filters in the GeoLocationTopComponent.", ex);
320  }
321  }
322 
323  // open the window
324  OpenGeolocationAction action = CallableSystemAction.get(OpenGeolocationAction.class);
325  if (action == null) {
326  logger.log(Level.WARNING, "Unable to obtain an OpenGeolocationAction instance from CallableSystemAction.");
327  } else {
328  action.performAction();
329  }
330  }
331 
335  private void disableNavButtons() {
336  commonViewInGeolocationBtn.setEnabled(false);
337  recentViewInGeolocationBtn.setEnabled(false);
338  }
339 
340  @Override
341  protected void fetchInformation(DataSource dataSource) {
342  disableNavButtons();
343  fetchInformation(dataFetchComponents, dataSource);
344  }
345 
346  @Override
347  protected void onNewDataSource(DataSource dataSource) {
348  disableNavButtons();
349  onNewDataSource(dataFetchComponents, tables, dataSource);
350  }
351 
352  @Override
353  List<ExcelExport.ExcelSheetExport> getExports(DataSource dataSource) {
354  GeolocationViewModel model = getFetchResult(geolocationFetcher, "Geolocation sheets", dataSource);
355  if (model == null) {
356  return Collections.emptyList();
357  }
358 
359  return Arrays.asList(
360  getTableExport(DEFAULT_TEMPLATE, Bundle.GeolocationPanel_mostRecent_tabName(), model.getMostRecentData()),
361  getTableExport(DEFAULT_TEMPLATE, Bundle.GeolocationPanel_mostCommon_tabName(), model.getMostCommonData())
362  );
363  }
364 
365  @Override
366  public void close() {
367  ingestRunningLabel.unregister();
368  super.close();
369  }
370 
376  @SuppressWarnings("unchecked")
377  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
378  private void initComponents() {
379 
380  javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane();
381  javax.swing.JPanel mainContentPanel = new javax.swing.JPanel();
382  javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
383  javax.swing.JLabel mostRecentLabel = new javax.swing.JLabel();
384  javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
385  javax.swing.JPanel mostRecentPanel = mostRecentTable;
386  javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
387  javax.swing.JLabel withinDistanceLabel = new javax.swing.JLabel();
388  javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
389  recentViewInGeolocationBtn = new javax.swing.JButton();
390  javax.swing.Box.Filler filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20));
391  javax.swing.JLabel mostCommonLabel = new javax.swing.JLabel();
392  javax.swing.Box.Filler filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
393  javax.swing.JPanel mostCommonPanel = mostCommonTable;
394  javax.swing.Box.Filler filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2));
395  javax.swing.JLabel withinDistanceLabel1 = new javax.swing.JLabel();
396  javax.swing.Box.Filler filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
397  commonViewInGeolocationBtn = new javax.swing.JButton();
398  javax.swing.Box.Filler filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
399 
400  mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
401  mainContentPanel.setLayout(new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS));
402 
403  ingestRunningPanel.setAlignmentX(0.0F);
404  ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25));
405  ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25));
406  ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25));
407  mainContentPanel.add(ingestRunningPanel);
408 
409  org.openide.awt.Mnemonics.setLocalizedText(mostRecentLabel, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.mostRecentLabel.text")); // NOI18N
410  mainContentPanel.add(mostRecentLabel);
411  mostRecentLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N
412 
413  filler1.setAlignmentX(0.0F);
414  mainContentPanel.add(filler1);
415 
416  mostRecentPanel.setAlignmentX(0.0F);
417  mostRecentPanel.setMaximumSize(new java.awt.Dimension(32767, 106));
418  mostRecentPanel.setMinimumSize(new java.awt.Dimension(100, 106));
419  mostRecentPanel.setPreferredSize(new java.awt.Dimension(100, 106));
420  mainContentPanel.add(mostRecentPanel);
421 
422  filler2.setAlignmentX(0.0F);
423  mainContentPanel.add(filler2);
424 
425  org.openide.awt.Mnemonics.setLocalizedText(withinDistanceLabel, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.withinDistanceLabel.text")); // NOI18N
426  mainContentPanel.add(withinDistanceLabel);
427 
428  filler3.setAlignmentX(0.0F);
429  mainContentPanel.add(filler3);
430 
431  org.openide.awt.Mnemonics.setLocalizedText(recentViewInGeolocationBtn, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.recentViewInGeolocationBtn.text")); // NOI18N
432  recentViewInGeolocationBtn.setEnabled(false);
433  recentViewInGeolocationBtn.addActionListener(new java.awt.event.ActionListener() {
434  public void actionPerformed(java.awt.event.ActionEvent evt) {
435  recentViewInGeolocationBtnActionPerformed(evt);
436  }
437  });
438  mainContentPanel.add(recentViewInGeolocationBtn);
439 
440  filler8.setAlignmentX(0.0F);
441  mainContentPanel.add(filler8);
442 
443  org.openide.awt.Mnemonics.setLocalizedText(mostCommonLabel, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.mostCommonLabel.text")); // NOI18N
444  mainContentPanel.add(mostCommonLabel);
445 
446  filler7.setAlignmentX(0.0F);
447  mainContentPanel.add(filler7);
448 
449  mostCommonPanel.setAlignmentX(0.0F);
450  mostCommonPanel.setMaximumSize(new java.awt.Dimension(32767, 106));
451  mostCommonPanel.setMinimumSize(new java.awt.Dimension(100, 106));
452  mostCommonPanel.setPreferredSize(new java.awt.Dimension(100, 106));
453  mainContentPanel.add(mostCommonPanel);
454 
455  filler6.setAlignmentX(0.0F);
456  mainContentPanel.add(filler6);
457 
458  org.openide.awt.Mnemonics.setLocalizedText(withinDistanceLabel1, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.withinDistanceLabel1.text")); // NOI18N
459  mainContentPanel.add(withinDistanceLabel1);
460 
461  filler4.setAlignmentX(0.0F);
462  mainContentPanel.add(filler4);
463 
464  org.openide.awt.Mnemonics.setLocalizedText(commonViewInGeolocationBtn, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.commonViewInGeolocationBtn.text")); // NOI18N
465  commonViewInGeolocationBtn.setEnabled(false);
466  commonViewInGeolocationBtn.addActionListener(new java.awt.event.ActionListener() {
467  public void actionPerformed(java.awt.event.ActionEvent evt) {
468  commonViewInGeolocationBtnActionPerformed(evt);
469  }
470  });
471  mainContentPanel.add(commonViewInGeolocationBtn);
472 
473  filler5.setAlignmentX(0.0F);
474  mainContentPanel.add(filler5);
475 
476  mainScrollPane.setViewportView(mainContentPanel);
477 
478  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
479  this.setLayout(layout);
480  layout.setHorizontalGroup(
481  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
482  .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
483  );
484  layout.setVerticalGroup(
485  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
486  .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 746, Short.MAX_VALUE)
487  );
488  }// </editor-fold>//GEN-END:initComponents
489 
490  private void recentViewInGeolocationBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_recentViewInGeolocationBtnActionPerformed
491  openGeolocationWindow(getDataSource(), DAYS_COUNT);
492  }//GEN-LAST:event_recentViewInGeolocationBtnActionPerformed
493 
494  private void commonViewInGeolocationBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_commonViewInGeolocationBtnActionPerformed
495  openGeolocationWindow(getDataSource(), null);
496  }//GEN-LAST:event_commonViewInGeolocationBtnActionPerformed
497 
498 
499  // Variables declaration - do not modify//GEN-BEGIN:variables
500  private javax.swing.JButton commonViewInGeolocationBtn;
501  private javax.swing.JButton recentViewInGeolocationBtn;
502  // End of variables declaration//GEN-END:variables
503 }
List< Pair< String, Integer > > formatList(CityCountsList countsList)
static< I, O > DataFetchResult< O > getSubResult(DataFetchResult< I > inputResult, Function< I, O > getSubResult)
void recentViewInGeolocationBtnActionPerformed(java.awt.event.ActionEvent evt)
void commonViewInGeolocationBtnActionPerformed(java.awt.event.ActionEvent evt)
void openGeolocationWindow(DataSource dataSource, Integer daysLimit)
CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount)
static< T, CextendsGuiCellModel > JTablePanel< T > getJTablePanel(List< ColumnModel< T, C >> columns)
final DataFetcher< DataSource, GeolocationViewModel > geolocationFetcher
void showCityContent(DataFetchResult< List< Pair< String, Integer >>> result, JTablePanel< Pair< String, Integer >> table, JButton goToGeolocation)
GeolocationViewModel convertToViewModel(CityData cityData)
Pair< String, Integer > formatRecord(CityRecordCount cityCount)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void handleData(DataFetchResult< GeolocationViewModel > result)
final List< DataFetchComponents< DataSource,?> > dataFetchComponents

Copyright © 2012-2021 Basis Technology. Generated on: Fri Aug 6 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.