Autopsy  4.16.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
TypesPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019 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.awt.BorderLayout;
22 import java.sql.SQLException;
23 import java.text.DecimalFormat;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import javax.swing.JLabel;
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.commons.lang3.tuple.Pair;
34 import org.openide.util.NbBundle.Messages;
52 
53 import org.sleuthkit.datamodel.DataSource;
54 import org.sleuthkit.datamodel.TskCoreException;
55 
60 @Messages({
61  "TypesPanel_artifactsTypesPieChart_title=Artifact Types",
62  "TypesPanel_filesByCategoryTable_allocatedRow_title=Allocated Files",
63  "TypesPanel_filesByCategoryTable_unallocatedRow_title=Unallocated Files",
64  "TypesPanel_filesByCategoryTable_slackRow_title=Slack Files",
65  "TypesPanel_filesByCategoryTable_directoryRow_title=Directories",
66  "TypesPanel_fileMimeTypesChart_title=File Types",
67  "TypesPanel_fileMimeTypesChart_audio_title=Audio",
68  "TypesPanel_fileMimeTypesChart_documents_title=Documents",
69  "TypesPanel_fileMimeTypesChart_executables_title=Executables",
70  "TypesPanel_fileMimeTypesChart_images_title=Images",
71  "TypesPanel_fileMimeTypesChart_videos_title=Videos",
72  "TypesPanel_fileMimeTypesChart_other_title=Other",
73  "TypesPanel_fileMimeTypesChart_unknown_title=Unknown",
74  "TypesPanel_fileMimeTypesChart_notAnalyzed_title=Not Analyzed",
75  "TypesPanel_usageLabel_title=Usage",
76  "TypesPanel_osLabel_title=OS",
77  "TypesPanel_sizeLabel_title=Size"})
78 class TypesPanel extends BaseDataSourceSummaryPanel {
79 
84  private static class LoadableLabel extends AbstractLoadableComponent<String> {
85 
86  private static final long serialVersionUID = 1L;
87 
88  private final JLabel label = new JLabel();
89  private final String key;
90 
96  LoadableLabel(String key) {
97  this.key = key;
98  setLayout(new BorderLayout());
99  add(label, BorderLayout.CENTER);
100  this.showResults(null);
101  }
102 
103  private void setValue(String value) {
104  String formattedKey = StringUtils.isBlank(key) ? "" : key;
105  String formattedValue = StringUtils.isBlank(value) ? "" : value;
106  label.setText(String.format("%s: %s", formattedKey, formattedValue));
107  }
108 
109  @Override
110  protected void setMessage(boolean visible, String message) {
111  setValue(message);
112  }
113 
114  @Override
115  protected void setResults(String data) {
116  setValue(data);
117  }
118  }
119 
123  private static class TypesPieChartData {
124 
125  private final List<PieChartItem> pieSlices;
126  private final boolean usefulContent;
127 
135  public TypesPieChartData(List<PieChartItem> pieSlices, boolean usefulContent) {
136  this.pieSlices = pieSlices;
137  this.usefulContent = usefulContent;
138  }
139 
143  public List<PieChartItem> getPieSlices() {
144  return pieSlices;
145  }
146 
150  public boolean isUsefulContent() {
151  return usefulContent;
152  }
153  }
154 
155  private static final long serialVersionUID = 1L;
156  private static final DecimalFormat INTEGER_SIZE_FORMAT = new DecimalFormat("#");
157  private static final DecimalFormat COMMA_FORMATTER = new DecimalFormat("#,###");
158  private static final String FILE_TYPE_FACTORY = FileTypeIdModuleFactory.class.getCanonicalName();
159  private static final String FILE_TYPE_MODULE_NAME = FileTypeIdModuleFactory.getModuleName();
160  private static final Logger logger = Logger.getLogger(TypesPanel.class.getName());
161 
162  // All file type categories.
163  private static final List<Pair<String, Set<String>>> FILE_MIME_TYPE_CATEGORIES = Arrays.asList(
164  Pair.of(Bundle.TypesPanel_fileMimeTypesChart_images_title(), FileTypeCategory.IMAGE.getMediaTypes()),
165  Pair.of(Bundle.TypesPanel_fileMimeTypesChart_videos_title(), FileTypeCategory.VIDEO.getMediaTypes()),
166  Pair.of(Bundle.TypesPanel_fileMimeTypesChart_audio_title(), FileTypeCategory.AUDIO.getMediaTypes()),
167  Pair.of(Bundle.TypesPanel_fileMimeTypesChart_documents_title(), FileTypeCategory.DOCUMENTS.getMediaTypes()),
168  Pair.of(Bundle.TypesPanel_fileMimeTypesChart_executables_title(), FileTypeCategory.EXECUTABLE.getMediaTypes()),
169  Pair.of(Bundle.TypesPanel_fileMimeTypesChart_unknown_title(), new HashSet<>(Arrays.asList("application/octet-stream")))
170  );
171 
172  private final LoadableLabel usageLabel = new LoadableLabel(Bundle.TypesPanel_usageLabel_title());
173  private final LoadableLabel osLabel = new LoadableLabel(Bundle.TypesPanel_osLabel_title());
174  private final LoadableLabel sizeLabel = new LoadableLabel(Bundle.TypesPanel_sizeLabel_title());
175 
176  private final PieChartPanel fileMimeTypesChart = new PieChartPanel(Bundle.TypesPanel_fileMimeTypesChart_title());
177 
178  private final LoadableLabel allocatedLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_allocatedRow_title());
179  private final LoadableLabel unallocatedLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_unallocatedRow_title());
180  private final LoadableLabel slackLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_slackRow_title());
181  private final LoadableLabel directoriesLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_directoryRow_title());
182 
183  // all loadable components
184  private final List<LoadableComponent<?>> loadables = Arrays.asList(
185  usageLabel,
186  osLabel,
187  sizeLabel,
188  fileMimeTypesChart,
189  allocatedLabel,
190  unallocatedLabel,
191  slackLabel,
192  directoriesLabel
193  );
194 
195  private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel();
196 
197  // all of the means for obtaining data for the gui components.
198  private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
199 
203  public TypesPanel() {
204  this(new MimeTypeSummary(), new TypesSummary(), new ContainerSummary());
205  }
206 
207  @Override
208  public void close() {
209  ingestRunningLabel.unregister();
210  super.close();
211  }
212 
220  public TypesPanel(
221  MimeTypeSummary mimeTypeData,
222  TypesSummary typeData,
223  ContainerSummary containerData) {
224 
225  super(mimeTypeData, typeData, containerData);
226 
227  this.dataFetchComponents = Arrays.asList(
228  // usage label worker
229  new DataFetchWorker.DataFetchComponents<>(
230  containerData::getDataSourceType,
231  (result) -> {
232  showResultWithModuleCheck(
233  usageLabel,
234  result,
235  StringUtils::isNotBlank,
236  IngestModuleCheckUtil.RECENT_ACTIVITY_FACTORY,
237  IngestModuleCheckUtil.RECENT_ACTIVITY_MODULE_NAME);
238  }),
239  // os label worker
240  new DataFetchWorker.DataFetchComponents<>(
241  containerData::getOperatingSystems,
242  (result) -> {
243  showResultWithModuleCheck(
244  osLabel,
245  result,
246  StringUtils::isNotBlank,
247  IngestModuleCheckUtil.RECENT_ACTIVITY_FACTORY,
248  IngestModuleCheckUtil.RECENT_ACTIVITY_MODULE_NAME);
249  }),
250  // size label worker
251  new DataFetchWorker.DataFetchComponents<>(
252  (dataSource) -> {
253  Long size = dataSource == null ? null : dataSource.getSize();
254  return SizeRepresentationUtil.getSizeString(size, INTEGER_SIZE_FORMAT, false);
255  },
256  sizeLabel::showDataFetchResult),
257  // file types worker
258  new DataFetchWorker.DataFetchComponents<>(
259  (dataSource) -> getMimeTypeCategoriesModel(mimeTypeData, dataSource),
260  this::showMimeTypeCategories),
261  // allocated files worker
262  new DataFetchWorker.DataFetchComponents<>(
263  (dataSource) -> getStringOrZero(typeData.getCountOfAllocatedFiles(dataSource)),
264  allocatedLabel::showDataFetchResult),
265  // unallocated files worker
266  new DataFetchWorker.DataFetchComponents<>(
267  (dataSource) -> getStringOrZero(typeData.getCountOfUnallocatedFiles(dataSource)),
268  unallocatedLabel::showDataFetchResult),
269  // slack files worker
270  new DataFetchWorker.DataFetchComponents<>(
271  (dataSource) -> getStringOrZero(typeData.getCountOfSlackFiles(dataSource)),
272  slackLabel::showDataFetchResult),
273  // directories worker
274  new DataFetchWorker.DataFetchComponents<>(
275  (dataSource) -> getStringOrZero(typeData.getCountOfDirectories(dataSource)),
276  directoriesLabel::showDataFetchResult)
277  );
278 
279  initComponents();
280  }
281 
282  @Override
283  protected void fetchInformation(DataSource dataSource) {
284  fetchInformation(dataFetchComponents, dataSource);
285  }
286 
287  @Override
288  protected void onNewDataSource(DataSource dataSource) {
289  onNewDataSource(dataFetchComponents, loadables, dataSource);
290  }
291 
299  private TypesPieChartData getMimeTypeCategoriesModel(MimeTypeSummary mimeTypeData, DataSource dataSource)
300  throws SQLException, SleuthkitCaseProviderException, TskCoreException {
301 
302  if (dataSource == null) {
303  return null;
304  }
305 
306  // for each category of file types, get the counts of files
307  List<Pair<String, Long>> fileCategoryItems = new ArrayList<>();
308  for (Pair<String, Set<String>> strCat : FILE_MIME_TYPE_CATEGORIES) {
309  fileCategoryItems.add(Pair.of(strCat.getLeft(),
310  getLongOrZero(mimeTypeData.getCountOfFilesForMimeTypes(
311  dataSource, strCat.getRight()))));
312  }
313 
314  // get a count of all files with no mime type
315  Long noMimeTypeCount = getLongOrZero(mimeTypeData.getCountOfFilesWithNoMimeType(dataSource));
316 
317  // get the sum of all counts for the known categories
318  Long categoryTotalCount = getLongOrZero(fileCategoryItems.stream()
319  .collect(Collectors.summingLong((pair) -> pair.getValue())));
320 
321  // get a count of all regular files
322  Long allRegularFiles = getLongOrZero(mimeTypeData.getCountOfAllRegularFiles(dataSource));
323 
324  // create entry for mime types in other category
325  fileCategoryItems.add(Pair.of(Bundle.TypesPanel_fileMimeTypesChart_other_title(),
326  allRegularFiles - (categoryTotalCount + noMimeTypeCount)));
327 
328  // check at this point to see if these are all 0; if so, we don't have useful content.
329  boolean usefulContent = fileCategoryItems.stream().anyMatch((pair) -> pair.getValue() != null && pair.getValue() > 0);
330 
331  // create entry for not analyzed mime types category
332  fileCategoryItems.add(Pair.of(Bundle.TypesPanel_fileMimeTypesChart_notAnalyzed_title(),
333  noMimeTypeCount));
334 
335  // create pie chart items to provide to pie chart
336  List<PieChartItem> items = fileCategoryItems.stream()
337  .filter(keyCount -> keyCount.getRight() != null && keyCount.getRight() > 0)
338  .map(keyCount -> new PieChartItem(keyCount.getLeft(), keyCount.getRight()))
339  .collect(Collectors.toList());
340 
341  return new TypesPieChartData(items, usefulContent);
342  }
343 
352  private void showMimeTypeCategories(DataFetchResult<TypesPieChartData> result) {
353  // if result is null check for ingest module and show empty results.
354  if (result == null) {
355  showPieResultWithModuleCheck(null);
356  return;
357  }
358 
359  // if error, show error
360  if (result.getResultType() == ResultType.ERROR) {
361  this.fileMimeTypesChart.showDataFetchResult(DataFetchResult.getErrorResult(result.getException()));
362  return;
363  }
364 
365  TypesPieChartData data = result.getData();
366  if (data == null) {
367  // if no data, do an ingest module check with empty results
368  showPieResultWithModuleCheck(null);
369  } else if (!data.isUsefulContent()) {
370  // if no useful data, do an ingest module check and show data
371  showPieResultWithModuleCheck(data.getPieSlices());
372  } else {
373  // otherwise, show the data
374  this.fileMimeTypesChart.showDataFetchResult(DataFetchResult.getSuccessResult(data.getPieSlices()));
375  }
376  }
377 
385  private void showPieResultWithModuleCheck(List<PieChartItem> items) {
386  boolean hasBeenIngested = false;
387  try {
388  hasBeenIngested = this.getIngestModuleCheckUtil().isModuleIngested(getDataSource(), FILE_TYPE_FACTORY);
389  } catch (TskCoreException | SleuthkitCaseProviderException ex) {
390  logger.log(Level.WARNING, "There was an error fetching whether or not the current data source has been ingested with the file type ingest module.", ex);
391  }
392 
393  if (hasBeenIngested) {
394  this.fileMimeTypesChart.showDataFetchResult(DataFetchResult.getSuccessResult(items));
395  } else {
396  this.fileMimeTypesChart.showDataWithMessage(items, getDefaultNoIngestMessage(FILE_TYPE_MODULE_NAME));
397  }
398  }
399 
407  private static long getLongOrZero(Long longVal) {
408  return longVal == null ? 0 : longVal;
409  }
410 
419  private static String getStringOrZero(Long longVal) {
420  return longVal == null ? "0" : COMMA_FORMATTER.format(longVal);
421  }
422 
428  @SuppressWarnings("unchecked")
429  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
430  private void initComponents() {
431 
432  javax.swing.JScrollPane scrollParent = new javax.swing.JScrollPane();
433  javax.swing.JPanel contentParent = new javax.swing.JPanel();
434  javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
435  javax.swing.JPanel usagePanel = usageLabel;
436  javax.swing.JPanel osPanel = osLabel;
437  javax.swing.JPanel sizePanel = sizeLabel;
438  javax.swing.JPanel fileMimeTypesPanel = fileMimeTypesChart;
439  javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
440  javax.swing.JPanel allocatedPanel = allocatedLabel;
441  javax.swing.JPanel unallocatedPanel = unallocatedLabel;
442  javax.swing.JPanel slackPanel = slackLabel;
443  javax.swing.JPanel directoriesPanel = directoriesLabel;
444  javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
445 
446  setLayout(new java.awt.BorderLayout());
447 
448  contentParent.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
449  contentParent.setMaximumSize(new java.awt.Dimension(32787, 32787));
450  contentParent.setMinimumSize(new java.awt.Dimension(400, 490));
451  contentParent.setLayout(new javax.swing.BoxLayout(contentParent, javax.swing.BoxLayout.PAGE_AXIS));
452 
453  ingestRunningPanel.setAlignmentX(0.0F);
454  ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25));
455  ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25));
456  ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25));
457  contentParent.add(ingestRunningPanel);
458 
459  usagePanel.setAlignmentX(0.0F);
460  usagePanel.setMaximumSize(new java.awt.Dimension(32767, 20));
461  usagePanel.setMinimumSize(new java.awt.Dimension(10, 20));
462  usagePanel.setName(""); // NOI18N
463  usagePanel.setPreferredSize(new java.awt.Dimension(800, 20));
464  contentParent.add(usagePanel);
465 
466  osPanel.setAlignmentX(0.0F);
467  osPanel.setMaximumSize(new java.awt.Dimension(32767, 20));
468  osPanel.setMinimumSize(new java.awt.Dimension(10, 20));
469  osPanel.setPreferredSize(new java.awt.Dimension(800, 20));
470  contentParent.add(osPanel);
471 
472  sizePanel.setAlignmentX(0.0F);
473  sizePanel.setMaximumSize(new java.awt.Dimension(32767, 20));
474  sizePanel.setMinimumSize(new java.awt.Dimension(10, 20));
475  sizePanel.setPreferredSize(new java.awt.Dimension(800, 20));
476  contentParent.add(sizePanel);
477 
478  fileMimeTypesPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
479  fileMimeTypesPanel.setAlignmentX(0.0F);
480  fileMimeTypesPanel.setMaximumSize(new java.awt.Dimension(400, 300));
481  fileMimeTypesPanel.setMinimumSize(new java.awt.Dimension(400, 300));
482  fileMimeTypesPanel.setPreferredSize(new java.awt.Dimension(400, 300));
483  contentParent.add(fileMimeTypesPanel);
484  contentParent.add(filler2);
485 
486  allocatedPanel.setAlignmentX(0.0F);
487  allocatedPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
488  allocatedPanel.setMinimumSize(new java.awt.Dimension(10, 16));
489  allocatedPanel.setPreferredSize(new java.awt.Dimension(800, 16));
490  contentParent.add(allocatedPanel);
491 
492  unallocatedPanel.setAlignmentX(0.0F);
493  unallocatedPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
494  unallocatedPanel.setMinimumSize(new java.awt.Dimension(10, 16));
495  unallocatedPanel.setPreferredSize(new java.awt.Dimension(800, 16));
496  contentParent.add(unallocatedPanel);
497 
498  slackPanel.setAlignmentX(0.0F);
499  slackPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
500  slackPanel.setMinimumSize(new java.awt.Dimension(10, 16));
501  slackPanel.setPreferredSize(new java.awt.Dimension(800, 16));
502  contentParent.add(slackPanel);
503 
504  directoriesPanel.setAlignmentX(0.0F);
505  directoriesPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
506  directoriesPanel.setMinimumSize(new java.awt.Dimension(10, 16));
507  directoriesPanel.setPreferredSize(new java.awt.Dimension(800, 16));
508  contentParent.add(directoriesPanel);
509  contentParent.add(filler3);
510 
511  scrollParent.setViewportView(contentParent);
512 
513  add(scrollParent, java.awt.BorderLayout.CENTER);
514  }// </editor-fold>//GEN-END:initComponents
515 
516 
517  // Variables declaration - do not modify//GEN-BEGIN:variables
518  // End of variables declaration//GEN-END:variables
519 }
TypesPieChartData(List< PieChartItem > pieSlices, boolean usefulContent)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

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