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

svn commit: r1451810 - in /subversion/trunk: ./ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ subversion/bindings/javahl/tests/org/apac...

Author: brane
Date: Sat Mar  2 01:24:45 2013
New Revision: 1451810

URL: http://svn.apache.org/r1451810
Log:
Working on isue #4326 (update javahl with new 1.8 APIs).

Implement the svn_version_extended interface in JavaHL.

* build.conf: Declare new JavaHL generated headers.

[in subversion/bindings/javahl/native]
* VersionExtended.h: New; declares native wrapper for svn_version_extended_t.
* VersionExtended.cpp: Out-of-line implementation of VersionExtended.h
* org_apache_subversion_javahl_types_VersionExtended.cpp:
   Implementations of native methods declared in VersionExtended.java.

* SVNClient.h (SVNCliend::getVersionExtended): New method.
* SVNClient.cpp: Inclide VersionExtended.h.
  (SVNCliend::getVersionExtended): Implement.
* org_apache_subversion_javahl_SVNClient.cpp
  (Java_org_apache_subversion_javahl_SVNClient_getVersionExtended):
   Implementation of JNI method SVNClient.getVersionExteded.

[in subversion/bindings/javahl/src/org/apache/subversion/javahl]
* ISVNClient.java (SVNCliend.getVersionExtended): New interface method.
* SVNClient.java (SVNCliend.getVersionExtended): New native method.
* types/VersionExtended.java: New; Java wrapper for svn_version_extended_t.

[in subversion/bindings/javahl/tests/org/apache/subversion/javahl]
* BasicTests.java
  (BasicTests.testVersionExtendedQuiet,
   BasicTests.testVersionExtendedVerbose): New test cases.

Added:
    subversion/trunk/subversion/bindings/javahl/native/VersionExtended.cpp
    subversion/trunk/subversion/bindings/javahl/native/VersionExtended.h
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_types_VersionExtended.cpp
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java
Modified:
    subversion/trunk/build.conf
    subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp
    subversion/trunk/subversion/bindings/javahl/native/SVNClient.h
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
    subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java

Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1451810&r1=1451809&r2=1451810&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Sat Mar  2 01:24:45 2013
@@ -57,6 +57,11 @@ private-built-includes =
         subversion/bindings/javahl/include/org_apache_subversion_javahl_SVNRepos.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_SVNClient.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_types_Version.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_types_VersionExtended.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_types_VersionExtended_LinkedLib.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_types_VersionExtended_LinkedLibIterator.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_types_VersionExtended_LoadedLib.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_types_VersionExtended_LoadedLibIterator.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_types_Revision.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_UserPasswordCallback.h
         subversion/svn/svn-help.inc

Modified: subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp?rev=1451810&r1=1451809&r2=1451810&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp Sat Mar  2 01:24:45 2013
@@ -35,6 +35,7 @@
 #include "Revision.h"
 #include "OutputStream.h"
 #include "RevisionRange.h"
+#include "VersionExtended.h"
 #include "BlameCallback.h"
 #include "ProplistCallback.h"
 #include "LogMessageCallback.h"
@@ -93,6 +94,41 @@ void SVNClient::dispose(jobject jthis)
     SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNClient");
 }
 
+jobject SVNClient::getVersionExtended(bool verbose)
+{
+    JNIEnv *const env = JNIUtil::getEnv();
+
+    jclass clazz = env->FindClass(JAVA_PACKAGE"/types/VersionExtended");
+    if (JNIUtil::isJavaExceptionThrown())
+        return NULL;
+
+    static volatile jmethodID ctor = 0;
+    if (!ctor)
+    {
+        ctor = env->GetMethodID(clazz, "<init>", "()V");
+        if (JNIUtil::isJavaExceptionThrown())
+            return NULL;
+    }
+
+    static volatile jfieldID fid = 0;
+    if (!fid)
+    {
+        fid = env->GetFieldID(clazz, "cppAddr", "J");
+        if (JNIUtil::isJavaExceptionThrown())
+            return NULL;
+    }
+
+    jobject j_ext_info = env->NewObject(clazz, ctor);
+    if (JNIUtil::isJavaExceptionThrown())
+        return NULL;
+
+    VersionExtended *vx = new VersionExtended(verbose);
+    env->SetLongField(j_ext_info, fid, vx->getCppAddr());
+
+    env->DeleteLocalRef(clazz);
+    return j_ext_info;
+}
+
 jstring SVNClient::getAdminDirectoryName()
 {
     SVN::Pool subPool(pool);

Modified: subversion/trunk/subversion/bindings/javahl/native/SVNClient.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/SVNClient.h?rev=1451810&r1=1451809&r2=1451810&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/SVNClient.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/SVNClient.h Sat Mar  2 01:24:45 2013
@@ -151,6 +151,7 @@ class SVNClient :public SVNBase
                    bool discoverPaths, bool includeMergedRevisions,
                    StringArray &revProps,
                    long limit, LogMessageCallback *callback);
+  jobject getVersionExtended(bool verbose);
   jstring getAdminDirectoryName();
   jboolean isAdminDirectory(const char *name);
   void addToChangelist(Targets &srcPaths, const char *changelist,

Added: subversion/trunk/subversion/bindings/javahl/native/VersionExtended.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/VersionExtended.cpp?rev=1451810&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/VersionExtended.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/VersionExtended.cpp Sat Mar  2 01:24:45 2013
@@ -0,0 +1,98 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file VersionExtended.cpp
+ * @brief Implementation of the VersionExtended class
+ */
+
+#include "JNIUtil.h"
+#include "VersionExtended.h"
+
+const VersionExtended *
+VersionExtended::getCppObject(jobject jthis)
+{
+  if (!jthis)
+    return NULL;
+
+  static jfieldID fid = 0;
+  jlong cppAddr = SVNBase::findCppAddrForJObject(
+      jthis, &fid, JAVA_PACKAGE"/types/VersionExtended");
+  return (cppAddr == 0 ? NULL : reinterpret_cast<VersionExtended *>(cppAddr));
+}
+
+namespace {
+static jobject getWrapperAddress(jobject jthat, volatile jfieldID *fid)
+{
+  JNIEnv *const env = JNIUtil::getEnv();
+  if (!*fid)
+    {
+      *fid = env->GetFieldID(env->GetObjectClass(jthat), "wrapper",
+                             "L"JAVA_PACKAGE"/types/VersionExtended;");
+      if (JNIUtil::isJavaExceptionThrown())
+        {
+          *fid = 0;
+          return 0;
+        }
+    }
+
+  jobject jthis = env->GetObjectField(jthat, *fid);
+  if (JNIUtil::isJavaExceptionThrown())
+    return 0;
+  return jthis;
+}
+} // anonymous namespace
+
+const VersionExtended *
+VersionExtended::getCppObjectFromLinkedLib(jobject jthat)
+{
+  static volatile jfieldID fid;
+  return getCppObject(getWrapperAddress(jthat, &fid));
+}
+
+const VersionExtended *
+VersionExtended::getCppObjectFromLoadedLib(jobject jthat)
+{
+  static volatile jfieldID fid;
+  return getCppObject(getWrapperAddress(jthat, &fid));
+}
+
+const VersionExtended *
+VersionExtended::getCppObjectFromLinkedLibIterator(jobject jthat)
+{
+  static volatile jfieldID fid;
+  return getCppObject(getWrapperAddress(jthat, &fid));
+}
+
+const VersionExtended *
+VersionExtended::getCppObjectFromLoadedLibIterator(jobject jthat)
+{
+  static volatile jfieldID fid;
+  return getCppObject(getWrapperAddress(jthat, &fid));
+}
+
+VersionExtended::~VersionExtended() {}
+
+void VersionExtended::dispose(jobject jthis)
+{
+  static jfieldID fid = 0;
+  SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/types/VersionExtended");
+}

Added: subversion/trunk/subversion/bindings/javahl/native/VersionExtended.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/VersionExtended.h?rev=1451810&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/VersionExtended.h (added)
+++ subversion/trunk/subversion/bindings/javahl/native/VersionExtended.h Sat Mar  2 01:24:45 2013
@@ -0,0 +1,89 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file VersionExtended.h
+ * @brief Interface for the VersionExtended class
+ */
+
+#ifndef JAVAHL_VERSION_EXTENDED_H
+#define JAVAHL_VERSION_EXTENDED_H
+
+#include "SVNBase.h"
+#include "svn_version.h"
+
+class VersionExtended : public SVNBase
+{
+public:
+  static const VersionExtended *getCppObject(jobject jthis);
+  static const VersionExtended *getCppObjectFromLinkedLib(jobject jthat);
+  static const VersionExtended *getCppObjectFromLoadedLib(jobject jthat);
+  static const VersionExtended *getCppObjectFromLinkedLibIterator(jobject jthat);
+  static const VersionExtended *getCppObjectFromLoadedLibIterator(jobject jthat);
+
+  virtual ~VersionExtended();
+  virtual void dispose(jobject jthis);
+
+  VersionExtended(bool verbose)
+    : m_ext_info(svn_version_extended(verbose, pool.getPool()))
+    {}
+
+  const char *build_date() const
+    { return svn_version_ext_build_date(m_ext_info); }
+
+  const char *build_time() const
+    { return svn_version_ext_build_time(m_ext_info); }
+
+  const char *build_host() const
+    { return svn_version_ext_build_host(m_ext_info); }
+
+  const char *copyright() const
+    { return svn_version_ext_copyright(m_ext_info); }
+
+  const char *runtime_host() const
+    { return svn_version_ext_runtime_host(m_ext_info); }
+
+  const char *runtime_osname() const
+    { return svn_version_ext_runtime_osname(m_ext_info); }
+
+  const svn_version_ext_linked_lib_t *get_linked_lib(int index) const
+    {
+      const apr_array_header_t *const libs =
+        svn_version_ext_linked_libs(m_ext_info);
+      if (!libs || index < 0 || libs->nelts <= index)
+        return NULL;
+      return &APR_ARRAY_IDX(libs, index, svn_version_ext_linked_lib_t);
+    }
+
+  const svn_version_ext_loaded_lib_t *get_loaded_lib(int index) const
+    {
+      const apr_array_header_t *const libs =
+        svn_version_ext_loaded_libs(m_ext_info);
+      if (!libs || index < 0 || libs->nelts <= index)
+        return NULL;
+      return &APR_ARRAY_IDX(libs, index, svn_version_ext_loaded_lib_t);
+    }
+
+private:
+  const svn_version_extended_t *m_ext_info;
+};
+
+#endif /* JAVAHL_VERSION_EXTENDED_H */

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=1451810&r1=1451809&r2=1451810&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 Sat Mar  2 01:24:45 2013
@@ -51,6 +51,7 @@
 #include "ChangelistCallback.h"
 #include "StringArray.h"
 #include "RevpropTable.h"
+#include "VersionExtended.h"
 #include "svn_version.h"
 #include "svn_private_config.h"
 #include "version.h"
@@ -89,6 +90,20 @@ Java_org_apache_subversion_javahl_SVNCli
     cl->finalize();
 }
 
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_SVNClient_getVersionExtended(
+    JNIEnv *env, jobject jthis, jboolean verbose)
+{
+  JNIEntry(SVNClient, getVersionExtended);
+  SVNClient *cl = SVNClient::getCppObject(jthis);
+  if (cl == NULL)
+    {
+      JNIUtil::throwError(_("bad C++ this"));
+      return NULL;
+    }
+  return cl->getVersionExtended(!!verbose);
+}
+
 JNIEXPORT jstring JNICALL
 Java_org_apache_subversion_javahl_SVNClient_getAdminDirectoryName
 (JNIEnv *env, jobject jthis)

Added: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_types_VersionExtended.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_types_VersionExtended.cpp?rev=1451810&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_types_VersionExtended.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_types_VersionExtended.cpp Sat Mar  2 01:24:45 2013
@@ -0,0 +1,264 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file org_apache_subversion_javahl_types_VersionExtended.cpp
+ * @brief Implementation of the native methods in the Java class VersionExtended.
+ */
+
+#include "../include/org_apache_subversion_javahl_types_VersionExtended.h"
+#include "../include/org_apache_subversion_javahl_types_VersionExtended_LinkedLib.h"
+#include "../include/org_apache_subversion_javahl_types_VersionExtended_LinkedLibIterator.h"
+#include "../include/org_apache_subversion_javahl_types_VersionExtended_LoadedLib.h"
+#include "../include/org_apache_subversion_javahl_types_VersionExtended_LoadedLibIterator.h"
+#include "VersionExtended.h"
+#include "JNIStackElement.h"
+#include <string>
+
+// VersionExtended native methods
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_getBuildDate(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended, getBuildDate);
+  const VersionExtended *const vx = VersionExtended::getCppObject(jthis);
+  if (vx)
+    return env->NewStringUTF(vx->build_date());
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_getBuildTime(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended, getBuildTime);
+  const VersionExtended *const vx = VersionExtended::getCppObject(jthis);
+  if (vx)
+    return env->NewStringUTF(vx->build_time());
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_getBuildHost(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended, getBuildHost);
+  const VersionExtended *const vx = VersionExtended::getCppObject(jthis);
+  if (vx)
+    return env->NewStringUTF(vx->build_host());
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_getCopyright(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended, getCopyright);
+  const VersionExtended *const vx = VersionExtended::getCppObject(jthis);
+  if (vx)
+    return env->NewStringUTF(vx->copyright());
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_getRuntimeHost(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended, getRuntimeHost);
+  const VersionExtended *const vx = VersionExtended::getCppObject(jthis);
+  if (vx)
+    return env->NewStringUTF(vx->runtime_host());
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_getRuntimeOSName(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended, getRuntimeOSName);
+  const VersionExtended *const vx = VersionExtended::getCppObject(jthis);
+  if (vx)
+    return env->NewStringUTF(vx->runtime_osname());
+  return 0;
+}
+
+
+// VersionExtended.LinkedLib native methods
+
+namespace {
+static const svn_version_ext_linked_lib_t *
+getLinkedLib(JNIEnv *env, jobject jthis)
+{
+  static volatile jfieldID fid = 0;
+  if (!fid)
+    {
+      fid = env->GetFieldID(env->GetObjectClass(jthis), "index", "I");
+      if (JNIUtil::isJavaExceptionThrown())
+        return NULL;      
+    }
+
+  const int index = env->GetIntField(jthis, fid);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;      
+
+  const VersionExtended *const vx =
+    VersionExtended::getCppObjectFromLinkedLib(jthis);
+  if (vx)
+    return vx->get_linked_lib(index);
+  return NULL;
+}
+} // anonymous namespace
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LinkedLib_getName(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LinkedLib, getName);
+  const svn_version_ext_linked_lib_t *const lib = getLinkedLib(env, jthis);
+  if (lib)
+    return env->NewStringUTF(lib->name);
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LinkedLib_getCompiledVersion(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LinkedLib, getCompiledVersion);
+  const svn_version_ext_linked_lib_t *const lib = getLinkedLib(env, jthis);
+  if (lib)
+    return env->NewStringUTF(lib->compiled_version);
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LinkedLib_getRuntimeVersion(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LinkedLib, getRuntimeVersion);
+  const svn_version_ext_linked_lib_t *const lib = getLinkedLib(env, jthis);
+  if (lib)
+    return env->NewStringUTF(lib->runtime_version);
+  return 0;
+}
+
+
+// VersionExtended.LoadedLib native methods
+
+namespace {
+static const svn_version_ext_loaded_lib_t *
+getLoadedLib(JNIEnv *env, jobject jthis)
+{
+  static volatile jfieldID fid = 0;
+  if (!fid)
+    {
+      fid = env->GetFieldID(env->GetObjectClass(jthis), "index", "I");
+      if (JNIUtil::isJavaExceptionThrown())
+        return NULL;      
+    }
+
+  const int index = env->GetIntField(jthis, fid);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;      
+
+  const VersionExtended *const vx =
+    VersionExtended::getCppObjectFromLoadedLib(jthis);
+  if (vx)
+    return vx->get_loaded_lib(index);
+  return NULL;
+}
+} // anonymous namespace
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LoadedLib_getName(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LoadedLib, getName);
+  const svn_version_ext_loaded_lib_t *const lib = getLoadedLib(env, jthis);
+  if (lib)
+    return env->NewStringUTF(lib->name);
+  return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LoadedLib_getVersion(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LoadedLib, getVersion);
+  const svn_version_ext_loaded_lib_t *const lib = getLoadedLib(env, jthis);
+  if (lib)
+    return env->NewStringUTF(lib->version);
+  return 0;
+}
+
+
+// VersionExtended.LinkedLibIterator and .LoadedLibIterator native methods
+
+JNIEXPORT jboolean JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LinkedLibIterator_hasNext(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LinkedLibIterator, hasNext);
+
+  static volatile jfieldID fid = 0;
+  if (!fid)
+    {
+      fid = env->GetFieldID(env->GetObjectClass(jthis), "index", "I");
+      if (JNIUtil::isJavaExceptionThrown())
+        return false;
+    }
+
+  const int index = env->GetIntField(jthis, fid);
+  if (JNIUtil::isJavaExceptionThrown())
+    return false;
+
+  const VersionExtended *const vx =
+    VersionExtended::getCppObjectFromLinkedLibIterator(jthis);
+  if (vx)
+    return !!vx->get_linked_lib(1 + index);
+  return false;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_apache_subversion_javahl_types_VersionExtended_00024LoadedLibIterator_hasNext(
+    JNIEnv *env, jobject jthis)
+{
+  JNIEntry(VersionExtended$LoadedLibIterator, hasNext);
+
+  static volatile jfieldID fid = 0;
+  if (!fid)
+    {
+      fid = env->GetFieldID(env->GetObjectClass(jthis), "index", "I");
+      if (JNIUtil::isJavaExceptionThrown())
+        return false;
+    }
+
+  const int index = env->GetIntField(jthis, fid);
+  if (JNIUtil::isJavaExceptionThrown())
+    return false;
+
+  const VersionExtended *const vx =
+    VersionExtended::getCppObjectFromLoadedLibIterator(jthis);
+  if (vx)
+    return !!vx->get_loaded_lib(1 + index);
+  return false;
+}

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1451810&r1=1451809&r2=1451810&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Sat Mar  2 01:24:45 2013
@@ -51,6 +51,12 @@ public interface ISVNClient
     public Version getVersion();
 
     /**
+     * @return Extended version information about the underlying
+     * native libraries and operating system.
+     */
+    public VersionExtended getVersionExtended(boolean verbose);
+
+    /**
      * @return The name of the working copy's administrative
      * directory, which is usually <code>.svn</code>.
      * @see <a

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java?rev=1451810&r1=1451809&r2=1451810&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java Sat Mar  2 01:24:45 2013
@@ -103,6 +103,8 @@ public class SVNClient implements ISVNCl
         return NativeResources.getVersion();
     }
 
+    public native VersionExtended getVersionExtended(boolean verbose);
+
     public native String getAdminDirectoryName();
 
     public native boolean isAdminDirectory(String name);

Added: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java?rev=1451810&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java (added)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java Sat Mar  2 01:24:45 2013
@@ -0,0 +1,238 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.types;
+
+/**
+ * Encapsulates information about the compile-time and run-time
+ * properties of the Subversion libraries.
+ * @since 1.8
+ */
+public class VersionExtended
+{
+    /**
+     * @return The date when the libsvn_subr library was compiled, in
+     * the format defined by the C standard macro #__DATE__.
+     */
+    public native String getBuildDate();
+
+    /**
+     * @return The time when the libsvn_subr library was compiled, in
+     * the format defined by the C standard macro #__TIME__.
+     */
+    public native String getBuildTime();
+
+    /**
+     * @return The canonical host triplet (arch-vendor-osname) of the
+     * system where libsvn_subr was compiled.
+     *
+     * @note On Unix-like systems (includng Mac OS X), this string is
+     * the same as the output of the config.guess script for the
+     * underlying Subversion libraries.
+     */
+    public native String getBuildHost();
+
+    /**
+     * @return The localized copyright notice.
+     */
+    public native String getCopyright();
+
+    /**
+     * @return The canonical host triplet (arch-vendor-osname) of the
+     * system where the current process is running.
+     *
+     * @note This string may not be the same as the output of
+     * config.guess on the same system.
+     */
+    public native String getRuntimeHost();
+
+    /**
+     * @return The "commercial" release name of the running operating
+     * system, if available.  Not to be confused with, e.g., the
+     * output of "uname -v" or "uname -r".  The returned value may
+     * be #null.
+     */
+    public native String getRuntimeOSName();
+
+    /**
+     * Dependent library information.
+     * Describes the name and versions of known dependencies
+     * used by libsvn_subr.
+     */
+    public class LinkedLib
+    {
+        /** @return Library name. */
+        public final native String getName();
+
+        /** @return Compile-time version string. */
+        public final native String getCompiledVersion();
+
+        /**
+         * @return Run-time version string (may be #null, which
+         * indicates that the library is embedded or statically
+         * linked).
+         */
+        public final native String getRuntimeVersion();
+
+        LinkedLib(VersionExtended wrapper, int index)
+        {
+            this.wrapper = wrapper;
+            this.index = index;
+        }
+
+        private final VersionExtended wrapper;
+        private final int index;
+    };
+
+    /**
+     * @return Iterator for an immutable internal list of #LinkedLib
+     * describing dependent libraries.  The list may be empty.
+     */
+    public java.util.Iterator<LinkedLib> getLinkedLibs()
+    {
+        return new LinkedLibIterator(this);
+    }
+
+    /**
+     * Loaded shared library information.
+     * Describes the name and, where available, version of the shared
+     * libraries loaded by the running program.
+     */
+    public class LoadedLib
+    {
+        /** @return Library name. */
+        public final native String getName();
+
+        /** @return Library version (may be #null). */
+        public final native String getVersion();
+
+        LoadedLib(VersionExtended wrapper, int index)
+        {
+            this.wrapper = wrapper;
+            this.index = index;
+        }
+
+        private final VersionExtended wrapper;
+        private final int index;
+    };
+
+    /**
+     * @return Iterator for an immutable internal list of #LoadedLib
+     * describing loaded shared libraries.  The the list may be empty.
+     *
+     * @note On Mac OS X, the loaded frameworks, private frameworks
+     * and system libraries will not be listed.
+     */
+    public java.util.Iterator<LoadedLib> getLoadedLibs()
+    {
+        return new LoadedLibIterator(this);
+    }
+
+    /**
+     * Iterator for #LinkedLib.
+     */
+    private class LinkedLibIterator implements java.util.Iterator<LinkedLib>
+    {
+        public LinkedLibIterator(VersionExtended wrapper)
+        {
+            this.wrapper = wrapper;
+            this.index = -1;
+        }
+
+        /**
+         * Implementation of java.util.Iterator#hasNext().
+         * @return #true if next() can be called safely.
+         */
+        public native boolean hasNext();
+
+        /**
+         * Implementation of java.util.Iterator#next().
+         * @return The next element of the sequence.
+         */
+        public LinkedLib next()
+        {
+            if (!hasNext())
+                throw new java.util.NoSuchElementException();
+            return new LinkedLib(this.wrapper, ++this.index);
+        }
+
+        /**
+         * Implementation of java.util.Iterator#remove().
+         * @note Not implemented, all sequences are immutable.
+         */
+        public void remove()
+        {
+            throw new java.lang.UnsupportedOperationException();
+        }
+
+        private final VersionExtended wrapper;
+        private int index;
+    };
+
+    /**
+     * Iterator for #LoadedLib.
+     */
+    private class LoadedLibIterator implements java.util.Iterator<LoadedLib>
+    {
+        public LoadedLibIterator(VersionExtended wrapper)
+        {
+            this.wrapper = wrapper;
+            this.index = -1;
+        }
+
+        /**
+         * Implementation of java.util.Iterator#hasNext().
+         * @return #true if next() can be called safely.
+         */
+        public native boolean hasNext();
+
+        /**
+         * Implementation of java.util.Iterator#next().
+         * @return The next element of the sequence.
+         */
+        public LoadedLib next()
+        {
+            if (!hasNext())
+                throw new java.util.NoSuchElementException();
+            return new LoadedLib(this.wrapper, ++this.index);
+        }
+
+        /**
+         * Implementation of java.util.Iterator#remove().
+         * @note Not implemented, all sequences are immutable.
+         */
+        public void remove()
+        {
+            throw new java.lang.UnsupportedOperationException();
+        }
+
+        private final VersionExtended wrapper;
+        private int index;
+    };
+
+    /**
+     * Slot for the adress of the native peer.
+     * The JNI code is the only user of this member.
+     */
+    private long cppAddr = 0;
+}

Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1451810&r1=1451809&r2=1451810&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Sat Mar  2 01:24:45 2013
@@ -131,6 +131,91 @@ public class BasicTests extends SVNTests
     }
 
     /**
+     * Test SVNClient.getVersionExtended().
+     * @throws Throwable
+     */
+    public void testVersionExtendedQuiet() throws Throwable
+    {
+        try
+        {
+            VersionExtended vx = client.getVersionExtended(false);
+            String result = vx.getBuildDate();
+            if (result == null || result.trim().length() == 0)
+                throw new Exception("Build date empty");
+            result = vx.getBuildTime();
+            if (result == null || result.trim().length() == 0)
+                throw new Exception("Build time empty");
+            result = vx.getBuildHost();
+            if (result == null || result.trim().length() == 0)
+                throw new Exception("Build host empty");
+            result = vx.getCopyright();
+            if (result == null || result.trim().length() == 0)
+                throw new Exception("Copyright empty");
+        }
+        catch (Exception e)
+        {
+            fail("VersionExtended should always be available unless the " +
+                 "native libraries failed to initialize: " + e);
+        }
+    }
+
+    /**
+     * Test SVNClient.getVersionExtended().
+     * @throws Throwable
+     */
+    public void testVersionExtendedVerbose() throws Throwable
+    {
+        try
+        {
+            VersionExtended vx = client.getVersionExtended(true);
+            String result = vx.getRuntimeHost();
+            if (result == null || result.trim().length() == 0)
+                throw new Exception("Runtime host empty");
+
+            // OS name is allowed to be null, but not empty
+            result = vx.getRuntimeOSName();
+            if (result != null && result.trim().length() == 0)
+                throw new Exception("Runtime OS name empty");
+
+            java.util.Iterator<VersionExtended.LinkedLib> ikl;
+            ikl = vx.getLinkedLibs();
+            if (ikl.hasNext())
+            {
+                VersionExtended.LinkedLib lib = ikl.next();
+                result = lib.getName();
+                if (result == null || result.trim().length() == 0)
+                    throw new Exception("Linked lib name empty");
+                result = lib.getCompiledVersion();
+                if (result == null || result.trim().length() == 0)
+                    throw new Exception("Linked lib compiled version empty");
+                // Runtime version is allowed to be null, but not empty
+                result = lib.getRuntimeVersion();
+                if (result != null && result.trim().length() == 0)
+                    throw new Exception("Linked lib runtime version empty");
+            }
+
+            java.util.Iterator<VersionExtended.LoadedLib> ill;
+            ill = vx.getLoadedLibs();
+            if (ill.hasNext())
+            {
+                VersionExtended.LoadedLib lib = ill.next();
+                result = lib.getName();
+                if (result == null || result.trim().length() == 0)
+                    throw new Exception("Loaded lib name empty");
+                // Version is allowed to be null, but not empty
+                result = lib.getVersion();
+                if (result != null && result.trim().length() == 0)
+                    throw new Exception("Loaded lib version empty");
+            }
+        }
+        catch (Exception e)
+        {
+            fail("VersionExtended should always be available unless the " +
+                 "native libraries failed to initialize: " + e);
+        }
+    }
+
+    /**
      * Test the JNIError class functionality
      * @throws Throwable
      */