Author: brane
Date: Fri Jun 21 08:51:49 2013
New Revision: 1495335
URL: http://svn.apache.org/r1495335
Log:
Add methods to the JavaHL RA api for manipulating revprops.
[in subversion/bindings/javahl/src/org/apache/subversion/javahl]
* ISVNRemote.java
(ISVNRemote.changeRevisionProperty,
ISVNRemote.getRevisionProperties,
ISVNRemote.getRevisionProperty): New methods.
* remote/RemoteSession.java
(ISVNRemote.changeRevisionProperty,
ISVNRemote.getRevisionProperties,
ISVNRemote.getRevisionProperty): New methods.
(RemoteSession.nativeChangeRevisionProperty): New native wrapper.
Modified:
subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp?rev=1495335&r1=1495334&r2=1495335&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
(original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp Fri
Jun 21 08:51:49 2013
@@ -27,10 +27,12 @@
#include <cstring>
#include <set>
+#include "JNIByteArray.h"
#include "JNIStringHolder.h"
#include "JNIUtil.h"
#include "svn_ra.h"
+#include "svn_string.h"
#include "CreateJ.h"
#include "EnumMapper.h"
@@ -387,6 +389,81 @@ RemoteSession::getRevisionByTimestamp(jl
return rev;
}
+namespace {
+bool byte_array_to_svn_string(JNIByteArray& ary, svn_string_t& str)
+{
+ if (ary.isNull())
+ return false;
+
+ str.data = reinterpret_cast<const char*>(ary.getBytes());
+ str.len = ary.getLength();
+ return true;
+}
+} // anonymous namespace
+
+void
+RemoteSession::changeRevisionProperty(
+ jlong jrevision, jstring jname,
+ jbyteArray jold_value, jbyteArray jvalue)
+{
+ JNIStringHolder name(jname);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ JNIByteArray old_value(jold_value);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ JNIByteArray value(jvalue);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ svn_string_t str_old_value;
+ svn_string_t* const p_old_value = &str_old_value;
+ svn_string_t* const* pp_old_value = NULL;
+ if (byte_array_to_svn_string(old_value, str_old_value))
+ pp_old_value = &p_old_value;
+
+ svn_string_t str_value;
+ svn_string_t* p_value = NULL;
+ if (byte_array_to_svn_string(value, str_value))
+ p_value = &str_value;
+
+ SVN::Pool subPool(pool);
+ SVN_JNI_ERR(svn_ra_change_rev_prop2(m_session,
+ svn_revnum_t(jrevision),
+ name, pp_old_value, p_value,
+ subPool.getPool()), );
+}
+
+jobject
+RemoteSession::getRevisionProperties(jlong jrevision)
+{
+ SVN::Pool subPool(pool);
+ apr_hash_t *props;
+ SVN_JNI_ERR(svn_ra_rev_proplist(m_session, svn_revnum_t(jrevision),
+ &props, subPool.getPool()),
+ NULL);
+
+ return CreateJ::PropertyMap(props);
+}
+
+jbyteArray
+RemoteSession::getRevisionProperty(jlong jrevision, jstring jname)
+{
+ JNIStringHolder name(jname);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+
+ SVN::Pool subPool(pool);
+ svn_string_t *propval;
+ SVN_JNI_ERR(svn_ra_rev_prop(m_session, svn_revnum_t(jrevision),
+ name, &propval, subPool.getPool()),
+ NULL);
+
+ return JNIUtil::makeJByteArray(propval);
+}
+
jobject
RemoteSession::getLocks(jstring jpath, jobject jdepth)
{
Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h?rev=1495335&r1=1495334&r2=1495335&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
(original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h Fri Jun
21 08:51:49 2013
@@ -65,8 +65,12 @@ class RemoteSession : public SVNBase
jstring getReposUUID();
jstring getReposRootUrl();
jlong getLatestRevision();
-
- jlong getRevisionByTimestamp(jlong timestamp);
+ jlong getRevisionByTimestamp(jlong jtimestamp);
+ void changeRevisionProperty(jlong jrevision, jstring jname,
+ jbyteArray jold_value,
+ jbyteArray jvalue);
+ jobject getRevisionProperties(jlong jrevision);
+ jbyteArray getRevisionProperty(jlong jrevision, jstring jname);
jobject getLocks(jstring jpath, jobject jdepth);
jobject checkPath(jstring jpath, jlong jrevision);
jboolean hasCapability(jstring capability);
Modified:
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp?rev=1495335&r1=1495334&r2=1495335&view=diff
==============================================================================
---
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
(original)
+++
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
Fri Jun 21 08:51:49 2013
@@ -154,6 +154,40 @@ Java_org_apache_subversion_javahl_remote
return ras->getRevisionByTimestamp(timestamp);
}
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_nativeChangeRevisionProperty(
+ JNIEnv *env, jobject jthis, jlong jrevision, jstring jname,
+ jbyteArray jold_value, jbyteArray jvalue)
+{
+ JNIEntry(RemoteSession, nativeChangeRevisionProperty);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, );
+
+ return ras->changeRevisionProperty(jrevision, jname, jold_value, jvalue);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getRevisionProperties(
+ JNIEnv *env, jobject jthis, jlong jrevision)
+{
+ JNIEntry(SVNReposAccess, getRevisionProperties);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getRevisionProperties(jrevision);
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getRevisionProperty(
+ JNIEnv *env, jobject jthis, jlong jrevision, jstring jname)
+{
+ JNIEntry(SVNReposAccess, getRevisionProperty);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getRevisionProperty(jrevision, jname);
+}
+
JNIEXPORT jobject JNICALL
Java_org_apache_subversion_javahl_remote_RemoteSession_checkPath(
JNIEnv *env, jobject jthis, jstring jpath, jlong jrevision)
Modified:
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java?rev=1495335&r1=1495334&r2=1495335&view=diff
==============================================================================
---
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
(original)
+++
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
Fri Jun 21 08:51:49 2013
@@ -111,6 +111,56 @@ public interface ISVNRemote
long getRevisionByTimestamp(long timestamp) throws ClientException;
/**
+ * Change the value of an unversioned property.
+ * @param revision The revision to which the propery is attached
+ * @param propertyName The name of the propery
+ * @param oldValue The previous value of the property (see note below)
+ * @param newValue The new value of the property. If <code>newValue</code>
+ * is <code>null</code>, the property will be deleted.
+ *
+ * @node If the server has Capability.atomic_revprops and
+ * <code>oldValue</code> is not <code>null</code>, and the
+ * present value of the propery is not <code>oldValue</code>
+ * (e.g., if another client changed the property), then
+ * the operation will fail.
+ * @note If the server does not adveritse Capability.atomic_revprops,
+ * then <code>oldValue</code> <em>must</em> be <code>null</code>.
+ *
+ * @throws IllegalArgumentException if <code>oldValue</code> is not
+ * <code>null</code> and the server does not advertise the
+ * atomic_revprops capability.
+ * @throws ClientException
+ */
+ void changeRevisionProperty(long revision,
+ String propertyName,
+ byte[] oldValue,
+ byte[] newValue)
+ throws ClientException;
+
+ /**
+ * Return the set of unversioned properties set on <code>revision</code>
+ * in the session's repository.
+ * @throws ClientException
+ */
+ Map<String, byte[]> getRevisionProperties(long revision)
+ throws ClientException;
+
+ /**
+ * Return the value of unversioned property <code>propertyName</code>
+ * in <code>revision</code> in the session's repository.
+ * Returns <code>null</code> if the property does not exist.
+ * @throws ClientException
+ */
+ byte[] getRevisionProperty(long revision, String propertyName)
+ throws ClientException;
+
+ /**
+ * Create a commit editor instance, rooted at the current session URL.
+ * @throws ClientException
+ */
+ ISVNEditor getCommitEditor() throws ClientException;
+
+ /**
* Return the kind of the node in path at revision.
* @param path A path relative to the sessionn URL
* @throws ClientException
@@ -131,10 +181,11 @@ public interface ISVNRemote
throws ClientException;
/**
- * Create a commit editor instance, rooted at the current session URL.
+ * Check if the server associated with this session has
+ * the given <code>capability</code>.
* @throws ClientException
*/
- ISVNEditor getCommitEditor() throws ClientException;
+ boolean hasCapability(Capability capability) throws ClientException;
/**
* Enumeration of known capabilities of the repository and server.
@@ -212,11 +263,4 @@ public interface ISVNRemote
private String token;
}
-
- /**
- * Check if the server associated with this session has
- * the given <code>capability</code>.
- * @throws ClientException
- */
- boolean hasCapability(Capability capability) throws ClientException;
}
Modified:
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java?rev=1495335&r1=1495334&r2=1495335&view=diff
==============================================================================
---
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
(original)
+++
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
Fri Jun 21 08:51:49 2013
@@ -86,10 +86,25 @@ public class RemoteSession extends JNIOb
public native long getRevisionByTimestamp(long timestamp)
throws ClientException;
- public native NodeKind checkPath(String path, long revision)
+ public void changeRevisionProperty(long revision,
+ String propertyName,
+ byte[] oldValue,
+ byte[] newValue)
+ throws ClientException
+ {
+ if (oldValue != null && !hasCapability(Capability.atomic_revprops))
+ throw new IllegalArgumentException(
+ "oldValue must be null;\n" +
+ "The server does not support" +
+ " atomic revision property changes");
+ nativeChangeRevisionProperty(revision, propertyName,
+ oldValue, newValue);
+ }
+
+ public native Map<String, byte[]> getRevisionProperties(long revision)
throws ClientException;
- public native Map<String, Lock> getLocks(String path, Depth depth)
+ public native byte[] getRevisionProperty(long revision, String
propertyName)
throws ClientException;
public ISVNEditor getCommitEditor() throws ClientException
@@ -101,6 +116,12 @@ public class RemoteSession extends JNIOb
return ed;
}
+ public native NodeKind checkPath(String path, long revision)
+ throws ClientException;
+
+ public native Map<String, Lock> getLocks(String path, Depth depth)
+ throws ClientException;
+
public boolean hasCapability(Capability capability)
throws ClientException
{
@@ -118,9 +139,17 @@ public class RemoteSession extends JNIOb
super(cppAddr);
}
+ /*
+ * Wrapped private native implementation declarations.
+ */
private native void nativeDispose();
-
- private native boolean nativeHasCapability(String capability);
+ private native void nativeChangeRevisionProperty(long revision,
+ String propertyName,
+ byte[] oldValue,
+ byte[] newValue)
+ throws ClientException;
+ private native boolean nativeHasCapability(String capability)
+ throws ClientException;
/*
* NOTE: This field is accessed from native code for callbacks.
Modified:
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1495335&r1=1495334&r2=1495335&view=diff
==============================================================================
---
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
(original)
+++
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
Fri Jun 21 08:51:49 2013
@@ -26,11 +26,13 @@ import org.apache.subversion.javahl.*;
import org.apache.subversion.javahl.remote.*;
import org.apache.subversion.javahl.types.*;
+import java.util.Arrays;
import java.util.Date;
import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.io.IOException;
+import java.nio.charset.Charset;
/**
* This class is used for testing the SVNReposAccess class
@@ -248,4 +250,81 @@ public class SVNRemoteTests extends SVNT
ISVNRemote session = getSession();
assert(session.hasCapability(ISVNRemote.Capability.depth));
}
+
+ public void testChangeRevpropNoAtomic() throws Exception
+ {
+ Charset UTF8 = Charset.forName("UTF-8");
+ ISVNRemote session = getSession();
+
+ boolean atomic =
+ session.hasCapability(ISVNRemote.Capability.atomic_revprops);
+
+ if (atomic)
+ return;
+
+ boolean exceptioned = false;
+ try
+ {
+ byte[] oldValue = "bumble".getBytes(UTF8);
+ byte[] newValue = "bee".getBytes(UTF8);
+ session.changeRevisionProperty(1, "svn:author",
+ oldValue, newValue);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ exceptioned = true;
+ }
+ assert(exceptioned);
+ }
+
+ public void testChangeRevpropAtomic() throws Exception
+ {
+ Charset UTF8 = Charset.forName("UTF-8");
+ ISVNRemote session = getSession();
+
+ boolean atomic =
+ session.hasCapability(ISVNRemote.Capability.atomic_revprops);
+
+ if (!atomic)
+ return;
+
+ byte[] oldValue = USERNAME.getBytes(UTF8);
+ byte[] newValue = "rayjandom".getBytes(UTF8);
+ try
+ {
+ session.changeRevisionProperty(1, "svn:author",
+ oldValue, newValue);
+ }
+ catch (ClientException ex)
+ {
+ String msg = ex.getMessage();
+ int index = msg.indexOf('\n');
+ assertEquals(msg.substring(0, index),
+ "Disabled repository feature");
+ return;
+ }
+
+ byte[] check = client.revProperty(getTestRepoUrl(), "svn:author",
+ Revision.getInstance(1));
+ assertTrue(Arrays.equals(newValue, check));
+ }
+
+ public void testGetRevpropList() throws Exception
+ {
+ Charset UTF8 = Charset.forName("UTF-8");
+ ISVNRemote session = getSession();
+
+ Map<String, byte[]> proplist = session.getRevisionProperties(1);
+ assertTrue(Arrays.equals(proplist.get("svn:author"),
+ USERNAME.getBytes(UTF8)));
+ }
+
+ public void testGetRevprop() throws Exception
+ {
+ Charset UTF8 = Charset.forName("UTF-8");
+ ISVNRemote session = getSession();
+
+ byte[] propval = session.getRevisionProperty(1, "svn:author");
+ assertTrue(Arrays.equals(propval, USERNAME.getBytes(UTF8)));
+ }
}