Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExcelExportAction.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2021 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.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.io.File;
24 import java.io.IOException;
25 import java.nio.file.Paths;
26 import java.text.DateFormat;
27 import java.text.SimpleDateFormat;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.Date;
31 import java.util.List;
32 import java.util.concurrent.CancellationException;
33 import java.util.concurrent.ExecutionException;
34 import java.util.function.Consumer;
35 import java.util.logging.Level;
36 import javax.swing.JOptionPane;
37 import javax.swing.SwingUtilities;
38 import javax.swing.SwingWorker;
39 import org.openide.util.NbBundle;
40 import org.openide.util.NbBundle.Messages;
41 import org.openide.windows.WindowManager;
51 import org.sleuthkit.datamodel.DataSource;
52 import org.sleuthkit.datamodel.TskCoreException;
53 
57 @Messages({
58  "ExcelExportAction_moduleName=Data Source Summary",})
59 class ExcelExportAction implements Consumer<DataSource> {
60 
61  private static final Logger logger = Logger.getLogger(ExcelExportAction.class.getName());
62 
66  interface ExportableTab {
67 
73  String getTabTitle();
74 
81  List<ExcelSheetExport> getExcelExports(DataSource dataSource);
82  }
83 
84  private final ExcelExport excelExport = ExcelExport.getInstance();
85  private final List<? extends ExportableTab> tabExports;
86 
92  ExcelExportAction(List<? extends ExportableTab> tabExports) {
93  this.tabExports = Collections.unmodifiableList(new ArrayList<>(tabExports));
94  }
95 
102  @Override
103  public void accept(DataSource ds) {
104  if (ds == null) {
105  return;
106  }
107 
108  File outputLoc = getXLSXPath(ds.getName());
109  if (outputLoc == null) {
110  return;
111  }
112 
113  runXLSXExport(ds, outputLoc);
114  }
115 
123  @NbBundle.Messages({
124  "ExcelExportAction_getXLSXPath_directory=DataSourceSummary",})
125  private File getXLSXPath(String dataSourceName) {
126  // set initial path to reports directory with filename that is
127  // a combination of the data source name and time stamp
128  DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
129  String fileName = String.format("%s-%s.xlsx", dataSourceName == null ? "" : FileUtil.escapeFileName(dataSourceName), dateFormat.format(new Date()));
130  try {
131  String reportsDir = Case.getCurrentCaseThrows().getReportDirectory();
132  File reportsDirFile = Paths.get(reportsDir, Bundle.ExcelExportAction_getXLSXPath_directory()).toFile();
133  if (!reportsDirFile.exists()) {
134  reportsDirFile.mkdirs();
135  }
136 
137  return Paths.get(reportsDirFile.getAbsolutePath(), fileName).toFile();
138  } catch (NoCurrentCaseException ex) {
139  logger.log(Level.WARNING, "Unable to find reports directory.", ex);
140  }
141 
142  return null;
143  }
144 
148  private class CancelExportListener implements ActionListener {
149 
150  private SwingWorker<Boolean, Void> worker = null;
151 
152  @Override
153  public void actionPerformed(ActionEvent e) {
154  if (worker != null && !worker.isCancelled() && !worker.isDone()) {
155  worker.cancel(true);
156  }
157  }
158 
164  SwingWorker<Boolean, Void> getWorker() {
165  return worker;
166  }
167 
173  void setWorker(SwingWorker<Boolean, Void> worker) {
174  this.worker = worker;
175  }
176  }
177 
185  @NbBundle.Messages({
186  "# {0} - dataSource",
187  "ExcelExportAction_runXLSXExport_progressTitle=Exporting {0} to XLSX",
188  "ExcelExportAction_runXLSXExport_progressCancelTitle=Cancel",
189  "ExcelExportAction_runXLSXExport_progressCancelActionTitle=Cancelling...",
190  "ExcelExportAction_runXLSXExport_errorTitle=Error While Exporting",
191  "ExcelExportAction_runXLSXExport_errorMessage=There was an error while exporting.",
192  })
193  private void runXLSXExport(DataSource dataSource, File path) {
194 
195  CancelExportListener cancelButtonListener = new CancelExportListener();
196 
197  ProgressIndicator progressIndicator = new ModalDialogProgressIndicator(
198  WindowManager.getDefault().getMainWindow(),
199  Bundle.ExcelExportAction_runXLSXExport_progressTitle(dataSource.getName()),
200  new String[]{Bundle.ExcelExportAction_runXLSXExport_progressCancelTitle()},
201  Bundle.ExcelExportAction_runXLSXExport_progressCancelTitle(),
202  cancelButtonListener
203  );
204 
205  SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
206  @Override
207  protected Boolean doInBackground() throws Exception {
208  exportToXLSX(progressIndicator, dataSource, path);
209  return true;
210  }
211 
212  @Override
213  protected void done() {
214  try {
215  get();
216  } catch (ExecutionException ex) {
217  logger.log(Level.WARNING, "Error while trying to export data source summary to xlsx.", ex);
218  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
219  Bundle.ExcelExportAction_runXLSXExport_errorMessage(),
220  Bundle.ExcelExportAction_runXLSXExport_errorTitle(),
221  JOptionPane.ERROR_MESSAGE);
222  } catch (InterruptedException | CancellationException ex) {
223  // no op on cancellation
224  } finally {
225  progressIndicator.finish();
226  }
227  }
228  };
229 
230  cancelButtonListener.setWorker(worker);
231  worker.execute();
232  }
233 
244  @NbBundle.Messages({
245  "ExcelExportAction_exportToXLSX_beginExport=Beginning Export...",
246  "# {0} - tabName",
247  "ExcelExportAction_exportToXLSX_gatheringTabData=Fetching Data for {0} Tab...",
248  "ExcelExportAction_exportToXLSX_writingToFile=Writing to File...",})
249 
250  private void exportToXLSX(ProgressIndicator progressIndicator, DataSource dataSource, File path)
251  throws InterruptedException, IOException, ExcelExport.ExcelExportException {
252 
253  int exportWeight = 3;
254  int totalWeight = tabExports.size() + exportWeight;
255  progressIndicator.start(Bundle.ExcelExportAction_exportToXLSX_beginExport(), totalWeight);
256  List<ExcelExport.ExcelSheetExport> sheetExports = new ArrayList<>();
257  for (int i = 0; i < tabExports.size(); i++) {
258  if (Thread.interrupted()) {
259  throw new InterruptedException("Export has been cancelled.");
260  }
261 
262  ExportableTab tab = tabExports.get(i);
263  progressIndicator.progress(Bundle.ExcelExportAction_exportToXLSX_gatheringTabData(tab == null ? "" : tab.getTabTitle()), i);
264 
265  List<ExcelExport.ExcelSheetExport> exports = tab.getExcelExports(dataSource);
266  if (exports != null) {
267  sheetExports.addAll(exports);
268  }
269  }
270 
271  if (Thread.interrupted()) {
272  throw new InterruptedException("Export has been cancelled.");
273  }
274 
275  progressIndicator.progress(Bundle.ExcelExportAction_exportToXLSX_writingToFile(), tabExports.size());
276  excelExport.writeExcel(sheetExports, path);
277 
278  progressIndicator.finish();
279 
280  try {
281  // add to reports
282  Case curCase = Case.getCurrentCaseThrows();
283  curCase.addReport(path.getParent(),
284  Bundle.ExcelExportAction_moduleName(),
285  path.getName(),
286  dataSource);
287 
288  // and show finished dialog
289  SwingUtilities.invokeLater(() -> {
290  ExcelExportDialog dialog = new ExcelExportDialog(WindowManager.getDefault().getMainWindow(), path);
291  dialog.setResizable(false);
292  dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
293  dialog.setVisible(true);
294  dialog.toFront();
295  });
296 
297  } catch (NoCurrentCaseException | TskCoreException ex) {
298  logger.log(Level.WARNING, "There was an error attaching report to case.", ex);
299  }
300  }
301 }

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.