Autopsy  4.17.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.List;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26 import java.util.stream.Collectors;
27 import java.util.stream.Stream;
28 import javax.swing.JButton;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.commons.lang3.tuple.Pair;
32 import org.openide.util.NbBundle.Messages;
33 import org.openide.util.actions.CallableSystemAction;
34 import org.openide.windows.TopComponent;
35 import org.openide.windows.WindowManager;
52 import org.sleuthkit.datamodel.DataSource;
53 
58 @Messages({
59  "GeolocationPanel_cityColumn_title=Closest City",
60  "GeolocationPanel_countColumn_title=Count",
61  "GeolocationPanel_onNoCrIngest_message=No results will be shown because the GPX Parser was not run.",
62  "GeolocationPanel_unknownRow_title=Unknown",})
63 public class GeolocationPanel extends BaseDataSourceSummaryPanel {
64 
65  private static final long serialVersionUID = 1L;
66  private static final int DAYS_COUNT = 30;
67  private static final int MAX_COUNT = 10;
68 
69  // The column indicating the city
70  private static final ColumnModel<Pair<String, Integer>> CITY_COL = new ColumnModel<>(
71  Bundle.GeolocationPanel_cityColumn_title(),
72  (pair) -> new DefaultCellModel(pair.getLeft()),
73  300
74  );
75 
76  // The column indicating the count of points seen close to that city
77  private static final ColumnModel<Pair<String, Integer>> COUNT_COL = new ColumnModel<>(
78  Bundle.GeolocationPanel_countColumn_title(),
79  (pair) -> new DefaultCellModel(Integer.toString(pair.getRight())),
80  100
81  );
82 
83  // tables displaying city and number of hits for that city
84  private final JTablePanel<Pair<String, Integer>> mostCommonTable = JTablePanel.getJTablePanel(Arrays.asList(CITY_COL, COUNT_COL))
85  .setKeyFunction((pair) -> pair.getLeft());
86 
87  private final JTablePanel<Pair<String, Integer>> mostRecentTable = JTablePanel.getJTablePanel(Arrays.asList(CITY_COL, COUNT_COL))
88  .setKeyFunction((pair) -> pair.getLeft());
89 
90  // loadable components on this tab
91  private final List<JTablePanel<?>> tables = Arrays.asList(mostCommonTable, mostRecentTable);
92 
93  private final Logger logger = Logger.getLogger(GeolocationPanel.class.getName());
94 
95  // means of fetching and displaying data
96  private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
97 
98  private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel();
99 
101 
105  public GeolocationPanel() {
106  this(new GeolocationSummary());
107  }
108 
114  public GeolocationPanel(GeolocationSummary whereUsedData) {
115  super(whereUsedData);
116 
117  this.whereUsedData = whereUsedData;
118  // set up data acquisition methods
119  dataFetchComponents = Arrays.asList(
121  (dataSource) -> whereUsedData.getCityCounts(dataSource, DAYS_COUNT, MAX_COUNT),
122  (result) -> handleData(result)));
123 
124  initComponents();
125  }
126 
132  private void handleData(DataFetchResult<CityData> result) {
133  showCityContent(DataFetchResult.getSubResult(result, (dr) -> dr.getMostCommon()), mostCommonTable, commonViewInGeolocationBtn);
134  showCityContent(DataFetchResult.getSubResult(result, (dr) -> dr.getMostRecent()), mostRecentTable, recentViewInGeolocationBtn);
135  }
136 
143  private static String getCityName(CityRecord record) {
144  if (record == null) {
145  return null;
146  }
147 
148  List<String> cityIdentifiers = Stream.of(record.getCityName(), record.getState(), record.getCountry())
149  .filter(StringUtils::isNotBlank)
150  .collect(Collectors.toList());
151 
152  if (cityIdentifiers.size() == 1) {
153  return cityIdentifiers.get(0);
154  } else if (cityIdentifiers.size() == 2) {
155  return String.format("%s, %s", cityIdentifiers.get(0), cityIdentifiers.get(1));
156  } else if (cityIdentifiers.size() >= 3) {
157  return String.format("%s, %s; %s", cityIdentifiers.get(0), cityIdentifiers.get(1), cityIdentifiers.get(2));
158  }
159 
160  return null;
161  }
162 
170  private Pair<String, Integer> formatRecord(CityRecordCount cityCount) {
171  if (cityCount == null) {
172  return null;
173  }
174 
175  String cityName = getCityName(cityCount.getCityRecord());
176  int count = cityCount.getCount();
177  return Pair.of(cityName, count);
178  }
179 
189  private List<Pair<String, Integer>> formatList(CityCountsList countsList) {
190  if (countsList == null) {
191  return null;
192  }
193 
194  Stream<CityRecordCount> countsStream = ((countsList.getCounts() == null)
195  ? new ArrayList<CityRecordCount>()
196  : countsList.getCounts()).stream();
197 
198  Stream<Pair<String, Integer>> pairStream = countsStream.map((r) -> formatRecord(r));
199 
200  Pair<String, Integer> unknownRecord = Pair.of(Bundle.GeolocationPanel_unknownRow_title(), countsList.getOtherCount());
201 
202  return Stream.concat(pairStream, Stream.of(unknownRecord))
203  .filter((p) -> p != null && p.getRight() != null && p.getRight() > 0)
204  .sorted((a, b) -> -Integer.compare(a.getRight(), b.getRight()))
205  .limit(MAX_COUNT)
206  .collect(Collectors.toList());
207  }
208 
216  private void showCityContent(DataFetchResult<CityCountsList> result, JTablePanel<Pair<String, Integer>> table, JButton goToGeolocation) {
217  DataFetchResult<List<Pair<String, Integer>>> convertedData = DataFetchResult.getSubResult(result, (countsList) -> formatList(countsList));
218  if (convertedData != null && convertedData.getResultType() == DataFetchResult.ResultType.SUCCESS && CollectionUtils.isNotEmpty(convertedData.getData())) {
219  goToGeolocation.setEnabled(true);
220  }
221 
222  table.showDataFetchResult(convertedData);
223  }
224 
233  private void openGeolocationWindow(DataSource dataSource, Integer daysLimit) {
234  // notify dialog (if in dialog) should close.
235  notifyParentClose();
236 
237  // set the filter
238  TopComponent topComponent = WindowManager.getDefault().findTopComponent(GeolocationTopComponent.class.getSimpleName());
239  if (topComponent instanceof GeolocationTopComponent) {
240  GeolocationTopComponent geoComponent = (GeolocationTopComponent) topComponent;
241 
242  GeoFilter filter = (daysLimit == null)
243  ? new GeoFilter(true, false, 0, Arrays.asList(dataSource), whereUsedData.getGeoTypes())
244  : new GeoFilter(false, false, DAYS_COUNT, Arrays.asList(dataSource), whereUsedData.getGeoTypes());
245 
246  try {
247  geoComponent.setFilterState(filter);
248  } catch (GeoLocationUIException ex) {
249  logger.log(Level.WARNING, "There was an error setting filters in the GeoLocationTopComponent.", ex);
250  }
251  }
252 
253  // open the window
254  OpenGeolocationAction action = CallableSystemAction.get(OpenGeolocationAction.class);
255  if (action == null) {
256  logger.log(Level.WARNING, "Unable to obtain an OpenGeolocationAction instance from CallableSystemAction.");
257  } else {
258  action.performAction();
259  }
260  }
261 
265  private void disableNavButtons() {
266  commonViewInGeolocationBtn.setEnabled(false);
267  recentViewInGeolocationBtn.setEnabled(false);
268  }
269 
270  @Override
271  protected void fetchInformation(DataSource dataSource) {
272  disableNavButtons();
273  fetchInformation(dataFetchComponents, dataSource);
274  }
275 
276  @Override
277  protected void onNewDataSource(DataSource dataSource) {
278  disableNavButtons();
279  onNewDataSource(dataFetchComponents, tables, dataSource);
280  }
281 
282  @Override
283  public void close() {
284  ingestRunningLabel.unregister();
285  super.close();
286  }
287 
293  @SuppressWarnings("unchecked")
294  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
295  private void initComponents() {
296 
297  javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane();
298  javax.swing.JPanel mainContentPanel = new javax.swing.JPanel();
299  javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
300  javax.swing.JLabel mostRecentLabel = new javax.swing.JLabel();
301  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));
302  javax.swing.JPanel mostRecentPanel = mostRecentTable;
303  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));
304  javax.swing.JLabel withinDistanceLabel = new javax.swing.JLabel();
305  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));
306  recentViewInGeolocationBtn = new javax.swing.JButton();
307  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));
308  javax.swing.JLabel mostCommonLabel = new javax.swing.JLabel();
309  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));
310  javax.swing.JPanel mostCommonPanel = mostCommonTable;
311  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));
312  javax.swing.JLabel withinDistanceLabel1 = new javax.swing.JLabel();
313  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));
314  commonViewInGeolocationBtn = new javax.swing.JButton();
315  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));
316 
317  mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
318  mainContentPanel.setLayout(new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS));
319 
320  ingestRunningPanel.setAlignmentX(0.0F);
321  ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25));
322  ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25));
323  ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25));
324  mainContentPanel.add(ingestRunningPanel);
325 
326  org.openide.awt.Mnemonics.setLocalizedText(mostRecentLabel, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.mostRecentLabel.text")); // NOI18N
327  mainContentPanel.add(mostRecentLabel);
328  mostRecentLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N
329 
330  filler1.setAlignmentX(0.0F);
331  mainContentPanel.add(filler1);
332 
333  mostRecentPanel.setAlignmentX(0.0F);
334  mostRecentPanel.setMaximumSize(new java.awt.Dimension(32767, 106));
335  mostRecentPanel.setMinimumSize(new java.awt.Dimension(100, 106));
336  mostRecentPanel.setPreferredSize(new java.awt.Dimension(100, 106));
337  mainContentPanel.add(mostRecentPanel);
338 
339  filler2.setAlignmentX(0.0F);
340  mainContentPanel.add(filler2);
341 
342  org.openide.awt.Mnemonics.setLocalizedText(withinDistanceLabel, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.withinDistanceLabel.text")); // NOI18N
343  mainContentPanel.add(withinDistanceLabel);
344 
345  filler3.setAlignmentX(0.0F);
346  mainContentPanel.add(filler3);
347 
348  org.openide.awt.Mnemonics.setLocalizedText(recentViewInGeolocationBtn, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.recentViewInGeolocationBtn.text")); // NOI18N
349  recentViewInGeolocationBtn.setEnabled(false);
350  recentViewInGeolocationBtn.addActionListener(new java.awt.event.ActionListener() {
351  public void actionPerformed(java.awt.event.ActionEvent evt) {
352  recentViewInGeolocationBtnActionPerformed(evt);
353  }
354  });
355  mainContentPanel.add(recentViewInGeolocationBtn);
356 
357  filler8.setAlignmentX(0.0F);
358  mainContentPanel.add(filler8);
359 
360  org.openide.awt.Mnemonics.setLocalizedText(mostCommonLabel, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.mostCommonLabel.text")); // NOI18N
361  mainContentPanel.add(mostCommonLabel);
362 
363  filler7.setAlignmentX(0.0F);
364  mainContentPanel.add(filler7);
365 
366  mostCommonPanel.setAlignmentX(0.0F);
367  mostCommonPanel.setMaximumSize(new java.awt.Dimension(32767, 106));
368  mostCommonPanel.setMinimumSize(new java.awt.Dimension(100, 106));
369  mostCommonPanel.setPreferredSize(new java.awt.Dimension(100, 106));
370  mainContentPanel.add(mostCommonPanel);
371 
372  filler6.setAlignmentX(0.0F);
373  mainContentPanel.add(filler6);
374 
375  org.openide.awt.Mnemonics.setLocalizedText(withinDistanceLabel1, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.withinDistanceLabel1.text")); // NOI18N
376  mainContentPanel.add(withinDistanceLabel1);
377 
378  filler4.setAlignmentX(0.0F);
379  mainContentPanel.add(filler4);
380 
381  org.openide.awt.Mnemonics.setLocalizedText(commonViewInGeolocationBtn, org.openide.util.NbBundle.getMessage(GeolocationPanel.class, "GeolocationPanel.commonViewInGeolocationBtn.text")); // NOI18N
382  commonViewInGeolocationBtn.setEnabled(false);
383  commonViewInGeolocationBtn.addActionListener(new java.awt.event.ActionListener() {
384  public void actionPerformed(java.awt.event.ActionEvent evt) {
385  commonViewInGeolocationBtnActionPerformed(evt);
386  }
387  });
388  mainContentPanel.add(commonViewInGeolocationBtn);
389 
390  filler5.setAlignmentX(0.0F);
391  mainContentPanel.add(filler5);
392 
393  mainScrollPane.setViewportView(mainContentPanel);
394 
395  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
396  this.setLayout(layout);
397  layout.setHorizontalGroup(
398  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
399  .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
400  );
401  layout.setVerticalGroup(
402  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
403  .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 746, Short.MAX_VALUE)
404  );
405  }// </editor-fold>//GEN-END:initComponents
406 
407  private void recentViewInGeolocationBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_recentViewInGeolocationBtnActionPerformed
408  openGeolocationWindow(getDataSource(), DAYS_COUNT);
409  }//GEN-LAST:event_recentViewInGeolocationBtnActionPerformed
410 
411  private void commonViewInGeolocationBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_commonViewInGeolocationBtnActionPerformed
412  openGeolocationWindow(getDataSource(), null);
413  }//GEN-LAST:event_commonViewInGeolocationBtnActionPerformed
414 
415 
416  // Variables declaration - do not modify//GEN-BEGIN:variables
417  private javax.swing.JButton commonViewInGeolocationBtn;
418  private javax.swing.JButton recentViewInGeolocationBtn;
419  // End of variables declaration//GEN-END:variables
420 }
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 > JTablePanel< T > getJTablePanel(List< ColumnModel< T >> columns)
Pair< String, Integer > formatRecord(CityRecordCount cityCount)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void showCityContent(DataFetchResult< CityCountsList > result, JTablePanel< Pair< String, Integer >> table, JButton goToGeolocation)
final List< DataFetchComponents< DataSource,?> > dataFetchComponents

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