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/11/21 01:22:34 UTC
svn commit: r1543993 - in /subversion/branches/javahl-1.8-extensions: ./
subversion/bindings/javahl/ subversion/bindings/javahl/native/
subversion/bindings/javahl/native/jniwrapper/
subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversio...
Author: brane
Date: Thu Nov 21 00:22:33 2013
New Revision: 1543993
URL: http://svn.apache.org/r1543993
Log:
On the javahl-1.8-extensions branch: Sync JavaHL with trunk to r1543991.
Added:
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/NativeStream.cpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/NativeStream.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/NativeStream.hpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/NativeStream.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_io_stream.cpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_io_stream.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_io_stream.hpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_io_stream.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_string_map.cpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_string_map.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_string_map.hpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_string_map.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_SubstLib.cpp
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_SubstLib.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeInputStream.java
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeInputStream.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeOutputStream.java
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeOutputStream.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/SubstLib.java
- copied unchanged from r1543991, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/SubstLib.java
Removed:
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_javahl_exception.hpp
Modified:
subversion/branches/javahl-1.8-extensions/build.conf
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/ (props changed)
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/ExternalItem.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.h
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/SVNClient.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
Modified: subversion/branches/javahl-1.8-extensions/build.conf
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/build.conf?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/build.conf (original)
+++ subversion/branches/javahl-1.8-extensions/build.conf Thu Nov 21 00:22:33 2013
@@ -58,6 +58,8 @@ private-built-includes =
subversion/bindings/javahl/include/org_apache_subversion_javahl_Path.h
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_NativeInputStream.h
+ subversion/bindings/javahl/include/org_apache_subversion_javahl_types_NativeOutputStream.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
@@ -75,6 +77,7 @@ private-built-includes =
subversion/bindings/javahl/include/org_apache_subversion_javahl_util_ConfigLib.h
subversion/bindings/javahl/include/org_apache_subversion_javahl_util_DiffLib.h
subversion/bindings/javahl/include/org_apache_subversion_javahl_util_PropLib.h
+ subversion/bindings/javahl/include/org_apache_subversion_javahl_util_SubstLib.h
test-scripts =
subversion/tests/cmdline/*_tests.py
Propchange: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/bindings/javahl:r1540992-1543991
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/ExternalItem.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/ExternalItem.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/ExternalItem.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/ExternalItem.cpp Thu Nov 21 00:22:33 2013
@@ -98,7 +98,7 @@ ExternalItem::get_external_item(SVN::Poo
{
svn_wc_external_item2_t* item;
apr_pool_t* const pool = svnpool.getPool();
- SVN_JAVAHL_CHECK(svn_wc_external_item2_create(&item, pool));
+ SVN_JAVAHL_CHECK(m_env, svn_wc_external_item2_create(&item, pool));
item->target_dir = apr_pstrdup(
pool, Java::String::Contents(m_target_dir).c_str());
@@ -135,7 +135,8 @@ jobject Revision::makeJRevision(const sv
{
const jclass cls = env.FindClass(
JAVA_PACKAGE"/types/Revision$DateSpec");
- return env.NewObject(cls, env.GetMethodID(cls, "<init>", "(J)V"));
+ return env.NewObject(cls, env.GetMethodID(cls, "<init>", "(J)V"),
+ jlong(rev.value.date / 1000));
}
const jclass cls = env.FindClass(JAVA_PACKAGE"/types/Revision");
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.cpp Thu Nov 21 00:22:33 2013
@@ -659,7 +659,7 @@ std::string JNIUtil::makeSVNErrorMessage
return buffer;
}
-void JNIUtil::wrappedHandleSVNError(svn_error_t *err)
+void JNIUtil::wrappedHandleSVNError(svn_error_t *err, jthrowable jcause)
{
jstring jmessage;
jobject jstack;
@@ -716,12 +716,14 @@ void JNIUtil::wrappedHandleSVNError(svn_
jmethodID mid = env->GetMethodID(clazz, "<init>",
"(Ljava/lang/String;"
+ "Ljava/lang/Throwable;"
"Ljava/lang/String;I"
"Ljava/util/List;)V");
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
- jobject nativeException = env->NewObject(clazz, mid, jmessage, jsource,
- jint(err->apr_err), jstack);
+ jobject nativeException = env->NewObject(clazz, mid, jmessage, jcause,
+ jsource, jint(err->apr_err),
+ jstack);
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
@@ -792,10 +794,10 @@ void JNIUtil::wrappedHandleSVNError(svn_
env->Throw(static_cast<jthrowable>(env->PopLocalFrame(nativeException)));
}
-void JNIUtil::handleSVNError(svn_error_t *err)
+void JNIUtil::handleSVNError(svn_error_t *err, jthrowable jcause)
{
try {
- wrappedHandleSVNError(err);
+ wrappedHandleSVNError(err, jcause);
} catch (...) {
svn_error_clear(err);
throw;
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.h?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.h (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/JNIUtil.h Thu Nov 21 00:22:33 2013
@@ -121,7 +121,7 @@ class JNIUtil
* Throw a Java exception corresponding to err, and run
* svn_error_clear() on err.
*/
- static void handleSVNError(svn_error_t *err);
+ static void handleSVNError(svn_error_t *err, jthrowable jcause = NULL);
static std::string makeSVNErrorMessage(svn_error_t *err,
jstring *jerror_message,
@@ -158,7 +158,7 @@ class JNIUtil
static JNIMutex *g_configMutex;
private:
- static void wrappedHandleSVNError(svn_error_t *err);
+ static void wrappedHandleSVNError(svn_error_t *err, jthrowable jcause);
static void putErrorsInTrace(svn_error_t *err,
std::vector<jobject> &stackTrace);
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/SVNClient.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/SVNClient.cpp Thu Nov 21 00:22:33 2013
@@ -449,12 +449,7 @@ void SVNClient::copy(CopySources ©So
SVN::Pool subPool(pool);
apr_array_header_t *srcs = copySources.array(subPool);
- if (srcs == NULL)
- {
- JNIUtil::throwNativeException(JAVA_PACKAGE "/ClientException",
- "Invalid copy sources");
- return;
- }
+ SVN_JNI_NULL_PTR_EX(srcs, "sources", );
SVN_JNI_NULL_PTR_EX(destPath, "destPath", );
Path destinationPath(destPath, subPool);
SVN_JNI_ERR(destinationPath.error_occurred(), );
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp Thu Nov 21 00:22:33 2013
@@ -27,7 +27,9 @@
#include "jni_object.hpp"
#include "jni_string.hpp"
#include "jni_array.hpp"
+#include "jni_stack.hpp"
+#include "../JNIUtil.h"
// Global library initializaiton
@@ -193,7 +195,6 @@ void Exception::static_init(Env env)
"getMessage", "()Ljava/lang/String;");
}
-
// Other exception class initializers
const char* const RuntimeException::m_class_name =
@@ -205,32 +206,41 @@ const char* const NullPointerException::
const char* const OutOfMemoryError::m_class_name =
"java/lang/OutOfMemoryError";
+const char* const IndexOutOfBoundsException::m_class_name =
+ "java/lang/IndexOutOfBoundsException";
+
const char* const IOException::m_class_name =
"java/io/IOException";
-} // namespace Java
-
-namespace JavaHL {
+// Implementation of jni_stack.hpp
-// class JavaHL::JavaException
-
-JavaException::~JavaException() throw() {}
-
-const char* JavaException::what() const throw()
+void handle_svn_error(Env env, ::svn_error_t* err)
{
- // FIXME: Implement this?
- return "";
-}
+ jthrowable cause = NULL;
-jthrowable JavaException::get_java_exception() const
-{
- return ::Java::Env().ExceptionOccurred();
-}
+ // If the exception being currently thrown was generated by the
+ // JavaHL bindings, then assume the error was propagated through
+ // native code and do not re-throw it.
+ if (env.ExceptionCheck())
+ {
+ cause = env.ExceptionOccurred();
+ if (env.IsInstanceOf(cause, ClassCache::get_subversion_exception()))
+ {
+ // XXX FIXME: Should really have a special error code
+ // specifically for propagating Java exceptions from
+ // callbacks through native code.
+ svn_error_clear(err);
+ throw SignalExceptionThrown();
+ }
+ }
-jthrowable JavaException::get_java_exception(const ::Java::Env& env) const
-{
- return env.ExceptionOccurred();
+ // Make sure there's only a single exception in the environment.
+ if (cause)
+ env.ExceptionClear();
+
+ ::JNIUtil::handleSVNError(err, cause);
+ throw SignalExceptionThrown();
}
-} // namespace JavaHL
+} // namespace Java
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp Thu Nov 21 00:22:33 2013
@@ -21,6 +21,9 @@
* @endcopyright
*/
+#include <stdexcept>
+
+#define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
#include "jni_env.hpp"
#include "jni_globalref.hpp"
#include "jni_exception.hpp"
@@ -35,7 +38,40 @@ const ClassCache* ClassCache::m_instance
void ClassCache::create()
{
- new ClassCache(Env());
+ const char* exception_message = NULL;
+
+ try
+ {
+ new ClassCache(Env());
+ }
+ catch (const std::exception& ex)
+ {
+ exception_message = ex.what();
+ }
+ catch (...)
+ {
+ exception_message = "Caught unknown C++ exception";
+ }
+
+ // Use the raw environment without exception checks here
+ ::JNIEnv* const jenv = Env().get();
+ if (exception_message || jenv->ExceptionCheck())
+ {
+ const jclass rtx = jenv->FindClass("java/lang/RuntimeException");
+ const jmethodID ctor = jenv->GetMethodID(rtx, "<init>",
+ "(Ljava/lang/String;"
+ "Ljava/lang/Throwable;)V");
+ jobject cause = jenv->ExceptionOccurred();
+ if (!cause && exception_message)
+ {
+ const jstring msg = jenv->NewStringUTF(exception_message);
+ cause = jenv->NewObject(rtx, ctor, msg, jthrowable(0));
+ }
+ const jstring reason =
+ jenv->NewStringUTF("JavaHL native library initialization failed");
+ const jobject exception = jenv->NewObject(rtx, ctor, reason, cause);
+ jenv->Throw(jthrowable(exception));
+ }
}
void ClassCache::destroy()
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp Thu Nov 21 00:22:33 2013
@@ -30,21 +30,30 @@
#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)
+# ifndef SVN_JAVAHL_JNIWRAPPER_LOG
+# include <iostream>
+# define SVN_JAVAHL_JNIWRAPPER_LOG(expr) \
+ (std::cerr << expr << std::endl)
+# endif // SVN_JAVAHL_JNIWRAPPER_LOG
#else
-#define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
+# define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
#endif // SVN_JAVAHL_DEBUG
namespace Java {
/**
+ * 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 SignalExceptionThrown {};
+
+/**
* Auto-initializing proxy for the JNI method ID.
*
* Behaves like a @c jmethodID but automatically initializes to @c NULL.
@@ -214,24 +223,36 @@ public:
}
/** Wrapped JNI function. */
- jint Throw(jthrowable exc) const
+ jint Throw(jthrowable exc) const throw()
{
return m_env->Throw(exc);
}
/** Wrapped JNI function. */
- jint ThrowNew(jclass cls, const char* message) const
+ jint ThrowNew(jclass cls, const char* message) const throw()
{
return m_env->ThrowNew(cls, message);
}
/** Wrapped JNI function. */
+ jboolean ExceptionCheck() const throw()
+ {
+ return m_env->ExceptionCheck();
+ }
+
+ /** Wrapped JNI function. */
jthrowable ExceptionOccurred() const throw()
{
return m_env->ExceptionOccurred();
}
/** Wrapped JNI function. */
+ void ExceptionClear() const throw()
+ {
+ m_env->ExceptionClear();
+ }
+
+ /** Wrapped JNI function. */
jclass FindClass(const char* name) const
{
jclass cls = m_env->FindClass(name);
@@ -259,6 +280,12 @@ public:
}
/** Wrapped JNI function. */
+ jboolean IsInstanceOf(jobject obj, jclass cls) const
+ {
+ return m_env->IsInstanceOf(obj, cls);
+ }
+
+ /** Wrapped JNI function. */
jmethodID GetMethodID(jclass cls, const char* name, const char* sig) const
{
jmethodID mid = m_env->GetMethodID(cls, name, sig);
@@ -524,13 +551,13 @@ private:
void throw_java_exception() const
{
- throw ::JavaHL::JavaException();
+ throw SignalExceptionThrown();
}
void check_java_exception() const
{
if (m_env->ExceptionCheck())
- throw ::JavaHL::JavaException();
+ throw SignalExceptionThrown();
}
void throw_java_out_of_memory(const char* message) const;
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp Thu Nov 21 00:22:33 2013
@@ -27,7 +27,6 @@
#include "jni_env.hpp"
#include "jni_object.hpp"
-#include "jni_javahl_exception.hpp"
namespace Java {
@@ -60,7 +59,7 @@ public:
void raise() const
{
throw_java_exception();
- throw ::JavaHL::JavaException();
+ throw SignalExceptionThrown();
}
/**
@@ -73,7 +72,7 @@ public:
void raise(const char* message) const
{
throw_java_exception(message);
- throw ::JavaHL::JavaException();
+ throw SignalExceptionThrown();
}
/**
@@ -168,6 +167,7 @@ private:
static const char* const m_class_name;
};
+
/**
* Generator class for exceptions of type @c java.lang.NullPointerException.
*
@@ -207,6 +207,26 @@ private:
};
/**
+ * Generator class for exceptions of type
+ * @c java.lang.IndexOutOfBoundsException.
+ *
+ * @since New in 1.9.
+ */
+class IndexOutOfBoundsException : public Exception
+{
+public:
+ /**
+ * Constructs an exception generator object.
+ */
+ explicit IndexOutOfBoundsException(Env env)
+ : Exception(env, m_class_name)
+ {}
+
+private:
+ static const char* const m_class_name;
+};
+
+/**
* Generator class for exceptions of type @c java.io.IOException.
*
* @since New in 1.9.
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.cpp Thu Nov 21 00:22:33 2013
@@ -92,7 +92,7 @@ jint BaseMutableList::length() const
{
if (!m_mid_size)
m_mid_size = m_env.GetMethodID(m_class, "size", "()I");
- return m_env.CallIntMethod(m_jthis, m_mid_add);
+ return m_env.CallIntMethod(m_jthis, m_mid_size);
}
} // namespace Java
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_list.hpp Thu Nov 21 00:22:33 2013
@@ -24,6 +24,7 @@
#ifndef SVN_JAVAHL_JNIWRAPPER_LIST_HPP
#define SVN_JAVAHL_JNIWRAPPER_LIST_HPP
+#include <algorithm>
#include <vector>
#include "jni_env.hpp"
@@ -63,16 +64,18 @@ protected:
/**
* Returns the object reference at @a index.
+ * @throw std::out_of_range if the index value is not valid.
*/
jobject operator[](jint index) const
{
return m_contents[ovector::size_type(index)];
}
+ const ovector m_contents;
+
private:
static const char* const m_class_name;
static ovector convert_to_vector(Env env, jclass cls, jobject jlist);
- const ovector m_contents;
};
/**
@@ -80,7 +83,7 @@ private:
*
* @since New in 1.9.
*/
-template <typename T>
+template <typename T, typename NativeT=jobject>
class List : public BaseList
{
public:
@@ -94,11 +97,44 @@ public:
/**
* Returns a wrapper object for the object reference at @a index.
+ * @throw std::out_of_range if the index value is not valid.
*/
T operator[](jint index) const
{
- return T(m_env, BaseList::operator[](index));
+ return T(m_env, NativeT(BaseList::operator[](index)));
+ }
+
+ /**
+ * Iterates over the items in the list, calling @a function for
+ * each item.
+ * @see std::for_each
+ */
+ template<typename F>
+ F for_each(F function) const
+ {
+ const FunctorAdapter<F> adapter(m_env, function);
+ std::for_each(m_contents.begin(), m_contents.end(), adapter);
+ return function;
}
+
+private:
+ template<typename F>
+ struct FunctorAdapter
+ {
+ explicit FunctorAdapter(const Env& env, F& function)
+ : m_env(env),
+ m_function(function)
+ {}
+
+ void operator()(const jobject& obj) const
+ {
+ const T item(m_env, NativeT(obj));
+ m_function(item);
+ }
+
+ const Env& m_env;
+ F& m_function;
+ };
};
/**
@@ -148,6 +184,7 @@ protected:
/**
* Returns the object reference at @a index.
+ * @note Throws a Java exception if the index value is not valid.
*/
jobject operator[](jint index) const;
@@ -164,7 +201,7 @@ private:
*
* @since New in 1.9.
*/
-template <typename T>
+template <typename T, typename NativeT=jobject>
class MutableList : public BaseMutableList
{
public:
@@ -179,8 +216,8 @@ public:
* Constructs and wraps an empty list of type @c java.util.ArrayList
* with initial allocation size @a length.
*/
- explicit MutableList(Env env, jint length = 0)
- : BaseMutableList(env, length)
+ explicit MutableList(Env env, jint length_ = 0)
+ : BaseMutableList(env, length_)
{}
/**
@@ -193,10 +230,11 @@ public:
/**
* Returns a wrapper object for the object reference at @a index.
+ * @note Throws a Java exception if the index value is not valid.
*/
T operator[](jint index) const
{
- return T(m_env, BaseMutableList::operator[](index));
+ return T(m_env, NativeT(BaseMutableList::operator[](index)));
}
};
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/jniwrapper/jni_stack.hpp Thu Nov 21 00:22:33 2013
@@ -24,10 +24,22 @@
#ifndef SVN_JAVAHL_JNIWRAPPER_STACK_HPP
#define SVN_JAVAHL_JNIWRAPPER_STACK_HPP
+#ifdef SVN_JAVAHL_DEBUG
+# ifndef SVN_JAVAHL_ASSERT_EXCEPTION_THROWN
+# include <cassert>
+# define SVN_JAVAHL_ASSERT_EXCEPTION_THROWN(E) \
+ assert((E).ExceptionCheck())
+# endif // SVN_JAVAHL_ASSERT_EXCEPTION_THROWN
+#else
+# define SVN_JAVAHL_ASSERT_EXCEPTION_THROWN(E)
+# endif // SVN_JAVAHL_DEBUG
+
#include "../JNIStackElement.h"
#include "jni_env.hpp"
#include "jni_exception.hpp"
+#include "svn_error.h"
+
/**
* Boilerplate for the native method implementation entry point.
*
@@ -36,7 +48,7 @@
* 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
+ * @param M The (Java) name of the method.
*
* This macro expects two additional parameters to be available
* (either as function arguments or local variables):
@@ -47,10 +59,22 @@
#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.
+ *
+ * Initializes local variable named @a V as a pointer to an instance
+ * of the native-bound class @a C.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_GET_BOUND_OBJECT(C, V) \
+ C* const V = C::get_self(::Java::Env(jenv), jthis)
+
/**
* Boilerplate for the native method implementation entry point.
*
- * Like SVN_JAVAHL_JNI_TRY, but for static methods where the @c jthis
+ * 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
@@ -63,6 +87,7 @@
::JNIStackElement st_ac_ke_le_me_nt_(jenv, #C, #M, jclazz); \
try
+
/**
* Boilerplate for the native method implementation exit point.
*
@@ -70,35 +95,97 @@
* macro to close the try/catch block of the function body and handle
* any exceptions thrown by the method implementation.
*
+ * This boilerplate variant converts C++ exceptions to the Java
+ * exception type @a X, but retains exceptions that are already in
+ * progress.
+ *
* @since New in 1.9.
*/
-#define SVN_JAVAHL_JNI_CATCH \
- catch (const ::JavaHL::JavaException&) \
- {} \
+#define SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(X) \
+ catch (const ::Java::SignalExceptionThrown&) \
+ { \
+ SVN_JAVAHL_ASSERT_EXCEPTION_THROWN(::Java::Env(jenv)); \
+ } \
catch (const ::std::exception& ex) \
{ \
- ::Java::RuntimeException(::Java::Env(jenv)) \
- .throw_java_exception(ex.what()); \
+ X(::Java::Env(jenv)).throw_java_exception(ex.what()); \
} \
catch (...) \
{ \
- ::Java::RuntimeException(::Java::Env(jenv)) \
+ X(::Java::Env(jenv)) \
.throw_java_exception(_("Caught unknown C++ exception")); \
}
/**
+ * Boilerplate for the native method implementation exit point.
+ *
+ * Invokes #SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION to throw a
+ * @c RuntimeException.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_JNI_CATCH \
+ SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(::Java::RuntimeException)
+
+/**
* Invocation wrapper for functions that return an @c svn_error_t *.
*
+ * @param E A wrapped environment (@c Java::Env) instance.
+ * @param S The statement to execute in the checked context.
+ *
* @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(); \
- } \
+#define SVN_JAVAHL_CHECK(E, S) \
+ do { \
+ svn_error_t* const ja_va_hl_err_te_mp_ = (S); \
+ if (ja_va_hl_err_te_mp_) \
+ ::Java::handle_svn_error((E), ja_va_hl_err_te_mp_); \
} while(0)
+/**
+ * Invocation wrapper for calling Java methods that may throw an
+ * exception from within a native callback that is expected to return
+ * an @c svn_error_t*.
+ *
+ * @param E A wrapped environment (@c Java::Env) instance.
+ * @param C A Subversion or APR error code.
+ * @param S The statement to execute in the checked context.
+ *
+ * @since New in 1.9.
+ */
+#define SVN_JAVAHL_CATCH(E, C, S) \
+ try \
+ { \
+ S; \
+ } \
+ catch (const ::Java::SignalExceptionThrown&) \
+ { \
+ SVN_JAVAHL_ASSERT_EXCEPTION_THROWN((E)); \
+ return svn_error_create((C), NULL, _("Java exception")); \
+ } \
+ catch (const ::std::exception& ex) \
+ { \
+ const char* const msg = ex.what(); \
+ ::Java::RuntimeException((E)).throw_java_exception(msg); \
+ return svn_error_create((C), NULL, msg); \
+ } \
+ catch (...) \
+ { \
+ const char* const msg = _("Caught unknown C++ exception"); \
+ ::Java::RuntimeException((E)).throw_java_exception(msg); \
+ return svn_error_create((C), NULL, msg); \
+ }
+
+namespace Java {
+
+/**
+ * Handle an error @a err returned from a native function and throws
+ * an appropriate Java exception.
+ *
+ * @since New in 1.9.
+ */
+void handle_svn_error(Env env, svn_error_t* err);
+
+} // namespace Java
+
#endif // SVN_JAVAHL_JNIWRAPPER_STACK_HPP
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp Thu Nov 21 00:22:33 2013
@@ -199,6 +199,82 @@ inline bool operator!=(const svn_opt_rev
{
return !(a == b);
}
+
+class UnparseFunctor
+{
+public:
+ explicit UnparseFunctor(std::ostringstream& buffer, bool old_format,
+ SVN::Pool& iterpool)
+ : m_buffer(buffer),
+ m_old_format(old_format),
+ m_iterpool(iterpool)
+ {}
+
+ void operator()(const JavaHL::ExternalItem& item)
+ {
+ m_iterpool.clear();
+
+ const Java::Env env(item.get_env());
+ const Java::LocalFrame frame(env);
+
+ if (!m_old_format)
+ {
+ if (item.revision()->kind != svn_opt_revision_head
+ && *item.revision() != *item.peg_revision())
+ {
+ m_buffer << "-r"
+ << FormatRevision(item.revision(), m_iterpool)
+ << ' ';
+ }
+ if (item.peg_revision()->kind == svn_opt_revision_head)
+ m_buffer << item.url() << ' ';
+ else
+ {
+ m_buffer << item.url() << '@'
+ << FormatRevision(item.peg_revision(), m_iterpool)
+ << ' ';
+ }
+ m_buffer << item.target_dir() << '\n';
+ }
+ else
+ {
+ // Sanity check: old format does not support peg revisions
+ if (item.peg_revision()->kind != svn_opt_revision_head
+ && *item.revision() != *item.peg_revision())
+ {
+ JavaHL::SubversionException(env)
+ .raise(_("Clients older than Subversion 1.5"
+ " do not support peg revision syntax"
+ " in the svn:externals property"));
+ }
+
+ // Sanity check: old format does not support relative URLs
+ const std::string url = item.url();
+ if ( (url.size() >= 1 && (url[0] == '.' || url[0] == '/'))
+ || (url.size() >= 2 && (url[0] == '^' && url[1] == '/')))
+ {
+ JavaHL::SubversionException(env)
+ .raise(_("Clients older than Subversion 1.5"
+ " do not support relative URLs"
+ " in the svn:externals property"));
+ }
+
+ m_buffer << item.target_dir() << ' ';
+ if (item.revision()->kind != svn_opt_revision_head)
+ {
+ m_buffer << "-r"
+ << FormatRevision(item.revision(), m_iterpool)
+ << ' ';
+ }
+ m_buffer << url << '\n';
+ }
+ }
+
+private:
+ std::ostringstream& m_buffer;
+ const bool m_old_format;
+ SVN::Pool& m_iterpool;
+};
} // anoymous namespace
@@ -226,7 +302,8 @@ Java_org_apache_subversion_javahl_util_P
svn_string_t* const description_contents =
Java::ByteArray::Contents(description).get_string(pool);
- SVN_JAVAHL_CHECK(svn_wc_parse_externals_description3(
+ SVN_JAVAHL_CHECK(env,
+ svn_wc_parse_externals_description3(
&externals,
Java::String::Contents(parent_dir).c_str(),
description_contents->data,
@@ -274,71 +351,13 @@ Java_org_apache_subversion_javahl_util_P
SVN::Pool iterpool;
std::ostringstream buffer;
- const jint items_length = items.length();
- for (jint i = 0; i < items_length; ++i)
- {
- iterpool.clear();
-
- const Java::LocalFrame frame(env);
- const JavaHL::ExternalItem item(items[i]);
-
- if (!jold_format)
- {
- if (item.revision()->kind != svn_opt_revision_head
- && *item.revision() != *item.peg_revision())
- {
- buffer << "-r"
- << FormatRevision(item.revision(), iterpool)
- << ' ';
- }
- if (item.peg_revision()->kind == svn_opt_revision_head)
- buffer << item.url() << ' ';
- else
- {
- buffer << item.url() << '@'
- << FormatRevision(item.peg_revision(), iterpool)
- << ' ';
- }
- buffer << item.target_dir() << '\n';
- }
- else
- {
- // Sanity check: old format does not support peg revisions
- if (item.peg_revision()->kind != svn_opt_revision_head
- && *item.revision() != *item.peg_revision())
- {
- JavaHL::SubversionException(env)
- .raise(_("Clients older than Subversion 1.5"
- " do not support peg revision syntax"
- " in the svn:externals property"));
- }
-
- // Sanity check: old format does not support relative URLs
- const std::string url = item.url();
- if ( (url.size() >= 1 && (url[0] == '.' || url[0] == '/'))
- || (url.size() >= 2 && (url[0] == '^' && url[1] == '/')))
- {
- JavaHL::SubversionException(env)
- .raise(_("Clients older than Subversion 1.5"
- " do not support relative URLs"
- " in the svn:externals property"));
- }
-
- buffer << item.target_dir() << ' ';
- if (item.revision()->kind != svn_opt_revision_head)
- {
- buffer << "-r"
- << FormatRevision(item.revision(), iterpool)
- << ' ';
- }
- buffer << url << '\n';
- }
- }
+ items.for_each(UnparseFunctor(buffer, jold_format, iterpool));
+ const std::string description(buffer.str());
// Validate the result. Even though we generated the string
// ourselves, we did not validate the input paths and URLs.
- const std::string description(buffer.str());
- SVN_JAVAHL_CHECK(svn_wc_parse_externals_description3(
+ SVN_JAVAHL_CHECK(env,
+ svn_wc_parse_externals_description3(
NULL,
Java::String::Contents(parent_dir).c_str(),
description.c_str(),
@@ -368,7 +387,8 @@ Java_org_apache_subversion_javahl_util_P
SVN::Pool pool;
const char* resolved_url;
- SVN_JAVAHL_CHECK(svn_wc__resolve_relative_external_url(
+ SVN_JAVAHL_CHECK(env,
+ svn_wc__resolve_relative_external_url(
&resolved_url,
item.get_external_item(pool),
Java::String::Contents(repos_root_url).c_str(),
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java Thu Nov 21 00:22:33 2013
@@ -79,10 +79,10 @@ public class ClientException extends Nat
* @param messageStack The whole stack of error messages
* @since 1.9
*/
- ClientException(String message, String source, int aprError,
- List<ErrorMessage> messageStack)
+ ClientException(String message, Throwable cause, String source,
+ int aprError, List<ErrorMessage> messageStack)
{
- super(message, source, aprError);
+ super(message, source, cause, aprError);
this.messageStack = messageStack;
}
@@ -96,7 +96,7 @@ public class ClientException extends Nat
*/
ClientException(String message, String source, int aprError)
{
- this(message, source, aprError, null);
+ this(message, null, source, aprError, null);
}
public List<ErrorMessage> getAllMessages()
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Thu Nov 21 00:22:33 2013
@@ -308,6 +308,7 @@ public interface ISVNClient
* @param handler the commit message callback, may be <code>null</code>
* if <code>destPath</code> is not a URL
* @throws ClientException If the copy operation fails.
+ * @throws NullPointerException if the <code>sources</code> list is empty.
*/
void copy(List<CopySource> sources, String destPath,
boolean copyAsChild, boolean makeParents,
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java Thu Nov 21 00:22:33 2013
@@ -58,9 +58,10 @@ class NativeException extends Subversion
* @param aprError Any associated APR error code for a wrapped
* <code>svn_error_t</code>.
*/
- NativeException(String message, String source, int aprError)
+ NativeException(String message, String source, Throwable cause,
+ int aprError)
{
- super(message);
+ super(message, cause);
this.source = source;
this.aprError = aprError;
}
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java Thu Nov 21 00:22:33 2013
@@ -29,7 +29,9 @@ import org.apache.subversion.javahl.util
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Date;
import java.util.List;
+import java.util.Map;
public class SVNUtil
{
@@ -398,6 +400,7 @@ public class SVNUtil
* <dd>relative to the scheme</dd>
* <dt><code>/</code></dt>
* <dd>relative to the server's hostname</dd>
+ * </dl>
*<p>
* The <code>../<code> and ^/ relative URLs may use <code>..<code>
* to remove path elements up to the server root.
@@ -416,4 +419,236 @@ public class SVNUtil
return propLib.resolveExternalsUrl(
external, reposRootUrl, parentDirUrl);
}
+
+ //
+ // Newline translation and keyword expansion
+ //
+ private static final SubstLib substLib = new SubstLib();
+
+ /**
+ * Use the linefeed code point ('<code>\x0a</code>')
+ * for the newline separator.
+ * @see translateStream
+ * @see untranslateStream
+ */
+ public static final byte[] EOL_LF = substLib.EOL_LF;
+
+ /**
+ * Use the carraige-return code point ('<code>\x0d</code>')
+ * for the newline separator.
+ * @see translateStream
+ * @see untranslateStream
+ */
+ public static final byte[] EOL_CR = substLib.EOL_CR;
+
+ /**
+ * Use carriage-return/linefeed sequence ('<code>\x0d\x0a</code>')
+ * for the newline separator.
+ * @see translateStream
+ * @see untranslateStream
+ */
+ public static final byte[] EOL_CRLF = substLib.EOL_CRLF;
+
+
+ /**
+ * Build a dictionary of expanded keyword values, given the
+ * contents of a file's <code>svn:keywords</code> property, its
+ * revision, URL, the date it was committed on, the author of the
+ * commit and teh URL of the repository root.
+ *<p>
+ * Custom keywords defined in <code>svn:keywords</code> properties
+ * are expanded using the provided parameters and in accordance
+ * with the following format substitutions in the
+ * <code>keywordsValue</code>:
+ * <dl>
+ * <dt><code>%a</dt></code>
+ * <dd>The author.</dd>
+ * <dt><code>%b</dt></code>
+ * <dd>The basename of the URL.</dd>
+ * <dt><code>%d</dt></code>
+ * <dd>Short format of the date.</dd>
+ * <dt><code>%D</dt></code>
+ * <dd>Long format of the date.</dd>
+ * <dt><code>%P</dt></code>
+ * <dd>The file's path, relative to the repository root URL.</dd>
+ * <dt><code>%r</dt></code>
+ * <dd>The revision.</dd>
+ * <dt><code>%R</dt></code>
+ * <dd>The URL to the root of the repository.</dd>
+ * <dt><code>%u</dt></code>
+ * <dd>The URL of the file.</dd>
+ * <dt><code>%_</dt></code>
+ * <dd>A space (keyword definitions cannot contain a literal space).</dd>
+ * <dt><code>%%</dt></code>
+ * <dd>A literal '%'.</dd>
+ * <dt><code>%H</dt></code>
+ * <dd>Equivalent to <code>%P%_%r%_%d%_%a</code>.</dd>
+ * <dt><code>%I</dt></code>
+ * <dd>Equivalent to <code>%b%_%r%_%d%_%a</code>.</dd>
+ * </dl>
+ *<p>
+ * Custom keywords are defined by appending '=' to the keyword
+ * name, followed by a string containing any combination of the
+ * format substitutions.
+ *<p>
+ * Any of the <code>revision</code>, <code>url</code>,
+ * <code>reposRootUrl</code>, <code>date</code> and
+ * <code>author</code> parameters may be <code>null</code>, or
+ * {@link Revision#SVN_INVALID_REVNUM} for <code>revision</code>,
+ * to indicate that the information is not present. Each piece of
+ * information that is not present expands to the empty string
+ * wherever it appears in an expanded keyword value. (This can
+ * result in multiple adjacent spaces in the expansion of a
+ * multi-valued keyword such as "<code>Id</code>".)
+ */
+ public static Map<String, byte[]> buildKeywords(byte[] keywordsValue,
+ long revision,
+ String url,
+ String reposRootUrl,
+ Date date,
+ String author)
+ throws SubversionException, ClientException
+ {
+ return substLib.buildKeywords(keywordsValue, revision,
+ url, reposRootUrl, date, author);
+ }
+
+ /**
+ * Return a stream which performs end-of-line translation and
+ * keyword expansion when read from.
+ *<p>
+ * <b>Important:</b> Make sure you close the reurned stream to
+ * ensure all data are flushed and cleaned up (this will also
+ * close the provided stream and dispose the related netive
+ * object).
+ *<p>
+ * If <code>eolMarker</code> is not <code>null</code>, replace
+ * whatever any end-of-line sequences in the input with
+ * <code>eolMarker</code>. If the input has an inconsistent line
+ * ending style, then:
+ * <ul>
+ * <li>if <code>repairEol</code> is <code>false</code>, then a
+ * subsequent read or other operation on the stream will
+ * generate an error when the inconsistency is detected;</li>
+ * <li>if <code>repaorEol</code> is <code>true</code>, convert any
+ * line ending to <code>eolMarker</code>.<br/>
+ * Recognized line endings are: "<code>\n</code>",
+ * "<code>\r</code>", and "<code>\r\n</code>".</li>
+ * </ul>
+ *<p>
+ * Expand or contract keywords using the contents of
+ * <code>keywords</code> as the new values. If
+ * <code>expandKeywords</code> is <code>true</code>, expand
+ * contracted keywords and re-expand expanded keywords; otherwise,
+ * contract expanded keywords and ignore contracted ones.
+ * Keywords not found in the dictionary are ignored (not
+ * contracted or expanded). If the <code>keywords</code> itself
+ * is <code>null</code>, keyword substitution will be altogether
+ * ignored.
+ *<p>
+ * Detect only keywords that are no longer than
+ * <code>SVN_KEYWORD_MAX_LEN</code> bytes (currently: 255),
+ * including the delimiters and the keyword itself.
+ *<p>
+ * Recommendation: if <code>expandKeywords</code> is
+ * <code>false</code>, then you don't care about the keyword
+ * values, so just put <code>null</code> values into the
+ * <code>keywords</code> dictionary.
+ *<p>
+ * If the inner stream implements marking and seeking via
+ * {@link InputStream#mark} and {@link InputStream#reset}, the
+ * translated stream will too.
+ *
+ * @param source the source (untranslated) stream.
+ * @param eolMarker the byte sequence to use as the end-of-line marker;
+ * must be one of {@link #EOL_LF}, {@link #EOL_CR}
+ * or {@link #EOL_CRLF}.
+ * @param repairEol flag to repair end-of-lines; see above
+ * @param keywords the keyword dictionary; see {@link buildKeywords}
+ * @param expandKeywords flag to expand keywords
+ */
+ public static InputStream translateStream(InputStream source,
+ byte[] eolMarker,
+ boolean repairEol,
+ Map<String, byte[]> keywords,
+ boolean expandKeywords)
+ throws SubversionException, ClientException
+ {
+ return substLib.translateInputStream(
+ source, eolMarker, repairEol,
+ keywords, true, expandKeywords,
+ null, Revision.SVN_INVALID_REVNUM,
+ null, null, null, null);
+ }
+
+ /**
+ * Expand keywords and return a stream which performs end-of-line
+ * translation and keyword expansion when read from.
+ * @see buildKeywords
+ * @see translateStream(InputStream,byte[],boolean,Map,boolean)
+ */
+ public static InputStream translateStream(InputStream source,
+ byte[] eolMarker,
+ boolean repairEol,
+ boolean expandKeywords,
+ byte[] keywordsValue,
+ long revision,
+ String url,
+ String reposRootUrl,
+ Date date,
+ String author)
+ throws SubversionException, ClientException
+ {
+ return substLib.translateInputStream(
+ source, eolMarker, repairEol,
+ null, false, expandKeywords,
+ keywordsValue, revision,
+ url, reposRootUrl, date, author);
+ }
+
+ /**
+ * Return a stream which performs end-of-line translation and
+ * keyword expansion when written to. Behaves like
+ * {@link #translateStream(InputStream,byte[],boolean,Map,boolean)},
+ * except that it translates an <code>OutputStream</code> and never
+ * supports marking and seeking.
+ */
+ public static OutputStream translateStream(OutputStream destination,
+ byte[] eolMarker,
+ boolean repairEol,
+ Map<String, byte[]> keywords,
+ boolean expandKeywords)
+ throws SubversionException, ClientException
+ {
+ return substLib.translateOutputStream(
+ destination, eolMarker, repairEol,
+ keywords, true, expandKeywords,
+ null, Revision.SVN_INVALID_REVNUM,
+ null, null, null, null);
+ }
+
+ /**
+ * Expand keywords and return a stream which performs end-of-line
+ * translation and keyword expansion when written to.
+ * @see buildKeywords
+ * @see translateStream(OutputStream,byte[],boolean,Map,boolean)
+ */
+ public static OutputStream translateStream(OutputStream destination,
+ byte[] eolMarker,
+ boolean repairEol,
+ boolean expandKeywords,
+ byte[] keywordsValue,
+ long revision,
+ String url,
+ String reposRootUrl,
+ Date date,
+ String author)
+ throws SubversionException, ClientException
+ {
+ return substLib.translateOutputStream(
+ destination, eolMarker, repairEol,
+ null, false, expandKeywords,
+ keywordsValue, revision,
+ url, reposRootUrl, date, author);
+ }
}
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java Thu Nov 21 00:22:33 2013
@@ -47,4 +47,16 @@ public class SubversionException extends
{
super(message);
}
+
+ /**
+ * This constructor is only used by sub-classes and the native
+ * implementation.
+ *
+ * @param message A description of the problem.
+ * @param cause The root cause of the exception.
+ */
+ protected SubversionException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
}
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java Thu Nov 21 00:22:33 2013
@@ -46,10 +46,10 @@ public class ExternalItem implements jav
*
* @param targetDir See {@link #getTargetDir}
* @param url See {@link #getUrl}
-- * @param revision See {@link #getRevision};
-- * <code>null</code> will be interpreted as <code>pegRevision</code>
-- * @param pegRevision See {@link #getPegRevision};
-- * <code>null</code> will be interpreted as {@link Revision#HEAD}
+ * @param revision See {@link #getRevision};
+ * <code>null</code> will be interpreted as <code>pegRevision</code>
+ * @param pegRevision See {@link #getPegRevision};
+ * <code>null</code> will be interpreted as {@link Revision#HEAD}
*/
public ExternalItem(String targetDir, String url,
Revision revision, Revision pegRevision)
Modified: subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java?rev=1543993&r1=1543992&r2=1543993&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java Thu Nov 21 00:22:33 2013
@@ -30,10 +30,15 @@ import org.apache.subversion.javahl.type
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Arrays;
-import java.util.List;
import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
/**
* Tests the JavaHL SVNUtil APIs.
@@ -298,11 +303,14 @@ public class UtilTests extends SVNTests
private static List<ExternalItem> old_externals = null;
static {
try {
- old_externals = new ArrayList<ExternalItem>(2);
+ old_externals = new ArrayList<ExternalItem>(3);
old_externals.add(new ExternalItem("X", "http://server/repo/path",
null, null));
old_externals.add(new ExternalItem("Y", "http://server/repo/path",
null, Revision.getInstance(42)));
+
+ old_externals.add(new ExternalItem("Z", "http://server/repo/path",
+ null, Revision.getInstance(new Date(0L))));
} catch (SubversionException ex) {
old_externals = null;
throw new RuntimeException(ex);
@@ -311,7 +319,8 @@ public class UtilTests extends SVNTests
private static final byte[] old_externals_propval =
("X http://server/repo/path\n" +
- "Y -r42 http://server/repo/path\n").getBytes();
+ "Y -r42 http://server/repo/path\n" +
+ "Z -r{1970-01-01T00:00:00.000000Z} http://server/repo/path\n").getBytes();
private static void compare_item_lists(List<ExternalItem> a,
List<ExternalItem> b,
@@ -387,4 +396,181 @@ public class UtilTests extends SVNTests
new ExternalItem("x", "//a/b/c", null, null),
"http://a", "http://a/b"));
}
+
+ public void testBuildKeywords() throws Throwable
+ {
+ final byte[] kwval = "TEST=%H%_%b%_%u".getBytes();
+
+ Map<String, byte[]> result;
+
+ result = SVNUtil.buildKeywords(kwval, Revision.SVN_INVALID_REVNUM,
+ null, null, null, null);
+ assertEquals(" ", new String(result.get("TEST")));
+
+ result = SVNUtil.buildKeywords(kwval, 42, "http://a/b/c",
+ "http://a", new Date(1), "X");
+ assertEquals("b/c 42 1970-01-01 00:00:00Z X c http://a/b/c",
+ new String(result.get("TEST")));
+ }
+
+ public void testTranslateStream() throws Throwable
+ {
+ final byte[] keywordsValue = "Id TEST=%H%_%b%_%u".getBytes();
+ final byte[] contentsContracted = "$Id$\n$TEST$\n".getBytes();
+ final byte[] contentsExpanded =
+ ("$Id: c 42 1970-01-01 00:00:00Z X $\r" +
+ "$TEST: b/c 42 1970-01-01 00:00:00Z X c http://a/b/c $\r"
+ ) .getBytes();
+ final Map<String, byte[]> keywords =
+ SVNUtil.buildKeywords(keywordsValue, 42, "http://a/b/c",
+ "http://a", new Date(1), "X");
+ byte[] buffer = new byte[1024];
+
+ // InputStream; expand
+ InputStream testin = null;
+ try {
+ testin = SVNUtil.translateStream(
+ new ByteArrayInputStream(contentsContracted),
+ SVNUtil.EOL_CR, true, keywords, true);
+ final int size = testin.read(buffer);
+ testin.close();
+ testin = null;
+
+ assertEquals(new String(contentsExpanded),
+ new String(buffer, 0, size));
+ } finally {
+ if (testin != null) {
+ testin.close();
+ testin = null;
+ }
+ }
+
+ try {
+ testin = SVNUtil.translateStream(
+ new ByteArrayInputStream(contentsContracted),
+ SVNUtil.EOL_CR, true, true,
+ keywordsValue, 42, "http://a/b/c",
+ "http://a", new Date(1), "X");
+ final int size = testin.read(buffer);
+ testin.close();
+ testin = null;
+
+ assertEquals(new String(contentsExpanded),
+ new String(buffer, 0, size));
+ } finally {
+ if (testin != null) {
+ testin.close();
+ testin = null;
+ }
+ }
+
+ // InputStream; contract
+ try {
+ testin = SVNUtil.translateStream(
+ new ByteArrayInputStream(contentsExpanded),
+ SVNUtil.EOL_LF, true, keywords, false);
+ final int size = testin.read(buffer);
+ testin.close();
+ testin = null;
+
+ assertEquals(new String(contentsContracted),
+ new String(buffer, 0, size));
+ } finally {
+ if (testin != null) {
+ testin.close();
+ testin = null;
+ }
+ }
+
+ try {
+ testin = SVNUtil.translateStream(
+ new ByteArrayInputStream(contentsExpanded),
+ SVNUtil.EOL_LF, true, false,
+ keywordsValue, 42, "http://a/b/c",
+ "http://a", new Date(1), "X");
+ final int size = testin.read(buffer);
+ testin.close();
+ testin = null;
+
+ assertEquals(new String(contentsContracted),
+ new String(buffer, 0, size));
+ } finally {
+ if (testin != null) {
+ testin.close();
+ testin = null;
+ }
+ }
+
+
+ // OutputStream; expand
+ OutputStream testout = null;
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ testout = SVNUtil.translateStream(
+ result, SVNUtil.EOL_CR, true, keywords, true);
+ testout.write(contentsContracted);
+ testout.close();
+ testout = null;
+
+ assertEquals(new String(contentsExpanded), result.toString());
+ } finally {
+ if (testout != null) {
+ testout.close();
+ testout = null;
+ }
+ }
+
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ testout = SVNUtil.translateStream(
+ result, SVNUtil.EOL_CR, true, true,
+ keywordsValue, 42, "http://a/b/c",
+ "http://a", new Date(1), "X");
+ testout.write(contentsContracted);
+ testout.close();
+ testout = null;
+
+ assertEquals(new String(contentsExpanded), result.toString());
+ } finally {
+ if (testout != null) {
+ testout.close();
+ testout = null;
+ }
+ }
+
+ // OutputStream; contract
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ testout = SVNUtil.translateStream(
+ result, SVNUtil.EOL_LF, true, keywords, false);
+ testout.write(contentsExpanded);
+ testout.close();
+ testout = null;
+
+ assertEquals(new String(contentsContracted), result.toString());
+ } finally {
+ if (testout != null) {
+ testout.close();
+ testout = null;
+ }
+ }
+
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ testout = SVNUtil.translateStream(
+ result, SVNUtil.EOL_LF, true, false,
+ keywordsValue, 42, "http://a/b/c",
+ "http://a", new Date(1), "X");
+ testout.write(contentsExpanded);
+ testout.close();
+ testout = null;
+
+ assertEquals(new String(contentsContracted), result.toString());
+ } finally {
+ if (testout != null) {
+ testout.close();
+ testout = null;
+ }
+ }
+ }
}