Index: subversion/bindings/javahl/native/SVNRa.h =================================================================== --- subversion/bindings/javahl/native/SVNRa.h (revision 0) +++ subversion/bindings/javahl/native/SVNRa.h (working copy) @@ -0,0 +1,53 @@ +#ifndef SVNRa_H +#define SVNRa_H + +#include + +#include "svn_ra.h" + +#include "SVNBase.h" +#include "RaContext.h" + +#include + +class SVNEditor; + +/* + * This class wraps Ra based operations from svn_ra.h + */ +class SVNRa : public SVNBase +{ + public: + static SVNRa *getCppObject(jobject jthis); + SVNRa(jobject *, jstring jurl, jstring juuid, jobject jconfig); + ~SVNRa(); + + jstring getReposRoot(); + jstring getUUID(); + jstring getUrl(); + jlong getLatestRevision(); + void reparent(jstring url); + + jobject getCommitEditor(jobject jrevprops, jobject commitCallback, + jobject lockTockens, jboolean keepLocks); + + virtual void dispose(jobject jthis); + + /* + * Support management of children via parent. + * This ensures that if the parent is disposed + * so are the children. Because the caller might dispose of the parent + * while holding onto children we need to be careful + */ + void deleteEditor(SVNEditor * editor); + + svn_ra_session_t * getRaSession(); + + private: + svn_ra_session_t * m_session; + + std::set m_svnEditors; + RaContext * m_context; +}; + +#endif //SVNRa_H Index: subversion/bindings/javahl/native/IDirectoryParent.h =================================================================== --- subversion/bindings/javahl/native/IDirectoryParent.h (revision 0) +++ subversion/bindings/javahl/native/IDirectoryParent.h (working copy) @@ -0,0 +1,21 @@ +#ifndef IDIRECTORYPARENT_H_ +#define IDIRECTORYPARENT_H_ + +/** + * Base class that specified methods that directory parents + * must implement + */ +class IDirectoryParent +{ +public: + virtual ~IDirectoryParent() = 0; + + /** + * Method for child directory to request parent to delete the child + */ + virtual void deleteChildDirectory() = 0; +}; + +inline IDirectoryParent::~IDirectoryParent() {} + +#endif /* IDIRECTORYPARENT_H_ */ Index: subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNEditor.cpp =================================================================== --- subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNEditor.cpp (revision 0) +++ subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNEditor.cpp (working copy) @@ -0,0 +1,49 @@ +#include "../include/org_apache_subversion_javahl_ra_SVNEditor.h" + +#include "JNIStackElement.h" +#include "JNIUtil.h" + +#include "SVNEditor.h" + +#include "svn_private_config.h" + + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNEditor_openRoot +(JNIEnv *env, jobject jthis, jlong baseRevision) +{ + JNIEntry(SVNEditor, openRoot); + SVNEditor *editor = SVNEditor::getCppObject(jthis); + CPPADDR_NULL_PTR(editor, NULL); + + return editor->openRoot(baseRevision); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNEditor_closeEdit +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNEditor, closeEdit); + SVNEditor *editor = SVNEditor::getCppObject(jthis); + CPPADDR_NULL_PTR(editor, ); + + editor->closeEdit(jthis); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNEditor_abortEdit +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNEditor, abortEdit); + SVNEditor *editor = SVNEditor::getCppObject(jthis); + CPPADDR_NULL_PTR(editor, ); + + editor->abortEdit(jthis); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNEditor_finalize +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNEditor, finalize); + SVNEditor *editor = SVNEditor::getCppObject(jthis); + + if(editor != NULL) + editor->finalize(); +} Index: subversion/bindings/javahl/native/RaContext.h =================================================================== --- subversion/bindings/javahl/native/RaContext.h (revision 0) +++ subversion/bindings/javahl/native/RaContext.h (working copy) @@ -0,0 +1,20 @@ +#ifndef RACONTEXT_H_ +#define RACONTEXT_H_ + +#include "svn_ra.h" + +#include "CommonContext.h" + +class RaContext : public CommonContext +{ + public: + RaContext(jobject contextHolder, SVN::Pool &pool, jobject jconfig); + virtual ~RaContext(); + void * getCallbackBaton(); + svn_ra_callbacks2_t * getCallbacks(); + + private: + svn_ra_callbacks2_t * m_raCallbacks; +}; + +#endif /* RACONTEXT_H_ */ Index: subversion/bindings/javahl/native/org_apache_subversion_javahl_types_ra_SVNDirectory.cpp =================================================================== --- subversion/bindings/javahl/native/org_apache_subversion_javahl_types_ra_SVNDirectory.cpp (revision 0) +++ subversion/bindings/javahl/native/org_apache_subversion_javahl_types_ra_SVNDirectory.cpp (working copy) @@ -0,0 +1,88 @@ +#include "../include/org_apache_subversion_javahl_ra_SVNDirectory.h" + +#include "JNIStackElement.h" +#include "JNIUtil.h" + +#include "SVNDirectory.h" + +#include "svn_private_config.h" + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_close +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNDirectory, close); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, ); + + dir->close(jthis); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_changeProperty +(JNIEnv *env, jobject jthis, jstring propertyName, jbyteArray propertyValue) +{ + JNIEntry(SVNDirectory, changeProperty); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, ); + + dir->changeProperty(propertyName, propertyValue); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_deleteEntry +(JNIEnv *env, jobject jthis, jstring path, jlong baseRevision) +{ + JNIEntry(SVNDirectory, deleteEntry); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, ); + + dir->deleteEntry(path, baseRevision); +} + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_addDirectory +(JNIEnv *env, jobject jthis, jstring path, jstring copyFromPath, jlong baseRevision) +{ + JNIEntry(SVNDirectory, addDirectory); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, NULL); + + return dir->addDirectory(path, copyFromPath, baseRevision); +} + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_openDirectory +(JNIEnv *env, jobject jthis, jstring path, jlong baseRevision) +{ + JNIEntry(SVNDirectory, openDirectory); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, NULL); + + return dir->openDirectory(path, baseRevision); +} + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_addFile +(JNIEnv *env, jobject jthis, jstring path, jstring copyFromPath, jlong baseRevision) +{ + JNIEntry(SVNDirectory, addFile); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, NULL); + + return dir->addFile(path, copyFromPath, baseRevision); +} + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_openFile +(JNIEnv *env, jobject jthis, jstring path, jlong baseRevision) +{ + JNIEntry(SVNDirectory, openFile); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + CPPADDR_NULL_PTR(dir, NULL); + + return dir->openFile(path, baseRevision); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNDirectory_finalize +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNDirectory, finalize); + SVNDirectory *dir = SVNDirectory::getCppObject(jthis); + + if(dir != NULL) + dir->finalize(); +} Index: subversion/bindings/javahl/native/RaContext.cpp =================================================================== --- subversion/bindings/javahl/native/RaContext.cpp (revision 0) +++ subversion/bindings/javahl/native/RaContext.cpp (working copy) @@ -0,0 +1,136 @@ +#include "RaContext.h" +#include "JNIUtil.h" +#include "Prompter.h" + +#define STRING_RETURN_SIGNATURE "()Ljava/lang/String;" + +RaContext::RaContext(jobject contextHolder, SVN::Pool &pool, jobject jconfig) + :CommonContext(pool), m_raCallbacks(NULL) +{ + /* + * Extract config properties + */ + JNIEnv *env = JNIUtil::getEnv(); + + static jmethodID midUsername = 0; + static jmethodID midPassword = 0; + static jmethodID midConfigDirectory = 0; + static jmethodID midPrompt = 0; + if (midUsername == 0 || midPassword == 0 || midConfigDirectory == 0 || midPrompt == 0) + { + jclass clazz = env->FindClass(JAVA_PACKAGE"/ra/ISVNRaConfig"); + if (JNIUtil::isJavaExceptionThrown()) + return; + + midUsername = env->GetMethodID(clazz, "getUsername", STRING_RETURN_SIGNATURE); + if (JNIUtil::isJavaExceptionThrown() || midUsername == 0) + return; + + midPassword = env->GetMethodID(clazz, "getPassword", STRING_RETURN_SIGNATURE); + if (JNIUtil::isJavaExceptionThrown() || midPassword == 0) + return; + + midConfigDirectory = env->GetMethodID(clazz, "getConfigDirectory", STRING_RETURN_SIGNATURE); + if (JNIUtil::isJavaExceptionThrown() || midConfigDirectory == 0) + return; + + midPrompt = env->GetMethodID(clazz, "getPrompt", "()Lorg/apache/subversion/javahl/callback/UserPasswordCallback;"); + if (JNIUtil::isJavaExceptionThrown() || midPrompt == 0) + return; + + env->DeleteLocalRef(clazz); + } + + jstring jusername = (jstring) env->CallObjectMethod(jconfig, midUsername); + if (JNIUtil::isExceptionThrown()) + return; + + if(jusername != NULL) + { + SVN_JNI_STRING(usernameStr, jusername, ); + username(usernameStr); + + JNIUtil::getEnv()->DeleteLocalRef(jusername); + } + + jstring jpassword = (jstring) env->CallObjectMethod(jconfig, midPassword); + if (JNIUtil::isExceptionThrown()) + return; + + if(jpassword != NULL) + { + SVN_JNI_STRING(passwordStr, jpassword, ); + password(passwordStr); + + JNIUtil::getEnv()->DeleteLocalRef(jpassword); + } + + jstring jconfigDirectory = (jstring) env->CallObjectMethod(jconfig, midConfigDirectory); + if (JNIUtil::isExceptionThrown()) + return; + + SVN_JNI_STRING(configDirectory, jconfigDirectory, ); + setConfigDirectory(configDirectory); + + JNIUtil::getEnv()->DeleteLocalRef(jconfigDirectory); + + jobject jprompter = env->CallObjectMethod(jconfig, midPrompt); + if (JNIUtil::isExceptionThrown()) + return; + + if(jprompter != NULL) + { + Prompter *prompter = Prompter::makeCPrompter(jprompter); + if (JNIUtil::isExceptionThrown()) + return; + + setPrompt(prompter); + JNIUtil::getEnv()->DeleteLocalRef(jprompter); + } + + /* + * Attach session context java object + */ + static jfieldID ctxFieldID = 0; + attachJavaObject(contextHolder, "L"JAVA_PACKAGE"/ra/RaContext;", "sessionContext", &ctxFieldID); + + /* + * Setup callbacks + */ + SVN_JNI_ERR(svn_ra_create_callbacks(&m_raCallbacks, m_pool->getPool()), ); + + m_raCallbacks->auth_baton = getAuthBaton(pool); + m_raCallbacks->cancel_func = checkCancel; + m_raCallbacks->get_client_string = clientName; + m_raCallbacks->progress_baton = m_jctx; + m_raCallbacks->progress_func = progress; + + /* + * JNI RA layer does not work with WC so all WC callbacks are set to NULL + */ + m_raCallbacks->get_wc_prop = NULL; + m_raCallbacks->invalidate_wc_props = NULL; + m_raCallbacks->push_wc_prop = NULL; + m_raCallbacks->set_wc_prop = NULL; + + /* + * Don't set deprecated callback + */ + m_raCallbacks->open_tmp_file = NULL; +} + +RaContext::~RaContext() +{ +} + +void * +RaContext::getCallbackBaton() +{ + return this; +} + +svn_ra_callbacks2_t * +RaContext::getCallbacks() +{ + return m_raCallbacks; +} Index: subversion/bindings/javahl/native/SVNEditor.h =================================================================== --- subversion/bindings/javahl/native/SVNEditor.h (revision 0) +++ subversion/bindings/javahl/native/SVNEditor.h (working copy) @@ -0,0 +1,68 @@ +#ifndef SVNEditor_H +#define SVNEditor_H + +#include + +#include "svn_ra.h" + +#include "CommitCallback.h" +#include "IDirectoryParent.h" +#include "SVNBase.h" +#include "SVNRa.h" + +class SVNDirectory; +class SVNFile; + +/* + * This class wraps editor based operations from svn_delta.h + */ +class SVNEditor : public SVNBase, public IDirectoryParent +{ + public: + // Lifecycle functions + static SVNEditor * getCppObject(jobject jthis); + + SVNEditor(SVN::Pool & pPool, SVNRa & parentRaSession, jobject *, + jobject jrevprops, jobject jcommitCallback, jobject jlockTockens, + jboolean keepLocks); + virtual ~SVNEditor(); + + // Editor functions + const svn_delta_editor_t * getEditor(); + SVN::Pool & getEditorPool(); + + void closeEdit(jobject jthis); + + void abortEdit(jobject jthis); + + // Directory functions + jobject openRoot(jlong baseRevision); + + virtual void deleteChildDirectory(); + + // File functions + void deleteFile(SVNFile * svnFile); + + void registerFile(SVNFile * svnFile); + + /* + * Partially dispose of this object without having reference to the associated jobject + */ + virtual void dispose(); + + private: + virtual void dispose(jobject jthis); + + const svn_delta_editor_t * m_deltaEditor; + void * m_editBaton; + SVNRa & m_parentRaSession; + CommitCallback * m_commitCallback; + + // Because of restriction #3 from svn_delta.h we only need to keep track of one directory + SVNDirectory * m_rootDirectory; + + //But we do have to keep track of all files as delta's can be sent at the end + std::set m_svnFiles; +}; + +#endif //SVNEditor_H Index: subversion/bindings/javahl/native/org_apache_subversion_javahl_types_ra_SVNFile.cpp =================================================================== --- subversion/bindings/javahl/native/org_apache_subversion_javahl_types_ra_SVNFile.cpp (revision 0) +++ subversion/bindings/javahl/native/org_apache_subversion_javahl_types_ra_SVNFile.cpp (working copy) @@ -0,0 +1,58 @@ +#include "../include/org_apache_subversion_javahl_ra_SVNFile.h" + +#include "JNIStackElement.h" +#include "JNIUtil.h" + +#include "SVNFile.h" + +#include "svn_private_config.h" + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNFile_sendStream +(JNIEnv *env, jobject jthis, jobject targetStream, jstring baseMd5CheckSum) +{ + JNIEntry(SVNFile, sendStream); + SVNFile *file = SVNFile::getCppObject(jthis); + CPPADDR_NULL_PTR(file, ); + + file->sendStream(targetStream, baseMd5CheckSum); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNFile_sendDeltaStream +(JNIEnv *env, jobject jthis, jobject sourceStream, jobject targetStream, jstring baseMd5CheckSum) +{ + JNIEntry(SVNFile, sendDeltaStream); + SVNFile *file = SVNFile::getCppObject(jthis); + CPPADDR_NULL_PTR(file, ); + + file->sendDeltaStream(sourceStream, targetStream, baseMd5CheckSum); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNFile_changeProperty +(JNIEnv *env, jobject jthis, jstring propertyName, jbyteArray propertyValue) +{ + JNIEntry(SVNFile, changeProperty); + SVNFile *file = SVNFile::getCppObject(jthis); + CPPADDR_NULL_PTR(file, ); + + file->changeProperty(propertyName, propertyValue); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNFile_close +(JNIEnv *env, jobject jthis, jstring md5HexChecksum) +{ + JNIEntry(SVNFile, close); + SVNFile *file = SVNFile::getCppObject(jthis); + CPPADDR_NULL_PTR(file, ); + + file->close(jthis, md5HexChecksum); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNFile_finalize +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNFile, finalize); + SVNFile *file = SVNFile::getCppObject(jthis); + + if(file != NULL) + file->finalize(); +} Index: subversion/bindings/javahl/native/SVNFile.cpp =================================================================== --- subversion/bindings/javahl/native/SVNFile.cpp (revision 0) +++ subversion/bindings/javahl/native/SVNFile.cpp (working copy) @@ -0,0 +1,152 @@ +#include "JNIStringHolder.h" +#include "JNIByteArray.h" +#include "JNIUtil.h" + +#include "svn_delta.h" +#include "svn_private_config.h" + +#include "InputStream.h" +#include "SVNFile.h" + +#define JAVA_CLASS_SVN_FILE JAVA_PACKAGE "/ra/SVNFile" + +SVNFile * +SVNFile::getCppObject(jobject jthis) +{ + static jfieldID fid = 0; + jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid, + JAVA_CLASS_SVN_FILE); + return (cppAddr == 0 ? NULL : reinterpret_cast(cppAddr)); +} + +SVNFile::SVNFile(SVN::Pool & pPool, SVNEditor & pParentEditor, jobject *jself, + void * pDirBaton) : + SVNBase(pPool), m_parentEditor(pParentEditor), m_fileBaton(pDirBaton) +{ + m_parentEditor.registerFile(this); + *jself = createCppBoundObject(JAVA_CLASS_SVN_FILE); + +} + +SVNFile::~SVNFile() +{ +} + +void +SVNFile::changeProperty(jstring jpropertyName, jbyteArray jpropertyValue) +{ + ASSERT_NOT_DISPOSED(); + + SVN_JNI_NULL_PTR_EX(jpropertyName, _("propertyName cannot be null"),); + SVN_JNI_STRING(propertyName, jpropertyName, ); + SVN_JNI_BYTE_ARRAY(propertyValue, jpropertyValue, ); + + SVN::Pool subPool(pool); + + SVN_JNI_ERR( + m_parentEditor.getEditor()->change_file_prop(m_fileBaton, propertyName, + propertyValue.getSvnString(subPool.getPool()), subPool.getPool()), + ); +} + +void +SVNFile::close(jobject jthis, jstring jMd5hexCheckSum) +{ + ASSERT_NOT_DISPOSED(); + + svn_error_t * result = NULL; + + { + SVN::Pool subPool(pool); + + SVN_JNI_STRING(md5hexCheckSum, jMd5hexCheckSum, ); + + result = m_parentEditor.getEditor()->close_file(m_fileBaton, md5hexCheckSum, + subPool.getPool()); + } + + dispose(jthis); + + SVN_JNI_ERR(result, ); +} + +void +SVNFile::sendDeltaStream(jobject jSourceStream, jobject jTargetStream, + jstring jBaseMd5HexChecksum) +{ + ASSERT_NOT_DISPOSED(); + + SVN_JNI_STRING(baseMd5HexChecksum, jBaseMd5HexChecksum, ); + + SVN_JNI_NULL_PTR_EX(jTargetStream, _("targetStream cannot be null"),); + SVN_JNI_INPUT_STREAM(targetStream, jTargetStream, ); + + SVN_JNI_NULL_PTR_EX(jSourceStream, _("sourceStream cannot be null"),); + SVN_JNI_INPUT_STREAM(sourceStream, jSourceStream, ); + + SVN::Pool subPool(pool); + + svn_txdelta_window_handler_t handler; + void *handlerBaton = NULL; + + SVN_JNI_ERR( + m_parentEditor.getEditor()->apply_textdelta(m_fileBaton, baseMd5HexChecksum, + pool.getPool(), &handler, &handlerBaton), + ); + + svn_txdelta_stream_t *txstream; + svn_txdelta(&txstream, sourceStream.getStream(subPool), + targetStream.getStream(subPool), subPool.getPool()); + + SVN_JNI_ERR( + svn_txdelta_send_txstream(txstream, handler, handlerBaton, subPool.getPool()), + ); +} + +void +SVNFile::sendStream(jobject jTargetStream, jstring jBaseMd5HexChecksum) +{ + ASSERT_NOT_DISPOSED(); + + SVN_JNI_STRING(baseMd5HexChecksum, jBaseMd5HexChecksum, ); + + SVN_JNI_NULL_PTR_EX(jTargetStream, _("targetStream cannot be null"),); + SVN_JNI_INPUT_STREAM(targetStream, jTargetStream, ); + + SVN::Pool subPool(pool); + + svn_txdelta_window_handler_t handler; + void *handlerBaton = NULL; + + SVN_JNI_ERR( + m_parentEditor.getEditor()->apply_textdelta(m_fileBaton, baseMd5HexChecksum, + pool.getPool(), &handler, &handlerBaton), + ); + + SVN_JNI_ERR( + svn_txdelta_send_stream(targetStream.getStream(subPool), handler, handlerBaton, + NULL, subPool.getPool()), + ); +} +void +SVNFile::dispose() +{ + m_fileBaton = NULL; + markDisposed(); +} + +void +SVNFile::dispose(jobject jthis) +{ + /* + * We are being disposed so lets clean up our cppAddr link + */ + static jfieldID fid = 0; + SVNBase::disconnectCppObject(jthis, &fid, JAVA_CLASS_SVN_FILE); + dispose(); + + /* + * Ask out parent to destroy us + */ + m_parentEditor.deleteFile(this); +} Index: subversion/bindings/javahl/native/SVNFile.h =================================================================== --- subversion/bindings/javahl/native/SVNFile.h (revision 0) +++ subversion/bindings/javahl/native/SVNFile.h (working copy) @@ -0,0 +1,63 @@ +#ifndef SVNFile_H +#define SVNFile_H + +#include + +#include "svn_ra.h" + +#include "SVNBase.h" +#include "SVNEditor.h" +#include "SVNDirectory.h" + +/* + * This class wraps file based operations from svn_delta.h + */ +class SVNFile : public SVNBase +{ + public: + static SVNFile *getCppObject(jobject jthis); + + SVNFile(SVN::Pool & pPool, SVNEditor & parentEditor, jobject *jself, + void * pFileBaton); + ~SVNFile(); + + /* + * Change property @a propertyName to value @a propertyValue + */ + void changeProperty(jstring propertyName, jbyteArray propertyValue); + + /* + * Release all resources help by this file object + * optional @a md5hexCheckSum specifies expected checksum after all file + * operations + */ + void close(jobject jthis, jstring md5hexCheckSum); + + /** + * Changes file with checksum @a baseMd5HexChecksum and context equivalent + * to @a sourceStream + * to have content as specified by @a targetStream + */ + void sendDeltaStream(jobject sourceStream, jobject targetStream, + jstring baseMd5HexChecksum); + + /** + * Changes file with checksum @a baseMd5HexChecksum to have content as + * specified by @a targetStream + */ + void sendStream(jobject targetStream, jstring baseMd5HexChecksum); + + /* + * Partially dispose of this object without having reference to the + * associated jobject + */ + virtual void dispose(); + + private: + virtual void dispose(jobject jthis); + + void * m_fileBaton; + SVNEditor & m_parentEditor; +}; + +#endif //SVNFile_H Index: subversion/bindings/javahl/native/SVNRa.cpp =================================================================== --- subversion/bindings/javahl/native/SVNRa.cpp (revision 0) +++ subversion/bindings/javahl/native/SVNRa.cpp (working copy) @@ -0,0 +1,192 @@ +#include "JNIStringHolder.h" +#include "JNIUtil.h" + +#include "svn_ra.h" + +#include "SVNEditor.h" +#include "SVNRa.h" + +#include "svn_private_config.h" + +#define JAVA_CLASS_SVN_RA JAVA_PACKAGE "/ra/SVNRa" + +SVNRa * +SVNRa::getCppObject(jobject jthis) +{ + static jfieldID fid = 0; + jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid, + JAVA_CLASS_SVN_RA); + return (cppAddr == 0 ? NULL : reinterpret_cast(cppAddr)); +} + +SVNRa::SVNRa(jobject *jthis_out, jstring jurl, jstring juuid, jobject jconfig) +{ + JNIEnv *env = JNIUtil::getEnv(); + + SVN_JNI_STRING(url, jurl, ); + SVN_JNI_STRING(uuid, juuid, ); + + // Create java session object + jclass clazz = env->FindClass(JAVA_CLASS_SVN_RA); + if (JNIUtil::isJavaExceptionThrown()) + return; + + static jmethodID ctor = 0; + if (ctor == 0) + { + ctor = env->GetMethodID(clazz, "", "(J)V"); + if (JNIUtil::isJavaExceptionThrown()) + return; + } + + jlong cppAddr = this->getCppAddr(); + + jobject jSVNRa = env->NewObject(clazz, ctor, cppAddr); + if (JNIUtil::isJavaExceptionThrown()) + return; + + *jthis_out = jSVNRa; + + m_context = new RaContext(jSVNRa, pool, jconfig); + if (JNIUtil::isJavaExceptionThrown()) + return; + + //TODO: add corrected URL support + SVN_JNI_ERR( + svn_ra_open4(&m_session, NULL, url, uuid, m_context->getCallbacks(), + m_context->getCallbackBaton(), m_context->getConfigData(), + pool.getPool()), + ); +} + +SVNRa::~SVNRa() +{ + if (m_context) + { + delete m_context; + } +} + +jstring +SVNRa::getReposRoot() +{ + SVN::Pool subPool(pool); + + const char * rootPath; + SVN_JNI_ERR(svn_ra_get_repos_root2(m_session, &rootPath, subPool.getPool()), + NULL); + + jstring description = JNIUtil::makeJString(rootPath); + if (JNIUtil::isJavaExceptionThrown()) + return NULL; + + return description; +} + +jlong +SVNRa::getLatestRevision() +{ + SVN::Pool subPool(pool); + svn_revnum_t rev; + + SVN_JNI_ERR(svn_ra_get_latest_revnum(m_session, &rev, subPool.getPool()), + SVN_INVALID_REVNUM); + + return rev; +} + +jstring +SVNRa::getUUID() +{ + SVN::Pool subPool(pool); + const char * uuid; + + SVN_JNI_ERR(svn_ra_get_uuid2(m_session, &uuid, subPool.getPool()), NULL); + + jstring juuid = JNIUtil::makeJString(uuid); + if (JNIUtil::isJavaExceptionThrown()) + return NULL; + + return juuid; +} + +jstring +SVNRa::getUrl() +{ + SVN::Pool subPool(pool); + const char * url; + + SVN_JNI_ERR(svn_ra_get_session_url(m_session, &url, subPool.getPool()), NULL); + + jstring jurl = JNIUtil::makeJString(url); + if (JNIUtil::isJavaExceptionThrown()) + return NULL; + + return jurl; +} + +void +SVNRa::reparent(jstring jurl) +{ + if (jurl == NULL) + { + JNIUtil::throwError(_("Reparent URL cannot be null")); + return; + } + + SVN::Pool subPool(pool); + + JNIStringHolder url(jurl); + if (JNIUtil::isExceptionThrown()) + return; + + SVN_JNI_ERR(svn_ra_reparent(m_session, url, subPool.getPool()), ); +} + +jobject +SVNRa::getCommitEditor(jobject jrevprops, jobject jcommitCallback, + jobject jlockTockens, jboolean keepLocks) +{ + jobject jSVNEditor = NULL; + + SVNEditor * pEditor = new SVNEditor(pool, *this, &jSVNEditor, jrevprops, + jcommitCallback, jlockTockens, keepLocks); + + m_svnEditors.insert(pEditor); + + return jSVNEditor; +} + +void +SVNRa::deleteEditor(SVNEditor * editor) +{ + /* + * Remove the editor from out list and dispose it + */ + m_svnEditors.erase(editor); + delete editor; +} + +void +SVNRa::dispose(jobject jthis) +{ + /* + * Dispose of any editors that caller did not + */ + std::set::iterator it; + for (it = m_svnEditors.begin(); it != m_svnEditors.end(); it++) + { + (*it)->dispose(); + } + + m_svnEditors.clear(); + + static jfieldID fid = 0; + SVNBase::dispose(jthis, &fid, JAVA_CLASS_SVN_RA); +} + +svn_ra_session_t * +SVNRa::getRaSession() +{ + return m_session; +} Index: subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNRaFactory.cpp =================================================================== --- subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNRaFactory.cpp (revision 0) +++ subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNRaFactory.cpp (working copy) @@ -0,0 +1,38 @@ +#include "../include/org_apache_subversion_javahl_ra_SVNRaFactory.h" + +#include "JNIStackElement.h" +#include "JNIUtil.h" +#include "JNIStringHolder.h" + +#include "SVNRa.h" + +#include "svn_private_config.h" + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNRaFactory_createRaSession +(JNIEnv *env, jclass jclass, jstring jurl, jstring juuid, jobject jconfig) +{ + //JNI macros need jthis but this is a static call + jobject jthis = NULL; + JNIEntry(SVNRaFactory, createRaSession); + + /* + * Initialize ra layer if we have not done so yet + */ + static bool initialized = false; + if(!initialized) + { + SVN_JNI_ERR(svn_ra_initialize(JNIUtil::getPool()), NULL); + initialized = true; + } + + /* + * Create Ra C++ object and return its java wrapper to the caller + */ + jobject jSVNRa = NULL; + + SVNRa * raSesson = new SVNRa(&jSVNRa, jurl, juuid, jconfig); + if (JNIUtil::isJavaExceptionThrown()) + return NULL; + + return jSVNRa; +} Index: subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNRa.cpp =================================================================== --- subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNRa.cpp (revision 0) +++ subversion/bindings/javahl/native/org_apache_subversion_javahl_ra_SVNRa.cpp (working copy) @@ -0,0 +1,89 @@ +#include "../include/org_apache_subversion_javahl_ra_SVNRa.h" + +#include "JNIStackElement.h" +#include "JNIUtil.h" +#include "Prompter.h" +#include "SVNRa.h" + +#include "svn_private_config.h" + + +JNIEXPORT void JNICALL +Java_org_apache_subversion_javahl_ra_SVNRa_finalize +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNRa, finalize); + SVNRa *ras = SVNRa::getCppObject(jthis); + if (ras != NULL) + ras->finalize(); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_dispose +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNRa, dispose); + SVNRa *ras = SVNRa::getCppObject(jthis); + if (ras != NULL) + ras->dispose(jthis); +} + +JNIEXPORT jstring JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_getRoot +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNRa, getRoot); + SVNRa *ras = SVNRa::getCppObject(jthis); + CPPADDR_NULL_PTR(ras, NULL); + + return ras->getReposRoot(); +} + +JNIEXPORT jlong JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_getLatestRevision +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNRa, getLatestRevision); + SVNRa *ras = SVNRa::getCppObject(jthis); + CPPADDR_NULL_PTR(ras, SVN_INVALID_REVNUM); + + return ras->getLatestRevision(); +} + +JNIEXPORT jstring JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_getUUID +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNRa, getUUID); + SVNRa *ras = SVNRa::getCppObject(jthis); + CPPADDR_NULL_PTR(ras, NULL); + + return ras->getUUID(); +} + +JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_reparent +(JNIEnv *env, jobject jthis, jstring url) +{ + JNIEntry(SVNRa, reparent); + SVNRa *ras = SVNRa::getCppObject(jthis); + CPPADDR_NULL_PTR(ras, ); + + ras->reparent(url); +} + + +JNIEXPORT jstring JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_getUrl +(JNIEnv *env, jobject jthis) +{ + JNIEntry(SVNRa, getUrl); + SVNRa *ras = SVNRa::getCppObject(jthis); + CPPADDR_NULL_PTR(ras, NULL); + + return ras->getUrl(); +} + +JNIEXPORT jobject JNICALL Java_org_apache_subversion_javahl_ra_SVNRa_getCommitEditor +(JNIEnv *env, jobject jthis, jobject jrevprops, jobject commitCallback, jobject lockTockens, jboolean keepLocks) +{ + JNIEntry(SVNRa, getCommitEditor); + SVNRa *ras = SVNRa::getCppObject(jthis); + CPPADDR_NULL_PTR(ras, NULL); + + return ras->getCommitEditor(jrevprops, commitCallback, lockTockens, keepLocks); +} Index: subversion/bindings/javahl/native/SVNDirectory.h =================================================================== --- subversion/bindings/javahl/native/SVNDirectory.h (revision 0) +++ subversion/bindings/javahl/native/SVNDirectory.h (working copy) @@ -0,0 +1,60 @@ +#ifndef SVNDirectory_H +#define SVNDirectory_H + +#include + +#include "svn_ra.h" + +#include "SVNBase.h" +#include "SVNEditor.h" +#include "IDirectoryParent.h" + +/* + * This class wraps directory based operations from svn_delta.h + */ +class SVNDirectory : public SVNBase, public IDirectoryParent +{ + public: + static SVNDirectory *getCppObject(jobject jthis); + + SVNDirectory(SVN::Pool & pPool, SVNEditor & parentEditor, + IDirectoryParent & pParent, jobject *jself, void * pDirBaton); + virtual ~SVNDirectory(); + + jobject addDirectory(jstring path, jstring copyFromPath, jlong copyFromRevision); + + jobject addFile(jstring path, jstring copyFromPath, jlong baseRevision); + + void changeProperty(jstring propertyName, jbyteArray propertyValue); + + void close(jobject jthis); + + void deleteEntry(jstring path, jlong baseRevision); + + /* + * Partially dispose of this object without having reference to the associated jobject + */ + virtual void dispose(); + + jobject openDirectory(jstring path, jlong baseRevision); + + jobject openFile(jstring path, jlong baseRevision); + + private: + /* + * dispose this object + */ + virtual void dispose(jobject jthis); + + /* + * Method for the child directory to call to have it deleted + */ + virtual void deleteChildDirectory(); + + void * m_dirBaton; + SVNEditor & m_parentEditor; + IDirectoryParent & m_parent; + SVNDirectory * m_childDirectory; +}; + +#endif //SVNDirectory_H Index: subversion/bindings/javahl/native/SVNEditor.cpp =================================================================== --- subversion/bindings/javahl/native/SVNEditor.cpp (revision 0) +++ subversion/bindings/javahl/native/SVNEditor.cpp (working copy) @@ -0,0 +1,228 @@ +#include "JNIStringHolder.h" +#include "JNIUtil.h" + +#include "SVNDirectory.h" +#include "SVNEditor.h" +#include "SVNFile.h" +#include "RevpropTable.h" +#include "StringsTable.h" + +#include "svn_private_config.h" + +#define JAVA_CLASS_SVN_EDITOR JAVA_PACKAGE "/ra/SVNEditor" + +SVNEditor * +SVNEditor::getCppObject(jobject jthis) +{ + static jfieldID fid = 0; + jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid, + JAVA_CLASS_SVN_EDITOR); + return (cppAddr == 0 ? NULL : reinterpret_cast(cppAddr)); +} + +SVNEditor::SVNEditor(SVN::Pool & pPool, SVNRa & pParentRaSession, + jobject *jthis_out, jobject jrevprops, jobject jcommitCallback, + jobject jlockTockens, jboolean keepLocks) : + SVNBase(pPool), m_parentRaSession(pParentRaSession), m_rootDirectory(NULL) +{ + *jthis_out = NULL; + + JNIEnv *env = JNIUtil::getEnv(); + + // Create java session object + jclass clazz = env->FindClass(JAVA_CLASS_SVN_EDITOR); + if (JNIUtil::isJavaExceptionThrown()) + return; + + static jmethodID ctor = 0; + if (ctor == 0) + { + ctor = env->GetMethodID(clazz, "", "(J)V"); + if (JNIUtil::isJavaExceptionThrown()) + return; + } + + jlong cppAddr = this->getCppAddr(); + + jobject jSVNEditor = env->NewObject(clazz, ctor, cppAddr); + if (JNIUtil::isJavaExceptionThrown()) + return; + + *jthis_out = jSVNEditor; + + if (jrevprops == NULL) + { + JNIUtil::throwError(_("revprops cannot be null")); + } + + RevpropTable revprops(jrevprops); + if (JNIUtil::isExceptionThrown()) + return; + + if (jcommitCallback == NULL) + { + m_commitCallback = NULL; + } + else + { + m_commitCallback = new CommitCallback(jcommitCallback, true); + if (JNIUtil::isExceptionThrown()) + return; + } + + SVN::Pool subPool(pool); + + apr_hash_t * aprLockTokens = NULL; + + if (jlockTockens != NULL) + { + StringsTable lockTockens(jlockTockens); + if (JNIUtil::isExceptionThrown()) + return; + aprLockTokens = lockTockens.hash(subPool.getPool()); + } + + SVN_JNI_ERR( + svn_ra_get_commit_editor3(pParentRaSession.getRaSession(), &m_deltaEditor, + &m_editBaton, revprops.hash(subPool.getPool(), false), + m_commitCallback ? CommitCallback::callback : NULL, m_commitCallback, + aprLockTokens, keepLocks == JNI_TRUE ? true : false, pool.getPool() ), + ); + +} + +SVNEditor::~SVNEditor() +{ + dispose(); +} + +void +SVNEditor::abortEdit(jobject jthis) +{ + ASSERT_NOT_DISPOSED(); + + svn_error_t * result = NULL; + + // need to make sure sub pool gets destroyed before we dispose the parent pool + { + SVN::Pool subPool(pool); + + result = m_deltaEditor->abort_edit(m_editBaton, subPool.getPool()); + } + + dispose(jthis); + + SVN_JNI_ERR(result, ); +} + +void +SVNEditor::closeEdit(jobject jthis) +{ + ASSERT_NOT_DISPOSED(); + + svn_error_t * result = NULL; + + // need to make sure sub pool gets destroyed before we dispose the parent pool + { + SVN::Pool subPool(pool); + + result = m_deltaEditor->close_edit(m_editBaton, subPool.getPool()); + } + + dispose(jthis); + + SVN_JNI_ERR(result, ); +} + +void +SVNEditor::deleteChildDirectory() +{ + if (m_rootDirectory != NULL) + { + delete m_rootDirectory; + m_rootDirectory = NULL; + } +} + +void +SVNEditor::deleteFile(SVNFile * svnFile) +{ + size_t itemsErased = m_svnFiles.erase(svnFile); + delete svnFile; +} + +const svn_delta_editor_t * +SVNEditor::getEditor() +{ + return m_deltaEditor; +} + +SVN::Pool & +SVNEditor::getEditorPool() +{ + return pool; +} + +jobject +SVNEditor::openRoot(jlong baseRevision) +{ + ASSERT_NOT_DISPOSED(NULL); + + void * pRootBaton = NULL; + + SVN_JNI_ERR( + m_deltaEditor->open_root(m_editBaton, baseRevision, pool.getPool(), &pRootBaton), + NULL); + + jobject jSVNDirectory = NULL; + + m_rootDirectory = new SVNDirectory(pool, *this, *this, &jSVNDirectory, + pRootBaton); + + return jSVNDirectory; +} + +void +SVNEditor::registerFile(SVNFile * svnFile) +{ + m_svnFiles.insert(svnFile); +} + +void +SVNEditor::dispose(jobject jthis) +{ + /* + * We are being deleted so lets clean up our cppAddr link + */ + static jfieldID fid = 0; + SVNBase::disconnectCppObject(jthis, &fid, JAVA_CLASS_SVN_EDITOR); + + m_parentRaSession.deleteEditor(this); +} + +void +SVNEditor::dispose() +{ + if (m_rootDirectory != NULL) + { + m_rootDirectory->dispose(); + m_rootDirectory = NULL; + } + m_deltaEditor = NULL; + m_editBaton = NULL; + + delete m_commitCallback; + + m_commitCallback = NULL; + + std::set::iterator it; + + for (it = m_svnFiles.begin(); it != m_svnFiles.end(); it++) + { + SVNFile * file = *it; + // We do not have handle to files jobject so we cannot delete it but only partially dispose + file->dispose(); + } + + markDisposed(); +} Index: subversion/bindings/javahl/native/SVNDirectory.cpp =================================================================== --- subversion/bindings/javahl/native/SVNDirectory.cpp (revision 0) +++ subversion/bindings/javahl/native/SVNDirectory.cpp (working copy) @@ -0,0 +1,250 @@ +#include "JNIStringHolder.h" +#include "JNIByteArray.h" +#include "JNIUtil.h" + +#include "SVNDirectory.h" +#include "SVNFile.h" + +#include "svn_private_config.h" + +#define JAVA_CLASS_SVN_DIRECTORY JAVA_PACKAGE "/ra/SVNDirectory" +#define EXISTING_CHILD_ERROR _("Directory already has a child directory open, please close it first") + +SVNDirectory * +SVNDirectory::getCppObject(jobject jthis) +{ + static jfieldID fid = 0; + jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid, + JAVA_CLASS_SVN_DIRECTORY); + return (cppAddr == 0 ? NULL : reinterpret_cast(cppAddr)); +} + +SVNDirectory::SVNDirectory(SVN::Pool & pPool, SVNEditor & pParentEditor, + IDirectoryParent & pParent, jobject *jself, void * pDirBaton) : + SVNBase(pPool), m_parentEditor(pParentEditor), m_dirBaton(pDirBaton), + m_childDirectory(NULL), m_parent(pParent) +{ + *jself = createCppBoundObject(JAVA_CLASS_SVN_DIRECTORY); +} + +SVNDirectory::~SVNDirectory() +{ + dispose(); +} + +jobject +SVNDirectory::addDirectory(jstring jpath, jstring jcopyFromPath, + jlong copyFromRevision) +{ + ASSERT_NOT_DISPOSED(NULL); + + if (m_childDirectory != NULL) + { + JNIUtil::throwError(EXISTING_CHILD_ERROR); + return NULL; + } + + SVN_JNI_NULL_PTR_EX(jpath, _("path cannot be null"), NULL); + + SVN_JNI_STRING(path, jpath, NULL); + SVN_JNI_STRING(copyFromPath, jcopyFromPath, NULL); + + void * directoryBaton = NULL; + + SVN_JNI_ERR( + m_parentEditor.getEditor()->add_directory(path, m_dirBaton, copyFromPath, + copyFromRevision, pool.getPool(), &directoryBaton), + NULL); + + jobject jSVNDirectory = NULL; + + m_childDirectory = new SVNDirectory(pool, m_parentEditor, *this, + &jSVNDirectory, directoryBaton); + + return jSVNDirectory; +} + +jobject +SVNDirectory::addFile(jstring jpath, jstring jcopyFromPath, + jlong copyFromRevision) +{ + ASSERT_NOT_DISPOSED(NULL); + + SVN_JNI_NULL_PTR_EX(jpath, _("path cannot be null"), NULL); + SVN_JNI_STRING(path, jpath, NULL); + + SVN_JNI_STRING(copyFromPath, jcopyFromPath, NULL); + + void * fileBaton = NULL; + + /* + * Because file's life cycle is tied to the editor we need to make sure to use + * editors pool + */ + SVN::Pool & editorPool = m_parentEditor.getEditorPool(); + + SVN_JNI_ERR( + m_parentEditor.getEditor()->add_file(path, m_dirBaton, copyFromPath, + copyFromRevision, editorPool.getPool(), &fileBaton), + NULL); + + jobject jSVNFile = NULL; + + SVNFile * file = new SVNFile(editorPool, m_parentEditor, &jSVNFile, + fileBaton); + + return jSVNFile; +} + +void +SVNDirectory::changeProperty(jstring jpropertyName, jbyteArray jpropertyValue) +{ + ASSERT_NOT_DISPOSED(); + + SVN_JNI_NULL_PTR_EX(jpropertyName, _("propertyName cannot be null"), ); + + SVN_JNI_STRING(propertyName, jpropertyName, ); + SVN_JNI_BYTE_ARRAY(propertyValue, jpropertyValue, ); + + SVN::Pool subPool(pool); + + SVN_JNI_ERR( + m_parentEditor.getEditor()->change_dir_prop(m_dirBaton, propertyName, + propertyValue.getSvnString(subPool.getPool()), subPool.getPool()), + ); +} + +void +SVNDirectory::close(jobject jthis) +{ + ASSERT_NOT_DISPOSED(); + + svn_error_t * result = NULL; + + { + SVN::Pool subPool(pool); + + result = m_parentEditor.getEditor()->close_directory(m_dirBaton, + subPool.getPool()); + } + + /* + * Since directory cannot be reused once closed, might as well dispose of it ourselves + */ + dispose(jthis); + + SVN_JNI_ERR(result, ); +} + +void +SVNDirectory::deleteEntry(jstring jpath, jlong baseRevision) +{ + ASSERT_NOT_DISPOSED(); + + SVN_JNI_NULL_PTR_EX(jpath, _("path cannot be null"), ); + + SVN_JNI_STRING(path, jpath, ); + + void * directoryBaton = NULL; + + SVN::Pool subPool(pool); + + SVN_JNI_ERR( + m_parentEditor.getEditor() ->delete_entry(path, baseRevision, m_dirBaton, + subPool.getPool()), + ); +} + +jobject +SVNDirectory::openDirectory(jstring jpath, jlong baseRevision) +{ + ASSERT_NOT_DISPOSED(NULL); + + if (m_childDirectory != NULL) + { + JNIUtil::throwError(EXISTING_CHILD_ERROR); + return NULL; + } + + SVN_JNI_NULL_PTR_EX(jpath, _("path cannot be null"), NULL); + SVN_JNI_STRING(path, jpath, NULL); + + void * directoryBaton = NULL; + + SVN_JNI_ERR( + m_parentEditor.getEditor() ->open_directory(path, m_dirBaton, baseRevision, pool.getPool(), &directoryBaton), + NULL); + + jobject jSVNDirectory = NULL; + + m_childDirectory = new SVNDirectory(pool, m_parentEditor, *this, + &jSVNDirectory, directoryBaton); + + return jSVNDirectory; +} + +void +SVNDirectory::deleteChildDirectory() +{ + ASSERT_NOT_DISPOSED(); + + if (m_childDirectory != NULL) + { + delete m_childDirectory; + m_childDirectory = NULL; + } +} + +jobject +SVNDirectory::openFile(jstring jpath, jlong baseRevision) +{ + ASSERT_NOT_DISPOSED(NULL); + + SVN_JNI_NULL_PTR_EX(jpath, _("path cannot be null"), NULL); + SVN_JNI_STRING(path, jpath, NULL); + + void * fileBaton = NULL; + + /* + * Because file's life cycle is tied to the editor we need to make sure to use + * editors pool + */ + SVN::Pool & editorPool = m_parentEditor.getEditorPool(); + + SVN_JNI_ERR( + m_parentEditor.getEditor()->open_file(path, m_dirBaton, baseRevision, editorPool.getPool(), &fileBaton), + NULL); + + jobject jSVNFile = NULL; + + SVNFile * file = new SVNFile(editorPool, m_parentEditor, &jSVNFile, + fileBaton); + + return jSVNFile; +} + +void +SVNDirectory::dispose() +{ + m_dirBaton = NULL; + + if (m_childDirectory != NULL) + { + m_childDirectory->dispose(); + m_childDirectory = NULL; + } + markDisposed(); +} + +void +SVNDirectory::dispose(jobject jthis) +{ + /* + * We are being deleted so lets clean up our cppAddr link + */ + static jfieldID fid = 0; + SVNBase::disconnectCppObject(jthis, &fid, JAVA_CLASS_SVN_DIRECTORY); + + m_parent.deleteChildDirectory(); +} +