19 package org.sleuthkit.autopsy.casemodule;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.List;
26 import javax.swing.JFileChooser;
27 import org.openide.util.NbBundle;
30 import java.util.logging.Level;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33 import javax.swing.AbstractListModel;
34 import javax.swing.JOptionPane;
41 @SuppressWarnings(
"PMD.SingularField")
42 final class LocalFilesPanel extends javax.swing.JPanel {
44 private static final long serialVersionUID = 1L;
46 private boolean enableNext =
false;
47 private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName());
48 private String displayName =
"";
49 private final LocalFilesModel listModel =
new LocalFilesModel();
59 private void customInit() {
60 localFileChooser.setMultiSelectionEnabled(
true);
61 errorLabel.setVisible(
false);
62 this.fileList.setModel(listModel);
64 this.displayNameLabel.setText(NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.displayNameLabel.text"));
72 @SuppressWarnings(
"unchecked")
74 private
void initComponents() {
75 java.awt.GridBagConstraints gridBagConstraints;
77 localFileChooser =
new javax.swing.JFileChooser();
78 selectButton =
new javax.swing.JButton();
79 deleteButon =
new javax.swing.JButton();
80 clearButton =
new javax.swing.JButton();
81 javax.swing.JScrollPane fileListScrollpane =
new javax.swing.JScrollPane();
82 fileList =
new javax.swing.JList<>();
83 javax.swing.JPanel displayNamePanel =
new javax.swing.JPanel();
84 changeNameButton =
new javax.swing.JButton();
85 displayNameLabel =
new javax.swing.JLabel();
86 javax.swing.JPanel padding =
new javax.swing.JPanel();
87 javax.swing.JLabel timeStampToIncludeLabel =
new javax.swing.JLabel();
88 modifiedTimeCheckBox =
new javax.swing.JCheckBox();
89 createTimeCheckBox =
new javax.swing.JCheckBox();
90 accessTimeCheckBox =
new javax.swing.JCheckBox();
91 javax.swing.JLabel timeStampNoteLabel =
new javax.swing.JLabel();
92 errorLabel =
new javax.swing.JLabel();
93 javax.swing.JPanel paddingBottom =
new javax.swing.JPanel();
95 localFileChooser.setApproveButtonText(
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.localFileChooser.approveButtonText"));
96 localFileChooser.setApproveButtonToolTipText(
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.localFileChooser.approveButtonToolTipText"));
97 localFileChooser.setDialogTitle(
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.localFileChooser.dialogTitle"));
98 localFileChooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_AND_DIRECTORIES);
100 setLayout(
new java.awt.GridBagLayout());
102 org.openide.awt.Mnemonics.setLocalizedText(selectButton,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.selectButton.text"));
103 selectButton.setToolTipText(
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.selectButton.toolTipText"));
104 selectButton.setActionCommand(
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.selectButton.actionCommand"));
105 selectButton.setMaximumSize(
new java.awt.Dimension(70, 23));
106 selectButton.setMinimumSize(
new java.awt.Dimension(70, 23));
107 selectButton.setPreferredSize(
new java.awt.Dimension(70, 23));
108 selectButton.addActionListener(
new java.awt.event.ActionListener() {
109 public void actionPerformed(java.awt.event.ActionEvent evt) {
110 selectButtonActionPerformed(evt);
113 gridBagConstraints =
new java.awt.GridBagConstraints();
114 gridBagConstraints.gridx = 1;
115 gridBagConstraints.gridy = 0;
116 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
117 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
118 gridBagConstraints.insets =
new java.awt.Insets(5, 5, 5, 5);
119 add(selectButton, gridBagConstraints);
121 org.openide.awt.Mnemonics.setLocalizedText(deleteButon,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.deleteButon.text"));
122 deleteButon.setMaximumSize(
new java.awt.Dimension(70, 23));
123 deleteButon.setMinimumSize(
new java.awt.Dimension(70, 23));
124 deleteButon.addActionListener(
new java.awt.event.ActionListener() {
125 public void actionPerformed(java.awt.event.ActionEvent evt) {
126 deleteButonActionPerformed(evt);
129 gridBagConstraints =
new java.awt.GridBagConstraints();
130 gridBagConstraints.gridx = 1;
131 gridBagConstraints.gridy = 1;
132 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
133 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
134 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 5, 5);
135 add(deleteButon, gridBagConstraints);
137 org.openide.awt.Mnemonics.setLocalizedText(clearButton,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.clearButton.text"));
138 clearButton.setToolTipText(
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.clearButton.toolTipText"));
139 clearButton.setMaximumSize(
new java.awt.Dimension(70, 23));
140 clearButton.setMinimumSize(
new java.awt.Dimension(70, 23));
141 clearButton.setPreferredSize(
new java.awt.Dimension(70, 23));
142 clearButton.addActionListener(
new java.awt.event.ActionListener() {
143 public void actionPerformed(java.awt.event.ActionEvent evt) {
144 clearButtonActionPerformed(evt);
147 gridBagConstraints =
new java.awt.GridBagConstraints();
148 gridBagConstraints.gridx = 1;
149 gridBagConstraints.gridy = 2;
150 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
151 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
152 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 5, 5);
153 add(clearButton, gridBagConstraints);
155 fileListScrollpane.setMaximumSize(
new java.awt.Dimension(32767, 100));
156 fileListScrollpane.setMinimumSize(
new java.awt.Dimension(100, 100));
157 fileListScrollpane.setPreferredSize(
new java.awt.Dimension(258, 100));
159 fileListScrollpane.setViewportView(fileList);
161 gridBagConstraints =
new java.awt.GridBagConstraints();
162 gridBagConstraints.gridx = 0;
163 gridBagConstraints.gridy = 0;
164 gridBagConstraints.gridheight = 3;
165 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
166 gridBagConstraints.weightx = 1.0;
167 gridBagConstraints.insets =
new java.awt.Insets(5, 5, 5, 0);
168 add(fileListScrollpane, gridBagConstraints);
170 displayNamePanel.setLayout(
new java.awt.GridBagLayout());
172 org.openide.awt.Mnemonics.setLocalizedText(changeNameButton,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.changeNameButton.text"));
173 changeNameButton.addActionListener(
new java.awt.event.ActionListener() {
174 public void actionPerformed(java.awt.event.ActionEvent evt) {
175 changeNameButtonActionPerformed(evt);
178 gridBagConstraints =
new java.awt.GridBagConstraints();
179 gridBagConstraints.gridx = 1;
180 gridBagConstraints.gridy = 0;
181 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
182 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
183 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 0, 0);
184 displayNamePanel.add(changeNameButton, gridBagConstraints);
186 org.openide.awt.Mnemonics.setLocalizedText(displayNameLabel,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.displayNameLabel.text"));
187 gridBagConstraints =
new java.awt.GridBagConstraints();
188 gridBagConstraints.gridx = 0;
189 gridBagConstraints.gridy = 0;
190 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
191 displayNamePanel.add(displayNameLabel, gridBagConstraints);
193 padding.setMinimumSize(
new java.awt.Dimension(0, 0));
194 padding.setPreferredSize(
new java.awt.Dimension(0, 0));
196 javax.swing.GroupLayout paddingLayout =
new javax.swing.GroupLayout(padding);
197 padding.setLayout(paddingLayout);
198 paddingLayout.setHorizontalGroup(
199 paddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
200 .addGap(0, 0, Short.MAX_VALUE)
202 paddingLayout.setVerticalGroup(
203 paddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
204 .addGap(0, 0, Short.MAX_VALUE)
207 gridBagConstraints =
new java.awt.GridBagConstraints();
208 gridBagConstraints.gridx = 2;
209 gridBagConstraints.gridy = 0;
210 gridBagConstraints.weightx = 1.0;
211 displayNamePanel.add(padding, gridBagConstraints);
213 gridBagConstraints =
new java.awt.GridBagConstraints();
214 gridBagConstraints.gridx = 0;
215 gridBagConstraints.gridy = 3;
216 gridBagConstraints.gridwidth = 2;
217 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
218 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
219 gridBagConstraints.weightx = 1.0;
220 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 5, 5);
221 add(displayNamePanel, gridBagConstraints);
223 org.openide.awt.Mnemonics.setLocalizedText(timeStampToIncludeLabel,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.timeStampToIncludeLabel.text"));
224 gridBagConstraints =
new java.awt.GridBagConstraints();
225 gridBagConstraints.gridx = 0;
226 gridBagConstraints.gridy = 4;
227 gridBagConstraints.gridwidth = 2;
228 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
229 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 5, 5);
230 add(timeStampToIncludeLabel, gridBagConstraints);
232 org.openide.awt.Mnemonics.setLocalizedText(modifiedTimeCheckBox,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.modifiedTimeCheckBox.text"));
233 gridBagConstraints =
new java.awt.GridBagConstraints();
234 gridBagConstraints.gridx = 0;
235 gridBagConstraints.gridy = 5;
236 gridBagConstraints.gridwidth = 2;
237 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
238 gridBagConstraints.insets =
new java.awt.Insets(0, 15, 5, 5);
239 add(modifiedTimeCheckBox, gridBagConstraints);
241 org.openide.awt.Mnemonics.setLocalizedText(createTimeCheckBox,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.createTimeCheckBox.text"));
242 gridBagConstraints =
new java.awt.GridBagConstraints();
243 gridBagConstraints.gridx = 0;
244 gridBagConstraints.gridy = 6;
245 gridBagConstraints.gridwidth = 2;
246 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
247 gridBagConstraints.insets =
new java.awt.Insets(0, 15, 5, 5);
248 add(createTimeCheckBox, gridBagConstraints);
250 org.openide.awt.Mnemonics.setLocalizedText(accessTimeCheckBox,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.accessTimeCheckBox.text"));
251 gridBagConstraints =
new java.awt.GridBagConstraints();
252 gridBagConstraints.gridx = 0;
253 gridBagConstraints.gridy = 7;
254 gridBagConstraints.gridwidth = 2;
255 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
256 gridBagConstraints.insets =
new java.awt.Insets(0, 15, 5, 5);
257 add(accessTimeCheckBox, gridBagConstraints);
259 org.openide.awt.Mnemonics.setLocalizedText(timeStampNoteLabel,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.timeStampNoteLabel.text"));
260 gridBagConstraints =
new java.awt.GridBagConstraints();
261 gridBagConstraints.gridx = 0;
262 gridBagConstraints.gridy = 8;
263 gridBagConstraints.gridwidth = 2;
264 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
265 gridBagConstraints.insets =
new java.awt.Insets(10, 5, 5, 5);
266 add(timeStampNoteLabel, gridBagConstraints);
268 errorLabel.setForeground(
new java.awt.Color(255, 0, 0));
269 org.openide.awt.Mnemonics.setLocalizedText(errorLabel,
org.openide.util.NbBundle.getMessage(LocalFilesPanel.class,
"LocalFilesPanel.errorLabel.text"));
270 gridBagConstraints =
new java.awt.GridBagConstraints();
271 gridBagConstraints.gridx = 0;
272 gridBagConstraints.gridy = 9;
273 gridBagConstraints.gridwidth = 2;
274 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
275 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
276 gridBagConstraints.weightx = 1.0;
277 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 5, 5);
278 add(errorLabel, gridBagConstraints);
280 paddingBottom.setMinimumSize(
new java.awt.Dimension(0, 0));
282 javax.swing.GroupLayout paddingBottomLayout =
new javax.swing.GroupLayout(paddingBottom);
283 paddingBottom.setLayout(paddingBottomLayout);
284 paddingBottomLayout.setHorizontalGroup(
285 paddingBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
286 .addGap(0, 0, Short.MAX_VALUE)
288 paddingBottomLayout.setVerticalGroup(
289 paddingBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
290 .addGap(0, 0, Short.MAX_VALUE)
293 gridBagConstraints =
new java.awt.GridBagConstraints();
294 gridBagConstraints.gridx = 0;
295 gridBagConstraints.gridy = 10;
296 gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
297 gridBagConstraints.weighty = 1.0;
298 add(paddingBottom, gridBagConstraints);
301 private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {
302 int returnVal = localFileChooser.showOpenDialog(
this);
304 if (returnVal == JFileChooser.APPROVE_OPTION) {
305 File[] files = localFileChooser.getSelectedFiles();
306 this.listModel.add(files);
309 enableNext = !this.listModel.getFiles().isEmpty();
312 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(),
false,
true);
313 }
catch (Exception e) {
314 logger.log(Level.SEVERE,
"LocalFilesPanel listener threw exception", e);
315 MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.moduleErr"),
316 NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.moduleErr.msg"),
317 MessageNotifyUtil.MessageType.ERROR);
321 private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {
325 private void changeNameButtonActionPerformed(java.awt.event.ActionEvent evt) {
326 final String selectedDisplayName = JOptionPane.showInputDialog(
"New Display Name: ");
327 if (selectedDisplayName != null && !selectedDisplayName.isEmpty()) {
328 this.displayName = selectedDisplayName;
329 this.displayNameLabel.setText(
"Display Name: " + this.displayName);
333 private void deleteButonActionPerformed(java.awt.event.ActionEvent evt) {
334 this.listModel.remove(this.fileList.getSelectedIndices());
335 this.fileList.clearSelection();
337 enableNext = !this.listModel.getFiles().isEmpty();
340 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(),
false,
true);
341 }
catch (Exception e) {
342 logger.log(Level.SEVERE,
"LocalFilesPanel listener threw exception", e);
343 MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.moduleErr"),
344 NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.moduleErr.msg"),
345 MessageNotifyUtil.MessageType.ERROR);
353 this.listModel.clear();
355 errorLabel.setVisible(
false);
357 this.displayNameLabel.setText(NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.displayNameLabel.text"));
359 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(),
false,
true);
360 }
catch (Exception e) {
361 logger.log(Level.SEVERE,
"LocalFilesPanel listener threw exception", e);
362 MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.moduleErr"),
363 NbBundle.getMessage(
this.getClass(),
"LocalFilesPanel.moduleErr.msg"),
364 MessageNotifyUtil.MessageType.ERROR);
374 List<String> getContentPaths() {
375 return this.listModel.getFiles().stream()
376 .map(File::getAbsolutePath)
377 .collect(Collectors.toList());
385 Boolean getCreateTimestamps() {
386 return createTimeCheckBox.isSelected();
394 Boolean getModifiedTimestamps() {
395 return modifiedTimeCheckBox.isSelected();
403 Boolean getAccessTimestamps() {
404 return accessTimeCheckBox.isSelected();
413 boolean validatePanel() {
415 warnIfPathIsInvalid(getContentPaths());
426 "LocalFilesPanel.pathValidation.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive",
427 "LocalFilesPanel.pathValidation.getOpenCase=WARNING: Exception while gettting open case."
429 private void warnIfPathIsInvalid(
final List<String> pathsList) {
430 errorLabel.setVisible(
false);
433 final Case.CaseType currentCaseType = Case.getCurrentCaseThrows().getCaseType();
435 for (String currentPath : pathsList) {
436 if (!PathValidator.isValidForCaseType(currentPath, currentCaseType)) {
437 errorLabel.setVisible(
true);
438 errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_dataSourceOnCDriveError());
442 }
catch (NoCurrentCaseException ex) {
443 errorLabel.setVisible(
true);
444 errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_getOpenCase());
453 String getFileSetName() {
454 return this.displayName;
471 return file == null ?
"" : file.getAbsolutePath();
487 private List<File> items = Collections.emptyList();
496 File f = items.get(index);
505 void add(File... files) {
506 items = Stream.concat(items.stream(), Stream.of(files))
507 .sorted(Comparator.comparing(f -> f.getAbsolutePath().toLowerCase()))
509 .collect(Collectors.toList());
511 this.fireContentsChanged(
this, 0, items.size() - 1);
518 void remove(
int[] selectedIndices) {
519 if (selectedIndices != null) {
520 Iterable<Integer> sortedIndices = (Iterable<Integer>) () -> Arrays.stream(selectedIndices)
523 .sorted((a,b) -> Integer.compare(b, a))
526 int prevIdxMax = items.size() - 1;
527 for (Integer idx: sortedIndices) {
528 if (idx != null && idx >= 0 && idx < this.items.size()) {
529 this.items.remove((
int) idx);
533 this.fireContentsChanged(
this, 0, prevIdxMax);
540 List<File> getFiles() {
549 this.fireContentsChanged(
this, 0, 0);
555 private javax.swing.JCheckBox accessTimeCheckBox;
556 private javax.swing.JButton changeNameButton;
557 private javax.swing.JButton clearButton;
558 private javax.swing.JCheckBox createTimeCheckBox;
559 private javax.swing.JButton deleteButon;
560 private javax.swing.JLabel displayNameLabel;
561 private javax.swing.JLabel errorLabel;
562 private javax.swing.JList<FileRecord> fileList;
563 private javax.swing.JFileChooser localFileChooser;
564 private javax.swing.JCheckBox modifiedTimeCheckBox;
565 private javax.swing.JButton selectButton;
FileRecord getElementAt(int index)