Autopsy  4.4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
Reports.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2016 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.datamodel;
20 
21 import java.awt.Desktop;
22 import java.awt.event.ActionEvent;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.io.File;
26 import java.io.IOException;
27 import java.text.SimpleDateFormat;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.EnumSet;
32 import java.util.List;
33 import java.util.Set;
34 import java.util.logging.Level;
35 import javax.swing.AbstractAction;
36 import javax.swing.Action;
37 import javax.swing.JCheckBox;
38 import javax.swing.JOptionPane;
39 import org.openide.nodes.ChildFactory;
40 import org.openide.nodes.Children;
41 import org.openide.nodes.Node;
42 import org.openide.nodes.Sheet;
43 import org.openide.util.NbBundle;
44 import org.openide.util.Utilities;
45 import org.openide.util.lookup.Lookups;
50 import org.sleuthkit.datamodel.Report;
51 import org.sleuthkit.datamodel.TskCoreException;
52 
56 public final class Reports implements AutopsyVisitableItem {
57 
58  private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
59 
60  @Override
61  public <T> T accept(AutopsyItemVisitor<T> visitor) {
62  // CreateAutopsyNodeVisitor.visit() constructs a ReportsListNode.
63  return visitor.visit(this);
64  }
65 
69  public static final class ReportsListNode extends DisplayableItemNode {
70 
71  private static final long serialVersionUID = 1L;
72  private static final String DISPLAY_NAME = NbBundle.getMessage(ReportsListNode.class, "ReportsListNode.displayName");
73  private static final String ICON_PATH = "org/sleuthkit/autopsy/images/report_16.png"; //NON-NLS
74 
75  public ReportsListNode() {
76  super(Children.create(new ReportNodeFactory(), true));
77  setName(DISPLAY_NAME);
78  setDisplayName(DISPLAY_NAME);
79  this.setIconBaseWithExtension(ICON_PATH);
80  }
81 
82  @Override
83  public boolean isLeafTypeNode() {
84  return true;
85  }
86 
87  @Override
88  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
89  // - GetPopupActionsDisplayableItemNodeVisitor.visit() returns null.
90  // - GetPreferredActionsDisplayableItemNodeVisitor.visit() returns null.
91  // - IsLeafItemVisitor.visit() returns false.
92  // - ShowItemVisitor.visit() returns true.
93  return visitor.visit(this);
94  }
95 
96  @Override
97  public String getItemType() {
98  return getClass().getName();
99  }
100  }
101 
106  private static final class ReportNodeFactory extends ChildFactory<Report> {
107 
109 
111  Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> {
112  String eventType = evt.getPropertyName();
113  if (eventType.equals(Case.Events.REPORT_ADDED.toString()) || eventType.equals(Case.Events.REPORT_DELETED.toString())) {
120  try {
122  ReportNodeFactory.this.refresh(true);
123  } catch (IllegalStateException notUsed) {
127  }
128  }
129  });
130  }
131 
132  @Override
133  protected boolean createKeys(List<Report> keys) {
134  try {
135  keys.addAll(Case.getCurrentCase().getAllReports());
136  } catch (TskCoreException ex) {
137  Logger.getLogger(Reports.ReportNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get reports", ex); //NON-NLS
138  }
139  return true;
140  }
141 
142  @Override
143  protected Node createNodeForKey(Report key) {
144  return new ReportNode(key);
145  }
146  }
147 
152  public static final class ReportNode extends DisplayableItemNode {
153 
154  private static final long serialVersionUID = 1L;
155  private static final String ICON_PATH = "org/sleuthkit/autopsy/images/report_16.png"; //NON-NLS
156  private final Report report;
157 
158  ReportNode(Report report) {
159  super(Children.LEAF, Lookups.fixed(report));
160  this.report = report;
161  super.setName(this.report.getSourceModuleName());
162  super.setDisplayName(this.report.getSourceModuleName());
163  this.setIconBaseWithExtension(ICON_PATH);
164  }
165 
166  @Override
167  public boolean isLeafTypeNode() {
168  return true;
169  }
170 
171  @Override
172  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
173  // - GetPopupActionsDisplayableItemNodeVisitor.visit() calls getActions().
174  // - GetPreferredActionsDisplayableItemNodeVisitor.visit() calls getPreferredAction().
175  // - IsLeafItemVisitor.visit() returns true.
176  // - ShowItemVisitor.visit() returns true.
177  return visitor.visit(this);
178  }
179 
180  @Override
181  protected Sheet createSheet() {
182  Sheet sheet = super.createSheet();
183  Sheet.Set propertiesSet = sheet.get(Sheet.PROPERTIES);
184  if (propertiesSet == null) {
185  propertiesSet = Sheet.createPropertiesSet();
186  sheet.put(propertiesSet);
187  }
188  propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.name"),
189  NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.displayName"),
190  NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.desc"),
191  this.report.getSourceModuleName()));
192  propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.reportNameProperty.name"),
193  NbBundle.getMessage(this.getClass(), "ReportNode.reportNameProperty.displayName"),
194  NbBundle.getMessage(this.getClass(), "ReportNode.reportNameProperty.desc"),
195  this.report.getReportName()));
196  propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.name"),
197  NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.displayName"),
198  NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.desc"),
199  dateFormatter.format(new java.util.Date(this.report.getCreatedTime() * 1000))));
200  propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.name"),
201  NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.displayName"),
202  NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.desc"),
203  this.report.getPath()));
204  return sheet;
205  }
206 
207  @Override
208  public Action[] getActions(boolean popup) {
209  List<Action> actions = new ArrayList<>();
210  actions.addAll(Arrays.asList(super.getActions(true)));
211  actions.add(new OpenReportAction());
212  actions.add(DeleteReportAction.getInstance());
213  return actions.toArray(new Action[actions.size()]);
214  }
215 
216  @Override
217  public AbstractAction getPreferredAction() {
218  return new OpenReportAction();
219  }
220 
221  @Override
222  public String getItemType() {
223  return getClass().getName();
224  }
225 
226  private static class DeleteReportAction extends AbstractAction {
227 
228  private static final long serialVersionUID = 1L;
229  private static DeleteReportAction instance;
230 
231  // This class is a singleton to support multi-selection of nodes,
232  // since org.openide.nodes.NodeOp.findActions(Node[] nodes) will
233  // only pick up an Action if every node in the array returns a
234  // reference to the same action object from Node.getActions(boolean).
235  private static DeleteReportAction getInstance() {
236  if (instance == null) {
237  instance = new DeleteReportAction();
238  }
239  if (Utilities.actionsGlobalContext().lookupAll(Report.class).size() == 1) {
240  instance.putValue(Action.NAME, NbBundle.getMessage(Reports.class, "DeleteReportAction.actionDisplayName.singleReport"));
241  } else {
242  instance.putValue(Action.NAME, NbBundle.getMessage(Reports.class, "DeleteReportAction.actionDisplayName.multipleReports"));
243  }
244  return instance;
245  }
246 
251  private DeleteReportAction() {
252  }
253 
254  @NbBundle.Messages({
255  "DeleteReportAction.showConfirmDialog.single.explanation=The report will remain on disk.",
256  "DeleteReportAction.showConfirmDialog.multiple.explanation=The reports will remain on disk.",
257  "DeleteReportAction.showConfirmDialog.errorMsg=An error occurred while deleting the reports."})
258  @Override
259  public void actionPerformed(ActionEvent e) {
260  Collection<? extends Report> selectedReportsCollection = Utilities.actionsGlobalContext().lookupAll(Report.class);
261  String message = selectedReportsCollection.size() > 1
262  ? NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg", selectedReportsCollection.size())
263  : NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.single.msg");
264  String explanation = selectedReportsCollection.size() > 1
265  ? Bundle.DeleteReportAction_showConfirmDialog_multiple_explanation()
266  : Bundle.DeleteReportAction_showConfirmDialog_single_explanation();
267  Object[] jOptionPaneContent = {message, explanation};
268  if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null, jOptionPaneContent,
269  NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.title"),
270  JOptionPane.YES_NO_OPTION)) {
271  try {
272  Case.getCurrentCase().deleteReports(selectedReportsCollection);
273  } catch (TskCoreException | IllegalStateException ex) {
274  Logger.getLogger(DeleteReportAction.class.getName()).log(Level.SEVERE, "Error deleting reports", ex); // NON-NLS
275  MessageNotifyUtil.Message.error(Bundle.DeleteReportAction_showConfirmDialog_errorMsg());
276  }
277  }
278  }
279  }
280 
281  private final class OpenReportAction extends AbstractAction {
282 
283  private static final long serialVersionUID = 1L;
284 
285  private OpenReportAction() {
286  super(NbBundle.getMessage(OpenReportAction.class, "OpenReportAction.actionDisplayName"));
287  }
288 
289  @Override
290  public void actionPerformed(ActionEvent e) {
291  String reportPath = ReportNode.this.report.getPath();
292  String extension = "";
293  int extPosition = reportPath.lastIndexOf('.');
294 
295  if (extPosition != -1) {
296  extension = reportPath.substring(extPosition, reportPath.length()).toLowerCase();
297  }
298 
299  File file = new File(reportPath);
300  ExternalViewerAction.openFile("", extension, file);
301  }
302  }
303  }
304 }
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
Definition: Reports.java:108
static void openFile(String mimeType, String ext, File file)
void deleteReports(Collection<?extends Report > reports)
Definition: Case.java:1470
static final SimpleDateFormat dateFormatter
Definition: Reports.java:58
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:395

Copyright © 2012-2016 Basis Technology. Generated on: Fri Sep 29 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.