Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
KeywordHit.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 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.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.util.Comparator;
24 import java.util.Objects;
25 import java.util.Optional;
26 import org.apache.commons.lang3.StringUtils;
29 import org.sleuthkit.datamodel.BlackboardAttribute;
30 import org.sleuthkit.datamodel.SleuthkitCase;
31 import org.sleuthkit.datamodel.TskCoreException;
32 
40 class KeywordHit implements Comparable<KeywordHit> {
41 
42  private static final String GET_CONTENT_ID_FROM_ARTIFACT_ID = "SELECT obj_id FROM blackboard_artifacts WHERE artifact_id = ";
43 
44  private final long solrObjectId;
45  private final int chunkId;
46  private final String snippet;
47  private final String hit;
48 
60  KeywordHit(String solrDocumentId, String snippet, String hit) {
61  this.snippet = StringUtils.stripToEmpty(snippet);
62  this.hit = hit;
63 
64  /*
65  * Parse the Solr document id to get the Solr object id and chunk id.
66  * The Solr object id will either be the object id of a file id or an
67  * artifact id from the case database.
68  *
69  * For every object (file or artifact) there will at least two Solr
70  * documents. One contains object metadata (chunk #1) and the second and
71  * subsequent documents contain chunks of the text.
72  */
73  if(!solrDocumentId.isEmpty()) {
74  String[] split = solrDocumentId.split(Server.CHUNK_ID_SEPARATOR);
75  if (split.length == 1) {
76  //chunk 0 has only the bare document id without the chunk id.
77  this.solrObjectId = Long.parseLong(solrDocumentId);
78  this.chunkId = 0;
79  } else {
80  this.solrObjectId = Long.parseLong(split[0]);
81  this.chunkId = Integer.parseInt(split[1]);
82  }
83  } else {
84  this.solrObjectId = 0;
85  this.chunkId = 0;
86  }
87  }
88 
89  KeywordHit(int chunkId, long sourceID, String snippet, String hit) {
90  this.snippet = StringUtils.stripToEmpty(snippet);
91  this.hit = hit;
92  this.chunkId = chunkId;
93  this.solrObjectId = sourceID;
94  }
95 
96 
97  String getHit() {
98  return hit;
99  }
100 
101  String getSolrDocumentId() {
102  return Long.toString(solrObjectId) + Server.CHUNK_ID_SEPARATOR + Long.toString(chunkId);
103  }
104 
105  Long getSolrObjectId() {
106  return this.solrObjectId;
107  }
108 
109  Integer getChunkId() {
110  return this.chunkId;
111  }
112 
113  boolean hasSnippet() {
114  return StringUtils.isNotBlank(this.snippet);
115  }
116 
117  String getSnippet() {
118  return this.snippet;
119  }
120 
132  long getContentID() throws TskCoreException {
133  if (isArtifactHit()) {
134  // If the hit was in an artifact, look up the source content for the artifact.
135  SleuthkitCase caseDb;
136  try {
137  caseDb = Case.getCurrentCaseThrows().getSleuthkitCase();
138  } catch (NoCurrentCaseException ex) {
139  throw new TskCoreException("Exception while getting open case.", ex);
140  }
141  try (SleuthkitCase.CaseDbQuery executeQuery =
142  caseDb.executeQuery(GET_CONTENT_ID_FROM_ARTIFACT_ID + this.solrObjectId);
143  ResultSet resultSet = executeQuery.getResultSet();) {
144  if (resultSet.next()) {
145  return resultSet.getLong("obj_id");
146  } else {
147  throw new TskCoreException("Failed to get obj_id for artifact with artifact_id =" + this.solrObjectId + ". No matching artifact was found.");
148  }
149  } catch (SQLException ex) {
150  throw new TskCoreException("Error getting obj_id for artifact with artifact_id =" + this.solrObjectId, ex);
151  }
152  } else {
153  //else the object id is for content.
154  return this.solrObjectId;
155  }
156  }
157 
163  boolean isArtifactHit() {
164  // artifacts have negative obj ids
165  return this.solrObjectId < 0;
166  }
167 
173  Optional<Long> getArtifactID() {
174  if (isArtifactHit()) {
175  return Optional.of(solrObjectId);
176  } else {
177  return Optional.empty();
178  }
179  }
180 
181  @Override
182  public boolean equals(Object obj) {
183  if (null == obj) {
184  return false;
185  }
186  if (getClass() != obj.getClass()) {
187  return false;
188  }
189  final KeywordHit other = (KeywordHit) obj;
190  return compareTo(other) == 0;
191  }
192 
193  @Override
194  public int hashCode() {
195  int hash = 7;
196  hash = 37 * hash + (int) (this.solrObjectId ^ (this.solrObjectId >>> 32));
197  hash = 37 * hash + this.chunkId;
198  hash = 37 * hash + Objects.hashCode(this.snippet);
199  hash = 37 * hash + Objects.hashCode(this.hit);
200  return hash;
201  }
202 
203  @Override
204  public int compareTo(KeywordHit other) {
205  return Comparator.comparing(KeywordHit::getSolrObjectId)
206  .thenComparing(KeywordHit::getChunkId)
207  .thenComparing(KeywordHit::getHit)
208  .thenComparing(KeywordHit::getSnippet)
209  .compare(this, other);
210  }
211 }

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.