You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/06/25 03:17:10 UTC

svn commit: r1496327 [1/2] - in /subversion/branches/javahl-1.7-extensions: ./ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ subvers...

Author: brane
Date: Tue Jun 25 01:17:09 2013
New Revision: 1496327

URL: http://svn.apache.org/r1496327
Log:
On the (new) javahl-1.7-extensions branch: Manually merge extensions from trunk up to r1494938
(this is effectively a merge from javahl-1.8-extensions).
All tests now pass.

Added:
    subversion/branches/javahl-1.7-extensions/BRANCH-README
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
Removed:
    subversion/branches/javahl-1.7-extensions/STATUS
Modified:
    subversion/branches/javahl-1.7-extensions/Makefile.in
    subversion/branches/javahl-1.7-extensions/build.conf
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/JNIUtil.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java

Added: subversion/branches/javahl-1.7-extensions/BRANCH-README
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/BRANCH-README?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/BRANCH-README (added)
+++ subversion/branches/javahl-1.7-extensions/BRANCH-README Tue Jun 25 01:17:09 2013
@@ -0,0 +1,2 @@
+This is a temporary backport branch for maintaining the 1.8 JavaHL extensions
+from ^/subversion/branches/javahl-1.8-extensions in a 1.7-based environment.

Modified: subversion/branches/javahl-1.7-extensions/Makefile.in
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/Makefile.in?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/Makefile.in (original)
+++ subversion/branches/javahl-1.7-extensions/Makefile.in Tue Jun 25 01:17:09 2013
@@ -440,10 +440,14 @@ clean-javahl:
 
 extraclean-javahl: clean-javahl
 
-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
+
+#check-javahl: javahl javahl-compat
+#	@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
 
 # "make check CLEANUP=true" will clean up directories for successful tests.
 # "make check TESTS=subversion/tests/cmdline/basic_tests.py"

Modified: subversion/branches/javahl-1.7-extensions/build.conf
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/build.conf?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/build.conf (original)
+++ subversion/branches/javahl-1.7-extensions/build.conf Tue Jun 25 01:17:09 2013
@@ -57,6 +57,8 @@ private-built-includes =
         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 @@ type = java
 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 @@ add-deps = $(javahl_java_DEPS)
 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 @@ path = subversion/bindings/javahl/native
 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)

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.cpp Tue Jun 25 01:17:09 2013
@@ -39,39 +39,13 @@
 
 
 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;
-
-        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;
+    attachJavaObject(jsvnclient, "L"JAVA_PACKAGE"/SVNClient$ClientContext;", "clientContext", &ctxFieldID);
 
-    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,16 +69,11 @@ ClientContext::ClientContext(jobject jsv
     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);
 }
 
 
@@ -139,7 +108,6 @@ svn_client_ctx_t *
 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
@@ -157,118 +125,15 @@ ClientContext::getContext(CommitMessage 
 
     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 @@ ClientContext::getContext(CommitMessage 
 }
 
 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 @@ ClientContext::notify(void *baton,
   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,

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.h?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/ClientContext.h Tue Jun 25 01:17:09 2013
@@ -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 @@ class CommitMessage;
  * 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 @@ class ClientContext
 
  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

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.cpp Tue Jun 25 01:17:09 2013
@@ -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
@@ -418,6 +419,72 @@ CreateJ::Lock(const svn_lock_t *lock)
 }
 
 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 +496,7 @@ CreateJ::ChangedPath(const char *path, s
 
   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 +509,7 @@ CreateJ::ChangedPath(const char *path, s
                                "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);

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.h?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/CreateJ.h Tue Jun 25 01:17:09 2013
@@ -55,6 +55,9 @@ class CreateJ
   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

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/JNIUtil.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/JNIUtil.h?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/JNIUtil.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/JNIUtil.h Tue Jun 25 01:17:09 2013
@@ -272,4 +272,12 @@ class JNIUtil
  */
 #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

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.cpp?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.cpp (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.cpp Tue Jun 25 01:17:09 2013
@@ -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;
+}

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.h?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.h (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/OperationContext.h Tue Jun 25 01:17:09 2013
@@ -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

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp Tue Jun 25 01:17:09 2013
@@ -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);
+}

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h Tue Jun 25 01:17:09 2013
@@ -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

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.cpp?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.cpp (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.cpp Tue Jun 25 01:17:09 2013
@@ -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;
+}

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.h?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.h (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSessionContext.h Tue Jun 25 01:17:09 2013
@@ -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 */

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.cpp Tue Jun 25 01:17:09 2013
@@ -30,7 +30,6 @@
 SVNBase::SVNBase()
     : pool(JNIUtil::getPool())
 {
-  jthis = NULL;
 }
 
 SVNBase::~SVNBase()
@@ -58,17 +57,6 @@ jlong SVNBase::findCppAddrForJObject(job
       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 @@ void SVNBase::finalize()
   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 @@ inline void SVNBase::findCppAddrFieldID(
         }
     }
 }
+
+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;
+}

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.h?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNBase.h Tue Jun 25 01:17:09 2013
@@ -49,7 +49,7 @@ class SVNBase
    *
    * @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 @@ class SVNBase
    *
    * @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:
   /**

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.cpp Tue Jun 25 01:17:09 2013
@@ -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 @@ SVNClient *SVNClient::getCppObject(jobje
     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()
@@ -1497,6 +1499,77 @@ SVNClient::patch(const char *patchPath, 
                                  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_occured(), 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()
 {

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.h?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNClient.h Tue Jun 25 01:17:09 2013
@@ -60,6 +60,7 @@ class RevpropTable;
 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);
@@ -196,7 +197,7 @@ class SVNClient :public SVNBase
   ClientContext &getClientContext();
 
   const char *getLastPath();
-  void dispose();
+  virtual void dispose(jobject jthis);
   static SVNClient *getCppObject(jobject jthis);
   SVNClient(jobject jthis_in);
   virtual ~SVNClient();

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.cpp Tue Jun 25 01:17:09 2013
@@ -54,10 +54,10 @@ SVNRepos *SVNRepos::getCppObject(jobject
   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()

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.h?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/SVNRepos.h Tue Jun 25 01:17:09 2013
@@ -69,7 +69,7 @@ class SVNRepos : public SVNBase
   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);

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Tue Jun 25 01:17:09 2013
@@ -75,7 +75,7 @@ Java_org_apache_subversion_javahl_SVNCli
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  cl->dispose();
+  cl->dispose(jthis);
 }
 
 JNIEXPORT void JNICALL
@@ -1764,3 +1764,22 @@ Java_org_apache_subversion_javahl_SVNCli
             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);
+}

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp?rev=1496327&r1=1496326&r2=1496327&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp Tue Jun 25 01:17:09 2013
@@ -60,7 +60,7 @@ Java_org_apache_subversion_javahl_SVNRep
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  cl->dispose();
+  cl->dispose(jthis);
 }
 
 JNIEXPORT void JNICALL

Added: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp?rev=1496327&view=auto
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp (added)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp Tue Jun 25 01:17:09 2013
@@ -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;
+}