1 /* 2 * Sleuth Kit Data Model 3 * 4 * Copyright 2011-2016 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.datamodel; 20 21 import java.util.ArrayList; 22 import java.util.Collections; 23 import java.util.HashSet; 24 import java.util.List; 25 import java.util.Set; 26 import java.util.logging.Level; 27 import java.util.logging.Logger; 28 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; 29 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; 30 import org.sleuthkit.datamodel.SleuthkitCase.ObjectInfo; 31 32 /** 33 * Implements some general methods from the Content interface common across many 34 * content sub types 35 */ 36 public abstract class AbstractContent implements Content { 37 38 public final static long UNKNOWN_ID = -1; 39 private final SleuthkitCase db; 40 private final long objId; 41 private final String name; 42 private Content parent; 43 private String uniquePath; 44 protected long parentId; 45 private volatile boolean hasChildren; 46 private volatile boolean checkedHasChildren; 47 private volatile int childrenCount; 48 private BlackboardArtifact genInfoArtifact = null; 49 AbstractContent(SleuthkitCase db, long obj_id, String name)50 protected AbstractContent(SleuthkitCase db, long obj_id, String name) { 51 this.db = db; 52 this.objId = obj_id; 53 this.name = name; 54 this.parentId = UNKNOWN_ID; 55 56 checkedHasChildren = false; 57 hasChildren = false; 58 childrenCount = -1; 59 } 60 61 @Override getName()62 public String getName() { 63 return this.name; 64 } 65 66 /* 67 * This base implementation simply walks the hierarchy appending its own 68 * name to the result of calling its parent's getUniquePath() method (with 69 * interleaving forward slashes). 70 */ 71 @Override getUniquePath()72 public synchronized String getUniquePath() throws TskCoreException { 73 if (uniquePath == null) { 74 uniquePath = ""; 75 if (!name.isEmpty()) { 76 uniquePath = "/" + getName(); 77 } 78 79 Content myParent = getParent(); 80 if (myParent != null) { 81 uniquePath = myParent.getUniquePath() + uniquePath; 82 } 83 } 84 return uniquePath; 85 } 86 87 @Override hasChildren()88 public boolean hasChildren() throws TskCoreException { 89 if (checkedHasChildren == true) { 90 return hasChildren; 91 } 92 93 hasChildren = this.getSleuthkitCase().getHasChildren(this); 94 checkedHasChildren = true; 95 96 return hasChildren; 97 } 98 99 @Override getChildrenCount()100 public int getChildrenCount() throws TskCoreException { 101 if (childrenCount != -1) { 102 return childrenCount; 103 } 104 105 childrenCount = this.getSleuthkitCase().getContentChildrenCount(this); 106 107 hasChildren = childrenCount > 0; 108 checkedHasChildren = true; 109 110 return childrenCount; 111 } 112 113 @Override getParent()114 public synchronized Content getParent() throws TskCoreException { 115 if (parent == null) { 116 ObjectInfo parentInfo; 117 parentInfo = db.getParentInfo(this); 118 if (parentInfo == null) { 119 parent = null; 120 } else { 121 parent = db.getContentById(parentInfo.getId()); 122 } 123 } 124 return parent; 125 } 126 setParent(Content parent)127 void setParent(Content parent) { 128 this.parent = parent; 129 } 130 131 /** 132 * Set the ID of the this AbstractContent's parent 133 * 134 * @param parentId the ID of the parent. Note: use 135 * AbstractContent.UNKNOWN_ID if the parent's ID is not 136 * known. 137 */ setParentId(long parentId)138 void setParentId(long parentId) { 139 this.parentId = parentId; 140 } 141 142 @Override getId()143 public long getId() { 144 return this.objId; 145 } 146 147 /** 148 * Gets all children of this abstract content, if any. 149 * 150 * @return A list of the children. 151 * 152 * @throws TskCoreException if there was an error querying the case 153 * database. 154 */ 155 @Override getChildren()156 public List<Content> getChildren() throws TskCoreException { 157 List<Content> children = new ArrayList<Content>(); 158 159 children.addAll(getSleuthkitCase().getAbstractFileChildren(this)); 160 children.addAll(getSleuthkitCase().getBlackboardArtifactChildren(this)); 161 162 return children; 163 164 } 165 166 /** 167 * Gets the object ids of objects, if any, that are children of this 168 * abstract content. 169 * 170 * @return A list of the object ids. 171 * 172 * @throws TskCoreException if there was an error querying the case 173 * database. 174 */ 175 @Override getChildrenIds()176 public List<Long> getChildrenIds() throws TskCoreException { 177 178 List<Long> childrenIDs = new ArrayList<Long>(); 179 180 childrenIDs.addAll(getSleuthkitCase().getAbstractFileChildrenIds(this)); 181 childrenIDs.addAll(getSleuthkitCase().getBlackboardArtifactChildrenIds(this)); 182 183 return childrenIDs; 184 } 185 186 // classes should override this if they can be a data source 187 @Override getDataSource()188 public Content getDataSource() throws TskCoreException { 189 Content myParent = getParent(); 190 if (myParent == null) { 191 return null; 192 } 193 194 return myParent.getDataSource(); 195 } 196 197 /** 198 * Gets handle of SleuthkitCase to which this content belongs 199 * 200 * @return the case handle 201 */ getSleuthkitCase()202 public SleuthkitCase getSleuthkitCase() { 203 return db; 204 } 205 206 @Override equals(Object obj)207 public boolean equals(Object obj) { 208 if (obj == null) { 209 return false; 210 } 211 if (getClass() != obj.getClass()) { 212 return false; 213 } 214 final AbstractContent other = (AbstractContent) obj; 215 if (this.objId != other.objId) { 216 return false; 217 } 218 219 try { 220 // New children may have been added to an existing content 221 // object in which case they are not equal. 222 if (this.getChildrenCount() != other.getChildrenCount()) { 223 return false; 224 } 225 } catch (TskCoreException ex) { 226 Logger.getLogger(AbstractContent.class.getName()).log(Level.SEVERE, null, ex); 227 } 228 229 return true; 230 } 231 232 @Override hashCode()233 public int hashCode() { 234 int hash = 7 + (int) (this.objId ^ (this.objId >>> 32)); 235 try { 236 hash = 41 * hash + this.getChildrenCount(); 237 } catch (TskCoreException ex) { 238 Logger.getLogger(AbstractContent.class.getName()).log(Level.SEVERE, null, ex); 239 } 240 return hash; 241 } 242 243 @Override newArtifact(int artifactTypeID)244 public BlackboardArtifact newArtifact(int artifactTypeID) throws TskCoreException { 245 // don't let them make more than 1 GEN_INFO 246 if (artifactTypeID == ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID()) { 247 return getGenInfoArtifact(true); 248 } 249 return db.newBlackboardArtifact(artifactTypeID, objId); 250 } 251 252 @Override newArtifact(BlackboardArtifact.ARTIFACT_TYPE type)253 public BlackboardArtifact newArtifact(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException { 254 return newArtifact(type.getTypeID()); 255 } 256 257 @Override getArtifacts(String artifactTypeName)258 public ArrayList<BlackboardArtifact> getArtifacts(String artifactTypeName) throws TskCoreException { 259 return getArtifacts(db.getArtifactType(artifactTypeName).getTypeID()); 260 } 261 262 @Override getArtifacts(int artifactTypeID)263 public ArrayList<BlackboardArtifact> getArtifacts(int artifactTypeID) throws TskCoreException { 264 if (artifactTypeID == ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID()) { 265 if (genInfoArtifact == null) // don't make one if it doesn't already exist 266 { 267 getGenInfoArtifact(false); 268 } 269 270 ArrayList<BlackboardArtifact> list = new ArrayList<BlackboardArtifact>(); 271 // genInfoArtifact coudl still be null if there isn't an artifact 272 if (genInfoArtifact != null) { 273 list.add(genInfoArtifact); 274 } 275 return list; 276 } 277 return db.getBlackboardArtifacts(artifactTypeID, objId); 278 } 279 280 @Override getArtifacts(BlackboardArtifact.ARTIFACT_TYPE type)281 public ArrayList<BlackboardArtifact> getArtifacts(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException { 282 return getArtifacts(type.getTypeID()); 283 } 284 285 @Override getGenInfoArtifact()286 public BlackboardArtifact getGenInfoArtifact() throws TskCoreException { 287 return getGenInfoArtifact(true); 288 } 289 290 @Override getGenInfoArtifact(boolean create)291 public BlackboardArtifact getGenInfoArtifact(boolean create) throws TskCoreException { 292 if (genInfoArtifact != null) { 293 return genInfoArtifact; 294 } 295 296 // go to db directly to avoid infinite loop 297 ArrayList<BlackboardArtifact> arts = db.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO, objId); 298 BlackboardArtifact retArt; 299 if (arts.isEmpty()) { 300 if (create) { 301 retArt = db.newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO, objId); 302 } else { 303 return null; 304 } 305 } else { 306 retArt = arts.get(0); 307 } 308 genInfoArtifact = retArt; 309 return retArt; 310 } 311 312 @Override getGenInfoAttributes(ATTRIBUTE_TYPE attr_type)313 public ArrayList<BlackboardAttribute> getGenInfoAttributes(ATTRIBUTE_TYPE attr_type) throws TskCoreException { 314 ArrayList<BlackboardAttribute> returnList = new ArrayList<BlackboardAttribute>(); 315 316 if (genInfoArtifact == null) { 317 getGenInfoArtifact(false); 318 if (genInfoArtifact == null) { 319 return returnList; 320 } 321 } 322 323 for (BlackboardAttribute attribute : genInfoArtifact.getAttributes()) { 324 if (attribute.getAttributeType().getTypeID() == attr_type.getTypeID()) { 325 returnList.add(attribute); 326 } 327 } 328 329 return returnList; 330 } 331 332 @Override getAllArtifacts()333 public ArrayList<BlackboardArtifact> getAllArtifacts() throws TskCoreException { 334 return db.getMatchingArtifacts("WHERE obj_id = " + objId); //NON-NLS 335 } 336 337 @Override getArtifactsCount(String artifactTypeName)338 public long getArtifactsCount(String artifactTypeName) throws TskCoreException { 339 return db.getBlackboardArtifactsCount(artifactTypeName, objId); 340 } 341 342 @Override getArtifactsCount(int artifactTypeID)343 public long getArtifactsCount(int artifactTypeID) throws TskCoreException { 344 return db.getBlackboardArtifactsCount(artifactTypeID, objId); 345 } 346 347 @Override getArtifactsCount(ARTIFACT_TYPE type)348 public long getArtifactsCount(ARTIFACT_TYPE type) throws TskCoreException { 349 return db.getBlackboardArtifactsCount(type, objId); 350 } 351 352 @Override getAllArtifactsCount()353 public long getAllArtifactsCount() throws TskCoreException { 354 return db.getBlackboardArtifactsCount(objId); 355 } 356 357 @Override getHashSetNames()358 public Set<String> getHashSetNames() throws TskCoreException { 359 Set<String> hashNames = new HashSet<String>(); 360 ArrayList<BlackboardArtifact> artifacts = getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); 361 362 for (BlackboardArtifact a : artifacts) { 363 BlackboardAttribute attribute = a.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME)); 364 if (attribute != null) { 365 hashNames.add(attribute.getValueString()); 366 } 367 } 368 return Collections.unmodifiableSet(hashNames); 369 } 370 371 @Override toString()372 public String toString() { 373 return toString(true); 374 } 375 toString(boolean preserveState)376 public String toString(boolean preserveState) { 377 if (preserveState) { 378 return "AbstractContent [\t" + "objId " + String.format("%010d", objId) + "\t" //NON-NLS 379 + "name " + name + "\t" + "parentId " + parentId + "\t" //NON-NLS 380 + "\t" + "checkedHasChildren " + checkedHasChildren //NON-NLS 381 + "\t" + "hasChildren " + hasChildren //NON-NLS 382 + "\t" + "childrenCount " + childrenCount //NON-NLS 383 + "uniquePath " + uniquePath + "]\t"; //NON-NLS 384 } else { 385 try { 386 if (getParent() != null) { 387 return "AbstractContent [\t" + "objId " + String.format("%010d", objId) //NON-NLS 388 + "\t" + "name " + name //NON-NLS 389 + "\t" + "checkedHasChildren " + checkedHasChildren //NON-NLS 390 + "\t" + "hasChildren " + hasChildren //NON-NLS 391 + "\t" + "childrenCount " + childrenCount //NON-NLS 392 + "\t" + "getUniquePath " + getUniquePath() //NON-NLS 393 + "\t" + "getParent " + getParent().getId() + "]\t"; //NON-NLS 394 } else { 395 return "AbstractContent [\t" + "objId " //NON-NLS 396 + String.format("%010d", objId) + "\t" + "name " + name //NON-NLS 397 + "\t" + "checkedHasChildren " + checkedHasChildren //NON-NLS 398 + "\t" + "hasChildren " + hasChildren //NON-NLS 399 + "\t" + "childrenCount " + childrenCount //NON-NLS 400 + "\t" + "uniquePath " + getUniquePath() //NON-NLS 401 + "\t" + "parentId " + parentId + "]\t"; //NON-NLS 402 } 403 } catch (TskCoreException ex) { 404 Logger.getLogger(AbstractContent.class.getName()).log(Level.SEVERE, "Could not find Parent", ex); //NON-NLS 405 return "AbstractContent [\t" + "objId " + String.format("%010d", objId) + "\t" //NON-NLS 406 + "name " + name + "\t" + "parentId " + parentId + "\t" //NON-NLS 407 + "\t" + "checkedHasChildren " + checkedHasChildren //NON-NLS 408 + "\t" + "hasChildren " + hasChildren //NON-NLS 409 + "\t" + "childrenCount " + childrenCount //NON-NLS 410 + "uniquePath " + uniquePath + "]\t"; //NON-NLS 411 } 412 } 413 } 414 } 415