/* * Autopsy Forensic Browser * * Copyright 2014-16 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.timeline.datamodel.eventtype; import java.text.MessageFormat; import java.util.Optional; import java.util.function.Function; import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; /** * */ public interface ArtifactEventType extends EventType { public static final Logger LOGGER = Logger.getLogger(ArtifactEventType.class.getName()); /** * Get the artifact type this event type is derived from. * * @return The artifact type this event type is derived from. */ public BlackboardArtifact.Type getArtifactType(); /** * The attribute type this event type is derived from. * * @return The attribute type this event type is derived from. */ public BlackboardAttribute.Type getDateTimeAttributeType(); /** * Get the ID of the the artifact type that this EventType is derived from. * * @return the ID of the the artifact type that this EventType is derived * from. */ public default int getArtifactTypeID() { return getArtifactType().getTypeID(); } /** * given an artifact, pull out the time stamp, and compose the descriptions. * Each implementation of ArtifactEventType needs to implement * parseAttributesHelper() as hook for buildEventDescription(org.sleuthkit.datamodel.BlackboardArtifact) * to invoke. Most subtypes can use this default implementation. * * @param artf * * @return an AttributeEventDescription containing the timestamp * and description information * * @throws TskCoreException */ default AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf) throws TskCoreException { final BlackboardAttribute dateTimeAttr = artf.getAttribute(getDateTimeAttributeType()); long time = dateTimeAttr.getValueLong(); String shortDescription = getShortExtractor().apply(artf); String medDescription = shortDescription + " : " + getMedExtractor().apply(artf); String fullDescription = medDescription + " : " + getFullExtractor().apply(artf); return new AttributeEventDescription(time, shortDescription, medDescription, fullDescription); } /** * @return a function from an artifact to a String to use as part of the * full event description */ Function<BlackboardArtifact, String> getFullExtractor(); /** * @return a function from an artifact to a String to use as part of the * medium event description */ Function<BlackboardArtifact, String> getMedExtractor(); /** * @return a function from an artifact to a String to use as part of the * short event description */ Function<BlackboardArtifact, String> getShortExtractor(); /** * bundles the per event information derived from a BlackBoard Artifact into * one object. Primarily used to have a single return value for * ArtifactEventType#buildEventDescription(ArtifactEventType, BlackboardArtifact). */ static class AttributeEventDescription { final private long time; public long getTime() { return time; } public String getShortDescription() { return shortDescription; } public String getMedDescription() { return medDescription; } public String getFullDescription() { return fullDescription; } final private String shortDescription; final private String medDescription; final private String fullDescription; public AttributeEventDescription(long time, String shortDescription, String medDescription, String fullDescription) { this.time = time; this.shortDescription = shortDescription; this.medDescription = medDescription; this.fullDescription = fullDescription; } } /** * Build a AttributeEventDescription derived from a BlackboardArtifact. This * is a template method that relies on each ArtifactEventType's * implementation of ArtifactEventType#parseAttributesHelper() to know how * to go from BlackboardAttributes to the event description. * * @param type * @param artf the BlackboardArtifact to derive the event description from * * @return an AttributeEventDescription derived from the given artifact, if * the given artifact has no timestamp * * @throws TskCoreException is there is a problem accessing the blackboard * data */ static public AttributeEventDescription buildEventDescription(ArtifactEventType type, BlackboardArtifact artf) throws TskCoreException { //if we got passed an artifact that doesn't correspond to the type of the event, //something went very wrong. throw an exception. if (type.getArtifactTypeID() != artf.getArtifactTypeID()) { throw new IllegalArgumentException(); } if (artf.getAttribute(type.getDateTimeAttributeType()) == null) { LOGGER.log(Level.WARNING, "Artifact {0} has no date/time attribute, skipping it.", artf.getArtifactID()); // NON-NLS return null; } //use the hook provided by this subtype implementation return type.parseAttributesHelper(artf); } static class AttributeExtractor implements Function<BlackboardArtifact, String> { public String apply(BlackboardArtifact artf) { return Optional.ofNullable(getAttributeSafe(artf, attributeType)) .map(BlackboardAttribute::getDisplayString) .map(StringUtils::defaultString) .orElse(""); } private final BlackboardAttribute.Type attributeType; public AttributeExtractor(BlackboardAttribute.Type attribute) { this.attributeType = attribute; } } static class EmptyExtractor implements Function<BlackboardArtifact, String> { @Override public String apply(BlackboardArtifact t) { return ""; } } static BlackboardAttribute getAttributeSafe(BlackboardArtifact artf, BlackboardAttribute.Type attrType) { try { return artf.getAttribute(attrType); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting attribute from artifact {0}.", artf.getArtifactID()), ex); // NON-NLS return null; } } }