Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataContentViewerArtifact.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2013 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 
20 package org.sleuthkit.autopsy.corecomponents;
21 
22 import java.awt.*;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.concurrent.ExecutionException;
28 import java.util.logging.Level;
29 import javax.swing.JMenuItem;
30 import javax.swing.JTextPane;
31 import javax.swing.SwingWorker;
32 import org.openide.nodes.Node;
33 import org.openide.util.Lookup;
34 import org.openide.util.NbBundle;
35 import org.openide.util.lookup.ServiceProvider;
48 
53 @ServiceProvider(service = DataContentViewer.class, position=3)
54 public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer{
55 
56  private final static Logger logger = Logger.getLogger(DataContentViewerArtifact.class.getName());
57  private final static String WAIT_TEXT = NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.waitText");
58  private final static String ERROR_TEXT = NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.errorText");
59  private Node currentNode; // @@@ Remove this when the redundant setNode() calls problem is fixed.
60  private int currentPage = 1;
61  private final Object lock = new Object();
62  private List<ArtifactStringContent> artifactContentStrings; // Accessed by multiple threads, use getArtifactContentStrings() and setArtifactContentStrings()
63  SwingWorker<ViewUpdate, Void> currentTask; // Accessed by multiple threads, use startNewTask()
64 
66  initComponents();
67  customizeComponents();
68  resetComponents();
69  }
70 
76  @SuppressWarnings("unchecked")
77  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
78  private void initComponents() {
79 
80  rightClickMenu = new javax.swing.JPopupMenu();
81  copyMenuItem = new javax.swing.JMenuItem();
82  selectAllMenuItem = new javax.swing.JMenuItem();
83  jPanel1 = new javax.swing.JPanel();
84  jScrollPane1 = new javax.swing.JScrollPane();
85  outputViewPane = new JTextPane(){
86  public boolean getScrollableTracksViewportWidth() {
87  return (getSize().width < 400);
88  }};
89  totalPageLabel = new javax.swing.JLabel();
90  ofLabel = new javax.swing.JLabel();
91  currentPageLabel = new javax.swing.JLabel();
92  pageLabel = new javax.swing.JLabel();
93  nextPageButton = new javax.swing.JButton();
94  pageLabel2 = new javax.swing.JLabel();
95  prevPageButton = new javax.swing.JButton();
96 
97  copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.copyMenuItem.text")); // NOI18N
98  rightClickMenu.add(copyMenuItem);
99 
100  selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.selectAllMenuItem.text")); // NOI18N
101  rightClickMenu.add(selectAllMenuItem);
102 
103  setPreferredSize(new java.awt.Dimension(622, 424));
104 
105  jPanel1.setPreferredSize(new java.awt.Dimension(622, 424));
106 
107  outputViewPane.setEditable(false);
108  outputViewPane.setPreferredSize(new java.awt.Dimension(700, 400));
109  jScrollPane1.setViewportView(outputViewPane);
110 
111  totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.totalPageLabel.text")); // NOI18N
112 
113  ofLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.ofLabel.text")); // NOI18N
114 
115  currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.currentPageLabel.text")); // NOI18N
116  currentPageLabel.setMaximumSize(new java.awt.Dimension(18, 14));
117  currentPageLabel.setMinimumSize(new java.awt.Dimension(18, 14));
118  currentPageLabel.setPreferredSize(new java.awt.Dimension(18, 14));
119 
120  pageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel.text")); // NOI18N
121  pageLabel.setMaximumSize(new java.awt.Dimension(33, 14));
122  pageLabel.setMinimumSize(new java.awt.Dimension(33, 14));
123  pageLabel.setPreferredSize(new java.awt.Dimension(33, 14));
124 
125  nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N NON-NLS
126  nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.nextPageButton.text")); // NOI18N
127  nextPageButton.setBorderPainted(false);
128  nextPageButton.setContentAreaFilled(false);
129  nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N NON-NLS
130  nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
131  nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
132  nextPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N NON-NLS
133  nextPageButton.addActionListener(new java.awt.event.ActionListener() {
134  public void actionPerformed(java.awt.event.ActionEvent evt) {
135  nextPageButtonActionPerformed(evt);
136  }
137  });
138 
139  pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel2.text")); // NOI18N
140  pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14));
141  pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14));
142  pageLabel2.setPreferredSize(new java.awt.Dimension(29, 14));
143 
144  prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N NON-NLS
145  prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.prevPageButton.text")); // NOI18N
146  prevPageButton.setBorderPainted(false);
147  prevPageButton.setContentAreaFilled(false);
148  prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N NON-NLS
149  prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
150  prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23));
151  prevPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N NON-NLS
152  prevPageButton.addActionListener(new java.awt.event.ActionListener() {
153  public void actionPerformed(java.awt.event.ActionEvent evt) {
154  prevPageButtonActionPerformed(evt);
155  }
156  });
157 
158  javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
159  jPanel1.setLayout(jPanel1Layout);
160  jPanel1Layout.setHorizontalGroup(
161  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
162  .addGroup(jPanel1Layout.createSequentialGroup()
163  .addContainerGap()
164  .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
165  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
166  .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
167  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
168  .addComponent(ofLabel)
169  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
170  .addComponent(totalPageLabel)
171  .addGap(41, 41, 41)
172  .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE)
173  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
174  .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
175  .addGap(0, 0, 0)
176  .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
177  .addContainerGap(366, Short.MAX_VALUE))
178  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE)
179  );
180  jPanel1Layout.setVerticalGroup(
181  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
182  .addGroup(jPanel1Layout.createSequentialGroup()
183  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
184  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
185  .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
186  .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
187  .addComponent(ofLabel)
188  .addComponent(totalPageLabel))
189  .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
190  .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
191  .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
192  .addGap(0, 0, 0)
193  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE))
194  );
195 
196  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
197  this.setLayout(layout);
198  layout.setHorizontalGroup(
199  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
200  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
201  );
202  layout.setVerticalGroup(
203  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
204  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
205  );
206  }// </editor-fold>//GEN-END:initComponents
207 
208  private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
209  currentPage = currentPage + 1;
210  currentPageLabel.setText(Integer.toString(currentPage));
211  startNewTask(new SelectedArtifactChangedTask(currentPage));
212  }//GEN-LAST:event_nextPageButtonActionPerformed
213 
214  private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
215  currentPage = currentPage - 1;
216  currentPageLabel.setText(Integer.toString(currentPage));
217  startNewTask(new SelectedArtifactChangedTask(currentPage));
218  }//GEN-LAST:event_prevPageButtonActionPerformed
219 
220  // Variables declaration - do not modify//GEN-BEGIN:variables
221  private javax.swing.JMenuItem copyMenuItem;
222  private javax.swing.JLabel currentPageLabel;
223  private javax.swing.JPanel jPanel1;
224  private javax.swing.JScrollPane jScrollPane1;
225  private javax.swing.JButton nextPageButton;
226  private javax.swing.JLabel ofLabel;
227  private javax.swing.JTextPane outputViewPane;
228  private javax.swing.JLabel pageLabel;
229  private javax.swing.JLabel pageLabel2;
230  private javax.swing.JButton prevPageButton;
231  private javax.swing.JPopupMenu rightClickMenu;
232  private javax.swing.JMenuItem selectAllMenuItem;
233  private javax.swing.JLabel totalPageLabel;
234  // End of variables declaration//GEN-END:variables
235 
236  private void customizeComponents(){
237  outputViewPane.setComponentPopupMenu(rightClickMenu);
238  ActionListener actList = new ActionListener(){
239  @Override
240  public void actionPerformed(ActionEvent e){
241  JMenuItem jmi = (JMenuItem) e.getSource();
242  if(jmi.equals(copyMenuItem))
243  outputViewPane.copy();
244  else if(jmi.equals(selectAllMenuItem))
245  outputViewPane.selectAll();
246  }
247  };
248  copyMenuItem.addActionListener(actList);
249  selectAllMenuItem.addActionListener(actList);
250 
251  Utilities.configureTextPaneAsHtml(outputViewPane);
252  }
253 
257  private void resetComponents() {
258  currentPage = 1;
259  currentPageLabel.setText("");
260  totalPageLabel.setText("");
261  outputViewPane.setText("");
262  prevPageButton.setEnabled(false);
263  nextPageButton.setEnabled(false);
264  currentNode = null;
265  }
266 
267  @Override
268  public void setNode(Node selectedNode) {
269  if (currentNode == selectedNode) {
270  return;
271  }
272  currentNode = selectedNode;
273 
274  // Make sure there is a node. Null might be passed to reset the viewer.
275  if (selectedNode == null) {
276  return;
277  }
278 
279  // Make sure the node is of the correct type.
280  Lookup lookup = selectedNode.getLookup();
281  Content content = lookup.lookup(Content.class);
282  if (content == null) {
283  return;
284  }
285 
286  startNewTask(new SelectedNodeChangedTask(selectedNode));
287  }
288 
289  @Override
290  public String getTitle() {
291  return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.title");
292  }
293 
294  @Override
295  public String getToolTip() {
296  return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.toolTip");
297  }
298 
299  @Override
300  public DataContentViewer createInstance() {
301  return new DataContentViewerArtifact();
302  }
303 
304  @Override
305  public Component getComponent() {
306  return this;
307  }
308 
309  @Override
310  public void resetComponent() {
311  resetComponents();
312  }
313 
314  @Override
315  public boolean isSupported(Node node) {
316  if (node == null) {
317  return false;
318  }
319 
320  Content content = node.getLookup().lookup(Content.class);
321  if(content != null) {
322  try {
323  return content.getAllArtifactsCount() > 0;
324  }
325  catch (TskException ex) {
326  logger.log(Level.WARNING, "Couldn't get count of BlackboardArtifacts for content", ex); //NON-NLS
327  }
328  }
329  return false;
330  }
331 
332  @Override
333  public int isPreferred(Node node) {
334  BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
335  // low priority if node doesn't have an artifact (meaning it was found from normal directory
336  // browsing, or if the artifact is something that means the user really wants to see the original
337  // file and not more details about the artifact
338  if ((artifact == null) ||
339  (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) ||
340  (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())) {
341  return 3;
342  }
343  else {
344  return 5;
345  }
346  }
347 
351  private class ViewUpdate {
352  int numberOfPages;
353  int currentPage;
354  String text;
355 
356  ViewUpdate(int numberOfPages, int currentPage, String text) {
357  this.currentPage = currentPage;
358  this.numberOfPages = numberOfPages;
359  this.text = text;
360  }
361  }
362 
367  private void updateView(ViewUpdate viewUpdate) {
368  this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
369 
370  nextPageButton.setEnabled(viewUpdate.currentPage < viewUpdate.numberOfPages);
371  prevPageButton.setEnabled(viewUpdate.currentPage > 1);
372  currentPage = viewUpdate.currentPage;
373  totalPageLabel.setText(Integer.toString(viewUpdate.numberOfPages));
374  currentPageLabel.setText(Integer.toString(currentPage));
375 
376  // @@@ This can take a long time. Perhaps a faster HTML renderer can be found.
377  // Note that the rendering appears to be done on a background thread, since the
378  // wait cursor reset below happens before the new text hits the JTextPane. On the
379  // other hand, the UI is unresponsive...
380  outputViewPane.setText(viewUpdate.text);
381  outputViewPane.moveCaretPosition(0);
382 
383  this.setCursor(null);
384  }
385 
390  private synchronized void startNewTask(SwingWorker<ViewUpdate, Void> task) {
391  outputViewPane.setText(WAIT_TEXT);
392  outputViewPane.moveCaretPosition(0);
393 
394  // The output of the previous task is no longer relevant.
395  if (currentTask != null) {
396  // This call sets a cancellation flag. It does not terminate the background thread running the task.
397  // The task must check the cancellation flag and react appropriately.
398  currentTask.cancel(false);
399  }
400 
401  // Start the new task.
402  currentTask = task;
403  currentTask.execute();
404  }
405 
410  private void setArtifactContentStrings(List<ArtifactStringContent> artifactStrings) {
411  synchronized (lock) {
412  this.artifactContentStrings = artifactStrings;
413  }
414  }
415 
420  private List<ArtifactStringContent> getArtifactContentStrings() {
421  synchronized (lock) {
422  return artifactContentStrings;
423  }
424  }
425 
430  private class SelectedNodeChangedTask extends SwingWorker<ViewUpdate, Void> {
431  private final Node selectedNode;
432 
433  SelectedNodeChangedTask(Node selectedNode) {
434  this.selectedNode = selectedNode;
435  }
436 
437  @Override
438  protected ViewUpdate doInBackground() {
439  // Get the lookup for the node for access to its underlying content and
440  // blackboard artifact, if any.
441  Lookup lookup = selectedNode.getLookup();
442 
443  // Get the content.
444  Content content = lookup.lookup(Content.class);
445  if (content == null) {
446  return new ViewUpdate(getArtifactContentStrings().size(), currentPage, ERROR_TEXT);
447  }
448 
449  // Get all of the blackboard artifacts associated with the content. These are what this
450  // viewer displays.
451  ArrayList<BlackboardArtifact> artifacts;
452  try {
453  artifacts = content.getAllArtifacts();
454  }
455  catch (TskException ex) {
456  logger.log(Level.WARNING, "Couldn't get artifacts", ex); //NON-NLS
457  return new ViewUpdate(getArtifactContentStrings().size(), currentPage, ERROR_TEXT);
458  }
459 
460  if (isCancelled()) {
461  return null;
462  }
463 
464  // Build the new artifact strings cache.
465  ArrayList<ArtifactStringContent> artifactStrings = new ArrayList<>();
466  for (BlackboardArtifact artifact : artifacts) {
467  artifactStrings.add(new ArtifactStringContent(artifact));
468  }
469 
470  // If the node has an underlying blackboard artifact, show it. If not,
471  // show the first artifact.
472  int index = 0;
473  BlackboardArtifact artifact = lookup.lookup(BlackboardArtifact.class);
474  if (artifact != null) {
475  index = artifacts.indexOf(artifact);
476  if (index == -1) {
477  index = 0;
478  } else {
479  // if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead
480  try {
481  for (BlackboardAttribute attr : artifact.getAttributes()) {
482  if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
483  long assocArtifactId = attr.getValueLong();
484  int assocArtifactIndex = -1;
485  for (BlackboardArtifact art: artifacts) {
486  if (assocArtifactId == art.getArtifactID()) {
487  assocArtifactIndex = artifacts.indexOf(art);
488  break;
489  }
490  }
491  if (assocArtifactIndex >= 0) {
492  index = assocArtifactIndex;
493  }
494  break;
495  }
496  }
497  }
498  catch (TskCoreException ex) {
499  logger.log(Level.WARNING, "Couldn't get associated artifact to display in Content Viewer.", ex); //NON-NLS
500  }
501  }
502 
503  }
504 
505  if (isCancelled()) {
506  return null;
507  }
508 
509  // Add one to the index of the artifact string for the corresponding page index. Note that the getString() method
510  // of ArtifactStringContent does a lazy fetch of the attributes of the correspoding artifact and represents them as
511  // HTML.
512  ViewUpdate viewUpdate = new ViewUpdate(artifactStrings.size(), index + 1, artifactStrings.get(index).getString());
513 
514  // It may take a considerable amount of time to fetch the attributes of the selected artifact and render them
515  // as HTML, so check for cancellation.
516  if (isCancelled()) {
517  return null;
518  }
519 
520  // Update the artifact strings cache.
521  setArtifactContentStrings(artifactStrings);
522 
523  return viewUpdate;
524  }
525 
526  @Override
527  protected void done() {
528  if (!isCancelled()) {
529  try {
530  ViewUpdate viewUpdate = get();
531  if (viewUpdate != null) {
532  updateView(viewUpdate);
533  }
534  }
535  catch (InterruptedException | ExecutionException ex) {
536  logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS
537  }
538  }
539  }
540  }
541 
546  private class SelectedArtifactChangedTask extends SwingWorker<ViewUpdate, Void> {
547  private final int pageIndex;
548 
549  SelectedArtifactChangedTask(final int pageIndex) {
550  this.pageIndex = pageIndex;
551  }
552 
553  @Override
555  // Get the artifact string to display from the cache. Note that one must be subtracted from the
556  // page index to get the corresponding artifact string index.
557  List<ArtifactStringContent> artifactStrings = getArtifactContentStrings();
558  ArtifactStringContent artifactStringContent = artifactStrings.get(pageIndex - 1);
559 
560  // The getString() method of ArtifactStringContent does a lazy fetch of the attributes of the
561  // correspoding artifact and represents them as HTML.
562  String artifactString = artifactStringContent.getString();
563 
564  // It may take a considerable amount of time to fetch the attributes of the selected artifact and render them
565  // as HTML, so check for cancellation.
566  if (isCancelled()) {
567  return null;
568  }
569 
570  return new ViewUpdate(artifactStrings.size(), pageIndex, artifactString);
571  }
572 
573  @Override
574  protected void done() {
575  if (!isCancelled()) {
576  try {
577  ViewUpdate viewUpdate = get();
578  if (viewUpdate != null) {
579  updateView(viewUpdate);
580  }
581  }
582  catch (InterruptedException | ExecutionException ex) {
583  logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS
584  }
585  }
586  }
587  }
588 }
void setArtifactContentStrings(List< ArtifactStringContent > artifactStrings)
synchronized void startNewTask(SwingWorker< ViewUpdate, Void > task)
static void configureTextPaneAsHtml(JTextPane pane)
Definition: Utilities.java:31
List< BlackboardAttribute > getAttributes()
ArrayList< BlackboardArtifact > getAllArtifacts()
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.