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/10/15 06:29:52 UTC
svn commit: r1532182 - in /subversion/trunk: ./
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/
subversion/bindings/javahl/src/org/apa...
Author: brane
Date: Tue Oct 15 04:29:52 2013
New Revision: 1532182
URL: http://svn.apache.org/r1532182
Log:
Expose the tunnel management callbacks in JavaHL.
* build.conf (private-built-includes): Add new generated JavaHL headers.
[in subversion/bindings/javahl/src/org/apache/subversion/javahl]
* callback/TunnelAgent.java: New public interface.
* ISVNClient.java, SVNClient.java (ISVNClient.setTunnelAgent): New method.
* remote/RemoteFactory.java
(RemoteFactory.RemoteFactory): New parameter tunnelAgent.
(RemoteFactory.setTunnelAgent): New method.
(RemoteFactory.tunnelAgent): New member.
(RemoteFactory.open): New parameter tunnelAgent; all callers updated.
* util/TunnelChannel.java, util/RequestChannel.java, util/ResponseChannel.java:
New private utility classes; implement byte channes for tunnels.
[in subversion/bindings/javahl/native]
* OperationContext.h
(OperationContext::m_jtunnelcb): New class member.
(OperationContext::checkTunnel,
OperationContext::openTunnel,
OperationContext::closeTUnnel): New static methods.
(OperationContext::setTunnelCallback,
OperationContext::getTunnelCallback): New methods.
* OperationContext.cpp
(OperationContext::OperationContext): Initialise m_jtunnelcb.
(OperationContext::~OperationContext): Release m_jtunnelcb.
(OperationContext::checkTunnel, OperationContext::openTunnel,
OperationContext::closeTUnnel, OperationContext::setTunnelCallback,
OperationContext::getTunnelCallback): Implement.
(TunnelContext): New local helper class.
(create_Channel, create_RequestChannel,
create_ResponseChannel): new local helper functions.
* ClientContext.h (ClientContext::setTunnelCallback): Override method.
* ClientContext.cpp (ClientContext::ClientContext): Set tunnel callbacks.
(ClientContext::setTunnelCallback): Implement.
* RemoteSessionContext.h
(RemoteSessionContext::RemoteSessionContext): New parameter jtunnelcb.
* RemoteSessionContext.cpp
(RemoteSessionContext::RemoteSessionContext): Update signature and
set tunnel callbacks.
* RemoteSession.h (RemoteSession::open, RemoteSession::RemoteSession):
New parameter jtunnelcb.
* RemoteSession.cpp (RemoteSession::open, RemoteSession::RemoteSession):
Update signature and implementation.
* SVNClient.cpp (SVNClient::openRemoteSession): Pass the tunnel callback
from the context to the session factory.
* org_apache_subversion_javahl_SVNClient.cpp
(Java_org_apache_subversion_javahl_SVNClient_setTunnelAgent):
Implement native method.
* org_apache_subversion_javahl_remote_RemoteFactory.cpp
(Java_org_apache_subversion_javahl_remote_RemoteFactory_open)
Update native method.
* org_apache_subversion_javahl_util_TunnelChannel.cpp: New.
Implementation of TunnelChannel, RequestChannel and ResponseChannel.
* JNIByteArray.h (JNIByteArray::m_abortOnRelease): New member.
(JNIByteArray::JNIByteArray): New default parameter abortOnRelease.
* JNIByteArray.cpp (JNIByteArray::JNIByteArray): Update constructor.
(JNIByteArray::~JNIByteArray): Optionally commit array changes.
[in subversion/bindings/javahl/tests/org/apache/subversion/javahl]
* SVNTests.java (SVNTests.DefaultProgressListener): Make protected.
* BasicTests.java (BasicTests.Tunnel): New helper class.
(BasicTests.testTunnelAgent): New test case for tunnels.
* SVNRemoteTests.java
(SVNRemoteTests.testSessionGC) Update factory construction.
(SVNRemoteTests.testGetSession_ConfigConstructor): Likewise.
Added:
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java
Modified:
subversion/trunk/build.conf
subversion/trunk/subversion/bindings/javahl/native/ClientContext.cpp
subversion/trunk/subversion/bindings/javahl/native/ClientContext.h
subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.cpp
subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.h
subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp
subversion/trunk/subversion/bindings/javahl/native/OperationContext.h
subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp
subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h
subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Tue Oct 15 04:29:52 2013
@@ -79,6 +79,9 @@ private-built-includes =
subversion/bindings/javahl/include/org_apache_subversion_javahl_util_ConfigImpl_Category.h
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_TunnelChannel.h
+ subversion/bindings/javahl/include/org_apache_subversion_javahl_util_RequestChannel.h
+ subversion/bindings/javahl/include/org_apache_subversion_javahl_util_ResponseChannel.h
test-scripts =
subversion/tests/cmdline/*_tests.py
Modified: subversion/trunk/subversion/bindings/javahl/native/ClientContext.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/ClientContext.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/ClientContext.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/ClientContext.cpp Tue Oct 15 04:29:52 2013
@@ -70,12 +70,38 @@ ClientContext::ClientContext(jobject jsv
m_context->conflict_baton2 = m_jctx;
m_context->client_name = getClientName();
+
+ if (m_jtunnelcb)
+ {
+ m_context->check_tunnel_func = checkTunnel;
+ m_context->open_tunnel_func = openTunnel;
+ m_context->close_tunnel_func = closeTunnel;
+ m_context->tunnel_baton = m_jtunnelcb;
+ }
}
ClientContext::~ClientContext()
{
}
+void ClientContext::setTunnelCallback(jobject jtunnelcb)
+{
+ OperationContext::setTunnelCallback(jtunnelcb);
+ if (m_jtunnelcb)
+ {
+ m_context->check_tunnel_func = checkTunnel;
+ m_context->open_tunnel_func = openTunnel;
+ m_context->close_tunnel_func = closeTunnel;
+ m_context->tunnel_baton = m_jtunnelcb;
+ }
+ else
+ {
+ m_context->check_tunnel_func = NULL;
+ m_context->open_tunnel_func = NULL;
+ m_context->close_tunnel_func = NULL;
+ m_context->tunnel_baton = NULL;
+ }
+}
/* Helper function to make sure that we don't keep dangling pointers in ctx.
Note that this function might be called multiple times if getContext()
Modified: subversion/trunk/subversion/bindings/javahl/native/ClientContext.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/ClientContext.h?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/ClientContext.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/ClientContext.h Tue Oct 15 04:29:52 2013
@@ -64,6 +64,7 @@ class ClientContext : public OperationCo
public:
ClientContext(jobject jsvnclient, SVN::Pool &pool);
virtual ~ClientContext();
+ virtual void setTunnelCallback(jobject jtunnelcb);
svn_client_ctx_t *getContext(CommitMessage *message, SVN::Pool &in_pool);
};
Modified: subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.cpp Tue Oct 15 04:29:52 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/trunk/subversion/bindings/javahl/native/JNIByteArray.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.h?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/JNIByteArray.h Tue Oct 15 04:29:52 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/trunk/subversion/bindings/javahl/native/OperationContext.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/OperationContext.cpp Tue Oct 15 04:29:52 2013
@@ -44,7 +44,8 @@ OperationContext::OperationContext(SVN::
m_cancelOperation(0),
m_pool(&pool),
m_jctx(NULL),
- m_jcfgcb(NULL)
+ m_jcfgcb(NULL),
+ m_jtunnelcb(NULL)
{}
void
@@ -92,6 +93,8 @@ OperationContext::~OperationContext()
env->DeleteGlobalRef(m_jctx);
if (m_jcfgcb)
env->DeleteGlobalRef(m_jcfgcb);
+ if (m_jtunnelcb)
+ env->DeleteGlobalRef(m_jtunnelcb);
}
apr_hash_t *
@@ -295,6 +298,26 @@ const Prompter& OperationContext::getPro
return *m_prompter;
}
+void OperationContext::setTunnelCallback(jobject jtunnelcb)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+ if (jtunnelcb)
+ {
+ jtunnelcb = env->NewGlobalRef(jtunnelcb);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ if (m_jtunnelcb)
+ env->DeleteGlobalRef(m_jtunnelcb);
+ m_jtunnelcb = jtunnelcb;
+}
+
+jobject OperationContext::getTunnelCallback() const
+{
+ return m_jtunnelcb;
+}
+
void
OperationContext::cancelOperation()
{
@@ -440,3 +463,177 @@ OperationContext::notifyConfigLoad()
env->CallVoidMethod(jcbimpl, dispose_mid);
env->DeleteLocalRef(jcbimpl);
}
+
+namespace {
+class TunnelContext
+{
+public:
+ explicit TunnelContext(apr_pool_t *pool)
+ : request_in(NULL),
+ request_out(NULL),
+ response_in(NULL),
+ response_out(NULL)
+ {
+ status = apr_file_pipe_create_ex(&request_in, &request_out,
+ APR_FULL_BLOCK, pool);
+ if (!status)
+ status = apr_file_pipe_create_ex(&response_in, &response_out,
+ APR_FULL_BLOCK, pool);
+ }
+
+ apr_file_t *request_in;
+ apr_file_t *request_out;
+ apr_file_t *response_in;
+ apr_file_t *response_out;
+ apr_status_t status;
+};
+
+jobject create_Channel(const char *class_name, JNIEnv *env, apr_file_t *fd)
+{
+ jclass cls = env->FindClass(class_name);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ jmethodID ctor = env->GetMethodID(cls, "<init>", "(J)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ return env->NewObject(cls, ctor, reinterpret_cast<jlong>(fd));
+}
+
+jobject create_RequestChannel(JNIEnv *env, apr_file_t *fd)
+{
+ return create_Channel(JAVA_PACKAGE"/util/RequestChannel", env, fd);
+}
+jobject create_ResponseChannel(JNIEnv *env, apr_file_t *fd)
+{
+ return create_Channel(JAVA_PACKAGE"/util/ResponseChannel", env, fd);
+}
+} // anonymous namespace
+
+svn_boolean_t
+OperationContext::checkTunnel(void *tunnel_baton, const char *tunnel_name)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ jstring jtunnel_name = JNIUtil::makeJString(tunnel_name);
+ if (JNIUtil::isJavaExceptionThrown())
+ return false;
+
+ static jmethodID mid = 0;
+ if (0 == mid)
+ {
+ jclass cls = env->FindClass(JAVA_PACKAGE"/callback/TunnelAgent");
+ if (JNIUtil::isJavaExceptionThrown())
+ return false;
+ mid = env->GetMethodID(cls, "checkTunnel",
+ "(Ljava/lang/String;)Z");
+ if (JNIUtil::isJavaExceptionThrown())
+ return false;
+ }
+
+ jobject jtunnelcb = jobject(tunnel_baton);
+ jboolean check = env->CallBooleanMethod(jtunnelcb, mid, jtunnel_name);
+ if (JNIUtil::isJavaExceptionThrown())
+ return false;
+
+ return svn_boolean_t(check);
+}
+
+svn_error_t *
+OperationContext::openTunnel(apr_file_t **request, apr_file_t **response,
+ void **tunnel_context, void *tunnel_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port,
+ apr_pool_t *pool)
+{
+ TunnelContext *tc = new TunnelContext(pool);
+ if (tc->status)
+ {
+ delete tc;
+ return svn_error_trace(
+ svn_error_wrap_apr(tc->status, _("Could not open tunnel streams")));
+ }
+
+ *request = tc->request_out;
+ *response = tc->response_in;
+
+ JNIEnv *env = JNIUtil::getEnv();
+
+ jobject jrequest = create_RequestChannel(env, tc->request_in);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ jobject jresponse = create_ResponseChannel(env, tc->response_out);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ jstring jtunnel_name = JNIUtil::makeJString(tunnel_name);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ jstring juser = JNIUtil::makeJString(user);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ jstring jhostname = JNIUtil::makeJString(hostname);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ static jmethodID mid = 0;
+ if (0 == mid)
+ {
+ jclass cls = env->FindClass(JAVA_PACKAGE"/callback/TunnelAgent");
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+ SVN_JNI_CATCH(
+ mid = env->GetMethodID(cls, "openTunnel",
+ "(Ljava/nio/channels/ReadableByteChannel;"
+ "Ljava/nio/channels/WritableByteChannel;"
+ "Ljava/lang/String;"
+ "Ljava/lang/String;"
+ "Ljava/lang/String;I)V"),
+ SVN_ERR_BASE);
+ }
+
+ jobject jtunnelcb = jobject(tunnel_baton);
+ SVN_JNI_CATCH(
+ env->CallVoidMethod(jtunnelcb, mid, jrequest, jresponse,
+ jtunnel_name, juser, jhostname, jint(port)),
+ SVN_ERR_BASE);
+
+ *tunnel_context = NULL;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+OperationContext::closeTunnel(void *tunnel_context, void *tunnel_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port)
+{
+ delete static_cast<TunnelContext*>(tunnel_context);
+
+ jstring jtunnel_name = JNIUtil::makeJString(tunnel_name);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ jstring juser = JNIUtil::makeJString(user);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ jstring jhostname = JNIUtil::makeJString(hostname);
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+ JNIEnv *env = JNIUtil::getEnv();
+
+ static jmethodID mid = 0;
+ if (0 == mid)
+ {
+ jclass cls = env->FindClass(JAVA_PACKAGE"/callback/TunnelAgent");
+ SVN_JNI_CATCH(, SVN_ERR_BASE);
+ SVN_JNI_CATCH(
+ mid = env->GetMethodID(cls, "closeTunnel",
+ "(Ljava/lang/String;"
+ "Ljava/lang/String;"
+ "Ljava/lang/String;I)V"),
+ SVN_ERR_BASE);
+ }
+
+ jobject jtunnelcb = jobject(tunnel_baton);
+ SVN_JNI_CATCH(
+ env->CallVoidMethod(jtunnelcb, mid,
+ jtunnel_name, juser, jhostname, jint(port)),
+ SVN_ERR_BASE);
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/bindings/javahl/native/OperationContext.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/OperationContext.h?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/OperationContext.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/OperationContext.h Tue Oct 15 04:29:52 2013
@@ -59,9 +59,27 @@ class OperationContext
jobject m_jctx;
jobject m_jcfgcb;
+ jobject m_jtunnelcb;
+
static void progress(apr_off_t progressVal, apr_off_t total,
void *baton, apr_pool_t *pool);
void notifyConfigLoad();
+
+ static svn_boolean_t checkTunnel(
+ void *tunnel_baton, const char *tunnel_name);
+
+ static svn_error_t *openTunnel(
+ apr_file_t **request, apr_file_t **response,
+ void **tunnel_context, void *tunnel_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port,
+ apr_pool_t *pool);
+
+ static svn_error_t *closeTunnel(
+ void *tunnel_context, void *tunnel_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port);
+
public:
OperationContext(SVN::Pool &pool);
void attachJavaObject(jobject contextHolder, const char *contextClassType, const char *contextFieldName, jfieldID * ctxFieldID);
@@ -98,6 +116,9 @@ class OperationContext
static svn_error_t * clientName(void *baton, const char **name, apr_pool_t *pool);
virtual const char * getClientName() const;
+
+ virtual void setTunnelCallback(jobject jtunnelcb);
+ jobject getTunnelCallback() const;
};
#endif // JAVAHL_OPERATION_CONTEXT_H
Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSession.cpp Tue Oct 15 04:29:52 2013
@@ -68,7 +68,7 @@ RemoteSession::open(jint jretryAttempts,
jstring jurl, jstring juuid,
jstring jconfigDirectory,
jstring jusername, jstring jpassword,
- jobject jprompter, jobject jprogress)
+ jobject jprompter, jobject jprogress, jobject jtunnelcb)
{
JNIEnv *env = JNIUtil::getEnv();
@@ -111,7 +111,7 @@ RemoteSession::open(jint jretryAttempts,
jobject jremoteSession = open(
jretryAttempts, url.c_str(), uuid,
(jconfigDirectory ? configDirectory.c_str() : NULL),
- usernameStr, passwordStr, prompter, jprogress);
+ usernameStr, passwordStr, prompter, jprogress, jtunnelcb);
if (JNIUtil::isExceptionThrown() || !jremoteSession)
{
delete prompter;
@@ -125,7 +125,7 @@ RemoteSession::open(jint jretryAttempts,
const char* url, const char* uuid,
const char* configDirectory,
const char* usernameStr, const char* passwordStr,
- Prompter*& prompter, jobject jprogress)
+ Prompter*& prompter, jobject jprogress, jobject jtunnelcb)
{
/*
* Initialize ra layer if we have not done so yet
@@ -139,7 +139,7 @@ RemoteSession::open(jint jretryAttempts,
RemoteSession* session = new RemoteSession(
jretryAttempts, url, uuid, configDirectory,
- usernameStr, passwordStr, prompter);
+ usernameStr, passwordStr, prompter, jtunnelcb);
if (JNIUtil::isJavaExceptionThrown() || !session)
{
delete session;
@@ -201,11 +201,11 @@ RemoteSession::RemoteSession(int retryAt
const char* url, const char* uuid,
const char* configDirectory,
const char* username, const char* password,
- Prompter*& prompter)
+ Prompter*& prompter, jobject jtunnelcb)
: m_session(NULL), m_context(NULL)
{
m_context = new RemoteSessionContext(
- pool, configDirectory, username, password, prompter);
+ pool, configDirectory, username, password, prompter, jtunnelcb);
if (JNIUtil::isJavaExceptionThrown())
return;
Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSession.h Tue Oct 15 04:29:52 2013
@@ -48,12 +48,14 @@ class RemoteSession : public SVNBase
jstring jurl, jstring juuid,
jstring jconfigDirectory,
jstring jusername, jstring jpassword,
- jobject jprompter, jobject jprogress);
+ jobject jprompter, jobject jprogress,
+ jobject jtunnelcb);
static jobject open(jint jretryAttempts,
const char* url, const char* uuid,
const char* configDirectory,
const char* username, const char* password,
- Prompter*& prompter, jobject jprogress);
+ Prompter*& prompter, jobject jprogress,
+ jobject jtunnelcb);
~RemoteSession();
void cancelOperation() const { m_context->cancelOperation(); }
@@ -117,7 +119,7 @@ class RemoteSession : public SVNBase
const char* url, const char* uuid,
const char* configDirectory,
const char* username, const char* password,
- Prompter*& prompter);
+ Prompter*& prompter, jobject jtunnelcb);
svn_ra_session_t* m_session;
RemoteSessionContext* m_context;
Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.cpp Tue Oct 15 04:29:52 2013
@@ -33,7 +33,7 @@
RemoteSessionContext::RemoteSessionContext(
SVN::Pool &pool, const char* configDirectory,
const char* usernameStr, const char* passwordStr,
- Prompter* prompter)
+ Prompter* prompter, jobject jtunnelcb)
: OperationContext(pool), m_raCallbacks(NULL)
{
setConfigDirectory(configDirectory);
@@ -44,6 +44,7 @@ RemoteSessionContext::RemoteSessionConte
password(passwordStr);
setPrompt(prompter);
+ setTunnelCallback(jtunnelcb);
/*
* Setup callbacks
@@ -68,6 +69,14 @@ RemoteSessionContext::RemoteSessionConte
* Don't set deprecated callback
*/
m_raCallbacks->open_tmp_file = NULL;
+
+ if (m_jtunnelcb)
+ {
+ m_raCallbacks->check_tunnel_func = checkTunnel;
+ m_raCallbacks->open_tunnel_func = openTunnel;
+ m_raCallbacks->close_tunnel_func = closeTunnel;
+ m_raCallbacks->tunnel_baton = m_jtunnelcb;
+ }
}
RemoteSessionContext::~RemoteSessionContext()
Modified: subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/RemoteSessionContext.h Tue Oct 15 04:29:52 2013
@@ -37,7 +37,7 @@ class RemoteSessionContext : public Oper
RemoteSessionContext(SVN::Pool &pool,
const char* jconfigDirectory,
const char* jusername, const char* jpassword,
- Prompter* prompter);
+ Prompter* prompter, jobject jtunnelcb);
virtual ~RemoteSessionContext();
void activate(jobject jremoteSession, jobject jprogress);
void * getCallbackBaton();
Modified: subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/SVNClient.cpp Tue Oct 15 04:29:52 2013
@@ -1511,10 +1511,6 @@ SVNClient::openRemoteSession(const char*
ctx, subPool.getPool()),
NULL);
- jobject jctx = context.getSelf();
- if (JNIUtil::isJavaExceptionThrown())
- return NULL;
-
/* Decouple the RemoteSession's context from SVNClient's context
by creating a copy of the prompter here. */
Prompter* prompter = new Prompter(context.getPrompter());
@@ -1525,7 +1521,7 @@ SVNClient::openRemoteSession(const char*
retryAttempts, path_info.url.c_str(), path_info.uuid.c_str(),
context.getConfigDirectory(),
context.getUsername(), context.getPassword(),
- prompter, jctx);
+ prompter, context.getSelf(), context.getTunnelCallback());
if (JNIUtil::isJavaExceptionThrown())
delete prompter;
Modified: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Tue Oct 15 04:29:52 2013
@@ -275,6 +275,21 @@ Java_org_apache_subversion_javahl_SVNCli
}
JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_SVNClient_setTunnelAgent
+(JNIEnv *env, jobject jthis, jobject jtunnelcb)
+{
+ JNIEntry(SVNClient, setPrompt);
+ SVNClient *cl = SVNClient::getCppObject(jthis);
+ if (cl == NULL)
+ {
+ JNIUtil::throwError(_("bad C++ this"));
+ return;
+ }
+
+ cl->getClientContext().setTunnelCallback(jtunnelcb);
+}
+
+JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNClient_logMessages
(JNIEnv *env, jobject jthis, jstring jpath, jobject jpegRevision,
jobject jranges, jboolean jstopOnCopy, jboolean jdisoverPaths,
Modified: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp Tue Oct 15 04:29:52 2013
@@ -40,7 +40,8 @@ Java_org_apache_subversion_javahl_remote
jstring jurl, jstring juuid,
jstring jconfigDirectory,
jstring jusername, jstring jpassword,
- jobject jprompter, jobject jprogress)
+ jobject jprompter, jobject jprogress,
+ jobject jtunnelcb)
{
//JNI macros need jthis but this is a static call
JNIEntryStatic(RemoteFactory, open);
@@ -50,7 +51,7 @@ Java_org_apache_subversion_javahl_remote
*/
jobject jremoteSession = RemoteSession::open(
jretryAttempts, jurl, juuid,
- jconfigDirectory, jusername, jpassword, jprompter, jprogress);
+ jconfigDirectory, jusername, jpassword, jprompter, jprogress, jtunnelcb);
if (JNIUtil::isJavaExceptionThrown())
return NULL;
Added: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp?rev=1532182&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp Tue Oct 15 04:29:52 2013
@@ -0,0 +1,223 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file org_apache_subversion_javahl_util_TunnelChannel.cpp
+ * @brief Implementation of the native methods in the Java classes
+ * TunnelChannel, RequestChannel and ResponseChannel
+ */
+
+#include <assert.h> // TEMPORARY until we handle weird byte arrays
+
+#include <string>
+
+#include <apr_file_io.h>
+
+#include "../include/org_apache_subversion_javahl_util_TunnelChannel.h"
+#include "../include/org_apache_subversion_javahl_util_RequestChannel.h"
+#include "../include/org_apache_subversion_javahl_util_ResponseChannel.h"
+
+#include "JNIUtil.h"
+#include "JNIStackElement.h"
+#include "JNIByteArray.h"
+
+#include "svn_private_config.h"
+
+namespace {
+apr_file_t* get_file_descriptor(jlong jfd)
+{
+ apr_file_t* fd = reinterpret_cast<apr_file_t*>(jfd);
+ if (!fd)
+ {
+ JNIUtil::throwNullPointerException("nativeChannel");
+ return NULL;
+ }
+ return fd;
+}
+
+void throw_IOException(const char* message, apr_status_t status)
+{
+ char buf[1024];
+ apr_strerror(status, buf, sizeof(buf) - 1);
+
+ std::string msg(message);
+ msg += ": ";
+ msg += buf;
+ JNIUtil::raiseThrowable("java/io/IOException", msg.c_str());
+}
+
+class ByteBufferProxy
+{
+public:
+ ByteBufferProxy(jobject buf, JNIEnv* env)
+ : m_buf(buf),
+ m_direct(env->GetDirectBufferAddress(buf)),
+ m_array(m_direct ? NULL : get_array(buf, env)),
+ m_array_offset(m_array ? get_array_offset(buf, env) : 0),
+ m_offset(get_position(buf, env)),
+ m_size(get_remaining(buf, env))
+ {}
+
+ jint read(apr_file_t* fd, JNIEnv* env)
+ {
+ if (!m_size)
+ return 0;
+
+ JNIByteArray arr(m_array, false, false);
+ apr_size_t bytes_read = m_size;
+ apr_status_t status = apr_file_read(
+ fd, get_base_address(arr), &bytes_read);
+ if (status && !APR_STATUS_IS_EOF(status))
+ {
+ throw_IOException(_("Error reading from native file handle"),
+ status);
+ return 0;
+ }
+ update_position(bytes_read, env);
+ return jint(bytes_read);
+ }
+
+ jint write(apr_file_t* fd, JNIEnv* env)
+ {
+ if (!m_size)
+ return 0;
+
+ JNIByteArray arr(m_array);
+ apr_size_t bytes_written;
+ apr_status_t status = apr_file_write_full(
+ fd, get_base_address(arr), m_size, &bytes_written);
+ if (status)
+ {
+ throw_IOException(_("Error writing to native file handle"),
+ status);
+ return 0;
+ }
+ update_position(bytes_written, env);
+ return jint(bytes_written);
+ }
+
+private:
+ void *get_base_address(JNIByteArray& arr)
+ {
+ void* base = (m_direct ? m_direct
+ : const_cast<signed char*>(arr.getBytes()));
+ // FIXME: We do not currently support buffers that are nether
+ // direct, nor have an accessible array.
+ assert(base != 0);
+ return static_cast<char*>(base) + m_offset + m_array_offset;
+ }
+
+ void update_position(apr_size_t amount, JNIEnv* env)
+ {
+ jmethodID mid = env->GetMethodID(
+ env->GetObjectClass(m_buf), "position", "(I)Ljava/nio/Buffer;");
+ if (mid)
+ env->CallObjectMethod(m_buf, mid, jint(amount));
+ }
+
+ static jbyteArray get_array(jobject buf, JNIEnv* env)
+ {
+ jclass cls = env->GetObjectClass(buf);
+ jmethodID mid = env->GetMethodID(cls, "hasArray", "()Z");
+ if (!mid)
+ return NULL;
+
+ jboolean has_array = env->CallBooleanMethod(buf, mid);
+ if (!has_array)
+ return NULL;
+
+ mid = env->GetMethodID(cls, "array", "()[B");
+ if (mid)
+ return jbyteArray(env->CallObjectMethod(buf, mid));
+ return NULL;
+ }
+
+ static apr_size_t get_array_offset(jobject buf, JNIEnv* env)
+ {
+ jmethodID mid = env->GetMethodID(
+ env->GetObjectClass(buf), "arrayOffset", "()I");
+ if (mid)
+ return env->CallIntMethod(buf, mid);
+ return 0;
+ }
+
+ static apr_size_t get_position(jobject buf, JNIEnv* env)
+ {
+ jmethodID mid = env->GetMethodID(
+ env->GetObjectClass(buf), "position", "()I");
+ if (mid)
+ return env->CallIntMethod(buf, mid);
+ return 0;
+ }
+
+ static apr_size_t get_remaining(jobject buf, JNIEnv* env)
+ {
+ jmethodID mid = env->GetMethodID(
+ env->GetObjectClass(buf), "remaining", "()I");
+ if (mid)
+ return env->CallIntMethod(buf, mid);
+ return 0;
+ }
+
+ jobject m_buf;
+ void *m_direct;
+ jbyteArray m_array;
+ apr_size_t m_array_offset;
+ apr_size_t m_offset;
+ apr_size_t m_size;
+};
+} // anonymous namespace
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_util_TunnelChannel_nativeClose(
+ JNIEnv* env, jclass jclazz, jlong nativeChannel)
+{
+ JNIEntryStatic(TunnelChannel, close);
+ apr_file_t* fd = reinterpret_cast<apr_file_t*>(nativeChannel);
+ if (!fd)
+ return;
+
+ apr_status_t status = apr_file_close(fd);
+ if (status)
+ throw_IOException(_("Error closing native file handle"), status);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_apache_subversion_javahl_util_RequestChannel_nativeRead(
+ JNIEnv* env, jclass jclazz, jlong nativeChannel, jobject dst)
+{
+ JNIEntryStatic(RequestChannel, read);
+ apr_file_t* fd = get_file_descriptor(nativeChannel);
+ if (fd)
+ return ByteBufferProxy(dst, env).read(fd, env);
+ return -1;
+}
+
+JNIEXPORT jint JNICALL
+Java_org_apache_subversion_javahl_util_ResponseChannel_nativeWrite(
+ JNIEnv* env, jclass jclazz, jlong nativeChannel, jobject src)
+{
+ JNIEntryStatic(ResponseChannel, write);
+ apr_file_t* fd = get_file_descriptor(nativeChannel);
+ if (fd)
+ return ByteBufferProxy(src, env).write(fd, env);
+ return -1;
+}
Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Tue Oct 15 04:29:52 2013
@@ -134,6 +134,12 @@ public interface ISVNClient
void setPrompt(UserPasswordCallback prompt);
/**
+ * Set callbacks for ra_svn tunnel handling.
+ * @since 1.9
+ */
+ void setTunnelAgent(TunnelAgent tunnelAgent);
+
+ /**
* Retrieve the log messages for an item.
* @param path path or url to get the log message for.
* @param pegRevision revision to interpret path
Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java Tue Oct 15 04:29:52 2013
@@ -132,6 +132,8 @@ public class SVNClient implements ISVNCl
public native void setPrompt(UserPasswordCallback prompt);
+ public native void setTunnelAgent(TunnelAgent tunnelAgent);
+
public native void logMessages(String path, Revision pegRevision,
List<RevisionRange> revisionRanges,
boolean stopOnCopy, boolean discoverPath,
Added: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java?rev=1532182&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java (added)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java Tue Oct 15 04:29:52 2013
@@ -0,0 +1,83 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.callback;
+
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+
+/**
+ * Callback interface for creating and managing tunnels for ra_svn
+ * connections.
+ *
+ * Note that tunnel agent implementations should run in a separate
+ * thread of control than the one that invokes an ISVNClient or
+ * RemoteSession method that requires a tunnel, otherwise the method
+ * will deadlock.
+ *
+ * @since 1.9
+ */
+public interface TunnelAgent
+{
+ /**
+ * This callback method is called before a tunnel is created, to
+ * determine whether to use this tunnel implementation, or revert
+ * to the default (native) tunnel implementation.
+ * @param name the name of the tunnel, as in
+ * <tt>svn+</tt><em>name</em><tt>://...</tt>
+ * @return <code>false</code> to defer to the default implementation.
+ */
+ boolean checkTunnel(String name);
+
+ /**
+ * This callback method is called when a tunnel needs to be
+ * created and the request and response streams attached to it.
+ * @param request The request stream of the tunnel. The tunnel
+ * agent implementation will read requests from this channel
+ * and send them to the tunnel process.
+ * @param response The request stream of the tunnel. The tunnel
+ * agent implementation will read requests from this channel
+ * and send them to the tunnel process.
+ * @param name the name of the tunnel, as in
+ * <tt>svn+</tt><em>name</em><tt>://...</tt>
+ * @param user the tunnel username
+ * @param hostname the host part of the svn+tunnel:// URL
+ * @param port the port part of the svn+tunnel:// URL
+ * @throws any exception will abort the connection
+ */
+ void openTunnel(ReadableByteChannel request, WritableByteChannel response,
+ String name, String user, String hostname, int port)
+ throws Throwable;
+
+ /**
+ * This callback method is called when a tunnel needs to be closed
+ * and the request and response streams detached from it.
+ * @param name the name of the tunnel, as in
+ * <tt>svn+</tt><em>name</em><tt>://...</tt>
+ * @param user the tunnel username
+ * @param hostname the host part of the svn+tunnel:// URL
+ * @param port the port part of the svn+tunnel:// URL
+ */
+ void closeTunnel(String name, String user, String hostname, int port)
+ throws Throwable;
+}
Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java Tue Oct 15 04:29:52 2013
@@ -59,13 +59,15 @@ public class RemoteFactory
public RemoteFactory(String configDirectory,
String username, String password,
UserPasswordCallback prompt,
- ProgressCallback progress)
+ ProgressCallback progress,
+ TunnelAgent tunnelAgent)
{
setConfigDirectory(configDirectory);
setUsername(username);
setPassword(password);
setPrompt(prompt);
setProgressCallback(progress);
+ setTunnelAgent(tunnelAgent);
}
/**
@@ -125,6 +127,14 @@ public class RemoteFactory
}
/**
+ * Set callbacks for ra_svn tunnel handling.
+ */
+ public void setTunnelAgent(TunnelAgent tunnelAgent)
+ {
+ this.tunnelAgent = tunnelAgent;
+ }
+
+ /**
* Open a persistent session to a repository.
* <p>
* <b>Note:</b> The URL can point to a subtree of the repository.
@@ -141,7 +151,7 @@ public class RemoteFactory
throws ClientException, SubversionException
{
return open(1, url, null, configDirectory,
- username, password, prompt, progress);
+ username, password, prompt, progress, tunnelAgent);
}
/**
@@ -168,7 +178,7 @@ public class RemoteFactory
throw new IllegalArgumentException(
"retryAttempts must be positive");
return open(retryAttempts, url, null, configDirectory,
- username, password, prompt, progress);
+ username, password, prompt, progress, tunnelAgent);
}
/**
@@ -195,7 +205,7 @@ public class RemoteFactory
if (reposUUID == null)
throw new IllegalArgumentException("reposUUID may not be null");
return open(1, url, reposUUID, configDirectory,
- username, password, prompt, progress);
+ username, password, prompt, progress, tunnelAgent);
}
/**
@@ -229,7 +239,7 @@ public class RemoteFactory
throw new IllegalArgumentException(
"retryAttempts must be positive");
return open(retryAttempts, url, reposUUID, configDirectory,
- username, password, prompt, progress);
+ username, password, prompt, progress, tunnelAgent);
}
private String configDirectory;
@@ -237,6 +247,7 @@ public class RemoteFactory
private String password;
private UserPasswordCallback prompt;
private ProgressCallback progress;
+ private TunnelAgent tunnelAgent;
/* Native factory implementation. */
private static native ISVNRemote open(int retryAttempts,
@@ -244,6 +255,7 @@ public class RemoteFactory
String configDirectory,
String username, String password,
UserPasswordCallback prompt,
- ProgressCallback progress)
+ ProgressCallback progress,
+ TunnelAgent tunnelAgent)
throws ClientException, SubversionException;
}
Added: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java?rev=1532182&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java (added)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java Tue Oct 15 04:29:52 2013
@@ -0,0 +1,49 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+/* The following channel subclasses are used by the native
+ implementation of the tunnel management code. */
+
+class RequestChannel
+ extends TunnelChannel
+ implements ReadableByteChannel
+{
+ private RequestChannel(long nativeChannel)
+ {
+ super(nativeChannel);
+ }
+
+ public int read(ByteBuffer dst) throws IOException
+ {
+ return nativeRead(nativeChannel, dst);
+ }
+
+ private static native int nativeRead(long nativeChannel, ByteBuffer dst)
+ throws IOException;
+}
Added: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java?rev=1532182&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java (added)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java Tue Oct 15 04:29:52 2013
@@ -0,0 +1,49 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+/* The following channel subclasses are used by the native
+ implementation of the tunnel management code. */
+
+class ResponseChannel
+ extends TunnelChannel
+ implements WritableByteChannel
+{
+ private ResponseChannel(long nativeChannel)
+ {
+ super(nativeChannel);
+ }
+
+ public int write(ByteBuffer src) throws IOException
+ {
+ return nativeWrite(nativeChannel, src);
+ }
+
+ private static native int nativeWrite(long nativeChannel, ByteBuffer src)
+ throws IOException;
+}
Added: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java?rev=1532182&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java (added)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java Tue Oct 15 04:29:52 2013
@@ -0,0 +1,55 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channel;
+
+/* The following channel subclasses are used by the native
+ implementation of the tunnel management code. */
+
+abstract class TunnelChannel implements Channel
+{
+ protected TunnelChannel(long nativeChannel)
+ {
+ this.nativeChannel = nativeChannel;
+ }
+
+ public boolean isOpen()
+ {
+ return (nativeChannel != 0);
+ }
+
+ public void close() throws IOException
+ {
+ nativeClose(nativeChannel);
+ nativeChannel = 0;
+ }
+
+ private native static void nativeClose(long nativeChannel)
+ throws IOException;
+
+ protected long nativeChannel;
+}
Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Tue Oct 15 04:29:52 2013
@@ -33,6 +33,9 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
import java.text.ParseException;
import java.util.Collection;
import java.util.Arrays;
@@ -3776,6 +3779,106 @@ public class BasicTests extends SVNTests
assertEquals(1, result.size());
}
+ private class Tunnel extends Thread implements TunnelAgent
+ {
+ public boolean checkTunnel(String name)
+ {
+ return name.equals("test");
+ }
+
+ public void openTunnel(ReadableByteChannel request,
+ WritableByteChannel response,
+ String name, String user,
+ String hostname, int port)
+ {
+ this.request = request;
+ this.response = response;
+ start();
+ }
+
+ public void closeTunnel(String name, String user,
+ String hostname, int port)
+ throws Throwable
+ {
+ request.close();
+ join();
+ response.close();
+ }
+
+ private ReadableByteChannel request;
+ private WritableByteChannel response;
+
+ public void run()
+ {
+
+ int index = 0;
+ byte[] raw_data = new byte[1024];
+ ByteBuffer data = ByteBuffer.wrap(raw_data);
+ while(index < commands.length && request.isOpen()) {
+ try {
+ byte[] command = commands[index++];
+ response.write(ByteBuffer.wrap(command));
+ } catch (IOException ex) {
+ break;
+ }
+
+ try {
+ data.clear();
+ request.read(data);
+ } catch (Throwable ex) {}
+ }
+
+ try {
+ response.close();
+ request.close();
+ } catch (Throwable t) {}
+ }
+
+ private final byte[][] commands = new byte[][]{
+ // Initial capabilities negotiation
+ ("( success ( 2 2 ( ) " +
+ "( edit-pipeline svndiff1 absent-entries commit-revprops " +
+ "depth log-revprops atomic-revprops partial-replay " +
+ "inherited-props ephemeral-txnprops file-revs-reverse " +
+ ") ) ) ").getBytes(),
+
+ // Response for successful connection
+ ("( success ( ( ANONYMOUS EXTERNAL ) " +
+ "36:e3c8c113-03ba-4ec5-a8e6-8fc555e57b91 ) ) ").getBytes(),
+
+ // Response to authentication request
+ ("( success ( ) ) ( success ( " +
+ "36:e3c8c113-03ba-4ec5-a8e6-8fc555e57b91 " +
+ "24:svn+test://localhost/foo ( mergeinfo ) ) ) ").getBytes(),
+
+ // Response to revprop request
+ ("( success ( ( ) 0: ) ) ( success ( ( 4:fake ) ) ) ").getBytes()
+ };
+ }
+
+ /**
+ * Test tunnel handling.
+ */
+ public void testTunnelAgent() throws Throwable
+ {
+ byte[] revprop;
+ SVNClient cl = new SVNClient();
+ try {
+ cl.notification2(new MyNotifier());
+ cl.setPrompt(new DefaultPromptUserPassword());
+ cl.username(USERNAME);
+ cl.setProgressCallback(new DefaultProgressListener());
+ cl.setConfigDirectory(conf.getAbsolutePath());
+
+ cl.setTunnelAgent(new Tunnel());
+ revprop = cl.revProperty("svn+test://localhost/foo", "svn:log",
+ Revision.getInstance(0L));
+ } finally {
+ cl.dispose();
+ }
+ assertEquals("fake", new String(revprop));
+ }
+
/**
* @return <code>file</code> converted into a -- possibly
* <code>canonical</code>-ized -- Subversion-internal path
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=1532182&r1=1532181&r2=1532182&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 Tue Oct 15 04:29:52 2013
@@ -111,7 +111,8 @@ public class SVNRemoteTests extends SVNT
session = new RemoteFactory(
super.conf.getAbsolutePath(),
USERNAME, PASSWORD,
- new DefaultPromptUserPassword(), null)
+ new DefaultPromptUserPassword(),
+ null, null)
.openRemoteSession(getTestRepoUrl());
}
catch (ClientException ex)
@@ -138,7 +139,8 @@ public class SVNRemoteTests extends SVNT
new RemoteFactory(
super.conf.getAbsolutePath(),
USERNAME, PASSWORD,
- new DefaultPromptUserPassword(), null)
+ new DefaultPromptUserPassword(),
+ null, null)
.openRemoteSession(prefix + "repositorydoesnotexisthere");
}
finally
Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java?rev=1532182&r1=1532181&r2=1532182&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java Tue Oct 15 04:29:52 2013
@@ -355,7 +355,7 @@ class SVNTests extends TestCase
}
}
- private static class DefaultProgressListener implements ProgressCallback
+ protected static class DefaultProgressListener implements ProgressCallback
{
public void onProgress(ProgressEvent event)