Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AnnotationsContentViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2018-2020 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.contentviewers;
20 
21 import java.awt.Component;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.function.Function;
26 import java.util.logging.Level;
27 import java.util.stream.Collectors;
28 import javax.swing.JLabel;
29 import javax.swing.text.EditorKit;
30 import javax.swing.text.html.HTMLEditorKit;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.commons.lang3.tuple.Pair;
33 
34 import static org.openide.util.NbBundle.Messages;
35 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
37 import org.openide.nodes.Node;
38 import org.openide.util.lookup.ServiceProvider;
46 import org.sleuthkit.datamodel.AbstractFile;
47 import org.sleuthkit.datamodel.BlackboardArtifact;
48 import org.sleuthkit.datamodel.BlackboardArtifactTag;
49 import org.sleuthkit.datamodel.Content;
50 import org.sleuthkit.datamodel.ContentTag;
51 import org.sleuthkit.datamodel.SleuthkitCase;
52 import org.sleuthkit.datamodel.Tag;
53 import org.sleuthkit.datamodel.TskCoreException;
55 import org.sleuthkit.datamodel.BlackboardAttribute;
56 import org.jsoup.Jsoup;
57 import org.jsoup.nodes.Document;
58 import org.jsoup.nodes.Element;
59 
63 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
64 @ServiceProvider(service = DataContentViewer.class, position = 8)
65 @Messages({
66  "AnnotationsContentViewer.title=Annotations",
67  "AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.",
68  "AnnotationsContentViewer.centralRepositoryEntry.title=Central Repository Comments",
69  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:",
70  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:",
71  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:",
72  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:",
73  "AnnotationsContentViewer.tagEntry.title=Tags",
74  "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:",
75  "AnnotationsContentViewer.tagEntryDataLabel.tagUser=Examiner:",
76  "AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:",
77  "AnnotationsContentViewer.fileHitEntry.artifactCommentTitle=Artifact Comment",
78  "AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments",
79  "AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments",
80  "AnnotationsContentViewer.fileHitEntry.setName=Set Name:",
81  "AnnotationsContentViewer.fileHitEntry.comment=Comment:",
82  "AnnotationsContentViewer.sourceFile.title=Source File",
83  "AnnotationsContentViewer.onEmpty=No annotations were found for this particular item."
84 })
85 public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer {
86 
94  private static class ItemEntry<T> {
95 
96  private final String itemName;
97  private final Function<T, String> valueRetriever;
98 
99  ItemEntry(String itemName, Function<T, String> valueRetriever) {
100  this.itemName = itemName;
101  this.valueRetriever = valueRetriever;
102  }
103 
104  String getItemName() {
105  return itemName;
106  }
107 
108  Function<T, String> getValueRetriever() {
109  return valueRetriever;
110  }
111 
112  String retrieveValue(T object) {
113  return valueRetriever.apply(object);
114  }
115  }
116 
122  private static class SectionConfig<T> {
123 
124  private final String title;
125  private final List<ItemEntry<T>> attributes;
126 
127  SectionConfig(String title, List<ItemEntry<T>> attributes) {
128  this.title = title;
129  this.attributes = attributes;
130  }
131 
135  String getTitle() {
136  return title;
137  }
138 
143  List<ItemEntry<T>> getAttributes() {
144  return attributes;
145  }
146  }
147 
148  private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName());
149 
150  private static final String EMPTY_HTML = "<html><head></head><body></body></html>";
151 
152  private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize();
153 
154  // how big the subheader should be
155  private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11;
156 
157  // how big the header should be
158  private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11;
159 
160  // the subsection indent
161  private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE;
162 
163  // spacing occurring after an item
164  private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE;
165  private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE * 2;
166  private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE / 2;
167  private static final int CELL_SPACING = DEFAULT_FONT_SIZE / 2;
168 
169  // html stylesheet classnames for components
170  private static final String MESSAGE_CLASSNAME = "message";
171  private static final String SUBSECTION_CLASSNAME = "subsection";
172  private static final String SUBHEADER_CLASSNAME = "subheader";
173  private static final String SECTION_CLASSNAME = "section";
174  private static final String HEADER_CLASSNAME = "header";
175  private static final String VERTICAL_TABLE_CLASSNAME = "vertical-table";
176 
177  // additional styling for components
178  private static final String STYLE_SHEET_RULE
179  = String.format(" .%s { font-size: %dpx;font-style:italic; margin: 0px; padding: 0px; } ", MESSAGE_CLASSNAME, DEFAULT_FONT_SIZE)
180  + String.format(" .%s {font-size:%dpx;font-weight:bold; margin: 0px; margin-top: %dpx; padding: 0px; } ",
181  SUBHEADER_CLASSNAME, SUBHEADER_FONT_SIZE, DEFAULT_SUBSECTION_SPACING)
182  + String.format(" .%s { font-size:%dpx;font-weight:bold; margin: 0px; padding: 0px; } ", HEADER_CLASSNAME, HEADER_FONT_SIZE)
183  + String.format(" td { vertical-align: top; font-size:%dpx; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px;} ", DEFAULT_FONT_SIZE, CELL_SPACING)
184  + String.format(" th { vertical-align: top; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px} ", DEFAULT_FONT_SIZE, CELL_SPACING)
185  + String.format(" .%s { margin: %dpx 0px; padding-left: %dpx; } ", SUBSECTION_CLASSNAME, DEFAULT_SUBSECTION_SPACING, DEFAULT_SUBSECTION_LEFT_PAD)
186  + String.format(" .%s { margin-bottom: %dpx; } ", SECTION_CLASSNAME, DEFAULT_SECTION_SPACING);
187 
188  // describing table values for a tag
189  private static final List<ItemEntry<Tag>> TAG_ENTRIES = Arrays.asList(
190  new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(),
191  (tag) -> (tag.getName() != null) ? tag.getName().getDisplayName() : null),
192  new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), (tag) -> tag.getUserName()),
193  new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), (tag) -> tag.getComment())
194  );
195 
196  private static final SectionConfig<Tag> TAG_CONFIG
197  = new SectionConfig<>(Bundle.AnnotationsContentViewer_tagEntry_title(), TAG_ENTRIES);
198 
199  // file set attributes and table configurations
200  private static final List<ItemEntry<BlackboardArtifact>> FILESET_HIT_ENTRIES = Arrays.asList(
201  new ItemEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_setName(),
202  (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)),
203  new ItemEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_comment(),
204  (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT))
205  );
206 
207  private static final SectionConfig<BlackboardArtifact> INTERESTING_FILE_CONFIG
208  = new SectionConfig<>(Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), FILESET_HIT_ENTRIES);
209 
210  private static final SectionConfig<BlackboardArtifact> HASHSET_CONFIG
211  = new SectionConfig<>(Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), FILESET_HIT_ENTRIES);
212 
213  private static final SectionConfig<BlackboardArtifact> ARTIFACT_COMMENT_CONFIG
214  = new SectionConfig<>(Bundle.AnnotationsContentViewer_fileHitEntry_artifactCommentTitle(), FILESET_HIT_ENTRIES);
215 
216  // central repository attributes and table configuration
217  private static final List<ItemEntry<CorrelationAttributeInstance>> CR_COMMENTS_ENTRIES = Arrays.asList(
218  new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(),
219  cai -> (cai.getCorrelationCase() != null) ? cai.getCorrelationCase().getDisplayName() : null),
220  new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()),
221  new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath())
222  );
223 
224  private static final SectionConfig<CorrelationAttributeInstance> CR_COMMENTS_CONFIG
225  = new SectionConfig<>(Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), CR_COMMENTS_ENTRIES);
226 
231  initComponents();
233  // get html editor kit and apply additional style rules
234  EditorKit editorKit = jTextPane1.getEditorKit();
235  if (editorKit instanceof HTMLEditorKit) {
236  HTMLEditorKit htmlKit = (HTMLEditorKit) editorKit;
237  htmlKit.getStyleSheet().addRule(STYLE_SHEET_RULE);
238  }
239  }
240 
241  @Override
242  public void setNode(Node node) {
243  if ((node == null) || (!isSupported(node))) {
244  resetComponent();
245  return;
246  }
247 
248  Document html = Jsoup.parse(EMPTY_HTML);
249  Element body = html.getElementsByTag("body").first();
250 
251  BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
252  Content sourceFile = null;
253 
254  try {
255  if (artifact != null) {
256  /*
257  * Get the source content based on the artifact to ensure we
258  * display the correct data instead of whatever was in the node.
259  */
260  sourceFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
261  } else {
262  /*
263  * No artifact is present, so get the content based on what's
264  * present in the node. In this case, the selected item IS the
265  * source file.
266  */
267  sourceFile = node.getLookup().lookup(AbstractFile.class);
268  }
269  } catch (TskCoreException ex) {
270  logger.log(Level.SEVERE, String.format(
271  "Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
272  artifact.getDisplayName(), artifact.getArtifactID()), ex);
273  }
274 
275  boolean somethingWasRendered = false;
276  if (artifact != null) {
277  somethingWasRendered = renderArtifact(body, artifact, sourceFile);
278  } else {
279  somethingWasRendered = renderContent(body, sourceFile, false);
280  }
281 
282  if (!somethingWasRendered) {
283  appendMessage(body, Bundle.AnnotationsContentViewer_onEmpty());
284  }
285 
286  jTextPane1.setText(html.html());
287  jTextPane1.setCaretPosition(0);
288  }
289 
300  private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) {
301  boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false);
302 
304  List<CorrelationAttributeInstance> centralRepoComments = getCentralRepositoryData(bba);
305  boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false);
306  contentRendered = contentRendered || crRendered;
307  }
308 
309  // if artifact is a hashset hit or interesting file and has a non-blank comment
310  if ((ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID()
311  || ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID())
312  && (hasTskComment(bba))) {
313 
314  boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false);
315  contentRendered = contentRendered || filesetRendered;
316  }
317 
318  Element sourceFileSection = appendSection(parent, Bundle.AnnotationsContentViewer_sourceFile_title());
319  boolean sourceFileRendered = renderContent(sourceFileSection, sourceContent, true);
320 
321  if (!sourceFileRendered) {
322  sourceFileSection.remove();
323  }
324 
325  return contentRendered || sourceFileRendered;
326  }
327 
338  private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) {
339  boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader);
340 
341  if (sourceContent instanceof AbstractFile) {
342  AbstractFile sourceFile = (AbstractFile) sourceContent;
343 
345  List<CorrelationAttributeInstance> centralRepoComments = getCentralRepositoryData(sourceFile);
346  boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader);
347  contentRendered = contentRendered || crRendered;
348  }
349 
350  boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG,
351  getFileSetHits(sourceFile, ARTIFACT_TYPE.TSK_HASHSET_HIT),
352  isSubheader);
353 
354  boolean interestingFileRendered = appendEntries(parent, INTERESTING_FILE_CONFIG,
355  getFileSetHits(sourceFile, ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT),
356  isSubheader);
357 
358  contentRendered = contentRendered || hashsetRendered || interestingFileRendered;
359  }
360  return contentRendered;
361  }
362 
370  private static List<ContentTag> getTags(Content sourceContent) {
371  try {
372  SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
373  return tskCase.getContentTagsByContent(sourceContent);
374  } catch (NoCurrentCaseException ex) {
375  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
376  } catch (TskCoreException ex) {
377  logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
378  }
379  return new ArrayList<>();
380  }
381 
389  private static List<BlackboardArtifactTag> getTags(BlackboardArtifact bba) {
390  try {
391  SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
392  return tskCase.getBlackboardArtifactTagsByArtifact(bba);
393  } catch (NoCurrentCaseException ex) {
394  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
395  } catch (TskCoreException ex) {
396  logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
397  }
398  return new ArrayList<>();
399  }
400 
410  private static List<BlackboardArtifact> getFileSetHits(AbstractFile sourceFile, ARTIFACT_TYPE type) {
411  try {
412  SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
413  return tskCase.getBlackboardArtifacts(type, sourceFile.getId()).stream()
414  .filter((bba) -> hasTskComment(bba))
415  .collect(Collectors.toList());
416  } catch (NoCurrentCaseException ex) {
417  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
418  } catch (TskCoreException ex) {
419  logger.log(Level.SEVERE, "Exception while getting file set hits from the case database.", ex); //NON-NLS
420  }
421  return new ArrayList<>();
422  }
423 
431  private static boolean hasTskComment(BlackboardArtifact artifact) {
432  return StringUtils.isNotBlank(tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT));
433  }
434 
444  private static String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType) {
445  if (artifact == null) {
446  return null;
447  }
448 
449  BlackboardAttribute attr = null;
450  try {
451  attr = artifact.getAttribute(new BlackboardAttribute.Type(attributeType));
452  } catch (TskCoreException ex) {
453  logger.log(Level.WARNING, String.format("Unable to fetch attribute of type %s for artifact %s", attributeType, artifact), ex);
454  }
455 
456  if (attr == null) {
457  return null;
458  }
459 
460  return attr.getValueString();
461  }
462 
472  private static List<CorrelationAttributeInstance> getCentralRepositoryData(BlackboardArtifact artifact) {
473  if (artifact == null) {
474  return new ArrayList<>();
475  }
476 
478  .stream()
479  .map(cai -> Pair.of(cai.getCorrelationType(), cai.getCorrelationValue()))
480  .collect(Collectors.toList());
481 
482  return getCorrelationAttributeComments(lookupKeys);
483  }
484 
494  private static List<CorrelationAttributeInstance> getCentralRepositoryData(AbstractFile sourceFile) {
495  if (sourceFile == null || StringUtils.isEmpty(sourceFile.getMd5Hash())) {
496  return new ArrayList<>();
497  }
498 
499  List<CorrelationAttributeInstance.Type> artifactTypes = null;
500  try {
502  } catch (CentralRepoException ex) {
503  logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS
504  }
505 
506  if (artifactTypes == null || artifactTypes.isEmpty()) {
507  return new ArrayList<>();
508  }
509 
510  String md5 = sourceFile.getMd5Hash();
511 
512  // get key lookups for a file attribute types and the md5 hash
513  List<Pair<CorrelationAttributeInstance.Type, String>> lookupKeys = artifactTypes.stream()
514  .filter((attributeType) -> attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
515  .map((attributeType) -> Pair.of(attributeType, md5))
516  .collect(Collectors.toList());
517 
518  return getCorrelationAttributeComments(lookupKeys);
519  }
520 
529  private static List<CorrelationAttributeInstance> getCorrelationAttributeComments(List<Pair<CorrelationAttributeInstance.Type, String>> lookupKeys) {
530  List<CorrelationAttributeInstance> instancesToRet = new ArrayList<>();
531 
532  try {
533  // use lookup instances to find the actual correlation attributes for the items selected
534  for (Pair<CorrelationAttributeInstance.Type, String> typeVal : lookupKeys) {
535  instancesToRet.addAll(CentralRepository.getInstance()
536  .getArtifactInstancesByTypeValue(typeVal.getKey(), typeVal.getValue())
537  .stream()
538  // for each one found, if it has a comment, return
539  .filter((cai) -> StringUtils.isNotBlank(cai.getComment()))
540  .collect(Collectors.toList()));
541  }
542 
543  } catch (CentralRepoException ex) {
544  logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS
546  logger.log(Level.SEVERE, "Error normalizing instance from Central Repository database.", ex); // NON-NLS
547  }
548 
549  return instancesToRet;
550  }
551 
567  private static <T> boolean appendEntries(Element parent, SectionConfig<T> config, List<? extends T> items,
568  boolean isSubsection) {
569  if (items == null || items.isEmpty()) {
570  return false;
571  }
572 
573  Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle());
574  appendVerticalEntryTables(sectionDiv, items, config.getAttributes());
575  return true;
576  }
577 
588  private static <T> Element appendVerticalEntryTables(Element parent, List<? extends T> items, List<ItemEntry<T>> rowHeaders) {
589  boolean isFirst = true;
590  for (T item : items) {
591  if (item == null) {
592  continue;
593  }
594 
595  List<List<String>> tableData = rowHeaders.stream()
596  .map(row -> Arrays.asList(row.getItemName(), row.retrieveValue(item)))
597  .collect(Collectors.toList());
598 
599  Element childTable = appendTable(parent, 2, tableData, null);
600  childTable.attr("class", VERTICAL_TABLE_CLASSNAME);
601 
602  if (isFirst) {
603  isFirst = false;
604  } else {
605  childTable.attr("style", String.format("margin-top: %dpx;", DEFAULT_TABLE_SPACING));
606  }
607  }
608 
609  return parent;
610  }
611 
624  private static Element appendTable(Element parent, int columnNumber, List<List<String>> content, List<String> columnHeaders) {
625  Element table = parent.appendElement("table");
626  if (columnHeaders != null && !columnHeaders.isEmpty()) {
627  Element header = table.appendElement("thead");
628  appendRow(header, columnHeaders, columnNumber, true);
629  }
630  Element tableBody = table.appendElement("tbody");
631 
632  content.forEach((rowData) -> appendRow(tableBody, rowData, columnNumber, false));
633  return table;
634  }
635 
647  private static Element appendRow(Element rowParent, List<String> data, int columnNumber, boolean isHeader) {
648  String cellType = isHeader ? "th" : "td";
649  Element row = rowParent.appendElement("tr");
650  for (int i = 0; i < columnNumber; i++) {
651  Element cell = row.appendElement(cellType);
652  if (data != null && i < data.size()) {
653  cell.text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i));
654  }
655  }
656  return row;
657  }
658 
667  private static Element appendSection(Element parent, String headerText) {
668  Element sectionDiv = parent.appendElement("div");
669  sectionDiv.attr("class", SECTION_CLASSNAME);
670  Element header = sectionDiv.appendElement("h1");
671  header.text(headerText);
672  header.attr("class", HEADER_CLASSNAME);
673  return sectionDiv;
674  }
675 
684  private static Element appendSubsection(Element parent, String headerText) {
685  Element subsectionDiv = parent.appendElement("div");
686  subsectionDiv.attr("class", SUBSECTION_CLASSNAME);
687  Element header = subsectionDiv.appendElement("h2");
688  header.text(headerText);
689  header.attr("class", SUBHEADER_CLASSNAME);
690  return subsectionDiv;
691  }
692 
703  private static Element appendMessage(Element parent, String message) {
704  Element messageEl = parent.appendElement("p");
705  messageEl.text(message);
706  messageEl.attr("class", MESSAGE_CLASSNAME);
707  return messageEl;
708  }
709 
715  @SuppressWarnings("unchecked")
716  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
717  private void initComponents() {
718 
719  jScrollPane5 = new javax.swing.JScrollPane();
720  jTextPane1 = new javax.swing.JTextPane();
721 
722  setPreferredSize(new java.awt.Dimension(100, 58));
723 
724  jTextPane1.setEditable(false);
725  jTextPane1.setName(""); // NOI18N
726  jTextPane1.setPreferredSize(new java.awt.Dimension(600, 52));
727  jScrollPane5.setViewportView(jTextPane1);
728 
729  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
730  this.setLayout(layout);
731  layout.setHorizontalGroup(
732  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
733  .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 907, Short.MAX_VALUE)
734  );
735  layout.setVerticalGroup(
736  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
737  .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE)
738  );
739  }// </editor-fold>//GEN-END:initComponents
740 
741  // Variables declaration - do not modify//GEN-BEGIN:variables
742  private javax.swing.JScrollPane jScrollPane5;
743  private javax.swing.JTextPane jTextPane1;
744  // End of variables declaration//GEN-END:variables
745 
746  @Override
747  public String getTitle() {
748  return Bundle.AnnotationsContentViewer_title();
749  }
750 
751  @Override
752  public String getToolTip() {
753  return Bundle.AnnotationsContentViewer_toolTip();
754  }
755 
756  @Override
758  return new AnnotationsContentViewer();
759  }
760 
761  @Override
762  public boolean isSupported(Node node) {
763  BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
764 
765  try {
766  if (artifact != null) {
767  if (artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()) != null) {
768  return true;
769  }
770  } else {
771  if (node.getLookup().lookup(AbstractFile.class) != null) {
772  return true;
773  }
774  }
775  } catch (TskCoreException ex) {
776  logger.log(Level.SEVERE, String.format(
777  "Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
778  artifact.getDisplayName(), artifact.getArtifactID()), ex);
779  }
780 
781  return false;
782  }
783 
784  @Override
785  public int isPreferred(Node node) {
786  return 1;
787  }
788 
789  @Override
790  public Component getComponent() {
791  return this;
792  }
793 
794  @Override
795  public void resetComponent() {
796  jTextPane1.setText(EMPTY_HTML);
797  }
798 }
static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent)
static< T > Element appendVerticalEntryTables(Element parent, List<?extends T > items, List< ItemEntry< T >> rowHeaders)
static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader)
static List< CorrelationAttributeInstance > getCentralRepositoryData(AbstractFile sourceFile)
static Element appendRow(Element rowParent, List< String > data, int columnNumber, boolean isHeader)
static Element appendMessage(Element parent, String message)
static List< BlackboardArtifactTag > getTags(BlackboardArtifact bba)
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
static List< BlackboardArtifact > getFileSetHits(AbstractFile sourceFile, ARTIFACT_TYPE type)
static Element appendSubsection(Element parent, String headerText)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()
static List< CorrelationAttributeInstance > makeCorrAttrsForCorrelation(BlackboardArtifact artifact)
static Element appendTable(Element parent, int columnNumber, List< List< String >> content, List< String > columnHeaders)
static void configureTextPaneAsHtml(JTextPane pane)
Definition: Utilities.java:32
static String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType)
static List< CorrelationAttributeInstance > getCorrelationAttributeComments(List< Pair< CorrelationAttributeInstance.Type, String >> lookupKeys)
static< T > boolean appendEntries(Element parent, SectionConfig< T > config, List<?extends T > items, boolean isSubsection)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static List< CorrelationAttributeInstance > getCentralRepositoryData(BlackboardArtifact artifact)
static List< ContentTag > getTags(Content sourceContent)
static Element appendSection(Element parent, String headerText)

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