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

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.