[[[ JavaHL: Factor out common progress and cancellation callbacks as well as configuration and authentication context into CommonContext class from SVNClient specific code in the ClientContext class so that it can be shared with the Ra JNI code
[ in subversion/bindings/javahl/native ] * CommonContext.cpp, CommonContext.h, ClientContext.cpp, ClientContext.h (username, password, getConfigDirectory, setConfigDirectory, setPrompt, cancelOperation, progress,): Move from ClientContext to CommonContext * CommonContext.cpp, CommonContext.h (attachJavaObject): Create new function to hold common logic of attaching to the java CommonContext class used for callbacks (getConfigData, getAuthBaton): Split getContext into separate configuration data setup and authentication data setup to better reflect their different life cycles (getClientName): New function to return client name that should be used in callbacks * ClientContext.cpp, ClientContext.h (ClientContext, getContext): Use the factored out CommonContext member variables and functions ]]]
Index: subversion/bindings/javahl/native/ClientContext.h =================================================================== --- subversion/bindings/javahl/native/ClientContext.h (revision 1328758) +++ subversion/bindings/javahl/native/ClientContext.h (working copy) @@ -29,6 +29,8 @@ #include <string> +#include "CommonContext.h" + #include "svn_types.h" #include "svn_client.h" @@ -36,7 +38,6 @@ #include "Pool.h" #include "JNIStringHolder.h" -class Prompter; class CommitMessage; /** @@ -44,25 +45,14 @@ class CommitMessage; * and implements the functions read & close of svn_stream_t. * */ -class ClientContext +class ClientContext : public CommonContext { private: svn_client_ctx_t *m_context; - const SVN::Pool *m_pool; - jobject m_jctx; - std::string m_userName; - std::string m_passWord; - std::string m_configDir; - - Prompter *m_prompter; - bool m_cancelOperation; - protected: static void notify(void *baton, const svn_wc_notify_t *notify, apr_pool_t *pool); - static void progress(apr_off_t progressVal, apr_off_t total, - void *baton, apr_pool_t *pool); static svn_error_t *resolve(svn_wc_conflict_result_t **result, const svn_wc_conflict_description2_t *desc, void *baton, @@ -73,24 +63,9 @@ class CommitMessage; public: ClientContext(jobject jsvnclient, SVN::Pool &pool); - ~ClientContext(); + virtual ~ClientContext(); - static svn_error_t *checkCancel(void *cancelBaton); - svn_client_ctx_t *getContext(CommitMessage *message, SVN::Pool &in_pool); - - void username(const char *pi_username); - void password(const char *pi_password); - void setPrompt(Prompter *prompter); - void cancelOperation(); - const char *getConfigDirectory() const; - - /** - * Set the configuration directory, taking the usual steps to - * ensure that Subversion's config file templates exist in the - * specified location. - */ - void setConfigDirectory(const char *configDir); }; #endif // CLIENTCONTEXT_H Index: subversion/bindings/javahl/native/CommonContext.cpp =================================================================== --- subversion/bindings/javahl/native/CommonContext.cpp (working copy) +++ subversion/bindings/javahl/native/CommonContext.cpp (working copy) @@ -20,15 +20,15 @@ * ==================================================================== * @endcopyright * - * @file ClientContext.cpp - * @brief Implementation of the class ClientContext + * @file CommonContext.cpp + * @brief Implementation of the class CommonContext */ #include "svn_client.h" #include "private/svn_wc_private.h" #include "svn_private_config.h" -#include "ClientContext.h" +#include "CommonContext.h" #include "JNIUtil.h" #include "JNICriticalSection.h" @@ -37,337 +37,247 @@ #include "EnumMapper.h" #include "CommitMessage.h" +CommonContext::CommonContext(SVN::Pool &pool) + :m_prompter(NULL), m_cancelOperation(false), m_pool(&pool), m_config(NULL), m_jctx(NULL) +{ +} -ClientContext::ClientContext(jobject jsvnclient, SVN::Pool &pool) - : m_prompter(NULL), - m_cancelOperation(false) +void +CommonContext::attachJavaObject(jobject contextHolder, const char *contextClassType, + const char *contextFieldName, jfieldID * ctxFieldID) { - JNIEnv *env = JNIUtil::getEnv(); + JNIEnv *env = JNIUtil::getEnv(); - /* Grab a global reference to the Java object embedded in the parent Java - object. */ - static jfieldID ctxFieldID = 0; - if (ctxFieldID == 0) + /* Grab a global reference to the Java object embedded in the parent Java + object. */ + if ((*ctxFieldID) == 0) { - jclass clazz = env->GetObjectClass(jsvnclient); - if (JNIUtil::isJavaExceptionThrown()) - return; - - ctxFieldID = env->GetFieldID(clazz, "clientContext", - "L"JAVA_PACKAGE"/SVNClient$ClientContext;"); - if (JNIUtil::isJavaExceptionThrown() || ctxFieldID == 0) - return; - - env->DeleteLocalRef(clazz); - } - - jobject jctx = env->GetObjectField(jsvnclient, ctxFieldID); - if (JNIUtil::isJavaExceptionThrown()) + jclass clazz = env->GetObjectClass(contextHolder); + if (JNIUtil::isJavaExceptionThrown()) return; - m_jctx = env->NewGlobalRef(jctx); - if (JNIUtil::isJavaExceptionThrown()) + (*ctxFieldID) = env->GetFieldID(clazz, contextFieldName, contextClassType); + if (JNIUtil::isJavaExceptionThrown() || (*ctxFieldID) == 0) return; - env->DeleteLocalRef(jctx); + env->DeleteLocalRef(clazz); + } - SVN_JNI_ERR(svn_client_create_context(&m_context, pool.getPool()), - ); + jobject jctx = env->GetObjectField(contextHolder, (*ctxFieldID)); + if (JNIUtil::isJavaExceptionThrown()) + return; - /* Clear the wc_ctx as we don't want to maintain this unconditionally - for compatibility reasons */ - SVN_JNI_ERR(svn_wc_context_destroy(m_context->wc_ctx), - ); - m_context->wc_ctx = NULL; + m_jctx = env->NewGlobalRef(jctx); + if (JNIUtil::isJavaExceptionThrown()) + return; - /* None of the following members change during the lifetime of - this object. */ - m_context->notify_func = NULL; - m_context->notify_baton = NULL; - m_context->log_msg_func3 = CommitMessage::callback; - m_context->log_msg_baton3 = NULL; - m_context->cancel_func = checkCancel; - m_context->cancel_baton = this; - m_context->notify_func2= notify; - m_context->notify_baton2 = m_jctx; - m_context->progress_func = progress; - m_context->progress_baton = m_jctx; - m_context->conflict_func2 = resolve; - m_context->conflict_baton2 = m_jctx; - - m_context->client_name = "javahl"; - m_pool = &pool; + env->DeleteLocalRef(jctx); } -ClientContext::~ClientContext() +CommonContext::~CommonContext() { - delete m_prompter; + delete m_prompter; - JNIEnv *env = JNIUtil::getEnv(); - env->DeleteGlobalRef(m_jctx); + JNIEnv *env = JNIUtil::getEnv(); + env->DeleteGlobalRef(m_jctx); } - -/* 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() - is called on the same pool. - - The use of this function assumes a proper subpool behavior by its user, - (read: SVNClient) usually per request. - */ -extern "C" { - -struct clearctx_baton_t +apr_hash_t * +CommonContext::getConfigData() { - svn_client_ctx_t *ctx; - svn_client_ctx_t *backup; -}; + if(m_pool->getPool() == NULL) + { + JNIUtil::throwNullPointerException("pool is null"); + } -static apr_status_t clear_ctx_ptrs(void *ptr) -{ - clearctx_baton_t *bt = (clearctx_baton_t*)ptr; + if (m_config == NULL) + { + const char *configDir = m_configDir.c_str(); + if (m_configDir.empty()) + configDir = NULL; + SVN_JNI_ERR( + svn_config_get_config(&m_config, configDir, m_pool->getPool()), NULL); + } - /* Reset all values to those before overwriting by getContext. */ - *bt->ctx = *bt->backup; - - return APR_SUCCESS; + return m_config; } -}; - -svn_client_ctx_t * -ClientContext::getContext(CommitMessage *message, SVN::Pool &in_pool) +svn_auth_baton_t * +CommonContext::getAuthBaton(SVN::Pool &in_pool) { - apr_pool_t *pool = in_pool.getPool(); - svn_auth_baton_t *ab; - svn_client_ctx_t *ctx = m_context; + svn_auth_baton_t *ab; + apr_pool_t *pool = in_pool.getPool(); - /* Make a temporary copy of ctx to restore at pool cleanup to avoid - leaving references to dangling pointers. + apr_hash_t * configData = getConfigData(); - Note that this allows creating a stack of context changes if - the function is invoked multiple times with different pools. - */ - clearctx_baton_t *bt = (clearctx_baton_t *)apr_pcalloc(pool, sizeof(*bt)); - bt->ctx = ctx; - bt->backup = (svn_client_ctx_t*)apr_pmemdup(pool, ctx, sizeof(*ctx)); - apr_pool_cleanup_register(in_pool.getPool(), bt, clear_ctx_ptrs, - clear_ctx_ptrs); + if (configData == NULL) + { + return NULL; + } + svn_config_t *config = (svn_config_t *) apr_hash_get(configData, + SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING); - if (!ctx->config) - { - const char *configDir = m_configDir.c_str(); - if (m_configDir.empty()) - configDir = NULL; - SVN_JNI_ERR(svn_config_get_config(&(ctx->config), configDir, - m_pool->getPool()), - NULL); + /* The whole list of registered providers */ + apr_array_header_t *providers; - bt->backup->config = ctx->config; - } - svn_config_t *config = (svn_config_t *) apr_hash_get(ctx->config, - SVN_CONFIG_CATEGORY_CONFIG, - APR_HASH_KEY_STRING); + /* Populate the registered providers with the platform-specific providers */ + SVN_JNI_ERR( + svn_auth_get_platform_specific_client_providers(&providers, config, pool), + NULL); + /* Use the prompter (if available) to prompt for password and cert + * caching. */ + svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL; + void *plaintext_prompt_baton = NULL; + svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func; + void *plaintext_passphrase_prompt_baton = NULL; - /* The whole list of registered providers */ - apr_array_header_t *providers; - - /* Populate the registered providers with the platform-specific providers */ - SVN_JNI_ERR(svn_auth_get_platform_specific_client_providers(&providers, - config, - pool), - NULL); - - /* Use the prompter (if available) to prompt for password and cert - * caching. */ - svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL; - void *plaintext_prompt_baton = NULL; - svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func; - void *plaintext_passphrase_prompt_baton = NULL; - - if (m_prompter != NULL) + if (m_prompter != NULL) { - plaintext_prompt_func = Prompter::plaintext_prompt; - plaintext_prompt_baton = m_prompter; - plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt; - plaintext_passphrase_prompt_baton = m_prompter; + plaintext_prompt_func = Prompter::plaintext_prompt; + plaintext_prompt_baton = m_prompter; + plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt; + plaintext_passphrase_prompt_baton = m_prompter; } - /* The main disk-caching auth providers, for both - * 'username/password' creds and 'username' creds. */ - svn_auth_provider_object_t *provider; + /* The main disk-caching auth providers, for both + * 'username/password' creds and 'username' creds. */ + svn_auth_provider_object_t *provider; - svn_auth_get_simple_provider2(&provider, plaintext_prompt_func, - plaintext_prompt_baton, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + svn_auth_get_simple_provider2(&provider, plaintext_prompt_func, + plaintext_prompt_baton, pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - svn_auth_get_username_provider(&provider, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + svn_auth_get_username_provider(&provider, pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - /* The server-cert, client-cert, and client-cert-password providers. */ - SVN_JNI_ERR(svn_auth_get_platform_specific_provider(&provider, - "windows", - "ssl_server_trust", - pool), - NULL); + /* The server-cert, client-cert, and client-cert-password providers. */ + SVN_JNI_ERR( + svn_auth_get_platform_specific_provider(&provider, "windows", "ssl_server_trust", pool), + NULL); - if (provider) - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - svn_auth_get_ssl_server_trust_file_provider(&provider, pool); + if (provider) APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - svn_auth_get_ssl_client_cert_file_provider(&provider, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - svn_auth_get_ssl_client_cert_pw_file_provider2(&provider, - plaintext_passphrase_prompt_func, - plaintext_passphrase_prompt_baton, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - if (m_prompter != NULL) + svn_auth_get_ssl_server_trust_file_provider(&provider, pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + svn_auth_get_ssl_client_cert_file_provider(&provider, pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + svn_auth_get_ssl_client_cert_pw_file_provider2(&provider, + plaintext_passphrase_prompt_func, plaintext_passphrase_prompt_baton, + pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + + if (m_prompter != NULL) { - /* Two basic prompt providers: username/password, and just username.*/ - provider = m_prompter->getProviderSimple(in_pool); + /* Two basic prompt providers: username/password, and just username.*/ + provider = m_prompter->getProviderSimple(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - provider = m_prompter->getProviderUsername(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + provider = m_prompter->getProviderUsername(in_pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - /* Three ssl prompt providers, for server-certs, client-certs, - * and client-cert-passphrases. */ - provider = m_prompter->getProviderServerSSLTrust(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + /* Three ssl prompt providers, for server-certs, client-certs, + * and client-cert-passphrases. */ + provider = m_prompter->getProviderServerSSLTrust(in_pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - provider = m_prompter->getProviderClientSSL(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + provider = m_prompter->getProviderClientSSL(in_pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - provider = m_prompter->getProviderClientSSLPassword(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; + provider = m_prompter->getProviderClientSSLPassword(in_pool); + APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; } - /* Build an authentication baton to give to libsvn_client. */ - svn_auth_open(&ab, providers, pool); + /* Build an authentication baton to give to libsvn_client. */ + svn_auth_open(&ab, providers, pool); - /* Place any default --username or --password credentials into the - * auth_baton's run-time parameter hash. ### Same with --no-auth-cache? */ - if (!m_userName.empty()) - svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME, - apr_pstrdup(in_pool.getPool(), - m_userName.c_str())); - if (!m_passWord.empty()) - svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD, - apr_pstrdup(in_pool.getPool(), - m_passWord.c_str())); - /* Store where to retrieve authentication data? */ - if (!m_configDir.empty()) - svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR, - apr_pstrdup(in_pool.getPool(), - m_configDir.c_str())); - - ctx->auth_baton = ab; - ctx->log_msg_baton3 = message; - m_cancelOperation = false; - - SVN_JNI_ERR(svn_wc_context_create(&ctx->wc_ctx, NULL, - in_pool.getPool(), in_pool.getPool()), - NULL); - - return ctx; + /* Place any default --username or --password credentials into the + * auth_baton's run-time parameter hash. ### Same with --no-auth-cache? */ + if (!m_userName.empty()) + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME, + apr_pstrdup(in_pool.getPool(), m_userName.c_str())); + if (!m_passWord.empty()) + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD, + apr_pstrdup(in_pool.getPool(), m_passWord.c_str())); + /* Store where to retrieve authentication data? */ + if (!m_configDir.empty()) + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR, + apr_pstrdup(in_pool.getPool(), m_configDir.c_str())); + return ab; } void -ClientContext::username(const char *pi_username) +CommonContext::username(const char *pi_username) { - m_userName = (pi_username == NULL ? "" : pi_username); + m_userName = (pi_username == NULL ? "" : pi_username); } void -ClientContext::password(const char *pi_password) +CommonContext::password(const char *pi_password) { - m_passWord = (pi_password == NULL ? "" : pi_password); + m_passWord = (pi_password == NULL ? "" : pi_password); } void -ClientContext::setPrompt(Prompter *prompter) +CommonContext::setPrompt(Prompter *prompter) { - delete m_prompter; - m_prompter = prompter; + delete m_prompter; + m_prompter = prompter; } void -ClientContext::setConfigDirectory(const char *configDir) +CommonContext::setConfigDirectory(const char *configDir) { - // A change to the config directory may necessitate creation of - // the config templates. - SVN::Pool requestPool; - SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), ); + // A change to the config directory may necessitate creation of + // the config templates. + SVN::Pool requestPool; + SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), ); - m_configDir = (configDir == NULL ? "" : configDir); - m_context->config = NULL; + m_configDir = (configDir == NULL ? "" : configDir); + + m_config = NULL; } const char * -ClientContext::getConfigDirectory() const +CommonContext::getConfigDirectory() const { - return m_configDir.c_str(); + return m_configDir.c_str(); } void -ClientContext::cancelOperation() +CommonContext::cancelOperation() { - m_cancelOperation = true; + m_cancelOperation = true; } -svn_error_t * -ClientContext::checkCancel(void *cancelBaton) +void +CommonContext::resetOperation() { - ClientContext *that = (ClientContext *)cancelBaton; - if (that->m_cancelOperation) - return svn_error_create(SVN_ERR_CANCELLED, NULL, - _("Operation cancelled")); - else - return SVN_NO_ERROR; + m_cancelOperation = false; } -void -ClientContext::notify(void *baton, - const svn_wc_notify_t *notify, - apr_pool_t *pool) +bool +CommonContext::isCancelledOperation() { - jobject jctx = (jobject) baton; - JNIEnv *env = JNIUtil::getEnv(); + return m_cancelOperation; +} - static jmethodID mid = 0; - if (mid == 0) - { - jclass clazz = env->GetObjectClass(jctx); - if (JNIUtil::isJavaExceptionThrown()) - return; - - mid = env->GetMethodID(clazz, "onNotify", - "(L"JAVA_PACKAGE"/ClientNotifyInformation;)V"); - if (JNIUtil::isJavaExceptionThrown() || mid == 0) - return; - - env->DeleteLocalRef(clazz); - } - - jobject jInfo = CreateJ::ClientNotifyInformation(notify); - if (JNIUtil::isJavaExceptionThrown()) - return; - - env->CallVoidMethod(jctx, mid, jInfo); - if (JNIUtil::isJavaExceptionThrown()) - return; - - env->DeleteLocalRef(jInfo); +svn_error_t * +CommonContext::checkCancel(void *cancelBaton) +{ + CommonContext *that = (CommonContext *) cancelBaton; + if (that->isCancelledOperation()) + return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Operation cancelled")); + else + return SVN_NO_ERROR; } void -ClientContext::progress(apr_off_t progressVal, apr_off_t total, - void *baton, apr_pool_t *pool) +CommonContext::progress(apr_off_t progressVal, apr_off_t total, void *baton, + apr_pool_t *pool) { jobject jctx = (jobject) baton; JNIEnv *env = JNIUtil::getEnv(); @@ -385,7 +295,7 @@ void POP_AND_RETURN_NOTHING(); mid = env->GetMethodID(clazz, "onProgress", - "(L"JAVA_PACKAGE"/ProgressEvent;)V"); + "(L"JAVA_PACKAGE"/ProgressEvent;)V"); if (JNIUtil::isJavaExceptionThrown() || mid == 0) POP_AND_RETURN_NOTHING(); } @@ -403,8 +313,8 @@ void } // Call the Java method. - jobject jevent = env->NewObject(clazz, midCT, - (jlong) progressVal, (jlong) total); + jobject jevent = env->NewObject(clazz, midCT, (jlong) progressVal, + (jlong) total); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); @@ -413,119 +323,18 @@ void POP_AND_RETURN_NOTHING(); } -svn_error_t * -ClientContext::resolve(svn_wc_conflict_result_t **result, - const svn_wc_conflict_description2_t *desc, - void *baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +const char * +CommonContext::getClientName() const { - jobject jctx = (jobject) baton; - JNIEnv *env = JNIUtil::getEnv(); - - // Create a local frame for our references - env->PushLocalFrame(LOCAL_FRAME_SIZE); - if (JNIUtil::isJavaExceptionThrown()) - return SVN_NO_ERROR; - - static jmethodID mid = 0; - if (mid == 0) - { - jclass clazz = env->GetObjectClass(jctx); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN(SVN_NO_ERROR); - - mid = env->GetMethodID(clazz, "resolve", - "(L"JAVA_PACKAGE"/ConflictDescriptor;)" - "L"JAVA_PACKAGE"/ConflictResult;"); - if (JNIUtil::isJavaExceptionThrown() || mid == 0) - POP_AND_RETURN(SVN_NO_ERROR); - } - - // Create an instance of the conflict descriptor. - jobject jdesc = CreateJ::ConflictDescriptor(desc); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN(SVN_NO_ERROR); - - // Invoke the Java conflict resolver callback method using the descriptor. - jobject jresult = env->CallObjectMethod(jctx, mid, jdesc); - if (JNIUtil::isJavaExceptionThrown()) - { - // If an exception is thrown by our conflict resolver, remove it - // from the JNI env, and convert it into a Subversion error. - SVN::Pool tmpPool(scratch_pool); - const char *msg = JNIUtil::thrownExceptionToCString(tmpPool); - svn_error_t *err = svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, - NULL, msg); - env->PopLocalFrame(NULL); - return err; - } - - *result = javaResultToC(jresult, result_pool); - if (*result == NULL) - { - // Unable to convert the result into a C representation. - env->PopLocalFrame(NULL); - return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, NULL); - } - - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + return "javahl"; } -svn_wc_conflict_result_t * -ClientContext::javaResultToC(jobject jresult, apr_pool_t *pool) +svn_error_t * +CommonContext::clientName(void *baton, const char **name, apr_pool_t *pool) { - JNIEnv *env = JNIUtil::getEnv(); + CommonContext *that = (CommonContext *) baton; - // Create a local frame for our references - env->PushLocalFrame(LOCAL_FRAME_SIZE); - if (JNIUtil::isJavaExceptionThrown()) - return SVN_NO_ERROR; + *name = that->getClientName(); - static jmethodID getChoice = 0; - static jmethodID getMergedPath = 0; - - jclass clazz = NULL; - if (getChoice == 0 || getMergedPath == 0) - { - clazz = env->FindClass(JAVA_PACKAGE "/ConflictResult"); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NULL; - } - - if (getChoice == 0) - { - getChoice = env->GetMethodID(clazz, "getChoice", - "()L"JAVA_PACKAGE"/ConflictResult$Choice;"); - if (JNIUtil::isJavaExceptionThrown() || getChoice == 0) - POP_AND_RETURN_NULL; - } - if (getMergedPath == 0) - { - getMergedPath = env->GetMethodID(clazz, "getMergedPath", - "()Ljava/lang/String;"); - if (JNIUtil::isJavaExceptionThrown() || getMergedPath == 0) - POP_AND_RETURN_NULL; - } - - jobject jchoice = env->CallObjectMethod(jresult, getChoice); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NULL; - - jstring jmergedPath = (jstring) env->CallObjectMethod(jresult, getMergedPath); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NULL; - - JNIStringHolder mergedPath(jmergedPath); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NULL; - - svn_wc_conflict_result_t *result = - svn_wc_create_conflict_result(EnumMapper::toConflictChoice(jchoice), - mergedPath.pstrdup(pool), - pool); - - env->PopLocalFrame(NULL); - return result; + return SVN_NO_ERROR; } Index: subversion/bindings/javahl/native/ClientContext.cpp =================================================================== --- subversion/bindings/javahl/native/ClientContext.cpp (revision 1328758) +++ subversion/bindings/javahl/native/ClientContext.cpp (working copy) @@ -39,38 +39,11 @@ ClientContext::ClientContext(jobject jsvnclient, SVN::Pool &pool) - : m_prompter(NULL), - m_cancelOperation(false) +: CommonContext(pool) { - JNIEnv *env = JNIUtil::getEnv(); - - /* Grab a global reference to the Java object embedded in the parent Java - object. */ static jfieldID ctxFieldID = 0; - if (ctxFieldID == 0) - { - jclass clazz = env->GetObjectClass(jsvnclient); - if (JNIUtil::isJavaExceptionThrown()) - return; + attachJavaObject(jsvnclient, "L"JAVA_PACKAGE"/SVNClient$ClientContext;", "clientContext", &ctxFieldID); - ctxFieldID = env->GetFieldID(clazz, "clientContext", - "L"JAVA_PACKAGE"/SVNClient$ClientContext;"); - if (JNIUtil::isJavaExceptionThrown() || ctxFieldID == 0) - return; - - env->DeleteLocalRef(clazz); - } - - jobject jctx = env->GetObjectField(jsvnclient, ctxFieldID); - if (JNIUtil::isJavaExceptionThrown()) - return; - - m_jctx = env->NewGlobalRef(jctx); - if (JNIUtil::isJavaExceptionThrown()) - return; - - env->DeleteLocalRef(jctx); - SVN_JNI_ERR(svn_client_create_context(&m_context, pool.getPool()), ); @@ -95,16 +68,11 @@ ClientContext::ClientContext(jobject jsvnclient, S m_context->conflict_func2 = resolve; m_context->conflict_baton2 = m_jctx; - m_context->client_name = "javahl"; - m_pool = &pool; + m_context->client_name = getClientName(); } ClientContext::~ClientContext() { - delete m_prompter; - - JNIEnv *env = JNIUtil::getEnv(); - env->DeleteGlobalRef(m_jctx); } @@ -139,7 +107,6 @@ svn_client_ctx_t * ClientContext::getContext(CommitMessage *message, SVN::Pool &in_pool) { apr_pool_t *pool = in_pool.getPool(); - svn_auth_baton_t *ab; svn_client_ctx_t *ctx = m_context; /* Make a temporary copy of ctx to restore at pool cleanup to avoid @@ -154,121 +121,17 @@ ClientContext::getContext(CommitMessage *message, apr_pool_cleanup_register(in_pool.getPool(), bt, clear_ctx_ptrs, clear_ctx_ptrs); - if (!ctx->config) { - const char *configDir = m_configDir.c_str(); - if (m_configDir.empty()) - configDir = NULL; - SVN_JNI_ERR(svn_config_get_config(&(ctx->config), configDir, - m_pool->getPool()), - NULL); + apr_hash_t * configData = getConfigData(); + ctx->config = configData; bt->backup->config = ctx->config; } - svn_config_t *config = (svn_config_t *) apr_hash_get(ctx->config, - SVN_CONFIG_CATEGORY_CONFIG, - APR_HASH_KEY_STRING); - - /* The whole list of registered providers */ - apr_array_header_t *providers; - - /* Populate the registered providers with the platform-specific providers */ - SVN_JNI_ERR(svn_auth_get_platform_specific_client_providers(&providers, - config, - pool), - NULL); - - /* Use the prompter (if available) to prompt for password and cert - * caching. */ - svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL; - void *plaintext_prompt_baton = NULL; - svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func; - void *plaintext_passphrase_prompt_baton = NULL; - - if (m_prompter != NULL) - { - plaintext_prompt_func = Prompter::plaintext_prompt; - plaintext_prompt_baton = m_prompter; - plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt; - plaintext_passphrase_prompt_baton = m_prompter; - } - - /* The main disk-caching auth providers, for both - * 'username/password' creds and 'username' creds. */ - svn_auth_provider_object_t *provider; - - svn_auth_get_simple_provider2(&provider, plaintext_prompt_func, - plaintext_prompt_baton, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - svn_auth_get_username_provider(&provider, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - /* The server-cert, client-cert, and client-cert-password providers. */ - SVN_JNI_ERR(svn_auth_get_platform_specific_provider(&provider, - "windows", - "ssl_server_trust", - pool), - NULL); - - if (provider) - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - svn_auth_get_ssl_server_trust_file_provider(&provider, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - svn_auth_get_ssl_client_cert_file_provider(&provider, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - svn_auth_get_ssl_client_cert_pw_file_provider2(&provider, - plaintext_passphrase_prompt_func, - plaintext_passphrase_prompt_baton, pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - if (m_prompter != NULL) - { - /* Two basic prompt providers: username/password, and just username.*/ - provider = m_prompter->getProviderSimple(in_pool); - - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - provider = m_prompter->getProviderUsername(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - /* Three ssl prompt providers, for server-certs, client-certs, - * and client-cert-passphrases. */ - provider = m_prompter->getProviderServerSSLTrust(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - provider = m_prompter->getProviderClientSSL(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - - provider = m_prompter->getProviderClientSSLPassword(in_pool); - APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider; - } - - /* Build an authentication baton to give to libsvn_client. */ - svn_auth_open(&ab, providers, pool); - - /* Place any default --username or --password credentials into the - * auth_baton's run-time parameter hash. ### Same with --no-auth-cache? */ - if (!m_userName.empty()) - svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME, - apr_pstrdup(in_pool.getPool(), - m_userName.c_str())); - if (!m_passWord.empty()) - svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD, - apr_pstrdup(in_pool.getPool(), - m_passWord.c_str())); - /* Store where to retrieve authentication data? */ - if (!m_configDir.empty()) - svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR, - apr_pstrdup(in_pool.getPool(), - m_configDir.c_str())); - - ctx->auth_baton = ab; + ctx->auth_baton = getAuthBaton(in_pool); ctx->log_msg_baton3 = message; - m_cancelOperation = false; + resetOperation(); SVN_JNI_ERR(svn_wc_context_create(&ctx->wc_ctx, NULL, in_pool.getPool(), in_pool.getPool()), @@ -278,60 +141,6 @@ ClientContext::getContext(CommitMessage *message, } void -ClientContext::username(const char *pi_username) -{ - m_userName = (pi_username == NULL ? "" : pi_username); -} - -void -ClientContext::password(const char *pi_password) -{ - m_passWord = (pi_password == NULL ? "" : pi_password); -} - -void -ClientContext::setPrompt(Prompter *prompter) -{ - delete m_prompter; - m_prompter = prompter; -} - -void -ClientContext::setConfigDirectory(const char *configDir) -{ - // A change to the config directory may necessitate creation of - // the config templates. - SVN::Pool requestPool; - SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), ); - - m_configDir = (configDir == NULL ? "" : configDir); - m_context->config = NULL; -} - -const char * -ClientContext::getConfigDirectory() const -{ - return m_configDir.c_str(); -} - -void -ClientContext::cancelOperation() -{ - m_cancelOperation = true; -} - -svn_error_t * -ClientContext::checkCancel(void *cancelBaton) -{ - ClientContext *that = (ClientContext *)cancelBaton; - if (that->m_cancelOperation) - return svn_error_create(SVN_ERR_CANCELLED, NULL, - _("Operation cancelled")); - else - return SVN_NO_ERROR; -} - -void ClientContext::notify(void *baton, const svn_wc_notify_t *notify, apr_pool_t *pool) @@ -365,54 +174,6 @@ ClientContext::notify(void *baton, env->DeleteLocalRef(jInfo); } -void -ClientContext::progress(apr_off_t progressVal, apr_off_t total, - void *baton, apr_pool_t *pool) -{ - jobject jctx = (jobject) baton; - JNIEnv *env = JNIUtil::getEnv(); - - // Create a local frame for our references - env->PushLocalFrame(LOCAL_FRAME_SIZE); - if (JNIUtil::isJavaExceptionThrown()) - return; - - static jmethodID mid = 0; - if (mid == 0) - { - jclass clazz = env->GetObjectClass(jctx); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NOTHING(); - - mid = env->GetMethodID(clazz, "onProgress", - "(L"JAVA_PACKAGE"/ProgressEvent;)V"); - if (JNIUtil::isJavaExceptionThrown() || mid == 0) - POP_AND_RETURN_NOTHING(); - } - - static jmethodID midCT = 0; - jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressEvent"); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NOTHING(); - - if (midCT == 0) - { - midCT = env->GetMethodID(clazz, "<init>", "(JJ)V"); - if (JNIUtil::isJavaExceptionThrown() || midCT == 0) - POP_AND_RETURN_NOTHING(); - } - - // Call the Java method. - jobject jevent = env->NewObject(clazz, midCT, - (jlong) progressVal, (jlong) total); - if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN_NOTHING(); - - env->CallVoidMethod(jctx, mid, jevent); - - POP_AND_RETURN_NOTHING(); -} - svn_error_t * ClientContext::resolve(svn_wc_conflict_result_t **result, const svn_wc_conflict_description2_t *desc, Index: subversion/bindings/javahl/native/CommonContext.h =================================================================== --- subversion/bindings/javahl/native/CommonContext.h (working copy) +++ subversion/bindings/javahl/native/CommonContext.h (working copy) @@ -20,12 +20,12 @@ * ==================================================================== * @endcopyright * - * @file ClientContext.h - * @brief Interface of the class ClientContext + * @file CommonContext.h + * @brief Interface of the class CommonContext */ -#ifndef CLIENTCONTEXT_H -#define CLIENTCONTEXT_H +#ifndef COMMONCONTEXT_H +#define COMMONCONTEXT_H #include <string> @@ -37,52 +37,43 @@ #include "JNIStringHolder.h" class Prompter; -class CommitMessage; /** - * This class contains a Java objects implementing the interface ClientContext - * and implements the functions read & close of svn_stream_t. - * + * This class contains a Java objects implementing the interface CommonContext */ -class ClientContext +class CommonContext { private: - svn_client_ctx_t *m_context; - const SVN::Pool *m_pool; - jobject m_jctx; - std::string m_userName; std::string m_passWord; std::string m_configDir; + apr_hash_t * m_config; + Prompter *m_prompter; bool m_cancelOperation; protected: - static void notify(void *baton, const svn_wc_notify_t *notify, - apr_pool_t *pool); + SVN::Pool *m_pool; + + jobject m_jctx; static void progress(apr_off_t progressVal, apr_off_t total, void *baton, apr_pool_t *pool); - static svn_error_t *resolve(svn_wc_conflict_result_t **result, - const svn_wc_conflict_description2_t *desc, - void *baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - static svn_wc_conflict_result_t *javaResultToC(jobject result, - apr_pool_t *pool); - public: - ClientContext(jobject jsvnclient, SVN::Pool &pool); - ~ClientContext(); + CommonContext(SVN::Pool &pool); + void attachJavaObject(jobject contextHolder, const char *contextClassType, const char *contextFieldName, jfieldID * ctxFieldID); + virtual ~CommonContext(); static svn_error_t *checkCancel(void *cancelBaton); - svn_client_ctx_t *getContext(CommitMessage *message, SVN::Pool &in_pool); + virtual void username(const char *pi_username); + virtual void password(const char *pi_password); + virtual void setPrompt(Prompter *prompter); + svn_auth_baton_t *getAuthBaton(SVN::Pool &in_pool); - void username(const char *pi_username); - void password(const char *pi_password); - void setPrompt(Prompter *prompter); void cancelOperation(); + void resetOperation(); + virtual bool isCancelledOperation(); const char *getConfigDirectory() const; /** @@ -91,6 +82,15 @@ class Prompter; * specified location. */ void setConfigDirectory(const char *configDir); + + /** + * Return configuration data for the context. + * Read it from config directory if necessary + */ + apr_hash_t *getConfigData(); + + static svn_error_t * clientName(void *baton, const char **name, apr_pool_t *pool); + virtual const char * getClientName() const; }; -#endif // CLIENTCONTEXT_H +#endif // COMMONCONTEXT_H