Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ContactCache.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 */
19package org.sleuthkit.autopsy.communications;
20
21import com.google.common.cache.CacheBuilder;
22import com.google.common.cache.CacheLoader;
23import com.google.common.cache.LoadingCache;
24import java.beans.PropertyChangeEvent;
25import java.beans.PropertyChangeListener;
26import java.sql.SQLException;
27import java.util.ArrayList;
28import java.util.EnumSet;
29import java.util.HashMap;
30import java.util.List;
31import java.util.Map;
32import java.util.concurrent.ExecutionException;
33import java.util.concurrent.TimeUnit;
34import java.util.logging.Level;
35import org.sleuthkit.autopsy.casemodule.Case;
36import org.sleuthkit.autopsy.coreutils.Logger;
37import org.sleuthkit.autopsy.ingest.IngestManager;
38import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
39import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
40import org.sleuthkit.datamodel.Account;
41import org.sleuthkit.datamodel.BlackboardArtifact;
42import org.sleuthkit.datamodel.BlackboardAttribute;
43import org.sleuthkit.datamodel.TskCoreException;
44
51final public class ContactCache {
52
53 private static final Logger logger = Logger.getLogger(ContactCache.class.getName());
54
55 private static ContactCache instance;
56
57 private final LoadingCache<String, Map<String, List<BlackboardArtifact>>> accountMap;
58
69 static public synchronized List<BlackboardArtifact> getContacts(Account account) throws ExecutionException {
70 return getInstance().accountMap.get("realMap").get(account.getTypeSpecificID());
71 }
72
76 static synchronized void invalidateCache() {
77 getInstance().accountMap.invalidateAll();
78 }
79
83 private ContactCache() {
84
85 accountMap = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build(
86 new CacheLoader<String, Map<String, List<BlackboardArtifact>>>() {
87 @Override
88 public Map<String, List<BlackboardArtifact>> load(String key) {
89 try {
90 return buildMap();
91 } catch (SQLException | TskCoreException ex) {
92 logger.log(Level.WARNING, "Failed to build account to contact map", ex);
93 }
94 return new HashMap<>(); // Return an empty map if there is an exception to avoid NPE and continual trying.
95 }
96 });
97
98 PropertyChangeListener ingestListener = pce -> {
99 String eventType = pce.getPropertyName();
100 if (eventType.equals(DATA_ADDED.toString())) {
101 ModuleDataEvent eventData = (ModuleDataEvent) pce.getOldValue();
102 if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
103 invalidateCache();
104 }
105 }
106 };
107
108 Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent event) -> {
109 if (event.getNewValue() == null) {
110 invalidateCache();
111 }
112 });
113
114 IngestManager.getInstance().addIngestModuleEventListener(EnumSet.of(DATA_ADDED), ingestListener);
115 }
116
122 private static synchronized ContactCache getInstance() {
123 if (instance == null) {
124 instance = new ContactCache();
125 }
126
127 return instance;
128 }
129
138 private Map<String, List<BlackboardArtifact>> buildMap() throws TskCoreException, SQLException {
139 Map<String, List<BlackboardArtifact>> acctMap = new HashMap<>();
140 List<BlackboardArtifact> contactList = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
141
142 for (BlackboardArtifact contactArtifact : contactList) {
143 List<BlackboardAttribute> contactAttributes = contactArtifact.getAttributes();
144 for (BlackboardAttribute attribute : contactAttributes) {
145 String typeName = attribute.getAttributeType().getTypeName();
146
147 if (typeName.startsWith("TSK_EMAIL")
148 || typeName.startsWith("TSK_PHONE")
149 || typeName.startsWith("TSK_NAME")
150 || typeName.startsWith("TSK_ID")) {
151 String accountID = attribute.getValueString();
152 List<BlackboardArtifact> artifactList = acctMap.getOrDefault(accountID, new ArrayList<>());
153
154 acctMap.put(accountID, artifactList);
155
156 if (!artifactList.contains(contactArtifact)) {
157 artifactList.add(contactArtifact);
158 }
159 }
160 }
161
162 }
163
164 return acctMap;
165 }
166}
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:712
final LoadingCache< String, Map< String, List< BlackboardArtifact > > > accountMap
static synchronized ContactCache getInstance()
static synchronized List< BlackboardArtifact > getContacts(Account account)
Map< String, List< BlackboardArtifact > > buildMap()
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static synchronized IngestManager getInstance()
void addIngestModuleEventListener(final PropertyChangeListener listener)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.