You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/12/15 17:20:09 UTC

svn commit: r890864 - /jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/JcrUtils.java

Author: jukka
Date: Tue Dec 15 16:20:09 2009
New Revision: 890864

URL: http://svn.apache.org/viewvc?rev=890864&view=rev
Log:
JCR-2439: More utility methods in JcrUtils

Add getOrAddFolder() and putFile() methods.

Revert the getOrAddNode(parent, name, type) method back to data-first style, i.e. don't enforce the node type.

Modified:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/JcrUtils.java

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/JcrUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/JcrUtils.java?rev=890864&r1=890863&r2=890864&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/JcrUtils.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/JcrUtils.java Tue Dec 15 16:20:09 2009
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.commons;
 
+import java.io.InputStream;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -23,7 +25,6 @@
 import javax.imageio.spi.ServiceRegistry;
 import javax.jcr.Binary;
 import javax.jcr.Item;
-import javax.jcr.ItemExistsException;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.Property;
@@ -33,6 +34,7 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.RepositoryFactory;
 import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.query.QueryResult;
 import javax.jcr.query.Row;
 import javax.jcr.query.RowIterator;
@@ -357,7 +359,7 @@
      * @see Node#addNode(String)
      * @param parent parent node
      * @param name name of the child node
-     * @return child node
+     * @return the child node
      * @throws RepositoryException if the child node can not be
      *                             accessed or created
      */
@@ -375,44 +377,160 @@
      * it does not already exist. If the child node gets added, then it
      * is created with the given node type. The caller is expected to take
      * care of saving or discarding any transient changes.
-     * <p>
-     * This method ensures not only that the named child node exists but
-     * also that it matches the given node type.  If the child node already
-     * exists but does not match the given node type, then an
-     * {@link ItemExistsException} is thrown to indicate that a node of the
-     * given type can only be added if the previous node is first removed.
      *
      * @see Node#getNode(String)
      * @see Node#addNode(String, String)
      * @see Node#isNodeType(String)
      * @param parent parent node
      * @param name name of the child node
-     * @param type type of the child node
-     * @return child node
-     * @throws ItemExistsException if the child node already exists but
-     *                             has a different type than specified
-     * @throws RepositoryException if the child node can not be
-     *                             accessed or created
+     * @param type type of the child node, ignored if the child already exists
+     * @return the child node
+     * @throws RepositoryException if the child node can not be accessed
+     *                             or created
      */
     public static Node getOrAddNode(Node parent, String name, String type)
             throws RepositoryException {
         if (parent.hasNode(name)) {
-            Node node = parent.getNode(name);
-            if (node.isNodeType(type)) {
-                return node;
-            } else {
-                throw new ItemExistsException(
-                        "Unable to add a node of type " + type
-                        + " at path " + node.getPath()
-                        + " since it already exists with the different type "
-                        + node.getPrimaryNodeType().getName());
-            }
+            return parent.getNode(name);
         } else {
             return parent.addNode(name, type);
         }
     }
 
     /**
+     * Returns the named child of the given node, creating it as an
+     * nt:folder node if it does not already exist. The caller is expected
+     * to take care of saving or discarding any transient changes.
+     * <p>
+     * Note that the type of the returned node is <em>not</em> guaranteed
+     * to match nt:folder in case the node already existed. The caller can
+     * use an explicit {@link Node#isNodeType(String)} check if needed, or
+     * simply use a data-first approach and not worry about the node type
+     * until a constraint violation is encountered.
+     *
+     * @param parent parent node
+     * @param name name of the child node
+     * @return the child node
+     * @throws RepositoryException if the child node can not be accessed
+     *                             or created
+     */
+    public static Node getOrAddFolder(Node parent, String name)
+            throws RepositoryException {
+        return getOrAddNode(parent, name, NodeType.NT_FOLDER);
+    }
+
+    /**
+     * Creates or updates the named child of the given node. If the child
+     * does not already exist, then it is created using the nt:file node type.
+     * This file child node is returned from this method.
+     * <p>
+     * If the file node does not already contain a jcr:content child, then
+     * one is created using the nt:resource node type. The following
+     * properties are set on the jcr:content node:
+     * <dl>
+     *   <dt>jcr:mimeType</dt>
+     *   <dd>media type</dd>
+     *   <dt>jcr:encoding (optional)</dt>
+     *   <dd>charset parameter of the media type, if any</dd>
+     *   <dt>jcr:lastModified</dt>
+     *   <dd>current time</dd>
+     *   <dt>jcr:data</dt>
+     *   <dd>binary content</dd>
+     * </dl>
+     * <p>
+     * Note that the types of the returned node or the jcr:content child are
+     * <em>not</em> guaranteed to match nt:file and nt:resource in case the
+     * nodes already existed. The caller can use an explicit
+     * {@link Node#isNodeType(String)} check if needed, or simply use a
+     * data-first approach and not worry about the node type until a constraint
+     * violation is encountered.
+     * <p>
+     * The given binary content stream is closed by this method.
+     *
+     * @param parent parent node
+     * @param name name of the file
+     * @param mime media type of the file
+     * @param data binary content of the file
+     * @return the child node
+     * @throws RepositoryException if the child node can not be created
+     *                             or updated
+     */
+    public static Node putFile(
+            Node parent, String name, String mime, InputStream data)
+            throws RepositoryException {
+        return putFile(parent, name, mime, Calendar.getInstance(), data);
+    }
+
+    /**
+     * Creates or updates the named child of the given node. If the child
+     * does not already exist, then it is created using the nt:file node type.
+     * This file child node is returned from this method.
+     * <p>
+     * If the file node does not already contain a jcr:content child, then
+     * one is created using the nt:resource node type. The following
+     * properties are set on the jcr:content node:
+     * <dl>
+     *   <dt>jcr:mimeType</dt>
+     *   <dd>media type</dd>
+     *   <dt>jcr:encoding (optional)</dt>
+     *   <dd>charset parameter of the media type, if any</dd>
+     *   <dt>jcr:lastModified</dt>
+     *   <dd>date of last modification</dd>
+     *   <dt>jcr:data</dt>
+     *   <dd>binary content</dd>
+     * </dl>
+     * <p>
+     * Note that the types of the returned node or the jcr:content child are
+     * <em>not</em> guaranteed to match nt:file and nt:resource in case the
+     * nodes already existed. The caller can use an explicit
+     * {@link Node#isNodeType(String)} check if needed, or simply use a
+     * data-first approach and not worry about the node type until a constraint
+     * violation is encountered.
+     * <p>
+     * The given binary content stream is closed by this method.
+     *
+     * @param parent parent node
+     * @param name name of the file
+     * @param mime media type of the file
+     * @param date date of last modification
+     * @param data binary content of the file
+     * @return the child node
+     * @throws RepositoryException if the child node can not be created
+     *                             or updated
+     */
+    public static Node putFile(
+            Node parent, String name, String mime, Calendar date,
+            InputStream data) throws RepositoryException {
+        Binary binary =
+            parent.getSession().getValueFactory().createBinary(data);
+        try {
+            Node file = getOrAddNode(parent, name, NodeType.NT_FILE);
+            Node content =
+                getOrAddNode(file, Node.JCR_CONTENT, NodeType.NT_RESOURCE);
+
+            content.setProperty(Property.JCR_MIMETYPE, mime);
+            String[] parameters = mime.split(";");
+            for (int i = 1; i < parameters.length; i++) {
+                int equals = parameters[i].indexOf('=');
+                if (equals != -1) {
+                    String parameter = parameters[i].substring(0, equals);
+                    if ("charset".equalsIgnoreCase(parameter.trim())) {
+                        content.setProperty(
+                                Property.JCR_ENCODING,
+                                parameters[i].substring(equals + 1).trim());
+                    }
+                }
+            }
+
+            content.setProperty(Property.JCR_LAST_MODIFIED, date);
+            content.setProperty(Property.JCR_DATA, binary);
+            return file;
+        } finally {
+            binary.dispose();
+        }
+    }
+
+    /**
      * Returns a string representation of the given item. The returned string
      * is designed to be easily readable while providing maximum amount of
      * information for logging and debugging purposes.