You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by fm...@apache.org on 2008/09/22 12:43:46 UTC

svn commit: r697778 - in /jackrabbit/trunk/jackrabbit-classloader/src: main/java/org/apache/jackrabbit/classloader/ main/java/org/apache/jackrabbit/net/ test/java/org/apache/jackrabbit/classloader/ test/resources/

Author: fmeschbe
Date: Mon Sep 22 03:43:46 2008
New Revision: 697778

URL: http://svn.apache.org/viewvc?rev=697778&view=rev
Log:
JCR-1749 Do not depend on nt:file and nt:resource node types when
trying to connect to a ClassLoader resource. Rather make assumptions
on the actual data in terms of jcr:content and jcr:data.

Modified:
    jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/classloader/Util.java
    jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/net/JCRURLConnection.java
    jackrabbit/trunk/jackrabbit-classloader/src/test/java/org/apache/jackrabbit/classloader/ClassLoaderTestBase.java
    jackrabbit/trunk/jackrabbit-classloader/src/test/resources/preload.properties

Modified: jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/classloader/Util.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/classloader/Util.java?rev=697778&r1=697777&r2=697778&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/classloader/Util.java (original)
+++ jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/classloader/Util.java Mon Sep 22 03:43:46 2008
@@ -30,13 +30,11 @@
 import org.slf4j.LoggerFactory;
 
 /**
- * The <code>Util</code> provides helper methods for the repository classloader
- * and its class path entry and resource classes.
+ * The <code>Util</code> provides helper methods for the repository
+ * classloader and its class path entry and resource classes.
  * <p>
  * This class may not be extended or instantiated, it just contains static
  * utility methods.
- *
- * @author Felix Meschberger
  */
 public class Util {
 
@@ -44,45 +42,85 @@
     private static final Logger log = LoggerFactory.getLogger(Util.class);
 
     /** Private constructor to not instantiate */
-    private Util() {}
+    private Util() {
+    }
 
     /**
-     * Resolves the given <code>item</code> to a <code>Property</code>. If the
-     * <code>item</code> is a node, the <code>getPrimaryItem</code> method is
-     * called repeatedly until a property is returned or until no more primary
-     * item is available. If the resulting property is a multivalue property,
-     * <code>null</code> is returned. Otherwise if the resulting property is
-     * a <code>REFERENCE</code> property, the node referred to is retrieved
-     * and this method is called recursively with the node. Otherwise, the
-     * resulting property is returned.
-     *
+     * Resolves the given <code>item</code> to a <code>Property</code> from
+     * which contents can be read.
+     * <p>
+     * The following mechanism is used to derive the contents:
+     * <ol>
+     * <li>If the <code>item</code> is a property, this property is used</li>
+     * <li>If the <code>item</code> is a node, three steps are tested:
+     * <ol>
+     * <li>If the node has a <code>jcr:content</code> child node, use that
+     * child node in the next steps. Otherwise continue with the node.</li>
+     * <li>Check for a <code>jcr:data</code> property and use that property
+     * if existing.</li>
+     * <li>Otherwise call <code>getPrimaryItem</code> method repeatedly until
+     * a property is returned or until no more primary item is available.</li>
+     * </ol>
+     * </ol>
+     * If no property can be resolved using the above algorithm or if the
+     * resulting property is a multivalue property, <code>null</code> is
+     * returned. Otherwise if the resulting property is a <code>REFERENCE</code>
+     * property, the node referred to is retrieved and this method is called
+     * recursively with the node. Otherwise, the resulting property is returned.
+     * 
      * @param item The <code>Item</code> to resolve to a <code>Property</code>.
-     *
-     * @return The resolved <code>Property</code> or <code>null</code> if the
-     *      resolved property is a multi-valued property.
-     *
-     * @throws ItemNotFoundException If the <code>item</code> is a node which
-     *      cannot be resolved to a property through (repeated) calls to
-     *      <code>Node.getPrimaryItem</code>.
+     * @return The resolved <code>Property</code> or <code>null</code> if
+     *         the resolved property is a multi-valued property or the
+     *         <code>item</code> is a node which cannot be resolved to a data
+     *         property.
      * @throws ValueFormatException If the <code>item</code> resolves to a
-     *      single-valued <code>REFERENCE</code> type property which cannot
-     *      be resolved to the node referred to.
+     *             single-valued <code>REFERENCE</code> type property which
+     *             cannot be resolved to the node referred to.
      * @throws RepositoryException if another error occurrs accessing the
-     *      repository.
+     *             repository.
      */
-    public static Property getProperty(Item item)
-            throws ItemNotFoundException, ValueFormatException,
+    public static Property getProperty(Item item) throws ValueFormatException,
             RepositoryException {
 
-        // if the item is a node, get its primary item until either
-        // no primary item exists any more or an ItemNotFoundException is thrown
-        while (item.isNode()) {
-            item = ((Node) item).getPrimaryItem();
+        Property prop;
+        if (item.isNode()) {
+
+            // check whether the node has a jcr:content node (e.g. nt:file)
+            Node node = (Node) item;
+            if (node.hasNode("jcr:content")) {
+                node = node.getNode("jcr:content");
+            }
+
+            // if the node has a jcr:data property, use that property
+            if (node.hasProperty("jcr:data")) {
+                
+                prop = node.getProperty("jcr:data");
+
+            } else {
+
+                // otherwise try to follow default item trail
+                try {
+                    item = node.getPrimaryItem();
+                    while (item.isNode()) {
+                        item = ((Node) item).getPrimaryItem();
+                    }
+                    prop = (Property) item;
+                } catch (ItemNotFoundException infe) {
+                    // we don't actually care, but log for completeness
+                    log.debug("getProperty: No primary items for "
+                        + node.getPath(), infe);
+                    return null;
+                }
+            }
+
+        } else {
+
+            prop = (Property) item;
+
         }
 
         // we get here with a property - otherwise an exception has already
         // been thrown
-        Property prop = (Property) item;
         if (prop.getDefinition().isMultiple()) {
             log.error("{} is a multivalue property", prop.getPath());
             return null;
@@ -97,34 +135,29 @@
     }
 
     /**
-     * Returns the last modification time of the property. If the property's
-     * parent node is a <code>nt:resource</code> the <code>long</code> value
-     * of the <code>jcr:lastModified</code> property of the parent node is
-     * returned. Otherwise the current system time is returned.
-     *
-     * @param prop The property for which to return the last modification
-     *      time.
-     *
-     * @return The last modification time of the resource or the current time
-     *      if the property is not a child of an <code>nt:resource</code> node.
-     *
+     * Returns the last modification time of the property, which is the long
+     * value of the <code>jcr:lastModified</code> property of the parent node
+     * of <code>prop</code>. If the parent node does not have a
+     * <code>jcr:lastModified</code> property the current system time is
+     * returned.
+     * 
+     * @param prop The property for which to return the last modification time.
+     * @return The last modification time of the resource or the current time if
+     *         the parent node of the property does not have a
+     *         <code>jcr:lastModified</code> property.
      * @throws ItemNotFoundException If the parent node of the property cannot
-     *      be retrieved.
-     * @throws PathNotFoundException If the "jcr:lastModified" property of the
-     *      parent node cannot be retrieved. This exception is unlikely in a
-     *      correctly configured repository as the jcr:lastModified property
-     *      has to be present in a node of type nt:resource.
+     *             be retrieved.
      * @throws AccessDeniedException If (read) access to the parent node is
-     *      denied.
+     *             denied.
      * @throws RepositoryException If any other error occurrs accessing the
-     *      repository to retrieve the last modification time.
+     *             repository to retrieve the last modification time.
      */
     public static long getLastModificationTime(Property prop)
             throws ItemNotFoundException, PathNotFoundException,
             AccessDeniedException, RepositoryException {
 
         Node parent = prop.getParent();
-        if (parent.isNodeType("nt:resource")) {
+        if (parent.hasProperty("jcr:lastModified")) {
             return parent.getProperty("jcr:lastModified").getLong();
         }
 

Modified: jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/net/JCRURLConnection.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/net/JCRURLConnection.java?rev=697778&r1=697777&r2=697778&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/net/JCRURLConnection.java (original)
+++ jackrabbit/trunk/jackrabbit-classloader/src/main/java/org/apache/jackrabbit/net/JCRURLConnection.java Mon Sep 22 03:43:46 2008
@@ -48,16 +48,18 @@
  * identify and access a repository <code>Property</code> based on the URL. This
  * main task is executed in the {@link #connect()} method.
  * <p>
- * Basically the guideposts to access content from a JCR Repository URl are
+ * Basically the guideposts to access content from a JCR Repository URL are
  * the following:
  * <ul>
  * <li>The URL must ultimately resolve to a repository property to provide
  *      content.
  * <li>If the URL itself is the path to a property, that property is used to
  *      provide the content.
- * <li>If the URL is a path to a node, the primary item chain starting with
- *      this node is followed until no further primary items exist. If the
- *      final item is a property, that property is used to provide the content.
+ * <li>If the URL is a path to a node, either the
+ *      <code>jcr:content/jcr:data</code> or <code>jcr:data</code> property is
+ *      used or the primary item chain starting with this node is followed until
+ *      no further primary items exist. If the final item is a property, that
+ *      property is used to provide the content.
  * <li>If neither of the above methods resolve to a property, the
  *      {@link #connect()} fails and access to the content is not possible.
  * </ul>
@@ -88,30 +90,25 @@
  *      representation of the value for all other value types.
  *
  * <dt><code>Content-Type</code>
- * <dd>If the property is a child of a <code>nt:resource</code> node, the
- *      content type is retrieved from the <code>jcr:mimeType</code>
- *      property of the parent node. If the parent node is not a
- *      <code>nt:resource</code>, the <code>guessContentTypeFromName</code>
- *      method is called on the {@link #getPath() path}. If this does not
- *      yield a content type, it is set to <code>application/octet-stream</code>
- *      for binary properties and to <code>text/plain</code> for other types.
+ * <dd>The content type is retrieved from the <code>jcr:mimeType</code>
+ *      property of the property's parent node if existing. Otherwise the
+ *      <code>guessContentTypeFromName</code> method is called on the
+ *      {@link #getPath() path}. If this does not yield a content type, it is
+ *      set to <code>application/octet-stream</code> for binary properties and
+ *      to <code>text/plain</code> for other types.
  *
  * <dt><code>Content-Enconding</code>
- * <dd>If the property is a child of a <code>nt:resource</code> node, the
- *      content encoding is retrieved from the <code>jcr:econding</code>
- *      property of the parent node. If the <code>jcr:encoding</code> property
- *      is not set, this header field remains undefined (aka <code>null</code>).
+ * <dd>The content encoding is retrieved from the <code>jcr:econding</code>
+ *      property of the property's parent node if existing. Otherwise this
+ *      header field remains undefined (aka <code>null</code>).
  *
  * <dt><code>Last-Modified</code>
- * <dd>If the property is a child of a <code>nt:resource</code> node, the
- *      last modified type is retrieved from the <code>jcr:lastModified</code>
- *      property of the parent node. If the parent node is not a
- *      <code>nt:resource</code>, the last modification time is set to zero.
+ * <dd>The last modified type is retrieved from the <code>jcr:lastModified</code>
+ *      property of the property's parent node if existing. Otherwise the last
+ *      modification time is set to zero.
  * </dl>
  * <p>
  * This class is not intended to be subclassed or instantiated by clients.
- *
- * @author Felix Meschberger
  */
 public class JCRURLConnection extends URLConnection {
 
@@ -336,16 +333,15 @@
      *      fails, because multi-valued properties are not currently supported.
      * <li>The content length header field is set from the property length
      *      (<code>Property.getLength())</code>).
-     * <li>If the property's parent node is of node type <code>nt:resource</code>,
-     *      the header fields for the content type, content encoding and last
+     * <li>The header fields for the content type, content encoding and last
      *      modification time are set from the <code>jcr:mimeType</code>,
      *      <code>jcr:encoding</code>, and <code>jcr:lastModification</code>
-     *      properties. Otherwise the content encoding field is set to
-     *      <code>null</code> and the last modification time is set to zero.
-     *      The content type field is guessed from the name of the URL item.
-     *      If the content type cannot be guessed, it is set to
-     *      <code>application/octet-stream</code> if the property is of binary
-     *      type or <code>text/plain</code> otherwise.
+     *      properties of the property's parent node if existing. Otherwise the
+     *      content encoding field is set to <code>null</code> and the last
+     *      modification time is set to zero. The content type field is guessed
+     *      from the name of the URL item. If the content type cannot be
+     *      guessed, it is set to <code>application/octet-stream</code> if the
+     *      property is of binary type or <code>text/plain</code> otherwise.
      * </ol>
      * <p>
      * When this method successfully returns, this connection is considered
@@ -377,26 +373,33 @@
                 long lastModified;
 
                 Node parent = property.getParent();
-                if (parent.isNodeType("nt:resource")) {
+                if (parent.hasProperty("jcr:lastModified")) {
                     lastModified = parent.getProperty("jcr:lastModified").getLong();
-                    contentType = parent.getProperty("jcr:mimeType").getString();
-                    if (parent.hasProperty("jcr:encoding")) {
-                        contentEncoding =
-                            parent.getProperty("jcr:encoding").getString();
-                    }
                 } else {
                     lastModified = 0;
+                }
+                
+                if (parent.hasProperty("jcr:mimeType")) {
+                    contentType = parent.getProperty("jcr:mimeType").getString();
+                } else {
                     contentType = guessContentTypeFromName(getItem().getName());
                     if (contentType == null) {
                         contentType = (property.getType() == PropertyType.BINARY)
-                                            ? APPLICATION_OCTET
-                                            : TEXT_PLAIN;
+                                ? APPLICATION_OCTET
+                                : TEXT_PLAIN;
                     }
                 }
+                
+                if (parent.hasProperty("jcr:encoding")) {
+                    contentEncoding = parent.getProperty("jcr:encoding").getString();
+                } else {
+                    contentEncoding = null;
+                }
 
-                log.debug("connect: Using atom '" + property.getPath() +
-                    "' with content type '" + contentType + "' for " +
-                    String.valueOf(contentLength) + " bytes");
+                log.debug(
+                    "connect: Using property '{}' with content type '{}' for {} bytes",
+                    new Object[] { property.getPath(), contentType,
+                        new Integer(contentLength) });
 
                 // set the fields
                 setProperty(property);

Modified: jackrabbit/trunk/jackrabbit-classloader/src/test/java/org/apache/jackrabbit/classloader/ClassLoaderTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-classloader/src/test/java/org/apache/jackrabbit/classloader/ClassLoaderTestBase.java?rev=697778&r1=697777&r2=697778&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-classloader/src/test/java/org/apache/jackrabbit/classloader/ClassLoaderTestBase.java (original)
+++ jackrabbit/trunk/jackrabbit-classloader/src/test/java/org/apache/jackrabbit/classloader/ClassLoaderTestBase.java Mon Sep 22 03:43:46 2008
@@ -99,7 +99,7 @@
     public void repositoryStart() throws Exception {
         InputStream config =
             RepositoryImpl.class.getResourceAsStream("repository.xml");
-        String home = new File("cltest").getAbsolutePath();
+        String home = new File("target/cltest").getAbsolutePath();
         RepositoryConfig rc = RepositoryConfig.create(config, home);
         RepositoryImpl repository = RepositoryImpl.create(rc);
 
@@ -355,7 +355,7 @@
     static void makeFileNode(Node node, URLConnection content)
             throws RepositoryException {
 
-        Node contentNode = node.addNode("jcr:content", "nt:resource");
+        Node contentNode = node.addNode("jcr:content", "nt:unstructured");
         InputStream ins = null;
         try {
             ins = content.getInputStream();

Modified: jackrabbit/trunk/jackrabbit-classloader/src/test/resources/preload.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-classloader/src/test/resources/preload.properties?rev=697778&r1=697777&r2=697778&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-classloader/src/test/resources/preload.properties (original)
+++ jackrabbit/trunk/jackrabbit-classloader/src/test/resources/preload.properties Mon Sep 22 03:43:46 2008
@@ -72,7 +72,7 @@
 /node1/file1/jcr:content/jcr:mimeType = p,String,text/plain
 
 /node1/file2 = n,nt:file
-/node1/file2/jcr:content = n,nt:resource
+/node1/file2/jcr:content = n,nt:unstructured
 /node1/file2/jcr:content/jcr:lastModified = p,Date,1966-12-26T22:15:00.000Z
 /node1/file2/jcr:content/jcr:mimeType = p,String,text/plain
 /node1/file2/jcr:content/jcr:data = p,Binary,This is the contents of file1\