diff --git a/bindings/java/jni/auto_db_java.cpp b/bindings/java/jni/auto_db_java.cpp
index 8df2bd647973cf963166ef56261d49d0a465a4d3..85e81370c3d4aeac3ba979db188cc99bcffc1cbe 100644
--- a/bindings/java/jni/auto_db_java.cpp
+++ b/bindings/java/jni/auto_db_java.cpp
@@ -14,6 +14,7 @@
  */
 
 #include "auto_db_java.h"
+#include "jni.h"
 #include "tsk/img/img_writer.h"
 #if HAVE_LIBEWF
 #include "tsk/img/ewf.h"
@@ -50,6 +51,9 @@ TskAutoDbJava::TskAutoDbJava()
     m_addUnallocSpace = false;
     m_minChunkSize = -1;
     m_maxChunkSize = -1;
+
+    m_jniEnv = NULL;
+
     tsk_init_lock(&m_curDirPathLock);
 }
 
@@ -59,77 +63,162 @@ TskAutoDbJava::~TskAutoDbJava()
     tsk_deinit_lock(&m_curDirPathLock);
 }
 
+TSK_RETVAL_ENUM
+TskAutoDbJava::initializeJni(JNIEnv * jniEnv, jobject jobj) {
+    m_jniEnv = jniEnv;
+    m_javaDbObj = m_jniEnv->NewGlobalRef(jobj); // TODO free this
+
+    printf("\n#### initializeJni\n");
+    fflush(stdout);
+
+    jclass localCallbackClass = m_jniEnv->FindClass("org/sleuthkit/datamodel/JniDbHelper");
+    if (localCallbackClass == NULL) {
+        return TSK_ERR;
+    }
+    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");
+    if (m_addImageMethodID == NULL) {
+        printf("#### Error loading m_addImageMethodID\n");
+        fflush(stdout);
+        return TSK_ERR;
+    }
+
+    m_addImageNameMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addImageName", "(JLjava/lang/String;J)I");
+    if (m_addImageNameMethodID == NULL) {
+        printf("#### Error loading m_addImageNameMethodID\n");
+        fflush(stdout);
+        return TSK_ERR;
+    }
+
+    printf("\n#### Yay found method IDs!\n");
+    fflush(stdout);
+    return TSK_OK;
+}
 
 ////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////
 
-int64_t
-addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const string & timezone, TSK_OFF_T size, const string &md5,
+
+
+
+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) {
-    printf("addImageInfo2\n");
-    return 2;
+
+    printf("addImageInfo - preparing all the jstrings\n");
+    fflush(stdout);
+
+    const char *tz_cstr = timezone.c_str();
+    jstring tzj = m_jniEnv->NewStringUTF(tz_cstr);
+
+    const char *md5_cstr = md5.c_str();
+    jstring md5j = m_jniEnv->NewStringUTF(md5_cstr);
+
+    const char *sha1_cstr = sha1.c_str();
+    jstring sha1j = m_jniEnv->NewStringUTF(sha1_cstr);
+
+    const char *sha256_cstr = sha256.c_str();
+    jstring sha256j = m_jniEnv->NewStringUTF(sha256_cstr);
+
+    const char *devId_cstr = deviceId.c_str();
+    jstring devIdj = m_jniEnv->NewStringUTF(devId_cstr);
+
+    const char *coll_cstr = collectionDetails.c_str();
+    jstring collj = m_jniEnv->NewStringUTF(coll_cstr);
+    // TODO TODO free strings?
+
+    printf("addImageInfo - making JNI call\n");
+    fflush(stdout);
+
+    if (m_addImageMethodID == NULL) {
+        printf("#### Yikes addImageMethodID is null...\n");
+        return TSK_ERR;
+    }
+
+    jlong objIdj = m_jniEnv->CallLongMethod(m_javaDbObj, m_addImageMethodID,
+        jint(type), jlong(ssize), tzj, jlong(size), md5j, sha1j, sha256j, devIdj, collj);
+    objId = (int64_t)objIdj;
+
+    return TSK_OK;
 }
 
-int64_t
-addImageName(int64_t objId, char const* imgName, int sequence) {
+TSK_RETVAL_ENUM
+TskAutoDbJava::addImageName(int64_t objId, char const* imgName, int sequence) {
     printf("addImageName\n");
-    return 3;
+
+    if (m_addImageNameMethodID == NULL) {
+        printf("#### Yikes m_addImageNameMethodID is null...\n");
+        return TSK_ERR;
+    }
+
+    jstring imgNamej = m_jniEnv->NewStringUTF(imgName);
+
+    jint res = m_jniEnv->CallIntMethod(m_javaDbObj, m_addImageNameMethodID,
+        jlong(objId), imgNamej, jlong(sequence));
+
+    if (res == 0) {
+        return TSK_OK;
+    }
+    else {
+        return TSK_ERR;
+    }
 }
 
-int64_t
-addVsInfo(const TSK_VS_INFO* vs_info, int64_t parObjId, int64_t& objId) {
-    printf("addImageName\n");
-    return 4;
+TSK_RETVAL_ENUM
+TskAutoDbJava::addVsInfo(const TSK_VS_INFO* vs_info, int64_t parObjId, int64_t& objId) {
+    printf("addVsInfo\n");
+    return TSK_OK;
 }
 
-int64_t
-addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) {
+TSK_RETVAL_ENUM
+TskAutoDbJava::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) {
     printf("addPoolInfoAndVS\n");
-    return 5;
+    return TSK_OK;
 }
 
-int64_t
-addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
+TSK_RETVAL_ENUM
+TskAutoDbJava::addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
     int64_t parObjId, int64_t& objId) {
     printf("addPoolVolumeInfo\n");
-    return 6;
+    return TSK_OK;
 }
 
 
-int64_t
-addVolumeInfo(const TSK_VS_PART_INFO* vs_part,
+TSK_RETVAL_ENUM
+TskAutoDbJava::addVolumeInfo(const TSK_VS_PART_INFO* vs_part,
     int64_t parObjId, int64_t& objId) {
     printf("addVolumeInfo\n");
-    return 7;
+    return TSK_OK;
 }
 
-int64_t
-addFsInfo(const TSK_FS_INFO* fs_info, int64_t parObjId,
+TSK_RETVAL_ENUM
+TskAutoDbJava::addFsInfo(const TSK_FS_INFO* fs_info, int64_t parObjId,
     int64_t& objId) {
     printf("addFsInfo\n");
-    return 8;
+    return TSK_OK;
 }
 
-int64_t
-addFsFile(TSK_FS_FILE* fs_file,
+TSK_RETVAL_ENUM
+TskAutoDbJava::addFsFile(TSK_FS_FILE* fs_file,
     const TSK_FS_ATTR* fs_attr, const char* path,
     const unsigned char*const md5, const TSK_DB_FILES_KNOWN_ENUM known,
     int64_t fsObjId, int64_t& objId, int64_t dataSourceObjId) {
 
     printf("addFsFile\n");
-    return 9;
+    return TSK_OK;
 }
 
-int64_t
+TSK_RETVAL_ENUM
 addFileWithLayoutRange(const TSK_DB_FILES_TYPE_ENUM dbFileType, const int64_t parentObjId,
     const int64_t fsObjId, const uint64_t size,
     vector<TSK_DB_FILE_LAYOUT_RANGE>& ranges, int64_t& objId,
     int64_t dataSourceObjId) {
     printf("addFileWithLayoutRange\n");
-    return 10;
+    return TSK_OK;
 }
 
-int64_t
+TSK_RETVAL_ENUM
 addUnallocBlockFile(const int64_t parentObjId, const int64_t fsObjId, const uint64_t size,
     vector<TSK_DB_FILE_LAYOUT_RANGE>& ranges, int64_t& objId,
     int64_t dataSourceObjId) {
@@ -138,7 +227,7 @@ addUnallocBlockFile(const int64_t parentObjId, const int64_t fsObjId, const uint
         dataSourceObjId);
 }
 
-int64_t
+TSK_RETVAL_ENUM
 addUnusedBlockFile(const int64_t parentObjId, const int64_t fsObjId, const uint64_t size,
     vector<TSK_DB_FILE_LAYOUT_RANGE>& ranges, int64_t& objId,
     int64_t dataSourceObjId) {
@@ -149,11 +238,11 @@ addUnusedBlockFile(const int64_t parentObjId, const int64_t fsObjId, const uint6
 
 
 
-int64_t
-addUnallocFsBlockFilesParent(const int64_t fsObjId, int64_t& objId,
+TSK_RETVAL_ENUM
+TskAutoDbJava::addUnallocFsBlockFilesParent(const int64_t fsObjId, int64_t& objId,
     int64_t dataSourceObjId) {
     printf("addUnallocFsBlockfilesParent\n");
-    return 11;
+    return TSK_OK;
 }
 
 
@@ -237,7 +326,6 @@ uint8_t
     TSK_IMG_TYPE_ENUM a_type, unsigned int a_ssize, const char* a_deviceId)
 {
 
-// make name of database
 #ifdef TSK_WIN32
 
     uint8_t retval = TskAuto::openImage(a_num, a_images, a_type, a_ssize);
@@ -301,12 +389,14 @@ TskAutoDbJava::addImageDetails(const char* deviceId)
     } else {
         devId = "";
     }
-    if (-1 == addImageInfo(m_img_info->itype, m_img_info->sector_size,
+    if (TSK_ERR == 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
     // convert image paths to UTF-8
@@ -356,8 +446,10 @@ TskAutoDbJava::addImageDetails(const char* deviceId)
     }
     free(img_ptrs);
 #endif
-
-    return 0;
+    printf("Returning error from end of addImageDetails\n"); // TODO TODO
+    fflush(stdout);
+    return 1;
+    //return 0;
 }
 
 
@@ -505,6 +597,8 @@ TSK_RETVAL_ENUM
  */
 uint8_t TskAutoDbJava::addFilesInImgToDb()
 {
+    printf("\n#### addFilesInImgToDb...\n");
+    fflush(stdout);
 
     // @@@ This seems bad because we are overriding what the user may
     // have set. We should remove the public API if we are going to 
diff --git a/bindings/java/jni/auto_db_java.h b/bindings/java/jni/auto_db_java.h
index 61132c24508e2974914bd22e4882f0e93df0589d..d6c53854b0172212aaa057c81b998e6e95dc2eef 100644
--- a/bindings/java/jni/auto_db_java.h
+++ b/bindings/java/jni/auto_db_java.h
@@ -22,6 +22,7 @@ using std::string;
 
 #include "tsk/auto/tsk_auto_i.h"
 #include "tsk/auto/tsk_db.h"
+#include "jni.h"
 
 
 /** \internal
@@ -109,6 +110,8 @@ class TskAutoDbJava :public TskAuto {
 #endif
     void stopAddImage();
 
+    TSK_RETVAL_ENUM initializeJni(JNIEnv *, jobject);
+
   private:
     int64_t m_curImgId;     ///< Object ID of image currently being processed
     int64_t m_curVsId;      ///< Object ID of volume system currently being processed
@@ -134,6 +137,14 @@ class TskAutoDbJava :public TskAuto {
     bool m_foundStructure;  ///< Set to true when we find either a volume or file system
     bool m_attributeAdded; ///< Set to true when an attribute was added by processAttributes
 
+    // JNI data
+    JNIEnv * m_jniEnv;
+    jclass m_callbackClass;
+    jobject m_javaDbObj;
+    jmethodID m_addImageMethodID = NULL;
+    jmethodID m_addImageNameMethodID = NULL;
+
+
     // prevent copying until we add proper logic to handle it
     TskAutoDbJava(const TskAutoDbJava&);
     TskAutoDbJava & operator=(const TskAutoDbJava&);
@@ -163,7 +174,6 @@ class TskAutoDbJava :public TskAuto {
     static TSK_WALK_RET_ENUM md5HashCallback(TSK_FS_FILE * file,
         TSK_OFF_T offset, TSK_DADDR_T addr, char *buf, size_t size,
         TSK_FS_BLOCK_FLAG_ENUM a_flags, void *ptr);
-    int md5HashAttr(unsigned char md5Hash[16], const TSK_FS_ATTR * fs_attr);
 
     static TSK_WALK_RET_ENUM fsWalkUnallocBlocksCb(const TSK_FS_BLOCK *a_block, void *a_ptr);
     TSK_RETVAL_ENUM addFsInfoUnalloc(const TSK_DB_FS_INFO & dbFsInfo);
@@ -172,6 +182,31 @@ class TskAutoDbJava :public TskAuto {
     TSK_RETVAL_ENUM addUnallocImageSpaceToDb();
     TSK_RETVAL_ENUM addUnallocSpaceToDb();
 
+    // 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);
+    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);
+    TSK_RETVAL_ENUM addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol, int64_t parObjId, int64_t& objId);
+    TSK_RETVAL_ENUM addVolumeInfo(const TSK_VS_PART_INFO* vs_part, int64_t parObjId, int64_t& objId);
+    TSK_RETVAL_ENUM addFsInfo(const TSK_FS_INFO* fs_info, int64_t parObjId, int64_t& objId);
+    TSK_RETVAL_ENUM addFsFile(TSK_FS_FILE* fs_file,
+        const TSK_FS_ATTR* fs_attr, const char* path,
+        const unsigned char*const md5, const TSK_DB_FILES_KNOWN_ENUM known,
+        int64_t fsObjId, int64_t& objId, int64_t dataSourceObjId);
+    //TSK_RETVAL_ENUM addFileWithLayoutRange(const TSK_DB_FILES_TYPE_ENUM dbFileType, const int64_t parentObjId,
+    //    const int64_t fsObjId, const uint64_t size,
+    //    vector<TSK_DB_FILE_LAYOUT_RANGE>& ranges, int64_t& objId,
+    //    int64_t dataSourceObjId);
+    //TSK_RETVAL_ENUM addUnallocBlockFile(const int64_t parentObjId, const int64_t fsObjId, const uint64_t size,
+    //    vector<TSK_DB_FILE_LAYOUT_RANGE>& ranges, int64_t& objId,
+    //    int64_t dataSourceObjId);
+    //TSK_RETVAL_ENUM addUnusedBlockFile(const int64_t parentObjId, const int64_t fsObjId, const uint64_t size,
+    //    vector<TSK_DB_FILE_LAYOUT_RANGE>& ranges, int64_t& objId,
+    //    int64_t dataSourceObjId);
+    TSK_RETVAL_ENUM addUnallocFsBlockFilesParent(const int64_t fsObjId, int64_t& objId, int64_t dataSourceObjId);
+
 };
 
 #endif
diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
index 3cb66fb24b45e70b597b7913742d4bdc6ebcc758..b5319122ba074ec5cfcd8e9ad58524aff7ad7618 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
@@ -962,8 +962,8 @@ JNIEXPORT jobject JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookup
  */
 JNIEXPORT jlong JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_initAddImgNat(JNIEnv * env,
-    jclass obj, jlong caseHandle, jstring timeZone, jboolean addUnallocSpace, jboolean skipFatFsOrphans) {
-    return Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat(env, obj, caseHandle, timeZone, true, addUnallocSpace, skipFatFsOrphans);
+    jclass obj, jlong caseHandle, jobject callbackObj, jstring timeZone, jboolean addUnallocSpace, jboolean skipFatFsOrphans) {
+    return Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat(env, obj, caseHandle, callbackObj, timeZone, true, addUnallocSpace, skipFatFsOrphans);
 }
 
 /*
@@ -981,7 +981,7 @@ JNIEXPORT jlong JNICALL
  */
 JNIEXPORT jlong JNICALL
 Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat(JNIEnv * env, jclass obj,
-    jlong caseHandle, jstring timeZone, jboolean addFileSystems, jboolean addUnallocSpace, jboolean skipFatFsOrphans) {
+    jlong caseHandle, jobject callbackObj, jstring timeZone, jboolean addFileSystems, jboolean addUnallocSpace, jboolean skipFatFsOrphans) {
     jboolean isCopy;
 
     //TskCaseDb *tskCase = castCaseDb(env, caseHandle);
@@ -1039,6 +1039,15 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat(JNIEnv * env, jcla
         tskAutoJava->setNoFatFsOrphans(true);
     }
 
+    // Set up the callbacks
+    if (TSK_ERR == tskAutoJava->initializeJni(env, callbackObj)) {
+        setThrowTskCoreError(env, "Error creating TskAutoDbJava");
+        return 0;
+    }
+
+    printf("\n#### initializeAddImgNat is returning TskAutoDbJava pointer 0x%x\n", tskAutoJava);
+    fflush(stdout);
+
     return (jlong)tskAutoJava;
 }
 
@@ -1059,10 +1068,10 @@ JNIEXPORT void JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_runOpenAndAddImgNat(JNIEnv * env,
     jclass obj, jlong process, jstring deviceId, jobjectArray paths, jint numImgs, jstring timeZone) {
 
-    TskAutoDb *tskAuto = ((TskAutoDb *) process);
+    TskAutoDbJava *tskAuto = ((TskAutoDbJava *) process);
     if (!tskAuto || tskAuto->m_tag != TSK_AUTO_TAG) {
         setThrowTskCoreError(env, 
-            "runAddImgNat: Invalid TskAutoDb object passed in");
+            "runAddImgNat: Invalid TskAutoDbJava object passed in");
         return;
     }
 
@@ -1107,6 +1116,8 @@ JNIEXPORT void JNICALL
     uint8_t ret = 0;
     if ( (ret = tskAuto->startAddImage((int) numImgs, imagepaths8,
         TSK_IMG_TYPE_DETECT, 0, device_id)) != 0) {
+        printf("runOpenAndAddImgNat - startAddImage finished with errors\n");
+        fflush(stdout);
         stringstream msgss;
         msgss << "Errors occurred while ingesting image " << std::endl;
         vector<TskAuto::error_record> errors = tskAuto->getErrorList();
@@ -1121,14 +1132,16 @@ JNIEXPORT void JNICALL
             setThrowTskCoreError(env, msgss.str().c_str());
         }
         else if (ret == 2) {
-            if(tskAuto->isDbOpen()) {
+            // TODO TODO
+            setThrowTskCoreError(env, msgss.str().c_str());
+            /*if(tskAuto->isDbOpen()) {
                 // if we can still talk to the database, it's a non-fatal error
                 setThrowTskDataError(env, msgss.str().c_str());
             }
             else {
                 // we cannot talk to the database, fatal error
                 setThrowTskCoreError(env, msgss.str().c_str());
-            }
+            }*/
         }
     }
 
@@ -1166,10 +1179,12 @@ JNIEXPORT void JNICALL
 Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env,
     jclass obj, jlong process, jstring deviceId, jlong a_img_info, jstring timeZone, jstring imageWriterPathJ) {
     
-    TskAutoDb *tskAuto = ((TskAutoDb *)process);
+    printf("\n#### runAddImgNat has TskAutoDbJava pointer 0x%x\n", process);
+    fflush(stdout);
+    TskAutoDbJava *tskAuto = ((TskAutoDbJava *)process);
     if (!tskAuto || tskAuto->m_tag != TSK_AUTO_TAG) {
         setThrowTskCoreError(env,
-            "runAddImgNat: Invalid TskAutoDb object passed in");
+            "runAddImgNat: Invalid TskAutoDbJava object passed in");
         return;
     }
 
@@ -1211,9 +1226,15 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env,
     // Add the data source.
     uint8_t ret = 0;
     if ((ret = tskAuto->startAddImage(img_info, device_id)) != 0) {
+        printf("runAddImgNat - startAddImage finished with errors\n");
+        fflush(stdout);
         stringstream msgss;
         msgss << "Errors occurred while ingesting image " << std::endl;
+        printf("runAddImgNat - calling getErrorList\n");
+        fflush(stdout);
         vector<TskAuto::error_record> errors = tskAuto->getErrorList();
+        printf("runAddImgNat - error list has size %d\n", errors.size());
+        fflush(stdout);
         for (size_t i = 0; i < errors.size(); i++) {
             msgss << (i + 1) << ". ";
             msgss << (TskAuto::errorRecordToString(errors[i]));
@@ -1225,6 +1246,9 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env,
             setThrowTskCoreError(env, msgss.str().c_str());
         }
         else if (ret == 2) {
+            // TODO TODO
+            setThrowTskCoreError(env, msgss.str().c_str());
+            /*
             if (tskAuto->isDbOpen()) {
                 // if we can still talk to the database, it's a non-fatal error
                 setThrowTskDataError(env, msgss.str().c_str());
@@ -1232,18 +1256,24 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env,
             else {
                 // we cannot talk to the database, fatal error
                 setThrowTskCoreError(env, msgss.str().c_str());
-            }
+            }*/
         }
     }
 
     // @@@ SHOULD WE CLOSE HERE before we commit / revert etc.
     //close image first before freeing the image paths
+    printf("runAddImgNat - closing image\n");
+    fflush(stdout);
     tskAuto->closeImage();
 
     // Cleanup
+    printf("runAddImgNat - cleanup\n");
+    fflush(stdout);
     env->ReleaseStringUTFChars(deviceId, (const char *)device_id);
 
     // if process completes successfully, must call revertAddImgNat or commitAddImgNat to free the TskAutoDb
+    printf("runAddImgNat - returning\n");
+    fflush(stdout);
 }
 
 
@@ -2145,7 +2175,7 @@ JNIEXPORT jstring JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_getCurDirNat
     (JNIEnv * env,jclass obj, jlong dbHandle)
 {
-    TskAutoDb *tskAuto = ((TskAutoDb *) dbHandle);
+    TskAutoDbJava *tskAuto = ((TskAutoDbJava *) dbHandle);
     const std::string curDir = tskAuto->getCurDir();
     jstring jdir = (*env).NewStringUTF(curDir.c_str());
     return jdir;
diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h
index a724200b043d2b21660a5b55e72e3a72a3e6b8c7..a0532dfe7a71b758ed3f9586fd793e0ae3f0af75 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.h
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.h
@@ -210,18 +210,18 @@ JNIEXPORT jobject JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookup
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
  * Method:    initAddImgNat
- * Signature: (JLjava/lang/String;ZZ)J
+ * Signature: (JLorg/sleuthkit/datamodel/JniDbHelper;Ljava/lang/String;ZZ)J
  */
 JNIEXPORT jlong JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_initAddImgNat
-  (JNIEnv *, jclass, jlong, jstring, jboolean, jboolean);
+  (JNIEnv *, jclass, jlong, jobject, jstring, jboolean, jboolean);
 
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
  * Method:    initializeAddImgNat
- * Signature: (JLjava/lang/String;ZZZ)J
+ * Signature: (JLorg/sleuthkit/datamodel/JniDbHelper;Ljava/lang/String;ZZZ)J
  */
 JNIEXPORT jlong JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat
-  (JNIEnv *, jclass, jlong, jstring, jboolean, jboolean, jboolean);
+  (JNIEnv *, jclass, jlong, jobject, jstring, jboolean, jboolean, jboolean);
 
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index effda90593ca1cf0e79fb122f24920194e7830e7..3238198a7c394552618349bcee0579d7ef76503a 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -10958,6 +10958,90 @@ private List<IngestModuleInfo> getIngestModules(int ingestJobId, CaseDbConnectio
 
 		}
 	}
+	
+		/**
+	 * Add an image to the database.
+	 *
+	 * @param type        Type of image
+	 * @param sectorSize  Sector size
+	 * @param size        Image size
+	 * @param displayName Display name for the image
+	 * @param imagePaths  Image path(s)
+	 * @param timezone    Time zone
+	 * @param md5         MD5 hash
+	 * @param sha1        SHA1 hash
+	 * @param sha256      SHA256 hash
+	 * @param deviceId    Device ID
+	 * @param transaction Case DB transaction
+	 *
+	 * @return the newly added Image
+	 *
+	 * @throws TskCoreException
+	 */
+	long addImageJNI(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName,
+			String timezone, String md5, String sha1, String sha256,
+			String deviceId,
+			CaseDbTransaction transaction) throws TskCoreException {
+		acquireSingleUserCaseWriteLock();
+		Statement statement = null;
+		try {
+			// Insert a row for the Image into the tsk_objects table.
+			CaseDbConnection connection = transaction.getConnection();
+			long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
+
+			// Add a row to tsk_image_info
+			// INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
+			PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO);
+			preparedStatement.clearParameters();
+			preparedStatement.setLong(1, newObjId);
+			preparedStatement.setShort(2, (short) type.getValue());
+			preparedStatement.setLong(3, sectorSize);
+			preparedStatement.setString(4, timezone);
+			//prevent negative size
+			long savedSize = size < 0 ? 0 : size;
+			preparedStatement.setLong(5, savedSize);
+			preparedStatement.setString(6, md5);
+			preparedStatement.setString(7, sha1);
+			preparedStatement.setString(8, sha256);
+			preparedStatement.setString(9, displayName);
+			connection.executeUpdate(preparedStatement);
+
+			// Add a row to data_source_info
+			preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DATA_SOURCE_INFO);
+			statement = connection.createStatement();
+			preparedStatement.setLong(1, newObjId);
+			preparedStatement.setString(2, deviceId);
+			preparedStatement.setString(3, timezone);
+			connection.executeUpdate(preparedStatement);
+
+			return newObjId;
+		} catch (SQLException ex) {
+			throw new TskCoreException(String.format("Error adding image with display name %s to database", displayName), ex);
+		} finally {
+			closeStatement(statement);
+			releaseSingleUserCaseWriteLock();
+		}
+	}
+	
+	void addImageNameJNI(long objId, String name, long sequence,
+			CaseDbTransaction transaction) throws TskCoreException {
+		acquireSingleUserCaseWriteLock();
+		Statement statement = null;
+		try {
+			CaseDbConnection connection = transaction.getConnection();
+			PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
+			preparedStatement.clearParameters();
+			preparedStatement.setLong(1, objId);
+			preparedStatement.setString(2, name);
+			preparedStatement.setLong(3, sequence);
+			connection.executeUpdate(preparedStatement);
+		} catch (SQLException ex) {
+			throw new TskCoreException(String.format("Error adding image name %s to image with object ID %d", name, objId), ex);
+		} finally {
+			closeStatement(statement);
+			releaseSingleUserCaseWriteLock();
+		}
+	}
 
 	/**
 	 * Stores a pair of object ID and its type
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
index 11c4069b0b2cabb2c27d7236a3f39394d2f74ff0..4a9382a3ed812c1a53d3d320529428ad95ad02f5 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
@@ -411,14 +411,22 @@ void free() throws TskCoreException {
 		 *                          case database.
 		 */
 		long addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone, SleuthkitCase skCase) throws TskCoreException {
+			JniDbHelper dbHelper = new JniDbHelper(skCase);
 			try {
-				long tskAutoDbPointer = initializeAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), false, false, false);
-				runOpenAndAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone);
+				dbHelper.beginTransaction();
+				System.out.println("@@@ About to call initAddImgNat from CaseDbHandle.addImageInfo()");
+				System.out.flush();
+				long tskAutoDbPointer = initializeAddImgNat(caseDbPointer, dbHelper, timezoneLongToShort(timeZone), false, false, false);
+				System.out.println("@@@ About to call runOpenAndAddImgNat from CaseDbHandle.addImageInfo()");
+				System.out.flush();
+				runOpenAndAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone);				
 				long id = commitAddImgNat(tskAutoDbPointer);
 				skCase.addDataSourceToHasChildrenMap();
 				return id;
 			} catch (TskDataException ex) {
 				throw new TskCoreException("Error adding image to case database", ex);
+			} finally {
+				dbHelper.commitTransaction();
 			}
 		}
 
@@ -455,6 +463,7 @@ public class AddImageProcess {
 			private volatile long tskAutoDbPointer;
 			private boolean isCanceled;
 			private final SleuthkitCase skCase;
+			private final JniDbHelper dbHelper;
 
 			/**
 			 * Constructs an object that encapsulates a multi-step process to
@@ -477,6 +486,7 @@ private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFa
 				tskAutoDbPointer = 0;
 				this.isCanceled = false;
 				this.skCase = skCase;
+				this.dbHelper = new JniDbHelper(skCase);
 			}
 
 			/**
@@ -508,18 +518,26 @@ public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws
 						}
 						if (!isCanceled) { //with isCanceled being guarded by this it will have the same value everywhere in this synchronized block
 							imageHandle = openImage(imageFilePaths, sectorSize, false, caseDbPointer);
-							tskAutoDbPointer = initAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans);
+							System.out.println("@@@ About to call initAddImgNat from AddImageProcess.run()");
+							System.out.flush();
+							dbHelper.beginTransaction();
+							tskAutoDbPointer = initAddImgNat(caseDbPointer, dbHelper, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans);
 						}
 						if (0 == tskAutoDbPointer) {
 							throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer");
 						}
 					}
 					if (imageHandle != 0) {
+						System.out.println("@@@ About to call runAddImgNat from AddImageProcess.run()");
+						System.out.flush();
 						runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, imageWriterPath);
 					}
 				} finally {
+					dbHelper.commitTransaction(); // TODO TODO
 					releaseTSKReadLock();
 				}
+				System.out.println("@@@ Done with AddImageProcess.run()");
+				System.out.flush();
 			}
 
 			/**
@@ -536,7 +554,7 @@ public synchronized void stop() throws TskCoreException {
 				try {
 					isCanceled = true;
 					if (tskAutoDbPointer != 0) {
-						stopAddImgNat(tskAutoDbPointer);
+						//stopAddImgNat(tskAutoDbPointer); // TODO TODO
 					}
 				} finally {
 					releaseTSKReadLock();
@@ -557,7 +575,7 @@ public synchronized void revert() throws TskCoreException {
 						throw new TskCoreException("AddImgProcess::revert: AutoDB pointer is NULL");
 					}
 
-					revertAddImgNat(tskAutoDbPointer);
+					//revertAddImgNat(tskAutoDbPointer); // TODO
 					// the native code deleted the object
 					tskAutoDbPointer = 0;
 				} finally {
@@ -581,13 +599,14 @@ public synchronized long commit() throws TskCoreException {
 						throw new TskCoreException("AddImgProcess::commit: AutoDB pointer is NULL");
 					}
 
-					long id = commitAddImgNat(tskAutoDbPointer);
+					//long id = commitAddImgNat(tskAutoDbPointer); // TODO
 
 					skCase.addDataSourceToHasChildrenMap();
 
 					// the native code deleted the object
 					tskAutoDbPointer = 0;
-					return id;
+					//return id; // TODO
+					return 1;
 				} finally {
 					releaseTSKReadLock();
 				}
@@ -1933,9 +1952,9 @@ public static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM at
 
 	private static native HashHitInfo hashDbLookupVerbose(String hash, int dbHandle) throws TskCoreException;
 
-	private static native long initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
+	private static native long initAddImgNat(long db, JniDbHelper dbHelperObj, String timezone, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
 
-	private static native long initializeAddImgNat(long db, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
+	private static native long initializeAddImgNat(long db, JniDbHelper dbHelperObj, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
 
 	private static native void runOpenAndAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone) throws TskCoreException, TskDataException;