Index: subversion/bindings/java/javahl/native/SVNClient.cpp =================================================================== --- subversion/bindings/java/javahl/native/SVNClient.cpp (revision 22341) +++ subversion/bindings/java/javahl/native/SVNClient.cpp (working copy) @@ -23,6 +23,7 @@ #include "JNIUtil.h" #include "Notify.h" #include "Notify2.h" +#include "ProgressListener.h" #include "Prompter.h" #include "Pool.h" #include "Targets.h" @@ -58,6 +59,7 @@ { m_notify = NULL; m_notify2 = NULL; + m_progressListener = NULL; m_prompter = NULL; m_commitMessage = NULL; } @@ -66,6 +68,7 @@ { delete m_notify; delete m_notify2; + delete m_progressListener; delete m_prompter; } @@ -545,6 +548,12 @@ m_notify2 = notify2; } +void SVNClient::setProgressListener(ProgressListener *listener) +{ + delete m_progressListener; + m_progressListener = listener; +} + void SVNClient::remove(Targets &targets, const char *message, bool force) { svn_client_commit_info_t *commit_info = NULL; @@ -1714,6 +1723,9 @@ ctx->notify_func2= Notify2::notify; ctx->notify_baton2 = m_notify2; + ctx->progress_func = ProgressListener::progress; + ctx->progress_baton = m_progressListener; + return ctx; } Index: subversion/bindings/java/javahl/native/ProgressListener.h =================================================================== --- subversion/bindings/java/javahl/native/ProgressListener.h (revision 0) +++ subversion/bindings/java/javahl/native/ProgressListener.h (revision 0) @@ -0,0 +1,88 @@ +/** + * @copyright + * ==================================================================== + * Copyright (c) 2006 CollabNet. All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://subversion.tigris.org/license-1.html. + * If newer versions of this license are posted there, you may use a + * newer version instead, at your option. + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://subversion.tigris.org/. + * ==================================================================== + * @endcopyright + * + * @file ProgressListener.h + * @brief Interface of the class ProgressListener + */ + +#if !defined(AFX_PROGRESS_H__10E278E8_EA8C_4BD1_AF10_4DB1C0608F65__INCLUDED_) +#define AFX_PROGRESS_H__10E278E8_EA8C_4BD1_AF10_4DB1C0608F65__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include +#include "svn_wc.h" + +/** + * This class passes progress events from Subversion to a Java object. + * @since 1.5 + */ +class ProgressListener +{ +private: + /** + * The Java object which handles the progress event. This is a + * global reference, because it has to live longer than the + * SVNClient.onProgress() call. + */ + jobject m_progressListener; + + /** + * Create a new instance, storing a global reference to the + * corresponding Java object. + * + * @param jprogressListener Reference to the Java peer. + */ + ProgressListener(jobject jprogressListener); + +public: + /** + * Destroy the instance, and delete the global reference to the + * Java object. + */ + ~ProgressListener(); + + /** Constructor function called from C JNI glue code. */ + static ProgressListener *makeCProgressListener(jobject jprogressListener); + + /** + * Implementation of the svn_ra_progress_notify_func_t API. + * + * @param progress The number of bytes already transferred. + * @param total The total number of bytes. + * @param baton A reference to the ProgressListener instance. + * @param pool An APR pool from which to allocate memory. + */ + static void progress(apr_off_t progress, + apr_off_t total, + void *baton, + apr_pool_t *pool); + + /** + * Handler for Subversion progress events. + * + * @param progress The number of bytes already transferred. + * @param total The total number of bytes. + * @param pool An APR pool from which to allocate memory. + */ + void onProgress(apr_off_t progress, + apr_off_t total, + apr_pool_t *pool); +}; +// !defined(AFX_PROGRESS_H__10E278E8_EA8C_4BD1_AF10_4DB1C0608F65__INCLUDED_) +#endif Index: subversion/bindings/java/javahl/native/org_tigris_subversion_javahl_SVNClient.cpp =================================================================== --- subversion/bindings/java/javahl/native/org_tigris_subversion_javahl_SVNClient.cpp (revision 22341) +++ subversion/bindings/java/javahl/native/org_tigris_subversion_javahl_SVNClient.cpp (working copy) @@ -28,6 +28,7 @@ #include "Revision.h" #include "Notify.h" #include "Notify2.h" +#include "ProgressListener.h" #include "CommitMessage.h" #include "Prompter.h" #include "Targets.h" @@ -410,6 +411,7 @@ } cl->notification(notify); } + /* * Class: org_tigris_subversion_javahl_SVNClient * Method: notification2 @@ -432,8 +434,33 @@ } cl->notification2(notify2); } + /* * Class: org_tigris_subversion_javahl_SVNClient + * Method: setProgressListener + * Signature: (Lorg/tigris/subversion/javahl/ProgressListener;)V + */ +JNIEXPORT void JNICALL Java_org_tigris_subversion_javahl_SVNClient_setProgressListener + (JNIEnv* env, jobject jthis, jobject jprogressListener) +{ + JNIEntry(SVNClient, setProgressListener); + SVNClient *cl = SVNClient::getCppObject(jthis); + if (cl == NULL) + { + JNIUtil::throwError(_("bad c++ this")); + return; + } + ProgressListener *listener = + ProgressListener::makeCProgressListener(jprogressListener); + if (JNIUtil::isExceptionThrown()) + { + return; + } + cl->setProgressListener(listener); +} + +/* + * Class: org_tigris_subversion_javahl_SVNClient * Method: commitMessageHandler * Signature: (Lorg/tigris/subversion/javahl/CommitMessage;)V */ Index: subversion/bindings/java/javahl/native/SVNClient.h =================================================================== --- subversion/bindings/java/javahl/native/SVNClient.h (revision 22341) +++ subversion/bindings/java/javahl/native/SVNClient.h (working copy) @@ -31,6 +31,7 @@ class Revision; class Notify; class Notify2; +class ProgressListener; class Targets; class JNIByteArray; class Prompter; @@ -112,6 +113,7 @@ void remove(Targets &targets, const char *message,bool force); void notification(Notify *notify); void notification2(Notify2 *notify2); + void setProgressListener(ProgressListener *progressListener); jlong checkout(const char *moduleName, const char *destPath, Revision &revision, Revision &pegRevsion, bool recurse, bool ignoreExternals); @@ -166,6 +168,7 @@ size_t& size); Notify *m_notify; Notify2 *m_notify2; + ProgressListener *m_progressListener; Prompter *m_prompter; Path m_lastPath; bool m_cancelOperation; Index: subversion/bindings/java/javahl/native/ProgressListener.cpp =================================================================== --- subversion/bindings/java/javahl/native/ProgressListener.cpp (revision 0) +++ subversion/bindings/java/javahl/native/ProgressListener.cpp (revision 0) @@ -0,0 +1,156 @@ +/** + * @copyright + * ==================================================================== + * Copyright (c) 2003-2005 CollabNet. All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://subversion.tigris.org/license-1.html. + * If newer versions of this license are posted there, you may use a + * newer version instead, at your option. + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://subversion.tigris.org/. + * ==================================================================== + * @endcopyright + * + * @file ProgressListener.cpp + * @brief Implementation of the class ProgressListener. + */ + +#include "ProgressListener.h" +#include "JNIUtil.h" + +ProgressListener::ProgressListener(jobject jprogressListener) +{ + m_progressListener = jprogressListener; +} + +ProgressListener::~ProgressListener() +{ + if (m_progressListener != NULL) + { + JNIEnv *env = JNIUtil::getEnv(); + env->DeleteGlobalRef(m_progressListener); + } +} + +ProgressListener * +ProgressListener::makeCProgressListener(jobject jprogressListener) +{ + if (jprogressListener == NULL) + { + return NULL; + } + + JNIEnv *env = JNIUtil::getEnv(); + + // Sanity check that the object implements the ProgressListener + // Java interface. + jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressListener"); + if (JNIUtil::isJavaExceptionThrown()) + { + return NULL; + } + if (!env->IsInstanceOf(jprogressListener, clazz)) + { + env->DeleteLocalRef(clazz); + return NULL; + } + env->DeleteLocalRef(clazz); + if (JNIUtil::isJavaExceptionThrown()) + { + return NULL; + } + + // Retain a global reference to our Java peer. + jobject myListener = env->NewGlobalRef(jprogressListener); + if (JNIUtil::isJavaExceptionThrown()) + { + return NULL; + } + + // Create the peer. + return new ProgressListener(myListener); +} + +void +ProgressListener::progress(apr_off_t progress, apr_off_t total, void *baton, + apr_pool_t *pool) +{ + if (baton) + { + ((ProgressListener *) baton)->onProgress(notify, pool); + } +} + +void +ProgressListener::onProgress(apr_off_t progress, apr_off_t total, + apr_pool_t *pool) +{ + JNIEnv *env = JNIUtil::getEnv(); + + // As Java method IDs will not change during the time this library + // is loaded, they can be cached. + static jmethodID mid = 0; + if (mid == 0) + { + // Initialize the method ID. + jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressListener"); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } + mid = env->GetMethodID(clazz, "onProgress", + "(Lorg/tigris/subversion/javahl/ProgressEvent;)V"); + if (JNIUtil::isJavaExceptionThrown() || mid == 0) + { + return; + } + env->DeleteLocalRef(clazz); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } + } + + static jmethodID midCT = 0; + jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressEvent"); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } + if (midCT == 0) + { + midCT = env->GetMethodID(clazz, "", "(JJ)V"); + if (JNIUtil::isJavaExceptionThrown() || midCT == 0) + { + return; + } + } + + // Call the Java method. + jobject jevent = env->NewObject(clazz, midCT, + (jlong) progress, (jlong) total); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } + env->DeleteLocalRef(clazz); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } + env->CallVoidMethod(m_progressListener, mid, jevent); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } + + env->DeleteLocalRef(jevent); + if (JNIUtil::isJavaExceptionThrown()) + { + return; + } +} Index: subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClientInterface.java =================================================================== --- subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClientInterface.java (revision 22341) +++ subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClientInterface.java (working copy) @@ -262,6 +262,14 @@ void notification2(Notify2 notify); /** + * Set the progress callback. + * + * @param listener The progress callback. + * @since 1.5 + */ + void setProgressListener(ProgressListener listener); + + /** * Sets the commit message handler. This allows more complex commit message * with the list of the elements to be commited as input. * @param messageHandler callback for entering commit messages Index: subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClient.java =================================================================== --- subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClient.java (revision 22341) +++ subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClient.java (working copy) @@ -326,6 +326,14 @@ public native void notification2(Notify2 notify); /** + * Set the progress callback. + * + * @param listener The progress callback. + * @since 1.5 + */ + public native void setProgressListener(ProgressListener listener); + + /** * Sets the commit message handler. This allows more complex commit message * with the list of the elements to be commited as input. * @param messageHandler callback for entering commit messages Index: subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClientSynchronized.java =================================================================== --- subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClientSynchronized.java (revision 22341) +++ subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/SVNClientSynchronized.java (working copy) @@ -404,6 +404,20 @@ } /** + * Set the progress callback. + * + * @param listener The progress callback. + * @since 1.5 + */ + public void setProgressListener(ProgressListener listener) + { + synchronized (clazz) + { + worker.setProgressListener(listener); + } + } + + /** * Sets the commit message handler. This allows more complex commit message * with the list of the elements to be commited as input. * @param messageHandler callback for entering commit messages Index: subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/ProgressEvent.java =================================================================== --- subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/ProgressEvent.java (revision 0) +++ subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/ProgressEvent.java (revision 0) @@ -0,0 +1,72 @@ +/** + * @copyright + * ==================================================================== + * Copyright (c) 2006 CollabNet. All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://subversion.tigris.org/license-1.html. + * If newer versions of this license are posted there, you may use a + * newer version instead, at your option. + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://subversion.tigris.org/. + * ==================================================================== + * @endcopyright + */ +package org.tigris.subversion.javahl; + +import java.util.EventObject; + +/** + * The event passed to the {@link + * ProgressListener.onProgress(ProgressEvent)} API to inform {@link + * SVNClientInterfacce} of command progress (in terms of bytes). + * + * @since 1.5 + */ +public class ProgressEvent extends EventObject +{ + /** + * The number of bytes already transferred. + */ + private long progress = -1; + + /** + * The total number of bytes, or -1 if not known. + */ + private long total = -1; + + /** + * This constructor is to be used by the native code. + * + * @param progress The number of bytes already transferred. + * @param total The total number of bytes, or -1 if + * not known. + */ + ProgressEvent(long progress, long total) + { + // TODO: Provide the repository action's URL as the source. + super(null); + this.progress = progress; + this.total = total; + } + + /** + * @return The number of bytes already transferred. + */ + public long getProgress() + { + return this.progress; + } + + /** + * @return The total number of bytes, or -1 if not + * known. + */ + public long getTotal() + { + return this.total; + } +} Index: subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/ProgressListener.java =================================================================== --- subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/ProgressListener.java (revision 0) +++ subversion/bindings/java/javahl/src/org/tigris/subversion/javahl/ProgressListener.java (revision 0) @@ -0,0 +1,40 @@ +/** + * @copyright + * ==================================================================== + * Copyright (c) 2006 CollabNet. All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://subversion.tigris.org/license-1.html. + * If newer versions of this license are posted there, you may use a + * newer version instead, at your option. + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://subversion.tigris.org/. + * ==================================================================== + * @endcopyright + */ +package org.tigris.subversion.javahl; + +import java.util.EventListener; + +/** + * Subversion progress event interface. + * + * Implement this interface to provide a custom progress event handler + * to the SVNClient class. If you need to pass extra information to + * the notification handler, add it to your implementing class. + * + * @since 1.5 + */ +public interface ProgressListener extends EventListener +{ + /** + * Implement this API to receive progress events for Subversion + * operations. + * + * @param info everything to know about this event + */ + public void onProgress(ProgressEvent event); +}