diff --git a/bindings/java/jni/auto_db_java.cpp b/bindings/java/jni/auto_db_java.cpp
index 969d87ba117d3a9b4959ad27feb27c116d42b62f..eb009c7d3f80e656ef39259b29e6c02bffff095f 100644
--- a/bindings/java/jni/auto_db_java.cpp
+++ b/bindings/java/jni/auto_db_java.cpp
@@ -79,7 +79,7 @@ TskAutoDbJava::initializeJni(JNIEnv * jniEnv, jobject jobj) {
     }
     m_callbackClass = (jclass)m_jniEnv->NewGlobalRef(localCallbackClass);
 
-    m_addImageMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addImageInfo", "(IJLjava/lang/String;JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J");
+    m_addImageMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addImageInfo", "(IJLjava/lang/String;JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)J");
     if (m_addImageMethodID == NULL) {
         return TSK_ERR;
     }
@@ -184,7 +184,8 @@ TskAutoDbJava::getObjectInfo(uint64_t objId, TSK_DB_OBJECT** obj_info) {
 */
 TSK_RETVAL_ENUM
 TskAutoDbJava::addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const string & timezone, TSK_OFF_T size, const string &md5,
-    const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails) {
+    const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails,
+    char** img_ptrs, int num_imgs) {
 
     const char *tz_cstr = timezone.c_str();
     jstring tzj = m_jniEnv->NewStringUTF(tz_cstr);
@@ -204,8 +205,18 @@ TskAutoDbJava::addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const st
     const char *coll_cstr = collectionDetails.c_str();
     jstring collj = m_jniEnv->NewStringUTF(coll_cstr);
 
+    jobjectArray imgNamesj = (jobjectArray)m_jniEnv->NewObjectArray(
+        num_imgs,
+        m_jniEnv->FindClass("java/lang/String"),
+        m_jniEnv->NewStringUTF(""));
+
+    for (int i = 0; i < num_imgs; i++) {
+        m_jniEnv->SetObjectArrayElement(
+            imgNamesj, i, m_jniEnv->NewStringUTF(img_ptrs[i]));
+    }
+
     jlong objIdj = m_jniEnv->CallLongMethod(m_javaDbObj, m_addImageMethodID,
-        type, ssize, tzj, size, md5j, sha1j, sha256j, devIdj, collj);
+        type, ssize, tzj, size, md5j, sha1j, sha256j, devIdj, collj, imgNamesj);
     objId = (int64_t)objIdj;
 
     if (objId < 0) {
@@ -1003,13 +1014,6 @@ TskAutoDbJava::addImageDetails(const char* deviceId)
     } else {
         devId = "";
     }
-    if (TSK_OK != addImageInfo(m_img_info->itype, m_img_info->sector_size,
-          m_curImgId, m_curImgTZone, m_img_info->size, md5, sha1, "", devId, collectionDetails)) {
-        registerError();
-        return 1;
-    }
-
-
 
     char **img_ptrs;
 #ifdef TSK_WIN32
@@ -1043,14 +1047,12 @@ TskAutoDbJava::addImageDetails(const char* deviceId)
     img_ptrs = m_img_info->images;
 #endif
 
-    // Add the image names
-    for (int i = 0; i < m_img_info->num_img; i++) {
-        const char *img_ptr = img_ptrs[i];
 
-        if (TSK_OK != addImageName(m_curImgId, img_ptr, i)) {
-            registerError();
-            return 1;
-        }
+    if (TSK_OK != addImageInfo(m_img_info->itype, m_img_info->sector_size,
+        m_curImgId, m_curImgTZone, m_img_info->size, md5, sha1, "", devId, collectionDetails,
+        img_ptrs, m_img_info->num_img)) {
+        registerError();
+        return 1;
     }
 
 #ifdef TSK_WIN32
diff --git a/bindings/java/jni/auto_db_java.h b/bindings/java/jni/auto_db_java.h
index e6c5e68dd7217d784695749cf53c24df090db75d..a4a55e509cf2c9cbac9bb8db521e3095e19953d1 100644
--- a/bindings/java/jni/auto_db_java.h
+++ b/bindings/java/jni/auto_db_java.h
@@ -204,7 +204,7 @@ class TskAutoDbJava :public TskAuto {
 
     // JNI methods
     TSK_RETVAL_ENUM addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const string & timezone, TSK_OFF_T size, const string &md5,
-        const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails);
+        const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails, char** img_ptrs, int num_imgs);
     TSK_RETVAL_ENUM addImageName(int64_t objId, char const* imgName, int sequence);
     TSK_RETVAL_ENUM addVsInfo(const TSK_VS_INFO* vs_info, int64_t parObjId, int64_t& objId);
     TSK_RETVAL_ENUM addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId);
diff --git a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java
index cac2fc8435543679410a72ba88f40fa568dc4388..cd0c5d447b5767173ef684d4554cfb511ea049c4 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java
@@ -24,9 +24,9 @@
  *
  */
 public interface AddDataSourceCallbacks {
-	void onDataSourceAdded(long dataSourceObjectId) throws AddDataSourceCallbackException;
+	void onDataSourceAdded(long dataSourceObjectId) throws AddDataSourceCallbacksException;
 	
-	void onFilesAdded(List<Long> fileObjectIds) throws AddDataSourceCallbackException;
+	void onFilesAdded(List<Long> fileObjectIds) throws AddDataSourceCallbacksException;
 	
-	void onCompleted() throws AddDataSourceCallbackException;
+	void onCompleted() throws AddDataSourceCallbacksException;
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbackException.java b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacksException.java
similarity index 83%
rename from bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbackException.java
rename to bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacksException.java
index 3fa66664177850deea8ae7b258aa9531dfaaa3e5..108fd54bc2361c0f1093f57a22b92425c8fc2bf2 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbackException.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacksException.java
@@ -21,13 +21,13 @@
 /**
  *
  */
-public class AddDataSourceCallbackException extends TskException {
+public class AddDataSourceCallbacksException extends TskException {
 		private static final long serialVersionUID = 123049876L;
 
 	/**
 	 * Default constructor when error message is not available
 	 */
-	public AddDataSourceCallbackException() {
+	public AddDataSourceCallbacksException() {
 		super("No error message available.");
 	}
 
@@ -36,7 +36,7 @@ public AddDataSourceCallbackException() {
 	 *
 	 * @param msg the message
 	 */
-	public AddDataSourceCallbackException(String msg) {
+	public AddDataSourceCallbacksException(String msg) {
 		super(msg);
 	}
 
@@ -46,7 +46,7 @@ public AddDataSourceCallbackException(String msg) {
 	 * @param msg the message
 	 * @param ex  cause exception
 	 */
-	public AddDataSourceCallbackException(String msg, Exception ex) {
+	public AddDataSourceCallbacksException(String msg, Exception ex) {
 		super(msg, ex);
 	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java b/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java
index b65ad77b136adda0578a7bce53ed9b2f56945902..0f15f6e72602fa3c30ecfe77a50b0bc09b830d23 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java
@@ -40,6 +40,7 @@ class JniDbHelper {
     
     private final SleuthkitCase caseDb;
     private CaseDbTransaction trans = null;
+	AddDataSourceCallbacks addDataSourceCallbacks;
     
     private final Map<Long, Long> fsIdToRootDir = new HashMap<>();
     private final Map<Long, TskData.TSK_FS_TYPE_ENUM> fsIdToFsType = new HashMap<>();
@@ -51,6 +52,13 @@ class JniDbHelper {
     
     JniDbHelper(SleuthkitCase caseDb) {
         this.caseDb = caseDb;
+        trans = null;
+		addDataSourceCallbacks = null;
+    }
+	
+	JniDbHelper(SleuthkitCase caseDb, AddDataSourceCallbacks addDataSourceCallbacks) {
+        this.caseDb = caseDb;
+		this.addDataSourceCallbacks = addDataSourceCallbacks;
         trans = null;
     }
     
@@ -114,18 +122,30 @@ void finish() {
      */
     long addImageInfo(int type, long ssize, String timezone, 
             long size, String md5, String sha1, String sha256, String deviceId, 
-            String collectionDetails) {    
+            String collectionDetails, String[] paths) {    
         try {
             beginTransaction();
             long objId = caseDb.addImageJNI(TskData.TSK_IMG_TYPE_ENUM.valueOf(type), ssize, size,
                     timezone, md5, sha1, sha256, deviceId, collectionDetails, trans);
+			for (int i = 0;i < paths.length;i++) {
+				caseDb.addImageNameJNI(objId, paths[i], i, trans);
+			}
             commitTransaction();
+			
+			if (addDataSourceCallbacks != null) {
+				try {
+					addDataSourceCallbacks.onDataSourceAdded(objId); 
+				} catch (AddDataSourceCallbacksException ex) {
+					logger.log(Level.SEVERE, "Error adding data source to ingest stream");
+					return -1;
+				}
+			}
             return objId;
         } catch (TskCoreException ex) {
             logger.log(Level.SEVERE, "Error adding image to the database", ex);
             revertTransaction();
             return -1;
-        } 
+        }
     }
     
     /**
@@ -339,6 +359,7 @@ long addFile(long parentObjId,
      * @return 0 if successful, -1 if not
      */
     private long addBatchedFilesToDb() {
+		List<Long> newObjIds = new ArrayList<>();
         try {
             beginTransaction();
             for (FileInfo fileInfo : batchedFiles) {
@@ -361,6 +382,7 @@ private long addBatchedFilesToDb() {
                         null, TskData.FileKnown.UNKNOWN,
                         fileInfo.escaped_path, fileInfo.extension, 
                         false, trans);
+					newObjIds.add(objId);
 
                     // If we're adding the root directory for the file system, cache it
                     if (fileInfo.parentObjId == fileInfo.fsObjId) {
@@ -385,6 +407,15 @@ private long addBatchedFilesToDb() {
                 }
             }
             commitTransaction();
+			
+			if (addDataSourceCallbacks != null) {
+				try {
+					addDataSourceCallbacks.onFilesAdded(newObjIds);
+				} catch (AddDataSourceCallbacksException ex) {
+					logger.log(Level.SEVERE, "Error adding files to ingest stream");
+					return -1;
+				}
+			}
         } catch (TskCoreException ex) {
             logger.log(Level.SEVERE, "Error adding batched files to database", ex);
             revertTransaction();
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
index 4fe44e69095ea9e9a78621ed570f2a5b3417896d..50b332524e61127e04675192acab56ec6c37c18b 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
@@ -470,7 +470,7 @@ public class AddImageProcess {
 			private volatile long tskAutoDbPointer;
 			private boolean isCanceled;
 			private final SleuthkitCase skCase;
-			private final JniDbHelper dbHelper;
+			private JniDbHelper dbHelper;
 
 			/**
 			 * Constructs an object that encapsulates a multi-step process to
@@ -493,7 +493,7 @@ private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFa
 				tskAutoDbPointer = 0;
 				this.isCanceled = false;
 				this.skCase = skCase;
-				this.dbHelper = new JniDbHelper(skCase);
+				
 			}
 
 			/**
@@ -515,6 +515,7 @@ private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFa
 			 *                          the process)
 			 */
 			public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws TskCoreException, TskDataException {
+				dbHelper = new JniDbHelper(skCase);
 				getTSKReadLock();
 				try {
 					long imageHandle = 0;
@@ -537,6 +538,50 @@ public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws
 					releaseTSKReadLock();
 				}
 			}
+			
+			/**
+			 * Starts the process of adding an image to the case database.
+			 * Either AddImageProcess.commit or AddImageProcess.revert MUST be
+			 * called after calling AddImageProcess.run.
+			 *
+			 * @param deviceId       An ASCII-printable identifier for the
+			 *                       device associated with the image that
+			 *                       should be unique across multiple cases
+			 *                       (e.g., a UUID).
+			 * @param imageFilePaths Full path(s) to the image file(s).
+			 * @param sectorSize     The sector size (use '0' for autodetect).
+			 *
+			 * @throws TskCoreException if a critical error occurs within the
+			 *                          SleuthKit.
+			 * @throws TskDataException if a non-critical error occurs within
+			 *                          the SleuthKit (should be OK to continue
+			 *                          the process)
+			 */
+			public void run(String deviceId, String[] imageFilePaths, int sectorSize, 
+					AddDataSourceCallbacks addDataSourceCallbacks) throws TskCoreException, TskDataException {
+				dbHelper = new JniDbHelper(skCase, addDataSourceCallbacks);
+				getTSKReadLock();
+				try {
+					long imageHandle = 0;
+					synchronized (this) {
+						if (0 != tskAutoDbPointer) {
+							throw new TskCoreException("Add image process already started");
+						}
+						if (!isCanceled) { //with isCanceled being guarded by this it will have the same value everywhere in this synchronized block
+							imageHandle = openImage(imageFilePaths, sectorSize, false, caseDbIdentifier);
+							tskAutoDbPointer = initAddImgNat(dbHelper, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans);
+						}
+						if (0 == tskAutoDbPointer) {
+							throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer");
+						}
+					}
+					if (imageHandle != 0) {
+						runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, imageWriterPath);
+					}
+				} finally {
+					releaseTSKReadLock();
+				}
+			}			
 
 			/**
 			 * Stops the process of adding the image to the case database that
@@ -597,7 +642,9 @@ public synchronized long commit() throws TskCoreException {
 						throw new TskCoreException("AddImgProcess::commit: AutoDB pointer is NULL");
 					}
 
-					dbHelper.finish();
+					if (dbHelper != null) {
+						dbHelper.finish();
+					}
 
 					// Get the image ID and delete the object in the native code
 					long id = finishAddImgNat(tskAutoDbPointer);