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 2014/06/06 14:43:50 UTC

svn commit: r1600873 - /subversion/trunk/subversion/bindings/javahl/native/

Author: brane
Date: Fri Jun  6 12:43:49 2014
New Revision: 1600873

URL: http://svn.apache.org/r1600873
Log:
Reimplement the authentication prompter in JavaHL,
based on the new native class wrappers.

[in subversion/bindings/javahl]
* native/Prompter.h, native/Prompter.cpp:
   Reimplement the whole shebang. Create a compatibility wrapper for the
   deprecated UserPasswordCallback.

* native/OperationContext.h: Include <memory>.
  (OperationContext::m_prompter): Change type to auto_ptr.
  (OperationContext::setPrompt): Change parameter to auto_ptr.
  (OperationContext::getPrompter): Removed.
  (OperationContext::clonePrompter): New.
* native/OperationContext.cpp:
   Adjust implementation to new Prompter interface.

* native/RemoteSession.h, native/RemoteSessionContext.h,
  native/RemoteSession.cpp, native/RemoteSessionContext.cpp.
  native/SVNClient.cpp, native/org_apache_subversion_javahl_SVNClient.cpp:
   Update prompter references to use smart pointers.

Modified:
    subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp
    subversion/trunk/subversion/bindings/javahl/native/OperationContext.h
    subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp
    subversion/trunk/subversion/bindings/javahl/native/Prompter.h
    subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
    subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
    subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp
    subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h
    subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp

Modified: subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp Fri Jun  6 12:43:49 2014
@@ -86,8 +86,6 @@ OperationContext::attachJavaObject(
 
 OperationContext::~OperationContext()
 {
-  delete m_prompter;
-
   JNIEnv *env = JNIUtil::getEnv();
   env->DeleteGlobalRef(m_jctx);
   if (m_jcfgcb)
@@ -154,12 +152,12 @@ OperationContext::getAuthBaton(SVN::Pool
       svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func;
       void *plaintext_passphrase_prompt_baton;
 
-      if (m_prompter != NULL)
+      if (m_prompter.get())
         {
           plaintext_prompt_func = Prompter::plaintext_prompt;
-          plaintext_prompt_baton = m_prompter;
+          plaintext_prompt_baton = m_prompter.get();
           plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt;
-          plaintext_passphrase_prompt_baton = m_prompter;
+          plaintext_passphrase_prompt_baton = m_prompter.get();
         }
       else
         {
@@ -196,24 +194,24 @@ OperationContext::getAuthBaton(SVN::Pool
       providers = apr_array_make(pool, 0, sizeof(svn_auth_provider_object_t *));
     }
 
-  if (m_prompter != NULL)
+  if (m_prompter.get())
     {
       /* Two basic prompt providers: username/password, and just username.*/
-      provider = m_prompter->getProviderSimple(in_pool);
+      provider = m_prompter->get_provider_simple(in_pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-      provider = m_prompter->getProviderUsername(in_pool);
+      provider = m_prompter->get_provider_username(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);
+      provider = m_prompter->get_provider_server_ssl_trust(in_pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-      provider = m_prompter->getProviderClientSSL(in_pool);
+      provider = m_prompter->get_provider_client_ssl(in_pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-      provider = m_prompter->getProviderClientSSLPassword(in_pool);
+      provider = m_prompter->get_provider_client_ssl_password(in_pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
     }
 
@@ -253,9 +251,8 @@ OperationContext::password(const char *p
 }
 
 void
-OperationContext::setPrompt(Prompter *prompter)
+OperationContext::setPrompt(Prompter::UniquePtr prompter)
 {
-  delete m_prompter;
   m_prompter = prompter;
 }
 
@@ -310,9 +307,11 @@ OperationContext::getPassword() const
   return (m_passWord.empty() ? NULL : m_passWord.c_str());
 }
 
-const Prompter& OperationContext::getPrompter() const
+Prompter::UniquePtr OperationContext::clonePrompter() const
 {
-  return *m_prompter;
+  if (m_prompter.get())
+    return m_prompter->clone();
+  return Prompter::UniquePtr(NULL);
 }
 
 void OperationContext::setTunnelCallback(jobject jtunnelcb)

Modified: subversion/trunk/subversion/bindings/javahl/native/OperationContext.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/OperationContext.h?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/OperationContext.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/OperationContext.h Fri Jun  6 12:43:49 2014
@@ -28,6 +28,7 @@
 #define JAVAHL_OPERATION_CONTEXT_H
 
 #include <string>
+#include <memory>
 
 #include "svn_types.h"
 #include "svn_client.h"
@@ -51,7 +52,7 @@ class OperationContext
 
   apr_hash_t * m_config;
 
-  Prompter *m_prompter;
+  std::auto_ptr<Prompter> m_prompter;
   svn_atomic_t m_cancelOperation;
 
  protected:
@@ -89,7 +90,7 @@ class OperationContext
 
   virtual void username(const char *pi_username);
   virtual void password(const char *pi_password);
-  virtual void setPrompt(Prompter *prompter);
+  virtual void setPrompt(std::auto_ptr<Prompter> prompter);
   svn_auth_baton_t *getAuthBaton(SVN::Pool &in_pool);
 
   void cancelOperation();
@@ -99,7 +100,7 @@ class OperationContext
   const char *getConfigDirectory() const;
   const char *getUsername() const;
   const char *getPassword() const;
-  const Prompter& getPrompter() const;
+  std::auto_ptr<Prompter> clonePrompter() const;
 
   /**
    * Set the configuration directory, taking the usual steps to

Modified: subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp Fri Jun  6 12:43:49 2014
@@ -25,348 +25,56 @@
  */
 
 #include "Prompter.h"
-#include "Pool.h"
+#include "AuthnCallback.hpp"
+
 #include "JNIUtil.h"
 #include "JNIStringHolder.h"
 #include "../include/org_apache_subversion_javahl_callback_UserPasswordCallback.h"
+
 #include <apr_strings.h>
-#include "svn_auth.h"
 #include "svn_error.h"
 #include "svn_error_codes.h"
 #include "svn_private_config.h"
 
-/**
- * Constructor
- * @param jprompter     a global reference to the Java callback object
- */
-Prompter::Prompter(jobject jprompter)
-  : m_prompter(jprompter),
-    m_maySave(false)
-{}
-
-Prompter::~Prompter()
-{
-  if (m_prompter!= NULL)
-    {
-      // Since the reference to the Java object is a global one, it
-      // has to be deleted.
-      JNIEnv *env = JNIUtil::getEnv();
-      env->DeleteGlobalRef(m_prompter);
-    }
-}
-
-/**
- * Create a C++ peer object for the Java callback object
- *
- * @param jprompter     Java callback object
- * @return              C++ peer object
- */
-Prompter *Prompter::makeCPrompter(jobject jprompter)
-{
-  // If we have no Java object, we need no C++ object.
-  if (jprompter == NULL)
-    return NULL;
-
-  JNIEnv *env = JNIUtil::getEnv();
-
-  // Create a local frame for our references
-  env->PushLocalFrame(LOCAL_FRAME_SIZE);
-  if (JNIUtil::isJavaExceptionThrown())
-    return NULL;
-
-  // Sanity check that the Java object implements UserPasswordCallback.
-  jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/UserPasswordCallback");
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
-
-  if (!env->IsInstanceOf(jprompter, clazz))
-    POP_AND_RETURN_NULL;
-
-  // Create a new global ref for the Java object, because it is
-  // longer used that this call.
-  jobject myPrompt = env->NewGlobalRef(jprompter);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
-
-  env->PopLocalFrame(NULL);
-
-  // Create the C++ peer.
-  return new Prompter(myPrompt);
-}
-
-Prompter *Prompter::makeCPrompter(const Prompter& prompter)
-{
-  return makeCPrompter(prompter.m_prompter);
-}
-
-/**
- * Retrieve the username from the Java object
- * @return Java string for the username or NULL
- */
-jstring Prompter::username()
-{
-  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/UserPasswordCallback");
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN_NULL;
-
-      mid = env->GetMethodID(clazz, "getUsername", "()Ljava/lang/String;");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN_NULL;
-    }
-
-  jstring ret = static_cast<jstring>(env->CallObjectMethod(m_prompter, mid));
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
-
-  return (jstring) env->PopLocalFrame(ret);
-}
-
-/**
- * Retrieve the password from the Java object
- * @return Java string for the password or NULL
- */
-jstring Prompter::password()
-{
-  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;
+#include "jniwrapper/jni_stack.hpp"
+#include "jniwrapper/jni_string.hpp"
 
-  if (mid == 0)
-    {
-      jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/UserPasswordCallback");
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN_NULL;
-
-      mid = env->GetMethodID(clazz, "getPassword", "()Ljava/lang/String;");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN_NULL;
-    }
+// Class Prompter
 
-  jstring ret = static_cast<jstring>(env->CallObjectMethod(m_prompter, mid));
-  if (JNIUtil::isJavaExceptionThrown())
-    return NULL;
-
-  return (jstring) env->PopLocalFrame(ret);
-}
-/**
- * Ask the user a question, which can be answered by yes/no.
- * @param realm         the server realm, for which this question is asked
- * @param question      the question to ask the user
- * @param yesIsDefault  flag if the yes-button should be the default button
- * @return flag who the user answered the question
- */
-bool Prompter::askYesNo(const char *realm, const char *question,
-                        bool yesIsDefault)
+Prompter::UniquePtr Prompter::create(jobject jprompter)
 {
-  JNIEnv *env = JNIUtil::getEnv();
-
-  // Create a local frame for our references
-  env->PushLocalFrame(LOCAL_FRAME_SIZE);
-  if (JNIUtil::isJavaExceptionThrown())
-    return false;
-
-  // 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/UserPasswordCallback");
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN(false);
-
-      mid = env->GetMethodID(clazz, "askYesNo",
-                             "(Ljava/lang/String;Ljava/lang/String;Z)Z");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN(false);
-    }
+  if (!jprompter)
+    return UniquePtr(NULL);
 
-  // convert the texts to Java strings
-  jstring jrealm = JNIUtil::makeJString(realm);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
-
-  jstring jquestion = JNIUtil::makeJString(question);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
-
-  // execute the callback
-  jboolean ret = env->CallBooleanMethod(m_prompter, mid, jrealm, jquestion,
-                                        yesIsDefault ? JNI_TRUE : JNI_FALSE);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
-
-  env->PopLocalFrame(NULL);
-  return ret ? true:false;
-}
-
-const char *Prompter::askQuestion(const char *realm, const char *question,
-                                  bool showAnswer, bool maySave)
-{
-  JNIEnv *env = JNIUtil::getEnv();
-
-  // Create a local frame for our references
-  env->PushLocalFrame(LOCAL_FRAME_SIZE);
-  if (JNIUtil::isJavaExceptionThrown())
-    return NULL;
-
-  static jmethodID mid = 0;
-  static jmethodID mid2 = 0;
-  if (mid == 0)
+  // Make sure no C++ exceptions are propagated from here.
+  const ::Java::Env jenv;
+  try
     {
-      jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/UserPasswordCallback");
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN_NULL;
-
-      mid = env->GetMethodID(clazz, "askQuestion",
-                             "(Ljava/lang/String;Ljava/lang/String;"
-                             "ZZ)Ljava/lang/String;");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN_NULL;
-
-      mid2 = env->GetMethodID(clazz, "userAllowedSave", "()Z");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN_NULL;
-    }
+      const jclass cls = ::Java::ClassCache::get_authn_cb();
+      if (!jenv.IsInstanceOf(jprompter, cls))
+        return UniquePtr(NULL);
 
-  jstring jrealm = JNIUtil::makeJString(realm);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
-
-  jstring jquestion = JNIUtil::makeJString(question);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
-
-  jstring janswer = static_cast<jstring>(
-                       env->CallObjectMethod(m_prompter, mid, jrealm,
-                                    jquestion,
-                                    showAnswer ? JNI_TRUE : JNI_FALSE,
-                                    maySave ? JNI_TRUE : JNI_FALSE));
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN_NULL;
-
-  JNIStringHolder answer(janswer);
-  if (answer != NULL)
-    {
-      m_answer = answer;
-      m_maySave = env->CallBooleanMethod(m_prompter, mid2) ? true: false;
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN_NULL;
+      return UniquePtr(new Prompter(jenv, jprompter));
     }
-  else
-    {
-      m_answer = "";
-      m_maySave = false;
-    }
-
-  env->PopLocalFrame(NULL);
-  return m_answer.c_str();
+  SVN_JAVAHL_JNI_CATCH;
+  return UniquePtr(NULL);
 }
 
-int Prompter::askTrust(const char *question, bool maySave)
+Prompter::UniquePtr Prompter::clone() const
 {
-   static jmethodID mid = 0;
-   JNIEnv *env = JNIUtil::getEnv();
-
-   // Create a local frame for our references
-   env->PushLocalFrame(LOCAL_FRAME_SIZE);
-   if (JNIUtil::isJavaExceptionThrown())
-     return -1;
-
-   if (mid == 0)
-     {
-       jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/UserPasswordCallback");
-       if (JNIUtil::isJavaExceptionThrown())
-         POP_AND_RETURN(-1);
-
-       mid = env->GetMethodID(clazz, "askTrustSSLServer",
-                              "(Ljava/lang/String;Z)I");
-       if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-         POP_AND_RETURN(-1);
-     }
-   jstring jquestion = JNIUtil::makeJString(question);
-   if (JNIUtil::isJavaExceptionThrown())
-     POP_AND_RETURN(-1);
-
-   jint ret = env->CallIntMethod(m_prompter, mid, jquestion,
-                                 maySave ? JNI_TRUE : JNI_FALSE);
-   if (JNIUtil::isJavaExceptionThrown())
-     POP_AND_RETURN(-1);
-
-   env->PopLocalFrame(NULL);
-   return ret;
+  return create(m_prompter.get());
 }
 
-bool Prompter::prompt(const char *realm, const char *pi_username, bool maySave)
-{
-  JNIEnv *env = JNIUtil::getEnv();
-  jboolean ret;
-
-  // Create a local frame for our references
-  env->PushLocalFrame(LOCAL_FRAME_SIZE);
-  if (JNIUtil::isJavaExceptionThrown())
-    return false;
-
-  static jmethodID mid = 0;
-  static jmethodID mid2 = 0;
-  if (mid == 0)
-    {
-      jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/UserPasswordCallback");
-      if (JNIUtil::isJavaExceptionThrown())
-        POP_AND_RETURN(false);
-
-      mid = env->GetMethodID(clazz, "prompt",
-                             "(Ljava/lang/String;Ljava/lang/String;Z)Z");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN(false);
-
-      mid2 = env->GetMethodID(clazz, "userAllowedSave", "()Z");
-      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
-        POP_AND_RETURN(false);
-    }
-
-  jstring jrealm = JNIUtil::makeJString(realm);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
-
-  jstring jusername = JNIUtil::makeJString(pi_username);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
-
-  ret = env->CallBooleanMethod(m_prompter, mid, jrealm, jusername,
-                               maySave ? JNI_TRUE: JNI_FALSE);
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
+Prompter::Prompter(::Java::Env env, jobject jprompter)
+  : m_prompter(env, jprompter)
+{}
 
-  m_maySave = env->CallBooleanMethod(m_prompter, mid2) ? true : false;
-  if (JNIUtil::isJavaExceptionThrown())
-    POP_AND_RETURN(false);
+Prompter::~Prompter() {}
 
-  env->PopLocalFrame(NULL);
-  return ret ? true:false;
-}
 
-svn_auth_provider_object_t *Prompter::getProviderSimple(SVN::Pool &in_pool)
+svn_auth_provider_object_t *
+Prompter::get_provider_simple(SVN::Pool &in_pool)
 {
   apr_pool_t *pool = in_pool.getPool();
   svn_auth_provider_object_t *provider;
@@ -379,7 +87,8 @@ svn_auth_provider_object_t *Prompter::ge
   return provider;
 }
 
-svn_auth_provider_object_t *Prompter::getProviderUsername(SVN::Pool &in_pool)
+svn_auth_provider_object_t *
+Prompter::get_provider_username(SVN::Pool &in_pool)
 {
   apr_pool_t *pool = in_pool.getPool();
   svn_auth_provider_object_t *provider;
@@ -392,7 +101,8 @@ svn_auth_provider_object_t *Prompter::ge
   return provider;
 }
 
-svn_auth_provider_object_t *Prompter::getProviderServerSSLTrust(SVN::Pool &in_pool)
+svn_auth_provider_object_t *Prompter::
+get_provider_server_ssl_trust(SVN::Pool &in_pool)
 {
   apr_pool_t *pool = in_pool.getPool();
   svn_auth_provider_object_t *provider;
@@ -402,7 +112,8 @@ svn_auth_provider_object_t *Prompter::ge
   return provider;
 }
 
-svn_auth_provider_object_t *Prompter::getProviderClientSSL(SVN::Pool &in_pool)
+svn_auth_provider_object_t *Prompter::
+get_provider_client_ssl(SVN::Pool &in_pool)
 {
   apr_pool_t *pool = in_pool.getPool();
   svn_auth_provider_object_t *provider;
@@ -415,7 +126,8 @@ svn_auth_provider_object_t *Prompter::ge
   return provider;
 }
 
-svn_auth_provider_object_t *Prompter::getProviderClientSSLPassword(SVN::Pool &in_pool)
+svn_auth_provider_object_t *
+Prompter::get_provider_client_ssl_password(SVN::Pool &in_pool)
 {
   apr_pool_t *pool = in_pool.getPool();
   svn_auth_provider_object_t *provider;
@@ -426,72 +138,425 @@ svn_auth_provider_object_t *Prompter::ge
   return provider;
 }
 
-svn_error_t *Prompter::simple_prompt(svn_auth_cred_simple_t **cred_p,
-                                     void *baton,
-                                     const char *realm, const char *username,
-                                     svn_boolean_t may_save,
-                                     apr_pool_t *pool)
-{
-  Prompter *that = static_cast<Prompter *>(baton);
-  svn_auth_cred_simple_t *ret =
-    reinterpret_cast<svn_auth_cred_simple_t*>(apr_pcalloc(pool, sizeof(*ret)));
-  if (!that->prompt(realm, username, may_save ? true : false))
+svn_error_t *Prompter::simple_prompt(
+    svn_auth_cred_simple_t **cred_p,
+    void *baton,
+    const char *realm,
+    const char *username,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_simple_prompt(
+          env, cred_p, realm, username, may_save, pool));
+  return err;
+}
+
+svn_error_t *Prompter::username_prompt(
+    svn_auth_cred_username_t **cred_p,
+    void *baton,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_username_prompt(
+          env, cred_p, realm, may_save, pool));
+  return err;
+}
+
+svn_error_t *Prompter::ssl_server_trust_prompt(
+    svn_auth_cred_ssl_server_trust_t **cred_p,
+    void *baton,
+    const char *realm,
+    apr_uint32_t failures,
+    const svn_auth_ssl_server_cert_info_t *cert_info,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_ssl_server_trust_prompt(
+          env, cred_p, realm, failures, cert_info, may_save, pool));
+  return err;
+}
+
+svn_error_t *Prompter::ssl_client_cert_prompt(
+    svn_auth_cred_ssl_client_cert_t **cred_p,
+    void *baton,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_ssl_client_cert_prompt(
+          env, cred_p, realm, may_save, pool));
+  return err;
+}
+
+svn_error_t *Prompter::ssl_client_cert_pw_prompt(
+    svn_auth_cred_ssl_client_cert_pw_t **cred_p,
+    void *baton,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_ssl_client_cert_pw_prompt(
+          env, cred_p, realm, may_save, pool));
+  return err;
+}
+
+svn_error_t *Prompter::plaintext_prompt(
+    svn_boolean_t *may_save_plaintext,
+    const char *realmstring,
+    void *baton,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_plaintext_prompt(
+          env, may_save_plaintext, realmstring, pool));
+  return err;
+}
+
+svn_error_t *Prompter::plaintext_passphrase_prompt(
+    svn_boolean_t *may_save_plaintext,
+    const char *realmstring,
+    void *baton,
+    apr_pool_t *pool)
+{
+  const ::Java::Env env;
+  svn_error_t *err;
+  SVN_JAVAHL_CATCH(
+      env, SVN_ERR_RA_NOT_AUTHORIZED,
+      err = static_cast<Prompter*>(baton)->dispatch_plaintext_passphrase_prompt(
+          env, may_save_plaintext, realmstring, pool));
+  return err;
+}
+
+
+svn_error_t *Prompter::dispatch_simple_prompt(
+    ::Java::Env env,
+    svn_auth_cred_simple_t **cred_p,
+    const char *realm,
+    const char *username,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+
+  ::JavaHL::AuthnCallback::AuthnResult result(
+      env,
+      authn.user_password_prompt(::Java::String(env, realm),
+                                 ::Java::String(env, username),
+                                 may_save));
+  if (!result.get())
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
-  jstring juser = that->username();
-  JNIStringHolder user(juser);
-  if (user == NULL)
+
+  ::Java::String user(env, result.identity());
+  ::Java::String pass(env, result.secret());
+  svn_auth_cred_simple_t *cred =
+    static_cast<svn_auth_cred_simple_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->username = user.strdup(pool);
+  cred->password  = pass.strdup(pool);
+  cred->may_save = result.save();
+  *cred_p = cred;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *Prompter::dispatch_username_prompt(
+    ::Java::Env env,
+    svn_auth_cred_username_t **cred_p,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+
+  ::JavaHL::AuthnCallback::AuthnResult result(
+      env,
+      authn.username_prompt(::Java::String(env, realm), may_save));
+  if (!result.get())
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
-  ret->username = apr_pstrdup(pool,user);
-  jstring jpass = that->password();
-  JNIStringHolder pass(jpass);
-  if (pass == NULL)
+
+  ::Java::String user(env, result.identity());
+  svn_auth_cred_username_t *cred =
+    static_cast<svn_auth_cred_username_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->username = user.strdup(pool);
+  cred->may_save = result.save();
+  *cred_p = cred;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *Prompter::dispatch_ssl_server_trust_prompt(
+    ::Java::Env env,
+    svn_auth_cred_ssl_server_trust_t **cred_p,
+    const char *realm,
+    apr_uint32_t failures,
+    const svn_auth_ssl_server_cert_info_t *cert_info,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+
+  ::JavaHL::AuthnCallback::AuthnResult result(
+      env,
+      authn.ssl_server_trust_prompt(
+          ::Java::String(env, realm),
+          ::JavaHL::AuthnCallback::SSLServerCertFailures(env, jint(failures)),
+          ::JavaHL::AuthnCallback::SSLServerCertInfo(
+              env,
+              ::Java::String(env, cert_info->hostname),
+              ::Java::String(env, cert_info->fingerprint),
+              ::Java::String(env, cert_info->valid_from),
+              ::Java::String(env, cert_info->valid_until),
+              ::Java::String(env, cert_info->issuer_dname),
+              ::Java::String(env, cert_info->ascii_cert)),
+          may_save));
+  if (!result.get())
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
-  else
+
+  const bool trust = result.trust();
+  if (!trust)
     {
-      ret->password  = apr_pstrdup(pool, pass);
-      ret->may_save = that->m_maySave;
+      *cred_p = NULL;
+      return SVN_NO_ERROR;
     }
-  *cred_p = ret;
+
+  const bool save = result.save();
+  svn_auth_cred_ssl_server_trust_t *cred =
+    static_cast<svn_auth_cred_ssl_server_trust_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->may_save = save;
+  if (save)
+    cred->accepted_failures = failures;
+  *cred_p = cred;
 
   return SVN_NO_ERROR;
 }
 
-svn_error_t *Prompter::username_prompt(svn_auth_cred_username_t **cred_p,
-                                       void *baton,
-                                       const char *realm,
-                                       svn_boolean_t may_save,
-                                       apr_pool_t *pool)
+svn_error_t *Prompter::dispatch_ssl_client_cert_prompt(
+    ::Java::Env env,
+    svn_auth_cred_ssl_client_cert_t **cred_p,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+
+  ::JavaHL::AuthnCallback::AuthnResult result(
+      env,
+      authn.ssl_client_cert_prompt(::Java::String(env, realm), may_save));
+  if (!result.get())
+    return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
+                            _("User canceled dialog"));
+
+  ::Java::String path(env, result.identity());
+  svn_auth_cred_ssl_client_cert_t *cred =
+    static_cast<svn_auth_cred_ssl_client_cert_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->cert_file = path.strdup(pool);
+  cred->may_save = result.save();
+  *cred_p = cred;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *Prompter::dispatch_ssl_client_cert_pw_prompt(
+    ::Java::Env env,
+    svn_auth_cred_ssl_client_cert_pw_t **cred_p,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+
+  ::JavaHL::AuthnCallback::AuthnResult result(
+      env,
+      authn.ssl_client_cert_passphrase_prompt(
+          ::Java::String(env, realm), may_save));
+  if (!result.get())
+    return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
+                            _("User canceled dialog"));
+
+  ::Java::String passphrase(env, result.secret());
+  svn_auth_cred_ssl_client_cert_pw_t *cred =
+    static_cast<svn_auth_cred_ssl_client_cert_pw_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->password = passphrase.strdup(pool);
+  cred->may_save = result.save();
+  *cred_p = cred;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *Prompter::dispatch_plaintext_prompt(
+    ::Java::Env env,
+    svn_boolean_t *may_save_plaintext,
+    const char *realmstring,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+  *may_save_plaintext =
+    authn.allow_store_plaintext_password(::Java::String(env, realmstring));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *Prompter::dispatch_plaintext_passphrase_prompt(
+    ::Java::Env env,
+    svn_boolean_t *may_save_plaintext,
+    const char *realmstring,
+    apr_pool_t *pool)
+{
+  ::JavaHL::AuthnCallback authn(env, m_prompter.get());
+  *may_save_plaintext =
+    authn.allow_store_plaintext_passphrase(::Java::String(env, realmstring));
+  return SVN_NO_ERROR;
+}
+
+
+// Class CompatPrompter
+
+Prompter::UniquePtr CompatPrompter::create(jobject jprompter)
+{
+  if (!jprompter)
+    return UniquePtr(NULL);
+
+  // Make sure no C++ exceptions are propagated from here.
+  const ::Java::Env jenv;
+  try
+    {
+      const jclass cls = ::Java::ClassCache::get_user_passwd_cb();
+      if (!jenv.IsInstanceOf(jprompter, cls))
+        return UniquePtr(NULL);
+
+      return UniquePtr(new CompatPrompter(jenv, jprompter));
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return UniquePtr(NULL);
+}
+
+Prompter::UniquePtr CompatPrompter::clone() const
+{
+  return create(m_prompter.get());
+}
+
+CompatPrompter::CompatPrompter(::Java::Env env, jobject jprompter)
+  : Prompter(env, jprompter)
+{}
+
+CompatPrompter::~CompatPrompter() {}
+
+namespace {
+jstring compat_ask_question(
+    bool& allowed_save,
+    ::Java::Env env,
+    ::JavaHL::UserPasswordCallback& authn,
+    const char *realm, const char *question,
+    bool show_answer, bool may_save)
+{
+  const jstring janswer =
+    authn.ask_question(::Java::String(env, realm),
+                       ::Java::String(env, question),
+                       show_answer, may_save);
+
+  if (janswer)
+    allowed_save = authn.user_allowed_save();
+  else
+    allowed_save = false;
+
+  return janswer;
+}
+} // anonymous namespace
+
+svn_error_t *CompatPrompter::dispatch_simple_prompt(
+    ::Java::Env env,
+    svn_auth_cred_simple_t **cred_p,
+    const char *realm, const char *username,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
 {
-  Prompter *that = static_cast<Prompter *>(baton);
-  svn_auth_cred_username_t *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)
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
+
+  if (!authn.prompt(::Java::String(env, realm),
+                    ::Java::String(env, username),
+                    may_save))
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
-  ret->username = apr_pstrdup(pool,user);
-  ret->may_save = that->m_maySave;
-  *cred_p = ret;
+  const ::Java::String user(env, authn.get_username());
+  const ::Java::String pass(env, authn.get_password());
+
+  if (!user.get() || !pass.get())
+    return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
+                            _("User canceled dialog"));
+
+  svn_auth_cred_simple_t *cred =
+    static_cast<svn_auth_cred_simple_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->username = user.strdup(pool);
+  cred->password  = pass.strdup(pool);
+  cred->may_save = authn.user_allowed_save();
+  *cred_p = cred;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *CompatPrompter::dispatch_username_prompt(
+    ::Java::Env env,
+    svn_auth_cred_username_t **cred_p,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
+
+  bool allowed_save;
+  const ::Java::String user(
+      env,
+      compat_ask_question(allowed_save, env, authn,
+                          realm, _("Username: "), true, may_save));
+  if (!user.get())
+    return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
+                            _("User canceled dialog"));
+
+  svn_auth_cred_username_t *cred =
+    static_cast<svn_auth_cred_username_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->username = user.strdup(pool);
+  cred->may_save = allowed_save;
+  *cred_p = cred;
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-Prompter::ssl_server_trust_prompt(svn_auth_cred_ssl_server_trust_t **cred_p,
-                                  void *baton,
-                                  const char *realm,
-                                  apr_uint32_t failures,
-                                  const svn_auth_ssl_server_cert_info_t *cert_info,
-                                  svn_boolean_t may_save,
-                                  apr_pool_t *pool)
-{
-  Prompter *that = static_cast<Prompter *>(baton);
-  svn_auth_cred_ssl_server_trust_t *ret =
-    reinterpret_cast<svn_auth_cred_ssl_server_trust_t*>(apr_pcalloc(pool, sizeof(*ret)));
+CompatPrompter::dispatch_ssl_server_trust_prompt(
+    ::Java::Env env,
+    svn_auth_cred_ssl_server_trust_t **cred_p,
+    const char *realm,
+    apr_uint32_t failures,
+    const svn_auth_ssl_server_cert_info_t *cert_info,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
 
   std::string question = _("Error validating server certificate for ");
   question += realm;
@@ -531,16 +596,19 @@ Prompter::ssl_server_trust_prompt(svn_au
       question += "\n";
     }
 
-  switch(that->askTrust(question.c_str(), may_save ? true : false))
+  svn_auth_cred_ssl_server_trust_t *cred =
+    static_cast<svn_auth_cred_ssl_server_trust_t*>(apr_pcalloc(pool, sizeof(*cred)));
+
+  switch (authn.ask_trust_ssl_server(::Java::String(env, question), may_save))
     {
     case org_apache_subversion_javahl_callback_UserPasswordCallback_AcceptTemporary:
-      *cred_p = ret;
-      ret->may_save = FALSE;
+      cred->may_save = FALSE;
+      *cred_p = cred;
       break;
     case org_apache_subversion_javahl_callback_UserPasswordCallback_AcceptPermanently:
-      *cred_p = ret;
-      ret->may_save = TRUE;
-      ret->accepted_failures = failures;
+      cred->may_save = TRUE;
+      cred->accepted_failures = failures;
+      *cred_p = cred;
       break;
     default:
       *cred_p = NULL;
@@ -549,79 +617,91 @@ Prompter::ssl_server_trust_prompt(svn_au
 }
 
 svn_error_t *
-Prompter::ssl_client_cert_prompt(svn_auth_cred_ssl_client_cert_t **cred_p,
-                                 void *baton,
-                                 const char *realm,
-                                 svn_boolean_t may_save,
-                                 apr_pool_t *pool)
-{
-  Prompter *that = static_cast<Prompter *>(baton);
-  svn_auth_cred_ssl_client_cert_t *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);
-  if (cert_file == NULL)
+CompatPrompter::dispatch_ssl_client_cert_prompt(
+    ::Java::Env env,
+    svn_auth_cred_ssl_client_cert_t **cred_p,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
+
+  bool allowed_save;
+  const ::Java::String path(
+      env,
+      compat_ask_question(allowed_save, env, authn, realm,
+                          _("Client certificate filename: "),
+                          true, may_save));
+  if (!path.get())
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
-  ret->cert_file = apr_pstrdup(pool, cert_file);
-  ret->may_save = that->m_maySave;
-  *cred_p = ret;
+
+  svn_auth_cred_ssl_client_cert_t *cred =
+    static_cast<svn_auth_cred_ssl_client_cert_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->cert_file = path.strdup(pool);
+  cred->may_save = allowed_save;
+  *cred_p = cred;
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-Prompter::ssl_client_cert_pw_prompt(svn_auth_cred_ssl_client_cert_pw_t **cred_p,
-                                    void *baton,
-                                    const char *realm,
-                                    svn_boolean_t may_save,
-                                    apr_pool_t *pool)
-{
-  Prompter *that = static_cast<Prompter *>(baton);
-  svn_auth_cred_ssl_client_cert_pw_t *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);
-  if (info == NULL)
+CompatPrompter::dispatch_ssl_client_cert_pw_prompt(
+    ::Java::Env env,
+    svn_auth_cred_ssl_client_cert_pw_t **cred_p,
+    const char *realm,
+    svn_boolean_t may_save,
+    apr_pool_t *pool)
+{
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
+
+  bool allowed_save;
+  const ::Java::String info(
+      env,
+      compat_ask_question(allowed_save, env, authn, realm,
+                          _("Client certificate passphrase: "),
+                          false, may_save));
+  if (!info.get())
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                             _("User canceled dialog"));
-  ret->password = apr_pstrdup(pool, info);
-  ret->may_save = that->m_maySave;
-  *cred_p = ret;
+
+  svn_auth_cred_ssl_client_cert_pw_t *cred =
+    static_cast<svn_auth_cred_ssl_client_cert_pw_t*>(apr_pcalloc(pool, sizeof(*cred)));
+  cred->password = info.strdup(pool);
+  cred->may_save = allowed_save;
+  *cred_p = cred;
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-Prompter::plaintext_prompt(svn_boolean_t *may_save_plaintext,
-                           const char *realmstring,
-                           void *baton,
-                           apr_pool_t *pool)
-{
-  Prompter *that = static_cast<Prompter *>(baton);
-
-  bool result = that->askYesNo(realmstring,
-                               _("Store password unencrypted?"),
-                               false);
-
-  *may_save_plaintext = (result ? TRUE : FALSE);
+CompatPrompter::dispatch_plaintext_prompt(
+    ::Java::Env env,
+    svn_boolean_t *may_save_plaintext,
+    const char *realmstring,
+    apr_pool_t *pool)
+{
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
+
+  *may_save_plaintext = authn.ask_yes_no(
+      ::Java::String(env, realmstring),
+      ::Java::String(env, _("Store password unencrypted?")),
+      false);
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-Prompter::plaintext_passphrase_prompt(svn_boolean_t *may_save_plaintext,
-                                      const char *realmstring,
-                                      void *baton,
-                                      apr_pool_t *pool)
-{
-  Prompter *that = static_cast<Prompter *>(baton);
-
-  bool result = that->askYesNo(realmstring,
-                               _("Store passphrase unencrypted?"),
-                               false);
-
-  *may_save_plaintext = (result ? TRUE : FALSE);
+CompatPrompter::dispatch_plaintext_passphrase_prompt(
+    ::Java::Env env,
+    svn_boolean_t *may_save_plaintext,
+    const char *realmstring,
+    apr_pool_t *pool)
+{
+  ::JavaHL::UserPasswordCallback authn(env, m_prompter.get());
+
+  *may_save_plaintext = authn.ask_yes_no(
+      ::Java::String(env, realmstring),
+      ::Java::String(env, _("Store passphrase unencrypted?")),
+      false);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/bindings/javahl/native/Prompter.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/Prompter.h?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/Prompter.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/Prompter.h Fri Jun  6 12:43:49 2014
@@ -24,96 +24,219 @@
  * @brief Interface of the class Prompter
  */
 
-#ifndef PROMPTER_H
-#define PROMPTER_H
+#ifndef SVN_JAVAHL_PROMPTER_H
+#define SVN_JAVAHL_PROMPTER_H
+
+#include <memory>
 
-#include <jni.h>
 #include "svn_auth.h"
-#include <string>
+
 #include "Pool.h"
-/**
- * This class requests username/password and informations about
- * ssl-certificates from the user.
- */
+
+#include "jniwrapper/jni_globalref.hpp"
+
 class Prompter
 {
- private:
+public:
+  typedef ::std::auto_ptr<Prompter> UniquePtr;
+
   /**
-   * The Java callback object.
+   * Factory method; @a prompter is a local reference to the Java
+   * callback object.
    */
-  jobject m_prompter;
+  static Prompter::UniquePtr create(jobject jprompter);
 
   /**
-   * Tntermediate storage for an answer.
+   * Return a clone of the current object, referring to the same Java
+   * prompter object.
    */
-  std::string m_answer;
+  virtual Prompter::UniquePtr clone() const;
+
+  virtual ~Prompter();
+
+  svn_auth_provider_object_t *get_provider_username(SVN::Pool &in_pool);
+  svn_auth_provider_object_t *get_provider_simple(SVN::Pool &in_pool);
+  svn_auth_provider_object_t *get_provider_server_ssl_trust(SVN::Pool &in_pool);
+  svn_auth_provider_object_t *get_provider_client_ssl(SVN::Pool &in_pool);
+  svn_auth_provider_object_t *get_provider_client_ssl_password(SVN::Pool &in_pool);
+
+protected:
+  explicit Prompter(::Java::Env env, jobject jprompter);
 
   /**
-   * Flag is the user allowed, that the last answer is stored in the
-   * configuration.
+   * The Java callback object.
    */
-  bool m_maySave;
+  ::Java::GlobalObject m_prompter;
 
-  Prompter(jobject jprompter);
-  Prompter(const Prompter&) {}
+  virtual svn_error_t *dispatch_simple_prompt(
+      ::Java::Env env,
+      svn_auth_cred_simple_t **cred_p,
+      const char *realm,
+      const char *username,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  static svn_error_t *simple_prompt(
+      svn_auth_cred_simple_t **cred_p,
+      void *baton,
+      const char *realm,
+      const char *username,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_username_prompt(
+      ::Java::Env env,
+      svn_auth_cred_username_t **cred_p,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  static svn_error_t *username_prompt(
+      svn_auth_cred_username_t **cred_p,
+      void *baton,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_ssl_server_trust_prompt(
+      ::Java::Env env,
+      svn_auth_cred_ssl_server_trust_t **cred_p,
+      const char *realm,
+      apr_uint32_t failures,
+      const svn_auth_ssl_server_cert_info_t *cert_info,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  static svn_error_t *ssl_server_trust_prompt(
+      svn_auth_cred_ssl_server_trust_t **cred_p,
+      void *baton,
+      const char *realm,
+      apr_uint32_t failures,
+      const svn_auth_ssl_server_cert_info_t *cert_info,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_ssl_client_cert_prompt(
+      ::Java::Env env,
+      svn_auth_cred_ssl_client_cert_t **cred_p,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  static svn_error_t *ssl_client_cert_prompt(
+      svn_auth_cred_ssl_client_cert_t **cred_p,
+      void *baton,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_ssl_client_cert_pw_prompt(
+      ::Java::Env env,
+      svn_auth_cred_ssl_client_cert_pw_t **cred_p,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  static svn_error_t *ssl_client_cert_pw_prompt(
+      svn_auth_cred_ssl_client_cert_pw_t **cred_p,
+      void *baton,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+protected:
+  virtual svn_error_t *dispatch_plaintext_prompt(
+      ::Java::Env env,
+      svn_boolean_t *may_save_plaintext,
+      const char *realmstring,
+      apr_pool_t *pool);
+
+public:
+  static svn_error_t *plaintext_prompt(
+      svn_boolean_t *may_save_plaintext,
+      const char *realmstring,
+      void *baton,
+      apr_pool_t *pool);
+
+protected:
+  virtual svn_error_t *dispatch_plaintext_passphrase_prompt(
+      ::Java::Env env,
+      svn_boolean_t *may_save_plaintext,
+      const char *realmstring,
+      apr_pool_t *pool);
 
-  bool prompt(const char *realm, const char *pi_username, bool maySave);
-  bool askYesNo(const char *realm, const char *question, bool yesIsDefault);
-  const char *askQuestion(const char *realm, const char *question,
-                          bool showAnswer, bool maySave);
-  int askTrust(const char *question, bool maySave);
-  jstring password();
-  jstring username();
-  static svn_error_t *simple_prompt(svn_auth_cred_simple_t **cred_p,
-                                    void *baton, const char *realm,
-                                    const char *username,
-                                    svn_boolean_t may_save,
-                                    apr_pool_t *pool);
-  static svn_error_t *username_prompt
-    (svn_auth_cred_username_t **cred_p,
-     void *baton,
-     const char *realm,
-     svn_boolean_t may_save,
-     apr_pool_t *pool);
-  static svn_error_t *ssl_server_trust_prompt
-    (svn_auth_cred_ssl_server_trust_t **cred_p,
-     void *baton,
-     const char *realm,
-     apr_uint32_t failures,
-     const svn_auth_ssl_server_cert_info_t *cert_info,
-     svn_boolean_t may_save,
-     apr_pool_t *pool);
-  static svn_error_t *ssl_client_cert_prompt
-    (svn_auth_cred_ssl_client_cert_t **cred_p,
-     void *baton,
-     const char *realm,
-     svn_boolean_t may_save,
-     apr_pool_t *pool);
-  static svn_error_t *ssl_client_cert_pw_prompt
-    (svn_auth_cred_ssl_client_cert_pw_t **cred_p,
-     void *baton,
-     const char *realm,
-     svn_boolean_t may_save,
-     apr_pool_t *pool);
- public:
-  static Prompter *makeCPrompter(jobject jprompter);
-  static Prompter *makeCPrompter(const Prompter& prompter);
-  ~Prompter();
-  svn_auth_provider_object_t *getProviderUsername(SVN::Pool &in_pool);
-  svn_auth_provider_object_t *getProviderSimple(SVN::Pool &in_pool);
-  svn_auth_provider_object_t *getProviderServerSSLTrust(SVN::Pool &in_pool);
-  svn_auth_provider_object_t *getProviderClientSSL(SVN::Pool &in_pool);
-  svn_auth_provider_object_t *getProviderClientSSLPassword(SVN::Pool &in_pool);
-
-  static svn_error_t *plaintext_prompt(svn_boolean_t *may_save_plaintext,
-                                       const char *realmstring,
-                                       void *baton,
-                                       apr_pool_t *pool);
+public:
   static svn_error_t *plaintext_passphrase_prompt(
-                                      svn_boolean_t *may_save_plaintext,
-                                      const char *realmstring,
-                                      void *baton,
-                                      apr_pool_t *pool);
+      svn_boolean_t *may_save_plaintext,
+      const char *realmstring,
+      void *baton,
+      apr_pool_t *pool);
+};
+
+
+/**
+ * This class requests username/password and informations about
+ * ssl-certificates from the user.
+ */
+class CompatPrompter : public Prompter
+{
+public:
+  static Prompter::UniquePtr create(jobject jprompter);
+  virtual Prompter::UniquePtr clone() const;
+  virtual ~CompatPrompter();
+
+protected:
+  explicit CompatPrompter(::Java::Env env, jobject jprompter);
+
+  virtual svn_error_t *dispatch_simple_prompt(
+      ::Java::Env env,
+      svn_auth_cred_simple_t **cred_p,
+      const char *realm,
+      const char *username,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_username_prompt(
+      ::Java::Env env,
+      svn_auth_cred_username_t **cred_p,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_ssl_server_trust_prompt(
+      ::Java::Env env,
+      svn_auth_cred_ssl_server_trust_t **cred_p,
+      const char *realm,
+      apr_uint32_t failures,
+      const svn_auth_ssl_server_cert_info_t *cert_info,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_ssl_client_cert_prompt(
+      ::Java::Env env,
+      svn_auth_cred_ssl_client_cert_t **cred_p,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_ssl_client_cert_pw_prompt(
+      ::Java::Env env,
+      svn_auth_cred_ssl_client_cert_pw_t **cred_p,
+      const char *realm,
+      svn_boolean_t may_save,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_plaintext_prompt(
+      ::Java::Env env,
+      svn_boolean_t *may_save_plaintext,
+      const char *realmstring,
+      apr_pool_t *pool);
+
+  virtual svn_error_t *dispatch_plaintext_passphrase_prompt(
+      ::Java::Env env,
+      svn_boolean_t *may_save_plaintext,
+      const char *realmstring,
+      apr_pool_t *pool);
 };
 
-#endif // PROMPTER_H
+#endif // SVN_JAVAHL_PROMPTER_H

Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp Fri Jun  6 12:43:49 2014
@@ -101,23 +101,16 @@ RemoteSession::open(jint jretryAttempts,
     return NULL;
   env->DeleteLocalRef(jpassword);
 
-  Prompter *prompter = NULL;
-  if (jprompter != NULL)
-    {
-      prompter = Prompter::makeCPrompter(jprompter);
-      if (JNIUtil::isExceptionThrown())
-        return NULL;
-    }
+  Prompter::UniquePtr prompter(CompatPrompter::create(jprompter));
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
 
   jobject jremoteSession = open(
       jretryAttempts, url.c_str(), uuid,
       (jconfigDirectory ? configDirectory.c_str() : NULL),
       usernameStr, passwordStr, prompter, jprogress, jcfgcb, jtunnelcb);
   if (JNIUtil::isExceptionThrown() || !jremoteSession)
-    {
-      delete prompter;
-      jremoteSession = NULL;
-    }
+    jremoteSession = NULL;
   return jremoteSession;
 }
 
@@ -126,7 +119,7 @@ RemoteSession::open(jint jretryAttempts,
                     const char* url, const char* uuid,
                     const char* configDirectory,
                     const char*  usernameStr, const char*  passwordStr,
-                    Prompter*& prompter, jobject jprogress,
+                    Prompter::UniquePtr prompter, jobject jprogress,
                     jobject jcfgcb, jobject jtunnelcb)
 {
   RemoteSession* session = new RemoteSession(
@@ -193,7 +186,7 @@ RemoteSession::RemoteSession(int retryAt
                              const char* url, const char* uuid,
                              const char* configDirectory,
                              const char*  username, const char*  password,
-                             Prompter*& prompter,
+                             Prompter::UniquePtr prompter,
                              jobject jcfgcb, jobject jtunnelcb)
   : m_session(NULL), m_context(NULL)
 {
@@ -202,14 +195,6 @@ RemoteSession::RemoteSession(int retryAt
   if (JNIUtil::isJavaExceptionThrown())
     return;
 
-  // Avoid double-free in RemoteSession::open and
-  // SVNClient::openRemoteSession if the svn_ra_open call fails. The
-  // prompter object is now owned by m_context.
-  //
-  // FIXME: Should be using smart pointers, really -- but JavaHL
-  // currently doesn't. Future enhancements FTW.
-  prompter = NULL;
-
   const char* corrected_url = NULL;
   bool cycle_detected = false;
   attempt_set attempted;

Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h Fri Jun  6 12:43:49 2014
@@ -54,7 +54,7 @@ class RemoteSession : public SVNBase
                         const char* url, const char* uuid,
                         const char* configDirectory,
                         const char* username, const char* password,
-                        Prompter*& prompter, jobject jprogress,
+                        Prompter::UniquePtr prompter, jobject jprogress,
                         jobject jcfgcb, jobject jtunnelcb);
     ~RemoteSession();
 
@@ -119,7 +119,7 @@ class RemoteSession : public SVNBase
                   const char* url, const char* uuid,
                   const char* configDirectory,
                   const char* username, const char* password,
-                  Prompter*& prompter, jobject jcfgcb, jobject jtunnelcb);
+                  Prompter::UniquePtr prompter, jobject jcfgcb, jobject jtunnelcb);
 
     svn_ra_session_t* m_session;
     RemoteSessionContext* m_context;

Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp Fri Jun  6 12:43:49 2014
@@ -33,7 +33,7 @@
 RemoteSessionContext::RemoteSessionContext(
     SVN::Pool &pool, const char* configDirectory,
     const char* usernameStr, const char* passwordStr,
-    Prompter* prompter, jobject jcfgcb, jobject jtunnelcb)
+    Prompter::UniquePtr prompter, jobject jcfgcb, jobject jtunnelcb)
   : OperationContext(pool), m_raCallbacks(NULL)
 {
   setConfigDirectory(configDirectory);

Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h Fri Jun  6 12:43:49 2014
@@ -37,7 +37,7 @@ class RemoteSessionContext : public Oper
     RemoteSessionContext(SVN::Pool &pool,
                          const char* jconfigDirectory,
                          const char* jusername, const char* jpassword,
-                         Prompter* prompter,
+                         std::auto_ptr<Prompter> prompter,
                          jobject jcfgcb, jobject jtunnelcb);
     virtual ~RemoteSessionContext();
     void activate(jobject jremoteSession, jobject jprogress);

Modified: subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp Fri Jun  6 12:43:49 2014
@@ -1509,18 +1509,15 @@ SVNClient::openRemoteSession(const char*
 
     /* Decouple the RemoteSession's context from SVNClient's context
        by creating a copy of the prompter here. */
-    Prompter* prompter = Prompter::makeCPrompter(context.getPrompter());
-    if (!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, context.getSelf(),
+        context.clonePrompter(), context.getSelf(),
         context.getConfigEventHandler(), context.getTunnelCallback());
     if (JNIUtil::isJavaExceptionThrown())
-      delete prompter;
+      jremoteSession = NULL;
 
     return jremoteSession;
 }

Modified: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1600873&r1=1600872&r2=1600873&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Fri Jun  6 12:43:49 2014
@@ -268,7 +268,7 @@ Java_org_apache_subversion_javahl_SVNCli
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  Prompter *prompter = Prompter::makeCPrompter(jprompter);
+  Prompter::UniquePtr prompter(CompatPrompter::create(jprompter));
   if (JNIUtil::isExceptionThrown())
     return;