subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1539130 - in /subversion/trunk/subversion/bindings/javahl: native/ src/org/apache/subversion/javahl/ src/org/apache/subversion/javahl/types/ src/org/apache/subversion/javahl/util/ tests/org/apache/subversion/javahl/
Date Tue, 05 Nov 2013 21:05:37 GMT
Author: brane
Date: Tue Nov  5 21:05:37 2013
New Revision: 1539130

URL: http://svn.apache.org/r1539130
Log:
Add a utility API to parse and unparse svn:externals definitions to JavaHL.

[in subversion/bindings/javahl/src/org/apache/subversion/javahl]
* SVNUtil.java (SVNUtil.parseExternals): New static method.
  (SVNUtil.unparseExternals): Likewise.
  (SVNUtil.unparseExternalsForAncientUnsupportedClients): Likewise.
* types/ExternalItem.java (ExternalItem): New class.
* types/Revision.java (Revision.DateSpec.DateSpec): New private constructor.
   Creates a dated revision from a timestamp in milliseconds.
 * util/PropLib.java
   (PropLib.parseExternals, PropLib.unparseExternals): Declare native methods.

[in subversion/bindings/javahl/native]
* Revision.h (Revision::makeJRevision): New overload.
* ExternalItem.hpp, ExternalItem.cpp: New-style object wrappers for
   types.ExternalItem.
* ExternalItem.cpp (Revision::makeJRevision): New-style implementation
   of the new overload. Located here until the old-style Revision
   implementation can be ported to jniwrapper.

* org_apache_subversion_javahl_util_PropLib.cpp: Include the required
   new-style headers for the new method implementations.
  (FormatRevision): Helper object for formating revisions to std::ostream.
  (operator<<): Stream insertion operator for FormatRevision.
  (Java_org_apache_subversion_javahl_util_PropLib_parseExternals):
   Boilerplate native implementation of PropLib.parseExternals.
  (Java_org_apache_subversion_javahl_util_PropLib_unparseExternals):
   Native implementation of PropLib.unparseExternals.

[in subversion/bindings/javahl/tests/org/apache/subversion/javahl]
* UtilTests.java
  (UtilTests.externals, UtilTests.old_externals): New private members.
  (UtilTests.testUnparseExternals,
  (UtilTests.testUnparseExternalsOldstyle): New test cases.

Added:
    subversion/trunk/subversion/bindings/javahl/native/ExternalItem.cpp   (with props)
    subversion/trunk/subversion/bindings/javahl/native/ExternalItem.hpp   (with props)
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
  (with props)
Modified:
    subversion/trunk/subversion/bindings/javahl/native/Revision.h
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java
    subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java

Added: subversion/trunk/subversion/bindings/javahl/native/ExternalItem.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/ExternalItem.cpp?rev=1539130&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/ExternalItem.cpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/ExternalItem.cpp Tue Nov  5 21:05:37
2013
@@ -0,0 +1,146 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#include "ExternalItem.hpp"
+#include "JNIUtil.h"
+#include "Revision.h"
+
+namespace JavaHL {
+
+const char* const ExternalItem::m_class_name =
+  JAVA_PACKAGE"/types/ExternalItem";
+
+namespace {
+jstring get_string_field(::Java::Env env, jclass cls, jobject jthis,
+                         const char* field_name)
+{
+  return jstring(
+      env.GetObjectField(
+          jthis, env.GetFieldID(cls, field_name, "Ljava/lang/String;")));
+}
+
+svn_opt_revision_t get_revision_field(::Java::Env env,
+                                      jclass cls, jobject jthis,
+                                      const char* field_name)
+{
+  const jobject rev =  env.GetObjectField(
+      jthis, env.GetFieldID(cls, field_name,
+                            "L"JAVA_PACKAGE"/types/Revision;"));
+  return *Revision(rev).revision();
+}
+
+jobject make_external_item(::Java::Env env,
+                           const char* class_name,
+                           const char* target_dir,
+                           const char* url,
+                           const svn_opt_revision_t* revision,
+                           const svn_opt_revision_t* peg_revision)
+{
+  const jclass cls = env.FindClass(class_name);
+  const jmethodID mid_ctor =
+    env.GetMethodID(cls, "<init>",
+                    "(ZLjava/lang/String;Ljava/lang/String;"
+                    "L"JAVA_PACKAGE"/types/Revision;"
+                    "L"JAVA_PACKAGE"/types/Revision;)V");
+  return env.NewObject(cls, mid_ctor,
+                       env.NewStringUTF(target_dir),
+                       env.NewStringUTF(url),
+                       Revision::makeJRevision(*revision),
+                       Revision::makeJRevision(*peg_revision));
+}
+} // anonymous namespace
+
+ExternalItem::ExternalItem(::Java::Env env, jobject jthis)
+  : Object(env, m_class_name, jthis),
+    m_target_dir(env, get_string_field(env, m_class, jthis, "targetDir")),
+    m_url(env, get_string_field(env, m_class, jthis, "url")),
+    m_revision(get_revision_field(env, m_class, jthis, "revision")),
+    m_peg_revision(get_revision_field(env, m_class, jthis, "pegRevision"))
+{}
+
+ExternalItem::ExternalItem(::Java::Env env,
+                           const char* target_dir,
+                           const char* url,
+                           const svn_opt_revision_t* revision,
+                           const svn_opt_revision_t* peg_revision)
+  : Object(env, m_class_name,
+           make_external_item(env, m_class_name, target_dir, url,
+                              revision, peg_revision)),
+    m_target_dir(env, target_dir),
+    m_url(env, url),
+    m_revision(*revision),
+    m_peg_revision(*peg_revision)
+{}
+
+} // namespace JavaHL
+
+
+// FIXME: Should be in another source file, but Revision.cpp is
+// old-style, so we'll put this implementation here for now.
+namespace {
+inline jobject get_static_revision(::Java::Env env, jclass cls,
+                                   const char* field_name)
+{
+  return env.GetStaticObjectField(
+      cls, env.GetStaticFieldID(cls, field_name,
+                                "L"JAVA_PACKAGE"/types/Revision;"));
+}
+} // anonymous namespace
+
+jobject Revision::makeJRevision(const svn_opt_revision_t& rev)
+{
+  if (rev.kind == svn_opt_revision_number)
+      return Revision::makeJRevision(rev.value.number);
+
+  const ::Java::Env env;
+
+  if (rev.kind == svn_opt_revision_date)
+    {
+      const jclass cls = env.FindClass(
+          JAVA_PACKAGE"/types/Revision$DateSpec");
+      return env.NewObject(cls, env.GetMethodID(cls, "<init>", "(J)V"));
+    }
+
+  const jclass cls = env.FindClass(JAVA_PACKAGE"/types/Revision");
+  switch (rev.kind)
+    {
+    case svn_opt_revision_committed:
+      return get_static_revision(env, cls, "COMMITTED");
+
+    case svn_opt_revision_previous:
+      return get_static_revision(env, cls, "PREVIOUS");
+
+    case svn_opt_revision_base:
+      return get_static_revision(env, cls, "BASE");
+
+    case svn_opt_revision_working:
+      return get_static_revision(env, cls, "WORKING");
+
+    case svn_opt_revision_head:
+      return get_static_revision(env, cls, "HEAD");
+
+    case svn_opt_revision_unspecified:
+    default:
+      return get_static_revision(env, cls, "UNSPECIFIED");
+    }
+}

Propchange: subversion/trunk/subversion/bindings/javahl/native/ExternalItem.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: subversion/trunk/subversion/bindings/javahl/native/ExternalItem.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/ExternalItem.hpp?rev=1539130&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/ExternalItem.hpp (added)
+++ subversion/trunk/subversion/bindings/javahl/native/ExternalItem.hpp Tue Nov  5 21:05:37
2013
@@ -0,0 +1,103 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#ifndef SVN_JAVAHL_EXTERNAL_ITEM_HPP
+#define SVN_JAVAHL_EXTERNAL_ITEM_HPP
+
+#include <string>
+
+#include "svn_opt.h"
+
+#include "jniwrapper/jni_object.hpp"
+
+namespace JavaHL {
+
+/**
+ * Object wrapper for @c org.apache.subversion.javahl.types.ExternalItem.
+ *
+ * @since New in 1.9.
+ */
+class ExternalItem : public ::Java::Object
+{
+public:
+  /**
+   * Constructs a wrapper around @a jthis.
+   * The constructor does not verify the class of the wrapped object.
+   */
+  explicit ExternalItem(::Java::Env env, jobject jthis);
+
+  /**
+   * Constructs a new @c ExternalItem object and wrapper.
+   */
+  explicit ExternalItem(::Java::Env env,
+                        const char* target_dir,
+                        const char* url,
+                        const svn_opt_revision_t* revision,
+                        const svn_opt_revision_t* peg_revision);
+
+  /**
+   * Returns the value of the wrapped object's @c targetDir member.
+   */
+  std::string target_dir() const
+    {
+      const ::Java::String::Contents contents(m_target_dir);
+      return std::string(contents.c_str());
+    }
+
+  /**
+   * Returns the value of the wrapped object's @c url member.
+   */
+  std::string url() const
+    {
+      const ::Java::String::Contents contents(m_url);
+      return std::string(contents.c_str());
+    }
+
+  /**
+   * Returns the value of the wrapped object's @c revision member.
+   */
+  const svn_opt_revision_t* revision() const
+    {
+      return &m_revision;
+    }
+
+  /**
+   * Returns the value of the wrapped object's @c pegRevision member.
+   */
+  const svn_opt_revision_t* peg_revision() const
+    {
+      return &m_peg_revision;
+    }
+
+private:
+  static const char* const m_class_name;
+
+  ::Java::String m_target_dir;
+  ::Java::String m_url;
+  svn_opt_revision_t m_revision;
+  svn_opt_revision_t m_peg_revision;
+};
+
+} // namespace JavaHL
+
+#endif // SVN_JAVAHL_EXTERNAL_ITEM_HPP

Propchange: subversion/trunk/subversion/bindings/javahl/native/ExternalItem.hpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/bindings/javahl/native/Revision.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/Revision.h?rev=1539130&r1=1539129&r2=1539130&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/Revision.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/Revision.h Tue Nov  5 21:05:37 2013
@@ -50,6 +50,7 @@ class Revision
    * Make a Revision Java object.
    */
   static jobject makeJRevision(svn_revnum_t rev);
+  static jobject makeJRevision(const svn_opt_revision_t& rev);
 };
 
 #endif // REVISION_H

Modified: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp?rev=1539130&r1=1539129&r2=1539130&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp
(original)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_PropLib.cpp
Tue Nov  5 21:05:37 2013
@@ -24,6 +24,9 @@
  * @brief Implementation of the native methods in the Java class PropLib
  */
 
+#include <iostream>
+#include <sstream>
+
 #include "../include/org_apache_subversion_javahl_util_PropLib.h"
 
 #include "JNIStackElement.h"
@@ -36,8 +39,11 @@
 #include "Pool.h"
 
 #include "svn_props.h"
+#include "svn_time.h"
 #include "svn_wc.h"
 
+#include "svn_private_config.h"
+
 
 namespace {
 class PropGetter
@@ -132,3 +138,149 @@ Java_org_apache_subversion_javahl_util_P
 
   return JNIUtil::makeJByteArray(canonval->data, int(canonval->len));
 }
+
+
+#include "jniwrapper/jni_stack.hpp"
+#include "jniwrapper/jni_array.hpp"
+#include "jniwrapper/jni_list.hpp"
+#include "ExternalItem.hpp"
+#include "SubversionException.hpp"
+
+
+namespace {
+struct FormatRevision
+{
+  explicit FormatRevision(const svn_opt_revision_t* const& revarg,
+                          const SVN::Pool& poolarg)
+    : rev(revarg), pool(poolarg)
+    {}
+
+  const svn_opt_revision_t* const& rev;
+  const SVN::Pool& pool;
+};
+
+std::ostream& operator<<(std::ostream& os, const FormatRevision& pr)
+{
+  switch (pr.rev->kind)
+    {
+    case svn_opt_revision_number:
+      os << pr.rev->value.number;
+      break;
+    case svn_opt_revision_date:
+      os << '{'
+         << svn_time_to_cstring(pr.rev->value.date, pr.pool.getPool())
+         << '}';
+      break;
+    default:
+      throw std::logic_error(
+          _("Invalid revision tag; must be a number or a date"));
+    }
+  return os;
+}
+} // anoymous namespace
+
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_util_PropLib_parseExternals(
+    JNIEnv* jenv, jobject jthis,
+    jbyteArray jdescription, jstring jparent_dir, jboolean jcanonicalize_url)
+{
+  SVN_JAVAHL_JNI_TRY(PropLib, parseExternals)
+    {
+      const Java::Env env(jenv);
+
+      const Java::ByteArray description(env, jdescription);
+      const Java::String paren_dir(env, jparent_dir);
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return NULL;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_org_apache_subversion_javahl_util_PropLib_unparseExternals(
+    JNIEnv* jenv, jobject jthis,
+    jobject jitems, jstring jparent_dir, jboolean jold_format)
+{
+  SVN_JAVAHL_JNI_TRY(PropLib, unparseExternals)
+    {
+      const Java::Env env(jenv);
+
+      const Java::List<JavaHL::ExternalItem> items(env, jitems);
+      const Java::String parent_dir(env, jparent_dir);
+
+      // Using a "global" iteration pool since we don't keep a context
+      // with its own pool around for these functions.
+      SVN::Pool iterpool;
+
+      std::ostringstream buffer;
+      for (jint i = 0; i < items.length(); ++i)
+        {
+          iterpool.clear();
+
+          const Java::LocalFrame frame(env);
+          const JavaHL::ExternalItem item(items[i]);
+
+          if (!jold_format)
+            {
+              if (item.revision()->kind != svn_opt_revision_head)
+                {
+                  buffer << "-r"
+                         << FormatRevision(item.revision(), iterpool)
+                         << ' ';
+                }
+              if (item.peg_revision()->kind == svn_opt_revision_head)
+                buffer << item.url() << ' ';
+              else
+                {
+                  buffer << item.url() << '@'
+                         << FormatRevision(item.peg_revision(), iterpool)
+                         << ' ';
+                }
+              buffer << item.target_dir() << '\n';
+            }
+          else
+            {
+              // Sanity check: old format does not support peg revisions
+              if (item.peg_revision()->kind != svn_opt_revision_head)
+                {
+                  JavaHL::SubversionException(env)
+                    .raise(_("Clients older than Subversion 1.5"
+                             " do not support peg revision syntax"
+                             " in the svn:externals property"));
+                }
+
+              // Sanity check: old format does not support relative URLs
+              const std::string url = item.url();
+              if (   (url.size() >= 1 && (url[0] == '.' || url[0] == '/'))
+                  || (url.size() >= 2 && (url[0] == '^' && url[1] == '/')))
+                {
+                  JavaHL::SubversionException(env)
+                    .raise(_("Clients older than Subversion 1.5"
+                             " do not support relative URLs"
+                             " in the svn:externals property"));
+                }
+
+              buffer << item.target_dir() << ' ';
+              if (item.revision()->kind != svn_opt_revision_head)
+                {
+                  buffer << "-r"
+                         << FormatRevision(item.revision(), iterpool)
+                         << ' ';
+                }
+              buffer << url << '\n';
+            }
+        }
+
+      // Validate the result. Even though we generated the string
+      // ourselves, we did not validate the input paths and URLs.
+      const std::string description(buffer.str());
+      SVN_JAVAHL_CHECK(svn_wc_parse_externals_description3(
+                           NULL,
+                           Java::String::Contents(parent_dir).c_str(),
+                           description.c_str(),
+                           false, iterpool.getPool()));
+      return Java::ByteArray(env, description).get();
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return NULL;
+}

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java?rev=1539130&r1=1539129&r2=1539130&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
(original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
Tue Nov  5 21:05:37 2013
@@ -29,6 +29,7 @@ import org.apache.subversion.javahl.util
 
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.List;
 
 public class SVNUtil
 {
@@ -340,4 +341,64 @@ public class SVNUtil
         return new PropLib().canonicalizeNodeProperty(
             name, value, path, kind, mimeType, fileContents);
     }
+
+    /**
+     * Parse <code>description</code>, assuming it is an externals
+     * specification in the format required for the
+     * <code>svn:externals</code> property, and return a list of
+     * parsed external items.
+     * @param description The externals description.
+     * @param parentDirectory Used to construct error messages.
+     * @param canonicalizeUrl Whe <code>true</code>, canonicalize the
+     *     <code>url</code> member of the returned objects. If the
+     *     <code>url</code> member refers to an absolute URL, it will
+     *     be canonicalized as URL consistent with the way URLs are
+     *     canonicalized throughout the Subversion API. If, however,
+     *     the <code>url</code> member makes use of the recognized
+     *     (SVN-specific) relative URL syntax for
+     *     <code>svn:externals</code>, "canonicalization" is an
+     *     ill-defined concept which may even result in munging the
+     *     relative URL syntax beyond recognition. You've been warned.
+     * @return a list of {@link ExternalItem}s
+     */
+    public static List<ExternalItem> parseExternals(byte[] description,
+                                                    String parentDirectory,
+                                                    boolean canonicalizeUrl)
+        throws ClientException
+    {
+        return new PropLib().parseExternals(description, parentDirectory,
+                                            canonicalizeUrl);
+    }
+
+    /**
+     * Unparse and list of external items into a format suitable for
+     * the value of the <code>svn:externals</code> property and
+     * validate the result.
+     * @param items The list of {@link ExternalItem}s
+     * @param parentDirectory Used to construct error messages.
+     * @param compatibleWithSvn1_5 When <code>true</code>, the format
+     *     of the returned property value will be compatible with
+     *     clients older than Subversion 1.5.
+     */
+    public static byte[] unparseExternals(List<ExternalItem> items,
+                                          String parentDirectory)
+        throws SubversionException
+    {
+        return new PropLib().unparseExternals(items, parentDirectory, false);
+    }
+
+    /**
+     * Unparse and list of external items into a format suitable for
+     * the value of the <code>svn:externals</code> property compatible
+     * with Subversion clients older than release 1.5, and validate
+     * the result.
+     * @param items The list of {@link ExternalItem}s
+     * @param parentDirectory Used to construct error messages.
+     */
+    public static byte[] unparseExternalsForAncientUnsupportedClients(
+        List<ExternalItem> items, String parentDirectory)
+        throws SubversionException
+    {
+        return new PropLib().unparseExternals(items, parentDirectory, true);
+    }
 }

Added: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java?rev=1539130&view=auto
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
(added)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
Tue Nov  5 21:05:37 2013
@@ -0,0 +1,132 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.types;
+
+import org.apache.subversion.javahl.SubversionException;
+
+/**
+ * Describes one external item declaration
+ * @since 1.9
+ */
+public class ExternalItem implements java.io.Serializable
+{
+    // Update the serialVersionUID when there is a incompatible change
+    // made to this class.
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Create a new external item declaration.
+     * @param targetDir See {@link #getTargetDir}
+     * @param url See {@link #getUrl}
+     * @param revision See {@link #getRevision};
+     *     <code>null</code> will be interpreted as {@link Revision#HEAD}
+     * @param pegRevision See {@link #getPegRevision};
+     *     <code>null</code> will be interpreted as {@link Revision#HEAD}
+     */
+    public ExternalItem(String targetDir, String url,
+                        Revision revision, Revision pegRevision)
+        throws SubversionException
+    {
+        this(false, targetDir, url, revision, pegRevision);
+        validateRevision(revision, "revision");
+        validateRevision(pegRevision, "pegRevision");
+    }
+
+    /* This constructor is called directly by the native implementation */
+    private ExternalItem(boolean dummy_parameter_to_discriminate_constructors,
+                         String targetDir, String url,
+                         Revision revision, Revision pegRevision)
+    {
+        this.targetDir = targetDir;
+        this.url = url;
+        this.revision = (revision != null ? revision : Revision.HEAD);
+        this.pegRevision = (pegRevision != null ? pegRevision : Revision.HEAD);
+    }
+
+    /**
+     * The name of the subdirectory into which this external should be
+     * checked out.  This is relative to the parent directory that
+     * holds this external item.
+     */
+    public String getTargetDir()
+    {
+        return targetDir;
+    }
+
+    /**
+     * Where to check out from. This is possibly a relative external
+     * URL, as allowed in externals definitions, but without the peg
+     * revision.
+     */
+    public String getUrl()
+    {
+        return url;
+    }
+
+    /**
+     * What revision to check out. The only valid kinds for this are a
+     * numered revision {@link Revision.Number}, a date
+     * {@link Revision.DateSpec}, or {@link Revision#HEAD}.
+     */
+    public Revision getRevision()
+    {
+        return revision;
+    }
+
+    /**
+     * The peg revision to use when checking out. The only valid kinds
+     * for this are a numered revision {@link Revision.Number}, a date
+     * {@link Revision.DateSpec}, or {@link Revision#HEAD}.
+     */
+    public Revision getPegRevision()
+    {
+        return pegRevision;
+    }
+
+    /* Exception class for failed revision kind validation. */
+    private static class BadRevisionKindException extends SubversionException
+    {
+        public BadRevisionKindException(String param)
+        {
+            super("the '" + param + "' constructor argument" +
+                  " must be a date, a number, or Revision.HEAD");
+        }
+    }
+
+    /* Validates the revision and pegRevision parameters of the ctor. */
+    private static void validateRevision(Revision revision, String param)
+        throws SubversionException
+    {
+        if (revision != null
+            && revision.getKind() != Revision.Kind.number
+            && revision.getKind() != Revision.Kind.date
+            && revision.getKind() != Revision.Kind.head)
+            throw new BadRevisionKindException(param);
+    }
+
+    private String targetDir;
+    private String url;
+    private Revision revision;
+    private Revision pegRevision;
+}

Propchange: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java?rev=1539130&r1=1539129&r2=1539130&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java
(original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java
Tue Nov  5 21:05:37 2013
@@ -277,6 +277,16 @@ public class Revision implements java.io
                 throw new IllegalArgumentException("a date must be specified");
             revDate = date;
         }
+
+        /**
+         * Create a revision from a timestamp in milliseconds.
+         * Used by the native implementaiton.
+         */
+        private DateSpec(long milliseconds)
+        {
+            this(new Date(milliseconds));
+        }
+
         /**
          * Returns the date of the revision
          * @return the date
@@ -316,7 +326,6 @@ public class Revision implements java.io
         {
             return revDate.hashCode();
         }
-
     }
 
     /**

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java?rev=1539130&r1=1539129&r2=1539130&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java
(original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java
Tue Nov  5 21:05:37 2013
@@ -25,10 +25,13 @@ package org.apache.subversion.javahl.uti
 
 import org.apache.subversion.javahl.SVNUtil;
 import org.apache.subversion.javahl.ClientException;
+import org.apache.subversion.javahl.SubversionException;
 import org.apache.subversion.javahl.NativeResources;
+import org.apache.subversion.javahl.types.ExternalItem;
 import org.apache.subversion.javahl.types.NodeKind;
 import org.apache.subversion.javahl.types.Revision;
 
+import java.util.List;
 import java.io.InputStream;
 
 /**
@@ -64,4 +67,17 @@ public class PropLib
                                         InputStream fileContents,
                                         boolean skipSomeChecks)
         throws ClientException;
+
+
+    /** @see SVNUtil.parseExternals */
+    public native List<ExternalItem> parseExternals(byte[] description,
+                                                    String parentDirectory,
+                                                    boolean canonicalizeUrl)
+        throws ClientException;
+
+    /** @see SVNUtil.unparseExternals */
+    public native byte[] unparseExternals(List<ExternalItem> items,
+                                          String parentDirectory,
+                                          boolean old_format)
+        throws SubversionException;
 }

Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java?rev=1539130&r1=1539129&r2=1539130&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
(original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
Tue Nov  5 21:05:37 2013
@@ -23,13 +23,17 @@
 
 package org.apache.subversion.javahl;
 
+import org.apache.subversion.javahl.types.ExternalItem;
 import org.apache.subversion.javahl.types.NodeKind;
+import org.apache.subversion.javahl.types.Revision;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * Tests the JavaHL SVNUtil APIs.
@@ -188,4 +192,102 @@ public class UtilTests extends SVNTests
         }
         assertTrue(caught_exception);
     }
+
+
+    private static List<ExternalItem> externals = null;
+    static {
+        try {
+            externals = new ArrayList<ExternalItem>(20);
+            externals.add(new ExternalItem("a", "http://server/repo/path",
+                                           null, null));
+            externals.add(new ExternalItem("b", "//server/repo/path",
+                                           null, null));
+            externals.add(new ExternalItem("c", "/repo/path",
+                                           null, null));
+            externals.add(new ExternalItem("d", "^/path",
+                                           null, null));
+            externals.add(new ExternalItem("e", "^/../oper/path",
+                                           null, null));
+
+            externals.add(new ExternalItem("f", "http://server/repo/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("g", "//server/repo/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("h", "/repo/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("j", "^/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("j", "^/../oper/path",
+                                           Revision.getInstance(42), null));
+
+            externals.add(new ExternalItem("k", "http://server/repo/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("l", "//server/repo/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("m", "/repo/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("n", "^/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("o", "^/../oper/path",
+                                           null, Revision.getInstance(42)));
+
+            externals.add(new ExternalItem("p", "http://server/repo/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("q", "//server/repo/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("r", "/repo/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("s", "^/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("t", "^/../oper/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+        } catch (SubversionException ex) {
+            externals = null;
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public void testUnparseExternals() throws Throwable
+    {
+        byte[] props = SVNUtil.unparseExternals(externals, "dirname");
+        assertEquals(424, props.length);
+    }
+
+    private static List<ExternalItem> old_externals = null;
+    static {
+        try {
+            old_externals = new ArrayList<ExternalItem>(2);
+            old_externals.add(new ExternalItem("X", "http://server/repo/path",
+                                               null, null));
+            old_externals.add(new ExternalItem("Y", "http://server/repo/path",
+                                               Revision.getInstance(42), null));
+        } catch (SubversionException ex) {
+            old_externals = null;
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public void testUnparseExternalsOldstyle() throws Throwable
+    {
+        byte[] props;
+
+        props = SVNUtil.unparseExternalsForAncientUnsupportedClients(
+                     old_externals, "dirname");
+        assertEquals(57, props.length);
+
+        // The fancy new features are not supported in the old format
+        boolean caught_exception = false;
+        try {
+            props = SVNUtil.unparseExternalsForAncientUnsupportedClients(
+                         externals, "dirname");
+        } catch (SubversionException ex) {
+            caught_exception = true;
+        }
+        assertTrue(caught_exception);
+    }
 }



Mime
View raw message