subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1539114 - in /subversion/trunk: ./ subversion/bindings/javahl/native/ subversion/bindings/javahl/native/jniwrapper/
Date Tue, 05 Nov 2013 19:59:45 GMT
Author: brane
Date: Tue Nov  5 19:59:44 2013
New Revision: 1539114

URL: http://svn.apache.org/r1539114
Log:
Introduce a new-style JNI wrapper to the JavaHL native implementaiton.
The old-style, rather messy code will eventually be ported to this.

* build.conf
  (private-includes): Add JavaHL *.hpp and jniwrapper headers.
  (libsvnjavahl): Add jniwrapper sources.

* subversion/bindings/javahl/native/JNIUtil.cpp
  (g_jvm, JNI_OnLoad, JNI_OnUnload): Removed; replaced by equivalent
   functionality in jniwrapper.
  (JNIUtil::getEnv): Reimplement using jniwrapper's Java::Env class.

* subversion/bindings/javahl/native/jniwrapper: New directory.
* subversion/bindings/javahl/native/jniwrapper/jni_array.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_base.cpp,
  subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp,
  subversion/bindings/javahl/native/jniwrapper/jni_env.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_globalref.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_list.cpp,
  subversion/bindings/javahl/native/jniwrapper/jni_list.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_object.hpp,
  subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp: New files.

Added:
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_array.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_globalref.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp   (with props)
Modified:
    subversion/trunk/build.conf
    subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp

Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1539114&r1=1539113&r2=1539114&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Tue Nov  5 19:59:44 2013
@@ -43,6 +43,8 @@ private-includes =
         subversion/bindings/cxxhl/src/*.hpp
         subversion/bindings/cxxhl/src/aprwrap/*.hpp
         subversion/bindings/cxxhl/src/private/*.hpp
+        subversion/bindings/javahl/native/*.hpp
+        subversion/bindings/javahl/native/jniwrapper/jni_*.hpp
         subversion/libsvn_subr/utf8proc/utf8proc.h
         subversion/libsvn_subr/utf8proc/utf8proc.c
         subversion/libsvn_subr/utf8proc/utf8proc_data.c
@@ -687,7 +689,7 @@ type = lib
 path = subversion/bindings/javahl/native
 libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff 
        libsvn_subr libsvn_fs aprutil apriconv apr java-sdk
-sources = *.cpp
+sources = *.cpp jniwrapper/*.cpp
 add-deps = $(javahl_java_DEPS) $(javahl_callback_javah_DEPS)
            $(javahl_remote_javah_DEPS) $(javahl_types_javah_DEPS)
            $(javahl_util_javah_DEPS) $(javahl_javah_DEPS)

Modified: subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1539114&r1=1539113&r2=1539114&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp Tue Nov  5 19:59:44 2013
@@ -64,6 +64,8 @@
 #include "Pool.h"
 
 
+#include "jniwrapper/jni_env.hpp"
+
 // Static members of JNIUtil are allocated here.
 apr_pool_t *JNIUtil::g_pool = NULL;
 std::list<SVNBase*> JNIUtil::g_finalizedObjects;
@@ -76,34 +78,13 @@ JNIEnv *JNIUtil::g_initEnv;
 int JNIUtil::g_logLevel = JNIUtil::noLog;
 std::ofstream JNIUtil::g_logStream;
 
-namespace {
-JavaVM *g_jvm = NULL;
-} // anonymous namespace
-
-extern "C" JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *jvm, void*)
-{
-  g_jvm = jvm;
-  return JNI_VERSION_1_2;
-}
-
-extern "C" JNIEXPORT void JNICALL
-JNI_OnUnload(JavaVM*, void*)
-{}
-
 /**
  * Return the JNI environment to use
  * @return the JNI environment
  */
 JNIEnv *JNIUtil::getEnv()
 {
-  // During init -> look into the global variable.
-  if (g_inInit)
-    return g_initEnv;
-
-  void* penv;
-  g_jvm->GetEnv(&penv, JNI_VERSION_1_2);
-  return static_cast<JNIEnv*>(penv);
+  return Java::Env().get();
 }
 
 /**

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_array.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_array.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_array.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_array.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,208 @@
+/**
+ * @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_JNIWRAPPER_ARRAY_HPP
+#define SVN_JAVAHL_JNIWRAPPER_ARRAY_HPP
+
+#include <string>
+
+#include "svn_string.h"
+
+#include "jni_env.hpp"
+
+namespace Java {
+
+/**
+ * Wrapper class for Java byte arrays.
+ *
+ * @since New in 1.9.
+ */
+class ByteArray
+{
+public:
+  /**
+   * Constructs a wrapper around an existing @a array.
+   */
+  explicit ByteArray(Env env, jbyteArray array)
+    : m_env(env),
+      m_length(array ? m_env.GetArrayLength(array) : -1),
+      m_array(array)
+    {}
+
+  /**
+   * Constructs a new array and wrapper from @a text.
+   */
+  explicit ByteArray(Env env, const char* text)
+    : m_env(env),
+      m_length(jsize(::strlen(text))),
+      m_array(m_env.NewByteArray(m_length))
+    {
+      ByteArray::Contents contents(*this);
+      ::memcpy(contents.data(), text, m_length);
+    }
+
+  /**
+   * Constructs a new array and wrapper of size @a length
+   * from @a data.
+   */
+  explicit ByteArray(Env env, const void* data, jsize length)
+    : m_env(env),
+      m_length(length),
+      m_array(m_env.NewByteArray(m_length))
+    {
+      ByteArray::Contents contents(*this);
+      ::memcpy(contents.data(), data, m_length);
+    }
+
+  /**
+   * Constructs a new array and wrapper from @a text.
+   */
+  explicit ByteArray(Env env, const std::string& text)
+    : m_env(env),
+      m_length(jsize(text.size())),
+      m_array(m_env.NewByteArray(m_length))
+    {
+      ByteArray::Contents contents(*this);
+      ::memcpy(contents.data(), text.c_str(), m_length);
+    }
+
+  /**
+   * Returns the wrapped native array reference.
+   */
+  jbyteArray get() const
+    {
+      return m_array;
+    }
+
+  /**
+   * Returns the size of the wrapped array.
+   */
+  jsize length() const
+    {
+      return m_length;
+    }
+
+  /**
+   * Accessor class for the contents of the byte array.
+   *
+   * Objects of this class should be created within the scope where
+   * the raw data stored in the array must be manipulated. They will
+   * create either a mutable or an immutable mirror of the array
+   * contents, depending on the constantness of the array wrapper. The
+   * data will be released (and changes copied into the JVM, depending
+   * on access mode) by the destructor.
+   */
+  class Contents
+  {
+  public:
+    /**
+     * Constructs a mutable array contents accessor.
+     */
+    explicit Contents(ByteArray& array)
+      : m_array(array),
+        m_data(array.m_env.GetByteArrayElements(array.m_array, NULL)),
+        m_mode(0)
+      {
+        //fprintf(stderr,
+        //        "%s:%d: non-const byte array data, size=%d\n",
+        //        __FILE__, __LINE__, int(m_array.m_length));
+      }
+
+    /**
+     * Constructs an immutable array contents accessor.
+     *
+     * Whilst the returned contents are themselves mutable, the
+     * destructor will discard any changes.
+     */
+    explicit Contents(const ByteArray& array)
+      : m_array(array),
+        m_data(array.m_env.GetByteArrayElements(array.m_array, NULL)),
+        m_mode(JNI_ABORT)
+      {
+        //fprintf(stderr,
+        //        "%s:%d: const byte array data, size=%d\n",
+        //        __FILE__, __LINE__, int(m_array.m_length));
+      }
+
+    /**
+     * Releases the array contents, possibly committing changes to the JVM.
+     */
+    ~Contents()
+      {
+        const Env& env = m_array.m_env;
+        env.ReleaseByteArrayElements(m_array.m_array, m_data, m_mode);
+      }
+
+    /**
+     * Returns the address of the array contents.
+     */
+    const char* data() const
+      {
+        return reinterpret_cast<const char*>(m_data);
+      }
+
+    /**
+     * Returns the address of the array contents.
+     * @throw std::logic_error if the data reference is immutable.
+     */
+    char* data()
+      {
+        if (!m_mode)
+          return reinterpret_cast<char*>(const_cast<jbyte*>(m_data));
+        throw std::logic_error(
+            _("Can't make a writable pointer to immutable array contents."));
+      }
+
+    /**
+     * Returns the size of the array contents.
+     */
+    jsize length() const
+      {
+        return m_array.m_length;
+      }
+
+    /**
+     * Constructs @a str that refers to the array contents.
+     */
+    void get_string(svn_string_t* str) const
+      {
+        str->data = data();
+        str->len = m_array.m_length;
+      }
+
+  private:
+    const ByteArray& m_array;
+    jbyte* const m_data;
+    const jint m_mode;
+  };
+
+private:
+  friend class Contents;
+  const Env m_env;
+  const jsize m_length;
+  const jbyteArray m_array;
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_ARRAY_HPP

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,232 @@
+/**
+ * @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 "jni_env.hpp"
+#include "jni_globalref.hpp"
+#include "jni_exception.hpp"
+#include "jni_object.hpp"
+#include "jni_array.hpp"
+
+
+// Global library initializaiton
+
+/**
+ * Initializer function, called just after the JVM loads the native
+ * library.  Stores the global JVM reference and creates the global
+ * class cache.
+ */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM* jvm, void*)
+{
+  ::Java::Env::m_jvm = jvm;
+  new ::Java::ClassCache(::Java::Env());
+  return JNI_VERSION_1_2;
+}
+
+/**
+ * Cleanup function, called just before the JVM unloads the native
+ * library.  Destroys the global class cache.
+ */
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM*, void*)
+{
+  delete ::Java::ClassCache::m_instance;
+}
+
+
+namespace Java {
+
+// class Java::Env
+
+::JavaVM* Env::m_jvm = NULL;
+
+::JNIEnv* Env::env_from_jvm()
+{
+  if (m_jvm)
+    {
+      void *penv;
+      switch (m_jvm->GetEnv(&penv, JNI_VERSION_1_2))
+        {
+        case JNI_OK:
+          return static_cast<JNIEnv*>(penv);
+
+        case JNI_EDETACHED:
+          throw std::runtime_error(
+              _("Native thread is not attached to a Java VM"));
+
+        case JNI_EVERSION:
+          throw std::runtime_error(_("Unsupported JNI version"));
+
+        default:
+          throw std::runtime_error(_("Invalid JNI environment"));
+        }
+    }
+  throw std::logic_error(_("JavaVM instance was not initialized"));
+}
+
+void Env::throw_java_out_of_memory(const char* message) const
+{
+  OutOfMemoryError(*this).raise(message);
+}
+
+// class Java::LocalFrame
+
+const jint LocalFrame::DEFAULT_CAPACITY = 16;
+
+
+// class Java::GlobalObject
+
+GlobalObject& GlobalObject::operator=(jobject that)
+{
+  this->~GlobalObject();
+  return *new(this) GlobalObject(Env(), that);
+}
+
+GlobalObject::~GlobalObject()
+{
+  Env().DeleteGlobalRef(m_obj);
+}
+
+
+// class Java::GlobalClass
+
+GlobalClass& GlobalClass::operator=(jclass that)
+{
+  this->~GlobalClass();
+  return *new(this) GlobalClass(Env(), that);
+}
+
+
+// Class Java::Object
+
+const char* const Object::m_class_name = "java/lang/Object";
+
+
+// Class Java::Class
+
+const char* const Class::m_class_name = "java/lang/Class";
+jmethodID Class::m_mid_get_class = NULL;
+jmethodID Class::m_mid_get_name = NULL;
+void Class::static_init(Env env)
+{
+  m_mid_get_class = env.GetMethodID(
+      ClassCache::get_object(),
+      "getClass", "()Ljava/lang/Class;");
+  m_mid_get_name = env.GetMethodID(
+      ClassCache::get_classtype(),
+      "getName",  "()Ljava/lang/String;");
+}
+
+namespace{
+jobject get_class_of_object(Env env, jobject obj, jmethodID mid_get_class)
+{
+  if (!obj)
+    return NULL;
+  return env.CallObjectMethod(obj, mid_get_class);
+}
+} // anonymous namespace
+
+Class::Class(Env env, jobject obj)
+  : Object(env, ClassCache::get_classtype(),
+           get_class_of_object(env, obj, m_mid_get_class))
+{}
+
+Class::Class(const Object& obj)
+  : Object(obj.get_env(), ClassCache::get_classtype(),
+           get_class_of_object(obj.get_env(), obj.get(), m_mid_get_class))
+{}
+
+jstring Class::get_name() const
+{
+  if (!m_jthis)
+    return NULL;
+  return jstring(m_env.CallObjectMethod(m_jthis, m_mid_get_name));
+}
+
+
+// Class Java::String
+
+const char* const String::m_class_name = "java/lang/String";
+void String::static_init(Env env)
+{
+  // TODO: Init various string methods
+}
+
+
+// class Java::Exception
+
+jstring Exception::get_message() const
+{
+  if (instantiated())
+    return jstring(m_env.CallObjectMethod(m_jthis, m_mid_get_message));
+  throw std::logic_error(_("Could not get exception message:"
+                           " Exception instance is not available"));
+}
+
+const char* const Exception::m_class_name = "java/lang/Throwable";
+jmethodID Exception::m_mid_get_message = NULL;
+void Exception::static_init(Env env)
+{
+  m_mid_get_message = env.GetMethodID(
+      ClassCache::get_throwable(),
+      "getMessage", "()Ljava/lang/String;");
+}
+
+
+// Other exception class initializers
+
+const char* const RuntimeException::m_class_name =
+  "java/lang/RuntimeException";
+
+const char* const NullPointerException::m_class_name =
+  "java/lang/NullPointerException";
+
+const char* const OutOfMemoryError::m_class_name =
+  "java/lang/OutOfMemoryError";
+
+} // namespace Java
+
+
+namespace JavaHL {
+
+// class JavaHL::JavaException
+
+JavaException::~JavaException() throw() {}
+
+const char* JavaException::what() const throw()
+{
+  // FIXME: Implement this?
+  return "";
+}
+
+jthrowable JavaException::get_java_exception() const
+{
+  return ::Java::Env().ExceptionOccurred();
+}
+
+jthrowable JavaException::get_java_exception(const ::Java::Env& env) const
+{
+  return env.ExceptionOccurred();
+}
+
+} // namespace JavaHL

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

Added: 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=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,53 @@
+/**
+ * @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 "jni_env.hpp"
+#include "jni_globalref.hpp"
+#include "jni_exception.hpp"
+#include "jni_object.hpp"
+
+#include "../SubversionException.hpp"
+
+namespace Java {
+
+const ClassCache* ClassCache::m_instance = NULL;
+
+ClassCache::~ClassCache() {}
+
+#define SVN_JAVAHL_JNIWRAPPER_CLASS_CACHE_INIT(M, C)    \
+  m_##M(env, env.FindClass(C::m_class_name))
+ClassCache::ClassCache(Env env)
+  : SVN_JAVAHL_JNIWRAPPER_CLASS_CACHE_INIT(object, Object),
+    SVN_JAVAHL_JNIWRAPPER_CLASS_CACHE_INIT(classtype, Class),
+    SVN_JAVAHL_JNIWRAPPER_CLASS_CACHE_INIT(throwable, Exception),
+    SVN_JAVAHL_JNIWRAPPER_CLASS_CACHE_INIT(string, String)
+{
+  m_instance = this;
+  // no-op: Object::static_init(env);
+  Class::static_init(env);
+  Exception::static_init(env);
+  String::static_init(env);
+}
+#undef SVN_JAVAHL_JNIWRAPPER_CLASS_CACHE_INIT
+
+} // namespace Java

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,510 @@
+/**
+ * @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_JNIWRAPPER_ENV_HPP
+#define SVN_JAVAHL_JNIWRAPPER_ENV_HPP
+
+#include <jni.h>
+#include <cstdarg>
+#include <stdexcept>
+
+#include "svn_private_config.h"
+
+#include "jni_javahl_exception.hpp"
+
+#ifdef SVN_JAVAHL_DEBUG
+#include <iostream>
+#define SVN_JAVAHL_JNIWRAPPER_LOG(expr)       \
+  do {                                        \
+    std::cerr << expr << std::endl;           \
+  } while(0)
+#else
+#define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
+#endif // SVN_JAVAHL_DEBUG
+
+namespace Java {
+
+/**
+ * Encapsulation of a JNI environment reference.
+ *
+ * This class wraps all (relevant) JNI functions and checks for thrown
+ * exceptions, so that call sites don't have to be cluttered with KNI
+ * exception checks.
+ *
+ * @since New in 1.9.
+ */
+class Env
+{
+public:
+  /**
+   * Constructs an environment object, retreiving the JNI environment
+   * reference from the global JVM reference.
+   */
+  explicit Env()
+    : m_env(env_from_jvm())
+    {}
+
+  /**
+   * Given a JNI renvironment reference, constructs an environment object.
+   */
+  explicit Env(::JNIEnv* env)
+    : m_env(env)
+    {}
+
+  /**
+   * Returns the wrapped JNI environment reference.
+   *
+   * This method is present for compatibility with the old-style
+   * native implmentation that needs the raw pointer, and will be
+   * removed presently. Do not use it in new-style code.
+   */
+  ::JNIEnv* get() const
+    {
+      SVN_JAVAHL_JNIWRAPPER_LOG("Warning: Direct access to JNIEnv at "
+                                << __FILE__ << ":" << __LINE__);
+      return m_env;
+    }
+
+  /** Wrapped JNI function. */
+  jobject NewGlobalRef(jobject obj) const
+    {
+      jobject ret = m_env->NewGlobalRef(obj);
+      check_java_exception();
+      if (!ret)
+        throw_java_out_of_memory(_("Could not create global reference"));
+      return ret;
+    }
+
+  /** Wrapped JNI function. */
+  void DeleteGlobalRef(jobject obj) const
+    {
+      m_env->DeleteGlobalRef(obj);
+    }
+
+  /** Wrapped JNI function. */
+  void PushLocalFrame(jint capacity) const
+    {
+      if (0 > m_env->PushLocalFrame(capacity))
+        throw_java_exception();
+    }
+
+  /** Wrapped JNI function. */
+  void PopLocalFrame() const
+    {
+      m_env->PopLocalFrame(NULL);
+    }
+
+  /** Wrapped JNI function. */
+  jint Throw(jthrowable exc) const
+    {
+      return m_env->Throw(exc);
+    }
+
+  /** Wrapped JNI function. */
+  jint ThrowNew(jclass cls, const char* message) const
+    {
+      return m_env->ThrowNew(cls, message);
+    }
+
+  /** Wrapped JNI function. */
+  jthrowable ExceptionOccurred() const throw()
+    {
+      return m_env->ExceptionOccurred();
+    }
+
+  /** Wrapped JNI function. */
+  jclass FindClass(const char* name) const
+    {
+      jclass cls = m_env->FindClass(name);
+      check_java_exception();
+      return cls;
+    }
+
+  /** Wrapped JNI function. */
+  jobject NewObject(jclass cls, jmethodID ctor, ...) const
+    {
+      std::va_list args;
+      va_start(args, ctor);
+      jobject obj = m_env->NewObjectV(cls, ctor, args);
+      va_end(args);
+      check_java_exception();
+      return obj;
+    }
+
+  /** Wrapped JNI function. */
+  jclass GetObjectClass(jobject obj) const
+    {
+      jclass cls = m_env->GetObjectClass(obj);
+      check_java_exception();
+      return cls;
+    }
+
+  /** Wrapped JNI function. */
+  jmethodID GetMethodID(jclass cls, const char* name, const char* sig) const
+    {
+      jmethodID mid = m_env->GetMethodID(cls, name, sig);
+      check_java_exception();
+      return mid;
+    }
+
+  /** Wrapped JNI function. */
+  jfieldID GetFieldID(jclass cls, const char* name, const char* sig) const
+    {
+      jfieldID fid = m_env->GetFieldID(cls, name, sig);
+      check_java_exception();
+      return fid;
+    }
+
+  /** Wrapped JNI function. */
+  jfieldID GetStaticFieldID(jclass cls, const char* name,
+                            const char* sig) const
+    {
+      jfieldID fid = m_env->GetStaticFieldID(cls, name, sig);
+      check_java_exception();
+      return fid;
+    }
+
+  /** Wrapped JNI function. */
+  jstring NewStringUTF(const char* text) const
+    {
+      if (!text)
+        return NULL;
+
+      jstring str = m_env->NewStringUTF(text);
+      check_java_exception();
+      return str;
+    }
+
+  /** Wrapped JNI function. */
+  jsize GetStringLength(jstring str) const
+    {
+      jsize len = m_env->GetStringLength(str);
+      check_java_exception();
+      return len;
+    }
+
+  /** Wrapped JNI function. */
+  jsize GetStringUTFLength(jstring str) const
+    {
+      jsize len = m_env->GetStringUTFLength(str);
+      check_java_exception();
+      return len;
+    }
+
+  /** Wrapped JNI function. */
+  const char* GetStringUTFChars(jstring str, jboolean* is_copy) const
+    {
+      if (!str)
+        return NULL;
+
+      const char* text = m_env->GetStringUTFChars(str, is_copy);
+      check_java_exception();
+      if (!text)
+        throw std::runtime_error(
+              _("Could not get contents of Java String"));
+      return text;
+    }
+
+  /** Wrapped JNI function. */
+  void ReleaseStringUTFChars(jstring str, const char* new_text) const
+    {
+      if (!str)
+        throw std::logic_error(
+              _("Can not release contents of a null String"));
+      m_env->ReleaseStringUTFChars(str, new_text);
+      check_java_exception();
+    }
+
+  /** Wrapped JNI function. */
+  void CallVoidMethod(jobject obj, jmethodID mid, ...) const
+    {
+      std::va_list args;
+      va_start(args, mid);
+      m_env->CallObjectMethodV(obj, mid, args);
+      va_end(args);
+      check_java_exception();
+    }
+
+  /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(T, N)               \
+  T Call##N##Method(jobject obj, jmethodID mid, ...) const      \
+    {                                                           \
+      std::va_list args;                                        \
+      va_start(args, mid);                                      \
+      T ret = m_env->Call##N##MethodV(obj, mid, args);          \
+      va_end(args);                                             \
+      check_java_exception();                                   \
+      return ret;                                               \
+    }
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jobject, Object)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jboolean, Boolean)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jbyte, Byte)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jchar, Char)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jshort, Short)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jint, Int)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jlong, Long)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jfloat, Float)
+  SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD
+
+  /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(T, N)                 \
+  T Get##N##Field(jobject obj, jfieldID fid) const              \
+    {                                                           \
+      T ret = m_env->Get##N##Field(obj, fid);                   \
+      check_java_exception();                                   \
+      return ret;                                               \
+    }
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jobject, Object)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jboolean, Boolean)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jbyte, Byte)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jchar, Char)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jshort, Short)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jint, Int)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jlong, Long)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jfloat, Float)
+  SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD
+
+  /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(T, N)                 \
+  void Set##N##Field(jobject obj, jfieldID fid, T val) const    \
+    {                                                           \
+      m_env->Set##N##Field(obj, fid, val);                      \
+      check_java_exception();                                   \
+    }
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jobject, Object)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jboolean, Boolean)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jbyte, Byte)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jchar, Char)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jshort, Short)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jint, Int)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jlong, Long)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jfloat, Float)
+  SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD
+
+  /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(T, N)          \
+  T GetStatic##N##Field(jclass cls, jfieldID fid) const         \
+    {                                                           \
+      T ret = m_env->GetStatic##N##Field(cls, fid);             \
+      check_java_exception();                                   \
+      return ret;                                               \
+    }
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jobject, Object)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jboolean, Boolean)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jbyte, Byte)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jchar, Char)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jshort, Short)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jint, Int)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jlong, Long)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jfloat, Float)
+  SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD
+
+  /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(T, N)                  \
+  void SetStatic##N##Field(jclass cls, jfieldID fid, T val) const       \
+    {                                                                   \
+      m_env->SetStatic##N##Field(cls, fid, val);                        \
+      check_java_exception();                                           \
+    }
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jobject, Object)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jboolean, Boolean)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jbyte, Byte)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jchar, Char)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jshort, Short)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jint, Int)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jlong, Long)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jfloat, Float)
+  SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD
+
+  /** Wrapped JNI function. */
+  jsize GetArrayLength(jarray array) const
+    {
+      if (!array)
+        return -1;
+      return m_env->GetArrayLength(array);
+    }
+
+  /** Wrapped JNI function. */
+  jobjectArray NewObjectArray(jsize length, jclass cls, jobject init) const
+    {
+      jobjectArray array = m_env->NewObjectArray(length, cls, init);
+      check_java_exception();
+      if (!array)
+        throw std::runtime_error(_("Could not create Object array"));
+      return array;
+    }
+
+  /** Wrapped JNI function. */
+  jobject GetObjectArrayElement(jobjectArray array, jsize index) const
+    {
+      jobject obj = m_env->GetObjectArrayElement(array, index);
+      check_java_exception();
+      return obj;
+    }
+
+  /** Wrapped JNI function. */
+  void SetObjectArrayElement(jobjectArray array,
+                             jsize index, jobject value) const
+    {
+      m_env->SetObjectArrayElement(array, index, value);
+      check_java_exception();
+    }
+
+  /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(T, N)                \
+  T##Array New##N##Array(jsize length) const                            \
+    {                                                                   \
+      T##Array array = m_env->New##N##Array(length);                    \
+      check_java_exception();                                           \
+      if (!array)                                                       \
+        throw_java_out_of_memory(_("Could not create "#T" array"));     \
+      return array;                                                     \
+    }                                                                   \
+  T* Get##N##ArrayElements(T##Array array, jboolean* is_copy) const     \
+    {                                                                   \
+      T* data = m_env->Get##N##ArrayElements(array, is_copy);           \
+      check_java_exception();                                           \
+      if (!data)                                                        \
+        throw std::runtime_error(                                       \
+            _("Could not get "#T" array contents"));                    \
+      return data;                                                      \
+    }                                                                   \
+  void Release##N##ArrayElements(T##Array array, T* data, jint mode) const \
+    {                                                                   \
+      m_env->Release##N##ArrayElements(array, data, mode);              \
+      check_java_exception();                                           \
+    }
+
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jboolean, Boolean)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jbyte, Byte)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jchar, Char)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jshort, Short)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jint, Int)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jlong, Long)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jfloat, Float)
+  SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY
+
+private:
+  ::JNIEnv* m_env;
+
+  JNIEXPORT jint JNICALL friend ::JNI_OnLoad(::JavaVM*, void*);
+  static ::JavaVM* m_jvm;
+  static ::JNIEnv* env_from_jvm();
+
+  void throw_java_exception() const
+    {
+      throw ::JavaHL::JavaException();
+    }
+
+  void check_java_exception() const
+    {
+      if (m_env->ExceptionCheck())
+        throw ::JavaHL::JavaException();
+    }
+
+  void throw_java_out_of_memory(const char* message) const;
+};
+
+
+/**
+ * Encapsulation of a JNI local frame.
+ *
+ * Used within loop bodies to limit the proliferation of local
+ * references, or anywhere else where such references should be
+ * pre-emptively discarded.
+ *
+ * @since New in 1.9.
+ */
+class LocalFrame
+{
+  static const jint DEFAULT_CAPACITY;
+
+public:
+  /**
+   * Constructs a local frame, retreiving the JNI environment
+   * reference from the global JVM reference.
+   */
+  explicit LocalFrame()
+    : m_env(Env())
+    {
+      m_env.PushLocalFrame(DEFAULT_CAPACITY);
+    }
+
+  /**
+   * Given a JNI renvironment reference, constructs a local frame.
+   */
+  explicit LocalFrame(Env env)
+    : m_env(env)
+    {
+      m_env.PushLocalFrame(DEFAULT_CAPACITY);
+    }
+
+  /**
+   * Constructs a local frame with the given initial @a capacity,
+   * retreiving the JNI environment reference from the global JVM
+   * reference.
+   */
+  explicit LocalFrame(jint capacity)
+    : m_env(Env())
+    {
+      m_env.PushLocalFrame(capacity);
+    }
+
+  /**
+   * Given a JNI renvironment reference, constructs a local frame with
+   * the given initial @a capacity.
+   */
+  explicit LocalFrame(Env env, jint capacity)
+    : m_env(env)
+    {
+      m_env.PushLocalFrame(capacity);
+    }
+
+  ~LocalFrame()
+    {
+      m_env.PopLocalFrame();
+    }
+
+  /**
+   * Returns the stored enviromnent object.
+   */
+  Env get_env() const
+    {
+      return m_env;
+    }
+
+private:
+  const Env m_env;
+  LocalFrame(const LocalFrame&);
+  LocalFrame& operator=(const LocalFrame&);
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_ENV_HPP

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,211 @@
+/**
+ * @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_JNIWRAPPER_EXCEPTION_HPP
+#define SVN_JAVAHL_JNIWRAPPER_EXCEPTION_HPP
+
+#include "jni_env.hpp"
+#include "jni_object.hpp"
+#include "jni_javahl_exception.hpp"
+
+namespace Java {
+
+/**
+ * Base class for all exception generators, and generator class for
+ * exceptions of type @c java.lang.Throwable.
+ *
+ * The associated JNI class reference is stored for the lifetime of
+ * the JVM in the global class cache.
+ *
+ * @since New in 1.9.
+ */
+class Exception : public Object
+{
+public:
+  /**
+   * Constructs a wrapper for the @c jthrowable object @a exc.
+   */
+  explicit Exception(Env env, jthrowable exc)
+    : Object(env, exc)
+    {}
+
+  /**
+   * Raises a Java exception of the concrete class, and throws a
+   * native exception at the same time.
+   *
+   * It is an error to call this method if an existing @c jthrowable
+   * object was wrapped.
+   */
+  void raise() const
+    {
+      throw_java_exception();
+      throw ::JavaHL::JavaException();
+    }
+
+  /**
+   * Raises a Java exception of the concrete class with the givem
+   * @a message, and throws a native exception at the same time.
+   *
+   * It is an error to call this method if an existing @c jthrowable
+   * object was wrapped.
+   */
+  void raise(const char* message) const
+    {
+      throw_java_exception(message);
+      throw ::JavaHL::JavaException();
+    }
+
+  /**
+   * Raises a Java exception of the concrete class, but does not throw
+   * a native exception.
+   *
+   * It is an error to call this method if an existing @c jthrowable
+   * object was wrapped.
+   */
+  void throw_java_exception() const
+    {
+      if (instantiated()
+          ? m_env.Throw(throwable())
+          : m_env.ThrowNew(m_class, NULL))
+        throw std::runtime_error(_("Could not throw Java exception"));
+    }
+
+  /**
+   * Raises a Java exception of the concrete class with the given
+   * @a message, but does not throw a native exception.
+   *
+   * It is an error to call this method if an existing @c jthrowable
+   * object was wrapped.
+   */
+  void throw_java_exception(const char* message) const
+    {
+      if (m_env.ThrowNew(m_class, message))
+        throw std::runtime_error(_("Could not throw Java exception"));
+    }
+
+  /**
+   * Checks if an existing @c jthrowable object was wrapped.
+   */
+  bool instantiated() const
+    {
+      return (m_jthis != NULL);
+    }
+
+  /**
+   * Returns the wrapped @c jthrowable object.
+   */
+  jthrowable throwable() const
+    {
+      return jthrowable(Object::get());
+    }
+
+  /**
+   * Wrapper for the Java method @c getMessage().
+   * Only valid if an existing @c jthrowable object was wrapped.
+   */
+  jstring get_message() const;
+
+protected:
+  /**
+   * Constructs an exception generator with the concrete class
+   * @a class_name.
+   */
+  explicit Exception(Env env, const char* class_name)
+    : Object(env, class_name, NULL)
+    {}
+
+  /**
+   * Constructs an exception generator with the concrete class @a cls.
+   */
+  explicit Exception(Env env, jclass cls)
+    : Object(env, cls, NULL)
+    {}
+
+private:
+  friend class ClassCache;
+  static void static_init(Env env);
+  static const char* const m_class_name;
+  static jmethodID m_mid_get_message;
+};
+
+/**
+ * Generator class for exceptions of type @c java.lang.RuntimeException.
+ *
+ * @since New in 1.9.
+ */
+class RuntimeException : public Exception
+{
+public:
+  /**
+   * Constructs an exception generator object.
+   */
+  explicit RuntimeException(Env env)
+    : Exception(env, m_class_name)
+    {}
+
+private:
+  static const char* const m_class_name;
+};
+
+/**
+ * Generator class for exceptions of type @c java.lang.NullPointerException.
+ *
+ * @since New in 1.9.
+ */
+class NullPointerException : public Exception
+{
+public:
+  /**
+   * Constructs an exception generator object.
+   */
+  explicit NullPointerException(Env env)
+    : Exception(env, m_class_name)
+    {}
+
+private:
+  static const char* const m_class_name;
+};
+
+/**
+ * Generator class for exceptions of type @c java.lang.OutOfMemoryError.
+ *
+ * @since New in 1.9.
+ */
+class OutOfMemoryError : public Exception
+{
+public:
+  /**
+   * Constructs an exception generator object.
+   */
+  explicit OutOfMemoryError(Env env)
+    : Exception(env, m_class_name)
+    {}
+
+private:
+  static const char* const m_class_name;
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_ENV_HPP

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_globalref.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_globalref.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_globalref.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_globalref.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,90 @@
+/**
+ * @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_JNIWRAPPER_GLOBALREF_HPP
+#define SVN_JAVAHL_JNIWRAPPER_GLOBALREF_HPP
+
+#include <jni.h>
+
+#include "jni_env.hpp"
+
+namespace Java {
+
+/**
+ * Wrapper for a global object reference. The reference is held until
+ * the wrapper goes out of scope (i.e., until the destructor is called).
+ *
+ * @since New in 1.9.
+ */
+class GlobalObject
+{
+public:
+  explicit GlobalObject(Env env, jobject obj)
+    : m_obj(env.NewGlobalRef(obj))
+    {}
+
+  ~GlobalObject();
+
+  GlobalObject& operator=(jobject that);
+
+  jobject get() const
+    {
+      return m_obj;
+    }
+
+private:
+  GlobalObject(const GlobalObject&);
+  GlobalObject& operator=(const GlobalObject&);
+
+  jobject m_obj;
+};
+
+/**
+ * Wrapper for a global class reference. Behaves just like the object
+ * reference wrapper, but provides a more type-safe interface for
+ * class references.
+ *
+ * @since New in 1.9.
+ */
+class GlobalClass : protected GlobalObject
+{
+public:
+  explicit GlobalClass(Env env, jclass cls)
+    : GlobalObject(env, cls)
+    {}
+
+  GlobalClass& operator=(jclass that);
+
+  jclass get() const
+    {
+      return jclass(GlobalObject::get());
+    }
+
+private:
+  GlobalClass(const GlobalClass&);
+  GlobalClass& operator=(const GlobalClass&);
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_GLOBALREF_HPP

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,70 @@
+/**
+ * @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_JNIWRAPPER_JAVAHL_EXCEPTION_HPP
+#define SVN_JAVAHL_JNIWRAPPER_JAVAHL_EXCEPTION_HPP
+
+#include <exception>
+#include <stdexcept>
+
+namespace Java {
+class Env;                      // Forward declaration; see below.
+} // namespace Java
+
+namespace JavaHL {
+
+/**
+ * A C++ exception object for signalling that a Java exception has
+ * been thrown.
+ *
+ * Thrown to unwind the stack while avoiding code clutter when a Java
+ * exception is detected in the JNI environment.
+ *
+ * @since New in 1.9.
+ */
+class JavaException : public std::exception
+{
+public:
+  explicit JavaException()
+    {}
+
+  virtual ~JavaException() throw();
+
+  virtual const char* what() const throw();
+
+  /**
+   * Returns a local reference to the Java exception object,
+   * retreiving the JNI environment reference from the global JVM
+   * reference.
+   */
+  jthrowable get_java_exception() const;
+
+  /**
+   * Returns a local reference to the Java exception object.
+   */
+  jthrowable get_java_exception(const ::Java::Env& env) const;
+};
+
+} // namespace JavaHL
+
+#endif // SVN_JAVAHL_JNIWRAPPER_JAVAHL_EXCEPTION_HPP

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,49 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#include "jni_list.hpp"
+
+namespace Java {
+
+const char* const BaseList::m_class_name = "java/util/List";
+
+BaseList::ovector
+BaseList::convert_to_vector(Env env, jclass cls, jobject jlist)
+{
+  const size_type length = size_type(
+      env.CallIntMethod(jlist, env.GetMethodID(cls, "size", "()I")));
+
+  if (!length)
+    return ovector();
+
+  const jmethodID mid_get = env.GetMethodID(cls, "get",
+                                            "(I)Ljava/lang/Object;");
+  ovector contents(length);
+  ovector::iterator it;
+  jint i;
+  for (i = 0, it = contents.begin(); it != contents.end(); ++it, ++i)
+    *it = env.CallObjectMethod(jlist, mid_get, i);
+  return contents;
+}
+
+} // namespace Java

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,104 @@
+/**
+ * @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_JNIWRAPPER_LIST_HPP
+#define SVN_JAVAHL_JNIWRAPPER_LIST_HPP
+
+#include <vector>
+
+#include "jni_env.hpp"
+#include "jni_object.hpp"
+
+namespace Java {
+
+/**
+ * Non-template base for an immutable type-safe Java list.
+ *
+ * Converts the list to a @c std::vector of @c jobject references.
+ *
+ * @since New in 1.9.
+ */
+class BaseList : public Object
+{
+  typedef std::vector<jobject> ovector;
+
+public:
+  typedef ovector::size_type size_type;
+
+  /**
+   * Returns the number of elements in the list.
+   */
+  size_type length() const
+    {
+      return m_contents.size();
+    }
+
+protected:
+  explicit BaseList(Env env, jobject jlist)
+    : Object(env, m_class_name, jlist),
+      m_contents(convert_to_vector(env, m_class, m_jthis))
+    {}
+
+  /**
+   * Returns the object reference at @a index.
+   */
+  jobject operator[](ovector::size_type index) const
+    {
+      return m_contents[index];
+    }
+
+private:
+  static const char* const m_class_name;
+  static ovector convert_to_vector(Env env, jclass cls, jobject jlist);
+  const ovector m_contents;
+};
+
+/**
+ * Template wrapper for an immutable type-safe Java list.
+ *
+ * @since New in 1.9.
+ */
+template <typename T>
+class List : public BaseList
+{
+public:
+  /**
+   * Constructs the list wrapper, converting the contents to an
+   * @c std::vector.
+   */
+  explicit List(Env env, jobject jlist)
+    : BaseList(env, jlist)
+    {}
+
+  /**
+   * Returns a wrapper object for the object reference at @a index.
+   */
+  T operator[](size_type index) const
+    {
+      return T(m_env, BaseList::operator[](index));
+    }
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_LIST_HPP

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

Added: 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=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_object.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,344 @@
+/**
+ * @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_JNIWRAPPER_OBJECT_HPP
+#define SVN_JAVAHL_JNIWRAPPER_OBJECT_HPP
+
+#include <string>
+
+#include "jni_env.hpp"
+#include "jni_globalref.hpp"
+
+namespace Java {
+
+/**
+ * An abstract wrapper for a @c java.lang.Object instance.
+ *
+ * This is the base class for all concrete object wrapper classes. It
+ * is self-contained in the sense that it heeps its own JVM
+ * environment, class and object reference; Java object methods are
+ * expected to be exposed as methods of derived classes.
+ *
+ * The associated JNI class reference is stored for the lifetime of
+ * the JVM in the global class cache.
+ *
+ * @since New in 1.9.
+ */
+class Object
+{
+public:
+  /**
+   * Returns the wrapped JNI object reference.
+   */
+  jobject get() const
+    {
+      return m_jthis;
+    }
+
+  /**
+   * Returns the wrapped JNI class reference.
+   */
+  jclass get_class() const
+    {
+      return m_class;
+    }
+
+  /**
+   * Returns the wrapped enviromnment reference.
+   */
+  Env get_env() const
+    {
+      return m_env;
+    }
+
+protected:
+  /**
+   * Constructs an object wrapper given the @a class_name and an
+   * object reference @a jthis.
+   */
+  Object(Env env, const char* class_name, jobject jthis)
+    : m_env(env),
+      m_class(env.FindClass(class_name)),
+      m_jthis(jthis)
+    {}
+
+  /**
+   * Constructs an object wrapper given a class reference @a cls and
+   * an object reference @a jthis.
+   */
+  Object(Env env, jclass cls, jobject jthis)
+    : m_env(env),
+      m_class(cls),
+      m_jthis(jthis)
+    {}
+
+  /**
+   * Constructs an object wrapper given an object reference @a jthis
+   * and derives the class reference from it.
+   */
+  Object(Env env, jobject jthis)
+    : m_env(env),
+      m_class(env.GetObjectClass(jthis)),
+      m_jthis(jthis)
+    {}
+
+  const Env m_env;        ///< JVM environment wrapper
+  const jclass m_class;   ///< Class reference for this object wrapper
+  const jobject m_jthis;  ///< @c this object reference
+
+private:
+  friend class ClassCache;
+  static const char* const m_class_name;
+};
+
+/**
+ * A singleton cache for global class references.
+ *
+ * The instance is created when the native library is loaded by the
+ * JVM, and destroyed when it is unloaded. It creates global
+ * references for a number of classes and calls said classes'
+ * single-threded static initializers, which usually find and store
+ * method and field IDs (which are usually only valid until the
+ * associated class is garbage-collected).
+ *
+ * Be aware that as long as the global references exist, these classes
+ * cannot be garbage-collected. The number of classes stored in this
+ * cache should therefore be kept to a reasonable minimum.
+ *
+ * @since New in 1.9.
+ */
+class ClassCache
+{
+  JNIEXPORT jint JNICALL friend ::JNI_OnLoad(::JavaVM*, void*);
+  JNIEXPORT void JNICALL friend ::JNI_OnUnload(::JavaVM*, void*);
+  explicit ClassCache(Env env);
+  ~ClassCache();
+
+  static const ClassCache* m_instance;
+
+#define SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS(N)   \
+ private:                                       \
+   GlobalClass m_##N;                           \
+ public:                                        \
+  static jclass get_##N()                       \
+  {                                             \
+    return m_instance->m_##N.get();             \
+  }                                             \
+
+  SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS(object);
+  SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS(classtype);
+  SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS(throwable);
+  SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS(string);
+  SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS(subversion_exception);
+#undef SVN_JAVAHL_JNIWRAPPER_CACHED_CLASS
+};
+
+
+/**
+ * Object wrapper for @c java.lang.Class.
+ *
+ * The associated JNI class reference is stored for the lifetime of
+ * the JVM in the global class cache.
+ *
+ * @since New in 1.9.
+ */
+class Class : public Object
+{
+public:
+  /**
+   * Constructs class instance wrapper for @a obj.
+   */
+  explicit Class(Env env, jobject obj);
+
+  /**
+   * Constructs class instance wrapper for @a obj.
+   */
+  explicit Class(const Object& obj);
+
+  /**
+   * Wrapper for the Java @c getName() method.
+   */
+  jstring get_name() const;
+
+private:
+  friend class ClassCache;
+  static void static_init(Env env);
+  static const char* const m_class_name;
+  static jmethodID m_mid_get_class;
+  static jmethodID m_mid_get_name;
+};
+
+
+/**
+ * Object wrapper for @c java.lang.String.
+ *
+ * The associated JNI class reference is stored for the lifetime of
+ * the JVM in the global class cache.
+ *
+ * @since New in 1.9.
+ */
+class String : public Object
+{
+public:
+  /**
+   * onstructs a wrapper around an existing string @a str.
+   */
+  explicit String(Env env, jstring str)
+    : Object(env, ClassCache::get_string(), str)
+    {}
+
+  /**
+   * Constructs a new string and wrapper from @a text.
+   */
+  explicit String(Env env, const char* text)
+    : Object(env, ClassCache::get_string(), env.NewStringUTF(text))
+    {}
+
+  /**
+   * Returns the wrapped JNI object reference. Overridden from the
+   * base class in order to return the correct JNI reference type.
+   */
+  jstring get() const
+    {
+      return jstring(Object::get());
+    }
+
+  /**
+   * Returns the number of Unicode characters in the string.
+   */
+  jsize length() const
+    {
+      return m_env.GetStringLength(get());
+    }
+
+  /**
+   * Returns the length of the modified UTF-8 representation of the
+   * string.
+   */
+  jsize utf8_length() const
+    {
+      return m_env.GetStringUTFLength(get());
+    }
+
+  /**
+   * Accessor class for the contents of the string.
+   *
+   * Objects of this class should be created within the scope where
+   * the raw C string is required. They will create either a mutable
+   * or an immutable modified UTF-8 representation of the string
+   * contents, depending on the constantness of the string
+   * wrapper. The data will be released (and changes copied into the
+   * JVM, depending on access mode) by the destructor.
+   */
+  class Contents
+  {
+  public:
+    /**
+     * Constructs a mutable string contents accessor.
+     */
+    explicit Contents(String& str)
+      : m_str(str),
+        m_text(!str.get() ? NULL
+               : str.m_env.GetStringUTFChars(str.get(), NULL)),
+        m_new_text(NULL),
+        m_mutable(true),
+        m_length(m_text ? jsize(::strlen(m_text)) : 0)
+      {}
+
+    /**
+     * Constructs an immutable string contents accessor.
+     */
+    explicit Contents(const String& str)
+      : m_str(str),
+        m_text(!str.get() ? NULL
+               : str.m_env.GetStringUTFChars(str.get(), NULL)),
+        m_new_text(NULL),
+        m_mutable(false),
+        m_length(m_text ? jsize(::strlen(m_text)) : 0)
+      {}
+
+    /**
+     * Releases the string contents, possibly committing changes to the JVM.
+     */
+    ~Contents()
+      {
+        if (m_text)
+          m_str.m_env.ReleaseStringUTFChars(m_str.get(), m_new_text);
+      }
+
+    /**
+     * Returns the C representation of the string contents.
+     */
+    const char* c_str() const
+      {
+        if (m_new_text)
+          return m_new_text;
+        return m_text;
+      }
+
+    /**
+     * Returns the length of the C representation of the string.
+     */
+    jsize utf8_length() const
+      {
+        return m_length;
+      }
+
+    /**
+     * Sets a new value for the string, to be committed to the JVM
+     * when the accessor object is destroyed.
+     * @throw std::logic_error if this is a @c null or immutable string.
+     */
+    void set_value(const char* new_text)
+      {
+        if (m_text && m_mutable)
+          {
+            m_new_text = new_text;
+            m_length = jsize(::strlen(new_text));
+          }
+        else if (!m_mutable)
+          throw std::logic_error(
+              _("Cannot change the contents of an immutable String"));
+        else
+          throw std::logic_error(
+              _("Cannot change the contents of a null String"));
+      }
+
+  private:
+    const String& m_str;
+    const char* m_text;
+    const char* m_new_text;
+    const bool m_mutable;
+    jsize m_length;
+  };
+
+private:
+  friend class Contents;
+  friend class ClassCache;
+  static void static_init(Env env);
+  static const char* const m_class_name;
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_OBJECT_HPP

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

Added: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp?rev=1539114&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp Tue Nov  5 19:59:44 2013
@@ -0,0 +1,104 @@
+/**
+ * @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_JNIWRAPPER_STACK_HPP
+#define SVN_JAVAHL_JNIWRAPPER_STACK_HPP
+
+#include "../JNIStackElement.h"
+#include "jni_env.hpp"
+#include "jni_exception.hpp"
+
+/**
+ * Boilerplate for the native method implementation entry point.
+ *
+ * Every native method implementation should start by invoking this
+ * macro to initialize the logging stack element and begin the
+ * try/catch block of the function body.
+ *
+ * @param C The name of the Java class that declares this method.
+ * @param M The (Java) name of the method
+ *
+ * This macro expects two additional parameters to be available
+ * (either as function arguments or local variables):
+ * @c JNIEnv* @a jenv and @c jobject @a jthis.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_JNI_TRY(C, M)                                \
+  ::JNIStackElement st_ac_ke_le_me_nt_(jenv, #C, #M, jthis);    \
+  try
+/**
+ * Boilerplate for the native method implementation entry point.
+ *
+ * Like SVN_JAVAHL_JNI_TRY, but for static methods where the @c jthis
+ * argument is not available.
+ *
+ * This macro expects two additional parameters to be available
+ * (either as function arguments or local variables):
+ * @c JNIEnv* @a jenv and @c jclass @a jclazz.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_JNI_TRY_STATIC(C, M)                         \
+  ::JNIStackElement st_ac_ke_le_me_nt_(jenv, #C, #M, jclazz);   \
+  try
+
+/**
+ * Boilerplate for the native method implementation exit point.
+ *
+ * Every native method implementation should end by invoking this
+ * macro to close the try/catch block of the function body and handle
+ * any exceptions thrown by the method implementation.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_JNI_CATCH                                            \
+  catch (const ::JavaHL::JavaException&)                                \
+    {}                                                                  \
+  catch (const ::std::exception& ex)                                    \
+    {                                                                   \
+      ::Java::RuntimeException(::Java::Env(jenv))                       \
+        .throw_java_exception(ex.what());                               \
+    }                                                                   \
+  catch (...)                                                           \
+    {                                                                   \
+      ::Java::RuntimeException(::Java::Env(jenv))                       \
+        .throw_java_exception(_("Caught unknown C++ exception"));       \
+    }
+
+/**
+ * Invocation wrapper for functions that return an @c svn_error_t *.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_CHECK(e)                             \
+  do {                                                  \
+    svn_error_t* javahl__err__temp = (e);               \
+    if (javahl__err__temp)                              \
+      {                                                 \
+        JNIUtil::handleSVNError(javahl__err__temp);     \
+        throw JavaHL::JavaException();                  \
+    }                                                   \
+  } while(0)
+
+#endif // SVN_JAVAHL_JNIWRAPPER_STACK_HPP

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



Mime
View raw message