20 package org.sleuthkit.autopsy.keywordsearch;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashSet;
25 import java.util.List;
27 import java.util.logging.Level;
29 import java.util.regex.Pattern;
30 import java.util.regex.PatternSyntaxException;
31 import org.apache.solr.client.solrj.SolrQuery;
32 import org.apache.solr.client.solrj.response.TermsResponse;
33 import org.apache.solr.client.solrj.response.TermsResponse.Term;
45 class TermComponentQuery
implements KeywordSearchQuery {
47 private static final int TERMS_UNLIMITED = -1;
49 private static final String TERMS_SEARCH_FIELD = Server.Schema.CONTENT_WS.toString();
50 private static final String TERMS_HANDLER =
"/terms";
51 private static final int TERMS_TIMEOUT = 90 * 1000;
52 private static final Logger logger = Logger.getLogger(TermComponentQuery.class.getName());
53 private String queryEscaped;
54 private final KeywordList keywordList;
55 private final Keyword keyword;
56 private boolean isEscaped;
57 private List<Term> terms;
58 private final List<KeywordQueryFilter> filters =
new ArrayList<>();
60 private static final int MAX_TERMS_RESULTS = 20000;
62 private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
64 public TermComponentQuery(KeywordList keywordList, Keyword keyword) {
66 this.keyword = keyword;
67 this.keywordList = keywordList;
68 this.queryEscaped = keyword.getQuery();
74 public void addFilter(KeywordQueryFilter filter) {
75 this.filters.add(filter);
79 public void setField(String field) {
84 public void setSubstringQuery() {
85 queryEscaped =
".*" + queryEscaped +
".*";
89 public void escape() {
90 queryEscaped = Pattern.quote(keyword.getQuery());
95 public boolean validate() {
96 if (queryEscaped.equals(
"")) {
100 boolean valid =
true;
102 Pattern.compile(queryEscaped);
103 }
catch (PatternSyntaxException ex1) {
105 }
catch (IllegalArgumentException ex2) {
112 public boolean isEscaped() {
117 public boolean isLiteral() {
124 protected SolrQuery createQuery() {
125 final SolrQuery q =
new SolrQuery();
126 q.setRequestHandler(TERMS_HANDLER);
128 q.setTermsLimit(TERMS_UNLIMITED);
129 q.setTermsRegexFlag(
"case_insensitive");
133 q.setTermsRegex(queryEscaped);
134 q.addTermsField(TERMS_SEARCH_FIELD);
135 q.setTimeAllowed(TERMS_TIMEOUT);
144 protected List<Term> executeQuery(SolrQuery q)
throws NoOpenCoreException {
146 Server solrServer = KeywordSearch.getServer();
147 TermsResponse tr = solrServer.queryTerms(q);
148 List<Term> termsCol = tr.getTerms(TERMS_SEARCH_FIELD);
150 }
catch (KeywordSearchModuleException ex) {
151 logger.log(Level.WARNING,
"Error executing the regex terms query: " + keyword.getQuery(), ex);
157 public String getEscapedQueryString() {
158 return this.queryEscaped;
162 public String getQueryString() {
163 return keyword.getQuery();
169 public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName) {
170 final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
173 BlackboardArtifact bba;
174 KeywordCachedArtifact writeResult;
175 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
177 bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
178 writeResult =
new KeywordCachedArtifact(bba);
179 }
catch (Exception e) {
180 logger.log(Level.WARNING,
"Error adding bb artifact for keyword hit", e);
185 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID(), MODULE_NAME, termHit));
187 if ((listName != null) && (listName.equals(
"") ==
false)) {
188 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), MODULE_NAME, listName));
192 if (snippet != null) {
193 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID(), MODULE_NAME, snippet));
196 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID(), MODULE_NAME, keyword.getQuery()));
198 if (hit.isArtifactHit()) {
199 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID(), MODULE_NAME, hit.getArtifact().getArtifactID()));
203 bba.addAttributes(attributes);
204 writeResult.add(attributes);
206 }
catch (TskException e) {
207 logger.log(Level.WARNING,
"Error adding bb attributes for terms search artifact", e);
214 public QueryResults performQuery() throws NoOpenCoreException {
216 final SolrQuery q = createQuery();
217 q.setShowDebugInfo(DEBUG);
218 q.setTermsLimit(MAX_TERMS_RESULTS);
219 logger.log(Level.INFO,
"Query: {0}", q.toString());
220 terms = executeQuery(q);
222 QueryResults results =
new QueryResults(
this, keywordList);
225 for (Term term : terms) {
226 final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
228 LuceneQuery filesQuery =
new LuceneQuery(keywordList,
new Keyword(termStr,
true));
231 for (KeywordQueryFilter filter : filters) {
235 filesQuery.addFilter(filter);
238 QueryResults subResults = filesQuery.performQuery();
239 Set<KeywordHit> filesResults =
new HashSet<>();
240 for (Keyword key : subResults.getKeywords()) {
241 List<KeywordHit> keyRes = subResults.getResults(key);
242 resultSize += keyRes.size();
243 filesResults.addAll(keyRes);
245 results.addResult(
new Keyword(term.getTerm(),
false),
new ArrayList<>(filesResults));
246 }
catch (NoOpenCoreException e) {
247 logger.log(Level.WARNING,
"Error executing Solr query,", e);
249 }
catch (RuntimeException e) {
250 logger.log(Level.WARNING,
"Error executing Solr query,", e);
256 logger.log(Level.INFO,
"Regex # results: {0}", resultSize);
262 public KeywordList getKeywordList() {