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

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