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/18 00:51:05 UTC

svn commit: r1603306 - in /subversion/trunk/subversion/bindings/javahl: native/ native/jniwrapper/ src/org/apache/subversion/javahl/ src/org/apache/subversion/javahl/util/ tests/org/apache/subversion/javahl/

Author: brane
Date: Tue Jun 17 22:51:05 2014
New Revision: 1603306

URL: http://svn.apache.org/r1603306
Log:
Add credentials management (searching and deleting) to JavaHL.

[in subversion/bindings/javahl]
* src/org/apache/subversion/javahl/SVNUtil.java
  (SVNUtil.CredentialTypeMismatch): New exception class.
  (SVNUtil.Credential): Make concrete and serializable, and
   encapsulate all credential kinds within this one class.
  (SVNUtil.UsernameCredential,
   SVNUtil.SimpleCredential,
   SVNUtil.SSLServerCertCredential,
   SVNUtil.SSLClientCertPassphraseCredential): Removed.
  (SVNUtil.getCredential, SVNUtil.removeCredential, SVNUtil.searchCredentials):
   Also throw SubversionException.
  (SVNUtil.addCredential): Removed; not viable, there is no native API.
  (SVNUtil.deleteCredentials): Removed as redundant.
* src/org/apache/subversion/javahl/util/ConfigLib.java:
   Import SubversionException class.
  (SVNUtil.getCredential, SVNUtil.nativeGetCredential,
   SVNUtil.removeCredential, SVNUtil.nativeRemoveCredential,
   SVNUtil.searchCredentials):
   Also throw SubversionException.
  (SVNUtil.addCredential, SVNUtil.nativeAddCredential): Removed.
  (SVNUtil.deleteCredentials): Removed as redundant.
  (SVNUtil.deleteCredentials): Removed.
  (SVNUtil.nativeSarchCredentials): New; replaces iterateCredentials.

* native/Credential.hpp, native/Credential.cpp:
   New; native implementation of the SVNUtil.Credential class.
* native/jniwrapper/jni_object.hpp, native/jniwrapper/jni_class_cache.cpp
  (ClassCache.get_credential, ClassCache.get_credential_kind)
   New; factory method for Credential and Credential::Kind implementations.
* native/org_apache_subversion_javahl_util_ConfigLib.cpp
  (build_credential, WalkCredentialsCallback, SimpleSearchCallback):
   New helper function and classes.
  (Java_org_apache_subversion_javahl_util_ConfigLib_nativeGetCredential,
   Java_org_apache_subversion_javahl_util_ConfigLib_nativeRemoveCredential,
   Java_org_apache_subversion_javahl_util_ConfigLib_nativeSearchCredentials):
   Implemented.
  (Java_org_apache_subversion_javahl_util_ConfigLib_nativeAddCredential):
   Removed.

* tests/org/apache/subversion/javahl/UtilTests.java
  (UtilTests.testCredentials): New test case.

Added:
    subversion/trunk/subversion/bindings/javahl/native/Credential.cpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/Credential.hpp   (with props)
Modified:
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java
    subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java

Added: subversion/trunk/subversion/bindings/javahl/native/Credential.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/Credential.cpp?rev=1603306&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/Credential.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/Credential.cpp Tue Jun 17 22:51:05 2014
@@ -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
+ */
+
+#include "Credential.hpp"
+
+#include "JNIUtil.h"
+
+namespace JavaHL {
+
+// Class JavaHL::Credential
+const char* const Credential::m_class_name =
+  JAVA_PACKAGE"/SVNUtil$Credential";
+
+Credential::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
+  : ::Java::Object::ClassImpl(env, cls),
+    m_mid_ctor(
+        env.GetMethodID(cls, "<init>",
+                        "(L"JAVA_PACKAGE"/SVNUtil$Credential$Kind;"
+                        "Ljava/lang/String;Ljava/lang/String;"
+                        "Ljava/lang/String;Ljava/lang/String;"
+                        "L"JAVA_PACKAGE"/callback/AuthnCallback$SSLServerCertInfo;"
+                        "L"JAVA_PACKAGE"/callback/AuthnCallback$SSLServerCertFailures;"
+                        "Ljava/lang/String;)V"))
+{}
+
+Credential::ClassImpl::~ClassImpl() {}
+
+Credential::Credential(::Java::Env env, jobject kind,
+                       const ::Java::String& realm,
+                       const ::Java::String& store,
+                       const ::Java::String& username,
+                       const ::Java::String& password,
+                       jobject info, jobject failures,
+                       const ::Java::String& passphrase)
+  : ::Java::Object(env, ::Java::ClassCache::get_credential())
+{
+  set_this(env.NewObject(get_class(), impl().m_mid_ctor,
+                         kind, realm.get(), store.get(),
+                         username.get(), password.get(),
+                         info, failures, passphrase.get()));
+}
+
+// Enum JavaHL::Credential::Kind
+const char* const Credential::Kind::m_class_name =
+  JAVA_PACKAGE"/SVNUtil$Credential$Kind";
+
+Credential::Kind::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
+  : ::Java::Object::ClassImpl(env, cls),
+    m_static_mid_from_string(
+        env.GetStaticMethodID(cls, "fromString",
+                              "(Ljava/lang/String;)"
+                              "L"JAVA_PACKAGE"/SVNUtil$Credential$Kind;"))
+{}
+
+Credential::Kind::ClassImpl::~ClassImpl() {}
+
+Credential::Kind::Kind(::Java::Env env,
+                       const ::Java::String& value)
+  : ::Java::Object(env, ::Java::ClassCache::get_credential_kind())
+{
+  set_this(env.CallStaticObjectMethod(
+               get_class(), impl().m_static_mid_from_string, value.get()));
+}
+
+} // namespace JavaHL

Propchange: subversion/trunk/subversion/bindings/javahl/native/Credential.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: subversion/trunk/subversion/bindings/javahl/native/Credential.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/Credential.hpp?rev=1603306&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/Credential.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/Credential.hpp Tue Jun 17 22:51:05 2014
@@ -0,0 +1,126 @@
+/**
+ * @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
+ */
+
+#ifndef SVN_JAVAHL_CREDENTIAL_HPP
+#define SVN_JAVAHL_CREDENTIAL_HPP
+
+#include "jniwrapper/jni_object.hpp"
+#include "jniwrapper/jni_string.hpp"
+
+#include "AuthnCallback.hpp"
+
+namespace JavaHL {
+
+/**
+ * Object wrapper for @c org.apache.subversion.javahl.SVNUtil.Credential.
+ *
+ * @since New in 1.9.
+ */
+class Credential : public ::Java::Object
+{
+public:
+  /**
+   * Object wrapper for @c ...Credential$Kind.
+   */
+  class Kind : public ::Java::Object
+  {
+  public:
+    /**
+     * Constructs a and wraps a new Credential$Kind object.
+     */
+    explicit Kind(::Java::Env env, const ::Java::String& value);
+
+  private:
+    /**
+     * This object's implementation details.
+     */
+    class ClassImpl : public Object::ClassImpl
+    {
+      friend class ::Java::ClassCacheImpl;
+
+    protected:
+      explicit ClassImpl(::Java::Env env, jclass cls);
+
+    public:
+      virtual ~ClassImpl();
+
+      const ::Java::MethodID m_static_mid_from_string;
+    };
+
+    const ClassImpl& impl() const
+      {
+        return *dynamic_cast<const ClassImpl*>(m_impl);
+      }
+
+    friend class ::Java::ClassCacheImpl;
+    static const char* const m_class_name;
+  };
+
+  /**
+   * Constructs a wrapper around @a jthis.
+   * The constructor does not verify the class of the wrapped object.
+   */
+  explicit Credential(::Java::Env env, jobject jthis)
+    : ::Java::Object(env, ::Java::ClassCache::get_credential(), jthis)
+    {}
+
+  /**
+   * Constructs and wraps a new Credential object
+   */
+  explicit Credential(::Java::Env env, jobject kind,
+                      const ::Java::String& realm,
+                      const ::Java::String& store,
+                      const ::Java::String& username,
+                      const ::Java::String& password,
+                      jobject info, jobject failures,
+                      const ::Java::String& passphrase);
+
+private:
+  /**
+   * This object's implementation details.
+   */
+  class ClassImpl : public Object::ClassImpl
+  {
+    friend class ::Java::ClassCacheImpl;
+
+  protected:
+    explicit ClassImpl(::Java::Env env, jclass cls);
+
+  public:
+    virtual ~ClassImpl();
+
+    const ::Java::MethodID m_mid_ctor;
+  };
+
+  const ClassImpl& impl() const
+    {
+      return *dynamic_cast<const ClassImpl*>(m_impl);
+    }
+
+  friend class ::Java::ClassCacheImpl;
+  static const char* const m_class_name;
+};
+
+} // namespace JavaHL
+
+#endif // SVN_JAVAHL_CREDENTIAL_HPP

Propchange: subversion/trunk/subversion/bindings/javahl/native/Credential.hpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp?rev=1603306&r1=1603305&r2=1603306&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp Tue Jun 17 22:51:05 2014
@@ -39,6 +39,7 @@
 
 #include "../SubversionException.hpp"
 #include "../AuthnCallback.hpp"
+#include "../Credential.hpp"
 #include "../ExternalItem.hpp"
 #include "../EditorCallbacks.hpp"
 
@@ -193,6 +194,11 @@ class ClassCacheImpl
   JNIWRAPPER_DEFINE_CACHED_CLASS(user_passwd_cb,
                                  ::JavaHL::UserPasswordCallback);
 
+  JNIWRAPPER_DEFINE_CACHED_CLASS(credential,
+                                 ::JavaHL::Credential);
+  JNIWRAPPER_DEFINE_CACHED_CLASS(credential_kind,
+                                 ::JavaHL::Credential::Kind);
+
   JNIWRAPPER_DEFINE_CACHED_CLASS(external_item,
                                  ::JavaHL::ExternalItem);
 
@@ -296,6 +302,10 @@ JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(aut
 JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(authn_ssl_server_cert_info);
 JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(user_passwd_cb);
 
+
+JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(credential);
+JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(credential_kind);
+
 JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(external_item);
 
 JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(editor_provide_base_cb);

Modified: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp?rev=1603306&r1=1603305&r2=1603306&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp Tue Jun 17 22:51:05 2014
@@ -193,6 +193,9 @@ public:
   JNIWRAPPER_DECLARE_CACHED_CLASS_ACCESSOR(authn_ssl_server_cert_info);
   JNIWRAPPER_DECLARE_CACHED_CLASS_ACCESSOR(user_passwd_cb);
 
+  JNIWRAPPER_DECLARE_CACHED_CLASS_ACCESSOR(credential);
+  JNIWRAPPER_DECLARE_CACHED_CLASS_ACCESSOR(credential_kind);
+
   JNIWRAPPER_DECLARE_CACHED_CLASS_ACCESSOR(external_item);
 
   JNIWRAPPER_DECLARE_CACHED_CLASS_ACCESSOR(editor_provide_base_cb);

Modified: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp?rev=1603306&r1=1603305&r2=1603306&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp Tue Jun 17 22:51:05 2014
@@ -26,15 +26,23 @@
 
 #include "../include/org_apache_subversion_javahl_util_ConfigLib.h"
 
+#include <apr_fnmatch.h>
+#include <apr_strings.h>
+
+#include "jniwrapper/jni_list.hpp"
 #include "jniwrapper/jni_stack.hpp"
 
 #include "AuthnCallback.hpp"
-#include "GlobalConfig.h"
+#include "Credential.hpp"
+#include "SubversionException.hpp"
 
+#include "GlobalConfig.h"
 #include "JNIUtil.h"
 #include "JNICriticalSection.h"
 
+#include "svn_auth.h"
 #include "svn_config.h"
+#include "svn_hash.h"
 
 #include "svn_private_config.h"
 
@@ -84,6 +92,178 @@ Java_org_apache_subversion_javahl_util_C
   return JNI_FALSE;
 }
 
+
+namespace {
+jobject build_credential(Java::Env env, apr_hash_t* cred,
+                         const char* cred_kind, const char* realm,
+                         apr_pool_t* scratch_pool)
+{
+  svn_string_t* entry = static_cast<svn_string_t*>(
+      svn_hash_gets(cred, SVN_CONFIG_REALMSTRING_KEY));
+  if (!entry || !realm || 0 != strcmp(realm, entry->data))
+    {
+      JavaHL::SubversionException(env).throw_java_exception(
+          apr_psprintf(scratch_pool,
+                       "Unexpected realm; got: [%s], expected: [%s]",
+                       (entry ? entry->data : "(null)"),
+                       (realm ? realm : "(null)")));
+    }
+
+  entry = static_cast<svn_string_t*>(
+      svn_hash_gets(cred, SVN_CONFIG_AUTHN_PASSTYPE_KEY));
+
+  const char* store = (entry ? entry->data : NULL);
+  const char* username = NULL;
+  const char* password = NULL;
+  jobject info = NULL;
+  jobject failures = NULL;
+  const char* passphrase = NULL;
+
+  if (0 == strcmp(cred_kind, SVN_AUTH_CRED_USERNAME))
+    {
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_USERNAME_KEY));
+      if (entry)
+        username = entry->data;
+    }
+  else if (0 == strcmp(cred_kind, SVN_AUTH_CRED_SIMPLE))
+    {
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_USERNAME_KEY));
+      if (entry)
+        username = entry->data;
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_PASSWORD_KEY));
+      if (entry)
+        password = entry->data;
+    }
+  else if (0 == strcmp(cred_kind, SVN_AUTH_CRED_SSL_SERVER_TRUST))
+    {
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_HOSTNAME_KEY));
+      const char* hostname = (entry ? entry->data : NULL);
+
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_FINGERPRINT_KEY));
+      const char* fingerprint = (entry ? entry->data : NULL);
+
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_VALID_FROM_KEY));
+      const char* valid_from = (entry ? entry->data : NULL);
+
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY));
+      const char* valid_until = (entry ? entry->data : NULL);
+
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_ISSUER_DN_KEY));
+      const char* issuer = (entry ? entry->data : NULL);
+
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_ASCII_CERT_KEY));
+      const char* der = (entry ? entry->data : NULL);
+
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_FAILURES_KEY));
+      jint failflags = (!entry ? 0 : jint(apr_atoi64(entry->data)));
+
+      info = JavaHL::AuthnCallback
+        ::SSLServerCertInfo(env,
+                            Java::String(env, hostname),
+                            Java::String(env, fingerprint),
+                            Java::String(env, valid_from),
+                            Java::String(env, valid_until),
+                            Java::String(env, issuer),
+                            Java::String(env, der)).get();
+      failures = JavaHL::AuthnCallback
+        ::SSLServerCertFailures(env, failflags).get();
+    }
+  else if (0 == strcmp(cred_kind, SVN_AUTH_CRED_SSL_CLIENT_CERT_PW))
+    {
+      entry = static_cast<svn_string_t*>(
+          svn_hash_gets(cred, SVN_CONFIG_AUTHN_PASSPHRASE_KEY));
+      if (entry)
+        passphrase = entry->data;
+    }
+  else
+    {
+      JavaHL::SubversionException(env).throw_java_exception(
+          apr_psprintf(scratch_pool,
+                       "Invalid credential type: [%s]",
+                       cred_kind));
+    }
+
+  return JavaHL::Credential(
+      env,
+      JavaHL::Credential::Kind(env, Java::String(env, cred_kind)).get(),
+      Java::String(env, realm), Java::String(env, store),
+      Java::String(env, username), Java::String(env, password),
+      info, failures, Java::String(env, passphrase)).get();
+}
+
+class WalkCredentialsCallback
+{
+public:
+  static svn_error_t* walk_func(svn_boolean_t *delete_cred,
+                                void *walk_baton,
+                                const char *cred_kind,
+                                const char *realmstring,
+                                apr_hash_t *cred,
+                                apr_pool_t *scratch_pool)
+    {
+      WalkCredentialsCallback& self =
+        *static_cast<WalkCredentialsCallback*>(walk_baton);
+      return self(delete_cred, cred_kind, realmstring, cred, scratch_pool);
+    }
+
+  virtual svn_error_t* operator()(svn_boolean_t *delete_cred,
+                                  const char *cred_kind,
+                                  const char *realmstring,
+                                  apr_hash_t *cred_hash,
+                                  apr_pool_t *scratch_pool) = 0;
+};
+
+class SimpleSearchCallback : public WalkCredentialsCallback
+{
+  const char* const m_cred_kind;
+  const char* const m_realm;
+  const bool m_delete_when_found;
+  apr_hash_t* m_cred;
+
+public:
+  explicit SimpleSearchCallback(const char* cred_kind, const char* realm,
+                                bool delete_when_found)
+    : m_cred_kind(cred_kind),
+      m_realm(realm),
+      m_delete_when_found(delete_when_found),
+      m_cred(NULL)
+    {}
+
+  const char* cred_kind() const { return m_cred_kind; }
+  const char* realm() const { return m_realm; }
+  apr_hash_t* cred() const { return m_cred; }
+
+  virtual svn_error_t* operator()(svn_boolean_t *delete_cred,
+                                  const char *cred_kind,
+                                  const char *realmstring,
+                                  apr_hash_t *cred_hash,
+                                  apr_pool_t *scratch_pool)
+    {
+      if (0 == strcmp(cred_kind, m_cred_kind)
+          && 0 == strcmp(realmstring, m_realm))
+        {
+          m_cred = cred_hash;
+          *delete_cred = m_delete_when_found;
+          return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, "");
+        }
+
+      *delete_cred = false;
+      return SVN_NO_ERROR;
+    }
+};
+} // anonymous namespace
+
+
 JNIEXPORT jobject JNICALL
 Java_org_apache_subversion_javahl_util_ConfigLib_nativeGetCredential(
     JNIEnv* jenv, jobject jthis,
@@ -95,6 +275,26 @@ Java_org_apache_subversion_javahl_util_C
         return NULL;
 
       const Java::Env env(jenv);
+      const Java::String config_dir(env, jconfig_dir);
+      const Java::String cred_kind(env, jcred_kind);
+      const Java::String realm(env, jrealm);
+
+      // Using a "global" request pool since we don't keep a context
+      // with its own pool around for these functions.
+      SVN::Pool pool;
+
+      SimpleSearchCallback cb(cred_kind.strdup(pool.getPool()),
+                              realm.strdup(pool.getPool()),
+                              false);
+
+      SVN_JAVAHL_CHECK(env,
+                       svn_config_walk_auth_data(
+                           Java::String::Contents(config_dir).c_str(),
+                           cb.walk_func, &cb, pool.getPool()));
+      if (!cb.cred())
+        return NULL;
+      return build_credential(env, cb.cred(), cb.cred_kind(), cb.realm(),
+                              pool.getPool());
     }
   SVN_JAVAHL_JNI_CATCH;
   return NULL;
@@ -111,41 +311,35 @@ Java_org_apache_subversion_javahl_util_C
         return NULL;
 
       const Java::Env env(jenv);
-    }
-  SVN_JAVAHL_JNI_CATCH;
-  return NULL;
-}
-
-JNIEXPORT jobject JNICALL
-Java_org_apache_subversion_javahl_util_ConfigLib_nativeAddCredential(
-    JNIEnv* jenv, jobject jthis,
-    jstring jconfig_dir, jstring jcred_kind, jstring jrealm,
-    jstring jusername, jstring jpassword,
-    jstring jserver_cert_hostname,
-    jstring jserver_cert_fingerprint,
-    jstring jserver_cert_valid_from,
-    jstring jserver_cert_valid_until,
-    jstring jserver_cert_issuer,
-    jstring jserver_cert_der,
-    jint jserver_cert_failures,
-    jstring jclient_cert_passphrase)
-{
-  SVN_JAVAHL_JNI_TRY(ConfigLib, nativeAddCredential)
-    {
-      if (!GlobalConfig::useNativeCredentialsStore())
+      const Java::String config_dir(env, jconfig_dir);
+      const Java::String cred_kind(env, jcred_kind);
+      const Java::String realm(env, jrealm);
+
+      // Using a "global" request pool since we don't keep a context
+      // with its own pool around for these functions.
+      SVN::Pool pool;
+
+      SimpleSearchCallback cb(cred_kind.strdup(pool.getPool()),
+                              realm.strdup(pool.getPool()),
+                              true);
+
+      SVN_JAVAHL_CHECK(env,
+                       svn_config_walk_auth_data(
+                           Java::String::Contents(config_dir).c_str(),
+                           cb.walk_func, &cb, pool.getPool()));
+      if (!cb.cred())
         return NULL;
 
-      const Java::Env env(jenv);
+      return build_credential(env, cb.cred(), cb.cred_kind(), cb.realm(),
+                              pool.getPool());
     }
   SVN_JAVAHL_JNI_CATCH;
   return NULL;
 }
 
-
 JNIEXPORT jobject JNICALL
-Java_org_apache_subversion_javahl_util_ConfigLib_iterateCredentials(
+Java_org_apache_subversion_javahl_util_ConfigLib_nativeSearchCredentials(
     JNIEnv* jenv, jobject jthis,
-    jboolean jdelete_matching,
     jstring jconfig_dir, jstring jcred_kind,
     jstring jrealm_pattern, jstring jusername_pattern,
     jstring jhostname_pattern, jstring jtext_pattern)
@@ -156,6 +350,142 @@ Java_org_apache_subversion_javahl_util_C
         return NULL;
 
       const Java::Env env(jenv);
+      const Java::String config_dir(env, jconfig_dir);
+      const Java::String cred_kind(env, jcred_kind);
+      const Java::String realm_pattern(env, jrealm_pattern);
+      const Java::String username_pattern(env, jusername_pattern);
+      const Java::String hostname_pattern(env, jhostname_pattern);
+      const Java::String text_pattern(env, jtext_pattern);
+
+      // Using a "global" request pool since we don't keep a context
+      // with its own pool around for these functions.
+      SVN::Pool pool;
+
+      class Callback : public WalkCredentialsCallback
+      {
+        const char* const m_cred_kind;
+        const char* const m_realm_pattern;
+        const char* const m_username_pattern;
+        const char* const m_hostname_pattern;
+        const char* const m_text_pattern;
+
+        const ::Java::Env m_env;
+        ::Java::MutableList<JavaHL::Credential> m_credentials;
+
+      public:
+        explicit Callback(::Java::Env ctor_env,
+                          const char* ctor_cred_kind,
+                          const char* ctor_realm_pattern,
+                          const char* ctor_username_pattern,
+                          const char* ctor_hostname_pattern,
+                          const char* ctor_text_pattern)
+          : m_cred_kind(ctor_cred_kind),
+            m_realm_pattern(ctor_realm_pattern),
+            m_username_pattern(ctor_username_pattern),
+            m_hostname_pattern(ctor_hostname_pattern),
+            m_text_pattern(ctor_text_pattern),
+            m_env(ctor_env),
+            m_credentials(ctor_env)
+          {}
+
+        jobject credentials() const
+          {
+            if (m_credentials.is_empty())
+              return NULL;
+            return m_credentials.get();
+          }
+
+        virtual svn_error_t* operator()(svn_boolean_t *delete_cred,
+                                        const char *cb_cred_kind,
+                                        const char *cb_realmstring,
+                                        apr_hash_t *cb_cred_hash,
+                                        apr_pool_t *cb_scratch_pool)
+          {
+            *delete_cred = false;
+            if (m_cred_kind && 0 != strcmp(cb_cred_kind, m_cred_kind))
+              return SVN_NO_ERROR;
+
+            svn_string_t* entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_USERNAME_KEY));
+            const char* const username = (entry ? entry->data : NULL);
+
+            entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_PASSTYPE_KEY));
+            const char* const store = (entry ? entry->data : NULL);
+
+            entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_HOSTNAME_KEY));
+            const char* const hostname = (entry ? entry->data : NULL);
+
+            entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_FINGERPRINT_KEY));
+            const char* const fingerprint = (entry ? entry->data : NULL);
+
+            entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_VALID_FROM_KEY));
+            const char* const valid_from = (entry ? entry->data : NULL);
+
+            entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY));
+            const char* const valid_until = (entry ? entry->data : NULL);
+
+            entry = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_ISSUER_DN_KEY));
+            const char* const issuer = (entry ? entry->data : NULL);
+
+            bool match = (m_realm_pattern
+                          && !apr_fnmatch(m_realm_pattern, cb_realmstring, 0));
+
+            if (!match && m_username_pattern)
+              match = (match
+                       || (username
+                           && !apr_fnmatch(m_username_pattern, username, 0)));
+
+            if (!match && m_hostname_pattern)
+              match = (match
+                       || (hostname
+                           && !apr_fnmatch(m_hostname_pattern, hostname, 0)));
+
+            if (!match && m_text_pattern)
+              match = (match
+                       || (username
+                           && !apr_fnmatch(m_text_pattern, username, 0))
+                       || (store
+                           && !apr_fnmatch(m_text_pattern, store, 0))
+                       || (hostname
+                           && !apr_fnmatch(m_text_pattern, hostname, 0))
+                       || (fingerprint
+                           && !apr_fnmatch(m_text_pattern, fingerprint, 0))
+                       || (valid_from
+                           && !apr_fnmatch(m_text_pattern, valid_from, 0))
+                       || (valid_until
+                           && !apr_fnmatch(m_text_pattern, valid_until, 0))
+                       || (issuer
+                           && !apr_fnmatch(m_text_pattern, issuer, 0)));
+
+            if (match)
+              m_credentials.add(
+                  ::JavaHL::Credential(m_env,
+                                       build_credential(m_env,
+                                                        cb_cred_hash,
+                                                        cb_cred_kind,
+                                                        cb_realmstring,
+                                                        cb_scratch_pool)));
+
+            return SVN_NO_ERROR;
+          }
+      } cb(env,
+           cred_kind.strdup(pool.getPool()),
+           realm_pattern.strdup(pool.getPool()),
+           username_pattern.strdup(pool.getPool()),
+           hostname_pattern.strdup(pool.getPool()),
+           text_pattern.strdup(pool.getPool()));
+
+      SVN_JAVAHL_CHECK(env,
+                       svn_config_walk_auth_data(
+                           Java::String::Contents(config_dir).c_str(),
+                           cb.walk_func, &cb, pool.getPool()));
+      return cb.credentials();
     }
   SVN_JAVAHL_JNI_CATCH;
   return NULL;

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java?rev=1603306&r1=1603305&r2=1603306&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java Tue Jun 17 22:51:05 2014
@@ -96,11 +96,34 @@ public class SVNUtil
     //
 
     /**
+     * Exception used by calling the wrong accessor on Credential for
+     * the given credential type.
+     */
+    public static class CredentialTypeMismatch extends SubversionException
+    {
+        // Update the serialVersionUID when there is a incompatible change made to
+        // this class.  See the java documentation for when a change is incompatible.
+        // http://java.sun.com/javase/7/docs/platform/serialization/spec/version.html#6678
+        private static final long serialVersionUID = 1L;
+
+        public CredentialTypeMismatch(Credential.Kind kind, String attribute)
+        {
+            super("Credential type '" + kind.toString()
+                  + "'  does not have the attribute '" + attribute + "'");
+        }
+    }
+
+    /**
      * Generic credential description. Provides default accessors for
      * concrete implementations.
      */
-    public static abstract class Credential
+    public static class Credential implements java.io.Serializable
     {
+        // Update the serialVersionUID when there is a incompatible change made to
+        // this class.  See the java documentation for when a change is incompatible.
+        // http://java.sun.com/javase/7/docs/platform/serialization/spec/version.html#6678
+        private static final long serialVersionUID = 1L;
+
         /**
          * Describes the kind of the credential.
          */
@@ -130,6 +153,16 @@ public class SVNUtil
             {
                 return this.token;
             }
+
+            /* Factory used by the native implementation */
+            private static Kind fromString(String stringrep)
+            {
+                for (Kind kind : Kind.values()) {
+                    if (kind.toString().equals(stringrep))
+                        return kind;
+                }
+                return null;
+            }
         }
 
         /** @return the kind of the credential. */
@@ -150,7 +183,11 @@ public class SVNUtil
          * credential does not contain any secrets bits.
          */
         public String getSecureStore()
+            throws CredentialTypeMismatch
         {
+            if (kind != Kind.simple && kind != Kind.sslClientPassphrase)
+                throw new CredentialTypeMismatch(kind, "secure store");
+
             return store;
         }
 
@@ -160,8 +197,12 @@ public class SVNUtil
          * credential type.
          */
         public String getUsername()
+            throws CredentialTypeMismatch
         {
-            return null;
+            if (kind != Kind.username && kind != Kind.simple)
+                throw new CredentialTypeMismatch(kind, "username");
+
+            return username;
         }
 
         /**
@@ -170,8 +211,12 @@ public class SVNUtil
          * credential type.
          */
         public String getPassword()
+            throws CredentialTypeMismatch
         {
-            return null;
+            if (kind != Kind.simple && kind != Kind.sslClientPassphrase)
+                throw new CredentialTypeMismatch(kind, "password");
+
+            return password;
         }
 
         /**
@@ -180,8 +225,12 @@ public class SVNUtil
          * certificate in the concrete credential type.
          */
         public AuthnCallback.SSLServerCertInfo getServerCertInfo()
+            throws CredentialTypeMismatch
         {
-            return null;
+            if (kind != Kind.sslServer)
+                throw new CredentialTypeMismatch(kind, "server cert info");
+
+            return info;
         }
 
         /**
@@ -190,8 +239,12 @@ public class SVNUtil
          * server certificate in the concrete credential type.
          */
         public AuthnCallback.SSLServerCertFailures getServerCertFailures()
+            throws CredentialTypeMismatch
         {
-            return null;
+            if (kind != Kind.sslServer)
+                throw new CredentialTypeMismatch(kind, "server cert failures");
+
+            return failures;
         }
 
         /**
@@ -200,166 +253,119 @@ public class SVNUtil
          * certificate in the concrete credential type.
          */
         public String getClientCertPassphrase()
+            throws CredentialTypeMismatch
         {
-            return null;
+            if (kind != Kind.sslClientPassphrase)
+                throw new CredentialTypeMismatch(kind, "passphrase");
+
+            return passphrase;
         }
 
-        /** Protected constructor used by subclasses. */
-        protected Credential(Kind kind, String realm, String store)
-        {
+        // ### TODO: There are currently no proper APIs in Subversion
+        //           for adding credentials. These factory methods are
+        //           placeholders.
+        //
+        ///**
+        // * Creates an "svn.username" credential.
+        // * @param realm The realm string.
+        // * @param username The username for <code>realm</code>.
+        // */
+        //public static Credential
+        //    createUsername(String realm, String username)
+        //{
+        //    return new Credential(Kind.username, realm, null,
+        //                          username, null, null, null, null);
+        //}
+        //
+        ///**
+        // * Creates an "svn.simple" credential.
+        // * @param realm The realm string.
+        // * @param username The username for <code>realm</code>.
+        // * @param password The password for <code>username</code>.
+        // */
+        //public static Credential
+        //    createSimple(String realm, String username, String password)
+        //{
+        //    return new Credential(Kind.simple, realm, null,
+        //                          username, password, null, null, null);
+        //}
+        //
+        ///** Creates an "svn.ssl.server" credential. */
+        //public static Credential
+        //    createSSLServerCertTrust(String realm,
+        //                             AuthnCallback.SSLServerCertInfo info,
+        //                             AuthnCallback.SSLServerCertFailures failures)
+        //{
+        //    return new Credential(Kind.sslServer, realm, null,
+        //                          null, null, info, failures, null);
+        //}
+        //
+        ///**
+        // * Creates an "svn.ssl.client-passphrase" credential.
+        // * @param realm The realm string.
+        // * @param passphrase The passphrase for for the client certificate
+        // *        used for <code>realm</code>.
+        // */
+        //public static Credential
+        //    createSSLClientCertPassphrase(String realm, String passphrase)
+        //{
+        //    return new Credential(Kind.simple, realm, null,
+        //                          null, null, null, null, passphrase);
+        //}
+
+        private Credential(Kind kind, String realm, String store,
+                           String username, String password,
+                           AuthnCallback.SSLServerCertInfo info,
+                           AuthnCallback.SSLServerCertFailures failures,
+                           String passphrase)
+        {
+            assert(kind != null && realm != null);
+            switch (kind) {
+            case username:
+                assert(username != null && password == null
+                       && info == null && failures == null
+                       && passphrase == null);
+                break;
+            case simple:
+                assert(username != null && password != null
+                       && info == null && failures == null
+                       && passphrase == null);
+                break;
+            case sslServer:
+                assert(username == null && password == null
+                       && info != null && failures != null
+                       && passphrase == null);
+                break;
+            case sslClientPassphrase:
+                assert(username == null && password == null
+                       && info == null && failures == null
+                       && passphrase != null);
+                break;
+            default:
+                assert(kind == Kind.username
+                       || kind == Kind.simple
+                       || kind == Kind.sslServer
+                       || kind == Kind.sslClientPassphrase);
+            }
+
             this.kind = kind;
             this.realm = realm;
             this.store = store;
-        }
-
-        protected Kind kind;
-        protected String realm;
-        protected String store;
-    }
-
-    /**
-     * A credential that defines a username.
-     */
-    public static class UsernameCredential extends Credential
-    {
-        /** Constructs a username credential. */
-        public UsernameCredential(String realm, String username)
-        {
-            super(Kind.username, realm, null);
-            this.username = username;
-        }
-
-        /** @return the username associated with the credential. */
-        public String getUsername()
-        {
-            return username;
-        }
-
-        /** Protected constructor used by subclasses. */
-        protected UsernameCredential(Kind kind, String realm, String store,
-                                     String username)
-        {
-            super(kind, realm, null);
-            this.username = username;
-        }
-
-        /** Protected constructor used by the native implementation. */
-        protected UsernameCredential(String realm, String store,
-                                     String username)
-        {
-            super(Kind.username, realm, store);
             this.username = username;
-        }
-
-        protected String username;
-    }
-
-    /**
-     * A credential that defines a username and password.
-     */
-    public static class SimpleCredential extends UsernameCredential
-    {
-        /** Constructs a simple credential. */
-        public SimpleCredential(String realm, String username, String password)
-        {
-            super(Kind.simple, realm, null, username);
             this.password = password;
-        }
-
-        /** @return the password associated with the credential. */
-        public String getPassword()
-        {
-            return password;
-        }
-
-        /** Protected constructor used by the native implementation. */
-        protected SimpleCredential(String realm, String store,
-                                   String username, String password)
-        {
-            super(Kind.simple, realm, store, username);
-            this.password = password;
-        }
-
-        protected String password;
-    }
-
-    /**
-     * A credential that defines a trusted SSL server certificate.
-     */
-    public static class SSLServerCertCredential extends Credential
-    {
-        /** Constructs an SSL server certificate credential. */
-        public SSLServerCertCredential(String realm,
-                                       AuthnCallback.SSLServerCertInfo info,
-                                       AuthnCallback.SSLServerCertFailures failures)
-        {
-            super(Kind.sslServer, realm, null);
             this.info = info;
             this.failures = failures;
-        }
-
-        /**
-         * @return the server certificate info associated with the
-         * credential.
-         */
-        public AuthnCallback.SSLServerCertInfo getServerCertInfo()
-        {
-            return info;
-        }
-
-        /**
-         * @return the accepted server certificate failures associated
-         * with the credential.
-         */
-        public AuthnCallback.SSLServerCertFailures getServerCertFailures()
-        {
-            return failures;
-        }
-
-        /** Protected constructor used by the native implementation. */
-        protected SSLServerCertCredential(String realm, String store,
-                                          AuthnCallback.SSLServerCertInfo info,
-                                          AuthnCallback.SSLServerCertFailures failures)
-        {
-            super(Kind.sslServer, realm, store);
-            this.info = info;
-            this.failures = failures;
-        }
-
-        protected AuthnCallback.SSLServerCertInfo info;
-        protected AuthnCallback.SSLServerCertFailures failures;
-    }
-
-    /**
-     * A credential that defines an SSL client certificate passphrase.
-     */
-    public static class SSLClientCertPassphraseCredential extends Credential
-    {
-        /** Constructs an SSL client certificate passphrase credential. */
-        public SSLClientCertPassphraseCredential(String realm, String passprase)
-        {
-            super(Kind.sslClientPassphrase, realm, null);
             this.passphrase = passphrase;
         }
 
-        /**
-         * @return the client certificate passphrase associated with
-         * the credential.
-         */
-        public String getClientCertPassphrase()
-        {
-            return passphrase;
-        }
-
-        /** Protected constructor used by the native implementation. */
-        protected SSLClientCertPassphraseCredential(String realm, String store,
-                                                    String passprase)
-        {
-            super(Kind.sslClientPassphrase, realm, store);
-            this.passphrase = passphrase;
-        }
-
-        protected String passphrase;
+        private Kind kind;
+        private String realm;
+        private String store;
+        private String username;
+        private String password;
+        private AuthnCallback.SSLServerCertInfo info;
+        private AuthnCallback.SSLServerCertFailures failures;
+        private String passphrase;
     }
 
     /**
@@ -380,7 +386,7 @@ public class SVNUtil
     public static Credential getCredential(String configDir,
                                            Credential.Kind kind,
                                            String realm)
-        throws ClientException
+        throws ClientException, SubversionException
     {
         return configLib.getCredential(configDir, kind, realm);
     }
@@ -403,39 +409,42 @@ public class SVNUtil
     public static Credential removeCredential(String configDir,
                                               Credential.Kind kind,
                                               String realm)
-        throws ClientException
+        throws ClientException, SubversionException
     {
         return configLib.removeCredential(configDir, kind, realm);
     }
 
-    /**
-     * Store a new credential, or replace an existing credential.
-     * <p>
-     * <b>Note:</b> If the native credentials store is disabled, this
-     *              method will always return <code>null</code>.
-     *
-     * @param configDir The path to the configuration directory; if
-     *        <code>null</code>, the default (system-specific) user
-     *        configuration path will be used.
-     * @param credential The credential to store.
-     * @param replace If <code>true</code>, any existing matching
-     *        credential will be replaced.
-     *
-     * @return the stored credential. If <code>replace</code> was
-     * <code>false</code>, and a credential with the same kind and
-     * for the same realm exists, it will be returned. If the given
-     * credential was successfully added, the same object reference
-     * will be returned (the calling code can compare reference values
-     * to determine this). Will return <code>null</code> if the
-     * credential could not be stored for any reason.
-     */
-    public static Credential addCredential(String configDir,
-                                           Credential credential,
-                                           boolean replace)
-        throws ClientException
-    {
-        return configLib.addCredential(configDir, credential, replace);
-    }
+    // ### TODO: There are currently no proper APIs in Subversion for
+    //           adding credentials. This method is a placeholder.
+    //
+    ///**
+    // * Store a new credential, or replace an existing credential.
+    // * <p>
+    // * <b>Note:</b> If the native credentials store is disabled, this
+    // *              method will always return <code>null</code>.
+    // *
+    // * @param configDir The path to the configuration directory; if
+    // *        <code>null</code>, the default (system-specific) user
+    // *        configuration path will be used.
+    // * @param credential The credential to store.
+    // * @param replace If <code>true</code>, any existing matching
+    // *        credential will be replaced.
+    // *
+    // * @return the stored credential. If <code>replace</code> was
+    // * <code>false</code>, and a credential with the same kind and
+    // * for the same realm exists, it will be returned. If the given
+    // * credential was successfully added, the same object reference
+    // * will be returned (the calling code can compare reference values
+    // * to determine this). Will return <code>null</code> if the
+    // * credential could not be stored for any reason.
+    // */
+    //public static Credential addCredential(String configDir,
+    //                                       Credential credential,
+    //                                       boolean replace)
+    //    throws ClientException, SubversionException
+    //{
+    //    return configLib.addCredential(configDir, credential, replace);
+    //}
 
     /**
      * Find stored credentials that match the given search criteria.
@@ -475,37 +484,13 @@ public class SVNUtil
                           String usernamePattern,
                           String hostnamePattern,
                           String textPattern)
-        throws ClientException
+        throws ClientException, SubversionException
     {
         return configLib.searchCredentials(configDir, kind, realmPattern,
                                            usernamePattern, hostnamePattern,
                                            textPattern);
     }
 
-    /**
-     * Delete stored credentials that match the given search criteria.
-     * The parameters of this method are the same as for
-     * {@link #searchCredentials}.
-     * <p>
-     * <b>Note:</b> If the native credentials store is disabled, this
-     *              method will always return <code>null</code>.
-     *
-     * @return the list of deleted credentials.
-     */
-    public static List<Credential>
-        deleteCredentials(String configDir,
-                          Credential.Kind kind,
-                          String realmPattern,
-                          String usernamePattern,
-                          String hostnamePattern,
-                          String textPattern)
-        throws ClientException
-    {
-        return configLib.deleteCredentials(configDir, kind, realmPattern,
-                                           usernamePattern, hostnamePattern,
-                                           textPattern);
-    }
-
     //
     // Diff and Merge
     //

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java?rev=1603306&r1=1603305&r2=1603306&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java Tue Jun 17 22:51:05 2014
@@ -28,6 +28,7 @@ import org.apache.subversion.javahl.call
 import org.apache.subversion.javahl.SVNUtil;
 import org.apache.subversion.javahl.ClientException;
 import org.apache.subversion.javahl.NativeResources;
+import org.apache.subversion.javahl.SubversionException;
 
 import java.util.List;
 
@@ -66,7 +67,7 @@ public class ConfigLib
     public SVNUtil.Credential getCredential(String configDir,
                                             SVNUtil.Credential.Kind kind,
                                             String realm)
-        throws ClientException
+        throws ClientException, SubversionException
     {
         return nativeGetCredential(configDir, kind.toString(), realm);
     }
@@ -75,33 +76,52 @@ public class ConfigLib
     public SVNUtil.Credential removeCredential(String configDir,
                                                SVNUtil.Credential.Kind kind,
                                                String realm)
-        throws ClientException
+        throws ClientException, SubversionException
     {
         return nativeRemoveCredential(configDir, kind.toString(), realm);
     }
 
-    /** @see SVNUtil.addCredential */
-    public SVNUtil.Credential addCredential(String configDir,
-                                            SVNUtil.Credential credential,
-                                            boolean replace)
-        throws ClientException
-    {
-        final AuthnCallback.SSLServerCertInfo sci = credential.getServerCertInfo();
-        final AuthnCallback.SSLServerCertFailures scf = credential.getServerCertFailures();
-        return nativeAddCredential(configDir,
-                                   credential.getKind().toString(),
-                                   credential.getRealm(),
-                                   credential.getUsername(),
-                                   credential.getPassword(),
-                                   (sci != null ? sci.getHostname() : null),
-                                   (sci != null ? sci.getFingerprint() : null),
-                                   (sci != null ? sci.getValidFrom() : null),
-                                   (sci != null ? sci.getValidUntil() : null),
-                                   (sci != null ? sci.getIssuer() : null),
-                                   (sci != null ? sci.getDER() : null),
-                                   (scf != null ? scf.getFailures() : 0),
-                                   credential.getClientCertPassphrase());
-    }
+    ///** @see SVNUtil.addCredential */
+    //public SVNUtil.Credential addCredential(String configDir,
+    //                                        SVNUtil.Credential credential,
+    //                                        boolean replace)
+    //    throws ClientException, SubversionException
+    //{
+    //    final SVNUtil.Credential.Kind kind = credential.getKind();
+    //
+    //    final String username =
+    //        ((kind == SVNUtil.Credential.Kind.username
+    //          || kind == SVNUtil.Credential.Kind.simple)
+    //         ? credential.getUsername() : null);
+    //
+    //    final String password =
+    //        (kind == SVNUtil.Credential.Kind.simple
+    //         ? credential.getPassword() : null);
+    //
+    //    final AuthnCallback.SSLServerCertInfo sci =
+    //        (kind == SVNUtil.Credential.Kind.sslServer
+    //         ? credential.getServerCertInfo() : null);
+    //
+    //    final AuthnCallback.SSLServerCertFailures scf =
+    //        (kind == SVNUtil.Credential.Kind.sslServer
+    //         ? credential.getServerCertFailures() : null);
+    //
+    //    final String passphrase =
+    //        (kind == SVNUtil.Credential.Kind.sslClientPassphrase
+    //         ? credential.getClientCertPassphrase() : null);
+    //
+    //    return nativeAddCredential(configDir, kind.toString(),
+    //                               credential.getRealm(),
+    //                               username, password,
+    //                               (sci != null ? sci.getHostname() : null),
+    //                               (sci != null ? sci.getFingerprint() : null),
+    //                               (sci != null ? sci.getValidFrom() : null),
+    //                               (sci != null ? sci.getValidUntil() : null),
+    //                               (sci != null ? sci.getIssuer() : null),
+    //                               (sci != null ? sci.getDER() : null),
+    //                               (scf != null ? scf.getFailures() : 0),
+    //                               passphrase);
+    //}
 
     /** @see SVNUtil.searchCredentials */
     public List<SVNUtil.Credential>
@@ -111,64 +131,49 @@ public class ConfigLib
                           String usernamePattern,
                           String hostnamePattern,
                           String textPattern)
-        throws ClientException
-    {
-        return iterateCredentials(
-            false, configDir, kind.toString(), realmPattern,
-            usernamePattern, hostnamePattern, textPattern);
-    }
-
-    /** @see SVNUtil.deleteCredentials */
-    public List<SVNUtil.Credential>
-        deleteCredentials(String configDir,
-                          SVNUtil.Credential.Kind kind,
-                          String realmPattern,
-                          String usernamePattern,
-                          String hostnamePattern,
-                          String textPattern)
-        throws ClientException
+        throws ClientException, SubversionException
     {
-        return iterateCredentials(
-            true, configDir, kind.toString(), realmPattern,
-            usernamePattern, hostnamePattern, textPattern);
+        return nativeSearchCredentials(
+            configDir,
+            (kind != null ? kind.toString() : null),
+            realmPattern, usernamePattern, hostnamePattern, textPattern);
     }
 
     private native SVNUtil.Credential
         nativeGetCredential(String configDir,
                                String kind,
                                String realm)
-        throws ClientException;
+        throws ClientException, SubversionException;
 
     private native SVNUtil.Credential
         nativeRemoveCredential(String configDir,
                                String kind,
                                String realm)
-        throws ClientException;
+        throws ClientException, SubversionException;
 
-    private native SVNUtil.Credential
-        nativeAddCredential(String configDir,
-                            String kind,
-                            String realm,
-                            String username,
-                            String password,
-                            String serverCertHostname,
-                            String serverCertFingerprint,
-                            String serverCertValidFrom,
-                            String serverCertValidUntil,
-                            String serverCertIssuer,
-                            String serverCertDER,
-                            int serverCertFailures,
-                            String clientCertPassphrase)
-        throws ClientException;
+    //private native SVNUtil.Credential
+    //    nativeAddCredential(String configDir,
+    //                        String kind,
+    //                        String realm,
+    //                        String username,
+    //                        String password,
+    //                        String serverCertHostname,
+    //                        String serverCertFingerprint,
+    //                        String serverCertValidFrom,
+    //                        String serverCertValidUntil,
+    //                        String serverCertIssuer,
+    //                        String serverCertDER,
+    //                        int serverCertFailures,
+    //                        String clientCertPassphrase)
+    //    throws ClientException, SubversionException;
 
     private native List<SVNUtil.Credential>
-        iterateCredentials(boolean deleteMatching,
-                           String configDir,
-                           String kind,
-                           String realmPattern,
-                           String usernamePattern,
-                           String hostnamePattern,
-                           String textPattern)
-        throws ClientException;
+        nativeSearchCredentials(String configDir,
+                                String kind,
+                                String realmPattern,
+                                String usernamePattern,
+                                String hostnamePattern,
+                                String textPattern)
+        throws ClientException, SubversionException;
 }
 

Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java?rev=1603306&r1=1603305&r2=1603306&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java Tue Jun 17 22:51:05 2014
@@ -30,6 +30,7 @@ import org.apache.subversion.javahl.type
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.FileWriter;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -587,4 +588,186 @@ public class UtilTests extends SVNTests
             }
         }
     }
+
+
+    // Credentials definitions for testing the credentials utilities
+    private static final String util_cred_hash =
+        "4d7de6b1e103fbfc5e61565223ca23be";
+
+    private static final String util_cred_username =
+        "K 8\n" +
+        "username\n" +
+        "V 5\n" +
+        "mungo\n" +
+        "K 15\n" +
+        "svn:realmstring\n" +
+        "V 27\n" +
+        "https://svn.example.com:443\n" +
+        "END\n";
+
+    private static final String util_cred_simple =
+        "K 8\n" +
+        "passtype\n" +
+        "V 10\n" +
+        "javahltest\n" +
+        "K 8\n" +
+        "username\n" +
+        "V 5\n" +
+        "mungo\n" +
+        "K 8\n" +
+        "password\n" +
+        "V 6\n" +
+        "secret\n" +
+        "K 15\n" +
+        "svn:realmstring\n" +
+        "V 27\n" +
+        "https://svn.example.com:443\n" +
+        "END\n";
+
+    private static final String util_cred_ssl_server =
+        "K 10\n" +
+        "ascii_cert\n" +
+        "V 12\n" +
+        "NotTelling==\n" +
+        "K 8\n" +
+        "failures\n" +
+        "V 1\n" +
+        "8\n" +
+        "K 15\n" +
+        "svn:realmstring\n" +
+        "V 27\n" +
+        "https://svn.example.com:443\n" +
+        "END\n";
+
+    private static final String util_cred_ssl_client_passphrase =
+        "K 8\n" +
+        "passtype\n" +
+        "V 10\n" +
+        "javahltest\n" +
+        "K 10\n" +
+        "passphrase\n" +
+        "V 24\n" +
+        "secret with spaces in it\n" +
+        "K 15\n" +
+        "svn:realmstring\n" +
+        "V 27\n" +
+        "https://svn.example.com:443\n" +
+        "END\n";
+
+    // Initialize credentials used for testing credentials utilities
+    private void initCredentials() throws Throwable
+    {
+        File auth = new File(this.conf, "auth");
+        if (auth.exists())
+            removeDirOrFile(auth);
+        auth.mkdirs();
+
+        File store = new File(auth, "svn.username");
+        store.mkdir();
+        FileWriter cred = new FileWriter(new File(store, util_cred_hash));
+        cred.write(util_cred_username);
+        cred.close();
+
+        store = new File(auth, "svn.simple");
+        store.mkdir();
+        cred = new FileWriter(new File(store, util_cred_hash));
+        cred.write(util_cred_simple);
+        cred.close();
+
+        store = new File(auth, "svn.ssl.server");
+        store.mkdir();
+        cred = new FileWriter(new File(store, util_cred_hash));
+        cred.write(util_cred_ssl_server);
+        cred.close();
+
+        store = new File(auth, "svn.ssl.client-passphrase");
+        store.mkdir();
+        cred = new FileWriter(new File(store, util_cred_hash));
+        cred.write(util_cred_ssl_client_passphrase);
+        cred.close();
+    }
+
+    /**
+     * Test credentials search.
+     */
+    public void testCredentials() throws Throwable
+    {
+        initCredentials();
+
+        final String configDir = this.conf.getAbsolutePath();
+        SVNUtil.Credential cred;
+        List<SVNUtil.Credential> creds;
+
+        /* one username credential */
+        cred = SVNUtil.getCredential(configDir,
+                                     SVNUtil.Credential.Kind.username,
+                                     "https://svn.example.com:443");
+        assertNotNull(cred);
+        assertEquals(cred.getUsername(), "mungo");
+
+        /* one simple credential */
+        cred = SVNUtil.getCredential(configDir,
+                                     SVNUtil.Credential.Kind.simple,
+                                     "https://svn.example.com:443");
+        assertNotNull(cred);
+        assertEquals(cred.getUsername(), "mungo");
+        assertEquals(cred.getPassword(), "secret");
+        assertEquals(cred.getSecureStore(), "javahltest");
+
+        /* one SSL server trust credential */
+        cred = SVNUtil.getCredential(configDir,
+                                     SVNUtil.Credential.Kind.sslServer,
+                                     "https://svn.example.com:443");
+        assertNotNull(cred);
+        assertEquals(cred.getServerCertInfo().getDER(), "NotTelling==");
+
+        /* one SSL client passphrase credential */
+        cred = SVNUtil.getCredential(configDir,
+                                     SVNUtil.Credential.Kind.sslClientPassphrase,
+                                     "https://svn.example.com:443");
+        assertNotNull(cred);
+        assertEquals(cred.getClientCertPassphrase(), "secret with spaces in it");
+        assertEquals(cred.getSecureStore(), "javahltest");
+
+        /* search with no parameters (empty return) */
+        creds = SVNUtil.searchCredentials(configDir, null,
+                                          null, null, null, null);
+        assertNull(creds);
+
+        /* search with unmatched parameters */
+        creds = SVNUtil.searchCredentials(configDir,
+                                          SVNUtil.Credential.Kind.sslServer,
+                                          null, null, null, "*java*");
+        assertNull(creds);
+
+        /* search with unmatched parameters */
+        creds = SVNUtil.searchCredentials(configDir, null,
+                                          null, "*java*", null, null);
+        assertNull(creds);
+
+        /* search with match on kind */
+        creds = SVNUtil.searchCredentials(configDir,
+                                          SVNUtil.Credential.Kind.sslServer,
+                                          "*", null, null, null);
+        assertNotNull(creds);
+        assertEquals(creds.size(), 1);
+
+        /* search with match on passtype */
+        creds = SVNUtil.searchCredentials(configDir, null,
+                                          null, null, null, "*java*");
+        assertNotNull(creds);
+        assertEquals(creds.size(), 2);
+
+        /* search with match on username */
+        creds = SVNUtil.searchCredentials(configDir, null,
+                                          null, "mungo", null, null);
+        assertNotNull(creds);
+        assertEquals(creds.size(), 2);
+
+        /* search with match on realm */
+        creds = SVNUtil.searchCredentials(configDir, null,
+                                          "*example*", null, null, null);
+        assertNotNull(creds);
+        assertEquals(creds.size(), 4);
+    }
 }