You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/07/26 03:41:12 UTC

svn commit: r1507177 - in /subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl: ./ native/ src/org/apache/subversion/javahl/ src/org/apache/subversion/javahl/remote/ tests/org/apache/subversion/javahl/

Author: brane
Date: Fri Jul 26 01:41:11 2013
New Revision: 1507177

URL: http://svn.apache.org/r1507177
Log:
On the javahl-1.7-extensions branch: Sync JavaHL with trunk up to r1507175.

Modified:
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/   (props changed)
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
    subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java

Propchange: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/
------------------------------------------------------------------------------
  Merged /subversion/trunk/subversion/bindings/javahl:r1502118-1507175

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp?rev=1507177&r1=1507176&r2=1507177&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.cpp Fri Jul 26 01:41:11 2013
@@ -122,7 +122,7 @@ RemoteSession::open(jint jretryAttempts,
                     const char* url, const char* uuid,
                     const char* configDirectory, jobject jconfigHandler,
                     const char*  usernameStr, const char*  passwordStr,
-                    Prompter* prompter, jobject jprogress)
+                    Prompter*& prompter, jobject jprogress)
 {
   /*
    * Initialize ra layer if we have not done so yet
@@ -165,7 +165,7 @@ RemoteSession::RemoteSession(jobject* jt
                              const char* configDirectory,
                              jobject jconfigHandler,
                              const char*  username, const char*  password,
-                             Prompter* prompter, jobject jprogress)
+                             Prompter*& prompter, jobject jprogress)
   : m_session(NULL), m_context(NULL)
 {
   // Create java session object
@@ -195,6 +195,14 @@ RemoteSession::RemoteSession(jobject* jt
   if (JNIUtil::isJavaExceptionThrown())
     return;
 
+  // Avoid double-free in RemoteSession::open and
+  // SVNClient::openRemoteSession if the svn_ra_open call fails. The
+  // prompter object is now owned by m_context.
+  //
+  // FIXME: Should be using smart pointers, really -- but JavaHL
+  // currently doesn't. Future enhancements FTW.
+  prompter = NULL;
+
   const char* corrected_url = NULL;
   bool cycle_detected = false;
   attempt_set attempted;
@@ -813,7 +821,138 @@ RemoteSession::checkPath(jstring jpath, 
 }
 
 // TODO: stat
-// TODO: getLocations
+
+namespace {
+apr_array_header_t*
+long_iterable_to_revnum_array(jobject jlong_iterable, apr_pool_t* pool)
+{
+
+  JNIEnv* env = JNIUtil::getEnv();
+
+  jclass cls = env->FindClass("java/lang/Long");
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  static jmethodID mid = 0;
+  if (0 == mid)
+    {
+      mid = env->GetMethodID(cls, "longValue", "()J");
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+    }
+
+  apr_array_header_t* array = apr_array_make(pool, 0, sizeof(svn_revnum_t));
+  Iterator iter(jlong_iterable);
+  while (iter.hasNext())
+    {
+      const jlong entry = env->CallLongMethod(iter.next(), mid);
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+      APR_ARRAY_PUSH(array, svn_revnum_t) = svn_revnum_t(entry);
+    }
+  return array;
+}
+
+jobject
+location_hash_to_map(apr_hash_t* locations, apr_pool_t* scratch_pool)
+{
+  JNIEnv* env = JNIUtil::getEnv();
+
+  jclass long_cls = env->FindClass("java/lang/Long");
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  static jmethodID long_ctor = 0;
+  if (0 == long_ctor)
+    {
+      long_ctor = env->GetMethodID(long_cls, "<init>", "(J)V");
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+    }
+
+  jclass hash_cls = env->FindClass("java/util/HashMap");
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  static jmethodID hash_ctor = 0;
+  if (0 == hash_ctor)
+    {
+      hash_ctor = env->GetMethodID(hash_cls, "<init>", "()V");
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+    }
+
+  static jmethodID hash_put = 0;
+  if (0 == hash_put)
+    {
+      hash_put = env->GetMethodID(hash_cls, "put",
+                                  "(Ljava/lang/Object;Ljava/lang/Object;"
+                                  ")Ljava/lang/Object;");
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+    }
+
+  jobject result = env->NewObject(hash_cls, hash_ctor);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+
+  if (!locations)
+    return result;
+
+  for (apr_hash_index_t* hi = apr_hash_first(scratch_pool, locations);
+       hi; hi = apr_hash_next(hi))
+    {
+      const void* key;
+      void* val;
+
+      apr_hash_this(hi, &key, NULL, &val);
+
+      jobject jkey = env->NewObject(
+          long_cls, long_ctor, jlong(*static_cast<const svn_revnum_t*>(key)));
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+      jstring jval = JNIUtil::makeJString(static_cast<const char*>(val));
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+
+      env->CallObjectMethod(result, hash_put, jkey, jval);
+      if (JNIUtil::isExceptionThrown())
+        return NULL;
+
+      env->DeleteLocalRef(jkey);
+      env->DeleteLocalRef(jval);
+    }
+
+  return result;
+}
+} // anonymous namespace
+
+jobject
+RemoteSession::getLocations(jstring jpath, jlong jpeg_revision,
+                            jobject jlocation_revisions)
+{
+  if (!jpath || !jlocation_revisions)
+    return NULL;
+
+  SVN::Pool subPool(pool);
+  Relpath path(jpath, subPool);
+  if (JNIUtil::isExceptionThrown())
+    return NULL;
+  SVN_JNI_ERR(path.error_occurred(), NULL);
+
+  apr_array_header_t* location_revisions =
+    long_iterable_to_revnum_array(jlocation_revisions, subPool.getPool());
+  if (!location_revisions)
+    return NULL;
+
+  apr_hash_t* locations;
+  SVN_JNI_ERR(svn_ra_get_locations(m_session, &locations,
+                                   path.c_str(), svn_revnum_t(jpeg_revision),
+                                   location_revisions, subPool.getPool()),
+              NULL);
+  return location_hash_to_map(locations, subPool.getPool());
+}
+
 // TODO: getLocationSegments
 // TODO: getFileRevisions
 // TODO: lock

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h?rev=1507177&r1=1507176&r2=1507177&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/RemoteSession.h Fri Jul 26 01:41:11 2013
@@ -55,7 +55,7 @@ class RemoteSession : public SVNBase
                         const char* configDirectory,
                         jobject jconfigHandler,
                         const char* username, const char* password,
-                        Prompter* prompter, jobject jprogress);
+                        Prompter*& prompter, jobject jprogress);
     ~RemoteSession();
 
     void cancelOperation() const { m_context->cancelOperation(); }
@@ -93,7 +93,8 @@ class RemoteSession : public SVNBase
                 jobject jrevprops, jobject jlog_callback);
     jobject checkPath(jstring jpath, jlong jrevision);
     // TODO: stat
-    // TODO: getLocations
+    jobject getLocations(jstring jpath, jlong jpeg_revision,
+                         jobject jlocation_revisions);
     // TODO: getLocationSegments
     // TODO: getFileRevisions
     // TODO: lock
@@ -113,7 +114,7 @@ class RemoteSession : public SVNBase
                   const char* configDirectory,
                   jobject jconfigHandler,
                   const char* username, const char* password,
-                  Prompter* prompter, jobject jprogress);
+                  Prompter*& prompter, jobject jprogress);
 
     svn_ra_session_t* m_session;
     RemoteSessionContext* m_context;

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp?rev=1507177&r1=1507176&r2=1507177&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp Fri Jul 26 01:41:11 2013
@@ -273,7 +273,19 @@ Java_org_apache_subversion_javahl_remote
 }
 
 // TODO: stat
-// TODO: getLocations
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getLocations(
+    JNIEnv *env, jobject jthis, jstring jpath, jlong jpeg_revision,
+    jobject jlocation_revisions)
+{
+  JNIEntry(SVNReposAccess, checkPath);
+  RemoteSession *ras = RemoteSession::getCppObject(jthis);
+  CPPADDR_NULL_PTR(ras, NULL);
+
+  return ras->getLocations(jpath, jpeg_revision, jlocation_revisions);
+}
+
 // TODO: getLocationSegments
 // TODO: getFileRevisions
 // TODO: lock

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java?rev=1507177&r1=1507176&r2=1507177&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java Fri Jul 26 01:41:11 2013
@@ -441,7 +441,23 @@ public interface ISVNRemote
             throws ClientException;
 
     // TODO: stat
-    // TODO: getLocations
+
+    /**
+     * Find the locations of the object identified by
+     * <code>path</code> and <code>pegRevision</code> in the
+     * repository at the given revisions. If the object does not exist
+     * in a given revision, that revision will be ignored.
+     * <p>
+     * <b>Note:</b> None of the parameters may be NULL.
+     * @param path A path relative to the session URL
+     * @param pegRevision The peg revision to use for locating the object
+     * @param locationRevisions The set of revisions to find locations for
+     * @throws ClientException
+     */
+    Map<Long, String> getLocations(String path, long pegRevision,
+                                   Iterable<Long> locationRevisions)
+            throws ClientException;
+
     // TODO: getLocationSegments
     // TODO: getFileRevisions
     // TODO: lock

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java?rev=1507177&r1=1507176&r2=1507177&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java Fri Jul 26 01:41:11 2013
@@ -198,7 +198,12 @@ public class RemoteSession extends JNIOb
             throws ClientException;
 
     // TODO: stat
-    // TODO: getLocations
+
+    public native Map<Long, String>
+        getLocations(String path, long pegRevision,
+                     Iterable<Long> locationRevisions)
+            throws ClientException;
+
     // TODO: getLocationSegments
     // TODO: getFileRevisions
     // TODO: lock

Modified: subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1507177&r1=1507176&r2=1507177&view=diff
==============================================================================
--- subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/branches/javahl-1.7-extensions/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Fri Jul 26 01:41:11 2013
@@ -579,4 +579,20 @@ public class SVNRemoteTests extends SVNT
         assertEquals(1, ranges.size());
         assertEquals("1-3", ranges.get(0).toString());
     }
+
+    public void testGetLocations() throws Exception
+    {
+        ISVNRemote session = getSession();
+
+        Long expected = new Long(1L);
+        ArrayList<Long> revs = new ArrayList<Long>(3);
+        revs.add(new Long(0L));
+        revs.add(expected);
+
+        Map<Long, String> locs = session.getLocations("A", 1, revs);
+
+        assertEquals(1, locs.size());
+        assertTrue(locs.containsKey(expected));
+        assertEquals("/A", locs.get(expected));
+    }
 }