You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/10/15 10:52:18 UTC
svn commit: r1532250 [5/37] - in /subversion/branches/cache-server: ./
build/ build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ contrib/client-side/emacs/ contrib/hook-scripts/
contrib/server-side/fsfsfixer/ contrib/ser...
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.cpp Tue Oct 15 08:52:06 2013
@@ -30,12 +30,14 @@
#include "JNIStringHolder.h"
#include "EnumMapper.h"
#include "RevisionRange.h"
+#include "RevisionRangeList.h"
#include "CreateJ.h"
#include "../include/org_apache_subversion_javahl_types_Revision.h"
#include "../include/org_apache_subversion_javahl_CommitItemStateFlags.h"
#include "svn_path.h"
#include "svn_props.h"
+#include "svn_mergeinfo.h"
#include "private/svn_wc_private.h"
jobject
@@ -230,6 +232,61 @@ CreateJ::Checksum(const svn_checksum_t *
}
jobject
+CreateJ::DirEntry(const char *path, const char *absPath,
+ const svn_dirent_t *dirent)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ // Create a local frame for our references
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return SVN_NO_ERROR;
+
+ jclass clazz = env->FindClass(JAVA_PACKAGE"/types/DirEntry");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ static jmethodID mid = 0;
+ if (mid == 0)
+ {
+ mid = env->GetMethodID(clazz, "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;"
+ "L"JAVA_PACKAGE"/types/NodeKind;"
+ "JZJJLjava/lang/String;)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ }
+
+ jstring jPath = JNIUtil::makeJString(path);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jstring jAbsPath = JNIUtil::makeJString(absPath);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jobject jNodeKind = EnumMapper::mapNodeKind(dirent->kind);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jlong jSize = dirent->size;
+ jboolean jHasProps = (dirent->has_props? JNI_TRUE : JNI_FALSE);
+ jlong jLastChangedRevision = dirent->created_rev;
+ jlong jLastChanged = dirent->time;
+ jstring jLastAuthor = JNIUtil::makeJString(dirent->last_author);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jobject ret = env->NewObject(clazz, mid, jPath, jAbsPath, jNodeKind,
+ jSize, jHasProps, jLastChangedRevision,
+ jLastChanged, jLastAuthor);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ return env->PopLocalFrame(ret);
+}
+
+jobject
CreateJ::Info(const char *path, const svn_client_info2_t *info)
{
JNIEnv *env = JNIUtil::getEnv();
@@ -423,6 +480,72 @@ CreateJ::Lock(const svn_lock_t *lock)
}
jobject
+CreateJ::LockMap(const apr_hash_t *locks, apr_pool_t *pool)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ if (locks == NULL)
+ return NULL;
+
+ // Create a local frame for our references
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ jclass clazz = env->FindClass("java/util/HashMap");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ static jmethodID init_mid = 0;
+ if (init_mid == 0)
+ {
+ init_mid = env->GetMethodID(clazz, "<init>", "()V");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ }
+
+ static jmethodID put_mid = 0;
+ if (put_mid == 0)
+ {
+ put_mid = env->GetMethodID(clazz, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)"
+ "Ljava/lang/Object;");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ }
+
+ jobject map = env->NewObject(clazz, init_mid);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ apr_hash_index_t *hi;
+ int i = 0;
+ for (hi = apr_hash_first(pool, (apr_hash_t *) locks); hi;
+ hi = apr_hash_next(hi), ++i)
+ {
+ const char *key = (const char *) svn__apr_hash_index_key(hi);
+ const svn_lock_t *lock = (const svn_lock_t *) svn__apr_hash_index_val(hi);
+
+ jstring jpath = JNIUtil::makeJString(key);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jobject jlock = Lock(lock);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ env->CallObjectMethod(map, put_mid, jpath, jlock);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ env->DeleteLocalRef(jpath);
+ env->DeleteLocalRef(jlock);
+ }
+
+ return env->PopLocalFrame(map);
+}
+
+jobject
CreateJ::ChangedPath(const char *path, svn_log_changed_path2_t *log_item)
{
JNIEnv *env = JNIUtil::getEnv();
@@ -655,7 +778,7 @@ CreateJ::ClientNotifyInformation(const s
"L"JAVA_PACKAGE"/types/NodeKind;"
"Ljava/lang/String;"
"L"JAVA_PACKAGE"/types/Lock;"
- "Ljava/lang/String;"
+ "Ljava/lang/String;Ljava/util/List;"
"L"JAVA_PACKAGE"/ClientNotifyInformation$Status;"
"L"JAVA_PACKAGE"/ClientNotifyInformation$Status;"
"L"JAVA_PACKAGE"/ClientNotifyInformation$LockStatus;"
@@ -688,7 +811,9 @@ CreateJ::ClientNotifyInformation(const s
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
- jstring jErr = JNIUtil::makeSVNErrorMessage(wcNotify->err);
+ jstring jErr;
+ jobject jErrStack;
+ JNIUtil::makeSVNErrorMessage(wcNotify->err, &jErr, &jErrStack);
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
@@ -735,7 +860,7 @@ CreateJ::ClientNotifyInformation(const s
jlong jhunkModifiedLength = wcNotify->hunk_modified_length;
jlong jhunkMatchedLine = wcNotify->hunk_matched_line;
jint jhunkFuzz = static_cast<jint>(wcNotify->hunk_fuzz);
- if (jhunkFuzz != wcNotify->hunk_fuzz)
+ if (jhunkFuzz < 0 || jhunkFuzz != wcNotify->hunk_fuzz)
{
env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
"Overflow converting C svn_linenum_t to Java int");
@@ -744,7 +869,7 @@ CreateJ::ClientNotifyInformation(const s
// call the Java method
jobject jInfo = env->NewObject(clazz, midCT, jPath, jAction,
- jKind, jMimeType, jLock, jErr,
+ jKind, jMimeType, jLock, jErr, jErrStack,
jContentState, jPropState, jLockState,
(jlong) wcNotify->revision, jChangelistName,
jMergeRange, jpathPrefix, jpropName,
@@ -951,82 +1076,129 @@ CreateJ::CommitInfo(const svn_commit_inf
}
jobject
-CreateJ::RevisionRangeList(svn_rangelist_t *ranges)
+CreateJ::StringSet(const apr_array_header_t *strings)
{
- JNIEnv *env = JNIUtil::getEnv();
-
- // Create a local frame for our references
- env->PushLocalFrame(LOCAL_FRAME_SIZE);
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
-
- jclass clazz = env->FindClass("java/util/ArrayList");
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+ std::vector<jobject> jstrs;
- static jmethodID init_mid = 0;
- if (init_mid == 0)
+ for (int i = 0; i < strings->nelts; ++i)
{
- init_mid = env->GetMethodID(clazz, "<init>", "()V");
+ const char *str = APR_ARRAY_IDX(strings, i, const char *);
+ jstring jstr = JNIUtil::makeJString(str);
if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
- }
+ return NULL;
- static jmethodID add_mid = 0;
- if (add_mid == 0)
- {
- add_mid = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z");
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+ jstrs.push_back(jstr);
}
- jobject jranges = env->NewObject(clazz, init_mid);
+ return CreateJ::Set(jstrs);
+}
- for (int i = 0; i < ranges->nelts; ++i)
- {
- // Convert svn_merge_range_t *'s to Java RevisionRange objects.
- svn_merge_range_t *range =
- APR_ARRAY_IDX(ranges, i, svn_merge_range_t *);
+namespace {
+void fill_property_map(jobject map,
+ apr_hash_t* prop_hash, apr_array_header_t* prop_diffs,
+ apr_pool_t* scratch_pool, jmethodID put_mid)
+{
+ SVN_ERR_ASSERT_NO_RETURN(!prop_hash != !prop_diffs
+ || !prop_hash && !prop_diffs);
- jobject jrange = RevisionRange::makeJRevisionRange(range);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+ if (!map || (prop_hash == NULL && prop_diffs == NULL))
+ return;
- env->CallBooleanMethod(jranges, add_mid, jrange);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+ JNIEnv *env = JNIUtil::getEnv();
- env->DeleteLocalRef(jrange);
+ // Create a local frame for our references
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ // The caller may not know the concrete class of the map, so
+ // determine the "put" method identifier here.
+ if (put_mid == 0)
+ {
+ put_mid = env->GetMethodID(env->GetObjectClass(map), "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)"
+ "Ljava/lang/Object;");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NOTHING();
}
- return env->PopLocalFrame(jranges);
-}
+ struct body
+ {
+ void operator()(const char* key, const svn_string_t* val)
+ {
+ jstring jpropName = JNIUtil::makeJString(key);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ jbyteArray jpropVal = (!val ? NULL
+ : JNIUtil::makeJByteArray(val));
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ m_env->CallObjectMethod(m_map, m_put_mid, jpropName, jpropVal);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ m_env->DeleteLocalRef(jpropName);
+ m_env->DeleteLocalRef(jpropVal);
+ }
+
+ JNIEnv*& m_env;
+ jmethodID& m_put_mid;
+ jobject& m_map;
+
+ body(JNIEnv*& xenv, jmethodID& xput_mid, jobject& xmap)
+ : m_env(xenv), m_put_mid(xput_mid), m_map(xmap)
+ {}
+ } loop_body(env, put_mid, map);
+
+ if (prop_hash)
+ {
+ if (!scratch_pool)
+ scratch_pool = apr_hash_pool_get(prop_hash);
+
+ apr_hash_index_t *hi;
+ for (hi = apr_hash_first(scratch_pool, prop_hash);
+ hi; hi = apr_hash_next(hi))
+ {
+ const char* key;
+ svn_string_t* val;
-jobject
-CreateJ::StringSet(apr_array_header_t *strings)
-{
- std::vector<jobject> jstrs;
+ const void* v_key;
+ void* v_val;
- for (int i = 0; i < strings->nelts; ++i)
- {
- const char *str = APR_ARRAY_IDX(strings, i, const char *);
- jstring jstr = JNIUtil::makeJString(str);
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
+ apr_hash_this(hi, &v_key, NULL, &v_val);
+ key = static_cast<const char*>(v_key);
+ val = static_cast<svn_string_t*>(v_val);
- jstrs.push_back(jstr);
+ loop_body(key, val);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NOTHING();
+ }
+ }
+ else
+ {
+ for (int i = 0; i < prop_diffs->nelts; ++i)
+ {
+ svn_prop_t* prop = APR_ARRAY_IDX(prop_diffs, i, svn_prop_t*);
+ loop_body(prop->name, prop->value);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NOTHING();
+ }
}
-
- return CreateJ::Set(jstrs);
}
-jobject CreateJ::PropertyMap(apr_hash_t *prop_hash)
+jobject property_map(apr_hash_t *prop_hash, apr_array_header_t* prop_diffs,
+ apr_pool_t* scratch_pool)
{
- JNIEnv *env = JNIUtil::getEnv();
+ SVN_ERR_ASSERT_NO_RETURN(!prop_hash != !prop_diffs
+ || !prop_hash && !prop_diffs);
- if (prop_hash == NULL)
+ if (prop_hash == NULL && prop_diffs == NULL)
return NULL;
+ JNIEnv *env = JNIUtil::getEnv();
+
// Create a local frame for our references
env->PushLocalFrame(LOCAL_FRAME_SIZE);
if (JNIUtil::isJavaExceptionThrown())
@@ -1058,35 +1230,35 @@ jobject CreateJ::PropertyMap(apr_hash_t
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(apr_hash_pool_get(prop_hash), prop_hash);
- hi; hi = apr_hash_next(hi))
- {
- const char *key;
- svn_string_t *val;
-
- apr_hash_this(hi,
- reinterpret_cast<const void **>(&key),
- NULL,
- reinterpret_cast<void **>(&val));
+ fill_property_map(map, prop_hash, prop_diffs, scratch_pool, put_mid);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
- jstring jpropName = JNIUtil::makeJString(key);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+ return env->PopLocalFrame(map);
+}
+} // anonymous namespace
- jbyteArray jpropVal = JNIUtil::makeJByteArray(val);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+jobject CreateJ::PropertyMap(apr_hash_t *prop_hash, apr_pool_t* scratch_pool)
+{
+ return property_map(prop_hash, NULL, scratch_pool);
+}
- env->CallObjectMethod(map, put_mid, jpropName, jpropVal);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+jobject CreateJ::PropertyMap(apr_array_header_t* prop_diffs,
+ apr_pool_t* scratch_pool)
+{
+ return property_map(NULL, prop_diffs, scratch_pool);
+}
- env->DeleteLocalRef(jpropName);
- env->DeleteLocalRef(jpropVal);
- }
+void CreateJ::FillPropertyMap(jobject map, apr_hash_t* prop_hash,
+ apr_pool_t* scratch_pool, jmethodID put_mid)
+{
+ fill_property_map(map, prop_hash, NULL, scratch_pool, put_mid);
+}
- return env->PopLocalFrame(map);
+void CreateJ::FillPropertyMap(jobject map, apr_array_header_t* prop_diffs,
+ apr_pool_t* scratch_pool, jmethodID put_mid)
+{
+ fill_property_map(map, NULL, prop_diffs, scratch_pool, put_mid);
}
jobject CreateJ::InheritedProps(apr_array_header_t *iprops)
@@ -1169,6 +1341,64 @@ jobject CreateJ::InheritedProps(apr_arra
return env->PopLocalFrame(array);
}
+jobject CreateJ::Mergeinfo(svn_mergeinfo_t mergeinfo, apr_pool_t* scratch_pool)
+{
+ if (mergeinfo == NULL)
+ return NULL;
+
+ // Transform mergeinfo into Java Mergeinfo object.
+ JNIEnv *env = JNIUtil::getEnv();
+ jclass clazz = env->FindClass(JAVA_PACKAGE "/types/Mergeinfo");
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ static jmethodID ctor = 0;
+ if (ctor == 0)
+ {
+ ctor = env->GetMethodID(clazz, "<init>", "()V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ }
+
+ static jmethodID addRevisions = 0;
+ if (addRevisions == 0)
+ {
+ addRevisions = env->GetMethodID(clazz, "addRevisions",
+ "(Ljava/lang/String;"
+ "Ljava/util/List;)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ }
+
+ jobject jmergeinfo = env->NewObject(clazz, ctor);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ apr_hash_index_t *hi;
+ for (hi = apr_hash_first(scratch_pool, mergeinfo);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *path;
+ void *val;
+ apr_hash_this(hi, &path, NULL, &val);
+
+ jstring jpath =
+ JNIUtil::makeJString(static_cast<const char*>(path));
+ jobject jranges =
+ RevisionRangeList(static_cast<svn_rangelist_t*>(val)).toList();
+
+ env->CallVoidMethod(jmergeinfo, addRevisions, jpath, jranges);
+
+ env->DeleteLocalRef(jranges);
+ env->DeleteLocalRef(jpath);
+ }
+
+ env->DeleteLocalRef(clazz);
+
+ return jmergeinfo;
+}
+
jobject CreateJ::Set(std::vector<jobject> &objects)
{
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/CreateJ.h Tue Oct 15 08:52:06 2013
@@ -31,6 +31,7 @@
#include "svn_wc.h"
#include "svn_repos.h"
#include "svn_client.h"
+#include "svn_mergeinfo.h"
#include <vector>
@@ -49,12 +50,19 @@ class CreateJ
Checksum(const svn_checksum_t *checksum);
static jobject
+ DirEntry(const char *path, const char *absPath,
+ const svn_dirent_t *dirent);
+
+ static jobject
Info(const char *path, const svn_client_info2_t *info);
static jobject
Lock(const svn_lock_t *lock);
static jobject
+ LockMap(const apr_hash_t *locks, apr_pool_t *pool);
+
+ static jobject
ChangedPath(const char *path, svn_log_changed_path2_t *log_item);
static jobject
@@ -74,17 +82,30 @@ class CreateJ
CommitInfo(const svn_commit_info_t *info);
static jobject
- RevisionRangeList(svn_rangelist_t *ranges);
+ StringSet(const apr_array_header_t *strings);
static jobject
- StringSet(apr_array_header_t *strings);
+ PropertyMap(apr_hash_t *prop_hash, apr_pool_t* scratch_pool = NULL);
static jobject
- PropertyMap(apr_hash_t *prop_hash);
+ PropertyMap(apr_array_header_t* prop_diffs, apr_pool_t* scratch_pool = NULL);
+
+ static void
+ FillPropertyMap(jobject map, apr_hash_t* prop_hash,
+ apr_pool_t* scratch_pool,
+ jmethodID put_method_id = 0);
+
+ static void
+ FillPropertyMap(jobject map, apr_array_header_t* prop_diffs,
+ apr_pool_t* scratch_pool,
+ jmethodID put_method_id = 0);
static jobject
InheritedProps(apr_array_header_t *inherited_props);
+ static jobject
+ Mergeinfo(svn_mergeinfo_t mergeinfo, apr_pool_t* scratch_pool);
+
/* This creates a set of Objects. It derefs the members of the vector
* after putting them in the set, so they caller doesn't need to. */
static jobject
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.cpp Tue Oct 15 08:52:06 2013
@@ -191,12 +191,42 @@ int EnumMapper::toLogLevel(jobject jLogL
return getOrdinal(JAVA_PACKAGE"/SVNClient$ClientLogLevel", jLogLevel);
}
+svn_node_kind_t EnumMapper::toNodeKind(jobject jNodeKind)
+{
+ return svn_node_kind_t(
+ getOrdinal(JAVA_PACKAGE"/types/NodeKind", jNodeKind));
+}
+
+svn_checksum_kind_t EnumMapper::toChecksumKind(jobject jChecksumKind)
+{
+ return svn_checksum_kind_t(
+ getOrdinal(JAVA_PACKAGE"/types/Checksum$Kind", jChecksumKind));
+}
+
+svn_tristate_t EnumMapper::toTristate(jobject jTristate)
+{
+ switch (getOrdinal(JAVA_PACKAGE"/types/Tristate", jTristate))
+ {
+ case 1: return svn_tristate_false;
+ case 2: return svn_tristate_true;
+ default: return svn_tristate_unknown;
+ }
+}
+
svn_depth_t EnumMapper::toDepth(jobject jdepth)
{
// The offset for depths is -2
return static_cast<svn_depth_t>(getOrdinal(JAVA_PACKAGE"/types/Depth", jdepth) - 2);
}
+svn_mergeinfo_inheritance_t
+EnumMapper::toMergeinfoInheritance(jobject jInheritance)
+{
+ return static_cast<svn_mergeinfo_inheritance_t>(
+ getOrdinal(JAVA_PACKAGE"/types/Mergeinfo$Inheritance", jInheritance));
+}
+
+
jobject EnumMapper::mapDepth(svn_depth_t depth)
{
// We're assuming a valid value for the C enum above
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/EnumMapper.h Tue Oct 15 08:52:06 2013
@@ -48,6 +48,11 @@ class EnumMapper
static svn_wc_conflict_choice_t toConflictChoice(jobject jchoice);
static int toMergeinfoLogKind(jobject jLogKind);
static int toLogLevel(jobject jLogLevel);
+ static svn_node_kind_t toNodeKind(jobject jNodeKind);
+ static svn_checksum_kind_t toChecksumKind(jobject jChecksumKind);
+ static svn_tristate_t toTristate(jobject jTristate);
+ static svn_mergeinfo_inheritance_t
+ toMergeinfoInheritance(jobject jInheritance);
/* Converting from C enum's */
static jint mapCommitMessageStateFlags(apr_byte_t flags);
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/InfoCallback.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/InfoCallback.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/InfoCallback.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/InfoCallback.h Tue Oct 15 08:52:06 2013
@@ -30,8 +30,6 @@
#include <jni.h>
#include "svn_client.h"
-struct info_entry;
-
/**
* This class holds a Java callback object, which will receive every line of
* the file for which the callback information is requested.
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.cpp Tue Oct 15 08:52:06 2013
@@ -32,30 +32,24 @@
* @param flag that the underlying byte array reference should be deleted at
* destruction
*/
-JNIByteArray::JNIByteArray(jbyteArray jba, bool deleteByteArray)
-{
- m_array = jba;
- m_deleteByteArray = deleteByteArray;
- if (jba != NULL)
- {
- // Get the bytes.
- JNIEnv *env = JNIUtil::getEnv();
- m_data = env->GetByteArrayElements(jba, NULL);
- }
- else
- {
- m_data = NULL;
- }
-}
+JNIByteArray::JNIByteArray(jbyteArray jba,
+ bool deleteByteArray,
+ bool abortOnRelease)
+ : m_array(jba),
+ m_data(!jba ? NULL
+ : JNIUtil::getEnv()->GetByteArrayElements(jba, NULL)),
+ m_deleteByteArray(deleteByteArray),
+ m_abortOnRelease(abortOnRelease)
+{}
JNIByteArray::~JNIByteArray()
{
if (m_array != NULL)
{
// Release the bytes
- JNIUtil::getEnv()->ReleaseByteArrayElements(m_array,
- m_data,
- JNI_ABORT);
+ JNIUtil::getEnv()->ReleaseByteArrayElements(
+ m_array, m_data,
+ (m_abortOnRelease ? JNI_ABORT: JNI_COMMIT));
if (m_deleteByteArray)
// And if needed the byte array.
JNIUtil::getEnv()->DeleteLocalRef(m_array);
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/JNIByteArray.h Tue Oct 15 08:52:06 2013
@@ -51,11 +51,18 @@ class JNIByteArray
* at destruction.
*/
bool m_deleteByteArray;
+
+ /**
+ * False if changes to the array should be committed to the Java VM.
+ */
+ bool m_abortOnRelease;
public:
bool isNull() const;
const signed char *getBytes() const;
int getLength();
- JNIByteArray(jbyteArray jba, bool deleteByteArray = false);
+ JNIByteArray(jbyteArray jba,
+ bool deleteByteArray = false,
+ bool abortOnRelease = true);
~JNIByteArray();
};
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/JNIStringHolder.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/JNIStringHolder.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/JNIStringHolder.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/JNIStringHolder.h Tue Oct 15 08:52:06 2013
@@ -36,6 +36,7 @@ class JNIStringHolder
JNIStringHolder(jstring jtext);
~JNIStringHolder();
operator const char *() { return m_str; }
+ const char* c_str() const { return m_str; }
const char *pstrdup(apr_pool_t *pool);
protected:
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.cpp Tue Oct 15 08:52:06 2013
@@ -24,6 +24,13 @@
* @brief Implementation of the class JNIUtil
*/
+/* Include apr.h first, or INT64_C won't be defined properly on some C99
+ compilers, when other headers include <stdint.h> before defining some
+ macros.
+
+ See apr.h for the ugly details */
+#include <apr.h>
+
#include "JNIUtil.h"
#include "Array.h"
@@ -35,6 +42,8 @@
#include <apr_tables.h>
#include <apr_general.h>
#include <apr_lib.h>
+#include <apr_file_info.h>
+#include <apr_time.h>
#include "svn_pools.h"
#include "svn_fs.h"
@@ -44,7 +53,7 @@
#include "svn_dso.h"
#include "svn_path.h"
#include "svn_cache_config.h"
-#include <apr_file_info.h>
+#include "private/svn_atomic.h"
#include "svn_private_config.h"
#ifdef WIN32
/* FIXME: We're using an internal APR header here, which means we
@@ -68,6 +77,7 @@ apr_pool_t *JNIUtil::g_pool = NULL;
std::list<SVNBase*> JNIUtil::g_finalizedObjects;
JNIMutex *JNIUtil::g_finalizedObjectsMutex = NULL;
JNIMutex *JNIUtil::g_logMutex = NULL;
+JNIMutex *JNIUtil::g_configMutex = NULL;
bool JNIUtil::g_initException;
bool JNIUtil::g_inInit;
JNIEnv *JNIUtil::g_initEnv;
@@ -104,6 +114,93 @@ bool JNIUtil::JNIInit(JNIEnv *env)
return true;
}
+namespace
+{
+struct GlobalInitGuard
+{
+ enum InitState
+ {
+ state_null,
+ state_init,
+ state_done,
+ state_error
+ };
+
+ GlobalInitGuard()
+ : m_finished(false),
+ m_state(InitState(svn_atomic_cas(&m_global_state,
+ state_init, state_null)))
+ {
+ switch (m_state)
+ {
+ case state_null:
+ // This thread won the initialization contest.
+ break;
+
+ case state_done:
+ // The library is already initialized.
+ break;
+
+ case state_init:
+ // Another thread is currently initializing the
+ // library. Spin and wait for it to finish, with exponential
+ // backoff, but no longer than half a second.
+ for (unsigned shift = 0;
+ m_state == state_init && shift < 8;
+ ++shift)
+ {
+ apr_sleep((APR_USEC_PER_SEC / 1000) << shift);
+ m_state = InitState(svn_atomic_cas(&m_global_state,
+ state_null, state_null));
+ }
+ if (m_state == state_init)
+ // The initialization didn't complete in half a second,
+ // which probably implies a thread crash or a deadlock.
+ m_state = state_error;
+ break;
+
+ default:
+ // Error state, or unknown state. In any case, do not continue.
+ m_state = state_error;
+ }
+ }
+
+ ~GlobalInitGuard()
+ {
+ // Signal the end of the library intialization if we're the
+ // initializing thread.
+ if (m_finished && m_state == state_null)
+ {
+ SVN_ERR_ASSERT_NO_RETURN(
+ state_init == svn_atomic_cas(&m_global_state,
+ state_done, state_init));
+ }
+ }
+
+ bool done() const
+ {
+ return (m_state == state_done);
+ }
+
+ bool error() const
+ {
+ return (m_state == state_error);
+ }
+
+ void finish()
+ {
+ m_finished = true;
+ }
+
+private:
+ bool m_finished;
+ InitState m_state;
+ static volatile svn_atomic_t m_global_state;
+};
+volatile svn_atomic_t
+GlobalInitGuard::m_global_state = GlobalInitGuard::state_null;
+} // anonymous namespace
+
/**
* Initialize the environment for all requests.
* @param env the JNI environment for this request
@@ -111,27 +208,19 @@ bool JNIUtil::JNIInit(JNIEnv *env)
bool JNIUtil::JNIGlobalInit(JNIEnv *env)
{
// This method has to be run only once during the run a program.
- static bool run = false;
- svn_error_t *err;
- if (run) // already run
+ GlobalInitGuard guard;
+ if (guard.done())
return true;
-
- run = true;
-
- // Do not run this part more than one time. This leaves a small
- // time window when two threads create their first SVNClient and
- // SVNAdmin at the same time, but I do not see a better option
- // without APR already initialized
- if (g_inInit)
+ else if (guard.error())
return false;
g_inInit = true;
g_initEnv = env;
+ svn_error_t *err;
apr_status_t status;
-
/* Initialize the APR subsystem, and register an atexit() function
* to Uninitialize that subsystem at program exit. */
status = apr_initialize();
@@ -179,7 +268,7 @@ bool JNIUtil::JNIGlobalInit(JNIEnv *env)
apr_allocator_max_free_set(allocator, 1);
}
- svn_utf_initialize2(g_pool, FALSE); /* Optimize character conversions */
+ svn_utf_initialize2(FALSE, g_pool); /* Optimize character conversions */
svn_fs_initialize(g_pool); /* Avoid some theoretical issues */
svn_ra_initialize(g_pool);
@@ -268,6 +357,10 @@ bool JNIUtil::JNIGlobalInit(JNIEnv *env)
if (isExceptionThrown())
return false;
+ g_configMutex = new JNIMutex(g_pool);
+ if (isExceptionThrown())
+ return false;
+
// initialized the thread local storage
if (!JNIThreadData::initThreadData())
return false;
@@ -278,6 +371,8 @@ bool JNIUtil::JNIGlobalInit(JNIEnv *env)
g_initEnv = NULL;
g_inInit = false;
+
+ guard.finish();
return true;
}
@@ -308,16 +403,6 @@ void JNIUtil::raiseThrowable(const char
env->DeleteLocalRef(clazz);
}
-jstring JNIUtil::makeSVNErrorMessage(svn_error_t *err)
-{
- if (err == NULL)
- return NULL;
- std::string buffer;
- assembleErrorMessage(err, 0, APR_SUCCESS, buffer);
- jstring jmessage = makeJString(buffer.c_str());
- return jmessage;
-}
-
void
JNIUtil::throwNativeException(const char *className, const char *msg,
const char *source, int aprErr)
@@ -418,10 +503,173 @@ JNIUtil::putErrorsInTrace(svn_error_t *e
env->DeleteLocalRef(jfileName);
}
-void JNIUtil::handleSVNError(svn_error_t *err)
+namespace {
+struct MessageStackItem
+{
+ apr_status_t m_code;
+ std::string m_message;
+ bool m_generic;
+
+ MessageStackItem(apr_status_t code, const char* message,
+ bool generic = false)
+ : m_code(code),
+ m_message(message),
+ m_generic(generic)
+ {}
+};
+typedef std::vector<MessageStackItem> ErrorMessageStack;
+
+/*
+ * Build the error message from the svn error into buffer. This
+ * method iterates through all the chained errors
+ *
+ * @param err the subversion error
+ * @param buffer the buffer where the formated error message will
+ * be stored
+ * @return An array of error codes and messages
+ */
+ErrorMessageStack assemble_error_message(
+ svn_error_t *err, std::string &result)
+{
+ // buffer for a single error message
+ char errbuf[1024];
+ apr_status_t parent_apr_err = 0;
+ ErrorMessageStack message_stack;
+
+ /* Pretty-print the error */
+ /* Note: we can also log errors here someday. */
+
+ for (int depth = 0; err;
+ ++depth, parent_apr_err = err->apr_err, err = err->child)
+ {
+ /* When we're recursing, don't repeat the top-level message if its
+ * the same as before. */
+ if (depth == 0 || err->apr_err != parent_apr_err)
+ {
+ const char *message;
+ /* Is this a Subversion-specific error code? */
+ if ((err->apr_err > APR_OS_START_USEERR)
+ && (err->apr_err <= APR_OS_START_CANONERR))
+ message = svn_strerror(err->apr_err, errbuf, sizeof(errbuf));
+ /* Otherwise, this must be an APR error code. */
+ else
+ {
+ /* Messages coming from apr_strerror are in the native
+ encoding, it's a good idea to convert them to UTF-8. */
+ apr_strerror(err->apr_err, errbuf, sizeof(errbuf));
+ svn_error_t* utf8_err =
+ svn_utf_cstring_to_utf8(&message, errbuf, err->pool);
+ if (utf8_err)
+ {
+ /* Use fuzzy transliteration instead. */
+ svn_error_clear(utf8_err);
+ message = svn_utf_cstring_from_utf8_fuzzy(errbuf, err->pool);
+ }
+ }
+
+ message_stack.push_back(
+ MessageStackItem(err->apr_err, message, true));
+ }
+ if (err->message)
+ {
+ message_stack.push_back(
+ MessageStackItem(err->apr_err, err->message));
+ }
+ }
+
+ for (ErrorMessageStack::const_iterator it = message_stack.begin();
+ it != message_stack.end(); ++it)
+ {
+ if (!it->m_generic)
+ result += "svn: ";
+ result += it->m_message;
+ result += '\n';
+ }
+ return message_stack;
+}
+
+jobject construct_Jmessage_stack(const ErrorMessageStack& message_stack)
{
- std::string msg;
- assembleErrorMessage(svn_error_purge_tracing(err), 0, APR_SUCCESS, msg);
+ JNIEnv *env = JNIUtil::getEnv();
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ jclass list_clazz = env->FindClass("java/util/ArrayList");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ jmethodID mid = env->GetMethodID(list_clazz, "<init>", "(I)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ jmethodID add_mid = env->GetMethodID(list_clazz, "add",
+ "(Ljava/lang/Object;)Z");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ jobject jlist = env->NewObject(list_clazz, mid, jint(message_stack.size()));
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jclass clazz = env->FindClass(JAVA_PACKAGE"/ClientException$ErrorMessage");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ mid = env->GetMethodID(clazz, "<init>",
+ "(ILjava/lang/String;Z)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ for (ErrorMessageStack::const_iterator it = message_stack.begin();
+ it != message_stack.end(); ++it)
+ {
+ jobject jmessage = JNIUtil::makeJString(it->m_message.c_str());
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ jobject jitem = env->NewObject(clazz, mid,
+ jint(it->m_code), jmessage,
+ jboolean(it->m_generic));
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ env->CallBooleanMethod(jlist, add_mid, jitem);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ env->DeleteLocalRef(jmessage);
+ env->DeleteLocalRef(jitem);
+ }
+ return env->PopLocalFrame(jlist);
+}
+} // anonymous namespace
+
+std::string JNIUtil::makeSVNErrorMessage(svn_error_t *err,
+ jstring *jerror_message,
+ jobject *jmessage_stack)
+{
+ if (jerror_message)
+ *jerror_message = NULL;
+ if (jmessage_stack)
+ *jmessage_stack = NULL;
+
+ std::string buffer;
+ err = svn_error_purge_tracing(err);
+ if (err == NULL || err->apr_err == 0
+ || !(jerror_message || jmessage_stack))
+ return buffer;
+
+ ErrorMessageStack message_stack = assemble_error_message(err, buffer);
+ if (jerror_message)
+ *jerror_message = makeJString(buffer.c_str());
+ if (jmessage_stack)
+ *jmessage_stack = construct_Jmessage_stack(message_stack);
+ return buffer;
+}
+
+void JNIUtil::wrappedHandleSVNError(svn_error_t *err)
+{
+ jstring jmessage;
+ jobject jstack;
+ std::string msg = makeSVNErrorMessage(err, &jmessage, &jstack);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
const char *source = NULL;
#ifdef SVN_DEBUG
#ifndef SVN_ERR__TRACING
@@ -465,19 +713,18 @@ void JNIUtil::handleSVNError(svn_error_t
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
- jstring jmessage = makeJString(msg.c_str());
- if (isJavaExceptionThrown())
- POP_AND_RETURN_NOTHING();
jstring jsource = makeJString(source);
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
jmethodID mid = env->GetMethodID(clazz, "<init>",
- "(Ljava/lang/String;Ljava/lang/String;I)V");
+ "(Ljava/lang/String;"
+ "Ljava/lang/String;I"
+ "Ljava/util/List;)V");
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
jobject nativeException = env->NewObject(clazz, mid, jmessage, jsource,
- static_cast<jint>(err->apr_err));
+ jint(err->apr_err), jstack);
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
@@ -513,7 +760,7 @@ void JNIUtil::handleSVNError(svn_error_t
POP_AND_RETURN_NOTHING();
const jsize stSize = static_cast<jsize>(newStackTrace.size());
- if (stSize != newStackTrace.size())
+ if (stSize < 0 || stSize != newStackTrace.size())
{
env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
"Overflow converting C size_t to JNI jsize");
@@ -546,7 +793,16 @@ void JNIUtil::handleSVNError(svn_error_t
#endif
env->Throw(static_cast<jthrowable>(env->PopLocalFrame(nativeException)));
+}
+void JNIUtil::handleSVNError(svn_error_t *err)
+{
+ try {
+ wrappedHandleSVNError(err);
+ } catch (...) {
+ svn_error_clear(err);
+ throw;
+ }
svn_error_clear(err);
}
@@ -643,26 +899,46 @@ bool JNIUtil::isJavaExceptionThrown()
return false;
}
-const char *
-JNIUtil::thrownExceptionToCString(SVN::Pool &in_pool)
+namespace {
+const char* known_exception_to_cstring(apr_pool_t* pool)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+ jthrowable t = env->ExceptionOccurred();
+ jclass cls = env->GetObjectClass(t);
+
+ jstring jclass_name;
+ {
+ jmethodID mid = env->GetMethodID(cls, "getClass", "()Ljava/lang/Class;");
+ jobject clsobj = env->CallObjectMethod(t, mid);
+ jclass basecls = env->GetObjectClass(clsobj);
+ mid = env->GetMethodID(basecls, "getName", "()Ljava/lang/String;");
+ jclass_name = (jstring) env->CallObjectMethod(clsobj, mid);
+ }
+
+ jstring jmessage;
+ {
+ jmethodID mid = env->GetMethodID(cls, "getMessage",
+ "()Ljava/lang/String;");
+ jmessage = (jstring) env->CallObjectMethod(t, mid);
+ }
+
+ JNIStringHolder class_name(jclass_name);
+ if (jmessage)
+ {
+ JNIStringHolder message(jmessage);
+ return apr_pstrcat(pool, class_name.c_str(), ": ", message.c_str(), NULL);
+ }
+ else
+ return class_name.pstrdup(pool);
+ // ### Conditionally add t.printStackTrace() to msg?
+}
+
+const char* exception_to_cstring(apr_pool_t* pool)
{
const char *msg;
- JNIEnv *env = getEnv();
- if (env->ExceptionCheck())
+ if (JNIUtil::getEnv()->ExceptionCheck())
{
- jthrowable t = env->ExceptionOccurred();
- static jmethodID getMessage = 0;
- if (getMessage == 0)
- {
- jclass clazz = env->FindClass("java/lang/Throwable");
- getMessage = env->GetMethodID(clazz, "getMessage",
- "(V)Ljava/lang/String;");
- env->DeleteLocalRef(clazz);
- }
- jstring jmsg = (jstring) env->CallObjectMethod(t, getMessage);
- JNIStringHolder tmp(jmsg);
- msg = tmp.pstrdup(in_pool.getPool());
- // ### Conditionally add t.printStackTrace() to msg?
+ msg = known_exception_to_cstring(pool);
}
else
{
@@ -670,6 +946,27 @@ JNIUtil::thrownExceptionToCString(SVN::P
}
return msg;
}
+} // anonymous namespace
+
+const char *
+JNIUtil::thrownExceptionToCString(SVN::Pool &in_pool)
+{
+ return exception_to_cstring(in_pool.getPool());
+}
+
+svn_error_t*
+JNIUtil::checkJavaException(apr_status_t errorcode)
+{
+ if (!getEnv()->ExceptionCheck())
+ return SVN_NO_ERROR;
+ svn_error_t* err = svn_error_create(errorcode, NULL, NULL);
+ const char* const msg = known_exception_to_cstring(err->pool);
+ if (msg)
+ err->message = apr_psprintf(err->pool, _("Java exception: %s"), msg);
+ else
+ err->message = _("Java exception");
+ return err;
+}
/**
* Create a Java string from a native UTF-8 string.
@@ -796,6 +1093,31 @@ jobject JNIUtil::createDate(apr_time_t t
return ret;
}
+apr_time_t
+JNIUtil::getDate(jobject jdate)
+{
+ JNIEnv *env = getEnv();
+ jclass clazz = env->FindClass("java/util/Date");
+ if (isJavaExceptionThrown())
+ return 0;
+
+ static jmethodID mid = 0;
+ if (mid == 0)
+ {
+ mid = env->GetMethodID(clazz, "getTime", "()J");
+ if (isJavaExceptionThrown())
+ return 0;
+ }
+
+ jlong jmillis = env->CallLongMethod(jdate, mid);
+ if (isJavaExceptionThrown())
+ return 0;
+
+ env->DeleteLocalRef(clazz);
+
+ return jmillis * 1000;
+}
+
/**
* Create a Java byte array from an array of characters.
* @param data the character array
@@ -803,11 +1125,9 @@ jobject JNIUtil::createDate(apr_time_t t
*/
jbyteArray JNIUtil::makeJByteArray(const void *data, int length)
{
- if (data == NULL)
- {
- // a NULL will create no Java array
- return NULL;
- }
+ // a NULL will create no Java array
+ if (!data)
+ return NULL;
JNIEnv *env = getEnv();
@@ -838,48 +1158,11 @@ jbyteArray JNIUtil::makeJByteArray(const
*/
jbyteArray JNIUtil::makeJByteArray(const svn_string_t *str)
{
- return JNIUtil::makeJByteArray(str->data, static_cast<int>(str->len));
-}
-
-/**
- * Build the error message from the svn error into buffer. This
- * method calls itselft recursively for all the chained errors
- *
- * @param err the subversion error
- * @param depth the depth of the call, used for formating
- * @param parent_apr_err the apr of the previous level, used for formating
- * @param buffer the buffer where the formated error message will
- * be stored
- */
-void JNIUtil::assembleErrorMessage(svn_error_t *err, int depth,
- apr_status_t parent_apr_err,
- std::string &buffer)
-{
- // buffer for a single error message
- char errbuf[256];
-
- /* Pretty-print the error */
- /* Note: we can also log errors here someday. */
-
- /* When we're recursing, don't repeat the top-level message if its
- * the same as before. */
- if (depth == 0 || err->apr_err != parent_apr_err)
- {
- /* Is this a Subversion-specific error code? */
- if ((err->apr_err > APR_OS_START_USEERR)
- && (err->apr_err <= APR_OS_START_CANONERR))
- buffer.append(svn_strerror(err->apr_err, errbuf, sizeof(errbuf)));
- /* Otherwise, this must be an APR error code. */
- else
- buffer.append(apr_strerror(err->apr_err, errbuf, sizeof(errbuf)));
- buffer.append("\n");
- }
- if (err->message)
- buffer.append(_("svn: ")).append(err->message).append("\n");
-
- if (err->child)
- assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);
+ // a NULL will create no Java array
+ if (!str)
+ return NULL;
+ return JNIUtil::makeJByteArray(str->data, static_cast<int>(str->len));
}
/**
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/JNIUtil.h Tue Oct 15 08:52:06 2013
@@ -37,8 +37,11 @@ class SVNBase;
#include <fstream>
#include <apr_time.h>
#include <string>
+#include <vector>
struct svn_error_t;
+#include "svn_error.h"
+
#define JAVA_PACKAGE "org/apache/subversion/javahl"
struct svn_string_t;
@@ -67,6 +70,7 @@ class JNIUtil
static jbyteArray makeJByteArray(const void *data, int length);
static jbyteArray makeJByteArray(const svn_string_t *str);
static jobject createDate(apr_time_t time);
+ static apr_time_t getDate(jobject jdate);
static void logMessage(const char *message);
static int getLogLevel();
static char *getFormatBuffer();
@@ -107,12 +111,20 @@ class JNIUtil
static const char *thrownExceptionToCString(SVN::Pool &in_pool);
/**
+ * Check if a Java exception was thrown and convert it to a
+ * Subversion error, using @a errorcode as the generic error code.
+ */
+ static svn_error_t* checkJavaException(apr_status_t errorcode);
+
+ /**
* Throw a Java exception corresponding to err, and run
* svn_error_clear() on err.
*/
static void handleSVNError(svn_error_t *err);
- static jstring makeSVNErrorMessage(svn_error_t *err);
+ static std::string makeSVNErrorMessage(svn_error_t *err,
+ jstring *jerror_message,
+ jobject *jmessage_stack);
/**
* Create and throw a java.lang.Throwable instance.
@@ -140,10 +152,13 @@ class JNIUtil
enum { formatBufferSize = 2048 };
enum { noLog, errorLog, exceptionLog, entryLog } LogLevel;
+ /**
+ * Mutex that secures the global configuration object.
+ */
+ static JNIMutex *g_configMutex;
+
private:
- static void assembleErrorMessage(svn_error_t *err, int depth,
- apr_status_t parent_apr_err,
- std::string &buffer);
+ static void wrappedHandleSVNError(svn_error_t *err);
static void putErrorsInTrace(svn_error_t *err,
std::vector<jobject> &stackTrace);
/**
@@ -283,4 +298,10 @@ class JNIUtil
} \
} while (0)
+#define SVN_JNI_CATCH(statement, errorcode) \
+ do { \
+ do { statement; } while(0); \
+ SVN_ERR(JNIUtil::checkJavaException((errorcode))); \
+ } while(0)
+
#endif // JNIUTIL_H
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/ListCallback.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/ListCallback.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/ListCallback.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/ListCallback.cpp Tue Oct 15 08:52:06 2013
@@ -126,53 +126,5 @@ jobject
ListCallback::createJavaDirEntry(const char *path, const char *absPath,
const svn_dirent_t *dirent)
{
- JNIEnv *env = JNIUtil::getEnv();
-
- // Create a local frame for our references
- env->PushLocalFrame(LOCAL_FRAME_SIZE);
- if (JNIUtil::isJavaExceptionThrown())
- return SVN_NO_ERROR;
-
- jclass clazz = env->FindClass(JAVA_PACKAGE"/types/DirEntry");
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
-
- static jmethodID mid = 0;
- if (mid == 0)
- {
- mid = env->GetMethodID(clazz, "<init>",
- "(Ljava/lang/String;Ljava/lang/String;"
- "L"JAVA_PACKAGE"/types/NodeKind;"
- "JZJJLjava/lang/String;)V");
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
- }
-
- jstring jPath = JNIUtil::makeJString(path);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
-
- jstring jAbsPath = JNIUtil::makeJString(absPath);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
-
- jobject jNodeKind = EnumMapper::mapNodeKind(dirent->kind);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
-
- jlong jSize = dirent->size;
- jboolean jHasProps = (dirent->has_props? JNI_TRUE : JNI_FALSE);
- jlong jLastChangedRevision = dirent->created_rev;
- jlong jLastChanged = dirent->time;
- jstring jLastAuthor = JNIUtil::makeJString(dirent->last_author);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
-
- jobject ret = env->NewObject(clazz, mid, jPath, jAbsPath, jNodeKind,
- jSize, jHasProps, jLastChangedRevision,
- jLastChanged, jLastAuthor);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
-
- return env->PopLocalFrame(ret);
+ return CreateJ::DirEntry(path, absPath, dirent);
}
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/LogMessageCallback.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/LogMessageCallback.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/LogMessageCallback.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/LogMessageCallback.cpp Tue Oct 15 08:52:06 2013
@@ -117,7 +117,7 @@ LogMessageCallback::singleMessage(svn_lo
jobject jrevprops = NULL;
if (log_entry->revprops != NULL && apr_hash_count(log_entry->revprops) > 0)
- jrevprops = CreateJ::PropertyMap(log_entry->revprops);
+ jrevprops = CreateJ::PropertyMap(log_entry->revprops, pool);
env->CallVoidMethod(m_callback,
sm_mid,
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/PatchCallback.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/PatchCallback.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/PatchCallback.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/PatchCallback.h Tue Oct 15 08:52:06 2013
@@ -30,8 +30,6 @@
#include <jni.h>
#include "svn_client.h"
-struct info_entry;
-
/**
* This class holds a Java callback object, which will receive every line of
* the file for which the callback information is requested.
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/Path.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/Path.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/Path.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/Path.cpp Tue Oct 15 08:52:06 2013
@@ -27,18 +27,24 @@
#include <jni.h>
#include "Path.h"
#include "svn_path.h"
+#include "svn_dirent_uri.h"
#include "JNIUtil.h"
+#include "JNIStringHolder.h"
#include "Pool.h"
+#include "svn_private_config.h"
/**
* Constructor
*
- * @see Path::Path(const std::string &)
+ * @see PathBase::PathBase(const std::string &)
* @param path Path string
*/
-Path::Path(const char *pi_path, SVN::Pool &in_pool)
+PathBase::PathBase(const char *pi_path,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool)
+ : m_error_occurred(NULL)
{
- init(pi_path, in_pool);
+ init(pi_path, initfunc, in_pool);
}
/**
@@ -48,19 +54,26 @@ Path::Path(const char *pi_path, SVN::Poo
*
* @param path Path string
*/
-Path::Path(const std::string &pi_path, SVN::Pool &in_pool)
+PathBase::PathBase(const std::string &pi_path,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool)
+ : m_error_occurred(NULL)
{
- init(pi_path.c_str(), in_pool);
+ init(pi_path.c_str(), initfunc, in_pool);
}
/**
- * Copy constructor
- *
- * @param path Path to be copied
+ * Constructor from a Java string.
*/
-Path::Path(const Path &pi_path, SVN::Pool &in_pool)
+PathBase::PathBase(jstring jpath,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool)
+ : m_error_occurred(NULL)
{
- init(pi_path.c_str(), in_pool);
+ JNIStringHolder path(jpath);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ init(path, initfunc, in_pool);
}
/**
@@ -69,17 +82,13 @@ Path::Path(const Path &pi_path, SVN::Poo
* @param path Path string
*/
void
-Path::init(const char *pi_path, SVN::Pool &in_pool)
+PathBase::init(const char *pi_path,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool)
{
- if (*pi_path == 0)
- {
- m_error_occurred = NULL;
- m_path = "";
- }
- else
+ if (pi_path && *pi_path)
{
- m_error_occurred = JNIUtil::preprocessPath(pi_path, in_pool.getPool());
-
+ m_error_occurred = initfunc(pi_path, in_pool);
m_path = pi_path;
}
}
@@ -88,7 +97,7 @@ Path::init(const char *pi_path, SVN::Poo
* @return Path string
*/
const std::string &
-Path::path() const
+PathBase::path() const
{
return m_path;
}
@@ -97,7 +106,7 @@ Path::path() const
* @return Path string as a C string
*/
const char *
-Path::c_str() const
+PathBase::c_str() const
{
return m_path.c_str();
}
@@ -105,8 +114,8 @@ Path::c_str() const
/**
* Assignment operator
*/
-Path&
-Path::operator=(const Path &pi_path)
+PathBase&
+PathBase::operator=(const PathBase &pi_path)
{
m_error_occurred = NULL;
m_path = pi_path.m_path;
@@ -114,12 +123,12 @@ Path::operator=(const Path &pi_path)
return *this;
}
- svn_error_t *Path::error_occurred() const
+svn_error_t *PathBase::error_occurred() const
{
return m_error_occurred;
}
-jboolean Path::isValid(const char *p)
+jboolean PathBase::isValid(const char *p)
{
if (p == NULL)
return JNI_FALSE;
@@ -136,3 +145,25 @@ jboolean Path::isValid(const char *p)
return JNI_FALSE;
}
}
+
+svn_error_t*
+Path::initfunc(const char*& path, SVN::Pool& pool)
+{
+ return JNIUtil::preprocessPath(path, pool.getPool());
+}
+
+svn_error_t*
+URL::initfunc(const char*& path, SVN::Pool& pool)
+{
+ if (svn_path_is_url(path))
+ return JNIUtil::preprocessPath(path, pool.getPool());
+ return svn_error_createf(SVN_ERR_BAD_URL, NULL,
+ _("Not an URL: %s"), path);
+}
+
+svn_error_t*
+Relpath::initfunc(const char*& path, SVN::Pool& pool)
+{
+ path = svn_relpath__internal_style(path, pool.getPool());
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/Path.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/Path.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/Path.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/Path.h Tue Oct 15 08:52:06 2013
@@ -24,18 +24,19 @@
* @brief Interface of the C++ class Path.
*/
-#ifndef PATH_H
-#define PATH_H
+#ifndef JAVAHL_PATH_H
+#define JAVAHL_PATH_H
#include <string>
#include <jni.h>
#include "Pool.h"
struct svn_error_t;
+
/**
* Encapsulation for Subversion Path handling
*/
-class Path
+class PathBase
{
private:
// The path to be stored.
@@ -48,9 +49,11 @@ class Path
*
* @param pi_path Path string
*/
- void init(const char *pi_path, SVN::Pool &in_pool);
+ void init(const char *pi_path,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool);
- public:
+ protected:
/**
* Constructor that takes a string as parameter.
* The string is converted to subversion internal
@@ -58,27 +61,31 @@ class Path
*
* @param pi_path Path string
*/
- Path(const std::string &pi_path, SVN::Pool &in_pool);
+ PathBase(const std::string &pi_path,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool);
/**
* Constructor
*
- * @see Path::Path (const std::string &)
+ * @see PathBase::PathBase (const std::string &)
* @param pi_path Path string
*/
- Path(const char *pi_path, SVN::Pool &in_pool);
+ PathBase(const char *pi_path,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool);
/**
- * Copy constructor
- *
- * @param pi_path Path to be copied
+ * Constructor from a Java string.
*/
- Path(const Path &pi_path, SVN::Pool &in_pool);
+ PathBase(jstring jpath,
+ svn_error_t* initfunc(const char*&, SVN::Pool&),
+ SVN::Pool &in_pool);
/**
* Assignment operator
*/
- Path &operator=(const Path&);
+ PathBase &operator=(const PathBase&);
/**
* @return Path string
@@ -92,6 +99,7 @@ class Path
svn_error_t *error_occurred() const;
+public:
/**
* Returns whether @a path is non-NULL and passes the @c
* svn_path_check_valid() test.
@@ -101,4 +109,113 @@ class Path
static jboolean isValid(const char *path);
};
-#endif // PATH_H
+
+/**
+ * Dirent or URI
+ */
+class Path : protected PathBase
+{
+ public:
+ Path(const std::string &pi_path, SVN::Pool &in_pool)
+ : PathBase(pi_path, initfunc, in_pool)
+ {}
+
+ Path(const char *pi_path, SVN::Pool &in_pool)
+ : PathBase(pi_path, initfunc, in_pool)
+ {}
+
+ Path(jstring jpath, SVN::Pool &in_pool)
+ : PathBase(jpath, initfunc, in_pool)
+ {}
+
+ Path& operator=(const Path& that)
+ {
+ PathBase::operator=(that);
+ return *this;
+ }
+
+ const std::string &path() const { return PathBase::path(); }
+ const char *c_str() const { return PathBase::c_str(); }
+
+ svn_error_t *error_occurred() const
+ {
+ return PathBase::error_occurred();
+ }
+
+ private:
+ static svn_error_t* initfunc(const char*&, SVN::Pool&);
+};
+
+/**
+ * URL
+ */
+class URL : protected PathBase
+{
+ public:
+ URL(const std::string &pi_path, SVN::Pool &in_pool)
+ : PathBase(pi_path, initfunc, in_pool)
+ {}
+
+ URL(const char *pi_path, SVN::Pool &in_pool)
+ : PathBase(pi_path, initfunc, in_pool)
+ {}
+
+ URL(jstring jpath, SVN::Pool &in_pool)
+ : PathBase(jpath, initfunc, in_pool)
+ {}
+
+ URL& operator=(const URL& that)
+ {
+ PathBase::operator=(that);
+ return *this;
+ }
+
+ const std::string &path() const { return PathBase::path(); }
+ const char *c_str() const { return PathBase::c_str(); }
+
+ svn_error_t *error_occurred() const
+ {
+ return PathBase::error_occurred();
+ }
+
+ private:
+ static svn_error_t* initfunc(const char*&, SVN::Pool&);
+};
+
+/**
+ * Relative path
+ */
+class Relpath : protected PathBase
+{
+ public:
+ Relpath(const std::string &pi_path, SVN::Pool &in_pool)
+ : PathBase(pi_path, initfunc, in_pool)
+ {}
+
+ Relpath(const char *pi_path, SVN::Pool &in_pool)
+ : PathBase(pi_path, initfunc, in_pool)
+ {}
+
+ Relpath(jstring jpath, SVN::Pool &in_pool)
+ : PathBase(jpath, initfunc, in_pool)
+ {}
+
+ Relpath& operator=(const Relpath& that)
+ {
+ PathBase::operator=(that);
+ return *this;
+ }
+
+ const std::string &path() const { return PathBase::path(); }
+ const char *c_str() const { return PathBase::c_str(); }
+
+ svn_error_t *error_occurred() const
+ {
+ return PathBase::error_occurred();
+ }
+
+ private:
+ static svn_error_t* initfunc(const char*&, SVN::Pool&);
+};
+
+#endif // JAVAHL_PATH_H
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/Prompter.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/Prompter.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/Prompter.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/Prompter.cpp Tue Oct 15 08:52:06 2013
@@ -40,9 +40,9 @@
* @param jprompter a global reference to the Java callback object
*/
Prompter::Prompter(jobject jprompter)
-{
- m_prompter = jprompter;
-}
+ : m_prompter(jprompter),
+ m_maySave(false)
+{}
Prompter::~Prompter()
{
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/ProplistCallback.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/ProplistCallback.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/ProplistCallback.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/ProplistCallback.cpp Tue Oct 15 08:52:06 2013
@@ -104,7 +104,7 @@ svn_error_t *ProplistCallback::singlePat
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN(SVN_NO_ERROR);
- jobject jmap = CreateJ::PropertyMap(prop_hash);
+ jobject jmap = CreateJ::PropertyMap(prop_hash, pool);
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN(SVN_NO_ERROR);
@@ -159,7 +159,7 @@ svn_error_t *ProplistCallback::singlePat
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN(SVN_NO_ERROR);
- jobject jmap = CreateJ::PropertyMap(prop_hash);
+ jobject jmap = CreateJ::PropertyMap(prop_hash, pool);
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN(SVN_NO_ERROR);
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.cpp Tue Oct 15 08:52:06 2013
@@ -44,60 +44,117 @@ RevisionRange::~RevisionRange()
// explicitly destroyed.
}
-const svn_opt_revision_range_t *RevisionRange::toRange(SVN::Pool &pool) const
+namespace {
+void get_range_info(jobject jrange,
+ svn_opt_revision_t* range_start,
+ svn_opt_revision_t* range_end,
+ svn_boolean_t* range_inheritable)
{
JNIEnv *env = JNIUtil::getEnv();
jclass clazz = env->FindClass(JAVA_PACKAGE"/types/RevisionRange");
if (JNIUtil::isExceptionThrown())
- return NULL;
+ return;
- static jmethodID fmid = 0;
- if (fmid == 0)
+ if (range_start)
{
- fmid = env->GetMethodID(clazz, "getFromRevision",
- "()L"JAVA_PACKAGE"/types/Revision;");
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
+
+ static jmethodID fmid = 0;
+ if (fmid == 0)
+ {
+ fmid = env->GetMethodID(clazz, "getFromRevision",
+ "()L"JAVA_PACKAGE"/types/Revision;");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ jobject jstartRevision = env->CallObjectMethod(jrange, fmid);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ Revision startRevision(jstartRevision);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ *range_start = *startRevision.revision();
+ if (JNIUtil::isExceptionThrown())
+ return;
}
- static jmethodID tmid = 0;
- if (tmid == 0)
+ if (range_end)
{
- tmid = env->GetMethodID(clazz, "getToRevision",
- "()L"JAVA_PACKAGE"/types/Revision;");
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
+ static jmethodID tmid = 0;
+ if (tmid == 0)
+ {
+ tmid = env->GetMethodID(clazz, "getToRevision",
+ "()L"JAVA_PACKAGE"/types/Revision;");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ jobject jendRevision = env->CallObjectMethod(jrange, tmid);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ Revision endRevision(jendRevision);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ *range_end = *endRevision.revision();
+ if (JNIUtil::isExceptionThrown())
+ return;
}
- jobject jstartRevision = env->CallObjectMethod(m_range, fmid);
- if (JNIUtil::isExceptionThrown())
- return NULL;
+ if (range_inheritable)
+ {
+ static jmethodID imid = 0;
+ if (imid == 0 && range_inheritable)
+ {
+ imid = env->GetMethodID(clazz, "isInheritable", "()Z");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ jboolean inheritable = env->CallBooleanMethod(jrange, imid);
+ if (JNIUtil::isExceptionThrown())
+ return;
+ *range_inheritable = inheritable;
+ }
+}
+} // anonymous namespace
- Revision startRevision(jstartRevision);
+svn_merge_range_t* RevisionRange::toMergeRange(SVN::Pool &pool) const
+{
+ svn_opt_revision_t range_start, range_end;
+ svn_boolean_t range_inheritable;
+ get_range_info(m_range, &range_start, &range_end, &range_inheritable);
if (JNIUtil::isExceptionThrown())
return NULL;
- jobject jendRevision = env->CallObjectMethod(m_range, tmid);
- if (JNIUtil::isExceptionThrown())
- return NULL;
+ if (range_start.kind != svn_opt_revision_number
+ || range_end.kind != svn_opt_revision_number)
+ JNIUtil::raiseThrowable("java.lang.InvalidStateException",
+ "Revsision ranges must contain revision numbers");
- Revision endRevision(jendRevision);
- if (JNIUtil::isExceptionThrown())
- return NULL;
+ svn_merge_range_t* range =
+ static_cast<svn_merge_range_t*>
+ (apr_palloc(pool.getPool(), sizeof(*range)));
+
+ range->start = range_start.value.number;
+ range->end = range_end.value.number;
+ range->inheritable = range_inheritable;
+ return range;
+}
+svn_opt_revision_range_t *RevisionRange::toRange(SVN::Pool &pool) const
+{
svn_opt_revision_range_t *range =
- reinterpret_cast<svn_opt_revision_range_t *>
+ static_cast<svn_opt_revision_range_t *>
(apr_palloc(pool.getPool(), sizeof(*range)));
- range->start = *startRevision.revision();
- if (JNIUtil::isExceptionThrown())
- return NULL;
-
- range->end = *endRevision.revision();
+ get_range_info(m_range, &range->start, &range->end, NULL);
if (JNIUtil::isExceptionThrown())
- return NULL;
-
+ range = NULL;
return range;
}
@@ -112,13 +169,14 @@ RevisionRange::makeJRevisionRange(svn_me
static jmethodID rangeCtor = 0;
if (rangeCtor == 0)
{
- rangeCtor = env->GetMethodID(rangeClazz, "<init>", "(JJ)V");
+ rangeCtor = env->GetMethodID(rangeClazz, "<init>", "(JJZ)V");
if (JNIUtil::isJavaExceptionThrown())
return NULL;
}
jobject jrange = env->NewObject(rangeClazz, rangeCtor,
- (jlong) range->start,
- (jlong) range->end);
+ jlong(range->start),
+ jlong(range->end),
+ jboolean(range->inheritable));
if (JNIUtil::isJavaExceptionThrown())
return NULL;
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/RevisionRange.h Tue Oct 15 08:52:06 2013
@@ -29,6 +29,7 @@
#include <jni.h>
#include "svn_types.h"
+#include "svn_opt.h"
#include "Pool.h"
@@ -53,7 +54,12 @@ class RevisionRange
/**
* Return an svn_opt_revision_range_t.
*/
- const svn_opt_revision_range_t *toRange(SVN::Pool &pool) const;
+ svn_opt_revision_range_t *toRange(SVN::Pool &pool) const;
+
+ /**
+ * Return an svn_merge_range_t.
+ */
+ svn_merge_range_t* toMergeRange(SVN::Pool &pool) const;
/**
* Make a (single) RevisionRange Java object.
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.cpp Tue Oct 15 08:52:06 2013
@@ -97,3 +97,29 @@ inline void SVNBase::findCppAddrFieldID(
}
}
}
+
+jobject SVNBase::createCppBoundObject(const char *clazzName)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ // Create java session object
+ jclass clazz = env->FindClass(clazzName);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ static jmethodID ctor = 0;
+ if (ctor == 0)
+ {
+ ctor = env->GetMethodID(clazz, "<init>", "(J)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ }
+
+ jlong cppAddr = this->getCppAddr();
+
+ jobject jself = env->NewObject(clazz, ctor, cppAddr);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jself;
+}
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.h (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/SVNBase.h Tue Oct 15 08:52:06 2013
@@ -82,6 +82,11 @@ class SVNBase
*/
void dispose(jobject jthis, jfieldID *fid, const char *className);
+ /**
+ * Instantiates java object attached to this base object
+ */
+ jobject createCppBoundObject(const char *clazzName);
+
private:
/**
* If the value pointed to by @a fid is zero, find the @c jfieldID
Modified: subversion/branches/cache-server/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/bindings/javahl/native/SVNClient.cpp?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/branches/cache-server/subversion/bindings/javahl/native/SVNClient.cpp Tue Oct 15 08:52:06 2013
@@ -30,6 +30,7 @@
#include "DiffSummaryReceiver.h"
#include "ClientContext.h"
#include "Prompter.h"
+#include "RemoteSession.h"
#include "Pool.h"
#include "Targets.h"
#include "Revision.h"
@@ -50,7 +51,7 @@
#include "CommitMessage.h"
#include "EnumMapper.h"
#include "StringArray.h"
-#include "RevpropTable.h"
+#include "PropertyTable.h"
#include "DiffOptions.h"
#include "CreateJ.h"
#include "svn_auth.h"
@@ -70,6 +71,7 @@
#include <vector>
#include <iostream>
#include <sstream>
+#include <string>
SVNClient::SVNClient(jobject jthis_in)
@@ -227,23 +229,23 @@ rev_range_vector_to_apr_array(std::vecto
std::vector<RevisionRange>::const_iterator it;
for (it = revRanges.begin(); it != revRanges.end(); ++it)
{
- if (it->toRange(subPool)->start.kind
- == svn_opt_revision_unspecified
- && it->toRange(subPool)->end.kind
- == svn_opt_revision_unspecified)
+ const svn_opt_revision_range_t *range = it->toRange(subPool);
+
+ if (range->start.kind == svn_opt_revision_unspecified
+ && range->end.kind == svn_opt_revision_unspecified)
{
- svn_opt_revision_range_t *range =
+ svn_opt_revision_range_t *full =
reinterpret_cast<svn_opt_revision_range_t *>
(apr_pcalloc(subPool.getPool(), sizeof(*range)));
- range->start.kind = svn_opt_revision_number;
- range->start.value.number = 1;
- range->end.kind = svn_opt_revision_head;
- APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
+ full->start.kind = svn_opt_revision_number;
+ full->start.value.number = 1;
+ full->end.kind = svn_opt_revision_head;
+ full->end.value.number = 0;
+ APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = full;
}
else
{
- APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
- it->toRange(subPool);
+ APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
}
if (JNIUtil::isExceptionThrown())
return NULL;
@@ -317,7 +319,7 @@ jlong SVNClient::checkout(const char *mo
}
void SVNClient::remove(Targets &targets, CommitMessage *message, bool force,
- bool keep_local, RevpropTable &revprops,
+ bool keep_local, PropertyTable &revprops,
CommitCallback *callback)
{
SVN::Pool subPool(pool);
@@ -417,7 +419,7 @@ jlongArray SVNClient::update(Targets &ta
void SVNClient::commit(Targets &targets, CommitMessage *message,
svn_depth_t depth, bool noUnlock, bool keepChangelist,
- StringArray &changelists, RevpropTable &revprops,
+ StringArray &changelists, PropertyTable &revprops,
CommitCallback *callback)
{
SVN::Pool subPool(pool);
@@ -442,7 +444,7 @@ void SVNClient::commit(Targets &targets,
void SVNClient::copy(CopySources ©Sources, const char *destPath,
CommitMessage *message, bool copyAsChild,
bool makeParents, bool ignoreExternals,
- RevpropTable &revprops, CommitCallback *callback)
+ PropertyTable &revprops, CommitCallback *callback)
{
SVN::Pool subPool(pool);
@@ -471,7 +473,7 @@ void SVNClient::copy(CopySources ©So
void SVNClient::move(Targets &srcPaths, const char *destPath,
CommitMessage *message, bool force, bool moveAsChild,
bool makeParents, bool metadataOnly, bool allowMixRev,
- RevpropTable &revprops, CommitCallback *callback)
+ PropertyTable &revprops, CommitCallback *callback)
{
SVN::Pool subPool(pool);
@@ -496,7 +498,7 @@ void SVNClient::move(Targets &srcPaths,
}
void SVNClient::mkdir(Targets &targets, CommitMessage *message,
- bool makeParents, RevpropTable &revprops,
+ bool makeParents, PropertyTable &revprops,
CommitCallback *callback)
{
SVN::Pool subPool(pool);
@@ -545,6 +547,7 @@ void SVNClient::resolve(const char *path
jlong SVNClient::doExport(const char *srcPath, const char *destPath,
Revision &revision, Revision &pegRevision,
bool force, bool ignoreExternals,
+ bool ignoreKeywords,
svn_depth_t depth, const char *nativeEOL)
{
SVN::Pool subPool(pool);
@@ -563,7 +566,7 @@ jlong SVNClient::doExport(const char *sr
destinationPath.c_str(),
pegRevision.revision(),
revision.revision(), force,
- ignoreExternals, FALSE,
+ ignoreExternals, ignoreKeywords,
depth,
nativeEOL, ctx,
subPool.getPool()),
@@ -613,7 +616,7 @@ void SVNClient::doImport(const char *pat
CommitMessage *message, svn_depth_t depth,
bool noIgnore, bool noAutoProps,
bool ignoreUnknownNodeTypes,
- RevpropTable &revprops,
+ PropertyTable &revprops,
ImportFilterCallback *ifCallback,
CommitCallback *commitCallback)
{
@@ -749,8 +752,6 @@ jobject
SVNClient::getMergeinfo(const char *target, Revision &pegRevision)
{
SVN::Pool subPool(pool);
- JNIEnv *env = JNIUtil::getEnv();
-
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
return NULL;
@@ -765,57 +766,7 @@ SVNClient::getMergeinfo(const char *targ
NULL);
if (mergeinfo == NULL)
return NULL;
-
- // Transform mergeinfo into Java Mergeinfo object.
- jclass clazz = env->FindClass(JAVA_PACKAGE "/types/Mergeinfo");
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
-
- static jmethodID ctor = 0;
- if (ctor == 0)
- {
- ctor = env->GetMethodID(clazz, "<init>", "()V");
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
- }
-
- static jmethodID addRevisions = 0;
- if (addRevisions == 0)
- {
- addRevisions = env->GetMethodID(clazz, "addRevisions",
- "(Ljava/lang/String;"
- "Ljava/util/List;)V");
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
- }
-
- jobject jmergeinfo = env->NewObject(clazz, ctor);
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
-
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(subPool.getPool(), mergeinfo);
- hi;
- hi = apr_hash_next(hi))
- {
- const void *path;
- void *val;
- apr_hash_this(hi, &path, NULL, &val);
-
- jstring jpath =
- JNIUtil::makeJString(reinterpret_cast<const char *>(path));
- jobject jranges =
- CreateJ::RevisionRangeList(reinterpret_cast<svn_rangelist_t *>(val));
-
- env->CallVoidMethod(jmergeinfo, addRevisions, jpath, jranges);
-
- env->DeleteLocalRef(jranges);
- env->DeleteLocalRef(jpath);
- }
-
- env->DeleteLocalRef(clazz);
-
- return jmergeinfo;
+ return CreateJ::Mergeinfo(mergeinfo, subPool.getPool());
}
void SVNClient::getMergeinfoLog(int type, const char *pathOrURL,
@@ -954,7 +905,7 @@ void SVNClient::propertySetRemote(const
const char *name,
CommitMessage *message,
JNIByteArray &value, bool force,
- RevpropTable &revprops,
+ PropertyTable &revprops,
CommitCallback *callback)
{
SVN::Pool subPool(pool);
@@ -1169,7 +1120,7 @@ void SVNClient::streamFileContent(const
return;
SVN_JNI_ERR(svn_client_cat2(outputStream.getStream(subPool),
- path, pegRevision.revision(),
+ intPath.c_str(), pegRevision.revision(),
revision.revision(), ctx, subPool.getPool()),
);
}
@@ -1465,19 +1416,14 @@ jobject SVNClient::revProperties(const c
&set_rev, ctx, subPool.getPool()),
NULL);
- return CreateJ::PropertyMap(props);
+ return CreateJ::PropertyMap(props, subPool.getPool());
}
-struct info_baton
-{
- std::vector<info_entry> infoVect;
- apr_pool_t *pool;
-};
-
void
-SVNClient::info2(const char *path, Revision &revision, Revision &pegRevision,
- svn_depth_t depth, StringArray &changelists,
- InfoCallback *callback)
+SVNClient::info2(const char *path,
+ Revision &revision, Revision &pegRevision, svn_depth_t depth,
+ svn_boolean_t fetchExcluded, svn_boolean_t fetchActualOnly,
+ StringArray &changelists, InfoCallback *callback)
{
SVN_JNI_NULL_PTR_EX(path, "path", );
@@ -1492,7 +1438,7 @@ SVNClient::info2(const char *path, Revis
SVN_JNI_ERR(svn_client_info3(checkedPath.c_str(),
pegRevision.revision(),
revision.revision(),
- depth, FALSE, TRUE,
+ depth, fetchExcluded, fetchActualOnly,
changelists.array(subPool),
InfoCallback::callback, callback,
ctx, subPool.getPool()), );
@@ -1525,6 +1471,63 @@ SVNClient::patch(const char *patchPath,
ctx, subPool.getPool()), );
}
+jobject
+SVNClient::openRemoteSession(const char* path, int retryAttempts)
+{
+ static const svn_opt_revision_t HEAD = { svn_opt_revision_head, {0}};
+ static const svn_opt_revision_t NONE = { svn_opt_revision_unspecified, {0}};
+
+ SVN_JNI_NULL_PTR_EX(path, "path", NULL);
+
+ SVN::Pool subPool(pool);
+ svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
+ if (ctx == NULL)
+ return NULL;
+
+ Path checkedPath(path, subPool);
+ SVN_JNI_ERR(checkedPath.error_occurred(), NULL);
+
+ struct PathInfo
+ {
+ std::string url;
+ std::string uuid;
+ static svn_error_t *callback(void *baton,
+ const char *,
+ const svn_client_info2_t *info,
+ apr_pool_t *)
+ {
+ PathInfo* const pi = static_cast<PathInfo*>(baton);
+ pi->url = info->URL;
+ pi->uuid = info->repos_UUID;
+ return SVN_NO_ERROR;
+ }
+ } path_info;
+
+ SVN_JNI_ERR(svn_client_info3(
+ checkedPath.c_str(), &NONE,
+ (svn_path_is_url(checkedPath.c_str()) ? &HEAD : &NONE),
+ svn_depth_empty, FALSE, TRUE, NULL,
+ PathInfo::callback, &path_info,
+ ctx, subPool.getPool()),
+ NULL);
+
+ /* Decouple the RemoteSession's context from SVNClient's context
+ by creating a copy of the prompter here. */
+ Prompter* prompter = new Prompter(context.getPrompter());
+ if (!prompter)
+ return NULL;
+
+ jobject jremoteSession = RemoteSession::open(
+ retryAttempts, path_info.url.c_str(), path_info.uuid.c_str(),
+ context.getConfigDirectory(),
+ context.getUsername(), context.getPassword(),
+ prompter, context.getSelf(), context.getTunnelCallback());
+ if (JNIUtil::isJavaExceptionThrown())
+ delete prompter;
+
+ return jremoteSession;
+}
+
ClientContext &
SVNClient::getClientContext()
{