Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractedContentViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2014 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.keywordsearch;
20 
21 import java.awt.Component;
22 import java.awt.Cursor;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.logging.Level;
29 
30 import org.openide.util.NbBundle;
32 import org.openide.nodes.Node;
33 import org.openide.util.lookup.ServiceProvider;
43 
49 @ServiceProvider(service = DataContentViewer.class, position = 4)
50 public class ExtractedContentViewer implements DataContentViewer {
51 
52  private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName());
53  private ExtractedContentPanel panel;
54  private volatile Node currentNode = null;
55  private TextMarkup currentSource = null;
56  private final IsDirVisitor isDirVisitor = new IsDirVisitor();
57 
58 
60  logger.log(Level.INFO, "Created TextView instance: " + this); //NON-NLS
61  }
62 
63  @Override
64  public void setNode(final Node selectedNode) {
65  // to clear the viewer
66  if (selectedNode == null) {
67  currentNode = null;
68  resetComponent();
69  return;
70  }
71 
72  //TODO why setNode() is called twice for the same node sometimes (when selected in dir tree first)
73  //for now, do not update second time
74  if (selectedNode == currentNode) {
75  return;
76  }
77  else {
78  currentNode = selectedNode;
79  }
80 
81  /* Sources contain implementations that will markup the text
82  * in different ways. The original behavior for this was a source
83  * for the text markedup by SOLR and another that just displayed
84  * raw text.
85  */
86  final List<TextMarkup> sources = new ArrayList<TextMarkup>();
87 
88  // See if the node has any sources attached to it and add them to our
89  // internal list
90  sources.addAll(selectedNode.getLookup().lookupAll(TextMarkup.class));
91 
92  // Q: Can this be moved up? Is is possible to have "sources" when the
93  // node doesn't have a content object or the content size is 0?
94  Content content = selectedNode.getLookup().lookup(Content.class);
95  if (content == null || content.getSize() == 0) {
96  setPanel(sources);
97  return;
98  }
99 
100  long objectId = getDocumentId(selectedNode);
101  boolean isDir = content.accept(isDirVisitor);
102 
103  if (!isDir && solrHasContent(objectId) == false) {
104  setPanel(sources);
105  return;
106  }
107 
108  // make a new source for the raw content
109  TextMarkup rawSource = new RawTextMarkup(content, objectId);
110 
111  currentSource = rawSource;
112  sources.add(rawSource);
113 
114  //init pages
115  int currentPage = currentSource.getCurrentPage();
116  if (currentPage == 0 && currentSource.hasNextPage()) {
117  currentSource.nextPage();
118  }
119  updatePageControls();
120 
121  // first source will be the default displayed
122  setPanel(sources);
123  }
124 
125  private void scrollToCurrentHit() {
126  final TextMarkup source = panel.getSelectedSource();
127  if (source == null || !source.isSearchable()) {
128  return;
129  }
130 
131  panel.scrollToAnchor(source.getAnchorPrefix() + Integer.toString(source.currentItem()));
132 
133  }
134 
135  @Override
136  public String getTitle() {
137  return NbBundle.getMessage(this.getClass(), "ExtractedContentViewer.getTitle");
138  }
139 
140  @Override
141  public String getToolTip() {
142  return NbBundle.getMessage(this.getClass(), "ExtractedContentViewer.toolTip");
143  }
144 
145  @Override
146  public DataContentViewer createInstance() {
147  return new ExtractedContentViewer();
148  }
149 
150  @Override
151  public synchronized Component getComponent() {
152  if (panel == null) {
153  panel = new ExtractedContentPanel();
154  panel.addPrevMatchControlListener(new PrevFindActionListener());
155  panel.addNextMatchControlListener(new NextFindActionListener());
156  panel.addPrevPageControlListener(new PrevPageActionListener());
157  panel.addNextPageControlListener(new NextPageActionListener());
158  panel.addSourceComboControlListener(new SourceChangeActionListener());
159  }
160  return panel;
161  }
162 
163  @Override
164  public void resetComponent() {
165  setPanel(new ArrayList<TextMarkup>());
166  panel.resetDisplay();
167  currentNode = null;
168  currentSource = null;
169  }
170 
171  @Override
172  public boolean isSupported(Node node) {
173  if (node == null) {
174  return false;
175  }
176 
177  // see if the node has a MarkupSource object in it
178  // BC @@@ This seems to be added from the upper right search.
179  Collection<? extends TextMarkup> sources = node.getLookup().lookupAll(TextMarkup.class);
180  if (sources.isEmpty() == false) {
181  return true;
182  }
183 
184  // see if the node has a Highlight object in it.
185  // BC @@@ This seems to be added by BlackboardArtifactNode from the tree
186  if (node.getLookup().lookup(TextMarkupLookup.class) != null) {
187  return true;
188  }
189 
190  return solrHasContent(getDocumentId(node));
191  }
192 
193  @Override
194  public int isPreferred(Node node) {
195  BlackboardArtifact art = node.getLookup().lookup(BlackboardArtifact.class);
196 
197  if (art == null) {
198  return 4;
199  } else if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
200  return 6;
201  } else {
202  return 4;
203  }
204  }
205 
212  private void setPanel(List<TextMarkup> sources) {
213  if (panel != null) {
214  panel.setSources(sources);
215  }
216  }
217 
218 
219 
220  private class IsDirVisitor extends ContentVisitor.Default<Boolean> {
221 
222  @Override
223  protected Boolean defaultVisit(Content cntnt) {
224  return false;
225  }
226 
227  @Override
228  public Boolean visit(Directory d) {
229  return true;
230  }
231  }
232 
239  private boolean solrHasContent(Long objectId) {
240  final Server solrServer = KeywordSearch.getServer();
241 
242  try {
243  return solrServer.queryIsIndexed(objectId);
244  } catch (NoOpenCoreException ex) {
245  logger.log(Level.WARNING, "Couldn't determine whether content is supported.", ex); //NON-NLS
246  return false;
247  } catch (KeywordSearchModuleException ex) {
248  logger.log(Level.WARNING, "Couldn't determine whether content is supported.", ex); //NON-NLS
249  return false;
250  }
251  }
252 
260  private Long getDocumentId(Node node) {
261  HighlightedTextMarkup markup = node.getLookup().lookup(HighlightedTextMarkup.class);
262 
263  if (markup != null) {
264  return markup.getObjectId();
265  }
266 
267  Content content = node.getLookup().lookup(Content.class);
268 
269  if (content != null)
270  return content.getId();
271 
272  return 0L;
273  }
274 
275  private class NextFindActionListener implements ActionListener {
276 
277  @Override
278  public void actionPerformed(ActionEvent e) {
279  TextMarkup source = panel.getSelectedSource();
280  if (source == null) {
281  // reset
282  panel.updateControls(null);
283  return;
284  }
285  final boolean hasNextItem = source.hasNextItem();
286  final boolean hasNextPage = source.hasNextPage();
287  int indexVal = 0;
288  if (hasNextItem || hasNextPage) {
289  if (!hasNextItem) {
290  //flip the page
291  nextPage();
292  indexVal = source.currentItem();
293  } else {
294  indexVal = source.nextItem();
295  }
296 
297  //scroll
298  panel.scrollToAnchor(source.getAnchorPrefix() + Integer.toString(indexVal));
299 
300  //update display
301  panel.updateCurrentMatchDisplay(source.currentItem());
302  panel.updateTotaMatcheslDisplay(source.getNumberHits());
303 
304  //update controls if needed
305  if (!source.hasNextItem() && !source.hasNextPage()) {
306  panel.enableNextMatchControl(false);
307  }
308  if (source.hasPreviousItem() || source.hasPreviousPage()) {
309  panel.enablePrevMatchControl(true);
310  }
311  }
312  }
313  }
314 
315  private class PrevFindActionListener implements ActionListener {
316 
317  @Override
318  public void actionPerformed(ActionEvent e) {
319  TextMarkup source = panel.getSelectedSource();
320  final boolean hasPreviousItem = source.hasPreviousItem();
321  final boolean hasPreviousPage = source.hasPreviousPage();
322  int indexVal = 0;
323  if (hasPreviousItem || hasPreviousPage) {
324  if (!hasPreviousItem) {
325  //flip the page
326  previousPage();
327  indexVal = source.currentItem();
328  } else {
329  indexVal = source.previousItem();
330  }
331 
332  //scroll
333  panel.scrollToAnchor(source.getAnchorPrefix() + Integer.toString(indexVal));
334 
335  //update display
336  panel.updateCurrentMatchDisplay(source.currentItem());
337  panel.updateTotaMatcheslDisplay(source.getNumberHits());
338 
339  //update controls if needed
340  if (!source.hasPreviousItem() && !source.hasPreviousPage()) {
341  panel.enablePrevMatchControl(false);
342  }
343  if (source.hasNextItem() || source.hasNextPage()) {
344  panel.enableNextMatchControl(true);
345  }
346  }
347  }
348  }
349 
350  private class SourceChangeActionListener implements ActionListener {
351 
352  @Override
353  public void actionPerformed(ActionEvent e) {
354 
355  currentSource = panel.getSelectedSource();
356 
357  if (currentSource == null) {
358  //TODO might need to reset something
359  return;
360  }
361 
362  updatePageControls();
363  updateSearchControls();
364 
365  }
366  }
367 
368  private void updateSearchControls() {
369  panel.updateSearchControls(currentSource);
370  }
371 
372  private void updatePageControls() {
373  panel.updateControls(currentSource);
374  }
375 
376  private void nextPage() {
377  // we should never have gotten here -- reset
378  if (currentSource == null) {
379  panel.updateControls(null);
380  return;
381  }
382 
383  if (currentSource.hasNextPage()) {
384  currentSource.nextPage();
385 
386  //set new text
387  panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
388  panel.refreshCurrentMarkup();
389  panel.setCursor(null);
390 
391  //update display
392  panel.updateCurrentPageDisplay(currentSource.getCurrentPage());
393 
394  //scroll to current selection
396 
397  //update controls if needed
398  if (!currentSource.hasNextPage()) {
399  panel.enableNextPageControl(false);
400  }
401  if (currentSource.hasPreviousPage()) {
402  panel.enablePrevPageControl(true);
403  }
404 
405  updateSearchControls();
406  }
407  }
408 
409  private void previousPage() {
410  // reset, we should have never gotten here if null
411  if (currentSource == null) {
412  panel.updateControls(null);
413  return;
414  }
415 
416  if (currentSource.hasPreviousPage()) {
417  currentSource.previousPage();
418 
419  //set new text
420  panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
421  panel.refreshCurrentMarkup();
422  panel.setCursor(null);
423 
424  //update display
425  panel.updateCurrentPageDisplay(currentSource.getCurrentPage());
426 
427  //scroll to current selection
429 
430  //update controls if needed
431  if (!currentSource.hasPreviousPage()) {
432  panel.enablePrevPageControl(false);
433  }
434  if (currentSource.hasNextPage()) {
435  panel.enableNextPageControl(true);
436  }
437 
438  updateSearchControls();
439 
440 
441  }
442  }
443 
444  class NextPageActionListener implements ActionListener {
445 
446  @Override
447  public void actionPerformed(ActionEvent e) {
448  nextPage();
449  }
450  }
451 
452  private class PrevPageActionListener implements ActionListener {
453 
454  @Override
455  public void actionPerformed(ActionEvent e) {
456  previousPage();
457  }
458  }
459 }
boolean queryIsIndexed(long contentID)
Definition: Server.java:738
public< T > T accept(ContentVisitor< T > v)
static Logger getLogger(String name)
Definition: Logger.java:131

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.