On the javahl-1.7-extensions branch:
Sync JavaHL changes from trunk up to r1494655.


git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/javahl-1.7-extensions@1494817 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/Makefile.in b/Makefile.in
index bab4577..d9758fc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -440,10 +440,12 @@
 
 extraclean-javahl: clean-javahl
 
-check-javahl: javahl javahl-compat
+#check-javahl: javahl javahl-compat
+check-javahl: javahl
 	@FIX_JAVAHL_LIB@
 	$(JAVA) "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" -Djava.library.path=@JAVAHL_OBJDIR@:$(libdir) -classpath $(javahl_tests_PATH):$(javahl_tests_CLASSPATH) "-Dtest.tests=$(JAVAHL_TESTS)" org.apache.subversion.javahl.RunTests
-	$(JAVA) "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" -Djava.library.path=@JAVAHL_OBJDIR@:$(libdir) -classpath $(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH) "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests
+
+#	$(JAVA) "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" -Djava.library.path=@JAVAHL_OBJDIR@:$(libdir) -classpath $(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH) "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests
 
 # "make check CLEANUP=true" will clean up directories for successful tests.
 # "make check TESTS=subversion/tests/cmdline/basic_tests.py"
diff --git a/build.conf b/build.conf
index 9587ca3..3d21479 100644
--- a/build.conf
+++ b/build.conf
@@ -57,6 +57,8 @@
         subversion/bindings/javahl/include/org_apache_subversion_javahl_types_Version.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_types_Revision.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_UserPasswordCallback.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_remote_RemoteSession.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_remote_RemoteFactory.h
 
 
 test-scripts =
@@ -529,6 +531,7 @@
 path = subversion/bindings/javahl/src/org/apache/subversion/javahl
   subversion/bindings/javahl/src/org/apache/subversion/javahl/callback
   subversion/bindings/javahl/src/org/apache/subversion/javahl/types
+  subversion/bindings/javahl/src/org/apache/subversion/javahl/remote
 src-root = subversion/bindings/javahl/src
 sources = *.java
 install = javahl-java
@@ -583,6 +586,17 @@
 install = javahl-javah
 link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
 
+[javahl-remote-javah]
+type = javah 
+path = subversion/bindings/javahl/src/org/apache/subversion/javahl/remote
+classes = subversion/bindings/javahl/classes
+headers = subversion/bindings/javahl/include
+package = org.apache.subversion.javahl.remote
+sources = *.java
+add-deps = $(javahl_java_DEPS)
+install = javahl-javah
+link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
+
 [javahl-callback-javah]
 type = javah 
 path = subversion/bindings/javahl/src/org/apache/subversion/javahl/callback
@@ -612,7 +626,7 @@
 libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff 
        libsvn_subr libsvn_fs aprutil apriconv apr neon
 sources = *.cpp *.c
-add-deps = $(javahl_javah_DEPS) $(javahl_java_DEPS) $(javahl_callback_javah_DEPS) $(javahl_types_javah_DEPS)
+add-deps = $(javahl_javah_DEPS) $(javahl_java_DEPS) $(javahl_callback_javah_DEPS) $(javahl_types_javah_DEPS) $(javahl_remote_javah_DEPS)
 install = javahl-lib
 # need special build rule to include -I$(JDK)/include/jni.h
 compile-cmd = $(COMPILE_JAVAHL_CXX)
diff --git a/subversion/bindings/javahl/README b/subversion/bindings/javahl/README
index c8cdaf2..bcbba3f 100644
--- a/subversion/bindings/javahl/README
+++ b/subversion/bindings/javahl/README
@@ -5,7 +5,7 @@
 a high level Java API for Subversion, which was originally targeted for
 implementors of GUI clients and IDE plug-ins for Subversion.  JavaHL
 currently provides a minimal-but-complete set of APIs which expose the
-core Subversion C API to Java.  It requires a JRE 1.2+ (runtime).
+core Subversion C API to Java.  It requires a JRE 1.5+ (runtime).
 
 It is currently quite mature, and can be considered for production use.
 
@@ -14,7 +14,7 @@
 ------------
 
 JavaHL should compile and run under Linux, Win32, and Mac OS X with a
-JDK 1.3+.
+JDK 1.5+.
 
 Its build will produce both a native library (libsvnjavahl-1.so on Unix
 or libsvnjavahl-1.dll on Win32) and a platform independent archive of
@@ -62,9 +62,6 @@
 
 Subclipse, Eclipse IDE plug-in <http://subclipse.tigris.org/>
 
-Svn-Up, Swing GUI and plug-in for the IDEA IDE
-<http://svnup.tigris.org/>
-
 
 Why not 100% pure Java?
 -----------------------
diff --git a/subversion/bindings/javahl/native/BlameCallback.cpp b/subversion/bindings/javahl/native/BlameCallback.cpp
index f0f84ad..5973707 100644
--- a/subversion/bindings/javahl/native/BlameCallback.cpp
+++ b/subversion/bindings/javahl/native/BlameCallback.cpp
@@ -61,11 +61,9 @@
                         apr_pool_t *pool)
 {
   if (baton)
-    return ((BlameCallback *)baton)->singleLine(start_revnum, end_revnum,
-                                                line_no, revision, rev_props,
-                                                merged_revision,
-                                                merged_rev_props, merged_path,
-                                                line, local_change, pool);
+    return static_cast<BlameCallback *>(baton)->singleLine(start_revnum,
+        end_revnum, line_no, revision, rev_props, merged_revision,
+        merged_rev_props, merged_path, line, local_change, pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/ChangelistCallback.cpp b/subversion/bindings/javahl/native/ChangelistCallback.cpp
index 5a9c9fc..d04ba32 100644
--- a/subversion/bindings/javahl/native/ChangelistCallback.cpp
+++ b/subversion/bindings/javahl/native/ChangelistCallback.cpp
@@ -53,7 +53,8 @@
                              apr_pool_t *pool)
 {
   if (baton)
-    ((ChangelistCallback *)baton)->doChangelist(path, changelist, pool);
+    static_cast<ChangelistCallback *>(baton)->doChangelist(path, changelist,
+            pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/ClientContext.cpp b/subversion/bindings/javahl/native/ClientContext.cpp
index b7e2de1..d8fe608 100644
--- a/subversion/bindings/javahl/native/ClientContext.cpp
+++ b/subversion/bindings/javahl/native/ClientContext.cpp
@@ -39,39 +39,12 @@
 
 
 ClientContext::ClientContext(jobject jsvnclient, SVN::Pool &pool)
-    : m_prompter(NULL),
-      m_cancelOperation(false)
+    : OperationContext(pool)
 {
-    JNIEnv *env = JNIUtil::getEnv();
-
-    /* Grab a global reference to the Java object embedded in the parent Java
-       object. */
     static jfieldID ctxFieldID = 0;
-    if (ctxFieldID == 0)
-    {
-        jclass clazz = env->GetObjectClass(jsvnclient);
-        if (JNIUtil::isJavaExceptionThrown())
-            return;
+    attachJavaObject(jsvnclient, "L"JAVA_PACKAGE"/SVNClient$ClientContext;", "clientContext", &ctxFieldID);
 
-        ctxFieldID = env->GetFieldID(clazz, "clientContext",
-                                "L"JAVA_PACKAGE"/SVNClient$ClientContext;");
-        if (JNIUtil::isJavaExceptionThrown() || ctxFieldID == 0)
-            return;
-
-        env->DeleteLocalRef(clazz);
-    }
-
-    jobject jctx = env->GetObjectField(jsvnclient, ctxFieldID);
-    if (JNIUtil::isJavaExceptionThrown())
-        return;
-
-    m_jctx = env->NewGlobalRef(jctx);
-    if (JNIUtil::isJavaExceptionThrown())
-        return;
-
-    env->DeleteLocalRef(jctx);
-
-    SVN_JNI_ERR(svn_client_create_context(&m_context, pool.getPool()),
+    SVN_JNI_ERR(svn_client_create_context(&m_context,pool.getPool()),
                 );
 
     /* Clear the wc_ctx as we don't want to maintain this unconditionally
@@ -95,23 +68,18 @@
     m_context->conflict_func2 = resolve;
     m_context->conflict_baton2 = m_jctx;
 
-    m_context->client_name = "javahl";
-    m_pool = &pool;
+    m_context->client_name = getClientName();
 }
 
 ClientContext::~ClientContext()
 {
-    delete m_prompter;
-
-    JNIEnv *env = JNIUtil::getEnv();
-    env->DeleteGlobalRef(m_jctx);
 }
 
 
 /* Helper function to make sure that we don't keep dangling pointers in ctx.
    Note that this function might be called multiple times if getContext()
    is called on the same pool.
-   
+
    The use of this function assumes a proper subpool behavior by its user,
    (read: SVNClient) usually per request.
  */
@@ -125,7 +93,7 @@
 
 static apr_status_t clear_ctx_ptrs(void *ptr)
 {
-    clearctx_baton_t *bt = (clearctx_baton_t*)ptr;
+    clearctx_baton_t *bt = reinterpret_cast<clearctx_baton_t*>(ptr);
 
     /* Reset all values to those before overwriting by getContext. */
     *bt->ctx = *bt->backup;
@@ -139,7 +107,6 @@
 ClientContext::getContext(CommitMessage *message, SVN::Pool &in_pool)
 {
     apr_pool_t *pool = in_pool.getPool();
-    svn_auth_baton_t *ab;
     svn_client_ctx_t *ctx = m_context;
 
     /* Make a temporary copy of ctx to restore at pool cleanup to avoid
@@ -148,127 +115,25 @@
        Note that this allows creating a stack of context changes if
        the function is invoked multiple times with different pools.
      */
-    clearctx_baton_t *bt = (clearctx_baton_t *)apr_pcalloc(pool, sizeof(*bt));
+    clearctx_baton_t *bt =
+      reinterpret_cast<clearctx_baton_t *>(apr_pcalloc(pool, sizeof(*bt)));
     bt->ctx = ctx;
-    bt->backup = (svn_client_ctx_t*)apr_pmemdup(pool, ctx, sizeof(*ctx));
+    bt->backup =
+      reinterpret_cast<svn_client_ctx_t*>(apr_pmemdup(pool, ctx, sizeof(*ctx)));
     apr_pool_cleanup_register(in_pool.getPool(), bt, clear_ctx_ptrs,
                               clear_ctx_ptrs);
 
-
     if (!ctx->config)
       {
-        const char *configDir = m_configDir.c_str();
-        if (m_configDir.empty())
-            configDir = NULL;
-        SVN_JNI_ERR(svn_config_get_config(&(ctx->config), configDir,
-                                          m_pool->getPool()),
-                    NULL);
+        apr_hash_t * configData = getConfigData();
 
+        ctx->config = configData;
         bt->backup->config = ctx->config;
       }
-    svn_config_t *config = (svn_config_t *) apr_hash_get(ctx->config,
-                                                         SVN_CONFIG_CATEGORY_CONFIG,
-                                                         APR_HASH_KEY_STRING);
 
-
-    /* The whole list of registered providers */
-    apr_array_header_t *providers;
-
-    /* Populate the registered providers with the platform-specific providers */
-    SVN_JNI_ERR(svn_auth_get_platform_specific_client_providers(&providers,
-                                                                config,
-                                                                pool),
-                NULL);
-
-    /* Use the prompter (if available) to prompt for password and cert
-     * caching. */
-    svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL;
-    void *plaintext_prompt_baton = NULL;
-    svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func;
-    void *plaintext_passphrase_prompt_baton = NULL;
-
-    if (m_prompter != NULL)
-    {
-        plaintext_prompt_func = Prompter::plaintext_prompt;
-        plaintext_prompt_baton = m_prompter;
-        plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt;
-        plaintext_passphrase_prompt_baton = m_prompter;
-    }
-
-    /* The main disk-caching auth providers, for both
-     * 'username/password' creds and 'username' creds.  */
-    svn_auth_provider_object_t *provider;
-
-    svn_auth_get_simple_provider2(&provider, plaintext_prompt_func,
-                                  plaintext_prompt_baton, pool);
-    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-    svn_auth_get_username_provider(&provider, pool);
-    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-    /* The server-cert, client-cert, and client-cert-password providers. */
-    SVN_JNI_ERR(svn_auth_get_platform_specific_provider(&provider,
-                                                        "windows",
-                                                        "ssl_server_trust",
-                                                        pool),
-                NULL);
-
-    if (provider)
-        APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-    svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
-    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-    svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
-    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-    svn_auth_get_ssl_client_cert_pw_file_provider2(&provider,
-                        plaintext_passphrase_prompt_func,
-                        plaintext_passphrase_prompt_baton, pool);
-    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-    if (m_prompter != NULL)
-    {
-        /* Two basic prompt providers: username/password, and just username.*/
-        provider = m_prompter->getProviderSimple(in_pool);
-
-        APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-        provider = m_prompter->getProviderUsername(in_pool);
-        APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-        /* Three ssl prompt providers, for server-certs, client-certs,
-         * and client-cert-passphrases.  */
-        provider = m_prompter->getProviderServerSSLTrust(in_pool);
-        APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-        provider = m_prompter->getProviderClientSSL(in_pool);
-        APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
-        provider = m_prompter->getProviderClientSSLPassword(in_pool);
-        APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-    }
-
-    /* Build an authentication baton to give to libsvn_client. */
-    svn_auth_open(&ab, providers, pool);
-
-    /* Place any default --username or --password credentials into the
-     * auth_baton's run-time parameter hash.  ### Same with --no-auth-cache? */
-    if (!m_userName.empty())
-        svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME,
-                               apr_pstrdup(in_pool.getPool(),
-                                           m_userName.c_str()));
-    if (!m_passWord.empty())
-        svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,
-                               apr_pstrdup(in_pool.getPool(),
-                                           m_passWord.c_str()));
-    /* Store where to retrieve authentication data? */
-    if (!m_configDir.empty())
-        svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR,
-                               apr_pstrdup(in_pool.getPool(),
-                                           m_configDir.c_str()));
-
-    ctx->auth_baton = ab;
+    ctx->auth_baton = getAuthBaton(in_pool);
     ctx->log_msg_baton3 = message;
-    m_cancelOperation = false;
+    resetCancelRequest();
 
     SVN_JNI_ERR(svn_wc_context_create(&ctx->wc_ctx, NULL,
                                       in_pool.getPool(), in_pool.getPool()),
@@ -278,60 +143,6 @@
 }
 
 void
-ClientContext::username(const char *pi_username)
-{
-    m_userName = (pi_username == NULL ? "" : pi_username);
-}
-
-void
-ClientContext::password(const char *pi_password)
-{
-    m_passWord = (pi_password == NULL ? "" : pi_password);
-}
-
-void
-ClientContext::setPrompt(Prompter *prompter)
-{
-    delete m_prompter;
-    m_prompter = prompter;
-}
-
-void
-ClientContext::setConfigDirectory(const char *configDir)
-{
-    // A change to the config directory may necessitate creation of
-    // the config templates.
-    SVN::Pool requestPool;
-    SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), );
-
-    m_configDir = (configDir == NULL ? "" : configDir);
-    m_context->config = NULL;
-}
-
-const char *
-ClientContext::getConfigDirectory() const
-{
-    return m_configDir.c_str();
-}
-
-void
-ClientContext::cancelOperation()
-{
-    m_cancelOperation = true;
-}
-
-svn_error_t *
-ClientContext::checkCancel(void *cancelBaton)
-{
-    ClientContext *that = (ClientContext *)cancelBaton;
-    if (that->m_cancelOperation)
-        return svn_error_create(SVN_ERR_CANCELLED, NULL,
-                                _("Operation cancelled"));
-    else
-        return SVN_NO_ERROR;
-}
-
-void
 ClientContext::notify(void *baton,
                       const svn_wc_notify_t *notify,
                       apr_pool_t *pool)
@@ -365,54 +176,6 @@
   env->DeleteLocalRef(jInfo);
 }
 
-void
-ClientContext::progress(apr_off_t progressVal, apr_off_t total,
-                        void *baton, apr_pool_t *pool)
-{
-  jobject jctx = (jobject) baton;
-  JNIEnv *env = JNIUtil::getEnv();
-
-  // Create a local frame for our references
-  env->PushLocalFrame(LOCAL_FRAME_SIZE);
-  if (JNIUtil::isJavaExceptionThrown())
-    return;
-
-  static jmethodID mid = 0;
-  if (mid == 0)
-    {
-      jclass clazz = env->GetObjectClass(jctx);
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN_NOTHING();
-
-      mid = env->GetMethodID(clazz, "onProgress",
-                             "(L"JAVA_PACKAGE"/ProgressEvent;)V");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN_NOTHING();
-    }
-
-  static jmethodID midCT = 0;
-  jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressEvent");
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NOTHING();
-
-  if (midCT == 0)
-    {
-      midCT = env->GetMethodID(clazz, "<init>", "(JJ)V");
-      if (JNIUtil::isJavaExceptionThrown() || midCT == 0)
-        POP_AND_RETURN_NOTHING();
-    }
-
-  // Call the Java method.
-  jobject jevent = env->NewObject(clazz, midCT,
-                                  (jlong) progressVal, (jlong) total);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NOTHING();
-
-  env->CallVoidMethod(jctx, mid, jevent);
-
-  POP_AND_RETURN_NOTHING();
-}
-
 svn_error_t *
 ClientContext::resolve(svn_wc_conflict_result_t **result,
                        const svn_wc_conflict_description2_t *desc,
diff --git a/subversion/bindings/javahl/native/ClientContext.h b/subversion/bindings/javahl/native/ClientContext.h
index de3ece1..bd0aae9 100644
--- a/subversion/bindings/javahl/native/ClientContext.h
+++ b/subversion/bindings/javahl/native/ClientContext.h
@@ -29,6 +29,8 @@
 
 #include <string>
 
+#include "OperationContext.h"
+
 #include "svn_types.h"
 #include "svn_client.h"
 
@@ -36,7 +38,6 @@
 #include "Pool.h"
 #include "JNIStringHolder.h"
 
-class Prompter;
 class CommitMessage;
 
 /**
@@ -44,25 +45,14 @@
  * and implements the functions read & close of svn_stream_t.
  *
  */
-class ClientContext
+class ClientContext : public OperationContext
 {
  private:
   svn_client_ctx_t *m_context;
-  const SVN::Pool *m_pool;
-  jobject m_jctx;
-
-  std::string m_userName;
-  std::string m_passWord;
-  std::string m_configDir;
-
-  Prompter *m_prompter;
-  bool m_cancelOperation;
 
  protected:
   static void notify(void *baton, const svn_wc_notify_t *notify,
                      apr_pool_t *pool);
-  static void progress(apr_off_t progressVal, apr_off_t total,
-                       void *baton, apr_pool_t *pool);
   static svn_error_t *resolve(svn_wc_conflict_result_t **result,
                               const svn_wc_conflict_description2_t *desc,
                               void *baton,
@@ -73,24 +63,9 @@
 
  public:
   ClientContext(jobject jsvnclient, SVN::Pool &pool);
-  ~ClientContext();
-
-  static svn_error_t *checkCancel(void *cancelBaton);
+  virtual ~ClientContext();
 
   svn_client_ctx_t *getContext(CommitMessage *message, SVN::Pool &in_pool);
-
-  void username(const char *pi_username);
-  void password(const char *pi_password);
-  void setPrompt(Prompter *prompter);
-  void cancelOperation();
-  const char *getConfigDirectory() const;
-
-  /**
-   * Set the configuration directory, taking the usual steps to
-   * ensure that Subversion's config file templates exist in the
-   * specified location.
-   */
-  void setConfigDirectory(const char *configDir);
 };
 
 #endif // CLIENTCONTEXT_H
diff --git a/subversion/bindings/javahl/native/CommitCallback.cpp b/subversion/bindings/javahl/native/CommitCallback.cpp
index e765a04..2ffe326 100644
--- a/subversion/bindings/javahl/native/CommitCallback.cpp
+++ b/subversion/bindings/javahl/native/CommitCallback.cpp
@@ -57,7 +57,7 @@
                          apr_pool_t *pool)
 {
   if (baton)
-    return ((CommitCallback *)baton)->commitInfo(commit_info, pool);
+    return static_cast<CommitCallback *>(baton)->commitInfo(commit_info, pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/CommitMessage.cpp b/subversion/bindings/javahl/native/CommitMessage.cpp
index 4f8db5f..a947f97 100644
--- a/subversion/bindings/javahl/native/CommitMessage.cpp
+++ b/subversion/bindings/javahl/native/CommitMessage.cpp
@@ -50,9 +50,9 @@
                         void *baton,
                         apr_pool_t *pool)
 {
-  if (baton && ((CommitMessage *)baton)->m_jcommitMessage)
-    return ((CommitMessage *)baton)->getCommitMessage(log_msg, tmp_file,
-                                                      commit_items, pool);
+  if (baton && static_cast<CommitMessage *>(baton)->m_jcommitMessage)
+    return static_cast<CommitMessage *>(baton)->getCommitMessage(
+            log_msg, tmp_file, commit_items, pool);
 
   *log_msg = NULL;
   *tmp_file = NULL;
diff --git a/subversion/bindings/javahl/native/CopySources.cpp b/subversion/bindings/javahl/native/CopySources.cpp
index 4137f18..0ae471d 100644
--- a/subversion/bindings/javahl/native/CopySources.cpp
+++ b/subversion/bindings/javahl/native/CopySources.cpp
@@ -95,12 +95,13 @@
   std::vector<jobject> sources = m_copySources.vector();
 
   apr_array_header_t *copySources =
-    apr_array_make(p, sources.size(), sizeof(svn_client_copy_source_t *));
+    apr_array_make(p, static_cast<int>(sources.size()),
+                   sizeof(svn_client_copy_source_t *));
   for (std::vector<jobject>::const_iterator it = sources.begin();
         it < sources.end(); ++it)
     {
       svn_client_copy_source_t *src =
-        (svn_client_copy_source_t *) apr_palloc(p, sizeof(*src));
+        reinterpret_cast<svn_client_copy_source_t *>(apr_palloc(p, sizeof(*src)));
 
       // Extract the path or URL from the copy source.
       static jmethodID getPath = 0;
@@ -141,10 +142,8 @@
 
       // TODO: Default this to svn_opt_revision_undefined (or HEAD)
       Revision rev(jrev);
-      src->revision = (const svn_opt_revision_t *)
-        apr_palloc(p, sizeof(*src->revision));
-      memcpy((void *) src->revision, rev.revision(),
-             sizeof(*src->revision));
+      src->revision = reinterpret_cast<const svn_opt_revision_t *>
+        (apr_pmemdup(p, rev.revision(), sizeof(*src->revision)));
       env->DeleteLocalRef(jrev);
 
       // Extract pegRevision from the copy source.
@@ -161,10 +160,8 @@
         return NULL;
 
       Revision pegRev(jPegRev, true);
-      src->peg_revision = (const svn_opt_revision_t *)
-        apr_palloc(p, sizeof(*src->peg_revision));
-      memcpy((void *) src->peg_revision, pegRev.revision(),
-             sizeof(*src->peg_revision));
+      src->peg_revision = reinterpret_cast<const svn_opt_revision_t *>
+        (apr_pmemdup(p, pegRev.revision(), sizeof(*src->peg_revision)));
       env->DeleteLocalRef(jPegRev);
 
       APR_ARRAY_PUSH(copySources, svn_client_copy_source_t *) = src;
diff --git a/subversion/bindings/javahl/native/CreateJ.cpp b/subversion/bindings/javahl/native/CreateJ.cpp
index 8bf9f30..fdde2ec 100644
--- a/subversion/bindings/javahl/native/CreateJ.cpp
+++ b/subversion/bindings/javahl/native/CreateJ.cpp
@@ -20,8 +20,8 @@
  * ====================================================================
  * @endcopyright
  *
- * @file ConflictResolverCallback.cpp
- * @brief Implementation of the class ConflictResolverCallback.
+ * @file CreateJ.cpp
+ * @brief Implementation of the class CreateJ.
  */
 
 #include "svn_error.h"
@@ -35,6 +35,7 @@
 #include "../include/org_apache_subversion_javahl_CommitItemStateFlags.h"
 
 #include "svn_path.h"
+#include "svn_props.h"
 #include "private/svn_wc_private.h"
 
 jobject
@@ -150,7 +151,8 @@
   static jmethodID ctor = 0;
   if (ctor == 0)
     {
-      ctor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;J"
+      ctor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;"
+                                               "Ljava/lang/String;J"
                                                "Ljava/lang/String;"
                                                "L"JAVA_PACKAGE"/types/NodeKind;"
                                                ")V");
@@ -168,7 +170,7 @@
   if (JNIUtil::isJavaExceptionThrown())
     POP_AND_RETURN_NULL;
 
-  jobject jversion = env->NewObject(clazz, ctor, jreposURL,
+  jobject jversion = env->NewObject(clazz, ctor, jreposURL, NULL,
                                     (jlong)version->peg_rev, jpathInRepos,
                                     jnodeKind);
   if (JNIUtil::isJavaExceptionThrown())
@@ -206,9 +208,9 @@
         POP_AND_RETURN_NULL;
     }
 
-  jbyteArray jdigest = JNIUtil::makeJByteArray(
-                            (const signed char *)checksum->digest,
-                            svn_checksum_size(checksum));
+  jbyteArray jdigest
+    = JNIUtil::makeJByteArray(checksum->digest,
+                              static_cast<int>(svn_checksum_size(checksum)));
   if (JNIUtil::isExceptionThrown())
     POP_AND_RETURN_NULL;
 
@@ -418,6 +420,72 @@
 }
 
 jobject
+CreateJ::LockMap(const apr_hash_t *locks, apr_pool_t *pool)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+
+  if (locks == NULL)
+    return NULL;
+
+  // Create a local frame for our references
+  env->PushLocalFrame(LOCAL_FRAME_SIZE);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  jclass clazz = env->FindClass("java/util/HashMap");
+  if (JNIUtil::isJavaExceptionThrown())
+    POP_AND_RETURN_NULL;
+
+  static jmethodID init_mid = 0;
+  if (init_mid == 0)
+    {
+      init_mid = env->GetMethodID(clazz, "<init>", "()V");
+      if (JNIUtil::isJavaExceptionThrown())
+        POP_AND_RETURN_NULL;
+    }
+
+  static jmethodID put_mid = 0;
+  if (put_mid == 0)
+    {
+      put_mid = env->GetMethodID(clazz, "put",
+                                 "(Ljava/lang/Object;Ljava/lang/Object;)"
+                                 "Ljava/lang/Object;");
+      if (JNIUtil::isJavaExceptionThrown())
+        POP_AND_RETURN_NULL;
+    }
+
+  jobject map = env->NewObject(clazz, init_mid);
+  if (JNIUtil::isJavaExceptionThrown())
+    POP_AND_RETURN_NULL;
+
+  apr_hash_index_t *hi;
+  int i = 0;
+  for (hi = apr_hash_first(pool, (apr_hash_t *) locks); hi;
+        hi = apr_hash_next(hi), ++i)
+    {
+      const char *key = (const char *) svn__apr_hash_index_key(hi);
+      const svn_lock_t *lock = (const svn_lock_t *) svn__apr_hash_index_val(hi);
+
+      jstring jpath = JNIUtil::makeJString(key);
+      if (JNIUtil::isJavaExceptionThrown())
+        POP_AND_RETURN_NULL;
+
+      jobject jlock = Lock(lock);
+      if (JNIUtil::isJavaExceptionThrown())
+        POP_AND_RETURN_NULL;
+
+      env->CallObjectMethod(map, put_mid, jpath, jlock);
+      if (JNIUtil::isJavaExceptionThrown())
+        POP_AND_RETURN_NULL;
+
+      env->DeleteLocalRef(jpath);
+      env->DeleteLocalRef(jlock);
+    }
+
+  return env->PopLocalFrame(map);
+}
+
+jobject
 CreateJ::ChangedPath(const char *path, svn_log_changed_path2_t *log_item)
 {
   JNIEnv *env = JNIUtil::getEnv();
@@ -429,7 +497,7 @@
 
   jclass clazzCP = env->FindClass(JAVA_PACKAGE"/types/ChangePath");
   if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(SVN_NO_ERROR);
+    POP_AND_RETURN_NULL;
 
   static jmethodID midCP = 0;
   if (midCP == 0)
@@ -442,7 +510,7 @@
                                "L"JAVA_PACKAGE"/types/Tristate;"
                                "L"JAVA_PACKAGE"/types/Tristate;)V");
       if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN(SVN_NO_ERROR);
+        POP_AND_RETURN_NULL;
     }
 
   jstring jpath = JNIUtil::makeJString(path);
@@ -506,6 +574,7 @@
                              "ZZZZZL"JAVA_PACKAGE"/types/Lock;"
                              "L"JAVA_PACKAGE"/types/Lock;"
                              "JJL"JAVA_PACKAGE"/types/NodeKind;"
+                             "Ljava/lang/String;Ljava/lang/String;"
                              "Ljava/lang/String;Ljava/lang/String;)V");
       if (JNIUtil::isJavaExceptionThrown())
         POP_AND_RETURN_NULL;
@@ -525,6 +594,8 @@
   jstring jLastCommitAuthor = NULL;
   jobject jLocalLock = NULL;
   jstring jChangelist = NULL;
+  jstring jMovedFromAbspath = NULL;
+  jstring jMovedToAbspath = NULL;
 
   enum svn_wc_status_kind text_status = status->node_status;
 
@@ -604,7 +675,8 @@
                                jIsSwitched, jIsFileExternal, jLocalLock,
                                jReposLock,
                                jOODLastCmtRevision, jOODLastCmtDate,
-                               jOODKind, jOODLastCmtAuthor, jChangelist);
+                               jOODKind, jOODLastCmtAuthor, jChangelist,
+                               jMovedFromAbspath, jMovedToAbspath);
 
   return env->PopLocalFrame(ret);
 }
@@ -711,7 +783,13 @@
   jlong jhunkModifiedStart = wcNotify->hunk_modified_start;
   jlong jhunkModifiedLength = wcNotify->hunk_modified_length;
   jlong jhunkMatchedLine = wcNotify->hunk_matched_line;
-  jint jhunkFuzz = wcNotify->hunk_fuzz;
+  jint jhunkFuzz = static_cast<jint>(wcNotify->hunk_fuzz);
+  if (jhunkFuzz != wcNotify->hunk_fuzz)
+    {
+      env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
+                    "Overflow converting C svn_linenum_t to Java int");
+      POP_AND_RETURN_NULL;
+    }
 
   // call the Java method
   jobject jInfo = env->NewObject(clazz, midCT, jPath, jAction,
@@ -810,7 +888,8 @@
                                         "(Ljava/lang/String;"
                                         "L"JAVA_PACKAGE"/types/NodeKind;"
                                         "ILjava/lang/String;"
-                                        "Ljava/lang/String;J)V");
+                                        "Ljava/lang/String;J"
+                                        "Ljava/lang/String;)V");
       if (JNIUtil::isExceptionThrown())
         POP_AND_RETURN_NULL;
     }
@@ -837,6 +916,9 @@
   if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY)
     jstateFlags |=
       org_apache_subversion_javahl_CommitItemStateFlags_IsCopy;
+  if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
+    jstateFlags |=
+      org_apache_subversion_javahl_CommitItemStateFlags_LockToken;
 
   jstring jurl = JNIUtil::makeJString(item->url);
   if (JNIUtil::isJavaExceptionThrown())
@@ -851,7 +933,7 @@
   // create the Java object
   jobject jitem = env->NewObject(clazz, midConstructor, jpath,
                                  jnodeKind, jstateFlags, jurl,
-                                 jcopyUrl, jcopyRevision);
+                                 jcopyUrl, jcopyRevision, NULL);
   if (JNIUtil::isJavaExceptionThrown())
     POP_AND_RETURN_NULL;
 
@@ -1019,21 +1101,22 @@
     POP_AND_RETURN_NULL;
 
   apr_hash_index_t *hi;
-  int i = 0;
   for (hi = apr_hash_first(apr_hash_pool_get(prop_hash), prop_hash);
-       hi; hi = apr_hash_next(hi), ++i)
+       hi; hi = apr_hash_next(hi))
     {
       const char *key;
       svn_string_t *val;
 
-      apr_hash_this(hi, (const void **)&key, NULL, (void **)&val);
+      apr_hash_this(hi,
+                    reinterpret_cast<const void **>(&key),
+                    NULL,
+                    reinterpret_cast<void **>(&val));
 
       jstring jpropName = JNIUtil::makeJString(key);
       if (JNIUtil::isJavaExceptionThrown())
         POP_AND_RETURN_NULL;
 
-      jbyteArray jpropVal = JNIUtil::makeJByteArray(
-                                    (const signed char *)val->data, val->len);
+      jbyteArray jpropVal = JNIUtil::makeJByteArray(val);
       if (JNIUtil::isJavaExceptionThrown())
         POP_AND_RETURN_NULL;
 
@@ -1048,6 +1131,7 @@
   return env->PopLocalFrame(map);
 }
 
+
 jobject CreateJ::Set(std::vector<jobject> &objects)
 {
   JNIEnv *env = JNIUtil::getEnv();
diff --git a/subversion/bindings/javahl/native/CreateJ.h b/subversion/bindings/javahl/native/CreateJ.h
index eacb9b4..c1ad307 100644
--- a/subversion/bindings/javahl/native/CreateJ.h
+++ b/subversion/bindings/javahl/native/CreateJ.h
@@ -55,6 +55,9 @@
   Lock(const svn_lock_t *lock);
 
   static jobject
+  LockMap(const apr_hash_t *locks, apr_pool_t *pool);
+
+  static jobject
   ChangedPath(const char *path, svn_log_changed_path2_t *log_item);
 
   static jobject
diff --git a/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp b/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp
index d9173e2..f4cf052 100644
--- a/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp
+++ b/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp
@@ -46,7 +46,7 @@
                                apr_pool_t *pool)
 {
   if (baton)
-    return ((DiffSummaryReceiver *) baton)->onSummary(diff, pool);
+    return static_cast<DiffSummaryReceiver *>(baton)->onSummary(diff, pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/EnumMapper.cpp b/subversion/bindings/javahl/native/EnumMapper.cpp
index c41cc02..089ef6f 100644
--- a/subversion/bindings/javahl/native/EnumMapper.cpp
+++ b/subversion/bindings/javahl/native/EnumMapper.cpp
@@ -81,7 +81,8 @@
 jobject EnumMapper::mapNotifyState(svn_wc_notify_state_t state)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Status", (int) state);
+  return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Status",
+                 static_cast<int>(state));
 }
 
 /**
@@ -90,13 +91,15 @@
 jobject EnumMapper::mapNotifyAction(svn_wc_notify_action_t action)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Action", (int) action);
+  return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Action",
+                 static_cast<int>(action));
 }
 
 jobject EnumMapper::mapReposNotifyNodeAction(svn_node_action action)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$NodeAction", (int) action);
+  return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$NodeAction",
+                 static_cast<int>(action));
 }
 
 /**
@@ -105,7 +108,8 @@
 jobject EnumMapper::mapReposNotifyAction(svn_repos_notify_action_t action)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$Action", (int) action);
+  return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$Action",
+                 static_cast<int>(action));
 }
 
 /**
@@ -114,7 +118,8 @@
 jobject EnumMapper::mapNodeKind(svn_node_kind_t nodeKind)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/types/NodeKind", (int) nodeKind);
+  return mapEnum(JAVA_PACKAGE"/types/NodeKind",
+                 static_cast<int>(nodeKind));
 }
 
 /**
@@ -123,7 +128,8 @@
 jobject EnumMapper::mapNotifyLockState(svn_wc_notify_lock_state_t state)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$LockStatus", (int) state);
+  return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$LockStatus",
+                 static_cast<int>(state));
 }
 
 /**
@@ -132,7 +138,8 @@
 jobject EnumMapper::mapScheduleKind(svn_wc_schedule_t schedule)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/types/Info$ScheduleKind", (int) schedule);
+  return mapEnum(JAVA_PACKAGE"/types/Info$ScheduleKind",
+                 static_cast<int>(schedule));
 }
 
 /**
@@ -142,31 +149,36 @@
 {
   // We're assuming a valid value for the C enum above
   // The offset here is +1
-  return mapEnum(JAVA_PACKAGE"/types/Status$Kind", ((int) svnKind) - 1);
+  return mapEnum(JAVA_PACKAGE"/types/Status$Kind",
+                 static_cast<int>(svnKind) - 1);
 }
 
 jobject EnumMapper::mapChecksumKind(svn_checksum_kind_t kind)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/types/Checksum$Kind", (int) kind);
+  return mapEnum(JAVA_PACKAGE"/types/Checksum$Kind",
+                 static_cast<int>(kind));
 }
 
 jobject EnumMapper::mapConflictKind(svn_wc_conflict_kind_t kind)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Kind", (int) kind);
+  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Kind",
+                 static_cast<int>(kind));
 }
 
 jobject EnumMapper::mapConflictAction(svn_wc_conflict_action_t action)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Action", (int) action);
+  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Action",
+                 static_cast<int>(action));
 }
 
 jobject EnumMapper::mapConflictReason(svn_wc_conflict_reason_t reason)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Reason", (int) reason);
+  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Reason",
+                 static_cast<int>(reason));
 }
 
 int EnumMapper::toMergeinfoLogKind(jobject jLogKind)
@@ -182,45 +194,47 @@
 svn_depth_t EnumMapper::toDepth(jobject jdepth)
 {
   // The offset for depths is -2
-  return (svn_depth_t) (getOrdinal(JAVA_PACKAGE"/types/Depth", jdepth) - 2);
+  return static_cast<svn_depth_t>(getOrdinal(JAVA_PACKAGE"/types/Depth", jdepth) - 2);
 }
 
 jobject EnumMapper::mapDepth(svn_depth_t depth)
 {
   // We're assuming a valid value for the C enum above
   // The offset for depths is -2
-  return mapEnum(JAVA_PACKAGE"/types/Depth", ((int) depth) + 2);
+  return mapEnum(JAVA_PACKAGE"/types/Depth", static_cast<int>(depth) + 2);
 }
 
 jobject EnumMapper::mapOperation(svn_wc_operation_t operation)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Operation", (int) operation);
+  return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Operation",
+                 static_cast<int>(operation));
 }
 
 jobject EnumMapper::mapTristate(svn_tristate_t tristate)
 {
   // We're assuming a valid value for the C enum above
   return mapEnum(JAVA_PACKAGE"/types/Tristate",
-                 (int) (tristate - svn_tristate_false));
+                 static_cast<int>(tristate - svn_tristate_false));
 }
 
 svn_wc_conflict_choice_t EnumMapper::toConflictChoice(jobject jchoice)
 {
-  return (svn_wc_conflict_choice_t) getOrdinal(
-                        JAVA_PACKAGE"/ConflictResult$Choice", jchoice);
+  return static_cast<svn_wc_conflict_choice_t>
+             (getOrdinal(JAVA_PACKAGE"/ConflictResult$Choice", jchoice));
 }
 
 svn_opt_revision_kind EnumMapper::toRevisionKind(jobject jkind)
 {
-  return (svn_opt_revision_kind) getOrdinal(JAVA_PACKAGE"/types/Revision$Kind",
-                                            jkind);
+  return static_cast<svn_opt_revision_kind>
+             (getOrdinal(JAVA_PACKAGE"/types/Revision$Kind", jkind));
 }
 
 jobject EnumMapper::mapSummarizeKind(svn_client_diff_summarize_kind_t sKind)
 {
   // We're assuming a valid value for the C enum above
-  return mapEnum(JAVA_PACKAGE"/DiffSummary$DiffKind", (int) sKind);
+  return mapEnum(JAVA_PACKAGE"/DiffSummary$DiffKind",
+                 static_cast<int>(sKind));
 }
 
 jobject EnumMapper::mapEnum(const char *clazzName, int index)
@@ -282,5 +296,5 @@
     POP_AND_RETURN(-1);
 
   env->PopLocalFrame(NULL);
-  return (int) jorder;
+  return static_cast<int>(jorder);
 }
diff --git a/subversion/bindings/javahl/native/File.cpp b/subversion/bindings/javahl/native/File.cpp
index 7a56f71..76e92dd 100644
--- a/subversion/bindings/javahl/native/File.cpp
+++ b/subversion/bindings/javahl/native/File.cpp
@@ -82,7 +82,7 @@
       /* We don't remove the local ref for jabsolutePath here, because
          JNIStringHolder expects that ref to be valid for the life of
          the object, which in this case is allocated on the stack.
-         
+
          So we just "leak" the reference, and it will get cleaned up when
          we eventually exit back to Java-land. */
       env->DeleteLocalRef(clazz);
diff --git a/subversion/bindings/javahl/native/InfoCallback.cpp b/subversion/bindings/javahl/native/InfoCallback.cpp
index 6ac44d1..8a9e375 100644
--- a/subversion/bindings/javahl/native/InfoCallback.cpp
+++ b/subversion/bindings/javahl/native/InfoCallback.cpp
@@ -52,7 +52,7 @@
                        apr_pool_t *pool)
 {
   if (baton)
-    return ((InfoCallback *)baton)->singleInfo(path, info, pool);
+    return static_cast<InfoCallback *>(baton)->singleInfo(path, info, pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/InputStream.cpp b/subversion/bindings/javahl/native/InputStream.cpp
index 5e8b238..1c73ba2 100644
--- a/subversion/bindings/javahl/native/InputStream.cpp
+++ b/subversion/bindings/javahl/native/InputStream.cpp
@@ -70,7 +70,7 @@
 {
   JNIEnv *env = JNIUtil::getEnv();
   // An object of our class is passed in as the baton.
-  InputStream *that = (InputStream*)baton;
+  InputStream *that = static_cast<InputStream *>(baton);
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
@@ -89,8 +89,7 @@
     }
 
   // Allocate a Java byte array to read the data.
-  jbyteArray data = JNIUtil::makeJByteArray((const signed char*)buffer,
-                                            *len);
+  jbyteArray data = JNIUtil::makeJByteArray(buffer, static_cast<int>(*len));
   if (JNIUtil::isJavaExceptionThrown())
     return SVN_NO_ERROR;
 
@@ -99,6 +98,14 @@
   if (JNIUtil::isJavaExceptionThrown())
     return SVN_NO_ERROR;
 
+  /*
+   * Convert -1 from InputStream.read that means EOF, 0 which is subversion equivalent
+   */
+  if(jread == -1)
+    {
+      jread = 0;
+    }
+
   // Put the Java byte array into a helper object to retrieve the
   // data bytes.
   JNIByteArray outdata(data, true);
@@ -107,7 +114,7 @@
 
   // Catch when the Java method tells us it read too much data.
   if (jread > (jint) *len)
-    jread = -1;
+    jread = 0;
 
   // In the case of success copy the data back to the Subversion
   // buffer.
@@ -130,7 +137,7 @@
   JNIEnv *env = JNIUtil::getEnv();
 
   // An object of our class is passed in as the baton
-  InputStream *that = (InputStream*)baton;
+  InputStream *that = reinterpret_cast<InputStream*>(baton);
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
diff --git a/subversion/bindings/javahl/native/JNICriticalSection.cpp b/subversion/bindings/javahl/native/JNICriticalSection.cpp
index c36349a..5efa2c5 100644
--- a/subversion/bindings/javahl/native/JNICriticalSection.cpp
+++ b/subversion/bindings/javahl/native/JNICriticalSection.cpp
@@ -39,7 +39,7 @@
 JNICriticalSection::JNICriticalSection(JNIMutex &mutex)
 {
   m_mutex = &mutex;
-  apr_status_t apr_err = apr_thread_mutex_lock (mutex.m_mutex);
+  apr_status_t apr_err = apr_thread_mutex_lock(mutex.m_mutex);
   if (apr_err)
     {
       JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_lock");
@@ -53,7 +53,7 @@
  */
 JNICriticalSection::~JNICriticalSection()
 {
-  apr_status_t apr_err = apr_thread_mutex_unlock (m_mutex->m_mutex);
+  apr_status_t apr_err = apr_thread_mutex_unlock(m_mutex->m_mutex);
   if (apr_err)
     {
       JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_unlock");
diff --git a/subversion/bindings/javahl/native/JNIMutex.cpp b/subversion/bindings/javahl/native/JNIMutex.cpp
index d5bc4f3..e718b25 100644
--- a/subversion/bindings/javahl/native/JNIMutex.cpp
+++ b/subversion/bindings/javahl/native/JNIMutex.cpp
@@ -38,7 +38,7 @@
 JNIMutex::JNIMutex(apr_pool_t *pool)
 {
   apr_status_t apr_err =
-    apr_thread_mutex_create (&m_mutex, APR_THREAD_MUTEX_NESTED, pool);
+    apr_thread_mutex_create(&m_mutex, APR_THREAD_MUTEX_NESTED, pool);
   if (apr_err)
     JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_create");
 }
@@ -48,7 +48,7 @@
  */
 JNIMutex::~JNIMutex()
 {
-  apr_status_t apr_err = apr_thread_mutex_destroy (m_mutex);
+  apr_status_t apr_err = apr_thread_mutex_destroy(m_mutex);
   if (apr_err)
     JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_destroy");
 }
diff --git a/subversion/bindings/javahl/native/JNIStackElement.cpp b/subversion/bindings/javahl/native/JNIStackElement.cpp
index 7c00109..2ca6c6e 100644
--- a/subversion/bindings/javahl/native/JNIStackElement.cpp
+++ b/subversion/bindings/javahl/native/JNIStackElement.cpp
@@ -58,20 +58,28 @@
             return;
         }
 
-      // This will call java.lang.Object.toString, even when it is
-      // overriden.
-      jobject oStr = env->CallNonvirtualObjectMethod(jthis, jlo, mid);
-      if (JNIUtil::isJavaExceptionThrown())
-        return;
-
-      // Copy the result to a buffer.
-      JNIStringHolder name(reinterpret_cast<jstring>(oStr));
       *m_objectID = 0;
-      strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
+
+      if(jthis == NULL)
+        {
+          strcpy(m_objectID, "<static>");
+        }
+      else
+        {
+          // This will call java.lang.Object.toString, even when it is
+          // overriden.
+          jobject oStr = env->CallNonvirtualObjectMethod(jthis, jlo, mid);
+          if (JNIUtil::isJavaExceptionThrown())
+            return;
+
+          // Copy the result to a buffer.
+          JNIStringHolder name(reinterpret_cast<jstring>(oStr));
+          strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
+          env->DeleteLocalRef(oStr);
+        }
 
       // Release the Java string.
       env->DeleteLocalRef(jlo);
-      env->DeleteLocalRef(oStr);
 
       // Remember the parameter for the exit of the method.
       m_clazz = clazz;
diff --git a/subversion/bindings/javahl/native/JNIThreadData.cpp b/subversion/bindings/javahl/native/JNIThreadData.cpp
index d950e7a..e3ce334 100644
--- a/subversion/bindings/javahl/native/JNIThreadData.cpp
+++ b/subversion/bindings/javahl/native/JNIThreadData.cpp
@@ -124,7 +124,7 @@
     }
   JNIThreadData *newData = new JNIThreadData();
   newData->m_previous =data;
-  apr_err = apr_threadkey_private_set (newData, g_key);
+  apr_err = apr_threadkey_private_set(newData, g_key);
   if (apr_err)
     {
       JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set");
@@ -151,7 +151,7 @@
 
   JNIThreadData *oldData = data->m_previous;
   delete data;
-  apr_err = apr_threadkey_private_set (oldData, g_key);
+  apr_err = apr_threadkey_private_set(oldData, g_key);
   if (apr_err)
     {
       JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set");
diff --git a/subversion/bindings/javahl/native/JNIThreadData.h b/subversion/bindings/javahl/native/JNIThreadData.h
index 629b35d..55d4141 100644
--- a/subversion/bindings/javahl/native/JNIThreadData.h
+++ b/subversion/bindings/javahl/native/JNIThreadData.h
@@ -21,7 +21,7 @@
  * @endcopyright
  *
  * @file JNIThreadData.h
- * @brief Interface of the class JNIData
+ * @brief Interface of the class JNIThreadData
  */
 
 #ifndef JNITHREADDATA_H
diff --git a/subversion/bindings/javahl/native/JNIUtil.cpp b/subversion/bindings/javahl/native/JNIUtil.cpp
index 109e250..c7b76f6 100644
--- a/subversion/bindings/javahl/native/JNIUtil.cpp
+++ b/subversion/bindings/javahl/native/JNIUtil.cpp
@@ -37,9 +37,13 @@
 #include <apr_lib.h>
 
 #include "svn_pools.h"
+#include "svn_fs.h"
+#include "svn_ra.h"
+#include "svn_utf.h"
 #include "svn_wc.h"
 #include "svn_dso.h"
 #include "svn_path.h"
+#include "svn_cache_config.h"
 #include <apr_file_info.h>
 #include "svn_private_config.h"
 #ifdef WIN32
@@ -175,6 +179,19 @@
       apr_allocator_max_free_set(allocator, 1);
     }
 
+  svn_utf_initialize(g_pool); /* Optimize character conversions */
+  svn_fs_initialize(g_pool); /* Avoid some theoretical issues */
+  svn_ra_initialize(g_pool);
+
+  /* We shouldn't fill the JVMs memory with FS cache data unless explictly
+     requested. */
+  {
+    svn_cache_config_t settings = *svn_cache_config_get();
+    settings.cache_size = 0;
+    settings.file_handle_count = 0;
+    settings.single_threaded = FALSE;
+    svn_cache_config_set(&settings);
+  }
 
 #ifdef ENABLE_NLS
 #ifdef WIN32
@@ -194,7 +211,7 @@
     GetModuleFileNameW(moduleHandle, ucs2_path, inwords);
     inwords = lstrlenW(ucs2_path);
     outbytes = outlength = 3 * (inwords + 1);
-    utf8_path = (char *)apr_palloc(pool, outlength);
+    utf8_path = reinterpret_cast<char *>(apr_palloc(pool, outlength));
     apr_err = apr_conv_ucs2_to_utf8((const apr_wchar_t *) ucs2_path,
                                     &inwords, utf8_path, &outbytes);
     if (!apr_err && (inwords > 0 || outbytes == 0))
@@ -223,7 +240,7 @@
   /* See http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt */
   /* ### This code really only needs to be invoked by consumers of
      ### the libsvn_wc library, which basically means SVNClient. */
-  if (getenv ("SVN_ASP_DOT_NET_HACK"))
+  if (getenv("SVN_ASP_DOT_NET_HACK"))
     {
       err = svn_wc_set_adm_dir("_svn", g_pool);
       if (err)
@@ -240,6 +257,8 @@
     }
 #endif
 
+  svn_error_set_malfunction_handler(svn_error_raise_on_malfunction);
+
   // Build all mutexes.
   g_finalizedObjectsMutex = new JNIMutex(g_pool);
   if (isExceptionThrown())
@@ -377,7 +396,7 @@
 
   char *tmp_path;
   char *path = svn_dirent_dirname(err->file, err->pool);
-  while (tmp_path = strchr(path, '/'))
+  while ((tmp_path = strchr(path, '/')))
     *tmp_path = '.';
 
   jstring jmethodName = makeJString(path);
@@ -493,8 +512,14 @@
   if (isJavaExceptionThrown())
     POP_AND_RETURN_NOTHING();
 
-  jobjectArray jStackTrace = env->NewObjectArray(newStackTrace.size(), stClazz,
-                                                 NULL);
+  const jsize stSize = static_cast<jsize>(newStackTrace.size());
+  if (stSize != newStackTrace.size())
+    {
+      env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
+                    "Overflow converting C size_t to JNI jsize");
+      POP_AND_RETURN_NOTHING();
+    }
+  jobjectArray jStackTrace = env->NewObjectArray(stSize, stClazz, NULL);
   if (isJavaExceptionThrown())
     POP_AND_RETURN_NOTHING();
 
@@ -771,12 +796,37 @@
   return ret;
 }
 
+apr_time_t
+JNIUtil::getDate(jobject jdate)
+{
+  JNIEnv *env = getEnv();
+  jclass clazz = env->FindClass("java/util/Date");
+  if (isJavaExceptionThrown())
+    return 0;
+
+  static jmethodID mid = 0;
+  if (mid == 0)
+    {
+      mid = env->GetMethodID(clazz, "getTime", "()J");
+      if (isJavaExceptionThrown())
+        return 0;
+    }
+
+  jlong jmillis = env->CallLongMethod(jdate, mid);
+  if (isJavaExceptionThrown())
+    return 0;
+
+  env->DeleteLocalRef(clazz);
+
+  return jmillis * 1000;
+}
+
 /**
  * Create a Java byte array from an array of characters.
  * @param data      the character array
  * @param length    the number of characters in the array
  */
-jbyteArray JNIUtil::makeJByteArray(const signed char *data, int length)
+jbyteArray JNIUtil::makeJByteArray(const void *data, int length)
 {
   if (data == NULL)
     {
@@ -808,6 +858,15 @@
 }
 
 /**
+ * Create a Java byte array from an svn_string_t.
+ * @param str       the string
+ */
+jbyteArray JNIUtil::makeJByteArray(const svn_string_t *str)
+{
+  return JNIUtil::makeJByteArray(str->data, static_cast<int>(str->len));
+}
+
+/**
  * Build the error message from the svn error into buffer.  This
  * method calls itselft recursively for all the chained errors
  *
@@ -837,7 +896,21 @@
         buffer.append(svn_strerror(err->apr_err, errbuf, sizeof(errbuf)));
       /* Otherwise, this must be an APR error code. */
       else
-        buffer.append(apr_strerror(err->apr_err, errbuf, sizeof(errbuf)));
+        {
+          /* Messages coming from apr_strerror are in the native
+             encoding, it's a good idea to convert them to UTF-8. */
+          const char* utf8_message;
+          apr_strerror(err->apr_err, errbuf, sizeof(errbuf));
+          svn_error_t* utf8_err = svn_utf_cstring_to_utf8(
+              &utf8_message, errbuf, err->pool);
+          if (utf8_err)
+            {
+              /* Use fuzzy transliteration instead. */
+              svn_error_clear(utf8_err);
+              utf8_message = svn_utf_cstring_from_utf8_fuzzy(errbuf, err->pool);
+            }
+          buffer.append(utf8_message);
+        }
       buffer.append("\n");
     }
   if (err->message)
diff --git a/subversion/bindings/javahl/native/JNIUtil.h b/subversion/bindings/javahl/native/JNIUtil.h
index f122556..7eda7d3 100644
--- a/subversion/bindings/javahl/native/JNIUtil.h
+++ b/subversion/bindings/javahl/native/JNIUtil.h
@@ -41,6 +41,8 @@
 
 #define JAVA_PACKAGE "org/apache/subversion/javahl"
 
+struct svn_string_t;
+
 /**
  * Class to hold a number of JNI related utility methods.  No Objects
  * of this class are ever created.
@@ -62,8 +64,10 @@
                                    int aprErr = -1);
 
   static void throwNullPointerException(const char *message);
-  static jbyteArray makeJByteArray(const signed char *data, int length);
+  static jbyteArray makeJByteArray(const void *data, int length);
+  static jbyteArray makeJByteArray(const svn_string_t *str);
   static jobject createDate(apr_time_t time);
+  static apr_time_t getDate(jobject jdate);
   static void logMessage(const char *message);
   static int getLogLevel();
   static char *getFormatBuffer();
@@ -214,9 +218,9 @@
  */
 
 #define SVN_JNI_NULL_PTR_EX(expr, str, ret_val) \
-  if (expr == NULL) {                           \
+  if ((expr) == NULL) {                         \
     JNIUtil::throwNullPointerException(str);    \
-    return ret_val ;                            \
+    return ret_val;                             \
   }
 
 /**
@@ -235,7 +239,7 @@
     svn_error_t *svn_jni_err__temp = (expr);            \
     if (svn_jni_err__temp != SVN_NO_ERROR) {            \
       JNIUtil::handleSVNError(svn_jni_err__temp);       \
-      return ret_val ;                                  \
+      return ret_val;                                   \
     }                                                   \
   } while (0)
 
@@ -251,7 +255,7 @@
   do                                    \
     {                                   \
       env->PopLocalFrame(NULL);         \
-      return ret_val ;                  \
+      return ret_val;                   \
     }                                   \
   while (0)
 
@@ -272,4 +276,12 @@
  */
 #define POP_AND_RETURN_NULL             POP_AND_RETURN(NULL)
 
+#define CPPADDR_NULL_PTR(expr, ret_val)                 \
+  do {                                                  \
+    if ((expr) == NULL) {                               \
+      JNIUtil::throwError(_("bad C++ this"));           \
+      return ret_val;                                   \
+    }                                                   \
+  } while (0)
+
 #endif  // JNIUTIL_H
diff --git a/subversion/bindings/javahl/native/ListCallback.cpp b/subversion/bindings/javahl/native/ListCallback.cpp
index 385bb1d..6de8857 100644
--- a/subversion/bindings/javahl/native/ListCallback.cpp
+++ b/subversion/bindings/javahl/native/ListCallback.cpp
@@ -54,11 +54,11 @@
                        const svn_dirent_t *dirent,
                        const svn_lock_t *lock,
                        const char *abs_path,
-                       apr_pool_t *pool)
+                       apr_pool_t *scratch_pool)
 {
   if (baton)
-    return ((ListCallback *)baton)->doList(path, dirent, lock, abs_path,
-                                           pool);
+    return static_cast<ListCallback *>(baton)->doList(
+            path, dirent, lock, abs_path, scratch_pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/ListCallback.h b/subversion/bindings/javahl/native/ListCallback.h
index 57e17a9..ac2ec6c 100644
--- a/subversion/bindings/javahl/native/ListCallback.h
+++ b/subversion/bindings/javahl/native/ListCallback.h
@@ -45,7 +45,7 @@
                                const svn_dirent_t *dirent,
                                const svn_lock_t *lock,
                                const char *abs_path,
-                               apr_pool_t *pool);
+                               apr_pool_t *scratch_pool);
 
 protected:
   svn_error_t *doList(const char *path,
diff --git a/subversion/bindings/javahl/native/LogMessageCallback.cpp b/subversion/bindings/javahl/native/LogMessageCallback.cpp
index cdd71fc..237aabf 100644
--- a/subversion/bindings/javahl/native/LogMessageCallback.cpp
+++ b/subversion/bindings/javahl/native/LogMessageCallback.cpp
@@ -57,7 +57,8 @@
                              apr_pool_t *pool)
 {
   if (baton)
-    return ((LogMessageCallback *)baton)->singleMessage(log_entry, pool);
+    return static_cast<LogMessageCallback *>(baton)->singleMessage(
+            log_entry, pool);
 
   return SVN_NO_ERROR;
 }
@@ -101,9 +102,10 @@
            hi;
            hi = apr_hash_next(hi))
         {
-          const char *path = (const char *) svn__apr_hash_index_key(hi);
+          const char *path =
+            reinterpret_cast<const char *>(svn__apr_hash_index_key(hi));
           svn_log_changed_path2_t *log_item =
-                    (svn_log_changed_path2_t *) svn__apr_hash_index_val(hi);
+            reinterpret_cast<svn_log_changed_path2_t *>(svn__apr_hash_index_val(hi));
 
           jobject cp = CreateJ::ChangedPath(path, log_item);
 
diff --git a/subversion/bindings/javahl/native/OperationContext.cpp b/subversion/bindings/javahl/native/OperationContext.cpp
new file mode 100644
index 0000000..1d20446
--- /dev/null
+++ b/subversion/bindings/javahl/native/OperationContext.cpp
@@ -0,0 +1,369 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file OperationContext.cpp
+ * @brief Implementation of the class OperationContext
+ */
+
+#include "svn_client.h"
+#include "private/svn_wc_private.h"
+#include "svn_private_config.h"
+
+#include "OperationContext.h"
+#include "JNIUtil.h"
+#include "JNICriticalSection.h"
+
+#include "Prompter.h"
+#include "CreateJ.h"
+#include "EnumMapper.h"
+#include "CommitMessage.h"
+
+OperationContext::OperationContext(SVN::Pool &pool)
+  : m_config(NULL),
+    m_prompter(NULL),
+    m_cancelOperation(false),
+    m_pool(&pool),
+    m_jctx(NULL)
+{}
+
+void
+OperationContext::attachJavaObject(
+    jobject contextHolder, const char *contextClassType,
+    const char *contextFieldName, jfieldID * ctxFieldID)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+
+  /* Grab a global reference to the Java object embedded in the parent
+     Java object. */
+  if ((*ctxFieldID) == 0)
+    {
+      jclass clazz = env->GetObjectClass(contextHolder);
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+
+      (*ctxFieldID) = env->GetFieldID(clazz, contextFieldName, contextClassType);
+      if (JNIUtil::isJavaExceptionThrown() || (*ctxFieldID) == 0)
+        return;
+
+      env->DeleteLocalRef(clazz);
+    }
+
+  jobject jctx = env->GetObjectField(contextHolder, (*ctxFieldID));
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  m_jctx = env->NewGlobalRef(jctx);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  env->DeleteLocalRef(jctx);
+}
+
+OperationContext::~OperationContext()
+{
+  delete m_prompter;
+
+  JNIEnv *env = JNIUtil::getEnv();
+  env->DeleteGlobalRef(m_jctx);
+}
+
+apr_hash_t *
+OperationContext::getConfigData()
+{
+  if(m_pool->getPool() == NULL)
+    {
+      JNIUtil::throwNullPointerException("pool is null");
+    }
+
+  if (m_config == NULL)
+    {
+      const char *configDir = m_configDir.c_str();
+      if (m_configDir.empty())
+        configDir = NULL;
+      SVN_JNI_ERR(
+          svn_config_get_config(&m_config, configDir, m_pool->getPool()), NULL);
+    }
+
+  return m_config;
+}
+
+svn_auth_baton_t *
+OperationContext::getAuthBaton(SVN::Pool &in_pool)
+{
+  svn_auth_baton_t *ab;
+  apr_pool_t *pool = in_pool.getPool();
+
+  apr_hash_t * configData = getConfigData();
+
+  if (configData == NULL)
+    {
+      return NULL;
+    }
+
+  svn_config_t *config = reinterpret_cast<svn_config_t *>(apr_hash_get(configData,
+      SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING));
+
+  /* The whole list of registered providers */
+  apr_array_header_t *providers;
+
+  /* Populate the registered providers with the platform-specific providers */
+  SVN_JNI_ERR(
+      svn_auth_get_platform_specific_client_providers(&providers, config, pool),
+      NULL);
+
+  /* Use the prompter (if available) to prompt for password and cert
+   * caching. */
+  svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL;
+  void *plaintext_prompt_baton = NULL;
+  svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func;
+  void *plaintext_passphrase_prompt_baton = NULL;
+
+  if (m_prompter != NULL)
+    {
+      plaintext_prompt_func = Prompter::plaintext_prompt;
+      plaintext_prompt_baton = m_prompter;
+      plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt;
+      plaintext_passphrase_prompt_baton = m_prompter;
+    }
+
+  /* The main disk-caching auth providers, for both
+   * 'username/password' creds and 'username' creds.  */
+  svn_auth_provider_object_t *provider;
+
+  svn_auth_get_simple_provider2(&provider, plaintext_prompt_func,
+      plaintext_prompt_baton, pool);
+  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+  svn_auth_get_username_provider(&provider, pool);
+  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+  /* The server-cert, client-cert, and client-cert-password providers. */
+  SVN_JNI_ERR(
+      svn_auth_get_platform_specific_provider(&provider, "windows", "ssl_server_trust", pool),
+      NULL);
+
+  if (provider)
+    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+  svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
+  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+  svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
+  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+  svn_auth_get_ssl_client_cert_pw_file_provider2(&provider,
+      plaintext_passphrase_prompt_func, plaintext_passphrase_prompt_baton,
+      pool);
+  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+  if (m_prompter != NULL)
+    {
+      /* Two basic prompt providers: username/password, and just username.*/
+      provider = m_prompter->getProviderSimple(in_pool);
+
+      APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+      provider = m_prompter->getProviderUsername(in_pool);
+      APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+      /* Three ssl prompt providers, for server-certs, client-certs,
+       * and client-cert-passphrases.  */
+      provider = m_prompter->getProviderServerSSLTrust(in_pool);
+      APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+      provider = m_prompter->getProviderClientSSL(in_pool);
+      APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+      provider = m_prompter->getProviderClientSSLPassword(in_pool);
+      APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+    }
+
+  /* Build an authentication baton to give to libsvn_client. */
+  svn_auth_open(&ab, providers, pool);
+
+  /* Place any default --username or --password credentials into the
+   * auth_baton's run-time parameter hash.  ### Same with --no-auth-cache? */
+  if (!m_userName.empty())
+    svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME,
+        apr_pstrdup(in_pool.getPool(), m_userName.c_str()));
+  if (!m_passWord.empty())
+    svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,
+        apr_pstrdup(in_pool.getPool(), m_passWord.c_str()));
+  /* Store where to retrieve authentication data? */
+  if (!m_configDir.empty())
+    svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR,
+        apr_pstrdup(in_pool.getPool(), m_configDir.c_str()));
+  return ab;
+}
+
+jobject OperationContext::getSelf() const
+{
+  jobject jctx = JNIUtil::getEnv()->NewGlobalRef(m_jctx);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+  return jctx;
+}
+
+void
+OperationContext::username(const char *pi_username)
+{
+  m_userName = (pi_username == NULL ? "" : pi_username);
+}
+
+void
+OperationContext::password(const char *pi_password)
+{
+  m_passWord = (pi_password == NULL ? "" : pi_password);
+}
+
+void
+OperationContext::setPrompt(Prompter *prompter)
+{
+  delete m_prompter;
+  m_prompter = prompter;
+}
+
+void
+OperationContext::setConfigDirectory(const char *configDir)
+{
+  // A change to the config directory may necessitate creation of
+  // the config templates.
+  SVN::Pool requestPool;
+  SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), );
+
+  m_configDir = (configDir == NULL ? "" : configDir);
+
+  m_config = NULL;
+}
+
+const char *
+OperationContext::getConfigDirectory() const
+{
+  return (m_configDir.empty() ? NULL : m_configDir.c_str());
+}
+
+const char *
+OperationContext::getUsername() const
+{
+  return (m_userName.empty() ? NULL : m_userName.c_str());
+}
+
+const char *
+OperationContext::getPassword() const
+{
+  return (m_passWord.empty() ? NULL : m_passWord.c_str());
+}
+
+const Prompter& OperationContext::getPrompter() const
+{
+  return *m_prompter;
+}
+
+void
+OperationContext::cancelOperation()
+{
+  m_cancelOperation = true;
+}
+
+void
+OperationContext::resetCancelRequest()
+{
+  m_cancelOperation = false;
+}
+
+bool
+OperationContext::isCancelledOperation()
+{
+  return m_cancelOperation;
+}
+
+svn_error_t *
+OperationContext::checkCancel(void *cancelBaton)
+{
+  OperationContext *that = static_cast<OperationContext *>(cancelBaton);
+  if (that->isCancelledOperation())
+    return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Operation cancelled"));
+  else
+    return SVN_NO_ERROR;
+}
+
+void
+OperationContext::progress(apr_off_t progressVal, apr_off_t total, void *baton,
+    apr_pool_t *pool)
+{
+  jobject jctx = (jobject) baton;
+  JNIEnv *env = JNIUtil::getEnv();
+
+  // Create a local frame for our references
+  env->PushLocalFrame(LOCAL_FRAME_SIZE);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  static jmethodID mid = 0;
+  if (mid == 0)
+    {
+      jclass clazz = env->GetObjectClass(jctx);
+      if (JNIUtil::isJavaExceptionThrown())
+        POP_AND_RETURN_NOTHING();
+
+      mid = env->GetMethodID(clazz, "onProgress",
+          "(L"JAVA_PACKAGE"/ProgressEvent;)V");
+      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
+        POP_AND_RETURN_NOTHING();
+    }
+
+  static jmethodID midCT = 0;
+  jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressEvent");
+  if (JNIUtil::isJavaExceptionThrown())
+    POP_AND_RETURN_NOTHING();
+
+  if (midCT == 0)
+    {
+      midCT = env->GetMethodID(clazz, "<init>", "(JJ)V");
+      if (JNIUtil::isJavaExceptionThrown() || midCT == 0)
+        POP_AND_RETURN_NOTHING();
+    }
+
+  // Call the Java method.
+  jobject jevent = env->NewObject(clazz, midCT, (jlong) progressVal,
+      (jlong) total);
+  if (JNIUtil::isJavaExceptionThrown())
+    POP_AND_RETURN_NOTHING();
+
+  env->CallVoidMethod(jctx, mid, jevent);
+
+  POP_AND_RETURN_NOTHING();
+}
+
+const char *
+OperationContext::getClientName() const
+{
+  return "javahl";
+}
+
+svn_error_t *
+OperationContext::clientName(void *baton, const char **name, apr_pool_t *pool)
+{
+  OperationContext *that = (OperationContext *) baton;
+
+  *name = that->getClientName();
+
+  return SVN_NO_ERROR;
+}
diff --git a/subversion/bindings/javahl/native/OperationContext.h b/subversion/bindings/javahl/native/OperationContext.h
new file mode 100644
index 0000000..0ea1e9f
--- /dev/null
+++ b/subversion/bindings/javahl/native/OperationContext.h
@@ -0,0 +1,100 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file OperationContext.h
+ * @brief Interface of the class OperationContext
+ */
+
+#ifndef JAVAHL_OPERATION_CONTEXT_H
+#define JAVAHL_OPERATION_CONTEXT_H
+
+#include <string>
+
+#include "svn_types.h"
+#include "svn_client.h"
+
+#include <jni.h>
+#include "Pool.h"
+#include "JNIStringHolder.h"
+
+class Prompter;
+
+/**
+ * This class contains a Java objects implementing the interface RaSharedContext
+ */
+class OperationContext
+{
+ private:
+  std::string m_userName;
+  std::string m_passWord;
+  std::string m_configDir;
+
+  apr_hash_t * m_config;
+
+  Prompter *m_prompter;
+  bool m_cancelOperation;
+
+ protected:
+  SVN::Pool *m_pool;
+
+  jobject m_jctx;
+  static void progress(apr_off_t progressVal, apr_off_t total,
+                       void *baton, apr_pool_t *pool);
+ public:
+  OperationContext(SVN::Pool &pool);
+  void attachJavaObject(jobject contextHolder, const char *contextClassType, const char *contextFieldName, jfieldID * ctxFieldID);
+  virtual ~OperationContext();
+
+  static svn_error_t *checkCancel(void *cancelBaton);
+
+  virtual void username(const char *pi_username);
+  virtual void password(const char *pi_password);
+  virtual void setPrompt(Prompter *prompter);
+  svn_auth_baton_t *getAuthBaton(SVN::Pool &in_pool);
+
+  void cancelOperation();
+  void resetCancelRequest();
+  virtual bool isCancelledOperation();
+  jobject getSelf() const;
+  const char *getConfigDirectory() const;
+  const char *getUsername() const;
+  const char *getPassword() const;
+  const Prompter& getPrompter() const;
+
+  /**
+   * Set the configuration directory, taking the usual steps to
+   * ensure that Subversion's config file templates exist in the
+   * specified location.
+   */
+  void setConfigDirectory(const char *configDir);
+
+  /**
+   * Return configuration data for the context.
+   * Read it from config directory if necessary
+   */
+  apr_hash_t *getConfigData();
+
+  static svn_error_t * clientName(void *baton, const char **name, apr_pool_t *pool);
+  virtual const char * getClientName() const;
+};
+
+#endif // JAVAHL_OPERATION_CONTEXT_H
diff --git a/subversion/bindings/javahl/native/OutputStream.cpp b/subversion/bindings/javahl/native/OutputStream.cpp
index ce80a95..9e85ec5 100644
--- a/subversion/bindings/javahl/native/OutputStream.cpp
+++ b/subversion/bindings/javahl/native/OutputStream.cpp
@@ -76,7 +76,7 @@
   JNIEnv *env = JNIUtil::getEnv();
 
   // An object of our class is passed in as the baton.
-  OutputStream *that = (OutputStream*)baton;
+  OutputStream *that = static_cast<OutputStream *>(baton);
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
@@ -95,8 +95,7 @@
     }
 
   // convert the data to a Java byte array
-  jbyteArray data = JNIUtil::makeJByteArray((const signed char*)buffer,
-                                            *len);
+  jbyteArray data = JNIUtil::makeJByteArray(buffer, static_cast<int>(*len));
   if (JNIUtil::isJavaExceptionThrown())
     return SVN_NO_ERROR;
 
@@ -120,7 +119,7 @@
   JNIEnv *env = JNIUtil::getEnv();
 
   // An object of our class is passed in as the baton
-  OutputStream *that = (OutputStream*)baton;
+  OutputStream *that = reinterpret_cast<OutputStream*>(baton);
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
diff --git a/subversion/bindings/javahl/native/PatchCallback.cpp b/subversion/bindings/javahl/native/PatchCallback.cpp
index b958af6..0cff577 100644
--- a/subversion/bindings/javahl/native/PatchCallback.cpp
+++ b/subversion/bindings/javahl/native/PatchCallback.cpp
@@ -54,10 +54,9 @@
                         apr_pool_t *pool)
 {
   if (baton)
-    return ((PatchCallback *)baton)->singlePatch(filtered,
-                                                 canon_path_from_patchfile,
-                                                 patch_abspath, reject_abspath,
-                                                 pool);
+    return static_cast<PatchCallback *>(baton)->singlePatch(
+            filtered, canon_path_from_patchfile, patch_abspath, reject_abspath,
+            pool);
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/bindings/javahl/native/Path.cpp b/subversion/bindings/javahl/native/Path.cpp
index 328f55b..b9c69ea 100644
--- a/subversion/bindings/javahl/native/Path.cpp
+++ b/subversion/bindings/javahl/native/Path.cpp
@@ -73,12 +73,12 @@
 {
   if (*pi_path == 0)
     {
-      m_error_occured = NULL;
+      m_error_occurred = NULL;
       m_path = "";
     }
   else
     {
-      m_error_occured = JNIUtil::preprocessPath(pi_path, in_pool.getPool());
+      m_error_occurred = JNIUtil::preprocessPath(pi_path, in_pool.getPool());
 
       m_path = pi_path;
     }
@@ -108,15 +108,15 @@
 Path&
 Path::operator=(const Path &pi_path)
 {
-  m_error_occured = NULL;
+  m_error_occurred = NULL;
   m_path = pi_path.m_path;
 
   return *this;
 }
 
-  svn_error_t *Path::error_occured() const
+  svn_error_t *Path::error_occurred() const
 {
-  return m_error_occured;
+  return m_error_occurred;
 }
 
 jboolean Path::isValid(const char *p)
diff --git a/subversion/bindings/javahl/native/Path.h b/subversion/bindings/javahl/native/Path.h
index 2959a42..d23261e 100644
--- a/subversion/bindings/javahl/native/Path.h
+++ b/subversion/bindings/javahl/native/Path.h
@@ -41,7 +41,7 @@
   // The path to be stored.
   std::string m_path;
 
-  svn_error_t *m_error_occured;
+  svn_error_t *m_error_occurred;
 
   /**
    * Initialize the class.
@@ -90,7 +90,7 @@
    */
   const char *c_str() const;
 
-  svn_error_t *error_occured() const;
+  svn_error_t *error_occurred() const;
 
   /**
    * Returns whether @a path is non-NULL and passes the @c
diff --git a/subversion/bindings/javahl/native/Pool.h b/subversion/bindings/javahl/native/Pool.h
index 4c7e2bc..a5b5f8e 100644
--- a/subversion/bindings/javahl/native/Pool.h
+++ b/subversion/bindings/javahl/native/Pool.h
@@ -39,7 +39,7 @@
   {
   public:
     Pool();
-    Pool(const Pool &parent_pool);
+    explicit Pool(const Pool &parent_pool);
     Pool(apr_pool_t *parent_pool);
     ~Pool();
     apr_pool_t *getPool() const;
diff --git a/subversion/bindings/javahl/native/Prompter.cpp b/subversion/bindings/javahl/native/Prompter.cpp
index 4ce8244..241fef3 100644
--- a/subversion/bindings/javahl/native/Prompter.cpp
+++ b/subversion/bindings/javahl/native/Prompter.cpp
@@ -40,9 +40,9 @@
  * @param jprompter     a global reference to the Java callback object
  */
 Prompter::Prompter(jobject jprompter)
-{
-  m_prompter = jprompter;
-}
+  : m_prompter(jprompter),
+    m_maySave(false)
+{}
 
 Prompter::~Prompter()
 {
@@ -427,9 +427,9 @@
                                      svn_boolean_t may_save,
                                      apr_pool_t *pool)
 {
-  Prompter *that = (Prompter*)baton;
+  Prompter *that = static_cast<Prompter *>(baton);
   svn_auth_cred_simple_t *ret =
-    (svn_auth_cred_simple_t*)apr_pcalloc(pool, sizeof(*ret));
+    reinterpret_cast<svn_auth_cred_simple_t*>(apr_pcalloc(pool, sizeof(*ret)));
   if (!that->prompt(realm, username, may_save ? true : false))
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
@@ -460,9 +460,9 @@
                                        svn_boolean_t may_save,
                                        apr_pool_t *pool)
 {
-  Prompter *that = (Prompter*)baton;
+  Prompter *that = static_cast<Prompter *>(baton);
   svn_auth_cred_username_t *ret =
-    (svn_auth_cred_username_t*)apr_pcalloc(pool, sizeof(*ret));
+    reinterpret_cast<svn_auth_cred_username_t*>(apr_pcalloc(pool, sizeof(*ret)));
   const char *user = that->askQuestion(realm, _("Username: "), true,
                                        may_save ? true : false);
   if (user == NULL)
@@ -484,9 +484,9 @@
                                   svn_boolean_t may_save,
                                   apr_pool_t *pool)
 {
-  Prompter *that = (Prompter*)baton;
+  Prompter *that = static_cast<Prompter *>(baton);
   svn_auth_cred_ssl_server_trust_t *ret =
-    (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc(pool, sizeof(*ret));
+    reinterpret_cast<svn_auth_cred_ssl_server_trust_t*>(apr_pcalloc(pool, sizeof(*ret)));
 
   std::string question = _("Error validating server certificate for ");
   question += realm;
@@ -550,9 +550,9 @@
                                  svn_boolean_t may_save,
                                  apr_pool_t *pool)
 {
-  Prompter *that = (Prompter*)baton;
+  Prompter *that = static_cast<Prompter *>(baton);
   svn_auth_cred_ssl_client_cert_t *ret =
-    (svn_auth_cred_ssl_client_cert_t*)apr_pcalloc(pool, sizeof(*ret));
+    reinterpret_cast<svn_auth_cred_ssl_client_cert_t*>(apr_pcalloc(pool, sizeof(*ret)));
   const char *cert_file =
     that->askQuestion(realm, _("client certificate filename: "), true,
                       may_save ? true : false);
@@ -572,9 +572,9 @@
                                     svn_boolean_t may_save,
                                     apr_pool_t *pool)
 {
-  Prompter *that = (Prompter*)baton;
+  Prompter *that = static_cast<Prompter *>(baton);
   svn_auth_cred_ssl_client_cert_pw_t *ret =
-    (svn_auth_cred_ssl_client_cert_pw_t*)apr_pcalloc(pool, sizeof(*ret));
+    reinterpret_cast<svn_auth_cred_ssl_client_cert_pw_t*>(apr_pcalloc(pool, sizeof(*ret)));
   const char *info = that->askQuestion(realm,
                                        _("client certificate passphrase: "),
                                        false, may_save ? true : false);
@@ -593,7 +593,7 @@
                            void *baton,
                            apr_pool_t *pool)
 {
-  Prompter *that = (Prompter *) baton;
+  Prompter *that = static_cast<Prompter *>(baton);
 
   bool result = that->askYesNo(realmstring,
                                _("Store password unencrypted?"),
@@ -610,7 +610,7 @@
                                       void *baton,
                                       apr_pool_t *pool)
 {
-  Prompter *that = (Prompter *) baton;
+  Prompter *that = static_cast<Prompter *>(baton);
 
   bool result = that->askYesNo(realmstring,
                                _("Store passphrase unencrypted?"),
diff --git a/subversion/bindings/javahl/native/ProplistCallback.cpp b/subversion/bindings/javahl/native/ProplistCallback.cpp
index a3bcee3..2e13fd8 100644
--- a/subversion/bindings/javahl/native/ProplistCallback.cpp
+++ b/subversion/bindings/javahl/native/ProplistCallback.cpp
@@ -33,10 +33,10 @@
  * Create a ProplistCallback object
  * @param jcallback the Java callback object.
  */
-ProplistCallback::ProplistCallback(jobject jcallback)
-{
-  m_callback = jcallback;
-}
+ProplistCallback::ProplistCallback(jobject jcallback, bool inherited)
+  : m_callback(jcallback),
+    m_inherited(inherited)
+{}
 
 /**
  * Destroy a ProplistCallback object
@@ -54,7 +54,10 @@
                            apr_pool_t *pool)
 {
   if (baton)
-    return ((ProplistCallback *)baton)->singlePath(path, prop_hash, pool);
+    {
+      ProplistCallback *cb = static_cast<ProplistCallback *>(baton);
+      return cb->singlePath(path, prop_hash, pool);
+    }
 
   return SVN_NO_ERROR;
 }
@@ -78,7 +81,7 @@
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
-  static jmethodID mid = 0;
+  static volatile jmethodID mid = 0;
   if (mid == 0)
     {
       jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/ProplistCallback");
@@ -108,3 +111,58 @@
 
   return SVN_NO_ERROR;
 }
+
+
+
+/**
+ * Callback called for a single path
+ * @param path      the path name
+ * @param prop_hash the hash of properties on this path
+ * @param inherited_props list of inherited props
+ * @param pool      memory pool for the use of this function
+ */
+svn_error_t *ProplistCallback::singlePath(
+    const char *path,
+    apr_hash_t *prop_hash,
+    apr_array_header_t *inherited_props,
+    apr_pool_t *pool)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+
+  // Create a local frame for our references
+  env->PushLocalFrame(LOCAL_FRAME_SIZE);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  // The method id will not change during the time this library is
+  // loaded, so it can be cached.
+  static jmethodID mid = 0;
+  if (mid == 0)
+    {
+      jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/InheritedProplistCallback");
+      if (JNIUtil::isJavaExceptionThrown())
+        return SVN_NO_ERROR;
+
+      mid = env->GetMethodID(clazz, "singlePath",
+                             "(Ljava/lang/String;Ljava/util/Map;Ljava/util/Collection;)V");
+      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
+        POP_AND_RETURN(SVN_NO_ERROR);
+    }
+
+  // convert the parameters to their Java relatives
+  jstring jpath = JNIUtil::makeJString(path);
+  if (JNIUtil::isJavaExceptionThrown())
+    POP_AND_RETURN(SVN_NO_ERROR);
+
+  jobject jmap = CreateJ::PropertyMap(prop_hash);
+  if (JNIUtil::isJavaExceptionThrown())
+    POP_AND_RETURN(SVN_NO_ERROR);
+
+  // call the Java method
+  env->CallVoidMethod(m_callback, mid, jpath, jmap, NULL);
+  // We return whether an exception was thrown or not.
+
+  env->PopLocalFrame(NULL);
+
+  return SVN_NO_ERROR;
+}
diff --git a/subversion/bindings/javahl/native/ProplistCallback.h b/subversion/bindings/javahl/native/ProplistCallback.h
index 72209ef..49ee94c 100644
--- a/subversion/bindings/javahl/native/ProplistCallback.h
+++ b/subversion/bindings/javahl/native/ProplistCallback.h
@@ -37,7 +37,7 @@
 class ProplistCallback
 {
  public:
-  ProplistCallback(jobject jcallback);
+  ProplistCallback(jobject jcallback, bool inherited);
   ~ProplistCallback();
 
   static svn_error_t *callback(void *baton,
@@ -45,16 +45,24 @@
                                apr_hash_t *prop_hash,
                                apr_pool_t *pool);
 
+  bool inherited() const { return m_inherited; }
+
  protected:
   svn_error_t *singlePath(const char *path,
                           apr_hash_t *prop_hash,
                           apr_pool_t *pool);
 
+  svn_error_t *singlePath(const char *path,
+                          apr_hash_t *prop_hash,
+                          apr_array_header_t *inherited_props,
+                          apr_pool_t *pool);
  private:
   /**
    * This a local reference to the Java object.
    */
   jobject m_callback;
+  bool m_inherited;
 };
 
+
 #endif  // PROPLISTCALLBACK_H
diff --git a/subversion/bindings/javahl/native/RemoteSession.cpp b/subversion/bindings/javahl/native/RemoteSession.cpp
new file mode 100644
index 0000000..2893b0c
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSession.cpp
@@ -0,0 +1,441 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSession.cpp
+ * @brief Implementation of the class RemoteSession
+ */
+
+#include <cstring>
+#include <set>
+
+#include "JNIStringHolder.h"
+#include "JNIUtil.h"
+
+#include "svn_ra.h"
+
+#include "CreateJ.h"
+#include "EnumMapper.h"
+#include "Prompter.h"
+#include "Revision.h"
+#include "RemoteSession.h"
+
+#include "svn_private_config.h"
+
+#define JAVA_CLASS_REMOTE_SESSION JAVA_PACKAGE "/remote/RemoteSession"
+
+RemoteSession *
+RemoteSession::getCppObject(jobject jthis)
+{
+  static jfieldID fid = 0;
+  jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid,
+      JAVA_CLASS_REMOTE_SESSION);
+  return (cppAddr == 0 ? NULL : reinterpret_cast<RemoteSession *>(cppAddr));
+}
+
+jobject
+RemoteSession::open(jint jretryAttempts,
+                    jstring jurl, jstring juuid,
+                    jstring jconfigDirectory,
+                    jstring jusername, jstring jpassword,
+                    jobject jprompter, jobject jprogress)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+
+  JNIStringHolder url(jurl);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+  env->DeleteLocalRef(jurl);
+
+  JNIStringHolder uuid(juuid);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+  env->DeleteLocalRef(juuid);
+
+  JNIStringHolder configDirectory(jconfigDirectory);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+  env->DeleteLocalRef(jconfigDirectory);
+
+  JNIStringHolder usernameStr(jusername);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+  env->DeleteLocalRef(jusername);
+
+  JNIStringHolder passwordStr(jpassword);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+  env->DeleteLocalRef(jpassword);
+
+  Prompter *prompter = NULL;
+  if (jprompter != NULL)
+    {
+      prompter = Prompter::makeCPrompter(jprompter);
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+    }
+
+  jobject jremoteSession = open(
+      jretryAttempts, url, uuid, configDirectory,
+      usernameStr, passwordStr, prompter, jprogress);
+  if (JNIUtil::isExceptionThrown() || !jremoteSession)
+    {
+      delete prompter;
+      jremoteSession = NULL;
+    }
+  return jremoteSession;
+}
+
+jobject
+RemoteSession::open(jint jretryAttempts,
+                    const char* url, const char* uuid,
+                    const char* configDirectory,
+                    const char*  usernameStr, const char*  passwordStr,
+                    Prompter* prompter, jobject jprogress)
+{
+  /*
+   * Initialize ra layer if we have not done so yet
+   */
+  static bool initialized = false;
+  if (!initialized)
+    {
+      SVN_JNI_ERR(svn_ra_initialize(JNIUtil::getPool()), NULL);
+      initialized = true;
+    }
+
+  jobject jthis_out = NULL;
+  RemoteSession* session = new RemoteSession(
+      &jthis_out, jretryAttempts, url, uuid, configDirectory,
+      usernameStr, passwordStr, prompter, jprogress);
+  if (JNIUtil::isJavaExceptionThrown() || !session)
+    {
+      delete session;
+      jthis_out = NULL;
+    }
+  return jthis_out;
+}
+
+
+namespace{
+  struct compare_c_strings
+  {
+    bool operator()(const char* a, const char* b)
+      {
+        return (0 < std::strcmp(a, b));
+      }
+  };
+  typedef std::set<const char*, compare_c_strings> attempt_set;
+  typedef std::pair<attempt_set::iterator, bool> attempt_insert;
+} // anonymous namespace
+
+RemoteSession::RemoteSession(jobject* jthis_out, int retryAttempts,
+                             const char* url, const char* uuid,
+                             const char* configDirectory,
+                             const char*  username, const char*  password,
+                             Prompter* prompter, jobject jprogress)
+  : m_session(NULL), m_context(NULL)
+{
+  // Create java session object
+  JNIEnv *env = JNIUtil::getEnv();
+
+  jclass clazz = env->FindClass(JAVA_CLASS_REMOTE_SESSION);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  static jmethodID ctor = 0;
+  if (ctor == 0)
+    {
+      ctor = env->GetMethodID(clazz, "<init>", "(J)V");
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+    }
+
+  jlong cppAddr = this->getCppAddr();
+
+  jobject jremoteSession = env->NewObject(clazz, ctor, cppAddr);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  m_context = new RemoteSessionContext(
+      jremoteSession, pool, configDirectory,
+      username, password, prompter, jprogress);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  const char* corrected_url = NULL;
+  bool cycle_detected = false;
+  attempt_set attempted;
+
+  while (retryAttempts-- >= 0)
+    {
+      SVN_JNI_ERR(
+          svn_ra_open4(&m_session, &corrected_url,
+                       url, uuid, m_context->getCallbacks(),
+                       m_context->getCallbackBaton(),
+                       m_context->getConfigData(),
+                       pool.getPool()),
+                  );
+
+      if (!corrected_url)
+        break;
+
+      attempt_insert result = attempted.insert(corrected_url);
+      if (!result.second)
+        {
+          cycle_detected = true;
+          break;
+        }
+    }
+
+  if (cycle_detected)
+    {
+      jstring exmsg = JNIUtil::makeJString(
+          apr_psprintf(pool.getPool(),
+                       _("Redirect cycle detected for URL '%s'"),
+                       corrected_url));
+
+      jclass excls = env->FindClass(
+          JAVA_PACKAGE "/SubversionException");
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+
+      static jmethodID exctor = 0;
+      if (exctor == 0)
+        {
+          exctor = env->GetMethodID(excls, "<init>", "(J)V");
+          if (JNIUtil::isJavaExceptionThrown())
+            return;
+        }
+
+      jobject ex = env->NewObject(excls, exctor, exmsg);
+      env->Throw(static_cast<jthrowable>(ex));
+      return;
+    }
+
+  if (corrected_url)
+    {
+      jstring exmsg = JNIUtil::makeJString(_("Too many redirects"));
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+
+      jstring exurl = JNIUtil::makeJString(corrected_url);
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+
+      jclass excls = env->FindClass(
+          JAVA_PACKAGE "/remote/RetryOpenSession");
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+
+      static jmethodID exctor = 0;
+      if (exctor == 0)
+        {
+          exctor = env->GetMethodID(excls, "<init>", "(JJ)V");
+          if (JNIUtil::isJavaExceptionThrown())
+            return;
+        }
+
+      jobject ex = env->NewObject(excls, exctor, exmsg, exurl);
+      env->Throw(static_cast<jthrowable>(ex));
+      return;
+    }
+
+  *jthis_out = jremoteSession;
+}
+
+RemoteSession::~RemoteSession()
+{
+  delete m_context;
+}
+
+void
+RemoteSession::dispose(jobject jthis)
+{
+  static jfieldID fid = 0;
+  SVNBase::dispose(jthis, &fid, JAVA_CLASS_REMOTE_SESSION);
+}
+
+void RemoteSession::reparent(jstring jurl)
+{
+  JNIStringHolder url(jurl);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  SVN::Pool subPool(pool);
+  SVN_JNI_ERR(svn_ra_reparent(m_session, url, subPool.getPool()), );
+}
+
+jstring
+RemoteSession::getSessionUrl()
+{
+  SVN::Pool subPool(pool);
+  const char* url;
+  SVN_JNI_ERR(svn_ra_get_session_url(m_session, &url, subPool.getPool()), NULL);
+
+  jstring jurl = JNIUtil::makeJString(url);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return jurl;
+}
+
+jstring
+RemoteSession::getSessionRelativePath(jstring jurl)
+{
+  JNIStringHolder url(jurl);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  SVN::Pool subPool(pool);
+  const char* rel_path;
+  SVN_JNI_ERR(svn_ra_get_path_relative_to_session(
+                  m_session, &rel_path, url, subPool.getPool()),
+              NULL);
+  jstring jrel_path = JNIUtil::makeJString(rel_path);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return jrel_path;
+}
+
+jstring
+RemoteSession::getReposRelativePath(jstring jurl)
+{
+  JNIStringHolder url(jurl);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  SVN::Pool subPool(pool);
+  const char* rel_path;
+  SVN_JNI_ERR(svn_ra_get_path_relative_to_root(m_session, &rel_path, url,
+                                               subPool.getPool()),
+              NULL);
+
+  jstring jrel_path = JNIUtil::makeJString(rel_path);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return jrel_path;
+}
+
+jstring
+RemoteSession::getReposUUID()
+{
+  SVN::Pool subPool(pool);
+  const char * uuid;
+  SVN_JNI_ERR(svn_ra_get_uuid2(m_session, &uuid, subPool.getPool()), NULL);
+
+  jstring juuid = JNIUtil::makeJString(uuid);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return juuid;
+}
+
+jstring
+RemoteSession::getReposRootUrl()
+{
+  SVN::Pool subPool(pool);
+  const char* url;
+  SVN_JNI_ERR(svn_ra_get_repos_root2(m_session, &url, subPool.getPool()),
+              NULL);
+
+  jstring jurl = JNIUtil::makeJString(url);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return jurl;
+}
+
+jlong
+RemoteSession::getLatestRevision()
+{
+  SVN::Pool subPool(pool);
+  svn_revnum_t rev;
+  SVN_JNI_ERR(svn_ra_get_latest_revnum(m_session, &rev, subPool.getPool()),
+              SVN_INVALID_REVNUM);
+  return rev;
+}
+
+jlong
+RemoteSession::getRevisionByTimestamp(jlong timestamp)
+{
+  SVN::Pool subPool(pool);
+  svn_revnum_t rev;
+  SVN_JNI_ERR(svn_ra_get_dated_revision(m_session, &rev,
+                                        apr_time_t(timestamp),
+                                        subPool.getPool()),
+              SVN_INVALID_REVNUM);
+  return rev;
+}
+
+jobject
+RemoteSession::getLocks(jstring jpath, jobject jdepth)
+{
+  JNIStringHolder path(jpath);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  svn_depth_t depth = EnumMapper::toDepth(jdepth);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  SVN::Pool subPool(pool);
+  apr_hash_t *locks;
+  SVN_JNI_ERR(svn_ra_get_locks2(m_session, &locks, path, depth,
+                                subPool.getPool()),
+              NULL);
+
+  return CreateJ::LockMap(locks, subPool.getPool());
+}
+
+jobject
+RemoteSession::checkPath(jstring jpath, jlong jrevision)
+{
+  JNIStringHolder path(jpath);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  SVN::Pool subPool(pool);
+  svn_node_kind_t kind;
+  SVN_JNI_ERR(svn_ra_check_path(m_session, path,
+                                svn_revnum_t(jrevision),
+                                &kind, subPool.getPool()),
+              NULL);
+
+  return EnumMapper::mapNodeKind(kind);
+}
+
+jboolean
+RemoteSession::hasCapability(jstring jcapability)
+{
+  JNIStringHolder capability(jcapability);
+  if (JNIUtil::isExceptionThrown())
+    return false;
+
+  SVN::Pool subPool(pool);
+  svn_boolean_t has;
+  SVN_JNI_ERR(svn_ra_has_capability(m_session, &has, capability,
+                                    subPool.getPool()),
+              false);
+
+  return jboolean(has);
+}
diff --git a/subversion/bindings/javahl/native/RemoteSession.h b/subversion/bindings/javahl/native/RemoteSession.h
new file mode 100644
index 0000000..17bf1c8
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSession.h
@@ -0,0 +1,85 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSession.h
+ * @brief Interface of the class RemoteSession
+ */
+
+#ifndef JAVAHL_REMOTE_SESSION_H
+#define JAVAHL_REMOTE_SESSION_H
+
+#include <jni.h>
+
+#include "svn_ra.h"
+
+#include "SVNBase.h"
+#include "RemoteSessionContext.h"
+#include "Prompter.h"
+
+/*
+ * This class wraps Ra based operations from svn_ra.h
+ */
+class RemoteSession : public SVNBase
+{
+  public:
+    static RemoteSession* getCppObject(jobject jthis);
+    static jobject open(jint jretryAttempts,
+                        jstring jurl, jstring juuid,
+                        jstring jconfigDirectory,
+                        jstring jusername, jstring jpassword,
+                        jobject jprompter, jobject jprogress);
+    static jobject open(jint jretryAttempts,
+                        const char* url, const char* uuid,
+                        const char* configDirectory,
+                        const char* username, const char* password,
+                        Prompter* prompter, jobject jprogress);
+    ~RemoteSession();
+
+    void cancelOperation() const { m_context->cancelOperation(); }
+
+    virtual void dispose(jobject jthis);
+
+    void reparent(jstring jurl);
+    jstring getSessionUrl();
+    jstring getSessionRelativePath(jstring jurl);
+    jstring getReposRelativePath(jstring jurl);
+    jstring getReposUUID();
+    jstring getReposRootUrl();
+    jlong getLatestRevision();
+
+    jlong getRevisionByTimestamp(jlong timestamp);
+    jobject getLocks(jstring jpath, jobject jdepth);
+    jobject checkPath(jstring jpath, jlong jrevision);
+    jboolean hasCapability(jstring capability);
+
+  private:
+    RemoteSession(jobject*, int retryAttempts,
+                  const char* url, const char* uuid,
+                  const char* configDirectory,
+                  const char* username, const char* password,
+                  Prompter* prompter, jobject jprogress);
+
+    svn_ra_session_t* m_session;
+    RemoteSessionContext* m_context;
+};
+
+#endif // JAVAHL_REMOTE_SESSION_H
diff --git a/subversion/bindings/javahl/native/RemoteSessionContext.cpp b/subversion/bindings/javahl/native/RemoteSessionContext.cpp
new file mode 100644
index 0000000..b5f40a8
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSessionContext.cpp
@@ -0,0 +1,114 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSessionContext.cpp
+ * @brief Implementation of the class RemoteSessionContext
+ */
+
+
+#include "RemoteSessionContext.h"
+#include "JNIUtil.h"
+#include "Prompter.h"
+
+#define STRING_RETURN_SIGNATURE "()Ljava/lang/String;"
+
+RemoteSessionContext::RemoteSessionContext(
+    jobject contextHolder, SVN::Pool &pool, const char* configDirectory,
+    const char*  usernameStr, const char*  passwordStr,
+    Prompter* prompter, jobject jprogress)
+  : OperationContext(pool), m_raCallbacks(NULL)
+{
+  setConfigDirectory(configDirectory);
+  if (usernameStr != NULL)
+    username(usernameStr);
+
+  if (passwordStr != NULL)
+    password(passwordStr);
+
+  setPrompt(prompter);
+
+  /*
+   * Attach session context java object
+   */
+  static jfieldID ctxFieldID = 0;
+  attachJavaObject(contextHolder,
+      "L"JAVA_PACKAGE"/remote/RemoteSession$RemoteSessionContext;",
+      "sessionContext", &ctxFieldID);
+
+  /*
+   * Set the progress callback
+   */
+  JNIEnv *env = JNIUtil::getEnv();
+
+  jclass clazz = env->GetObjectClass(m_jctx);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  jmethodID mid = env->GetMethodID(
+      clazz, "setProgressCallback",
+      "(L"JAVA_PACKAGE"/callback/ProgressCallback;)V");
+  if (JNIUtil::isJavaExceptionThrown() || mid == 0)
+    return;
+
+  env->CallVoidMethod(m_jctx, mid, jprogress);
+  env->DeleteLocalRef(jprogress);
+
+  /*
+   * Setup callbacks
+   */
+  SVN_JNI_ERR(svn_ra_create_callbacks(&m_raCallbacks, m_pool->getPool()), );
+
+  m_raCallbacks->auth_baton = getAuthBaton(pool);
+  m_raCallbacks->cancel_func = checkCancel;
+  m_raCallbacks->get_client_string = clientName;
+  m_raCallbacks->progress_baton = m_jctx;
+  m_raCallbacks->progress_func = progress;
+
+  /*
+   * JNI RA layer does not work with WC so all WC callbacks are set to NULL
+   */
+  m_raCallbacks->get_wc_prop = NULL;
+  m_raCallbacks->invalidate_wc_props = NULL;
+  m_raCallbacks->push_wc_prop = NULL;
+  m_raCallbacks->set_wc_prop = NULL;
+
+  /*
+   * Don't set deprecated callback
+   */
+  m_raCallbacks->open_tmp_file = NULL;
+}
+
+RemoteSessionContext::~RemoteSessionContext()
+{
+}
+
+void *
+RemoteSessionContext::getCallbackBaton()
+{
+  return this;
+}
+
+svn_ra_callbacks2_t *
+RemoteSessionContext::getCallbacks()
+{
+  return m_raCallbacks;
+}
diff --git a/subversion/bindings/javahl/native/RemoteSessionContext.h b/subversion/bindings/javahl/native/RemoteSessionContext.h
new file mode 100644
index 0000000..7b518fd
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSessionContext.h
@@ -0,0 +1,49 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSessionContext.h
+ * @brief Interface of the class RemoteSessionContext
+ */
+
+#ifndef JAVAHL_REMOTE_SESSION_CONTEXT_H
+#define JAVAHL_REMOTE_SESSION_CONTEXT_H
+
+#include "svn_ra.h"
+
+#include "OperationContext.h"
+
+class RemoteSessionContext : public OperationContext
+{
+  public:
+    RemoteSessionContext(jobject contextHolder, SVN::Pool &pool,
+                         const char* jconfigDirectory,
+                         const char* jusername, const char* jpassword,
+                         Prompter* prompter, jobject jprogress);
+    virtual ~RemoteSessionContext();
+    void * getCallbackBaton();
+    svn_ra_callbacks2_t* getCallbacks();
+
+  private:
+    svn_ra_callbacks2_t* m_raCallbacks;
+};
+
+#endif /* JAVAHL_REMOTE_SESSION_CONTEXT_H */
diff --git a/subversion/bindings/javahl/native/ReposNotifyCallback.cpp b/subversion/bindings/javahl/native/ReposNotifyCallback.cpp
index 2b3194f..a716653 100644
--- a/subversion/bindings/javahl/native/ReposNotifyCallback.cpp
+++ b/subversion/bindings/javahl/native/ReposNotifyCallback.cpp
@@ -49,7 +49,7 @@
                             apr_pool_t *pool)
 {
   if (baton)
-    ((ReposNotifyCallback *)baton)->onNotify(notify, pool);
+    static_cast<ReposNotifyCallback *>(baton)->onNotify(notify, pool);
 }
 
 /**
diff --git a/subversion/bindings/javahl/native/Revision.cpp b/subversion/bindings/javahl/native/Revision.cpp
index 32eaa47..7ba2094 100644
--- a/subversion/bindings/javahl/native/Revision.cpp
+++ b/subversion/bindings/javahl/native/Revision.cpp
@@ -31,7 +31,7 @@
 const svn_opt_revision_kind Revision::START = svn_opt_revision_unspecified;
 const svn_opt_revision_kind Revision::HEAD = svn_opt_revision_head;
 
-Revision::Revision (const svn_opt_revision_kind kind)
+Revision::Revision(const svn_opt_revision_kind kind)
 {
   m_revision.kind = kind;
   m_revision.value.number = 0;
@@ -149,7 +149,7 @@
 {
 }
 
-const svn_opt_revision_t *Revision::revision () const
+const svn_opt_revision_t *Revision::revision() const
 {
   return &m_revision;
 }
diff --git a/subversion/bindings/javahl/native/RevisionRange.cpp b/subversion/bindings/javahl/native/RevisionRange.cpp
index b73d5a4..677c7d5 100644
--- a/subversion/bindings/javahl/native/RevisionRange.cpp
+++ b/subversion/bindings/javahl/native/RevisionRange.cpp
@@ -20,7 +20,7 @@
  * ====================================================================
  * @endcopyright
  *
- * @file RevisionRanges.cpp
+ * @file RevisionRange.cpp
  * @brief Implementation of the class RevisionRange.
  */
 
@@ -87,7 +87,8 @@
     return NULL;
 
   svn_opt_revision_range_t *range =
-    (svn_opt_revision_range_t *) apr_palloc(pool.getPool(), sizeof(*range));
+    reinterpret_cast<svn_opt_revision_range_t *>
+      (apr_palloc(pool.getPool(), sizeof(*range)));
 
   range->start = *startRevision.revision();
   if (JNIUtil::isExceptionThrown())
diff --git a/subversion/bindings/javahl/native/RevpropTable.cpp b/subversion/bindings/javahl/native/RevpropTable.cpp
index 2f1d7b9..f273a73 100644
--- a/subversion/bindings/javahl/native/RevpropTable.cpp
+++ b/subversion/bindings/javahl/native/RevpropTable.cpp
@@ -41,9 +41,9 @@
     JNIUtil::getEnv()->DeleteLocalRef(m_revpropTable);
 }
 
-const apr_hash_t *RevpropTable::hash(const SVN::Pool &pool)
+apr_hash_t *RevpropTable::hash(const SVN::Pool &pool, bool nullIfEmpty)
 {
-  if (m_revprops.size() == 0)
+  if (m_revprops.size() == 0 && nullIfEmpty)
     return NULL;
 
   apr_hash_t *revprop_table = apr_hash_make(pool.getPool());
@@ -77,7 +77,7 @@
 
   if (jrevpropTable != NULL)
     {
-      static jmethodID keySet = 0, toArray = 0, get = 0;
+      static jmethodID keySet = 0, get = 0;
       JNIEnv *env = JNIUtil::getEnv();
 
       jclass mapClazz = env->FindClass("java/util/Map");
@@ -120,8 +120,8 @@
           if (JNIUtil::isExceptionThrown())
             return;
 
-          m_revprops[std::string((const char *)propname)]
-            = std::string((const char *)propval);
+          m_revprops[std::string(static_cast<const char *>(propname))]
+            = std::string(static_cast<const char *>(propval));
 
           JNIUtil::getEnv()->DeleteLocalRef(jpropval);
         }
diff --git a/subversion/bindings/javahl/native/RevpropTable.h b/subversion/bindings/javahl/native/RevpropTable.h
index ee5f14f..e90d89c 100644
--- a/subversion/bindings/javahl/native/RevpropTable.h
+++ b/subversion/bindings/javahl/native/RevpropTable.h
@@ -44,7 +44,7 @@
  public:
   RevpropTable(jobject jrevpropTable);
   ~RevpropTable();
-  const apr_hash_t *hash(const SVN::Pool &pool);
+  apr_hash_t *hash(const SVN::Pool &pool, bool nullIfEmpty = true);
 };
 
 #endif // REVPROPTABLE_H
diff --git a/subversion/bindings/javahl/native/SVNBase.cpp b/subversion/bindings/javahl/native/SVNBase.cpp
index d8e7310..5e20f93 100644
--- a/subversion/bindings/javahl/native/SVNBase.cpp
+++ b/subversion/bindings/javahl/native/SVNBase.cpp
@@ -30,7 +30,6 @@
 SVNBase::SVNBase()
     : pool(JNIUtil::getPool())
 {
-  jthis = NULL;
 }
 
 SVNBase::~SVNBase()
@@ -58,17 +57,6 @@
       if (JNIUtil::isJavaExceptionThrown())
         return 0;
 
-      if (cppAddr)
-        {
-          /* jthis is not guaranteed to be the same between JNI invocations, so
-             we do a little dance here and store the updated version in our
-             object for this invocation.
-
-             findCppAddrForJObject() is, by necessity, called before any other
-             methods on the C++ object, so by doing this we can guarantee a
-             valid jthis pointer for subsequent uses. */
-          (reinterpret_cast<SVNBase *> (cppAddr))->jthis = jthis;
-        }
       return cppAddr;
     }
 }
@@ -82,17 +70,15 @@
   JNIUtil::enqueueForDeletion(this);
 }
 
-void SVNBase::dispose(jfieldID *fid, const char *className)
+void SVNBase::dispose(jobject jthis, jfieldID *fid, const char *className)
 {
-  jobject my_jthis = this->jthis;
-
   delete this;
   JNIEnv *env = JNIUtil::getEnv();
   SVNBase::findCppAddrFieldID(fid, className, env);
   if (*fid == 0)
     return;
 
-  env->SetLongField(my_jthis, *fid, 0);
+  env->SetLongField(jthis, *fid, 0);
   if (JNIUtil::isJavaExceptionThrown())
     return;
 }
@@ -111,3 +97,29 @@
         }
     }
 }
+
+jobject SVNBase::createCppBoundObject(const char *clazzName)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+
+  // Create java session object
+  jclass clazz = env->FindClass(clazzName);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  static jmethodID ctor = 0;
+  if (ctor == 0)
+    {
+      ctor = env->GetMethodID(clazz, "<init>", "(J)V");
+      if (JNIUtil::isJavaExceptionThrown())
+        return NULL;
+    }
+
+  jlong cppAddr = this->getCppAddr();
+
+  jobject jself = env->NewObject(clazz, ctor, cppAddr);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return jself;
+}
diff --git a/subversion/bindings/javahl/native/SVNBase.h b/subversion/bindings/javahl/native/SVNBase.h
index 18ce43a..9b3d41a 100644
--- a/subversion/bindings/javahl/native/SVNBase.h
+++ b/subversion/bindings/javahl/native/SVNBase.h
@@ -49,7 +49,7 @@
    *
    * @since 1.4.0
    */
-  virtual void dispose() = 0;
+  virtual void dispose(jobject jthis) = 0;
 
   /**
    * This method should never be called, as @c dispose() should be
@@ -80,13 +80,12 @@
    *
    * @since 1.4.0
    */
-  void dispose(jfieldID *fid, const char *className);
+  void dispose(jobject jthis, jfieldID *fid, const char *className);
 
   /**
-   * A pointer to the parent java object.  This is not valid across JNI
-   * method invocations, and so should be set in each one.
+   * Instantiates java object attached to this base object
    */
-  jobject jthis;
+  jobject createCppBoundObject(const char *clazzName);
 
  private:
   /**
diff --git a/subversion/bindings/javahl/native/SVNClient.cpp b/subversion/bindings/javahl/native/SVNClient.cpp
index f8a840f..6344377 100644
--- a/subversion/bindings/javahl/native/SVNClient.cpp
+++ b/subversion/bindings/javahl/native/SVNClient.cpp
@@ -30,6 +30,7 @@
 #include "DiffSummaryReceiver.h"
 #include "ClientContext.h"
 #include "Prompter.h"
+#include "RemoteSession.h"
 #include "Pool.h"
 #include "Targets.h"
 #include "Revision.h"
@@ -67,10 +68,11 @@
 #include <vector>
 #include <iostream>
 #include <sstream>
+#include <string>
 
 
 SVNClient::SVNClient(jobject jthis_in)
-    : context(jthis_in, pool), m_lastPath("", pool)
+    : m_lastPath("", pool), context(jthis_in, pool)
 {
 }
 
@@ -86,10 +88,10 @@
     return (cppAddr == 0 ? NULL : reinterpret_cast<SVNClient *>(cppAddr));
 }
 
-void SVNClient::dispose()
+void SVNClient::dispose(jobject jthis)
 {
     static jfieldID fid = 0;
-    SVNBase::dispose(&fid, JAVA_PACKAGE"/SVNClient");
+    SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNClient");
 }
 
 jstring SVNClient::getAdminDirectoryName()
@@ -130,7 +132,7 @@
     SVN_JNI_NULL_PTR_EX(url, "path or url", );
 
     Path urlPath(url, subPool);
-    SVN_JNI_ERR(urlPath.error_occured(), );
+    SVN_JNI_ERR(urlPath.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_list2(urlPath.c_str(),
                                  pegRevision.revision(),
@@ -161,7 +163,7 @@
     callback->setWcCtx(ctx->wc_ctx);
 
     Path checkedPath(path, subPool);
-    SVN_JNI_ERR(checkedPath.error_occured(), );
+    SVN_JNI_ERR(checkedPath.error_occurred(), );
 
     rev.kind = svn_opt_revision_unspecified;
 
@@ -175,6 +177,43 @@
                                    subPool.getPool()), );
 }
 
+/* Convert a vector of revision ranges to an APR array of same. */
+static apr_array_header_t *
+rev_range_vector_to_apr_array(std::vector<RevisionRange> &revRanges,
+                              SVN::Pool &subPool)
+{
+    apr_array_header_t *ranges =
+      apr_array_make(subPool.getPool(),
+                     static_cast<int>(revRanges.size()),
+                     sizeof(svn_opt_revision_range_t *));
+
+    std::vector<RevisionRange>::const_iterator it;
+    for (it = revRanges.begin(); it != revRanges.end(); ++it)
+    {
+        if (it->toRange(subPool)->start.kind
+            == svn_opt_revision_unspecified
+            && it->toRange(subPool)->end.kind
+            == svn_opt_revision_unspecified)
+        {
+            svn_opt_revision_range_t *range =
+                reinterpret_cast<svn_opt_revision_range_t *>
+                    (apr_pcalloc(subPool.getPool(), sizeof(*range)));
+            range->start.kind = svn_opt_revision_number;
+            range->start.value.number = 1;
+            range->end.kind = svn_opt_revision_head;
+            APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
+        }
+        else
+        {
+            APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
+                it->toRange(subPool);
+        }
+        if (JNIUtil::isExceptionThrown())
+            return NULL;
+    }
+    return ranges;
+}
+
 void SVNClient::logMessages(const char *path, Revision &pegRevision,
                             std::vector<RevisionRange> &logRanges,
                             bool stopOnCopy, bool discoverPaths,
@@ -191,36 +230,12 @@
 
     Targets target(path, subPool);
     const apr_array_header_t *targets = target.array(subPool);
-    SVN_JNI_ERR(target.error_occured(), );
+    SVN_JNI_ERR(target.error_occurred(), );
 
     apr_array_header_t *ranges =
-        apr_array_make(subPool.getPool(), logRanges.size(),
-                       sizeof(svn_opt_revision_range_t *));
-
-    std::vector<RevisionRange>::const_iterator it;
-    for (it = logRanges.begin(); it != logRanges.end(); ++it)
-    {
-        if (it->toRange(subPool)->start.kind
-            == svn_opt_revision_unspecified
-            && it->toRange(subPool)->end.kind
-            == svn_opt_revision_unspecified)
-        {
-            svn_opt_revision_range_t *range =
-                (svn_opt_revision_range_t *)apr_pcalloc(subPool.getPool(),
-                                                        sizeof(*range));
-            range->start.kind = svn_opt_revision_number;
-            range->start.value.number = 1;
-            range->end.kind = svn_opt_revision_head;
-            APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
-        }
-        else
-        {
-            APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
-                it->toRange(subPool);
-        }
-        if (JNIUtil::isExceptionThrown())
-            return;
-    }
+      rev_range_vector_to_apr_array(logRanges, subPool);
+    if (JNIUtil::isExceptionThrown())
+        return;
 
     SVN_JNI_ERR(svn_client_log5(targets, pegRevision.revision(), ranges,
                                 limit, discoverPaths, stopOnCopy,
@@ -242,8 +257,8 @@
 
     Path url(moduleName, subPool);
     Path path(destPath, subPool);
-    SVN_JNI_ERR(url.error_occured(), -1);
-    SVN_JNI_ERR(path.error_occured(), -1);
+    SVN_JNI_ERR(url.error_occurred(), -1);
+    SVN_JNI_ERR(path.error_occurred(), -1);
     svn_revnum_t rev;
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
@@ -274,7 +289,7 @@
         return;
 
     const apr_array_header_t *targets2 = targets.array(subPool);
-    SVN_JNI_ERR(targets.error_occured(), );
+    SVN_JNI_ERR(targets.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_delete4(targets2, force, keep_local,
                                    revprops.hash(subPool),
@@ -295,14 +310,15 @@
 
     Targets target(path, subPool);
     const apr_array_header_t *targets = target.array(subPool);
-    SVN_JNI_ERR(target.error_occured(), );
+    SVN_JNI_ERR(target.error_occurred(), );
     SVN_JNI_ERR(svn_client_revert2(targets, depth,
                                    changelists.array(subPool), ctx,
                                    subPool.getPool()), );
 }
 
 void SVNClient::add(const char *path,
-                    svn_depth_t depth, bool force, bool no_ignore,
+                    svn_depth_t depth, bool force,
+                    bool no_ignore, bool no_autoprops,
                     bool add_parents)
 {
     SVN::Pool subPool(pool);
@@ -310,7 +326,7 @@
     SVN_JNI_NULL_PTR_EX(path, "path", );
 
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
         return;
@@ -333,7 +349,7 @@
         return NULL;
 
     const apr_array_header_t *array = targets.array(subPool);
-    SVN_JNI_ERR(targets.error_occured(), NULL);
+    SVN_JNI_ERR(targets.error_occurred(), NULL);
     SVN_JNI_ERR(svn_client_update4(&revs, array,
                                    revision.revision(),
                                    depth,
@@ -369,13 +385,14 @@
 {
     SVN::Pool subPool(pool);
     const apr_array_header_t *targets2 = targets.array(subPool);
-    SVN_JNI_ERR(targets.error_occured(), );
+    SVN_JNI_ERR(targets.error_occurred(), );
     svn_client_ctx_t *ctx = context.getContext(message, subPool);
     if (ctx == NULL)
         return;
 
     SVN_JNI_ERR(svn_client_commit5(targets2, depth,
-                                   noUnlock, keepChangelist, TRUE,
+                                   noUnlock, keepChangelist,
+                                   TRUE,
                                    changelists.array(subPool),
                                    revprops.hash(subPool),
                                    CommitCallback::callback, callback,
@@ -399,7 +416,7 @@
     }
     SVN_JNI_NULL_PTR_EX(destPath, "destPath", );
     Path destinationPath(destPath, subPool);
-    SVN_JNI_ERR(destinationPath.error_occured(), );
+    SVN_JNI_ERR(destinationPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(message, subPool);
     if (ctx == NULL)
@@ -414,16 +431,16 @@
 
 void SVNClient::move(Targets &srcPaths, const char *destPath,
                      CommitMessage *message, bool force, bool moveAsChild,
-                     bool makeParents, RevpropTable &revprops,
-                     CommitCallback *callback)
+                     bool makeParents, bool metadataOnly, bool allowMixRev,
+                     RevpropTable &revprops, CommitCallback *callback)
 {
     SVN::Pool subPool(pool);
 
     const apr_array_header_t *srcs = srcPaths.array(subPool);
-    SVN_JNI_ERR(srcPaths.error_occured(), );
+    SVN_JNI_ERR(srcPaths.error_occurred(), );
     SVN_JNI_NULL_PTR_EX(destPath, "destPath", );
     Path destinationPath(destPath, subPool);
-    SVN_JNI_ERR(destinationPath.error_occured(), );
+    SVN_JNI_ERR(destinationPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(message, subPool);
     if (ctx == NULL)
@@ -446,7 +463,7 @@
         return;
 
     const apr_array_header_t *targets2 = targets.array(subPool);
-    SVN_JNI_ERR(targets.error_occured(), );
+    SVN_JNI_ERR(targets.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_mkdir4(targets2, makeParents,
                                   revprops.hash(subPool),
@@ -459,7 +476,7 @@
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -474,7 +491,7 @@
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
         return;
@@ -492,9 +509,9 @@
     SVN_JNI_NULL_PTR_EX(srcPath, "srcPath", -1);
     SVN_JNI_NULL_PTR_EX(destPath, "destPath", -1);
     Path sourcePath(srcPath, subPool);
-    SVN_JNI_ERR(sourcePath.error_occured(), -1);
+    SVN_JNI_ERR(sourcePath.error_occurred(), -1);
     Path destinationPath(destPath, subPool);
-    SVN_JNI_ERR(destinationPath.error_occured(), -1);
+    SVN_JNI_ERR(destinationPath.error_occurred(), -1);
     svn_revnum_t rev;
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -525,9 +542,9 @@
     SVN_JNI_NULL_PTR_EX(path, "path", -1);
     SVN_JNI_NULL_PTR_EX(url, "url", -1);
     Path intUrl(url, subPool);
-    SVN_JNI_ERR(intUrl.error_occured(), -1);
+    SVN_JNI_ERR(intUrl.error_occurred(), -1);
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), -1);
+    SVN_JNI_ERR(intPath.error_occurred(), -1);
 
     svn_revnum_t rev;
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
@@ -552,16 +569,19 @@
 
 void SVNClient::doImport(const char *path, const char *url,
                          CommitMessage *message, svn_depth_t depth,
-                         bool noIgnore, bool ignoreUnknownNodeTypes,
-                         RevpropTable &revprops, CommitCallback *callback)
+                         bool noIgnore, bool noAutoProps,
+                         bool ignoreUnknownNodeTypes,
+                         RevpropTable &revprops,
+                         ImportFilterCallback *ifCallback,
+                         CommitCallback *commitCallback)
 {
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
     SVN_JNI_NULL_PTR_EX(url, "url", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
     Path intUrl(url, subPool);
-    SVN_JNI_ERR(intUrl.error_occured(), );
+    SVN_JNI_ERR(intUrl.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(message, subPool);
     if (ctx == NULL)
@@ -570,7 +590,7 @@
     SVN_JNI_ERR(svn_client_import4(intPath.c_str(), intUrl.c_str(), depth,
                                    noIgnore, ignoreUnknownNodeTypes,
                                    revprops.hash(subPool),
-                                   CommitCallback::callback, callback,
+                                   CommitCallback::callback, commitCallback,
                                    ctx, subPool.getPool()), );
 }
 
@@ -593,21 +613,22 @@
 
 void SVNClient::merge(const char *path1, Revision &revision1,
                       const char *path2, Revision &revision2,
-                      const char *localPath, bool force, svn_depth_t depth,
-                      bool ignoreAncestry, bool dryRun, bool recordOnly)
+                      const char *localPath, bool forceDelete,
+                      svn_depth_t depth, bool ignoreAncestry,
+                      bool dryRun, bool recordOnly)
 {
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path1, "path1", );
     SVN_JNI_NULL_PTR_EX(path2, "path2", );
     SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
     Path intLocalPath(localPath, subPool);
-    SVN_JNI_ERR(intLocalPath.error_occured(), );
+    SVN_JNI_ERR(intLocalPath.error_occurred(), );
 
     Path srcPath1(path1, subPool);
-    SVN_JNI_ERR(srcPath1.error_occured(), );
+    SVN_JNI_ERR(srcPath1.error_occurred(), );
 
     Path srcPath2(path2, subPool);
-    SVN_JNI_ERR(srcPath2.error_occured(), );
+    SVN_JNI_ERR(srcPath2.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -616,64 +637,42 @@
     SVN_JNI_ERR(svn_client_merge4(srcPath1.c_str(), revision1.revision(),
                                   srcPath2.c_str(), revision2.revision(),
                                   intLocalPath.c_str(),
-                                  depth,
-                                  ignoreAncestry, force, recordOnly, dryRun,
+                                  depth, ignoreAncestry,
+                                  forceDelete, recordOnly, dryRun,
                                   TRUE, NULL, ctx, subPool.getPool()), );
 }
 
 void SVNClient::merge(const char *path, Revision &pegRevision,
-                      std::vector<RevisionRange> &rangesToMerge,
-                      const char *localPath, bool force, svn_depth_t depth,
-                      bool ignoreAncestry, bool dryRun, bool recordOnly)
+                      std::vector<RevisionRange> *rangesToMerge,
+                      const char *localPath, bool forceDelete,
+                      svn_depth_t depth, bool ignoreAncestry,
+                      bool dryRun, bool recordOnly)
 {
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
     SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
     Path intLocalPath(localPath, subPool);
-    SVN_JNI_ERR(intLocalPath.error_occured(), );
+    SVN_JNI_ERR(intLocalPath.error_occurred(), );
 
     Path srcPath(path, subPool);
-    SVN_JNI_ERR(srcPath.error_occured(), );
+    SVN_JNI_ERR(srcPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
         return;
 
     apr_array_header_t *ranges =
-      apr_array_make(subPool.getPool(), rangesToMerge.size(),
-                     sizeof(const svn_opt_revision_range_t *));
-
-    std::vector<RevisionRange>::const_iterator it;
-    for (it = rangesToMerge.begin(); it != rangesToMerge.end(); ++it)
-    {
-        if (it->toRange(subPool)->start.kind
-            == svn_opt_revision_unspecified
-            && it->toRange(subPool)->end.kind
-            == svn_opt_revision_unspecified)
-        {
-            svn_opt_revision_range_t *range =
-                (svn_opt_revision_range_t *)apr_pcalloc(subPool.getPool(),
-                                                        sizeof(*range));
-            range->start.kind = svn_opt_revision_number;
-            range->start.value.number = 1;
-            range->end.kind = svn_opt_revision_head;
-            APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
-        }
-        else
-        {
-            APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
-                it->toRange(subPool);
-        }
-        if (JNIUtil::isExceptionThrown())
-            return;
-    }
+      (!rangesToMerge ? NULL
+       : rev_range_vector_to_apr_array(*rangesToMerge, subPool));
+    if (JNIUtil::isExceptionThrown())
+        return;
 
     SVN_JNI_ERR(svn_client_merge_peg4(srcPath.c_str(),
                                       ranges,
                                       pegRevision.revision(),
                                       intLocalPath.c_str(),
-                                      depth,
-                                      ignoreAncestry, force, recordOnly,
+                                      depth, ignoreAncestry,
+                                      forceDelete, recordOnly,
                                       dryRun, TRUE, NULL, ctx,
                                       subPool.getPool()), );
 }
@@ -685,10 +684,10 @@
     SVN_JNI_NULL_PTR_EX(path, "path", );
     SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
     Path intLocalPath(localPath, subPool);
-    SVN_JNI_ERR(intLocalPath.error_occured(), );
+    SVN_JNI_ERR(intLocalPath.error_occurred(), );
 
     Path srcPath(path, subPool);
-    SVN_JNI_ERR(srcPath.error_occured(), );
+    SVN_JNI_ERR(srcPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -713,7 +712,7 @@
 
     svn_mergeinfo_t mergeinfo;
     Path intLocalTarget(target, subPool);
-    SVN_JNI_ERR(intLocalTarget.error_occured(), NULL);
+    SVN_JNI_ERR(intLocalTarget.error_occurred(), NULL);
     SVN_JNI_ERR(svn_client_mergeinfo_get_merged(&mergeinfo,
                                                 intLocalTarget.c_str(),
                                                 pegRevision.revision(), ctx,
@@ -758,13 +757,13 @@
         void *val;
         apr_hash_this(hi, &path, NULL, &val);
 
-        jstring jpath = JNIUtil::makeJString((const char *) path);
+        jstring jpath =
+            JNIUtil::makeJString(reinterpret_cast<const char *>(path));
         jobject jranges =
             CreateJ::RevisionRangeList((apr_array_header_t *) val);
 
         env->CallVoidMethod(jmergeinfo, addRevisions, jpath, jranges);
 
-        env->DeleteLocalRef(jranges);
         env->DeleteLocalRef(jpath);
     }
 
@@ -790,11 +789,11 @@
 
     SVN_JNI_NULL_PTR_EX(pathOrURL, "path or url", );
     Path urlPath(pathOrURL, subPool);
-    SVN_JNI_ERR(urlPath.error_occured(), );
+    SVN_JNI_ERR(urlPath.error_occurred(), );
 
     SVN_JNI_NULL_PTR_EX(mergeSourceURL, "merge source url", );
     Path srcURL(mergeSourceURL, subPool);
-    SVN_JNI_ERR(srcURL.error_occured(), );
+    SVN_JNI_ERR(srcURL.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_mergeinfo_log((type == 1),
                                          urlPath.c_str(),
@@ -816,23 +815,24 @@
  * Get a property.
  */
 jbyteArray SVNClient::propertyGet(const char *path, const char *name,
-                                  Revision &revision, Revision &pegRevision)
+                                  Revision &revision, Revision &pegRevision,
+                                  StringArray &changelists)
 {
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", NULL);
     SVN_JNI_NULL_PTR_EX(name, "name", NULL);
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), NULL);
+    SVN_JNI_ERR(intPath.error_occurred(), NULL);
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
         return NULL;
 
     apr_hash_t *props;
-    SVN_JNI_ERR(svn_client_propget3(&props, name,
+    SVN_JNI_ERR(svn_client_propget4(&props, name,
                                     intPath.c_str(), pegRevision.revision(),
                                     revision.revision(), NULL, svn_depth_empty,
-                                    NULL, ctx, subPool.getPool()),
+                                    NULL, ctx, subPool.getPool(), subPool.getPool()),
                 NULL);
 
     apr_hash_index_t *hi;
@@ -842,23 +842,23 @@
         return NULL; // no property with this name
 
     svn_string_t *propval;
-    apr_hash_this(hi, NULL, NULL, (void**)&propval);
+    apr_hash_this(hi, NULL, NULL, reinterpret_cast<void**>(&propval));
 
     if (propval == NULL)
         return NULL;
 
-    return JNIUtil::makeJByteArray((const signed char *)propval->data,
-                                   propval->len);
+    return JNIUtil::makeJByteArray(propval);
 }
 
 void SVNClient::properties(const char *path, Revision &revision,
                            Revision &pegRevision, svn_depth_t depth,
-                           StringArray &changelists, ProplistCallback *callback)
+                           StringArray &changelists,
+                           ProplistCallback *callback)
 {
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -869,8 +869,6 @@
                                      changelists.array(subPool),
                                      ProplistCallback::callback, callback,
                                      ctx, subPool.getPool()), );
-
-    return;
 }
 
 void SVNClient::propertySetLocal(Targets &targets, const char *name,
@@ -884,8 +882,10 @@
     if (value.isNull())
       val = NULL;
     else
-      val = svn_string_ncreate((const char *)value.getBytes(), value.getLength(),
-                               subPool.getPool());
+      val = svn_string_ncreate
+               (reinterpret_cast<const char *>(value.getBytes()),
+                value.getLength(),
+                subPool.getPool());
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -912,11 +912,13 @@
     if (value.isNull())
       val = NULL;
     else
-      val = svn_string_ncreate((const char *)value.getBytes(), value.getLength(),
-                               subPool.getPool());
+      val = svn_string_ncreate
+               (reinterpret_cast<const char *>(value.getBytes()),
+                value.getLength(),
+                subPool.getPool());
 
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(message, subPool);
     if (ctx == NULL)
@@ -942,6 +944,7 @@
     const char *c_relToDir = relativeToDir ?
       svn_dirent_canonicalize(relativeToDir, subPool.getPool()) :
       relativeToDir;
+    bool noDiffAdded = false; /* ### Promote to argument */
 
     SVN_JNI_NULL_PTR_EX(target1, "target", );
     // target2 is ignored when pegRevision is provided.
@@ -954,7 +957,7 @@
         return;
 
     Path path1(target1, subPool);
-    SVN_JNI_ERR(path1.error_occured(), );
+    SVN_JNI_ERR(path1.error_occurred(), );
 
     apr_file_t *outfile = NULL;
     apr_status_t rv =
@@ -998,7 +1001,7 @@
     {
         // "Regular" diff (without a peg revision).
         Path path2(target2, subPool);
-        err = path2.error_occured();
+        err = path2.error_occurred();
         if (err)
         {
             if (outfile)
@@ -1081,9 +1084,9 @@
         return;
 
     Path path1(target1, subPool);
-    SVN_JNI_ERR(path1.error_occured(), );
+    SVN_JNI_ERR(path1.error_occurred(), );
     Path path2(target2, subPool);
-    SVN_JNI_ERR(path2.error_occured(), );
+    SVN_JNI_ERR(path2.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_diff_summarize2(path1.c_str(), revision1.revision(),
                                            path2.c_str(), revision2.revision(),
@@ -1110,7 +1113,7 @@
         return;
 
     Path path(target, subPool);
-    SVN_JNI_ERR(path.error_occured(), );
+    SVN_JNI_ERR(path.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_diff_summarize_peg2(path.c_str(),
                                                pegRevision.revision(),
@@ -1131,7 +1134,7 @@
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -1150,7 +1153,7 @@
     SVN_JNI_NULL_PTR_EX(path, "path", NULL);
     SVN_JNI_NULL_PTR_EX(name, "name", NULL);
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), NULL);
+    SVN_JNI_ERR(intPath.error_occurred(), NULL);
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -1178,8 +1181,7 @@
     if (propval == NULL)
         return NULL;
 
-    return JNIUtil::makeJByteArray((const signed char *)propval->data,
-                                   propval->len);
+    return JNIUtil::makeJByteArray(propval);
 }
 void SVNClient::relocate(const char *from, const char *to, const char *path,
                          bool ignoreExternals)
@@ -1189,13 +1191,13 @@
     SVN_JNI_NULL_PTR_EX(from, "from", );
     SVN_JNI_NULL_PTR_EX(to, "to", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     Path intFrom(from, subPool);
-    SVN_JNI_ERR(intFrom.error_occured(), );
+    SVN_JNI_ERR(intFrom.error_occurred(), );
 
     Path intTo(to, subPool);
-    SVN_JNI_ERR(intTo.error_occured(), );
+    SVN_JNI_ERR(intTo.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -1213,21 +1215,19 @@
 {
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", );
-    apr_pool_t *pool = subPool.getPool();
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
         return;
 
-    SVN_JNI_ERR(svn_client_blame5(intPath.c_str(), pegRevision.revision(),
-                                  revisionStart.revision(),
-                                  revisionEnd.revision(),
-                                  svn_diff_file_options_create(pool),
-                                  ignoreMimeType, includeMergedRevisions,
-                                  BlameCallback::callback, callback, ctx,
-                                  pool),
+    SVN_JNI_ERR(svn_client_blame5(
+          intPath.c_str(), pegRevision.revision(), revisionStart.revision(),
+          revisionEnd.revision(),
+          svn_diff_file_options_create(subPool.getPool()), ignoreMimeType,
+          includeMergedRevisions, BlameCallback::callback, callback, ctx,
+          subPool.getPool()),
         );
 }
 
@@ -1238,7 +1238,7 @@
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
 
     const apr_array_header_t *srcs = srcPaths.array(subPool);
-    SVN_JNI_ERR(srcPaths.error_occured(), );
+    SVN_JNI_ERR(srcPaths.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_add_to_changelist(srcs, changelist, depth,
                                              changelists.array(subPool),
@@ -1252,7 +1252,7 @@
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
 
     const apr_array_header_t *srcs = srcPaths.array(subPool);
-    SVN_JNI_ERR(srcPaths.error_occured(), );
+    SVN_JNI_ERR(srcPaths.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_remove_from_changelists(srcs, depth,
                                                 changelists.array(subPool),
@@ -1278,7 +1278,7 @@
 {
     SVN::Pool subPool(pool);
     const apr_array_header_t *targetsApr = targets.array(subPool);
-    SVN_JNI_ERR(targets.error_occured(), );
+    SVN_JNI_ERR(targets.error_occurred(), );
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
 
     SVN_JNI_ERR(svn_client_lock(targetsApr, comment, force, ctx,
@@ -1290,10 +1290,10 @@
     SVN::Pool subPool(pool);
 
     const apr_array_header_t *targetsApr = targets.array(subPool);
-    SVN_JNI_ERR(targets.error_occured(), );
+    SVN_JNI_ERR(targets.error_occurred(), );
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
-    SVN_JNI_ERR(svn_client_unlock((apr_array_header_t*)targetsApr, force,
-                                  ctx, subPool.getPool()), );
+    SVN_JNI_ERR(svn_client_unlock(
+        targetsApr, force, ctx, subPool.getPool()), );
 }
 void SVNClient::setRevProperty(const char *path,
                                const char *name, Revision &rev,
@@ -1304,7 +1304,7 @@
     SVN_JNI_NULL_PTR_EX(path, "path", );
     SVN_JNI_NULL_PTR_EX(name, "name", );
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), );
+    SVN_JNI_ERR(intPath.error_occurred(), );
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     if (ctx == NULL)
@@ -1342,7 +1342,7 @@
     SVN_JNI_NULL_PTR_EX(path, "path", NULL);
 
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), NULL);
+    SVN_JNI_ERR(intPath.error_occurred(), NULL);
 
     int wc_format;
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
@@ -1409,7 +1409,7 @@
         return;
 
     Path checkedPath(path, subPool);
-    SVN_JNI_ERR(checkedPath.error_occured(), );
+    SVN_JNI_ERR(checkedPath.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_upgrade(path, ctx, subPool.getPool()), );
 }
@@ -1420,7 +1420,7 @@
     SVN::Pool subPool(pool);
     SVN_JNI_NULL_PTR_EX(path, "path", NULL);
     Path intPath(path, subPool);
-    SVN_JNI_ERR(intPath.error_occured(), NULL);
+    SVN_JNI_ERR(intPath.error_occurred(), NULL);
 
     svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
     const char *URL;
@@ -1459,7 +1459,7 @@
         return;
 
     Path checkedPath(path, subPool);
-    SVN_JNI_ERR(checkedPath.error_occured(), );
+    SVN_JNI_ERR(checkedPath.error_occurred(), );
 
     SVN_JNI_ERR(svn_client_info3(checkedPath.c_str(),
                                  pegRevision.revision(),
@@ -1484,9 +1484,9 @@
         return;
 
     Path checkedPatchPath(patchPath, subPool);
-    SVN_JNI_ERR(checkedPatchPath.error_occured(), );
+    SVN_JNI_ERR(checkedPatchPath.error_occurred(), );
     Path checkedTargetPath(targetPath, subPool);
-    SVN_JNI_ERR(checkedTargetPath.error_occured(), );
+    SVN_JNI_ERR(checkedTargetPath.error_occurred(), );
 
     // Should parameterize the following, instead of defaulting to FALSE
     SVN_JNI_ERR(svn_client_patch(checkedPatchPath.c_str(),
@@ -1497,6 +1497,77 @@
                                  ctx, subPool.getPool()), );
 }
 
+jobject
+SVNClient::openRemoteSession(const char* path, int retryAttempts)
+{
+    static const svn_opt_revision_t HEAD = { svn_opt_revision_head, {0}};
+    static const svn_opt_revision_t NONE = { svn_opt_revision_unspecified, {0}};
+
+    SVN_JNI_NULL_PTR_EX(path, "path", NULL);
+
+    SVN::Pool subPool(pool);
+    svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
+    if (ctx == NULL)
+        return NULL;
+
+    Path checkedPath(path, subPool);
+    SVN_JNI_ERR(checkedPath.error_occurred(), NULL);
+
+    struct PathInfo
+    {
+        std::string url;
+        std::string uuid;
+        static svn_error_t *callback(void *baton,
+                                     const char *,
+                                     const svn_client_info2_t *info,
+                                     apr_pool_t *)
+          {
+              PathInfo* const pi = static_cast<PathInfo*>(baton);
+              pi->url = info->URL;
+              pi->uuid = info->repos_UUID;
+              return SVN_NO_ERROR;
+          }
+    } path_info;
+
+    SVN_JNI_ERR(svn_client_info3(
+                    checkedPath.c_str(), &NONE,
+                    (svn_path_is_url(checkedPath.c_str()) ? &HEAD : &NONE),
+                    svn_depth_empty, FALSE, TRUE, NULL,
+                    PathInfo::callback, &path_info,
+                    ctx, subPool.getPool()),
+                NULL);
+
+    jobject jctx = context.getSelf();
+    if (JNIUtil::isJavaExceptionThrown())
+        return NULL;
+
+    /* Decouple the RemoteSession's context from SVNClient's context
+       by creating a copy of the prompter here. */
+    Prompter* prompter = new Prompter(context.getPrompter());
+    if (!prompter)
+    {
+        /* context.getSelf() created a new global reference. */
+        JNIUtil::getEnv()->DeleteGlobalRef(jctx);
+        JNIUtil::throwNullPointerException("allocating Prompter");
+        return NULL;
+    }
+
+    jobject jremoteSession = RemoteSession::open(
+        retryAttempts, path_info.url.c_str(), path_info.uuid.c_str(),
+        context.getConfigDirectory(),
+        context.getUsername(), context.getPassword(),
+        prompter, jctx);
+    if (JNIUtil::isJavaExceptionThrown())
+    {
+        /* context.getSelf() created a new global reference. */
+        JNIUtil::getEnv()->DeleteGlobalRef(jctx);
+        jremoteSession = NULL;
+        delete prompter;
+    }
+
+    return jremoteSession;
+}
+
 ClientContext &
 SVNClient::getClientContext()
 {
diff --git a/subversion/bindings/javahl/native/SVNClient.h b/subversion/bindings/javahl/native/SVNClient.h
index 45ea79d..bbd6e2f 100644
--- a/subversion/bindings/javahl/native/SVNClient.h
+++ b/subversion/bindings/javahl/native/SVNClient.h
@@ -46,6 +46,7 @@
 class InfoCallback;
 class CommitCallback;
 class ListCallback;
+class ImportFilterCallback;
 class StatusCallback;
 class OutputStream;
 class PatchCallback;
@@ -53,6 +54,7 @@
 class CommitMessage;
 class StringArray;
 class RevpropTable;
+class DiffOptions;
 #include "svn_types.h"
 #include "svn_client.h"
 #include "SVNBase.h"
@@ -60,6 +62,7 @@
 class SVNClient :public SVNBase
 {
  public:
+  jobject openRemoteSession(const char* path, int);
   void patch(const char *patchPath, const char *targetPath, bool dryRun,
              int stripCount, bool reverse, bool ignoreWhitespace,
              bool removeTempfiles, PatchCallback *callback);
@@ -91,23 +94,28 @@
   jobject getMergeinfo(const char *target, Revision &pegRevision);
   void getMergeinfoLog(int type, const char *pathOrURL,
                        Revision &pegRevision, const char *mergeSourceURL,
-                       Revision &srcPegRevision, bool discoverChangedPaths,
+                       Revision &srcPegRevision,
+                       bool discoverChangedPaths,
                        svn_depth_t depth, StringArray &revProps,
                        LogMessageCallback *callback);
   jobject suggestMergeSources(const char *path, Revision &pegRevision);
-  void merge(const char *path1, Revision &revision1, const char *path2,
-             Revision &revision2, const char *localPath, bool force,
-             svn_depth_t depth, bool ignoreAncestry, bool dryRun,
-             bool recordOnly);
+  void merge(const char *path1, Revision &revision1,
+             const char *path2, Revision &revision2,
+             const char *localPath, bool forceDelete, svn_depth_t depth,
+             bool ignoreAncestry,
+             bool dryRun, bool recordOnly);
   void merge(const char *path, Revision &pegRevision,
-             std::vector<RevisionRange> &rangesToMerge,
-             const char *localPath, bool force, svn_depth_t depth,
-             bool ignoreAncestry, bool dryRun, bool recordOnly);
+             std::vector<RevisionRange> *rangesToMerge,
+             const char *localPath, bool forceDelete, svn_depth_t depth,
+             bool ignoreAncestry,
+             bool dryRun, bool recordOnly);
   void mergeReintegrate(const char *path, Revision &pegRevision,
                         const char *localPath, bool dryRun);
   void doImport(const char *path, const char *url, CommitMessage *message,
-                svn_depth_t depth, bool noIgnore, bool ignoreUnknownNodeTypes,
-                RevpropTable &revprops, CommitCallback *callback);
+                svn_depth_t depth, bool noIgnore, bool noAutoProps,
+                bool ignoreUnknownNodeTypes,
+                RevpropTable &revprops, ImportFilterCallback *ifCallback,
+                CommitCallback *commitCallback);
   jlong doSwitch(const char *path, const char *url, Revision &revision,
                  Revision &pegRevision, svn_depth_t depth,
                  bool depthIsSticky, bool ignoreExternals,
@@ -123,7 +131,8 @@
              RevpropTable &revprops, CommitCallback *callback);
   void move(Targets &srcPaths, const char *destPath,
             CommitMessage *message, bool force, bool moveAsChild,
-            bool makeParents, RevpropTable &revprops, CommitCallback *callback);
+            bool makeParents, bool metadataOnly, bool allowMixRev,
+            RevpropTable &revprops, CommitCallback *callback);
   void copy(CopySources &copySources, const char *destPath,
             CommitMessage *message, bool copyAsChild, bool makeParents,
             bool ignoreExternals, RevpropTable &revprops,
@@ -135,8 +144,8 @@
   jlongArray update(Targets &targets, Revision &revision, svn_depth_t depth,
                     bool depthIsSticky, bool makeParents, bool ignoreExternals,
                     bool allowUnverObstructions);
-  void add(const char *path, svn_depth_t depth, bool force, bool no_ignore,
-           bool add_parents);
+  void add(const char *path, svn_depth_t depth, bool force,
+           bool no_ignore, bool no_autoprops, bool add_parents);
   void revert(const char *path, svn_depth_t depth, StringArray &changelists);
   void remove(Targets &targets, CommitMessage *message, bool force,
               bool keep_local, RevpropTable &revprops,
@@ -149,6 +158,7 @@
                    bool discoverPaths, bool includeMergedRevisions,
                    StringArray &revProps,
                    long limit, LogMessageCallback *callback);
+  jobject getVersionExtended(bool verbose);
   jstring getAdminDirectoryName();
   jboolean isAdminDirectory(const char *name);
   void addToChangelist(Targets &srcPaths, const char *changelist,
@@ -171,7 +181,8 @@
                          bool lastChanged);
   void upgrade(const char *path);
   jbyteArray propertyGet(const char *path, const char *name,
-                         Revision &revision, Revision &pegRevision);
+                         Revision &revision, Revision &pegRevision,
+                         StringArray &changelists);
   void diff(const char *target1, Revision &revision1,
             const char *target2, Revision &revision2,
             const char *relativeToDir, const char *outfileName,
@@ -196,7 +207,7 @@
   ClientContext &getClientContext();
 
   const char *getLastPath();
-  void dispose();
+  void dispose(jobject jthis);
   static SVNClient *getCppObject(jobject jthis);
   SVNClient(jobject jthis_in);
   virtual ~SVNClient();
diff --git a/subversion/bindings/javahl/native/SVNRepos.cpp b/subversion/bindings/javahl/native/SVNRepos.cpp
index 079ad59..0f7e017 100644
--- a/subversion/bindings/javahl/native/SVNRepos.cpp
+++ b/subversion/bindings/javahl/native/SVNRepos.cpp
@@ -54,10 +54,10 @@
   return (cppAddr == 0 ? NULL : reinterpret_cast<SVNRepos *>(cppAddr));
 }
 
-void SVNRepos::dispose()
+void SVNRepos::dispose(jobject jthis)
 {
   static jfieldID fid = 0;
-  SVNBase::dispose(&fid, JAVA_PACKAGE"/SVNRepos");
+  SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNRepos");
 }
 
 void SVNRepos::cancelOperation()
@@ -68,7 +68,7 @@
 svn_error_t *
 SVNRepos::checkCancel(void *cancelBaton)
 {
-  SVNRepos *that = (SVNRepos *)cancelBaton;
+  SVNRepos *that = static_cast<SVNRepos *>(cancelBaton);
   if (that->m_cancelOperation)
     return svn_error_create(SVN_ERR_CANCELLED, NULL,
                             _("Operation cancelled"));
@@ -169,7 +169,7 @@
   for (revision = start; revision <= end; ++revision)
     {
       revisionPool.clear();
-      SVN_JNI_ERR(svn_fs_deltify_revision (fs, revision, revisionPool.getPool()),
+      SVN_JNI_ERR(svn_fs_deltify_revision(fs, revision, revisionPool.getPool()),
                   );
     }
 
@@ -177,7 +177,7 @@
 }
 
 void SVNRepos::dump(File &path, OutputStream &dataOut,
-                    Revision &revsionStart, Revision &revisionEnd,
+                    Revision &revisionStart, Revision &revisionEnd,
                     bool incremental, bool useDeltas,
                     ReposNotifyCallback *notifyCallback)
 {
@@ -199,9 +199,9 @@
   SVN_JNI_ERR(svn_fs_youngest_rev(&youngest, fs, requestPool.getPool()), );
 
   /* ### We only handle revision numbers right now, not dates. */
-  if (revsionStart.revision()->kind == svn_opt_revision_number)
-    lower = revsionStart.revision()->value.number;
-  else if (revsionStart.revision()->kind == svn_opt_revision_head)
+  if (revisionStart.revision()->kind == svn_opt_revision_number)
+    lower = revisionStart.revision()->value.number;
+  else if (revisionStart.revision()->kind == svn_opt_revision_head)
     lower = youngest;
   else
     lower = SVN_INVALID_REVNUM;
@@ -248,7 +248,7 @@
 }
 
 void SVNRepos::hotcopy(File &path, File &targetPath,
-                       bool cleanLogs)
+                       bool cleanLogs, bool incremental)
 {
   SVN::Pool requestPool;
 
@@ -270,7 +270,7 @@
 }
 
 static void
-list_dblogs (File &path, MessageReceiver &receiver, bool only_unused)
+list_dblogs(File &path, MessageReceiver &receiver, bool only_unused)
 {
   SVN::Pool requestPool;
   apr_array_header_t *logfiles;
@@ -294,7 +294,7 @@
       log_utf8 = svn_dirent_join(path.getInternalStyle(requestPool),
                                  APR_ARRAY_IDX(logfiles, i, const char *),
                                  requestPool.getPool());
-      log_utf8 = svn_dirent_local_style (log_utf8, requestPool.getPool());
+      log_utf8 = svn_dirent_local_style(log_utf8, requestPool.getPool());
       receiver.receiveMessage(log_utf8);
     }
 }
@@ -312,6 +312,8 @@
 
 void SVNRepos::load(File &path,
                     InputStream &dataIn,
+                    Revision &revisionStart,
+                    Revision &revisionEnd,
                     bool ignoreUUID,
                     bool forceUUID,
                     bool usePreCommitHook,
@@ -321,6 +323,7 @@
 {
   SVN::Pool requestPool;
   svn_repos_t *repos;
+  svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
   enum svn_repos_load_uuid uuid_action = svn_repos_load_uuid_default;
   if (ignoreUUID)
     uuid_action = svn_repos_load_uuid_ignore;
@@ -333,6 +336,20 @@
       return;
     }
 
+  /* ### We only handle revision numbers right now, not dates. */
+  if (revisionStart.revision()->kind == svn_opt_revision_number)
+    lower = revisionStart.revision()->value.number;
+  if (revisionEnd.revision()->kind == svn_opt_revision_number)
+    upper = revisionEnd.revision()->value.number;
+  if (upper < lower
+      && lower != SVN_INVALID_REVNUM
+      && upper != SVN_INVALID_REVNUM)
+    {
+      SVN_JNI_ERR(svn_error_create
+                  (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                   _("First revision cannot be higher than second")), );
+    }
+
   SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
                               NULL, requestPool.getPool()), );
 
@@ -362,13 +379,13 @@
 
   SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
                               NULL, requestPool.getPool()), );
-  fs = svn_repos_fs (repos);
+  fs = svn_repos_fs(repos);
   SVN_JNI_ERR(svn_fs_list_transactions(&txns, fs, requestPool.getPool()), );
 
   /* Loop, printing revisions. */
   for (int i = 0; i < txns->nelts; ++i)
     {
-      messageReceiver.receiveMessage(APR_ARRAY_IDX (txns, i, const char *));
+      messageReceiver.receiveMessage(APR_ARRAY_IDX(txns, i, const char *));
     }
 
 
@@ -399,7 +416,7 @@
    * recovery actually worked. */
   SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
                               NULL, requestPool.getPool()), -1);
-  SVN_JNI_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs (repos),
+  SVN_JNI_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs(repos),
                                   requestPool.getPool()),
               -1);
   return youngest_rev;
@@ -423,13 +440,13 @@
 
   SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
                               NULL, requestPool.getPool()), );
-  fs = svn_repos_fs (repos);
+  fs = svn_repos_fs(repos);
 
   args = transactions.array(requestPool);
   /* All the rest of the arguments are transaction names. */
   for (i = 0; i < args->nelts; ++i)
     {
-      const char *txn_name = APR_ARRAY_IDX (args, i, const char *);
+      const char *txn_name = APR_ARRAY_IDX(args, i, const char *);
       svn_error_t *err;
 
       /* Try to open the txn.  If that succeeds, try to abort it. */
@@ -443,7 +460,7 @@
        * all.  */
       if (err && (err->apr_err == SVN_ERR_FS_TRANSACTION_DEAD))
         {
-          svn_error_clear (err);
+          svn_error_clear(err);
           err = svn_fs_purge_txn(fs, txn_name, transactionPool.getPool());
         }
 
@@ -497,7 +514,7 @@
     }
   else
     {
-      svn_fs_t *fs = svn_repos_fs (repos);
+      svn_fs_t *fs = svn_repos_fs(repos);
       err = svn_fs_change_rev_prop2(fs, revision.revision()->value.number,
                                     propName, NULL, propValStr,
                                     requestPool.getPool());
@@ -554,7 +571,7 @@
    * with no interest in the output. */
   SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
                               NULL, requestPool.getPool()), );
-  SVN_JNI_ERR(svn_fs_youngest_rev(&youngest, svn_repos_fs (repos),
+  SVN_JNI_ERR(svn_fs_youngest_rev(&youngest, svn_repos_fs(repos),
                                   requestPool.getPool()), );
 
   /* Find the revision numbers at which to start and end. */
@@ -658,13 +675,13 @@
 
   std::vector<jobject> jlocks;
 
-  for (hi = apr_hash_first (requestPool.getPool(), locks);
+  for (hi = apr_hash_first(requestPool.getPool(), locks);
        hi;
-       hi = apr_hash_next (hi))
+       hi = apr_hash_next(hi))
     {
       void *val;
-      apr_hash_this (hi, NULL, NULL, &val);
-      svn_lock_t *lock = (svn_lock_t *)val;
+      apr_hash_this(hi, NULL, NULL, &val);
+      svn_lock_t *lock = reinterpret_cast<svn_lock_t *>(val);
       jobject jLock = CreateJ::Lock(lock);
 
       jlocks.push_back(jLock);
@@ -691,8 +708,8 @@
 
   SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
                               NULL, requestPool.getPool()), );
-  fs = svn_repos_fs (repos);
-  const char *username;
+  fs = svn_repos_fs(repos);
+  const char *username = NULL;
 
   /* svn_fs_unlock() demands that some username be associated with the
    * filesystem, so just use the UID of the person running 'svnadmin'.*/
@@ -704,7 +721,7 @@
         apr_uid_name_get (&un, uid, pool) == APR_SUCCESS)
       {
         svn_error_t *err = svn_utf_cstring_to_utf8(&username, un, pool);
-        svn_error_clear (err);
+        svn_error_clear(err);
         if (err)
           username = "administrator";
       }
@@ -720,7 +737,7 @@
   const apr_array_header_t *args = locks.array(requestPool);
   for (int i = 0; i < args->nelts; ++i)
     {
-      const char *lock_path = APR_ARRAY_IDX (args, i, const char *);
+      const char *lock_path = APR_ARRAY_IDX(args, i, const char *);
       svn_lock_t *lock;
 
       /* Fetch the path's svn_lock_t. */
@@ -731,13 +748,13 @@
         continue;
 
       /* Now forcibly destroy the lock. */
-      err = svn_fs_unlock (fs, lock_path,
-                           lock->token, 1 /* force */, subpool.getPool());
+      err = svn_fs_unlock(fs, lock_path,
+                          lock->token, 1 /* force */, subpool.getPool());
       if (err)
         goto move_on;
 
     move_on:
-      svn_error_clear (err);
+      svn_error_clear(err);
       subpool.clear();
     }
 
diff --git a/subversion/bindings/javahl/native/SVNRepos.h b/subversion/bindings/javahl/native/SVNRepos.h
index 492b940..91f39c3 100644
--- a/subversion/bindings/javahl/native/SVNRepos.h
+++ b/subversion/bindings/javahl/native/SVNRepos.h
@@ -52,13 +52,15 @@
   void rmtxns(File &path, StringArray &transactions);
   jlong recover(File &path, ReposNotifyCallback *notifyCallback);
   void lstxns(File &path, MessageReceiver &messageReceiver);
-  void load(File &path, InputStream &dataIn, bool ignoreUUID, bool forceUUID,
+  void load(File &path, InputStream &dataIn,
+            Revision &revsionStart, Revision &revisionEnd,
+            bool ignoreUUID, bool forceUUID,
             bool usePreCommitHook, bool usePostCommitHook,
             const char *relativePath, ReposNotifyCallback *notifyCallback);
   void listUnusedDBLogs(File &path,
                         MessageReceiver &messageReceiver);
   void listDBLogs(File &path, MessageReceiver &messageReceiver);
-  void hotcopy(File &path, File &targetPath, bool cleanLogs);
+  void hotcopy(File &path, File &targetPath, bool cleanLogs, bool incremental);
   void dump(File &path, OutputStream &dataOut, Revision &revsionStart,
             Revision &RevisionEnd, bool incremental, bool useDeltas,
             ReposNotifyCallback *notifyCallback);
@@ -69,7 +71,7 @@
   void pack(File &path, ReposNotifyCallback *callback);
   SVNRepos();
   virtual ~SVNRepos();
-  void dispose();
+  void dispose(jobject jthis);
   static SVNRepos *getCppObject(jobject jthis);
 
   static svn_error_t *checkCancel(void *cancelBaton);
diff --git a/subversion/bindings/javahl/native/StatusCallback.cpp b/subversion/bindings/javahl/native/StatusCallback.cpp
index 49a8043..cc0d67a 100644
--- a/subversion/bindings/javahl/native/StatusCallback.cpp
+++ b/subversion/bindings/javahl/native/StatusCallback.cpp
@@ -55,7 +55,8 @@
                          apr_pool_t *pool)
 {
   if (baton)
-    return ((StatusCallback *)baton)->doStatus(local_abspath, status, pool);
+    return static_cast<StatusCallback *>(baton)->doStatus(
+            local_abspath, status, pool);
 
   return SVN_NO_ERROR;
 }
@@ -93,7 +94,7 @@
 
   jstring jPath = JNIUtil::makeJString(local_abspath);
   if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
+    POP_AND_RETURN(SVN_NO_ERROR);
 
   jobject jStatus = CreateJ::Status(wc_ctx, status, pool);
   if (JNIUtil::isJavaExceptionThrown())
diff --git a/subversion/bindings/javahl/native/StringArray.cpp b/subversion/bindings/javahl/native/StringArray.cpp
index 03e7828..0438e44 100644
--- a/subversion/bindings/javahl/native/StringArray.cpp
+++ b/subversion/bindings/javahl/native/StringArray.cpp
@@ -39,7 +39,8 @@
 const apr_array_header_t *StringArray::array(const SVN::Pool &pool)
 {
   apr_array_header_t *strings
-    = apr_array_make(pool.getPool(), m_strings.size(), sizeof(char *));
+    = apr_array_make(pool.getPool(), static_cast<int>(m_strings.size()),
+                     sizeof(char *));
 
   std::vector<std::string>::const_iterator it;
   for (it = m_strings.begin(); it < m_strings.end(); ++it)
@@ -69,7 +70,7 @@
       if (JNIUtil::isExceptionThrown())
         return;
 
-      m_strings.push_back(std::string((const char *)str));
+      m_strings.push_back(std::string(static_cast<const char *>(str)));
     }
 }
 
diff --git a/subversion/bindings/javahl/native/Targets.cpp b/subversion/bindings/javahl/native/Targets.cpp
index 767caca..85ecc34 100644
--- a/subversion/bindings/javahl/native/Targets.cpp
+++ b/subversion/bindings/javahl/native/Targets.cpp
@@ -40,13 +40,13 @@
     : m_subpool(in_pool)
 {
   m_strArray = NULL;
-  m_targets.push_back (apr_pstrdup(m_subpool.getPool(), path));
-  m_error_occured = NULL;
+  m_targets.push_back(apr_pstrdup(m_subpool.getPool(), path));
+  m_error_occurred = NULL;
 }
 
 void Targets::add(const char *path)
 {
-  m_targets.push_back (path);
+  m_targets.push_back(path);
 }
 
 const apr_array_header_t *Targets::array(const SVN::Pool &pool)
@@ -62,7 +62,7 @@
           svn_error_t *err = JNIUtil::preprocessPath(tt, pool.getPool());
           if (err != NULL)
             {
-              m_error_occured = err;
+              m_error_occurred = err;
               break;
             }
           m_targets.push_back(tt);
@@ -72,9 +72,9 @@
   std::vector<const char*>::const_iterator it;
 
   apr_pool_t *apr_pool = pool.getPool();
-  apr_array_header_t *apr_targets = apr_array_make (apr_pool,
-                                                    m_targets.size(),
-                                                    sizeof(const char *));
+  apr_array_header_t *apr_targets
+    = apr_array_make(apr_pool, static_cast<int>(m_targets.size()),
+                               sizeof(const char *));
 
   for (it = m_targets.begin(); it != m_targets.end(); ++it)
     {
@@ -83,7 +83,7 @@
       svn_error_t *err = JNIUtil::preprocessPath(target, pool.getPool());
       if (err != NULL)
         {
-            m_error_occured = err;
+            m_error_occurred = err;
             break;
         }
       APR_ARRAY_PUSH(apr_targets, const char *) = target;
@@ -96,10 +96,10 @@
     : m_subpool(in_pool)
 {
   m_strArray = &strArray;
-  m_error_occured = NULL;
+  m_error_occurred = NULL;
 }
 
-svn_error_t *Targets::error_occured()
+svn_error_t *Targets::error_occurred()
 {
-  return m_error_occured;
+  return m_error_occurred;
 }
diff --git a/subversion/bindings/javahl/native/Targets.h b/subversion/bindings/javahl/native/Targets.h
index 3743fd8..8d27a0d 100644
--- a/subversion/bindings/javahl/native/Targets.h
+++ b/subversion/bindings/javahl/native/Targets.h
@@ -43,14 +43,14 @@
   SVN::Pool m_subpool;
   std::vector<const char*> m_targets;
   StringArray *m_strArray;
-  svn_error_t *m_error_occured;
+  svn_error_t *m_error_occurred;
  public:
   Targets(StringArray &strArray, SVN::Pool &in_pool);
   Targets(const char *path, SVN::Pool &in_pool);
   void add(const char *path);
   ~Targets();
   const apr_array_header_t *array(const SVN::Pool &pool);
-  svn_error_t *error_occured();
+  svn_error_t *error_occurred();
 };
 
 #endif // TARGETS_H
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
index 6d66c99..e471a7a 100644
--- a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
@@ -75,7 +75,7 @@
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  cl->dispose();
+  cl->dispose(jthis);
 }
 
 JNIEXPORT void JNICALL
@@ -160,7 +160,8 @@
 
   ListCallback callback(jcallback);
   cl->list(url, revision, pegRevision, EnumMapper::toDepth(jdepth),
-           (int)jdirentFields, jfetchLocks ? true : false, &callback);
+           static_cast<int>(jdirentFields), jfetchLocks ? true : false,
+           &callback);
 }
 
 JNIEXPORT void JNICALL
@@ -305,7 +306,7 @@
   cl->logMessages(path, pegRevision, revisionRanges,
                   jstopOnCopy ? true: false, jdisoverPaths ? true : false,
                   jincludeMergedRevisions ? true : false,
-                  revProps, jlimit, &callback);
+                  revProps, static_cast<long>(jlimit), &callback);
 }
 
 JNIEXPORT jlong JNICALL
@@ -401,7 +402,8 @@
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_add
 (JNIEnv *env, jobject jthis, jstring jpath, jobject jdepth,
- jboolean jforce, jboolean jnoIgnore, jboolean jaddParents)
+ jboolean jforce, jboolean jnoIgnore, jboolean jnoAutoProps,
+ jboolean jaddParents)
 {
   JNIEntry(SVNClient, add);
   SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -414,8 +416,11 @@
   if (JNIUtil::isExceptionThrown())
     return;
 
-  cl->add(path, EnumMapper::toDepth(jdepth), jforce ? true : false,
-          jnoIgnore ? true : false, jaddParents ? true : false);
+  cl->add(path, EnumMapper::toDepth(jdepth),
+          jforce ? true : false,
+          jnoIgnore ? true : false,
+          jnoAutoProps ? true : false,
+          jaddParents ? true : false);
 }
 
 JNIEXPORT jlongArray JNICALL
@@ -531,7 +536,8 @@
 Java_org_apache_subversion_javahl_SVNClient_move
 (JNIEnv *env, jobject jthis, jobject jsrcPaths, jstring jdestPath,
  jboolean jforce, jboolean jmoveAsChild, jboolean jmakeParents,
- jobject jrevpropTable, jobject jmessage, jobject jcallback)
+ jboolean jmetadataOnly, jboolean jallowMixRev, jobject jrevpropTable,
+ jobject jmessage, jobject jcallback)
 {
   JNIEntry(SVNClient, move);
 
@@ -561,6 +567,7 @@
   CommitCallback callback(jcallback);
   cl->move(srcPaths, destPath, &message, jforce ? true : false,
            jmoveAsChild ? true : false, jmakeParents ? true : false,
+           jmetadataOnly ? true: false, jallowMixRev ? true : false,
            revprops, jcallback ? &callback : NULL);
 }
 
@@ -711,8 +718,9 @@
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_doImport
 (JNIEnv *env, jobject jthis, jstring jpath, jstring jurl, jobject jdepth,
- jboolean jnoIgnore, jboolean jignoreUnknownNodeTypes, jobject jrevpropTable,
- jobject jmessage, jobject jcallback)
+ jboolean jnoIgnore, jboolean jnoAutoProps,
+ jboolean jignoreUnknownNodeTypes, jobject jrevpropTable,
+ jobject jimportFilterCallback, jobject jmessage, jobject jcommitCallback)
 {
   JNIEntry(SVNClient, doImport);
   SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -737,11 +745,13 @@
   if (JNIUtil::isExceptionThrown())
     return;
 
-  CommitCallback callback(jcallback);
+  CommitCallback commitCallback(jcommitCallback);
+
   cl->doImport(path, url, &message, EnumMapper::toDepth(jdepth),
-               jnoIgnore ? true : false,
+               jnoIgnore ? true : false, jnoAutoProps ? true : false,
                jignoreUnknownNodeTypes ? true : false, revprops,
-               jcallback ? &callback : NULL);
+                NULL,
+               jcommitCallback ? &commitCallback : NULL);
 }
 
 JNIEXPORT jobject JNICALL
@@ -770,9 +780,9 @@
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_merge__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2ZLorg_apache_subversion_javahl_types_Depth_2ZZZ
 (JNIEnv *env, jobject jthis, jstring jpath1, jobject jrevision1,
- jstring jpath2, jobject jrevision2, jstring jlocalPath, jboolean jforce,
- jobject jdepth, jboolean jignoreAncestry, jboolean jdryRun,
- jboolean jrecordOnly)
+ jstring jpath2, jobject jrevision2, jstring jlocalPath, jboolean jforceDelete,
+ jobject jdepth, jboolean jignoreAncestry,
+ jboolean jdryRun, jboolean jrecordOnly)
 {
   JNIEntry(SVNClient, merge);
   SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -802,16 +812,19 @@
     return;
 
   cl->merge(path1, revision1, path2, revision2, localPath,
-            jforce ? true:false, EnumMapper::toDepth(jdepth),
-            jignoreAncestry ? true:false, jdryRun ? true:false,
+            jforceDelete ? true:false,
+            EnumMapper::toDepth(jdepth),
+            jignoreAncestry ? true:false,
+            jdryRun ? true:false,
             jrecordOnly ? true:false);
 }
 
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_merge__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_util_List_2Ljava_lang_String_2ZLorg_apache_subversion_javahl_types_Depth_2ZZZ
 (JNIEnv *env, jobject jthis, jstring jpath, jobject jpegRevision,
- jobject jranges, jstring jlocalPath, jboolean jforce, jobject jdepth,
- jboolean jignoreAncestry, jboolean jdryRun, jboolean jrecordOnly)
+ jobject jranges, jstring jlocalPath, jboolean jforceDelete, jobject jdepth,
+ jboolean jignoreAncestry,
+ jboolean jdryRun, jboolean jrecordOnly)
 {
   JNIEntry(SVNClient, merge);
   SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -833,27 +846,34 @@
   if (JNIUtil::isExceptionThrown())
     return;
 
+  std::vector<RevisionRange> *revisionRanges = NULL;
+  std::vector<RevisionRange> realRevisionRanges;
   // Build the revision range vector from the Java array.
-  Array ranges(jranges);
-  if (JNIUtil::isExceptionThrown())
-    return;
-
-  std::vector<RevisionRange> revisionRanges;
-  std::vector<jobject> rangeVec = ranges.vector();
-
-  for (std::vector<jobject>::const_iterator it = rangeVec.begin();
-        it < rangeVec.end(); ++it)
+  if (jranges)
     {
-      RevisionRange revisionRange(*it);
+      Array ranges(jranges);
       if (JNIUtil::isExceptionThrown())
         return;
 
-      revisionRanges.push_back(revisionRange);
+      std::vector<jobject> rangeVec = ranges.vector();
+
+      for (std::vector<jobject>::const_iterator it = rangeVec.begin();
+           it < rangeVec.end(); ++it)
+        {
+          RevisionRange revisionRange(*it);
+          if (JNIUtil::isExceptionThrown())
+            return;
+
+          realRevisionRanges.push_back(revisionRange);
+        }
+      revisionRanges = &realRevisionRanges;
     }
 
   cl->merge(path, pegRevision, revisionRanges, localPath,
-            jforce ? true:false, EnumMapper::toDepth(jdepth),
-            jignoreAncestry ? true:false, jdryRun ? true:false,
+            jforceDelete ? true:false,
+            EnumMapper::toDepth(jdepth),
+            jignoreAncestry ? true:false,
+            jdryRun ? true:false,
             jrecordOnly ? true:false);
 }
 
@@ -886,13 +906,11 @@
                        jdryRun ? true:false);
 }
 
-JNIEXPORT void JNICALL
-Java_org_apache_subversion_javahl_SVNClient_properties
+static void SVNClient_properties
 (JNIEnv *env, jobject jthis, jstring jpath, jobject jrevision,
  jobject jpegRevision, jobject jdepth, jobject jchangelists,
- jobject jproplistCallback)
+ jobject jproplistCallback, bool inherited)
 {
-  JNIEntry(SVNClient, properties);
   SVNClient *cl = SVNClient::getCppObject(jthis);
   if (cl == NULL)
     {
@@ -915,11 +933,21 @@
   if (JNIUtil::isExceptionThrown())
     return;
 
-  ProplistCallback callback(jproplistCallback);
+  ProplistCallback callback(jproplistCallback, inherited);
   cl->properties(path, revision, pegRevision, EnumMapper::toDepth(jdepth),
                  changelists, &callback);
 }
 
+JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_SVNClient_properties
+(JNIEnv *env, jobject jthis, jstring jpath, jobject jrevision,
+ jobject jpegRevision, jobject jdepth, jobject jchangelists,
+ jobject jproplistCallback)
+{
+  JNIEntry(SVNClient, properties);
+  SVNClient_properties(env, jthis, jpath, jrevision, jpegRevision, jdepth,
+                       jchangelists, jproplistCallback, false);
+}
+
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_propertySetRemote
 (JNIEnv *env, jobject jthis, jstring jpath, jlong jbaseRev, jstring jname,
@@ -954,8 +982,8 @@
     return;
 
   CommitCallback callback(jcallback);
-  cl->propertySetRemote(path, jbaseRev, name, &message, value,
-                        jforce ? true:false,
+  cl->propertySetRemote(path, static_cast<svn_revnum_t>(jbaseRev),
+                        name, &message, value, jforce ? true : false,
                         revprops, jcallback ? &callback : NULL);
 }
 
@@ -1080,7 +1108,7 @@
 JNIEXPORT jbyteArray JNICALL
 Java_org_apache_subversion_javahl_SVNClient_propertyGet
 (JNIEnv *env, jobject jthis, jstring jpath, jstring jname, jobject jrevision,
- jobject jpegRevision)
+ jobject jpegRevision, jobject jchangelists)
 {
   JNIEntry(SVNClient, propertyGet);
   SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -1105,7 +1133,11 @@
   if (JNIUtil::isExceptionThrown())
     return NULL;
 
-  return cl->propertyGet(path, name, revision, pegRevision);
+  StringArray changelists(jchangelists);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  return cl->propertyGet(path, name, revision, pegRevision, changelists);
 }
 
 JNIEXPORT jobject JNICALL
@@ -1760,7 +1792,27 @@
     return;
 
   PatchCallback callback(jcallback);
-  cl->patch(patchPath, targetPath, jdryRun ? true : false, (int) jstripCount,
+  cl->patch(patchPath, targetPath,
+            jdryRun ? true : false, static_cast<int>(jstripCount),
             jreverse ? true : false, jignoreWhitespace ? true : false,
             jremoveTempfiles ? true : false, &callback);
 }
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_SVNClient_nativeOpenRemoteSession
+(JNIEnv *env, jobject jthis, jstring jpath, jint jretryAttempts)
+{
+  JNIEntry(SVNClient, openRemoteSession);
+  SVNClient *cl = SVNClient::getCppObject(jthis);
+  if (cl == NULL)
+    {
+      JNIUtil::throwError("bad C++ this");
+      return NULL;
+    }
+
+  JNIStringHolder path(jpath);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return cl->openRemoteSession(path, jretryAttempts);
+}
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
index b9ddbc6..b14b119 100644
--- a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
@@ -60,7 +60,7 @@
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  cl->dispose();
+  cl->dispose(jthis);
 }
 
 JNIEXPORT void JNICALL
@@ -170,7 +170,7 @@
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNRepos_hotcopy
 (JNIEnv *env, jobject jthis, jobject jpath, jobject jtargetPath,
- jboolean jcleanLogs)
+ jboolean jcleanLogs, jboolean jincremental)
 {
   JNIEntry(SVNRepos, hotcopy);
   SVNRepos *cl = SVNRepos::getCppObject(jthis);
@@ -188,7 +188,8 @@
   if (JNIUtil::isExceptionThrown())
     return;
 
-  cl->hotcopy(path, targetPath, jcleanLogs ? true : false);
+  cl->hotcopy(path, targetPath, jcleanLogs ? true : false,
+              jincremental ? true : false);
 }
 
 JNIEXPORT void JNICALL
@@ -240,6 +241,7 @@
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNRepos_load
 (JNIEnv *env, jobject jthis, jobject jpath, jobject jinputData,
+ jobject jrevisionStart, jobject jrevisionEnd,
  jboolean jignoreUUID, jboolean jforceUUID, jboolean jusePreCommitHook,
  jboolean jusePostCommitHook, jstring jrelativePath, jobject jnotifyCallback)
 {
@@ -263,12 +265,23 @@
   if (JNIUtil::isExceptionThrown())
     return;
 
+  Revision revisionStart(jrevisionStart);
+  if (JNIUtil::isExceptionThrown())
+    return;
+
+  Revision revisionEnd(jrevisionEnd, true);
+  if (JNIUtil::isExceptionThrown())
+    return;
+
   ReposNotifyCallback notifyCallback(jnotifyCallback);
 
-  cl->load(path, inputData, jignoreUUID ? true : false,
-           jforceUUID ? true : false, jusePreCommitHook ? true : false,
-           jusePostCommitHook ? true : false, relativePath,
-           jnotifyCallback != NULL ? &notifyCallback : NULL);
+  cl->load(path, inputData, revisionStart, revisionEnd,
+           jignoreUUID ? true : false,
+           jforceUUID ? true : false,
+           jusePreCommitHook ? true : false,
+           jusePostCommitHook ? true : false,
+           relativePath,
+           (jnotifyCallback != NULL ? &notifyCallback : NULL));
 }
 
 JNIEXPORT void JNICALL
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
new file mode 100644
index 0000000..0a16131
--- /dev/null
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
@@ -0,0 +1,58 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file org_apache_subversion_javahl_remote_RemoteFactory.cpp
+ * @brief Implementation of the native methods in the Java class RemoteFactory
+ */
+
+#include "../include/org_apache_subversion_javahl_remote_RemoteFactory.h"
+
+#include "JNIStackElement.h"
+#include "JNIUtil.h"
+#include "JNIStringHolder.h"
+
+#include "RemoteSession.h"
+
+#include "svn_private_config.h"
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteFactory_open(
+    JNIEnv *env, jclass jclass, jint jretryAttempts,
+    jstring jurl, jstring juuid,
+    jstring jconfigDirectory, jstring jusername, jstring jpassword,
+    jobject jprompter, jobject jprogress)
+{
+  //JNI macros need jthis but this is a static call
+  jobject jthis = NULL;
+  JNIEntry(Remotefactory, open);
+
+  /*
+   * Create RemoteSession C++ object and return its java wrapper to the caller
+   */
+  jobject jremoteSession = RemoteSession::open(
+      jretryAttempts, jurl, juuid, jconfigDirectory,
+      jusername, jpassword, jprompter, jprogress);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+
+  return jremoteSession;
+}
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
new file mode 100644
index 0000000..7dfdcf0
--- /dev/null
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
@@ -0,0 +1,188 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file org_apache_subversion_javahl_remote_RemoteSession.cpp
+ * @brief Implementation of the native methods in the Java class RemoteSession
+ */
+
+#include "../include/org_apache_subversion_javahl_remote_RemoteSession.h"
+
+#include "JNIStackElement.h"
+#include "JNIUtil.h"
+#include "Prompter.h"
+#include "RemoteSession.h"
+#include "Revision.h"
+#include "EnumMapper.h"
+
+#include "svn_private_config.h"
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_finalize(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, finalize);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  if (ras != NULL)
+    ras->finalize();
+}
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_nativeDispose(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, dispose);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  if (ras != NULL)
+    ras->dispose(jthis);
+}
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_cancelOperation(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, cancelOperation);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, );
+
+  ras->cancelOperation();
+}
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_reparent(
+    JNIEnv *env, jobject jthis, jstring jurl)
+{
+  JNIEntry(RemoteSession, getSessionUrl);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, );
+
+  ras->reparent(jurl);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getSessionRelativePath(
+    JNIEnv *env, jobject jthis, jstring jurl)
+{
+  JNIEntry(RemoteSession, getSessionUrl);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getSessionRelativePath(jurl);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getReposRelativePath(
+    JNIEnv *env, jobject jthis, jstring jurl)
+{
+  JNIEntry(RemoteSession, getSessionUrl);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getReposRelativePath(jurl);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getSessionUrl(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, getSessionUrl);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getSessionUrl();
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getReposUUID(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, geRepostUUID);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getReposUUID();
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getReposRootUrl(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, geRepostUUID);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getReposRootUrl();
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getLatestRevision(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(RemoteSession, getLatestRevision);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, SVN_INVALID_REVNUM);
+
+  return ras->getLatestRevision();
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getRevisionByTimestamp(
+    JNIEnv *env, jobject jthis, jlong timestamp)
+{
+  JNIEntry(RemoteSession, getDatedRevision);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, SVN_INVALID_REVNUM);
+
+  return ras->getRevisionByTimestamp(timestamp);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_checkPath(
+    JNIEnv *env, jobject jthis, jstring jpath, jlong jrevision)
+{
+  JNIEntry(SVNReposAccess, checkPath);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->checkPath(jpath, jrevision);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getLocks(
+    JNIEnv *env, jobject jthis, jstring jpath, jobject jdepth)
+{
+  JNIEntry(RemoteSession, getLocks);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getLocks(jpath, jdepth);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_nativeHasCapability(
+    JNIEnv *env, jobject jthis, jstring jcapability)
+{
+  JNIEntry(RemoteSession, nativeHasCapability);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, false);
+
+  return ras->hasCapability(jcapability);
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
index b1213c2..8a59e4d 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
@@ -544,7 +544,30 @@
         failed_forbidden_by_server ("failed forbidden by server"),
 
         /** Operation skipped the path because it was conflicted */
-        skip_conflicted ("skipped conflicted path");
+        skip_conflicted ("skipped conflicted path"),
+
+        /** The lock on a file was removed during update */
+        update_broken_lock ("broken lock removed"),
+
+        /** Operation failed because a node is obstructed */
+        failed_obstructed ("failed by obstruction"),
+
+        /** Conflict resolver is starting. */
+        conflict_resolver_starting ("conflict resolver starting"),
+
+        /** Conflict resolver is done. */
+        conflict_resolver_done ("conflict resolver done"),
+
+        /** Operation left local modifications. */
+        left_local_modifications ("left local modifications"),
+
+        /** A copy from a foreign repository has started
+         * @since New in 1.8. */
+        foreign_copy_begin ("foreign copy begin"),
+
+        /** A move in the working copy has been broken
+         * @since New in 1.8. */
+        move_broken ("move broken");
 
         /**
          * The description of the action.
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java
index 43dec0a..986faf6 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java
@@ -70,6 +70,11 @@
     long revision;
 
     /**
+     * the source of the move
+     */
+    String movedFromPath;
+
+    /**
      * This constructor will be only called from the jni code.
      * @param p     path to the commit item
      * @param nk    kind of node (see NodeKind)
@@ -77,8 +82,9 @@
      * @param u     url of the item
      * @param cu    copy source url
      * @param r     revision number
+     * @param mf    move source abspath
      */
-    public CommitItem(String p, NodeKind nk, int sf, String u, String cu, long r)
+    CommitItem(String p, NodeKind nk, int sf, String u, String cu, long r, String mf)
     {
         path = p;
         nodeKind = nk;
@@ -86,6 +92,7 @@
         url = u;
         copyUrl = cu;
         revision = r;
+        movedFromPath = mf;
     }
 
     /**
@@ -149,4 +156,13 @@
     {
         return revision;
     }
+
+    /**
+     * @return the absolute path of the source of a move.
+     * @since 1.8
+     */
+    public String getMovedFromPath()
+    {
+        return movedFromPath;
+    }
 }
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java
index 6ef0efb..6e8f593 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java
@@ -53,4 +53,15 @@
      * the item has been copied
      */
     public static final int IsCopy=16;
+
+    /**
+     * the item has a lock token
+     */
+    public static final int LockToken = 32;
+
+    /**
+     * the item was moved to this location
+     * @since 1.8
+     */
+    public static int MovedHere = 64;
 }
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java
index 75089c0..651dca1 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java
@@ -244,6 +244,7 @@
 
         /**
          * Object is already added or schedule-add.
+         * @since 1.6
          */
         added,
 
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
index b18ea2e..a527069 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
@@ -223,12 +223,30 @@
      *                  ignore patterns
      * @param addParents add any intermediate parents to the working copy
      * @throws ClientException
+     * @note this method behaves like the 1.8 version with noAutoProps=false
      */
     void add(String path, Depth depth, boolean force, boolean noIgnores,
              boolean addParents)
         throws ClientException;
 
     /**
+     * Adds a file to the repository.
+     * @param path      path to be added.
+     * @param depth     the depth to recurse into subdirectories
+     * @param force     if adding a directory and recurse true and path is a
+     *                  directory, all not already managed files are added.
+     * @param noIgnores if false, don't add files or directories matching
+     *                  ignore patterns
+     * @param noAutoProps if true, ignore any auto-props configuration
+     * @param addParents add any intermediate parents to the working copy
+     * @throws ClientException
+     * @since 1.8
+     */
+    void add(String path, Depth depth, boolean force,
+             boolean noIgnores, boolean noAutoProps, boolean addParents)
+        throws ClientException;
+
+    /**
      * Updates the directories or files from repository
      * @param path array of target files.
      * @param revision the revision number to update.
@@ -298,12 +316,27 @@
      * @param moveAsChild Whether to move <code>srcPaths</code> as
      * children of <code>destPath</code>.
      * @param makeParents Whether to create intermediate parents.
+     * @param metadataOnly Move just the metadata and not the working files/dirs
+     * @param allowMixRev If true use copy and delete without move tracking
+     *                    when a srcPath is mixed-revision, if false return
+     *                    an error when a srcPath is mixed-revision.
      * @param revpropTable A string-to-string mapping of revision properties
      *                     to values which will be set if this operation
      *                     results in a commit.
      * @param handler   the commit message callback, may be <code>null</code>
      *                  if <code>destPath</code> is not a URL
      * @throws ClientException If the move operation fails.
+     * @since 1.8
+     */
+    void move(Set<String> srcPaths, String destPath, boolean force,
+              boolean moveAsChild, boolean makeParents, boolean metadataOnly,
+              boolean allowMixRev, Map<String, String> revpropTable,
+              CommitMessageCallback handler, CommitCallback callback)
+        throws ClientException;
+
+    /**
+     * @deprecated Provided for backward compatibility with 1.7. Passes
+     *             metadataOnly false and allowMixRev true.
      */
     void move(Set<String> srcPaths, String destPath, boolean force,
               boolean moveAsChild, boolean makeParents,
@@ -400,8 +433,10 @@
      *                     to values which will be set if this operation
      *                     results in a commit.
      * @param handler   the commit message callback
+     * @param callback  the commit status callback
      * @throws ClientException
-     *
+     * @note this method behaves like the 1.8 version with noAutoProps=false
+     *       and without the filtering option.
      */
     void doImport(String path, String url, Depth depth,
                   boolean noIgnore, boolean ignoreUnknownNodeTypes,
@@ -433,6 +468,8 @@
      * @param dryRun         do not change anything
      * @param recordOnly     record mergeinfo but do not run merge
      * @throws ClientException
+     * @note Behaves like the 1.8 where ignoreAncestry maps to
+     *       both ignoreMergeinfo and diffIgnoreAncestry
      */
     void merge(String path1, Revision revision1, String path2,
                Revision revision2, String localPath, boolean force, Depth depth,
@@ -443,7 +480,9 @@
      * Merge set of revisions into a new local path.
      * @param path          path or url
      * @param pegRevision   revision to interpret path
-     * @param revisions     revisions to merge
+     * @param revisions     revisions to merge;
+     *                      may be null, indicating that the optimal range
+     *                      should be determined automatcially (new in 1.8)
      * @param localPath     target local path
      * @param force         overwrite local changes
      * @param depth         how deep to traverse into subdirectories
@@ -451,7 +490,10 @@
      * @param dryRun        do not change anything
      * @param recordOnly    record mergeinfo but do not run merge
      * @throws ClientException
+     * @note Behaves like the 1.8 where ignoreAncestry maps to
+     *       both ignoreMergeinfo and diffIgnoreAncestry
      */
+    // FIXME: Broken
     void merge(String path, Revision pegRevision, List<RevisionRange> revisions,
                String localPath, boolean force, Depth depth,
                boolean ignoreAncestry, boolean dryRun, boolean recordOnly)
@@ -472,6 +514,7 @@
      * @param localPath     target local path
      * @param dryRun        do not change anything
      * @throws ClientException
+     * @deprecated Will be removed in a future release
      */
     void mergeReintegrate(String path, Revision pegRevision,
                           String localPath, boolean dryRun)
@@ -521,6 +564,8 @@
      * @param force         diff even on binary files
      * @param copiesAsAdds  if set, copied files will be shown in their
      *                      entirety, not as diffs from their sources
+     * @param ignoreProps   don't show property diffs
+     * @param propsOnly     show property changes only
      * @throws ClientException
      */
     void diff(String target1, Revision revision1, String target2,
@@ -545,6 +590,8 @@
      * @param force         diff even on binary files
      * @param copiesAsAdds  if set, copied files will be shown in their
      *                      entirety, not as diffs from their sources
+     * @param ignoreProps   don't show property diffs
+     * @param propsOnly     show property changes only
      * @throws ClientException
      */
     void diff(String target, Revision pegRevision, Revision startRevision,
@@ -700,6 +747,10 @@
      * @throws ClientException
      */
     byte[] propertyGet(String path, String name, Revision revision,
+                       Revision pegRevision, Collection<String> changelists)
+            throws ClientException;
+
+    byte[] propertyGet(String path, String name, Revision revision,
                        Revision pegRevision)
             throws ClientException;
 
@@ -886,4 +937,36 @@
                int stripCount, boolean reverse, boolean ignoreWhitespace,
                boolean removeTempfiles, PatchCallback callback)
             throws ClientException;
+
+    /**
+     * Open a persistent session to a repository.
+     * @param path A path in a working copy from which the
+     *        session URL is derived.
+     * @throws remote.RetryOpenSession If the session URL was redirected
+     * @throws SubversionException If an URL redirect cycle was detected
+     * @throws ClientException
+     * @note The session object inherits the progress callback,
+     *       configuration directory and authentication info.
+     * @since 1.9
+     */
+    ISVNRemote openRemoteSession(String path)
+            throws ClientException, SubversionException;
+
+    /**
+     * Open a persistent session to a repository.
+     * @param path A path in a working copy from which the
+     *        session URL is derived.
+     * @param retryAttempts The number of times to retry the operation
+     *        if the given URL is redirected.
+     * @throws IllegalArgumentException If <code>retryAttempts</code>
+     *         is not positive
+     * @throws remote.RetryOpenSession If the session URL was redirected
+     * @throws SubversionException If an URL redirect cycle was detected
+     * @throws ClientException
+     * @note The session object inherits the progress callback,
+     *       configuration directory and authentication info.
+     * @since 1.9
+     */
+    ISVNRemote openRemoteSession(String path, int retryAttempts)
+            throws ClientException, SubversionException;
 }
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
new file mode 100644
index 0000000..fd9d870
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
@@ -0,0 +1,327 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Editor interface (implements the EV2 abstraction).
+ * @see <a href="http://svn.apache.org/repos/asf/subversion/trunk/subversion/include/private/svn_editor.h"
+ *      >svn_editor.h</a> for all restrictions on driving an editor.
+ * @since 1.9
+ */
+public interface ISVNEditor
+{
+    /**
+     * Release the native peer (should not depend on finalize),
+     * and abort the edit if it has not been completed yet.
+     */
+    void dispose();
+
+    /**
+     * Create a new directory at <code>relativePath</code>.
+     * The immediate parent of <code>relativePath</code> is expected to exist.
+     *
+     * For descriptions of <code>properties</code> and
+     * <code>replacesRevision</code>, see #addFile().
+     *
+     * A complete listing of the immediate children of
+     * <code>relativePath</code> that will be added subsequently is
+     * given in <code>children</code>. <code>children</code> is a
+     * collection of const strings, each giving the basename of an
+     * immediate child. It is an error to pass <code>null</code> for
+     * <code>children</code>; use an empty collection to indicate that
+     * the new directory will have no children.
+     *
+     * @throws ClientException
+     */
+    void addDirectory(String relativePath,
+                      Iterable<String> children,
+                      Map<String, byte[]> properties,
+                      long replacesRevision)
+            throws ClientException;
+
+    /**
+     * Create a new file at <code>relativePath</code>.
+     * The immediate parent of <code>relativePath</code> is expected to exist.
+     *
+     * The file's contents are specified in <code>contents</code>
+     * which has a checksum matching <code>checksum</code>. Both
+     * values must be non-<code>null</code>.
+     *
+     * Set the properties of the new file to
+     * <code>properties</code>. If no properties are being set on the
+     * new file, <code>properties</code> must be empty. It is an error
+     * to pass <code>null</code> for <code>properties</code>.
+     *
+     * If this add is expected to replace a previously existing file,
+     * symlink or directory at <code>relativePath</code>, the revision
+     * number of the node to be replaced must be given in
+     * <code>replacesRevision</code>. Otherwise,
+     * <code>replacesRevision</code> must be
+     * Revision.SVN_INVALID_REVNUM.
+     *
+     * @note It is not allowed to call a "delete" followed by an "add" on the
+     *       same path. Instead, an "add" with <code>replacesRevision</code>
+     *       set accordingly MUST be used.
+     *
+     * @throws ClientException
+     */
+    void addFile(String relativePath,
+                 Checksum checksum,
+                 InputStream contents,
+                 Map<String, byte[]> properties,
+                 long replacesRevision)
+            throws ClientException;
+
+    /**
+     * Create a new symbolic link at <code>relativePath</code>, with a
+     * link target of <code>target</code>. The immediate parent of
+     * <code>relativePath</code> is expected to exist.
+     *
+     * For descriptions of <code>properties</code> and
+     * <code>replacesRevision</code>, see #addFile().
+     *
+     * @throws ClientException
+     */
+    void addSymlink(String relativePath,
+                    String target,
+                    Map<String, byte[]> properties,
+                    long replacesRevision)
+            throws ClientException;
+
+    /**
+     * Create an "absent" node of kind <code>kind</code> at
+     * <code>relativePath</code>. The immediate parent of
+     * <code>relativePath</code> is expected to exist.
+     *
+     * For a description of <code>replacesRevision</code>, see #addFile().
+     *
+     * @throws ClientException
+     */
+    void addAbsent(String relativePath,
+                   NodeKind kind,
+                   long replacesRevision)
+            throws ClientException;
+
+    /**
+     * Alter the properties of the directory at <code>relativePath</code>.
+     *
+     * <code>revision</code> specifies the revision at which the
+     * receiver should expect to find this node. That is,
+     * <code>relativePath</code> at the start of the whole edit and
+     * <code>relativePath</code> at <code>revision</code> must lie
+     * within the same node-rev (aka location history segment). This
+     * information may be used to catch an attempt to alter and
+     * out-of-date directory. If the directory does not have a
+     * corresponding revision in the repository (e.g. it has not yet
+     * been committed), then <code>revision</code> should be
+     * Revision.SVN_INVALID_REVNUM.
+     *
+     * If any changes to the set of children will be made in the
+     * future of the edit drive, then <code>children</code>
+     * <em>must</em> specify the resulting set of children. See
+     * #addDirectory() for the format of <code>children</code>.  If
+     * not changes will be made, then NULL may be specified.
+     *
+     * For a description of <code>properties</code>, see
+     * #addFile(). If no changes to the properties will be made
+     * (ie. only future changes to the set of children), then
+     * <code>properties</code> may be <code>null</code>.
+     *
+     * @throws ClientException
+     */
+    void alterDirectory(String relativePath,
+                        long revision,
+                        Iterable<String> children,
+                        Map<String, byte[]> properties)
+            throws ClientException;
+
+    /**
+     * Alter the contents and/or the properties of the file at
+     * <code>relativePath</code> with <code>revision</code> as its
+     * expected revision. See #alterDirectory() for more information
+     * about <code>revision</code>.
+     *
+     * If <code>contents</code> is non-<code>null</code>, then the
+     * stream will be copied to the file, and its checksum must match
+     * <code>checksum</code> (which must also be
+     * non-<code>null</code>). If <code>contents</code> is
+     * <code>null</code>, then <code>checksum</code> must also be
+     * <code>null</code>, and no change will be applied to the file's
+     * contents.
+     *
+     * If <code>properties</code> is non-<code>null</code>, then the
+     * properties will be applied.
+     *
+     * For a description of <code>checksum</code> and
+     * <code>contents</code>, see #addFile().
+     *
+     * This function allows <code>properties</code> to be
+     * <code>null</code>, but the parameter is otherwise described by
+     * #addFile().
+     *
+     * @throws ClientException
+     */
+    void alterFile(String relativePath,
+                   long revision,
+                   Checksum checksum,
+                   InputStream contents,
+                   Map<String, byte[]> properties)
+            throws ClientException;
+
+    /**
+     * Alter the target and/or the properties of the symlink at
+     * <code>relativePath</code> with <code>revision</code> as its
+     * expected revision. See #alterDirectory() for more information
+     * about <code>revision</code>.
+     *
+     * If <code>target</code> is non-<code>null</code>, then the
+     * symlink's target will be updated.
+     *
+     * If <code>properties</code> is non-<code>null</code>, then the
+     * properties will be applied.
+     *
+     * The target and/or the properties must be changed. It is an
+     * error to pass <code>null</code> for both <code>target</code>
+     * and <code>properties</code>.
+     *
+     * This function allows <code>properties</code> to be
+     * <code>null</code>, but the parameter is otherwise described by
+     * #addFile().
+     *
+     * @throws ClientException
+     */
+    void alterSymlink(String relativePath,
+                      long revision,
+                      String target,
+                      Map<String, byte[]> properties)
+            throws ClientException;
+
+    /**
+     * Delete the existing node at <code>relativePath</code>, expected
+     * to be identical to revision <code>revision</code> of that path.
+     *
+     * @throws ClientException
+     */
+    void delete(String relativePath,
+                long revision)
+            throws ClientException;
+
+    /**
+     * Move the node at <code>sourceRelativePath</code> to
+     * <code>destinationRelativePath</code>.
+     *
+     * For a description of <code>replacesRevision</code>, see #addFile().
+     *
+     * @note See the general instructions on paths for this API. Since
+     * the <code>sourceRelativePath</code> argument must generally be
+     * able to reference any node in the repository, the implication
+     * is that the editor's root must be the repository root.
+     *
+     * @throws ClientException
+     */
+    void copy(String sourceRelativePath,
+              long sourceRevision,
+              String destinationRelativePath,
+              long replacesRevision)
+            throws ClientException;
+
+    /**
+     * Move the node at <code>sourceRelativePath</code> to
+     * <code>destinationRelativePath</code>.
+     *
+     * <code>sourceRevision</code> specifies the revision at which the
+     * receiver should expect to find this node.  That is,
+     * <code>sourceRelativePath</code> at the start of the whole edit
+     * and<code>sourceRelativePath</code> at
+     * <code>sourceRevision</code> must lie within the same node-rev
+     * (aka history-segment).  This is just like the #delete() and
+     * #rotate().
+     *
+     * For a description of <code>replacesRevision</code>, see #addFile().
+     *
+     * @throws ClientException
+     */
+    void move(String sourceRelativePath,
+              long sourceRevision,
+              String destinationRelativePath,
+              long replacesRevision)
+            throws ClientException;
+    /**
+     * Perform a rotation among multiple nodes in the target tree.
+     *
+     * The <code>elements</code> list specifies the nodes in the tree
+     * which are located at a path and expected to be at a specific
+     * revision. These nodes are simultaneously moved in a rotation
+     * pattern.  For example, the node at index 0
+     * <code>elements</code> will be moved to the relative path
+     * specified at index 1 of <code>elements</code>. The node at
+     * index 1 will be moved to the location at index 2. The node at
+     * index N-1 will be moved to the relative path specified at index 0.
+     *
+     * The simplest form of this operation is to swap nodes A and
+     * B. One may think to move A to a temporary location T, then move
+     * B to A, then move T to B. However, this last move violations
+     * the Once Rule by moving T (which had already by edited by the
+     * move from A). In order to keep the restrictions against
+     * multiple moves of a single node, the rotation operation is
+     * needed for certain types of tree edits.
+     *
+     * @throws ClientException
+     */
+    void rotate(List<RotatePair> elements) throws ClientException;
+
+    public static final class RotatePair
+    {
+        public RotatePair(String relativePath, long revision)
+        {
+            this.relativePath = relativePath;
+            this.revision = revision;
+        }
+        public final String relativePath;
+        public final long revision;
+    }
+
+    /**
+     * Signal that the edit has been completed successfully.
+     * After this method is called, the editor is considered closed.
+     *
+     * @throws ClientException
+     */
+    void complete() throws ClientException;
+
+    /**
+     * Signal that the edit transmission was not successful.
+     * After this method is called, the editor is considered closed.
+     *
+     * @throws ClientException
+     */
+    void abort() throws ClientException;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
new file mode 100644
index 0000000..522199f
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
@@ -0,0 +1,222 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Encapsulates an RA session object and related operations.
+ * @see subversion/include/svn_ra.h#svn_ra_open
+ * @since 1.9
+ */
+public interface ISVNRemote
+{
+    /**
+     * Release the native peer (should not depend on finalize).
+     * Also invalidates any existing editors related to this session.
+     */
+    void dispose();
+
+    /**
+     * Cancel the active operation.
+     * @throws ClientException
+     */
+    void cancelOperation() throws ClientException;
+
+    /** Change the URL of the session to point to a new path in the
+     * same repository.
+     * @throws ClientException
+     * @note The operation fails if the URL has a different repository
+     *       root than the current session URL.
+     */
+    void reparent(String url) throws ClientException;
+
+    /**
+     * Get the current session URL.
+     * @throws ClientException
+     */
+    String getSessionUrl() throws ClientException;
+
+    /**
+     * Return a path relative to the current session URL.
+     * @param url Must be a child of the current session URL.
+     * @throws ClientException
+     */
+    String getSessionRelativePath(String url) throws ClientException;
+
+    /**
+     * Return a path relative to the repository root URL associated with
+     * current session URL.
+     * @param url Must be a child of the repository root URL.
+     * @throws ClientException
+     */
+    String getReposRelativePath(String url) throws ClientException;
+
+    /**
+     * Get the UUID of the session's repository.
+     * @throws ClientException
+     */
+    String getReposUUID() throws ClientException;
+
+    /**
+     * Get the root URL of the session's repository.
+     * @throws ClientException
+     */
+    String getReposRootUrl() throws ClientException;
+
+    /**
+     * Get the latest revision number from the session's repository.
+     * @throws ClientException
+     */
+    long getLatestRevision() throws ClientException;
+
+    /**
+     * Get the latest revision number at the given time
+     * from the session's repository.
+     * @throws ClientException
+     */
+    long getRevisionByDate(Date date) throws ClientException;
+
+    /**
+     * Get the latest revision number at the given time, expressed as
+     * the number of milliseconds since the epoch, from the session's
+     * repository.
+     * @throws ClientException
+     */
+    long getRevisionByTimestamp(long timestamp) throws ClientException;
+
+    /**
+     * Return the kind of the node in path at revision.
+     * @param path A path relative to the sessionn URL
+     * @throws ClientException
+     */
+    NodeKind checkPath(String path, long revision)
+            throws ClientException;
+
+    /**
+     * Return a dictionary containing all locks on or below the given path.
+     * @param path A path relative to the sessionn URL
+     * @param depth The recursion depth
+     * @note It is not considered an error for the path to not exist in HEAD.
+     *       Such a search will simply return no locks.
+     * @note This functionality is not available in pre-1.2 servers.
+     * @throws ClientException
+     */
+    Map<String, Lock> getLocks(String path, Depth depth)
+            throws ClientException;
+
+    /**
+     * Create a commit editor instance, rooted at the current session URL.
+     * @throws ClientException
+     */
+    ISVNEditor getCommitEditor() throws ClientException;
+
+    /**
+     * Enumeration of known capabilities of the repository and server.
+     */
+    public enum Capability
+    {
+        /**
+         * The capability of understanding operation depth.
+         * @since 1.5
+         */
+        depth ("depth"),
+
+        /**
+         * The capability of doing the right thing with merge-tracking
+         * information.
+         * @since 1.5
+         */
+        mergeinfo ("mergeinfo"),
+
+        /**
+         * The capability of retrieving arbitrary revprops in #getLog().
+         * @since 1.5
+         */
+        log_revprops ("log-revprops"),
+
+        /**
+         * The capability of replaying a directory in the
+         * repository (partial replay).
+         * @since 1.5
+         */
+        partial_replay ("partial-replay"),
+
+        /**
+         * The capability of including revision properties in a commit.
+         * @since 1.5
+         */
+        commit_revprops ("commit-revprops"),
+
+        /**
+         * The capability of specifying (and atomically verifying) expected
+         * preexisting values when modifying revprops.
+         * @since 1.7
+         */
+        atomic_revprops ("atomic-revprops"),
+
+        /**
+         * The capability to get inherited properties.
+         * @since 1.8
+         */
+        inherited_props ("inherited-props"),
+
+        /**
+         * The capability of a server to automatically ephemeral
+         * transaction properties.
+         * @since 1.8
+         */
+        ephemeral_txnprops ("ephemeral-txnprops"),
+
+        /**
+         * The capability of a server to walk revisions backwards in
+         * #getFileRevisions().
+         * @since 1.8
+         */
+        get_file_revs_reversed ("get-file-revs-reversed");
+
+        private Capability(String token)
+        {
+            this.token = token;
+        }
+
+        public String toString()
+        {
+            return token;
+        }
+
+        private String token;
+    }
+
+    /**
+     * Check if the server associated with this session has
+     * the given <code>capability</code>.
+     * @throws ClientException
+     */
+    boolean hasCapability(Capability capability) throws ClientException;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
index 318fb07..3a907e7 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
@@ -113,6 +113,9 @@
 	 * @throws ClientException  throw in case of problem
 	 */
 	public abstract void hotcopy(File path, File targetPath,
+			boolean cleanLogs, boolean incremental) throws ClientException;
+
+	public abstract void hotcopy(File path, File targetPath,
 			boolean cleanLogs) throws ClientException;
 
 	/**
@@ -133,8 +136,35 @@
 	public abstract void listUnusedDBLogs(File path, MessageReceiver receiver)
 			throws ClientException;
 
+
 	/**
-	 * load the data of a dump into a repository,
+	 * load the data of a dump into a repository
+	 * @param path              the path to the repository
+	 * @param dataInput         the data input source
+         * @param start             the first revision to load
+         * @param end               the last revision to load
+	 * @param ignoreUUID        ignore any UUID found in the input stream
+	 * @param forceUUID         set the repository UUID to any found in the
+	 *                          stream
+	 * @param usePreCommitHook  use the pre-commit hook when processing commits
+	 * @param usePostCommitHook use the post-commit hook when processing commits
+	 * @param relativePath      the directory in the repository, where the data
+	 *                          in put optional.
+	 * @param callback          the target for processing messages
+	 * @throws ClientException  throw in case of problem
+         * @since 1.8
+	 */
+	public abstract void load(File path, InputStream dataInput,
+                                  Revision start, Revision end,
+                                  boolean ignoreUUID, boolean forceUUID,
+                                  boolean usePreCommitHook,
+                                  boolean usePostCommitHook,
+                                  String relativePath,
+                                  ReposNotifyCallback callback)
+        throws ClientException;
+
+	/**
+	 * load the data of a dump into a repository
 	 * @param path              the path to the repository
 	 * @param dataInput         the data input source
 	 * @param ignoreUUID        ignore any UUID found in the input stream
@@ -146,6 +176,8 @@
 	 *                          in put optional.
 	 * @param callback          the target for processing messages
 	 * @throws ClientException  throw in case of problem
+         * @note behaves like the 1.8 vesion with the revision
+         *       parameters set to Revision.START and Revision.HEAD.
 	 */
 	public abstract void load(File path, InputStream dataInput,
 			boolean ignoreUUID, boolean forceUUID, boolean usePreCommitHook,
@@ -163,8 +195,9 @@
 			throws ClientException;
 
 	/**
-	 * recover the berkeley db of a repository, returns youngest revision
+	 * recover the filesystem backend of a repository
 	 * @param path              the path to the repository
+         * @return youngest revision
 	 * @throws ClientException  throw in case of problem
 	 */
 	public abstract long recover(File path, ReposNotifyCallback callback)
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java
new file mode 100644
index 0000000..7c55510
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java
@@ -0,0 +1,42 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+/**
+ * This class is used internally by the JavaHL implementation and not considered
+ * part part of the public API.
+ */
+public abstract class JNIObject
+{
+    /**
+     * slot for the address of the native peer. The JNI code controls this
+     * field. If it is set to 0 then underlying JNI object has been freed
+     */
+    protected final long cppAddr;
+
+    protected JNIObject(long cppAddr)
+    {
+        this.cppAddr = cppAddr;
+    }
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java
new file mode 100644
index 0000000..ad56e12
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java
@@ -0,0 +1,46 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.callback.ProgressCallback;
+
+/**
+ * A private class to hold the contextual information required to
+ * persist in this object, such as notification handlers.
+ */
+public class OperationContext implements ProgressCallback
+{
+    private ProgressCallback progress = null;
+
+    public void onProgress(ProgressEvent event)
+    {
+        if (progress != null)
+            progress.onProgress(event);
+    }
+
+    public void setProgressCallback(ProgressCallback progress)
+    {
+        this.progress = progress;
+    }
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
index 8a90dca..7594d6c 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
@@ -188,7 +188,19 @@
         recover_start,
 
         /** Upgrade has started. */
-        upgrade_start;
+        upgrade_start,
+
+        /**
+         * A revision was skipped during loading.
+         * @since 1.8
+         */
+        load_skipped_rev,
+
+        /**
+         * The structure of a revision is being verified.
+         * @since 1.8
+         */
+        verify_rev_structure;
     }
 
     public enum NodeAction
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
index 8af71f3..09d3048 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
@@ -147,14 +147,14 @@
         clientContext.notify = notify;
     }
 
-    public void setConflictResolver(ConflictResolverCallback listener)
+    public void setConflictResolver(ConflictResolverCallback resolver)
     {
-        clientContext.resolver = listener;
+        clientContext.resolver = resolver;
     }
 
-    public void setProgressCallback(ProgressCallback listener)
+    public void setProgressCallback(ProgressCallback progress)
     {
-        clientContext.listener = listener;
+        clientContext.setProgressCallback(progress);
     }
 
     public native void remove(Set<String> paths, boolean force,
@@ -168,9 +168,17 @@
             throws ClientException;
 
     public native void add(String path, Depth depth, boolean force,
-                           boolean noIgnores, boolean addParents)
+                           boolean noIgnores, boolean noAutoProps,
+                           boolean addParents)
         throws ClientException;
 
+    public void add(String path, Depth depth, boolean force,
+                    boolean noIgnores, boolean addParents)
+        throws ClientException
+    {
+        add(path, depth, force, noIgnores, false, addParents);
+    }
+
     public native long[] update(Set<String> paths, Revision revision,
                                 Depth depth, boolean depthIsSticky,
                                 boolean makeParents,
@@ -194,11 +202,24 @@
 
     public native void move(Set<String> srcPaths, String destPath,
                             boolean force, boolean moveAsChild,
-                            boolean makeParents,
+                            boolean makeParents, boolean metadataOnly,
+                            boolean allowMixRev,
                             Map<String, String> revpropTable,
                             CommitMessageCallback handler, CommitCallback callback)
             throws ClientException;
 
+    /** @deprecated */
+    public void move(Set<String> srcPaths, String destPath,
+                     boolean force, boolean moveAsChild,
+                     boolean makeParents,
+                     Map<String, String> revpropTable,
+                     CommitMessageCallback handler, CommitCallback callback)
+        throws ClientException
+    {
+        move(srcPaths, destPath, force, moveAsChild, makeParents, false, true,
+             revpropTable, handler, callback);
+    }
+
     public native void mkdir(Set<String> paths, boolean makeParents,
                              Map<String, String> revpropTable,
                              CommitMessageCallback handler, CommitCallback callback)
@@ -224,22 +245,34 @@
                                 boolean ignoreAncestry)
             throws ClientException;
 
-    public native void doImport(String path, String url, Depth depth,
-                                boolean noIgnore,
+    private native void doImport(String path, String url, Depth depth,
+                                boolean noIgnore, boolean noAutoProps,
                                 boolean ignoreUnknownNodeTypes,
                                 Map<String, String> revpropTable,
-                                CommitMessageCallback handler, CommitCallback callback)
+                                Object importFilterCallback,
+                                CommitMessageCallback handler,
+                                CommitCallback commitCallback)
             throws ClientException;
 
+    public void doImport(String path, String url, Depth depth, boolean noIgnore,
+                         boolean ignoreUnknownNodeTypes,
+                         Map<String, String> revpropTable,
+                         CommitMessageCallback handler,
+                         CommitCallback callback)
+            throws ClientException
+    {
+        doImport(path, url, depth, noIgnore, false, ignoreUnknownNodeTypes,
+                 revpropTable, null, handler, callback);
+    }
+
     public native Set<String> suggestMergeSources(String path,
                                                   Revision pegRevision)
             throws SubversionException;
 
     public native void merge(String path1, Revision revision1, String path2,
                              Revision revision2, String localPath,
-                             boolean force, Depth depth,
-                             boolean ignoreAncestry, boolean dryRun,
-                             boolean recordOnly)
+                             boolean force, Depth depth, boolean ignoreAncestry,
+                             boolean dryRun, boolean recordOnly)
             throws ClientException;
 
     public native void merge(String path, Revision pegRevision,
@@ -248,6 +281,8 @@
                              boolean dryRun, boolean recordOnly)
             throws ClientException;
 
+
+    /** @deprecated */
     public native void mergeReintegrate(String path, Revision pegRevision,
                                         String localPath, boolean dryRun)
             throws ClientException;
@@ -264,6 +299,7 @@
                                        LogMessageCallback callback)
         throws ClientException;
 
+
     public native void diff(String target1, Revision revision1, String target2,
                             Revision revision2, String relativeToDir,
                             String outFileName, Depth depth,
@@ -326,8 +362,16 @@
                                       boolean force)
             throws ClientException;
 
+    public byte[] propertyGet(String path, String name,
+                              Revision revision, Revision pegRevision)
+            throws ClientException
+    {
+        return propertyGet(path, name, revision, pegRevision, null);
+    }
+
     public native byte[] propertyGet(String path, String name,
-                                     Revision revision, Revision pegRevision)
+                                     Revision revision, Revision pegRevision,
+                                     Collection<String> changelists)
             throws ClientException;
 
     public byte[] fileContent(String path, Revision revision,
@@ -458,16 +502,33 @@
                              PatchCallback callback)
             throws ClientException;
 
+    public ISVNRemote openRemoteSession(String path)
+            throws ClientException, SubversionException
+    {
+        return nativeOpenRemoteSession(path, 1);
+    }
+
+    public ISVNRemote openRemoteSession(String path, int retryAttempts)
+            throws ClientException, SubversionException
+    {
+        if (retryAttempts <= 0)
+            throw new IllegalArgumentException(
+                "retryAttempts must be positive");
+        return nativeOpenRemoteSession(path, retryAttempts);
+    }
+
+    private native ISVNRemote nativeOpenRemoteSession(
+        String path, int retryAttempts)
+            throws ClientException, SubversionException;
+
     /**
      * A private class to hold the contextual information required to
      * persist in this object, such as notification handlers.
      */
-    private class ClientContext
-        implements ClientNotifyCallback, ProgressCallback,
-            ConflictResolverCallback
+    private class ClientContext extends OperationContext
+        implements ClientNotifyCallback, ConflictResolverCallback
     {
         public ClientNotifyCallback notify = null;
-        public ProgressCallback listener = null;
         public ConflictResolverCallback resolver = null;
 
         public void onNotify(ClientNotifyInformation notifyInfo)
@@ -476,12 +537,6 @@
                 notify.onNotify(notifyInfo);
         }
 
-        public void onProgress(ProgressEvent event)
-        {
-            if (listener != null)
-                listener.onProgress(event);
-        }
-
         public ConflictResult resolve(ConflictDescriptor conflict)
             throws SubversionException
         {
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
index 98b611f..1cd5d99 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
@@ -130,7 +130,14 @@
      * @throws ClientException  throw in case of problem
      */
     public native void hotcopy(File path, File targetPath,
-                               boolean cleanLogs) throws ClientException;
+                               boolean cleanLogs, boolean incremental)
+            throws ClientException;
+
+    public void hotcopy(File path, File targetPath,
+                        boolean cleanLogs) throws ClientException
+    {
+        hotcopy(path, targetPath, cleanLogs, false);
+    }
 
     /**
      * list all logfiles (BDB) in use or not)
@@ -150,7 +157,19 @@
     public native void listUnusedDBLogs(File path, ISVNRepos.MessageReceiver receiver)
             throws ClientException;
 
+    public void load(File path, InputStream dataInput,
+                     boolean ignoreUUID, boolean forceUUID,
+                     boolean usePreCommitHook, boolean usePostCommitHook,
+                     String relativePath, ReposNotifyCallback callback)
+            throws ClientException
+    {
+        load(path, dataInput, Revision.START, Revision.HEAD,
+             ignoreUUID, forceUUID, usePreCommitHook, usePostCommitHook,
+             relativePath, callback);
+    }
+
     public native void load(File path, InputStream dataInput,
+                            Revision start, Revision end,
                             boolean ignoreUUID, boolean forceUUID,
                             boolean usePreCommitHook, boolean usePostCommitHook,
                             String relativePath, ReposNotifyCallback callback)
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
index 4da1506..61ff0ca 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
@@ -29,7 +29,7 @@
 
 /**
  * This interface is used to receive every single line for a file on a
- * the {@link ISVNClient#blame} call.
+ * the {@link ISVNClient#list} call.
  */
 public interface ListCallback
 {
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
index 98f73fd..5c6b0e7 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
@@ -33,7 +33,7 @@
 public interface ProplistCallback
 {
     /**
-     * the method will be called for every line in a file.
+     * the method will be called once for every file.
      * @param path        the path.
      * @param properties  the properties on the path.
      */
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
new file mode 100644
index 0000000..3b546d2
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
@@ -0,0 +1,171 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import org.apache.subversion.javahl.ISVNEditor;
+import org.apache.subversion.javahl.JNIObject;
+import org.apache.subversion.javahl.ClientException;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of ISVNEditor that drives commits.
+ * @since 1.9
+ */
+public class CommitEditor extends JNIObject implements ISVNEditor
+{
+    public void dispose() {/* TODO */}
+
+    public void addDirectory(String relativePath,
+                             Iterable<String> children,
+                             Map<String, byte[]> properties,
+                             long replacesRevision)
+            throws ClientException
+    {
+        notimplemented("addDirectory");
+    }
+
+    public void addFile(String relativePath,
+                        Checksum checksum,
+                        InputStream contents,
+                        Map<String, byte[]> properties,
+                        long replacesRevision)
+            throws ClientException
+    {
+        notimplemented("addFile");
+    }
+
+    public void addSymlink(String relativePath,
+                           String target,
+                           Map<String, byte[]> properties,
+                           long replacesRevision)
+            throws ClientException
+    {
+        notimplemented("addSymlink");
+    }
+
+    public void addAbsent(String relativePath,
+                          NodeKind kind,
+                          long replacesRevision)
+            throws ClientException
+    {
+        notimplemented("addAbsent");
+    }
+
+    public void alterDirectory(String relativePath,
+                               long revision,
+                               Iterable<String> children,
+                               Map<String, byte[]> properties)
+            throws ClientException
+    {
+        notimplemented("alterDirectory");
+    }
+
+    public void alterFile(String relativePath,
+                          long revision,
+                          Checksum checksum,
+                          InputStream contents,
+                          Map<String, byte[]> properties)
+            throws ClientException
+    {
+        notimplemented("alterFile");
+    }
+
+    public void alterSymlink(String relativePath,
+                             long revision,
+                             String target,
+                             Map<String, byte[]> properties)
+            throws ClientException
+    {
+        notimplemented("alterSymlink");
+    }
+
+    public void delete(String relativePath,
+                       long revision)
+            throws ClientException
+    {
+        notimplemented("delete");
+    }
+
+    public void copy(String sourceRelativePath,
+                     long sourceRevision,
+                     String destinationRelativePath,
+                     long replacesRevision)
+            throws ClientException
+    {
+        notimplemented("copy");
+    }
+
+    public void move(String sourceRelativePath,
+                     long sourceRevision,
+                     String destinationRelativePath,
+                     long replacesRevision)
+            throws ClientException
+    {
+        notimplemented("move");
+    }
+
+    public void rotate(List<RotatePair> elements) throws ClientException
+    {
+        notimplemented("rotate");
+    }
+
+    public void complete() throws ClientException
+    {
+        notimplemented("complete");
+    }
+
+    public void abort() throws ClientException
+    {
+        notimplemented("abort");
+    }
+
+    /**
+     * This factory method called from RemoteSession.getCommitEditor.
+     */
+    static final CommitEditor createInstance(RemoteSession owner)
+            throws ClientException
+    {
+        // FIXME: temporary implementation
+        return new CommitEditor(0L);
+    }
+
+    /**
+     * This constructor is called from JNI to get an instance.
+     */
+    protected CommitEditor(long cppAddr)
+    {
+        super(cppAddr);
+    }
+
+    private void notimplemented(String name)
+    {
+        throw new RuntimeException("Not implemented: " + name);
+    }
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
new file mode 100644
index 0000000..e250496
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
@@ -0,0 +1,226 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.callback.*;
+import org.apache.subversion.javahl.types.*;
+
+import org.apache.subversion.javahl.ISVNRemote;
+import org.apache.subversion.javahl.NativeResources;
+import org.apache.subversion.javahl.ClientException;
+import org.apache.subversion.javahl.SubversionException;
+
+import java.util.HashSet;
+
+
+/**
+ * Factory class for creating ISVNRemote instances.
+ * @since 1.9
+ */
+public class RemoteFactory
+{
+    /**
+     * Default constructor.
+     */
+    public RemoteFactory() {}
+
+    /**
+     * Initializing constructor. Any or all of its arguments may be null.
+     */
+    public RemoteFactory(String configDirectory,
+                         String username, String password,
+                         UserPasswordCallback prompt,
+                         ProgressCallback progress)
+    {
+        setConfigDirectory(configDirectory);
+        setUsername(username);
+        setPassword(password);
+        setPrompt(prompt);
+        setProgressCallback(progress);
+    }
+
+    /**
+     * Sets the username used for authentication.
+     * @param username The username; Set to the <code>null</code> to clear it.
+     * @throws IllegalArgumentException If <code>username</code> is empty.
+     * @see #password(String)
+     */
+    public void setUsername(String username)
+    {
+        if (username != null && username.isEmpty())
+            throw new IllegalArgumentException("username must not be empty");
+        this.username = username;
+    }
+
+    /**
+     * Sets the password used for authentication.
+     * @param password The passwordp Set <code>null</code> to clear it.
+     * @throws IllegalArgumentException If <code>password</code> is empty.
+     * @see #username(String)
+     */
+    public void setPassword(String password)
+    {
+        if (password != null && password.isEmpty())
+            throw new IllegalArgumentException("password must not be empty");
+        this.password = password;
+    }
+
+    /**
+     * Register callback interface to supply username and password on demand.
+     * This callback can also be used to provide theequivalent of the
+     * <code>--no-auth-cache</code> and <code>--non-interactive</code>
+     * arguments accepted by the command-line client.
+     * @param prompt the callback interface
+     */
+    public void setPrompt(UserPasswordCallback prompt)
+    {
+        this.prompt = prompt;
+    }
+
+    /**
+     * Set the progress callback for new sessions.
+     *
+     * @param progress The progress callback.
+     */
+    public void setProgressCallback(ProgressCallback progress)
+    {
+        this.progress = progress;
+    }
+
+    /**
+     * Set directory for the configuration information.
+     */
+    public void setConfigDirectory(String configDirectory)
+    {
+        this.configDirectory = configDirectory;
+    }
+
+
+    /**
+     * Open a persistent session to a repository.
+     * @param url The initial session root URL.
+     * @throws RetryOpenSession If the session URL was redirected
+     * @throws SubversionException If an URL redirect cycle was detected
+     * @throws ClientException
+     * @note The URL can point to a subtree of the repository.
+     * @note The session object inherits the progress callback,
+     *       configuration directory and authentication info.
+     */
+    public ISVNRemote openRemoteSession(String url)
+            throws ClientException, SubversionException
+    {
+        return open(1, url, null,
+                    configDirectory, username, password, prompt, progress);
+    }
+
+    /**
+     * Open a persistent session to a repository.
+     * @param url The initial session root URL.
+     * @param retryAttempts The number of times to retry the operation
+     *        if the given URL is redirected.
+     * @throws IllegalArgumentException If <code>retryAttempts</code>
+     *         is not positive
+     * @throws RetryOpenSession If the session URL was redirected
+     * @throws SubversionException If an URL redirect cycle was detected
+     * @throws ClientException
+     * @note The URL can point to a subtree of the repository.
+     * @note The session object inherits the progress callback,
+     *       configuration directory and authentication info.
+     */
+    public ISVNRemote openRemoteSession(String url, int retryAttempts)
+            throws ClientException, SubversionException
+    {
+        if (retryAttempts <= 0)
+            throw new IllegalArgumentException(
+                "retryAttempts must be positive");
+        return open(retryAttempts, url, null,
+                    configDirectory, username, password, prompt, progress);
+    }
+
+    /**
+     * Open a persistent session to a repository.
+     * @param url The initial session root URL.
+     * @param reposUUID The expected repository UUID; may not be null..
+     * @throws IllegalArgumentException If <code>reposUUID</code> is null.
+     * @throws RetryOpenSession If the session URL was redirected
+     * @throws SubversionException If an URL redirect cycle was detected
+     * @throws ClientException
+     * @note The URL can point to a subtree of the repository.
+     * @note If the UUID does not match the repository, this function fails.
+     * @note The session object inherits the progress callback,
+     *       configuration directory and authentication info.
+     */
+    public ISVNRemote openRemoteSession(String url, String reposUUID)
+            throws ClientException, SubversionException
+    {
+        if (reposUUID == null)
+            throw new IllegalArgumentException("reposUUID may not be null");
+        return open(1, url, reposUUID,
+                    configDirectory, username, password, prompt, progress);
+    }
+
+    /**
+     * Open a persistent session to a repository.
+     * @param url The initial session root URL.
+     * @param reposUUID The expected repository UUID; may not be null..
+     * @param retryAttempts The number of times to retry the operation
+     *        if the given URL is redirected.
+     * @throws IllegalArgumentException If <code>reposUUID</code> is null
+     *         or <code>retryAttempts</code> is not positive
+     * @throws RetryOpenSession If the session URL was redirected
+     * @throws SubversionException If an URL redirect cycle was detected
+     * @throws ClientException
+     * @note The URL can point to a subtree of the repository.
+     * @note If the UUID does not match the repository, this function fails.
+     * @note The session object inherits the progress callback,
+     *       configuration directory and authentication info.
+     */
+    public ISVNRemote openRemoteSession(String url, String reposUUID,
+                                        int retryAttempts)
+            throws ClientException, SubversionException
+    {
+        if (reposUUID == null)
+            throw new IllegalArgumentException("reposUUID may not be null");
+        if (retryAttempts <= 0)
+            throw new IllegalArgumentException(
+                "retryAttempts must be positive");
+        return open(retryAttempts, url, reposUUID,
+                    configDirectory, username, password, prompt, progress);
+    }
+
+    private String configDirectory;
+    private String username;
+    private String password;
+    private UserPasswordCallback prompt;
+    private ProgressCallback progress;
+
+    /* Native factory implementation. */
+    private static native ISVNRemote open(int retryAttempts,
+                                          String url, String reposUUID,
+                                          String configDirectory,
+                                          String username, String password,
+                                          UserPasswordCallback prompt,
+                                          ProgressCallback progress)
+            throws ClientException, SubversionException;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
new file mode 100644
index 0000000..aadc1f4
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
@@ -0,0 +1,136 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import org.apache.subversion.javahl.ISVNRemote;
+import org.apache.subversion.javahl.ISVNEditor;
+import org.apache.subversion.javahl.JNIObject;
+import org.apache.subversion.javahl.OperationContext;
+import org.apache.subversion.javahl.ClientException;
+
+import java.lang.ref.WeakReference;
+import java.util.HashSet;
+import java.util.Date;
+import java.util.Map;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+public class RemoteSession extends JNIObject implements ISVNRemote
+{
+    public void dispose()
+    {
+        if (editors != null)
+        {
+            // Deactivate all open editors
+            for (WeakReference<ISVNEditor> ref : editors)
+            {
+                ISVNEditor ed = ref.get();
+                if (ed == null)
+                    continue;
+                ed.dispose();
+                ref.clear();
+            }
+        }
+        nativeDispose();
+    }
+
+    public native void cancelOperation() throws ClientException;
+
+    public native void reparent(String url) throws ClientException;
+
+    public native String getSessionUrl() throws ClientException;
+
+    public native String getSessionRelativePath(String url)
+            throws ClientException;
+
+    public native String getReposRelativePath(String url)
+            throws ClientException;
+
+    public native String getReposUUID() throws ClientException;
+
+    public native String getReposRootUrl() throws ClientException;
+
+    public native long getLatestRevision() throws ClientException;
+
+    public long getRevisionByDate(Date date) throws ClientException
+    {
+        long timestamp = NANOSECONDS.convert(date.getTime(), MILLISECONDS);
+        return getRevisionByTimestamp(timestamp);
+    }
+
+    public native long getRevisionByTimestamp(long timestamp)
+            throws ClientException;
+
+    public native NodeKind checkPath(String path, long revision)
+            throws ClientException;
+
+    public native Map<String, Lock> getLocks(String path, Depth depth)
+            throws ClientException;
+
+    public ISVNEditor getCommitEditor() throws ClientException
+    {
+        ISVNEditor ed = CommitEditor.createInstance(this);
+        if (editors == null)
+            editors = new HashSet<WeakReference<ISVNEditor>>();
+        editors.add(new WeakReference<ISVNEditor>(ed));
+        return ed;
+    }
+
+    public boolean hasCapability(Capability capability)
+            throws ClientException
+    {
+        return nativeHasCapability(capability.toString());
+    }
+
+    @Override
+    public native void finalize() throws Throwable;
+
+    /**
+     * This constructor is called from JNI to get an instance.
+     */
+    protected RemoteSession(long cppAddr)
+    {
+        super(cppAddr);
+    }
+
+    private native void nativeDispose();
+
+    private native boolean nativeHasCapability(String capability);
+
+    /*
+     * NOTE: This field is accessed from native code for callbacks.
+     */
+    private RemoteSessionContext sessionContext = new RemoteSessionContext();
+    private class RemoteSessionContext extends OperationContext {}
+
+    /*
+     * The set of open editors. We need this in order to dispose/abort
+     * the editors when the session is disposed.
+     */
+    private HashSet<WeakReference<ISVNEditor>> editors;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java
new file mode 100644
index 0000000..cc23256
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java
@@ -0,0 +1,57 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.SubversionException;
+
+/**
+ * This checked exception is thrown only from ISVNClient.openRemoteSession
+ * or RemoteFactory.openRemoteSession if a session could not be opened
+ * due to a redirect.
+ */
+public class RetryOpenSession extends SubversionException
+{
+    // Update the serialVersionUID when there is a incompatible change
+    // made to this class.
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * This constructor is only called from native code.
+     */
+    protected RetryOpenSession(String message, String correctedUrl)
+    {
+        super(message);
+        this.correctedUrl = correctedUrl;
+    }
+
+    /**
+     * @return the corrected URL for the session.
+     */
+    public String getCorrectedUrl()
+    {
+        return correctedUrl;
+    }
+
+    private final String correctedUrl;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java
index 3c59726..3c37a89 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java
@@ -31,16 +31,19 @@
 public class ConflictVersion
 {
     private String reposURL;
+    private String reposUUID;
     private long pegRevision;
     private String pathInRepos;
 
     private NodeKind nodeKind;
 
     /** This constructor should only be called from JNI code. */
-    public ConflictVersion(String reposURL, long pegRevision, String pathInRepos,
+    ConflictVersion(String reposURL, String reposUUID,
+                    long pegRevision, String pathInRepos,
                     NodeKind nodeKind)
     {
         this.reposURL = reposURL;
+        this.reposUUID = reposUUID;
         this.pegRevision = pegRevision;
         this.pathInRepos = pathInRepos;
         this.nodeKind = nodeKind;
@@ -51,6 +54,12 @@
         return reposURL;
     }
 
+    /** @since 1.8 */
+    public String getReposUUID()
+    {
+        return reposUUID;
+    }
+
     public long getPegRevision()
     {
         return pegRevision;
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java
index f81d49f..ccf39ab 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java
@@ -28,17 +28,23 @@
  */
 public enum NodeKind
 {
-    /* absent */
+    /** absent */
     none    ("none"),
 
-    /* regular file */
+    /** regular file */
     file    ("file"),
 
-    /* directory */
+    /** directory */
     dir     ("dir"),
 
-    /* something's here, but we don't know what */
-    unknown ("unknown");
+    /** something's here, but we don't know what */
+    unknown ("unknown"),
+
+    /**
+     * symbolic link
+     * @since: 1.8
+     */
+    symlink ("symlink");
 
     /**
      * The description of the node kind.
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java
index 8b26741..4e628c1 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java
@@ -165,6 +165,10 @@
      */
     private String changelist;
 
+    private String movedFromAbspath;
+
+    private String movedToAbspath;
+
     /**
      * this constructor should only called from JNI code
      * @param path                  the file system path of item
@@ -203,6 +207,8 @@
      * @param reposLastCmtAuthor    the author of the last commit, if out of
      *                              date
      * @param changelist            the changelist the item is a member of
+     * @param movedFromAbspath      path moved from
+     * @param movedToAbspath        path moved from
      */
     public Status(String path, String url, NodeKind nodeKind, long revision,
                   long lastChangedRevision, long lastChangedDate,
@@ -212,7 +218,8 @@
                   boolean switched, boolean fileExternal, Lock localLock,
                   Lock reposLock, long reposLastCmtRevision,
                   long reposLastCmtDate, NodeKind reposKind,
-                  String reposLastCmtAuthor, String changelist)
+                  String reposLastCmtAuthor, String changelist,
+                  String movedFromAbspath, String movedToAbspath)
     {
         this.path = path;
         this.url = url;
@@ -237,6 +244,8 @@
         this.reposKind = reposKind;
         this.reposLastCmtAuthor = reposLastCmtAuthor;
         this.changelist = changelist;
+        this.movedFromAbspath = movedFromAbspath;
+        this.movedToAbspath = movedToAbspath;
     }
 
     /**
@@ -585,6 +594,16 @@
         return isConflicted;
     }
 
+    public String getMovedFromAbspath()
+    {
+        return movedFromAbspath;
+    }
+
+    public String getMovedToAbspath()
+    {
+        return movedToAbspath;
+    }
+
     /**
      * Converts microseconds since the epoch to a Date object.
      *
diff --git a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java
index 015f989..9c388c5 100644
--- a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java
+++ b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java
@@ -125,8 +125,12 @@
              aDesc.getAction().ordinal(), aDesc.getReason().ordinal(),
              aDesc.getOperation().ordinal(), aDesc.getBasePath(),
              aDesc.getTheirPath(), aDesc.getMyPath(), aDesc.getMergedPath(),
-             new ConflictVersion(aDesc.getSrcLeftVersion()),
-             new ConflictVersion(aDesc.getSrcRightVersion()));
+             aDesc.getSrcLeftVersion() != null
+               ? new ConflictVersion(aDesc.getSrcLeftVersion())
+               : null,
+             aDesc.getSrcRightVersion() != null
+               ? new ConflictVersion(aDesc.getSrcRightVersion())
+               : null);
     }
 
     public String getPath()
diff --git a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
index 6343283..b8582c5 100644
--- a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
+++ b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
@@ -795,6 +795,7 @@
     /**
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void remove(String[] paths, String message, boolean force,
                        boolean keepLocal, Map revpropTable)
             throws ClientException
@@ -964,6 +965,7 @@
     /**
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public long commit(String[] paths, String message, int depth,
                        boolean noUnlock, boolean keepChangelist,
                        String[] changelists, Map revpropTable)
@@ -998,6 +1000,7 @@
     /**
      * @since 1.7
      */
+    @SuppressWarnings("unchecked")
     public void copy(CopySource[] sources, String destPath, String message,
                      boolean copyAsChild, boolean makeParents,
                      boolean ignoreExternals, Map revpropTable)
@@ -1031,6 +1034,7 @@
      *                              boolean, boolean, Map)} instead.
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void copy(CopySource[] sources, String destPath, String message,
                      boolean copyAsChild, boolean makeParents,
                      Map revpropTable)
@@ -1057,6 +1061,7 @@
     /**
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void move(String[] srcPaths, String destPath, String message,
                      boolean force, boolean moveAsChild,
                      boolean makeParents, Map revpropTable)
@@ -1106,6 +1111,7 @@
     /**
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void mkdir(String[] paths, String message,
                       boolean makeParents, Map revpropTable)
             throws ClientException
@@ -1306,6 +1312,7 @@
     /**
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void doImport(String path, String url, String message,
                          int depth, boolean noIgnore,
                          boolean ignoreUnknownNodeTypes, Map revpropTable)
@@ -1888,6 +1895,7 @@
     /**
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void propertySet(String path, String name, String value, int depth,
                             String[] changelists, boolean force,
                             Map revpropTable)
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
index 8de939c..8eac120 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
@@ -147,10 +147,10 @@
                               CommitItemStateFlags.Add);
         Set<String> urls = new HashSet<String>(1);
         urls.add(thisTest.getUrl() + "/Y");
-        try 
+        try
         {
             tempclient.mkdir(urls, false, null, new ConstMsg("log_msg"), null);
-        } 
+        }
         catch(JNIError e)
         {
 	        return; // Test passes!
@@ -898,7 +898,7 @@
         }
         client.move(srcPaths,
                     new File(thisTest.getWorkingCopy(), "A/B/F").getPath(),
-                    false, true, false, null, null, null);
+                    false, true, false, false, false, null, null, null);
 
         // Commit the changes, and check the state of the WC.
         checkCommitRevision(thisTest,
@@ -2352,222 +2352,222 @@
         acquireMergeinfoAndAssertEquals(2, 4, 6, 6, targetPath, mergeSrc);
     }
 
-    /**
-     * Test merge with automatic source and revision determination
-     * (e.g. 'svn merge -g').
-     * @throws Throwable
-     * @since 1.5
-     */
-    public void testMergeUsingHistory() throws Throwable
-    {
-        OneTest thisTest = setupAndPerformMerge();
-
-        // Test that getMergeinfo() returns null.
-        assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
-                                       .toString(), Revision.HEAD));
-
-        // Merge and commit some changes (r4).
-        appendText(thisTest, "A/mu", "xxx", 4);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 4,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-        String branchPath = thisTest.getWCPath() + "/branches/A";
-        String modUrl = thisTest.getUrl() + "/A";
-        Revision unspec = new Revision(Revision.Kind.unspecified);
-        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
-        ranges.add(new RevisionRange(unspec, unspec));
-        client.merge(modUrl, Revision.HEAD, ranges,
-                     branchPath, true, Depth.infinity, false, false, false);
-
-        // commit the changes so that we can verify merge
-        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
-                              "branches/A", NodeKind.dir,
-                              CommitItemStateFlags.PropMods);
-        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
-                              "branches/A/mu", NodeKind.file,
-                              CommitItemStateFlags.TextMods);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 5,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-    }
-
-    /**
-     * Test reintegrating a branch with trunk
-     * (e.g. 'svn merge --reintegrate').
-     * @throws Throwable
-     * @since 1.5
-     */
-    public void testMergeReintegrate() throws Throwable
-    {
-        OneTest thisTest = setupAndPerformMerge();
-
-        // Test that getMergeinfo() returns null.
-        assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
-                                       .toString(), Revision.HEAD));
-
-        // Merge and commit some changes to main (r4).
-        appendText(thisTest, "A/mu", "xxx", 4);
-        checkCommitRevision(thisTest,
-                            "wrong revision number from main commit", 4,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-        // Merge and commit some changes to branch (r5).
-        appendText(thisTest, "branches/A/D/G/rho", "yyy", -1);
-        checkCommitRevision(thisTest,
-                            "wrong revision number from branch commit", 5,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-        // update the branch WC (to r5) before merge
-        update(thisTest, "/branches");
-
-        String branchPath = thisTest.getWCPath() + "/branches/A";
-        String modUrl = thisTest.getUrl() + "/A";
-        Revision unspec = new Revision(Revision.Kind.unspecified);
-        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
-        ranges.add(new RevisionRange(unspec, unspec));
-        client.merge(modUrl, Revision.HEAD, ranges,
-                     branchPath, true, Depth.infinity, false, false, false);
-
-        // commit the changes so that we can verify merge
-        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
-                              "branches/A", NodeKind.dir,
-                              CommitItemStateFlags.PropMods);
-        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
-                              "branches/A/mu", NodeKind.file,
-                              CommitItemStateFlags.TextMods);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 6,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-        // now we --reintegrate the branch with main
-        String branchUrl = thisTest.getUrl() + "/branches/A";
-        try
-        {
-            client.mergeReintegrate(branchUrl, Revision.HEAD,
-                                    thisTest.getWCPath() + "/A", false);
-            fail("reintegrate merged into a mixed-revision WC");
-        }
-        catch(ClientException e)
-        {
-            // update the WC (to r6) and try again
-            update(thisTest);
-            client.mergeReintegrate(branchUrl, Revision.HEAD,
-                                    thisTest.getWCPath() + "/A", false);
-        }
-        // commit the changes so that we can verify merge
-        addExpectedCommitItem(thisTest.getWCPath(),
-                             thisTest.getUrl().toString(), "A", NodeKind.dir,
-                              CommitItemStateFlags.PropMods);
-        addExpectedCommitItem(thisTest.getWCPath(),
-                             thisTest.getUrl().toString(), "A/D/G/rho",
-                             NodeKind.file, CommitItemStateFlags.TextMods);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 7,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-    }
-
-    /**
-     * Test automatic merge conflict resolution.
-     * @throws Throwable
-     * @since 1.5
-     */
-    public void testMergeConflictResolution() throws Throwable
-    {
-        // Add a conflict resolution callback which always chooses the
-        // user's version of a conflicted file.
-        client.setConflictResolver(new ConflictResolverCallback()
-            {
-                public ConflictResult resolve(ConflictDescriptor descrip)
-                {
-                    return new ConflictResult(ConflictResult.Choice.chooseTheirsConflict,
-                                              null);
-                }
-            });
-
-        OneTest thisTest = new OneTest();
-        String originalContents = thisTest.getWc().getItemContent("A/mu");
-        String expectedContents = originalContents + "xxx";
-
-        // Merge and commit a change (r2).
-        File mu = appendText(thisTest, "A/mu", "xxx", 2);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 2,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-        // Backdate the WC to the previous revision (r1).
-        client.update(thisTest.getWCPathSet(), Revision.getInstance(1),
-                      Depth.unknown, false, false, false, false);
-
-        // Prep for a merge conflict by changing A/mu in a different
-        // way.
-        mu = appendText(thisTest, "A/mu", "yyy", 1);
-
-        // Merge in the previous changes to A/mu (from r2).
-        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
-        ranges.add(new RevisionRange(new Revision.Number(1),
-                                     new Revision.Number(2)));
-        client.merge(thisTest.getUrl().toString(), Revision.HEAD, ranges,
-                     thisTest.getWCPath(), false, Depth.infinity, false,
-                     false, false);
-
-        assertFileContentsEquals("Unexpected conflict resolution",
-                                 expectedContents, mu);
-    }
-
-    /**
-     * Test merge --record-only
-     * @throws Throwable
-     * @since 1.5
-     */
-    public void testRecordOnlyMerge() throws Throwable
-    {
-        OneTest thisTest = setupAndPerformMerge();
-
-        // Verify that there are now potential merge sources.
-        Set<String> suggestedSrcs =
-            client.suggestMergeSources(thisTest.getWCPath() + "/branches/A",
-                                       Revision.WORKING);
-        assertNotNull(suggestedSrcs);
-        assertEquals(1, suggestedSrcs.size());
-
-        // Test that getMergeinfo() returns null.
-        assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
-                                       .toString(), Revision.HEAD));
-
-        // Merge and commit some changes (r4).
-        appendText(thisTest, "A/mu", "xxx", 4);
-        appendText(thisTest, "A/D/G/rho", "yyy", 4);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 4,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-        // --record-only merge changes in A to branches/A
-        String branchPath = thisTest.getWCPath() + "/branches/A";
-        String modUrl = thisTest.getUrl() + "/A";
-
-        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
-        ranges.add(new RevisionRange(new Revision.Number(2),
-                                     new Revision.Number(4)));
-        client.merge(modUrl, Revision.HEAD, ranges,
-                     branchPath, true, Depth.infinity, false, false, true);
-
-        // commit the changes so that we can verify merge
-        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
-                              "branches/A", NodeKind.dir,
-                              CommitItemStateFlags.PropMods);
-        checkCommitRevision(thisTest, "wrong revision number from commit", 5,
-                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
-                            false, false, null, null);
-
-        // Test retrieval of mergeinfo from a WC path.
-        String targetPath =
-            new File(thisTest.getWCPath(), "branches/A").getPath();
-        final String mergeSrc = thisTest.getUrl() + "/A";
-        acquireMergeinfoAndAssertEquals(2, 4, 0, 0, targetPath, mergeSrc);
-    }
+//FIXME:    /**
+//FIXME:     * Test merge with automatic source and revision determination
+//FIXME:     * (e.g. 'svn merge -g').
+//FIXME:     * @throws Throwable
+//FIXME:     * @since 1.5
+//FIXME:     */
+//FIXME:    public void testMergeUsingHistory() throws Throwable
+//FIXME:    {
+//FIXME:        OneTest thisTest = setupAndPerformMerge();
+//FIXME:
+//FIXME:        // Test that getMergeinfo() returns null.
+//FIXME:        assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+//FIXME:                                       .toString(), Revision.HEAD));
+//FIXME:
+//FIXME:        // Merge and commit some changes (r4).
+//FIXME:        appendText(thisTest, "A/mu", "xxx", 4);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 4,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:        String branchPath = thisTest.getWCPath() + "/branches/A";
+//FIXME:        String modUrl = thisTest.getUrl() + "/A";
+//FIXME:        Revision unspec = new Revision(Revision.Kind.unspecified);
+//FIXME:        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME:        ranges.add(new RevisionRange(unspec, unspec));
+//FIXME:        client.merge(modUrl, Revision.HEAD, ranges,
+//FIXME:                     branchPath, true, Depth.infinity, false, false, false);
+//FIXME:
+//FIXME:        // commit the changes so that we can verify merge
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME:                              "branches/A", NodeKind.dir,
+//FIXME:                              CommitItemStateFlags.PropMods);
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME:                              "branches/A/mu", NodeKind.file,
+//FIXME:                              CommitItemStateFlags.TextMods);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 5,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:    }
+//FIXME:
+//FIXME:    /**
+//FIXME:     * Test reintegrating a branch with trunk
+//FIXME:     * (e.g. 'svn merge --reintegrate').
+//FIXME:     * @throws Throwable
+//FIXME:     * @since 1.5
+//FIXME:     */
+//FIXME:    public void testMergeReintegrate() throws Throwable
+//FIXME:    {
+//FIXME:        OneTest thisTest = setupAndPerformMerge();
+//FIXME:
+//FIXME:        // Test that getMergeinfo() returns null.
+//FIXME:        assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+//FIXME:                                       .toString(), Revision.HEAD));
+//FIXME:
+//FIXME:        // Merge and commit some changes to main (r4).
+//FIXME:        appendText(thisTest, "A/mu", "xxx", 4);
+//FIXME:        checkCommitRevision(thisTest,
+//FIXME:                            "wrong revision number from main commit", 4,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:        // Merge and commit some changes to branch (r5).
+//FIXME:        appendText(thisTest, "branches/A/D/G/rho", "yyy", -1);
+//FIXME:        checkCommitRevision(thisTest,
+//FIXME:                            "wrong revision number from branch commit", 5,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:        // update the branch WC (to r5) before merge
+//FIXME:        update(thisTest, "/branches");
+//FIXME:
+//FIXME:        String branchPath = thisTest.getWCPath() + "/branches/A";
+//FIXME:        String modUrl = thisTest.getUrl() + "/A";
+//FIXME:        Revision unspec = new Revision(Revision.Kind.unspecified);
+//FIXME:        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME:        ranges.add(new RevisionRange(unspec, unspec));
+//FIXME:        client.merge(modUrl, Revision.HEAD, ranges,
+//FIXME:                     branchPath, true, Depth.infinity, false, false, false);
+//FIXME:
+//FIXME:        // commit the changes so that we can verify merge
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME:                              "branches/A", NodeKind.dir,
+//FIXME:                              CommitItemStateFlags.PropMods);
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME:                              "branches/A/mu", NodeKind.file,
+//FIXME:                              CommitItemStateFlags.TextMods);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 6,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:        // now we --reintegrate the branch with main
+//FIXME:        String branchUrl = thisTest.getUrl() + "/branches/A";
+//FIXME:        try
+//FIXME:        {
+//FIXME:            client.mergeReintegrate(branchUrl, Revision.HEAD,
+//FIXME:                                    thisTest.getWCPath() + "/A", false);
+//FIXME:            fail("reintegrate merged into a mixed-revision WC");
+//FIXME:        }
+//FIXME:        catch(ClientException e)
+//FIXME:        {
+//FIXME:            // update the WC (to r6) and try again
+//FIXME:            update(thisTest);
+//FIXME:            client.mergeReintegrate(branchUrl, Revision.HEAD,
+//FIXME:                                    thisTest.getWCPath() + "/A", false);
+//FIXME:        }
+//FIXME:        // commit the changes so that we can verify merge
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(),
+//FIXME:                             thisTest.getUrl().toString(), "A", NodeKind.dir,
+//FIXME:                              CommitItemStateFlags.PropMods);
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(),
+//FIXME:                             thisTest.getUrl().toString(), "A/D/G/rho",
+//FIXME:                             NodeKind.file, CommitItemStateFlags.TextMods);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 7,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:    }
+//FIXME:
+//FIXME:    /**
+//FIXME:     * Test automatic merge conflict resolution.
+//FIXME:     * @throws Throwable
+//FIXME:     * @since 1.5
+//FIXME:     */
+//FIXME:    public void testMergeConflictResolution() throws Throwable
+//FIXME:    {
+//FIXME:        // Add a conflict resolution callback which always chooses the
+//FIXME:        // user's version of a conflicted file.
+//FIXME:        client.setConflictResolver(new ConflictResolverCallback()
+//FIXME:            {
+//FIXME:                public ConflictResult resolve(ConflictDescriptor descrip)
+//FIXME:                {
+//FIXME:                    return new ConflictResult(ConflictResult.Choice.chooseTheirsConflict,
+//FIXME:                                              null);
+//FIXME:                }
+//FIXME:            });
+//FIXME:
+//FIXME:        OneTest thisTest = new OneTest();
+//FIXME:        String originalContents = thisTest.getWc().getItemContent("A/mu");
+//FIXME:        String expectedContents = originalContents + "xxx";
+//FIXME:
+//FIXME:        // Merge and commit a change (r2).
+//FIXME:        File mu = appendText(thisTest, "A/mu", "xxx", 2);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 2,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:        // Backdate the WC to the previous revision (r1).
+//FIXME:        client.update(thisTest.getWCPathSet(), Revision.getInstance(1),
+//FIXME:                      Depth.unknown, false, false, false, false);
+//FIXME:
+//FIXME:        // Prep for a merge conflict by changing A/mu in a different
+//FIXME:        // way.
+//FIXME:        mu = appendText(thisTest, "A/mu", "yyy", 1);
+//FIXME:
+//FIXME:        // Merge in the previous changes to A/mu (from r2).
+//FIXME:        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME:        ranges.add(new RevisionRange(new Revision.Number(1),
+//FIXME:                                     new Revision.Number(2)));
+//FIXME:        client.merge(thisTest.getUrl().toString(), Revision.HEAD, ranges,
+//FIXME:                     thisTest.getWCPath(), false, Depth.infinity, false,
+//FIXME:                     false, false);
+//FIXME:
+//FIXME:        assertFileContentsEquals("Unexpected conflict resolution",
+//FIXME:                                 expectedContents, mu);
+//FIXME:    }
+//FIXME:
+//FIXME:    /**
+//FIXME:     * Test merge --record-only
+//FIXME:     * @throws Throwable
+//FIXME:     * @since 1.5
+//FIXME:     */
+//FIXME:    public void testRecordOnlyMerge() throws Throwable
+//FIXME:    {
+//FIXME:        OneTest thisTest = setupAndPerformMerge();
+//FIXME:
+//FIXME:        // Verify that there are now potential merge sources.
+//FIXME:        Set<String> suggestedSrcs =
+//FIXME:            client.suggestMergeSources(thisTest.getWCPath() + "/branches/A",
+//FIXME:                                       Revision.WORKING);
+//FIXME:        assertNotNull(suggestedSrcs);
+//FIXME:        assertEquals(1, suggestedSrcs.size());
+//FIXME:
+//FIXME:        // Test that getMergeinfo() returns null.
+//FIXME:        assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+//FIXME:                                       .toString(), Revision.HEAD));
+//FIXME:
+//FIXME:        // Merge and commit some changes (r4).
+//FIXME:        appendText(thisTest, "A/mu", "xxx", 4);
+//FIXME:        appendText(thisTest, "A/D/G/rho", "yyy", 4);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 4,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:        // --record-only merge changes in A to branches/A
+//FIXME:        String branchPath = thisTest.getWCPath() + "/branches/A";
+//FIXME:        String modUrl = thisTest.getUrl() + "/A";
+//FIXME:
+//FIXME:        List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME:        ranges.add(new RevisionRange(new Revision.Number(2),
+//FIXME:                                     new Revision.Number(4)));
+//FIXME:        client.merge(modUrl, Revision.HEAD, ranges,
+//FIXME:                     branchPath, true, Depth.infinity, false, false, true);
+//FIXME:
+//FIXME:        // commit the changes so that we can verify merge
+//FIXME:        addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME:                              "branches/A", NodeKind.dir,
+//FIXME:                              CommitItemStateFlags.PropMods);
+//FIXME:        checkCommitRevision(thisTest, "wrong revision number from commit", 5,
+//FIXME:                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME:                            false, false, null, null);
+//FIXME:
+//FIXME:        // Test retrieval of mergeinfo from a WC path.
+//FIXME:        String targetPath =
+//FIXME:            new File(thisTest.getWCPath(), "branches/A").getPath();
+//FIXME:        final String mergeSrc = thisTest.getUrl() + "/A";
+//FIXME:        acquireMergeinfoAndAssertEquals(2, 4, 0, 0, targetPath, mergeSrc);
+//FIXME:    }
 
     /**
      * Setup a test with a WC.  In the repository, create a
@@ -2648,7 +2648,7 @@
     }
 
     /**
-     * Test the {@link SVNClientInterface.diff()} APIs.
+     * Test the {@link ISVNClient.diff()} APIs.
      * @since 1.5
      */
     public void testDiff()
@@ -3061,7 +3061,7 @@
         }
         client.move(srcPaths,
                     new File(thisTest.getWorkingCopy(), "A/B/F").getPath(),
-                    false, true, false, null, null, null);
+                    false, true, false, false, false, null, null, null);
 
         // Commit the changes, and check the state of the WC.
         checkCommitRevision(thisTest,
@@ -3102,16 +3102,21 @@
         ConflictDescriptor conflict = conflicts.iterator().next();
 
         assertNotNull("Conflict should not be null", conflict);
+        // 1.8 assertNotNull("Repository UUID must be set", conflict.getSrcLeftVersion().getReposUUID());
 
         assertEquals(conflict.getSrcLeftVersion().getNodeKind(), NodeKind.file);
         assertEquals(conflict.getSrcLeftVersion().getReposURL() + "/" +
                 conflict.getSrcLeftVersion().getPathInRepos(), tcTest.getUrl() + "/A/B/E/alpha");
         assertEquals(conflict.getSrcLeftVersion().getPegRevision(), 1L);
 
-        assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
-        assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl().toString());
-        assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
-
+        if (conflict.getSrcRightVersion() != null)
+        {
+            assertEquals(conflict.getSrcLeftVersion().getReposUUID(),
+                         conflict.getSrcRightVersion().getReposUUID());
+            assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
+            assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl().toString());
+            assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
+        }
     }
 
     /**
@@ -3146,12 +3151,12 @@
 
         // check the status of the working copy
         thisTest.checkStatus();
-        
+
         // now edit the propval directly in the repository
         long baseRev = 2L;
         client.propertySetRemote(thisTest.getUrl()+"/A/D/G/rho", baseRev, PROP, NEWVALUE,
                                  new ConstMsg("edit prop"), false, null, null);
-        
+
         // update the WC and verify that the property was changed
         client.update(thisTest.getWCPathSet(), Revision.HEAD, Depth.infinity, false, false,
                       false, false);
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
index 7779a60..0d01e8b 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
@@ -92,6 +92,7 @@
             {
                 // Add default test suites.
                 suite.addTestSuite(SVNReposTests.class);
+                suite.addTestSuite(SVNRemoteTests.class);
                 suite.addTestSuite(BasicTests.class);
             }
             else
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
new file mode 100644
index 0000000..509baad
--- /dev/null
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
@@ -0,0 +1,251 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you 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.
+ * ====================================================================
+ * @endcopyright
+ */
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.*;
+import org.apache.subversion.javahl.remote.*;
+import org.apache.subversion.javahl.types.*;
+
+import java.util.Date;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashSet;
+import java.io.IOException;
+
+/**
+ * This class is used for testing the SVNReposAccess class
+ *
+ * More methodes for testing are still needed
+ */
+public class SVNRemoteTests extends SVNTests
+{
+    protected OneTest thisTest;
+
+    public SVNRemoteTests()
+    {
+    }
+
+    public SVNRemoteTests(String name)
+    {
+        super(name);
+    }
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        thisTest = new OneTest();
+    }
+
+    public static ISVNRemote getSession(String url, String configDirectory)
+    {
+        try
+        {
+            RemoteFactory factory = new RemoteFactory();
+            factory.setConfigDirectory(configDirectory);
+            factory.setUsername(USERNAME);
+            factory.setPassword(PASSWORD);
+            factory.setPrompt(new DefaultPromptUserPassword());
+
+            ISVNRemote raSession = factory.openRemoteSession(url);
+            assertNotNull("Null session was returned by factory", raSession);
+            return raSession;
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private ISVNRemote getSession()
+    {
+        return getSession(getTestRepoUrl(), super.conf.getAbsolutePath());
+    }
+
+    /**
+     * Test the basic SVNAdmin.create functionality
+     * @throws SubversionException
+     */
+    public void testCreate()
+        throws SubversionException, IOException
+    {
+        assertTrue("repository exists", thisTest.getRepository().exists());
+    }
+
+    public void testGetSession_ConfigConstructor() throws Exception
+    {
+        ISVNRemote session;
+        try
+        {
+            session = new RemoteFactory(
+                super.conf.getAbsolutePath(),
+                USERNAME, PASSWORD,
+                new DefaultPromptUserPassword(), null)
+                .openRemoteSession(getTestRepoUrl());
+        }
+        catch (ClientException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+        assertNotNull("Null session was returned by factory", session);
+        assertEquals(getTestRepoUrl(), session.getSessionUrl());
+    }
+
+    public void testDispose() throws Exception
+    {
+        ISVNRemote session = getSession();
+        session.dispose();
+    }
+
+    public void testDatedRev() throws Exception
+    {
+        ISVNRemote session = getSession();
+
+        long revision = session.getRevisionByDate(new Date());
+        assertEquals(revision, 1);
+    }
+
+    public void testGetLocks() throws Exception
+    {
+        ISVNRemote session = getSession();
+
+        Set<String> iotaPathSet = new HashSet<String>(1);
+        String iotaPath = thisTest.getWCPath() + "/iota";
+        iotaPathSet.add(iotaPath);
+
+        client.lock(iotaPathSet, "foo", false);
+
+        Map<String, Lock> locks = session.getLocks("iota", Depth.infinity);
+
+        assertEquals(locks.size(), 1);
+        Lock lock = locks.get("/iota");
+        assertNotNull(lock);
+        assertEquals(lock.getOwner(), "jrandom");
+    }
+
+    public void testCheckPath() throws Exception
+    {
+        ISVNRemote session = getSession();
+
+        NodeKind kind = session.checkPath("iota", 1);
+        assertEquals(NodeKind.file, kind);
+
+        kind = session.checkPath("iota", 0);
+        assertEquals(NodeKind.none, kind);
+
+        kind = session.checkPath("A", 1);
+        assertEquals(NodeKind.dir, kind);
+    }
+
+    private String getTestRepoUrl()
+    {
+        return thisTest.getUrl().toASCIIString();
+    }
+
+    public void testGetLatestRevision() throws Exception
+    {
+        ISVNRemote session = getSession();
+        long revision = session.getLatestRevision();
+        assertEquals(revision, 1);
+    }
+
+    public void testGetUUID() throws Exception
+    {
+        ISVNRemote session = getSession();
+
+        /*
+         * Test UUID
+         * TODO: Test for actual UUID once test dump file has
+         * fixed UUID
+         */
+        assertNotNull(session.getReposUUID());
+    }
+
+    public void testGetUrl() throws Exception
+    {
+        ISVNRemote session = getSession();
+
+        assertEquals(getTestRepoUrl(), session.getSessionUrl());
+    }
+
+    public void testGetRootUrl() throws Exception
+    {
+        ISVNRemote session = getSession();
+        session.reparent(session.getSessionUrl() + "/A/B/E");
+        assertEquals(getTestRepoUrl(), session.getReposRootUrl());
+    }
+
+    public void testGetUrl_viaSVNClient() throws Exception
+    {
+        ISVNRemote session = client.openRemoteSession(getTestRepoUrl());
+
+        assertEquals(getTestRepoUrl(), session.getSessionUrl());
+    }
+
+    public void testGetUrl_viaSVNClientWorkingCopy() throws Exception
+    {
+        ISVNRemote session = client.openRemoteSession(thisTest.getWCPath());
+
+        assertEquals(getTestRepoUrl(), session.getSessionUrl());
+    }
+
+    public void testReparent() throws Exception
+    {
+        ISVNRemote session = getSession();
+        String newUrl = session.getSessionUrl() + "/A/B/E";
+        session.reparent(newUrl);
+        assertEquals(newUrl, session.getSessionUrl());
+    }
+
+    public void testGetRelativePath() throws Exception
+    {
+        ISVNRemote session = getSession();
+        String baseUrl = session.getSessionUrl() + "/A/B/E";
+        session.reparent(baseUrl);
+
+        String relPath = session.getSessionRelativePath(baseUrl + "/alpha");
+        assertEquals("alpha", relPath);
+
+        relPath = session.getReposRelativePath(baseUrl + "/beta");
+        assertEquals("A/B/E/beta", relPath);
+    }
+
+    public void testGetCommitEditor() throws Exception
+    {
+        ISVNRemote session = getSession();
+        session.getCommitEditor();
+    }
+
+    public void testDisposeCommitEditor() throws Exception
+    {
+        ISVNRemote session = getSession();
+        session.getCommitEditor();
+        session.dispose();
+    }
+
+    public void testHasCapability() throws Exception
+    {
+        ISVNRemote session = getSession();
+        assert(session.hasCapability(ISVNRemote.Capability.depth));
+    }
+}
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
index eaa1ebd..ed3a2a6 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
@@ -34,7 +34,7 @@
 import java.util.Map;
 
 /**
- * This class is used for testing the SVNAdmin class
+ * This class is used for testing the ISVNRepos interface
  *
  * More methodes for testing are still needed
  */
@@ -50,7 +50,7 @@
     }
 
     /**
-     * Test the basic SVNAdmin.create functionality
+     * Test the basic ISVNRepos.create functionality
      * @throws SubversionException
      */
     public void testCreate()
@@ -103,7 +103,7 @@
     public void testLoadRepo()
         throws SubversionException, IOException
     {
-        /* Make sure SVNAdmin.load() works, with a repo dump file known
+        /* Make sure ISVNRepos.load() works, with a repo dump file known
          * to provoke bug 2979
          */
         // makes repos with nothing in it
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
index 5e4f32e..dd79925 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
@@ -145,6 +145,16 @@
     protected static String rootUrl;
 
     /**
+     * Username to use in tests
+     */
+    protected final static String USERNAME = "jrandom";
+
+    /**
+     * Password to use in tests
+     */
+    protected final static String PASSWORD = "rayjandom";
+
+    /**
      * Create a JUnit <code>TestCase</code> instance.
      */
     protected SVNTests()
@@ -276,7 +286,7 @@
         this.client = new SVNClient();
         this.client.notification2(new MyNotifier());
         this.client.setPrompt(new DefaultPromptUserPassword());
-        this.client.username("jrandom");
+        this.client.username(USERNAME);
         this.client.setProgressCallback(new DefaultProgressListener());
         this.client.setConfigDirectory(this.conf.getAbsolutePath());
         this.expectedCommitItems = new HashMap<String, MyCommitItem>();
@@ -284,7 +294,7 @@
     /**
      * the default prompt : never prompts the user, provides defaults answers
      */
-    private static class DefaultPromptUserPassword implements UserPasswordCallback
+    protected static class DefaultPromptUserPassword implements UserPasswordCallback
     {
 
         public int askTrustSSLServer(String info, boolean allowPermanently)
@@ -304,12 +314,12 @@
 
         public String getPassword()
         {
-            return "rayjandom";
+            return PASSWORD;
         }
 
         public String getUsername()
         {
-            return "jrandom";
+            return USERNAME;
         }
 
         public boolean prompt(String realm, String username)
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
index 852e087..3407b96 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
@@ -2176,6 +2176,7 @@
      * are no revisions to return.
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     private long[] getMergeinfoRevisions(int kind, String pathOrUrl,
                                          Revision pegRevision,
                                          String mergeSourceUrl,
@@ -3039,10 +3040,12 @@
                 conflict.getSrcLeftVersion().getPathInRepos(), tcTest.getUrl() + "/A/B/E/alpha");
         assertEquals(conflict.getSrcLeftVersion().getPegRevision(), 1L);
 
-        assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
-        assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl());
-        assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
-
+        if (conflict.getSrcRightVersion() != null)
+        {
+            assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
+            assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl());
+            assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
+        }
     }
 
     /**
@@ -3240,6 +3243,7 @@
      * @throws Throwable
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public void testCommitRevprops() throws Throwable
     {
 
@@ -3346,6 +3350,7 @@
         // change made to this class.
         private static final long serialVersionUID = 1L;
 
+        @SuppressWarnings("unchecked")
         public void onSummary(DiffSummary descriptor)
         {
             super.put(descriptor.getPath(), descriptor);
@@ -3355,6 +3360,7 @@
     private class MyChangelistCallback extends HashMap
         implements ChangelistCallback
     {
+        @SuppressWarnings("unchecked")
         public void doChangelist(String path, String changelist)
         {
             if (super.containsKey(path))
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java
index 779b782..606142c 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java
@@ -47,6 +47,7 @@
          *
          * @return The complete test suite.
          */
+        @SuppressWarnings("unchecked")
         public static TestSuite suite()
         {
             TestSuite suite = new SVNTestSuite();
@@ -75,9 +76,8 @@
                         Constructor ctor =
                             clazz.getDeclaredConstructor(argTypes);
                         methodName = methodName.substring(i + 1);
-                        String[] args = { methodName };
                         testCases[testCaseIndex++] =
-                            (TestCase) ctor.newInstance(args);
+                            (TestCase) ctor.newInstance(methodName);
                     }
                     catch (Exception e)
                     {
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java
index 8b7d6ff..1e858c8 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java
@@ -438,6 +438,7 @@
      * @param stateFlags        expected commit state flags
      *                          (see CommitItemStateFlags)
      */
+    @SuppressWarnings("unchecked")
     protected void addExpectedCommitItem(String workingCopyPath,
                                          String baseUrl,
                                          String itemPath,
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java
index 4f1f389..6f68ae9 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java
@@ -627,6 +627,7 @@
          * @param path      the path of the item.
          * @param content   the content of the item. A null signals a directory.
          */
+        @SuppressWarnings("unchecked")
         private Item(String path, String content)
         {
             myPath = path;
@@ -639,6 +640,7 @@
          * @param source    the copy source.
          * @param owner     the WC of the copy
          */
+        @SuppressWarnings("unchecked")
         private Item(Item source, WC owner)
         {
             myPath = source.myPath;