diff --git a/bindings/java/jni/auto_db_java.cpp b/bindings/java/jni/auto_db_java.cpp
index 29043b25eff36c4d9ea8c80825da4357819eee6a..625739f8a5a374dc18ef49a0cf983277f1c493c6 100644
--- a/bindings/java/jni/auto_db_java.cpp
+++ b/bindings/java/jni/auto_db_java.cpp
@@ -442,9 +442,49 @@ void extractExtension(char *name, char *extension) {
     }
 }
 
+/**
+* Convert a sequence of characters to a jstring object.
+* We first convert the character sequence to UTF16 and then
+* use the JNI NewString() method to create the jstring.
+* We do it this way because we encountered data that contained
+* 4 byte (or more) UTF8 encoded characters and the JNI NewStringUTF()
+* method does not handle 4 byte UTF8 encoding.
+*
+* @param input The sequence of characters to be turned into a jstring.
+* @param newJString The new jstring object created from the input.
+* @returns TSK_ERR on error, TSK_OK on success
+*/
+TSK_RETVAL_ENUM TskAutoDbJava::createJString(const char * input, jstring & newJString) {
+    size_t input_len = strlen(input) + 1;
+    UTF16 * utf16_input;
+
+    if ((utf16_input = (UTF16 *)tsk_malloc(input_len * sizeof(UTF16))) == NULL) {
+        return TSK_ERR;
+    }
+
+    UTF8 * source = (UTF8 *)input;
+    UTF16 * target = utf16_input;
+
+    if (tsk_UTF8toUTF16((const UTF8 **)&source, (const UTF8 *)&source[input_len], &target, &target[input_len], TSKlenientConversion) != TSKconversionOK) {
+        free(utf16_input);
+        return TSK_ERR;
+    }
+
+    /*
+     * To determine the length of the new string we we subtract the address
+     * of the start of the UTF16 buffer from the address at the end of the 
+     * UTF16 buffer (target is advanced in the call to the conversion routine
+     * above).
+     */
+    newJString = m_jniEnv->NewString(utf16_input, (target - utf16_input) - 1);
+
+    free(utf16_input);
+    return TSK_OK;
+}
+
 /**
 * Adds a file and its associated slack file to database.
-* Does not learn object ID for new files, and files may 
+* Does not learn object ID for new files, and files may
 * not be added to the database immediately.
 *
 * @param fs_file
@@ -530,6 +570,12 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file,
         }
     }
 
+    jstring namej;
+    if (createJString(name, namej) != TSK_OK) {
+        free(name);
+        return TSK_ERR;
+    }
+
     // clean up path
     // +2 = space for leading slash and terminating null
     size_t path_len = strlen(path) + 2;
@@ -541,9 +587,21 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file,
     strncpy(escaped_path, "/", path_len);
     strncat(escaped_path, path, path_len - strlen(escaped_path));
 
-    jstring namej = m_jniEnv->NewStringUTF(name);
-    jstring pathj = m_jniEnv->NewStringUTF(escaped_path);
-    jstring extj = m_jniEnv->NewStringUTF(extension);
+    jstring pathj;
+    if (createJString(escaped_path, pathj) != TSK_OK) {
+        free(name);
+        free(escaped_path);
+        return TSK_ERR;
+    }
+
+    // Escaped path is not needed beyond this point so free it.
+    free(escaped_path);
+
+    jstring extj;
+    if (createJString(extension, extj) != TSK_OK) {
+        free(name);
+        return TSK_ERR;
+    }
 
     /* NTFS uses sequence, otherwise we hash the path. We do this to map to the
     * correct parent folder if there are two from the root dir that eventually point to
@@ -573,6 +631,7 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file,
         (uint64_t)meta_seq, par_meta_addr, par_seqj);
 
     if (ret_val < 0) {
+        free(name);
         return TSK_ERR;
     }
 
@@ -592,8 +651,16 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file,
         if (strlen(extension) > 0) {
             strncat(extension, "-slack", 6);
         }
-        jstring slackNamej = m_jniEnv->NewStringUTF(name);
-        jstring slackExtj = m_jniEnv->NewStringUTF(extension);
+        jstring slackNamej;
+        if (createJString(name, slackNamej) != TSK_OK) {
+            free(name);
+            return TSK_ERR;
+        }
+        jstring slackExtj;
+        if (createJString(extension, slackExtj) != TSK_OK) {
+            free(name);
+            return TSK_ERR;
+        }
         TSK_OFF_T slackSize = fs_attr->nrd.allocsize - fs_attr->nrd.initsize;
 
         // Add slack file to database
@@ -611,12 +678,12 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file,
             (uint64_t)meta_seq, par_meta_addr, par_seqj);
 
         if (ret_val < 0) {
+            free(name);
             return TSK_ERR;
         }
     }
 
     free(name);
-    free(escaped_path);
 
     return TSK_OK;
 }
@@ -739,7 +806,7 @@ TskAutoDbJava::addFileWithLayoutRange(const TSK_DB_FILES_TYPE_ENUM dbFileType, c
         TSK_DB_FILE_LAYOUT_RANGE & range = *it;
         range.fileObjId = objId;
         if (-1 == m_jniEnv->CallLongMethod(m_javaDbObj, m_addLayoutFileRangeMethodID,
-            objId, range.byteStart, range.byteLen, range.sequence)) {
+            objId, range.byteStart, range.byteLen, (uint64_t)range.sequence)) {
             return TSK_ERR;
         }
     }
diff --git a/bindings/java/jni/auto_db_java.h b/bindings/java/jni/auto_db_java.h
index a4a55e509cf2c9cbac9bb8db521e3095e19953d1..f2570cf2294b6ebacd0978857c7a17b672269447 100644
--- a/bindings/java/jni/auto_db_java.h
+++ b/bindings/java/jni/auto_db_java.h
@@ -167,6 +167,8 @@ class TskAutoDbJava :public TskAuto {
     void saveObjectInfo(uint64_t objId, uint64_t parObjId, TSK_DB_OBJECT_TYPE_ENUM type);
     TSK_RETVAL_ENUM getObjectInfo(uint64_t objId, TSK_DB_OBJECT** obj_info);
 
+    TSK_RETVAL_ENUM createJString(const char * inputString, jstring & newJString);
+
     // prevent copying until we add proper logic to handle it
     TskAutoDbJava(const TskAutoDbJava&);
     TskAutoDbJava & operator=(const TskAutoDbJava&);
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
index 16335ea7bdca9678b386461b6e9db36b52ef82ad..1064791a09a0ac80d54e54d12f79cc7fcd79b003 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
+++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
@@ -327,6 +327,7 @@ MiscTypes.GPSTrack.name=GPS Track
 MiscTypes.metadataLastPrinted.name=Document Last Printed
 MiscTypes.metadataLastSaved.name=Document Last Saved
 MiscTypes.metadataCreated.name=Document Created
+MiscTypes.programexecuted.name=Program Execution
 RootEventType.eventTypes.name=Event Types
 WebTypes.webDownloads.name=Web Downloads
 WebTypes.webCookies.name=Web Cookies
diff --git a/bindings/java/src/org/sleuthkit/datamodel/CommunicationsManager.java b/bindings/java/src/org/sleuthkit/datamodel/CommunicationsManager.java
index 43256938eb117da8235ba6bed79571f74a2de43a..0b36732ebc431b944da960470fb1707a5a8fe3c9 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/CommunicationsManager.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/CommunicationsManager.java
@@ -1323,7 +1323,7 @@ public List<Account> getAccountsRelatedToArtifact(BlackboardArtifact artifact) t
 						+ " SELECT DISTINCT (account_id), account_type_id, account_unique_identifier"
 						+ " FROM accounts"
 						+ " JOIN account_relationships ON account2_id = account_id"
-						+ " WHERE relationship_source_obj_id = %d)", artifact.getId(), artifact.getId());
+						+ " WHERE relationship_source_obj_id = %d) AS unionOfRelationships", artifact.getId(), artifact.getId());
 				try (Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery(query)) {
 					while (rs.next()) {
 						Account.Type accountType = null;
diff --git a/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java b/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java
index 0422de29a3774ebc864b896ea03dd692a6696941..8c6c1d545bf191500fcf022558d8af95c3e2e502 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java
@@ -512,7 +512,7 @@ private long addBatchedLayoutRangesToDb() {
                     caseDb.addLayoutFileRangeJNI(range.objId, range.byteStart, range.byteLen, range.seq, trans);
                 } catch (TskCoreException ex) {
                     logger.log(Level.SEVERE, "Error adding layout file range to the database - layout file ID: " + range.objId 
-                        + ", byte start: " + range.byteStart, ex);
+                        + ", byte start: " + range.byteStart + ", length: " + range.byteLen + ", seq: " + range.seq, ex);
                 }
             }
             commitTransaction();
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 3a26e343d1d92a00be16412b0adf2da130d98ef8..3c9ea38d733ae1fcc1ca3093c2fa6199d42d1f73 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -9593,7 +9593,7 @@ public List<TagName> getAllTagNames() throws TskCoreException {
 			resultSet = connection.executeQuery(statement);
 			ArrayList<TagName> tagNames = new ArrayList<>();
 			while (resultSet.next()) {
-				tagNames.add(new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
 			}
@@ -9627,7 +9627,7 @@ public List<TagName> getTagNamesInUse() throws TskCoreException {
 			resultSet = connection.executeQuery(statement);
 			ArrayList<TagName> tagNames = new ArrayList<>();
 			while (resultSet.next()) {
-				tagNames.add(new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
 			}
@@ -9671,7 +9671,7 @@ public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
 			statement.setLong(2, dsObjId);
 			resultSet = connection.executeQuery(statement); //NON-NLS
 			while (resultSet.next()) {
-				tagNames.add(new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
 			}
@@ -9746,8 +9746,8 @@ public TagName addOrUpdateTagName(String displayName, String description, TagNam
 			resultSet = connection.executeQuery(statement);
 			resultSet.next();
 
-			return new TagName(this, tagId,
-					displayName, description, color, knownStatus, resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
+			return new TagName(tagId, displayName, description, color, knownStatus, resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
+			
 		} catch (SQLException ex) {
 			throw new TskCoreException("Error adding row for " + displayName + " tag name to tag_names table", ex);
 		} finally {
@@ -9819,7 +9819,7 @@ public List<ContentTag> getAllContentTags() throws TskCoreException {
 			resultSet = connection.executeQuery(statement);
 			ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
 			while (resultSet.next()) {
-				TagName tagName = new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));  //NON-NLS
 				Content content = getContentById(resultSet.getLong("obj_id")); //NON-NLS
@@ -9949,7 +9949,7 @@ public ContentTag getContentTagByID(long contentTagID) throws TskCoreException {
 			resultSet = connection.executeQuery(statement);
 
 			while (resultSet.next()) {
-				TagName tagName = new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
 				tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")), tagName,
@@ -10085,7 +10085,7 @@ public List<ContentTag> getContentTagsByContent(Content content) throws TskCoreE
 			resultSet = connection.executeQuery(statement);
 			ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
 			while (resultSet.next()) {
-				TagName tagName = new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));  //NON-NLS
 				ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), content, tagName,
@@ -10165,7 +10165,7 @@ public List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCore
 			resultSet = connection.executeQuery(statement);
 			ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
 			while (resultSet.next()) {
-				TagName tagName = new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));  //NON-NLS
 				BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
@@ -10395,7 +10395,7 @@ public BlackboardArtifactTag getBlackboardArtifactTagByID(long artifactTagID) th
 			resultSet = connection.executeQuery(statement);
 
 			while (resultSet.next()) {
-				TagName tagName = new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
 				BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
@@ -10443,7 +10443,7 @@ public List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(Blackboar
 			resultSet = connection.executeQuery(statement);
 			ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
 			while (resultSet.next()) {
-				TagName tagName = new TagName(this, resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
+				TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
 						resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
 						TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));  //NON-NLS
 				Content content = getContentById(artifact.getObjectID());
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TagName.java b/bindings/java/src/org/sleuthkit/datamodel/TagName.java
index 131073bf5f44245861df7f8bdd36f18de86120e7..c514db5ff92fb1a3138bb798faa3272613836a0a 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/TagName.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TagName.java
@@ -1,7 +1,7 @@
 /*
  * Sleuth Kit Data Model
  *
- * Copyright 2011-2018 Basis Technology Corp.
+ * Copyright 2013-2020 Basis Technology Corp.
  * Contact: carrier <at> sleuthkit <dot> org
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +20,6 @@
 
 import java.io.Serializable;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Objects;
 
 /**
@@ -89,10 +88,9 @@ public static HTML_COLOR getColorByName(String colorName) {
 	private final TskData.FileKnown knownStatus;
 	private final long tagSetId;
 	private final int rank;
-	private final SleuthkitCase skCase;
 
 	// Clients of the org.sleuthkit.datamodel package should not directly create these objects.
-	TagName(SleuthkitCase sleuthkitCase, long id, String displayName, String description, HTML_COLOR color, TskData.FileKnown knownStatus, long tagSetId, int rank) {
+	TagName(long id, String displayName, String description, HTML_COLOR color, TskData.FileKnown knownStatus, long tagSetId, int rank) {
 		this.id = id;
 		this.displayName = displayName;
 		this.description = description;
@@ -100,7 +98,6 @@ public static HTML_COLOR getColorByName(String colorName) {
 		this.knownStatus = knownStatus;
 		this.tagSetId = tagSetId;
 		this.rank = rank;
-		this.skCase = sleuthkitCase;
 	}
 
 	public long getId() {
@@ -131,27 +128,6 @@ public int getRank() {
 		return rank;
 	}
 
-	/**
-	 * Returns the TagName TagSet object.
-	 *
-	 * @return TagName TagSet object or null if the TagName is not a part of a
-	 *         TagSet.
-	 *
-	 * @throws TskCoreException
-	 */
-	public TagSet getTagSet() throws TskCoreException {
-		if (tagSetId != 0) {
-			List<TagSet> tagSets = skCase.getTaggingManager().getTagSets();
-			for (TagSet set : tagSets) {
-				if (tagSetId == set.getId()) {
-					return set;
-				}
-			}
-		}
-
-		return null;
-	}
-
 	/**
 	 * Compares two TagName objects by comparing their display names.
 	 *
@@ -185,11 +161,11 @@ public boolean equals(Object obj) {
 			return false;
 		}
 		final TagName other = (TagName) obj;
-		return (this.id == other.id
-				&& Objects.equals(this.displayName, other.displayName)
-				&& Objects.equals(this.description, other.description)
-				&& Objects.equals(this.color, other.color)
-				&& Objects.equals(this.knownStatus, other.knownStatus)
-				&& this.tagSetId == other.tagSetId);
+		return (this.id == other.getId()
+				&& Objects.equals(this.displayName, other.getDisplayName())
+				&& Objects.equals(this.description, other.getDescription())
+				&& Objects.equals(this.color, other.getColor())
+				&& Objects.equals(this.knownStatus, other.getKnownStatus())
+				&& this.tagSetId == other.getTagSetId());
 	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java b/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java
index 97e8b7b4b7a42e1d4b963e9c234104a3f25c3c95..105121d36a611c34fa8a43f69fc3bea34597a5fe 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java
@@ -112,7 +112,7 @@ public TagSet addTagSet(String name, List<TagName> tagNames) throws TskCoreExcep
 					for (int index = 0; index < tagNames.size(); index++) {
 						TagName tagName = tagNames.get(index);
 						stmt.executeUpdate(String.format("UPDATE tag_names SET tag_set_id = %d, rank = %d WHERE tag_name_id = %d", setID, index, tagName.getId()));
-						updatedTags.add(new TagName(skCase, tagName.getId(),
+						updatedTags.add(new TagName(tagName.getId(),
 								tagName.getDisplayName(),
 								tagName.getDescription(),
 								tagName.getColor(),
@@ -173,6 +173,43 @@ public void deleteTagSet(TagSet tagSet) throws TskCoreException {
 		}
 	}
 
+	/**
+	 * Gets the tag set a tag name (tag definition) belongs to, if any.
+	 *
+	 * @param tagName The tag name.
+	 *
+	 * @return A TagSet object or null.
+	 *
+	 * @throws TskCoreException If there is an error querying the case database.
+	 */
+	public TagSet getTagSet(TagName tagName) throws TskCoreException {
+		if (tagName == null) {
+			throw new IllegalArgumentException("Null tagName argument");
+		}
+		
+		if (tagName.getTagSetId() <= 0) {
+			return null;
+		}
+		
+		CaseDbConnection connection = skCase.getConnection();
+		skCase.acquireSingleUserCaseReadLock();
+		TagSet tagSet = null;
+		String sqlQuery = String.format("SELECT * FROM tsk_tag_sets WHERE tag_set_id = %d", tagName.getTagSetId());
+		try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(sqlQuery);) {
+			if (resultSet.next()) {
+				int setID = resultSet.getInt("tag_set_id");
+				String setName = resultSet.getString("name");
+				tagSet = new TagSet(setID, setName, getTagNamesByTagSetID(setID));
+			}
+			return tagSet;
+		} catch (SQLException ex) {
+			throw new TskCoreException(String.format("Error occurred getting TagSet for TagName '%s' (ID=%d)", tagName.getDisplayName(), tagName.getId()), ex);
+		} finally {
+			connection.close();
+			skCase.releaseSingleUserCaseReadLock();
+		}
+	}
+
 	/**
 	 * Inserts a row into the blackboard_artifact_tags table in the case
 	 * database.
@@ -208,7 +245,6 @@ public BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, T
 				try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(selectQuery)) {
 					while (resultSet.next()) {
 						TagName removedTag = new TagName(
-								skCase,
 								resultSet.getLong("tag_name_id"),
 								resultSet.getString("display_name"),
 								resultSet.getString("description"),
@@ -305,7 +341,6 @@ public ContentTagChange addContentTag(Content content, TagName tagName, String c
 				try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(selectQuery)) {
 					while (resultSet.next()) {
 						TagName removedTag = new TagName(
-								skCase,
 								resultSet.getLong("tag_name_id"),
 								resultSet.getString("display_name"),
 								resultSet.getString("description"),
@@ -438,7 +473,7 @@ private List<TagName> getTagNamesByTagSetID(int tagSetId) throws TskCoreExceptio
 		String query = String.format("SELECT * FROM tag_names WHERE tag_set_id = %d", tagSetId);
 		try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(query)) {
 			while (resultSet.next()) {
-				tagNameList.add(new TagName(skCase, resultSet.getLong("tag_name_id"),
+				tagNameList.add(new TagName(resultSet.getLong("tag_name_id"),
 						resultSet.getString("display_name"),
 						resultSet.getString("description"),
 						TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeImpl.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeImpl.java
index 9debfc05d367ae75cae4c770d6322c734eb0cd01..c93a2436e930049531c1f1ac2cc403b346d82844 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeImpl.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeImpl.java
@@ -43,9 +43,9 @@ class TimelineEventArtifactTypeImpl extends TimelineEventTypeImpl {
 	private final TSKCoreCheckedFunction<BlackboardArtifact, String> shortExtractor;
 	private final TSKCoreCheckedFunction<BlackboardArtifact, TimelineEventDescriptionWithTime> artifactParsingFunction;
 
-	private static final int MAX_SHORT_DESCRIPTION_LENGTH = 500;
-	private static final int MAX_MED_DESCRIPTION_LENGTH = 500;
-	private static final int MAX_FULL_DESCRIPTION_LENGTH = 1024;
+	protected static final int MAX_SHORT_DESCRIPTION_LENGTH = 500;
+	protected static final int MAX_MED_DESCRIPTION_LENGTH = 500;
+	protected static final int MAX_FULL_DESCRIPTION_LENGTH = 1024;
 
 	TimelineEventArtifactTypeImpl(int typeID, String displayName,
 			TimelineEventType superType,
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java
index 6f0984dca7fcbf3e20fd94bb73e503c15f6e57bd..84f71ba7db494afe871ab6b6cd69734035b7d696 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java
@@ -33,6 +33,9 @@ class TimelineEventArtifactTypeSingleDescription extends TimelineEventArtifactTy
 	@Override
 	public TimelineEventDescriptionWithTime makeEventDescription(BlackboardArtifact artifact) throws TskCoreException {
 		String description = extractFullDescription(artifact);
+		if (description.length() > MAX_FULL_DESCRIPTION_LENGTH) {
+			description = description.substring(0, MAX_FULL_DESCRIPTION_LENGTH);
+		}
 		BlackboardAttribute timeAttribute = artifact.getAttribute(getDateTimeAttributeType());
 
 		if (timeAttribute == null) {
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java
index 8f99e5af32c36792f65d390f349776e0b42f0aab..87c1d3426deecab0336aa33d041dfb4626906cbe 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java
@@ -224,7 +224,8 @@ public int compare(TimelineEventType o1, TimelineEventType o2) {
 			builder.add(CALL_LOG, DEVICES_ATTACHED, EMAIL,
 					EXIF, GPS_BOOKMARK, GPS_LAST_KNOWN_LOCATION, GPS_TRACKPOINT,
 					GPS_ROUTE, GPS_SEARCH, GPS_TRACK, INSTALLED_PROGRAM, LOG_ENTRY, MESSAGE,
-					METADATA_LAST_PRINTED, METADATA_LAST_SAVED, METADATA_CREATED, RECENT_DOCUMENTS, REGISTRY);
+					METADATA_LAST_PRINTED, METADATA_LAST_SAVED, METADATA_CREATED, PROGRAM_EXECUTION,
+					RECENT_DOCUMENTS, REGISTRY);
 
 			return builder.build();
 		}
@@ -544,7 +545,7 @@ public SortedSet< TimelineEventType> getChildren() {
 			new BlackboardAttribute.Type(TSK_DATETIME_MODIFIED),
             artf -> {return getBundle().getString("MiscTypes.metadataLastSaved.name");},
 	        new EmptyExtractor(),
-	        new EmptyExtractor());
+	       new EmptyExtractor());
 
 	TimelineEventType METADATA_CREATED = new TimelineEventArtifactTypeImpl(35,
 			getBundle().getString("MiscTypes.metadataCreated.name"),// NON-NLS
@@ -554,6 +555,20 @@ public SortedSet< TimelineEventType> getChildren() {
             artf -> {return getBundle().getString("MiscTypes.metadataCreated.name");},
 	        new EmptyExtractor(),
 	        new EmptyExtractor());
+
+	TimelineEventType PROGRAM_EXECUTION = new TimelineEventArtifactTypeImpl(36,
+			getBundle().getString("MiscTypes.programexecuted.name"),// NON-NLS
+			MISC_TYPES,
+			new BlackboardArtifact.Type(TSK_PROG_RUN),
+			new Type(TSK_DATETIME),
+			new AttributeExtractor(new Type(TSK_PROG_NAME)),
+            artf -> {
+	                 String userName = stringValueOf(getAttributeSafe(artf, new Type(TSK_USER_NAME)));
+				     if (userName != null) {
+					    return userName;
+				     }
+	                 return "";},
+			new AttributeExtractor(new Type(TSK_COMMENT)));
 			
 	static SortedSet<? extends TimelineEventType> getCategoryTypes() {
 		return ROOT_EVENT_TYPE.getChildren();
diff --git a/win32/tsk_jni/tsk_jni.vcxproj b/win32/tsk_jni/tsk_jni.vcxproj
index 3e32c21b560a2e1511bbe957f1d3beb23a13520f..05e12e2433604902550a46bf379d5125173a2aaa 100755
--- a/win32/tsk_jni/tsk_jni.vcxproj
+++ b/win32/tsk_jni/tsk_jni.vcxproj
@@ -151,8 +151,8 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;$(ProjectDir)\..\..\tsk\hashdb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_WINDOWS;_USRDLL;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;$(ProjectDir)\..\..\tsk\hashdb;$(LIBEWF_HOME)\include;$(LIBEWF_HOME)\..\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_WINDOWS;_USRDLL;HAVE_LIBEWF;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -182,8 +182,8 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_WINDOWS;_USRDLL;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;$(LIBEWF_HOME)\include;$(LIBEWF_HOME)\..\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_WINDOWS;_USRDLL;HAVE_LIBEWF;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <PrecompiledHeader>
@@ -212,8 +212,8 @@
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;$(ProjectDir)\..\..\tsk\hashdb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;_USRDLL;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;$(ProjectDir)\..\..\tsk\hashdb;$(LIBEWF_HOME)\include;$(LIBEWF_HOME)\..\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;_USRDLL;HAVE_LIBEWF;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <PrecompiledHeader>
@@ -275,8 +275,8 @@
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;_USRDLL;TSK_JNI_EXPORTS;_CRT_SECURE_NO_WARNINGS;WINVER=0x0601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(JDK_HOME)\include;$(JDK_HOME)\include\win32;$(ProjectDir)\..\..;$(LIBEWF_HOME)\include;$(LIBEWF_HOME)\..\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;_USRDLL;TSK_JNI_EXPORTS;HAVE_LIBEWF;_CRT_SECURE_NO_WARNINGS;WINVER=0x0601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <PrecompiledHeader>