Autopsy  4.19.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.Color;
22 import java.sql.SQLException;
23 import java.text.DecimalFormat;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.stream.Collectors;
31 import java.util.stream.Stream;
32 import org.openide.util.NbBundle.Messages;
53 
54 import org.sleuthkit.datamodel.DataSource;
55 import org.sleuthkit.datamodel.TskCoreException;
56 
61 @Messages({
62  "TypesPanel_artifactsTypesPieChart_title=Artifact Types",
63  "TypesPanel_filesByCategoryTable_allocatedRow_title=Allocated Files",
64  "TypesPanel_filesByCategoryTable_unallocatedRow_title=Unallocated Files",
65  "TypesPanel_filesByCategoryTable_slackRow_title=Slack Files",
66  "TypesPanel_filesByCategoryTable_directoryRow_title=Directories",
67  "TypesPanel_fileMimeTypesChart_title=File Types",
68  "TypesPanel_fileMimeTypesChart_valueLabel=Count",
69  "TypesPanel_fileMimeTypesChart_audio_title=Audio",
70  "TypesPanel_fileMimeTypesChart_documents_title=Documents",
71  "TypesPanel_fileMimeTypesChart_executables_title=Executables",
72  "TypesPanel_fileMimeTypesChart_images_title=Images",
73  "TypesPanel_fileMimeTypesChart_videos_title=Videos",
74  "TypesPanel_fileMimeTypesChart_other_title=Other",
75  "TypesPanel_fileMimeTypesChart_unknown_title=Unknown",
76  "TypesPanel_fileMimeTypesChart_notAnalyzed_title=Not Analyzed",
77  "TypesPanel_usageLabel_title=Usage",
78  "TypesPanel_osLabel_title=OS",
79  "TypesPanel_sizeLabel_title=Size",
80  "TypesPanel_excelTabName=Types"})
81 class TypesPanel extends BaseDataSourceSummaryPanel {
82 
86  private static class TypesPieChartData {
87 
88  private final List<PieChartItem> pieSlices;
89  private final boolean usefulContent;
90 
98  public TypesPieChartData(List<PieChartItem> pieSlices, boolean usefulContent) {
99  this.pieSlices = pieSlices;
100  this.usefulContent = usefulContent;
101  }
102 
106  public List<PieChartItem> getPieSlices() {
107  return pieSlices;
108  }
109 
113  public boolean isUsefulContent() {
114  return usefulContent;
115  }
116  }
117 
121  private static class TypesPieCategory {
122 
123  private final String label;
124  private final Set<String> mimeTypes;
125  private final Color color;
126 
134  TypesPieCategory(String label, Set<String> mimeTypes, Color color) {
135  this.label = label;
136  this.mimeTypes = mimeTypes;
137  this.color = color;
138  }
139 
147  TypesPieCategory(String label, FileTypeCategory fileCategory, Color color) {
148  this(label, fileCategory.getMediaTypes(), color);
149  }
150 
154  String getLabel() {
155  return label;
156  }
157 
161  Set<String> getMimeTypes() {
162  return mimeTypes;
163  }
164 
168  Color getColor() {
169  return color;
170  }
171  }
172 
173  private static final long serialVersionUID = 1L;
174  private static final DecimalFormat INTEGER_SIZE_FORMAT = new DecimalFormat("#");
175  private static final String COMMA_FORMAT_STR = "#,###";
176 
177  private static final DecimalFormat COMMA_FORMATTER = new DecimalFormat(COMMA_FORMAT_STR);
178 
179  private static final Color IMAGES_COLOR = new Color(156, 39, 176);
180  private static final Color VIDEOS_COLOR = Color.YELLOW;
181  private static final Color AUDIO_COLOR = Color.BLUE;
182  private static final Color DOCUMENTS_COLOR = Color.GREEN;
183  private static final Color EXECUTABLES_COLOR = new Color(0, 188, 212);
184  private static final Color UNKNOWN_COLOR = Color.ORANGE;
185  private static final Color OTHER_COLOR = new Color(78, 52, 46);
186  private static final Color NOT_ANALYZED_COLOR = Color.WHITE;
187 
188  // All file type categories.
189  private static final List<TypesPieCategory> FILE_MIME_TYPE_CATEGORIES = Arrays.asList(
190  new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_images_title(), FileTypeCategory.IMAGE.getMediaTypes(), IMAGES_COLOR),
191  new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_videos_title(), FileTypeCategory.VIDEO.getMediaTypes(), VIDEOS_COLOR),
192  new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_audio_title(), FileTypeCategory.AUDIO.getMediaTypes(), AUDIO_COLOR),
193  new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_documents_title(), FileTypeCategory.DOCUMENTS.getMediaTypes(), DOCUMENTS_COLOR),
194  new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_executables_title(), FileTypeCategory.EXECUTABLE.getMediaTypes(), EXECUTABLES_COLOR),
195  new TypesPieCategory(Bundle.TypesPanel_fileMimeTypesChart_unknown_title(), new HashSet<>(Arrays.asList("application/octet-stream")), UNKNOWN_COLOR)
196  );
197 
198  private final DataFetcher<DataSource, String> usageFetcher;
199  private final DataFetcher<DataSource, String> osFetcher;
200  private final DataFetcher<DataSource, Long> sizeFetcher;
201 
202  private final DataFetcher<DataSource, TypesPieChartData> typesFetcher;
203 
204  private final DataFetcher<DataSource, Long> allocatedFetcher;
205  private final DataFetcher<DataSource, Long> unallocatedFetcher;
206  private final DataFetcher<DataSource, Long> slackFetcher;
207  private final DataFetcher<DataSource, Long> directoriesFetcher;
208 
209  private final LoadableLabel usageLabel = new LoadableLabel(Bundle.TypesPanel_usageLabel_title());
210  private final LoadableLabel osLabel = new LoadableLabel(Bundle.TypesPanel_osLabel_title());
211  private final LoadableLabel sizeLabel = new LoadableLabel(Bundle.TypesPanel_sizeLabel_title());
212 
213  private final PieChartPanel fileMimeTypesChart = new PieChartPanel(Bundle.TypesPanel_fileMimeTypesChart_title());
214 
215  private final LoadableLabel allocatedLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_allocatedRow_title());
216  private final LoadableLabel unallocatedLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_unallocatedRow_title());
217  private final LoadableLabel slackLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_slackRow_title());
218  private final LoadableLabel directoriesLabel = new LoadableLabel(Bundle.TypesPanel_filesByCategoryTable_directoryRow_title());
219 
220  // all loadable components
221  private final List<LoadableComponent<?>> loadables = Arrays.asList(
222  usageLabel,
223  osLabel,
224  sizeLabel,
225  fileMimeTypesChart,
226  allocatedLabel,
227  unallocatedLabel,
228  slackLabel,
229  directoriesLabel
230  );
231 
232  private final IngestRunningLabel ingestRunningLabel = new IngestRunningLabel();
233 
234  // all of the means for obtaining data for the gui components.
235  private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
236 
240  public TypesPanel() {
241  this(new MimeTypeSummary(), new TypesSummary(), new ContainerSummary());
242  }
243 
244  @Override
245  public void close() {
246  ingestRunningLabel.unregister();
247  super.close();
248  }
249 
257  public TypesPanel(
258  MimeTypeSummary mimeTypeData,
259  TypesSummary typeData,
260  ContainerSummary containerData) {
261 
262  super(mimeTypeData, typeData, containerData);
263 
264  this.usageFetcher = containerData::getDataSourceType;
265  this.osFetcher = containerData::getOperatingSystems;
266 
267  this.sizeFetcher = (dataSource) -> dataSource == null ? null : dataSource.getSize();
268 
269  this.typesFetcher = (dataSource) -> getMimeTypeCategoriesModel(mimeTypeData, dataSource);
270 
271  this.allocatedFetcher = (dataSource) -> typeData.getCountOfAllocatedFiles(dataSource);
272  this.unallocatedFetcher = (dataSource) -> typeData.getCountOfUnallocatedFiles(dataSource);
273  this.slackFetcher = (dataSource) -> typeData.getCountOfSlackFiles(dataSource);
274  this.directoriesFetcher = (dataSource) -> typeData.getCountOfDirectories(dataSource);
275 
276  this.dataFetchComponents = Arrays.asList(
277  new DataFetchWorker.DataFetchComponents<>(usageFetcher, usageLabel::showDataFetchResult),
278  new DataFetchWorker.DataFetchComponents<>(osFetcher, osLabel::showDataFetchResult),
279  new DataFetchWorker.DataFetchComponents<>(sizeFetcher,
280  (sizeResult) -> sizeLabel.showDataFetchResult(
281  DataFetchResult.getSubResult(sizeResult,
282  size -> SizeRepresentationUtil.getSizeString(size, INTEGER_SIZE_FORMAT, false)))),
283  new DataFetchWorker.DataFetchComponents<>(typesFetcher, this::showMimeTypeCategories),
284  new DataFetchWorker.DataFetchComponents<>(allocatedFetcher,
285  countRes -> allocatedLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count)))),
286  new DataFetchWorker.DataFetchComponents<>(unallocatedFetcher,
287  countRes -> unallocatedLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count)))),
288  new DataFetchWorker.DataFetchComponents<>(slackFetcher,
289  countRes -> slackLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count)))),
290  new DataFetchWorker.DataFetchComponents<>(directoriesFetcher,
291  countRes -> directoriesLabel.showDataFetchResult(DataFetchResult.getSubResult(countRes, (count) -> getStringOrZero(count))))
292  );
293 
294  initComponents();
295  }
296 
297  @Override
298  protected void fetchInformation(DataSource dataSource) {
299  fetchInformation(dataFetchComponents, dataSource);
300  }
301 
302  @Override
303  protected void onNewDataSource(DataSource dataSource) {
304  onNewDataSource(dataFetchComponents, loadables, dataSource);
305  }
306 
315  private TypesPieChartData getMimeTypeCategoriesModel(MimeTypeSummary mimeTypeData, DataSource dataSource)
316  throws SQLException, SleuthkitCaseProviderException, TskCoreException {
317 
318  if (dataSource == null) {
319  return null;
320  }
321 
322  // for each category of file types, get the counts of files
323  List<PieChartItem> fileCategoryItems = new ArrayList<>();
324  long categoryTotalCount = 0;
325 
326  for (TypesPieCategory cat : FILE_MIME_TYPE_CATEGORIES) {
327  long thisValue = getLongOrZero(mimeTypeData.getCountOfFilesForMimeTypes(dataSource, cat.getMimeTypes()));
328  categoryTotalCount += thisValue;
329 
330  fileCategoryItems.add(new PieChartItem(
331  cat.getLabel(),
332  thisValue,
333  cat.getColor()));
334  }
335 
336  // get a count of all files with no mime type
337  long noMimeTypeCount = getLongOrZero(mimeTypeData.getCountOfFilesWithNoMimeType(dataSource));
338 
339  // get a count of all regular files
340  long allRegularFiles = getLongOrZero(mimeTypeData.getCountOfAllRegularFiles(dataSource));
341 
342  // create entry for mime types in other category
343  long otherCount = allRegularFiles - (categoryTotalCount + noMimeTypeCount);
344  PieChartItem otherPieItem = new PieChartItem(Bundle.TypesPanel_fileMimeTypesChart_other_title(),
345  otherCount, OTHER_COLOR);
346 
347  // check at this point to see if these are all 0; if so, we don't have useful content.
348  boolean usefulContent = categoryTotalCount > 0 || otherCount > 0;
349 
350  // create entry for not analyzed mime types category
351  PieChartItem notAnalyzedItem = new PieChartItem(Bundle.TypesPanel_fileMimeTypesChart_notAnalyzed_title(),
352  noMimeTypeCount, NOT_ANALYZED_COLOR);
353 
354  // combine categories with 'other' and 'not analyzed'
355  List<PieChartItem> items = Stream.concat(
356  fileCategoryItems.stream(),
357  Stream.of(otherPieItem, notAnalyzedItem))
358  // remove items that have no value
359  .filter(slice -> slice.getValue() > 0)
360  .collect(Collectors.toList());
361 
362  return new TypesPieChartData(items, usefulContent);
363  }
364 
373  private void showMimeTypeCategories(DataFetchResult<TypesPieChartData> result) {
374  if (result == null) {
375  fileMimeTypesChart.showDataFetchResult(DataFetchResult.getSuccessResult(null));
376  return;
377  }
378 
379  // if error, show error
380  if (result.getResultType() == ResultType.ERROR) {
381  fileMimeTypesChart.showDataFetchResult(DataFetchResult.getErrorResult(result.getException()));
382  return;
383  }
384 
385  TypesPieChartData data = result.getData();
386  if (data == null) {
387  fileMimeTypesChart.showDataFetchResult(DataFetchResult.getSuccessResult(null));
388  } else {
389  fileMimeTypesChart.showDataFetchResult(DataFetchResult.getSuccessResult(data.getPieSlices()));
390  }
391  }
392 
400  private static long getLongOrZero(Long longVal) {
401  return longVal == null ? 0 : longVal;
402  }
403 
412  private static String getStringOrZero(Long longVal) {
413  return longVal == null ? "0" : COMMA_FORMATTER.format(longVal);
414  }
415 
424  private static KeyValueItemExportable getStrExportable(DataFetcher<DataSource, String> fetcher, String key, DataSource dataSource) {
425  String result = getFetchResult(fetcher, "Types", dataSource);
426  return (result == null) ? null : new KeyValueItemExportable(key, new DefaultCellModel<>(result));
427  }
428 
438  private static KeyValueItemExportable getCountExportable(DataFetcher<DataSource, Long> fetcher, String key, DataSource dataSource) {
439  Long count = getFetchResult(fetcher, "Types", dataSource);
440  return (count == null) ? null : new KeyValueItemExportable(key,
441  new DefaultCellModel<Long>(count, COMMA_FORMATTER::format, COMMA_FORMAT_STR));
442  }
443 
444  @Override
445  List<ExcelExport.ExcelSheetExport> getExports(DataSource dataSource) {
446  if (dataSource == null) {
447  return Collections.emptyList();
448  }
449 
450  // Retrieve data to create the types pie chart
451  TypesPieChartData typesData = TypesPanel.getFetchResult(typesFetcher, "Types", dataSource);
452  PieChartExport typesChart = (typesData == null || !typesData.isUsefulContent()) ? null :
453  new PieChartExport(
454  Bundle.TypesPanel_fileMimeTypesChart_title(),
455  Bundle.TypesPanel_fileMimeTypesChart_valueLabel(),
456  "#,###",
457  Bundle.TypesPanel_fileMimeTypesChart_title(),
458  typesData.getPieSlices());
459 
460  return Arrays.asList(new ExcelSpecialFormatExport(Bundle.TypesPanel_excelTabName(),
461  Stream.of(
462  getStrExportable(usageFetcher, Bundle.TypesPanel_usageLabel_title(), dataSource),
463  getStrExportable(osFetcher, Bundle.TypesPanel_osLabel_title(), dataSource),
464  new KeyValueItemExportable(Bundle.TypesPanel_sizeLabel_title(),
465  SizeRepresentationUtil.getBytesCell(getFetchResult(sizeFetcher, "Types", dataSource))),
466  typesChart,
467  getCountExportable(allocatedFetcher, Bundle.TypesPanel_filesByCategoryTable_allocatedRow_title(), dataSource),
468  getCountExportable(unallocatedFetcher, Bundle.TypesPanel_filesByCategoryTable_unallocatedRow_title(), dataSource),
469  getCountExportable(slackFetcher, Bundle.TypesPanel_filesByCategoryTable_slackRow_title(), dataSource),
470  getCountExportable(directoriesFetcher, Bundle.TypesPanel_filesByCategoryTable_directoryRow_title(), dataSource))
471  .filter(sheet -> sheet != null)
472  .collect(Collectors.toList())
473  ));
474  }
475 
481  @SuppressWarnings("unchecked")
482  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
483  private void initComponents() {
484 
485  javax.swing.JScrollPane scrollParent = new javax.swing.JScrollPane();
486  javax.swing.JPanel contentParent = new javax.swing.JPanel();
487  javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
488  javax.swing.JPanel usagePanel = usageLabel;
489  javax.swing.JPanel osPanel = osLabel;
490  javax.swing.JPanel sizePanel = sizeLabel;
491  javax.swing.JPanel fileMimeTypesPanel = fileMimeTypesChart;
492  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));
493  javax.swing.JPanel allocatedPanel = allocatedLabel;
494  javax.swing.JPanel unallocatedPanel = unallocatedLabel;
495  javax.swing.JPanel slackPanel = slackLabel;
496  javax.swing.JPanel directoriesPanel = directoriesLabel;
497  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));
498 
499  setLayout(new java.awt.BorderLayout());
500 
501  contentParent.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
502  contentParent.setMaximumSize(new java.awt.Dimension(32787, 32787));
503  contentParent.setMinimumSize(new java.awt.Dimension(400, 490));
504  contentParent.setLayout(new javax.swing.BoxLayout(contentParent, javax.swing.BoxLayout.PAGE_AXIS));
505 
506  ingestRunningPanel.setAlignmentX(0.0F);
507  ingestRunningPanel.setMaximumSize(new java.awt.Dimension(32767, 25));
508  ingestRunningPanel.setMinimumSize(new java.awt.Dimension(10, 25));
509  ingestRunningPanel.setPreferredSize(new java.awt.Dimension(10, 25));
510  contentParent.add(ingestRunningPanel);
511 
512  usagePanel.setAlignmentX(0.0F);
513  usagePanel.setMaximumSize(new java.awt.Dimension(32767, 20));
514  usagePanel.setMinimumSize(new java.awt.Dimension(10, 20));
515  usagePanel.setName(""); // NOI18N
516  usagePanel.setPreferredSize(new java.awt.Dimension(800, 20));
517  contentParent.add(usagePanel);
518 
519  osPanel.setAlignmentX(0.0F);
520  osPanel.setMaximumSize(new java.awt.Dimension(32767, 20));
521  osPanel.setMinimumSize(new java.awt.Dimension(10, 20));
522  osPanel.setPreferredSize(new java.awt.Dimension(800, 20));
523  contentParent.add(osPanel);
524 
525  sizePanel.setAlignmentX(0.0F);
526  sizePanel.setMaximumSize(new java.awt.Dimension(32767, 20));
527  sizePanel.setMinimumSize(new java.awt.Dimension(10, 20));
528  sizePanel.setPreferredSize(new java.awt.Dimension(800, 20));
529  contentParent.add(sizePanel);
530 
531  fileMimeTypesPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
532  fileMimeTypesPanel.setAlignmentX(0.0F);
533  fileMimeTypesPanel.setMaximumSize(new java.awt.Dimension(400, 300));
534  fileMimeTypesPanel.setMinimumSize(new java.awt.Dimension(400, 300));
535  fileMimeTypesPanel.setPreferredSize(new java.awt.Dimension(400, 300));
536  contentParent.add(fileMimeTypesPanel);
537  contentParent.add(filler2);
538 
539  allocatedPanel.setAlignmentX(0.0F);
540  allocatedPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
541  allocatedPanel.setMinimumSize(new java.awt.Dimension(10, 16));
542  allocatedPanel.setPreferredSize(new java.awt.Dimension(800, 16));
543  contentParent.add(allocatedPanel);
544 
545  unallocatedPanel.setAlignmentX(0.0F);
546  unallocatedPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
547  unallocatedPanel.setMinimumSize(new java.awt.Dimension(10, 16));
548  unallocatedPanel.setPreferredSize(new java.awt.Dimension(800, 16));
549  contentParent.add(unallocatedPanel);
550 
551  slackPanel.setAlignmentX(0.0F);
552  slackPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
553  slackPanel.setMinimumSize(new java.awt.Dimension(10, 16));
554  slackPanel.setPreferredSize(new java.awt.Dimension(800, 16));
555  contentParent.add(slackPanel);
556 
557  directoriesPanel.setAlignmentX(0.0F);
558  directoriesPanel.setMaximumSize(new java.awt.Dimension(32767, 16));
559  directoriesPanel.setMinimumSize(new java.awt.Dimension(10, 16));
560  directoriesPanel.setPreferredSize(new java.awt.Dimension(800, 16));
561  contentParent.add(directoriesPanel);
562  contentParent.add(filler3);
563 
564  scrollParent.setViewportView(contentParent);
565 
566  add(scrollParent, java.awt.BorderLayout.CENTER);
567  }// </editor-fold>//GEN-END:initComponents
568 
569 
570  // Variables declaration - do not modify//GEN-BEGIN:variables
571  // End of variables declaration//GEN-END:variables
572 }
TypesPieChartData(List< PieChartItem > pieSlices, boolean usefulContent)
Definition: TypesPanel.java:98

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.