Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DomainSearchArtifactsCache.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 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.discovery.search;
20 
21 import com.google.common.cache.CacheBuilder;
22 import com.google.common.cache.LoadingCache;
23 import com.google.common.eventbus.Subscribe;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.TimeUnit;
31 import org.sleuthkit.datamodel.BlackboardArtifact;
32 import org.sleuthkit.datamodel.SleuthkitCase;
33 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
34 
39 
40  private static final int MAXIMUM_CACHE_SIZE = 10;
41  private static final int TIME_TO_LIVE = 5; // In minutes
42  private static final LoadingCache<ArtifactCacheKey, Map<String, List<BlackboardArtifact>>> cache
43  = CacheBuilder.newBuilder()
44  .maximumSize(MAXIMUM_CACHE_SIZE)
45  .expireAfterWrite(TIME_TO_LIVE, TimeUnit.MINUTES)
46  .build(new DomainSearchArtifactsLoader());
47 
48  // Listen for new search events. When this happens, we should invalidate all the
49  // entries in the cache. This, along with the 5 minutes expiration, ensures that
50  // searches get up to date results during ingest.
51  private static final NewSearchListener newSearchListener = new NewSearchListener();
52  static {
53  DiscoveryEventUtils.getDiscoveryEventBus().register(newSearchListener);
54  }
66  public List<BlackboardArtifact> get(DomainSearchArtifactsRequest request) throws DiscoveryException {
67  String typeName = request.getArtifactType().getLabel();
68  if (!typeName.startsWith("TSK_WEB")) {
69  throw new IllegalArgumentException("Only web artifacts are valid arguments. Type provided was " + typeName);
70  }
71 
72  try {
73  Map<String, List<BlackboardArtifact>> artifactsByDomain = cache.get(new ArtifactCacheKey(request));
74  final String normalizedDomain = request.getDomain().trim().toLowerCase();
75  return artifactsByDomain.getOrDefault(normalizedDomain, Collections.emptyList());
76  } catch (ExecutionException ex) {
77  //throwing a new exception with the cause so that interrupted exceptions and other causes can be checked inside our wrapper
78  throw new DiscoveryException("Error fetching artifacts from cache for " + request.toString(), ex.getCause());
79  }
80  }
81 
85  static class NewSearchListener {
86 
87  @Subscribe
88  public void listenToSearchStartedEvent(SearchStartedEvent event) {
89  cache.invalidateAll();
90  }
91  }
92 
97  class ArtifactCacheKey {
98 
99  private final ARTIFACT_TYPE type;
100  private final SleuthkitCase caseDatabase;
101 
102  private ArtifactCacheKey(DomainSearchArtifactsRequest request) {
103  this.type = request.getArtifactType();
104  this.caseDatabase = request.getSleuthkitCase();
105  }
106 
107  ARTIFACT_TYPE getType() {
108  return this.type;
109  }
110 
111  SleuthkitCase getSleuthkitCase() {
112  return this.caseDatabase;
113  }
114 
115  @Override
116  public int hashCode() {
117  int hash = 7;
118  hash = 67 * hash + Objects.hashCode(this.type);
119  hash = 67 * hash + Objects.hashCode(this.caseDatabase);
120  return hash;
121  }
122 
123  @Override
124  public boolean equals(Object obj) {
125  if (this == obj) {
126  return true;
127  }
128 
129  if (obj == null || getClass() != obj.getClass()) {
130  return false;
131  }
132 
133  final ArtifactCacheKey other = (ArtifactCacheKey) obj;
134 
135  // The artifact type and case database references must be equal.
136  return this.type == other.type &&
137  Objects.equals(this.caseDatabase, other.caseDatabase);
138  }
139  }
140 }
static final LoadingCache< ArtifactCacheKey, Map< String, List< BlackboardArtifact > > > cache

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.