incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r632955 - in /incubator/sling/trunk: launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/ sling/ujax/src...
Date Mon, 03 Mar 2008 06:55:37 GMT
Author: cziegeler
Date: Sun Mar  2 22:55:35 2008
New Revision: 632955

URL: http://svn.apache.org/viewvc?rev=632955&view=rev
Log:
SLING-295: Apply patch from Tobias Bocanegra for
- divided content processing in 2 steps:
  1) collect all properties
  2) write back content
- altered deepGetOrCreateNode() to use jcr:primaryType and jcr:mixinType props
- simplified RequestProperty to be less intelligent. always has an 'abs path'
- targeted node is always created
- added test cases for (deep) node creation with node types
- (re)enabled move test cases

Modified:
    incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java
    incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletMoveTest.java
    incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/RequestProperty.java
    incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java
    incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java

Modified: incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java?rev=632955&r1=632954&r2=632955&view=diff
==============================================================================
--- incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java
(original)
+++ incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java
Sun Mar  2 22:55:35 2008
@@ -91,8 +91,7 @@
 
         // add node type param
         final Map<String,String> props = new HashMap<String,String>();
-        props.put("ujax:nodeType","nt:unstructured");
-        props.put("name1","value1B");
+        props.put("jcr:primaryType","nt:folder");
 
         // POST and get URL of created node
         String urlOfNewNode = null;
@@ -102,17 +101,54 @@
             fail("createNode failed: " + ioe);
         }
 
-        // get and check URL of created node
-        final GetMethod get = new GetMethod(urlOfNewNode);
-        final int status = httpClient.executeMethod(get);
-        assertEquals(urlOfNewNode + " must be accessible after createNode",200,status);
-        final String responseBodyStr = get.getResponseBodyAsString();
-        assertTrue(responseBodyStr.contains("nt:unstructured"));
+        String content = getContent(urlOfNewNode + ".json", CONTENT_TYPE_JSON);
+        assertJavascript("nt:folder", content, "out.println(data['jcr:primaryType'])");
+    }
+
+    public void testCreateNewNodeWithNodeType() throws IOException {
+        final String url = HTTP_BASE_URL + "/CreateNodeTest_4_" + System.currentTimeMillis()
+ "/*";
+
+        // add node type param
+        final Map<String,String> props = new HashMap<String,String>();
+        props.put("jcr:primaryType","nt:folder");
+
+        // POST and get URL of created node
+        String urlOfNewNode = null;
+        try {
+            urlOfNewNode = testClient.createNode(url, props);
+        } catch(IOException ioe) {
+            fail("createNode failed: " + ioe);
+        }
+
+        String content = getContent(urlOfNewNode + ".json", CONTENT_TYPE_JSON);
+        assertJavascript("nt:folder", content, "out.println(data['jcr:primaryType'])");
+    }
+
+    public void testDeepCreateNodeWithNodeType() throws IOException {
+        final String url = HTTP_BASE_URL + "/CreateNodeTest_5_" + System.currentTimeMillis();
+
+        // add node type param
+        final Map<String,String> props = new HashMap<String,String>();
+        props.put("jcr:primaryType","nt:folder");
+        props.put("foo/jcr:primaryType","nt:folder");
+        props.put("foo/bar/jcr:primaryType","nt:folder");
+
+        // POST and get URL of created node
+        String urlOfNewNode = null;
+        try {
+            urlOfNewNode = testClient.createNode(url, props);
+        } catch(IOException ioe) {
+            fail("createNode failed: " + ioe);
+        }
+
+        String content = getContent(urlOfNewNode + ".3.json", CONTENT_TYPE_JSON);
+        assertJavascript("nt:folder", content, "out.println(data['jcr:primaryType'])");
+        assertJavascript("nt:folder", content, "out.println(data.foo['jcr:primaryType'])");
+        assertJavascript("nt:folder", content, "out.println(data.foo.bar['jcr:primaryType'])");
     }
 
-    /** Disabled - See SLING-299
     public void testCreateEmptyNode() throws IOException {
-        final String url = HTTP_BASE_URL + "/CreateNodeTest_4_" + System.currentTimeMillis();
+        final String url = HTTP_BASE_URL + "/CreateNodeTest_6_" + System.currentTimeMillis();
 
         // add node type param
         final Map<String,String> props = new HashMap<String,String>();
@@ -130,5 +166,4 @@
         final int status = httpClient.executeMethod(get);
         assertEquals(urlOfNewNode + " must be accessible after createNode",200,status);
     }
-    */
 }

Modified: incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletMoveTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletMoveTest.java?rev=632955&r1=632954&r2=632955&view=diff
==============================================================================
--- incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletMoveTest.java
(original)
+++ incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletMoveTest.java
Sun Mar  2 22:55:35 2008
@@ -24,16 +24,16 @@
 
 /** Test node move via the MicrojaxPostServlet */
 public class PostServletMoveTest extends HttpTestBase {
-    public static final String TEST_BASE_PATH = "/ujax-tests";
-    private String testPath;
+
+    public static final String TEST_BASE_PATH = "/ujax-move-tests";
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        testPath = TEST_BASE_PATH + "/" + System.currentTimeMillis();
     }
 
-    public void XtestMoveNodeAbsolute() throws IOException {
+    public void testMoveNodeAbsolute() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/abs/" + System.currentTimeMillis();
         Map<String, String> props = new HashMap<String, String>();
         props.put("text", "Hello");
         testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
@@ -46,7 +46,8 @@
         assertJavascript("Hello", content, "out.println(data.text)");
     }
 
-    public void XtestMoveNodeRelative() throws IOException {
+    public void testMoveNodeRelative() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/rel/" + System.currentTimeMillis();
         Map<String, String> props = new HashMap<String, String>();
         props.put("text", "Hello");
         testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
@@ -59,7 +60,8 @@
         assertJavascript("Hello", content, "out.println(data.text)");
     }
 
-    public void XtestMoveNodeNew() throws IOException {
+    public void testMoveNodeNew() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/new/" + System.currentTimeMillis();
         Map<String, String> props = new HashMap<String, String>();
         props.put("text", "Hello");
         testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
@@ -67,14 +69,13 @@
         props.clear();
         props.put("ujax:moveSrc", testPath + "/src");
         props.put("ujax:moveDest", "new");
-        // special case - need force creation of the new node 
-        props.put("jcr:created", "");
         String newNode = testClient.createNode(HTTP_BASE_URL + testPath + "/*", props);
         String content = getContent(newNode + "/new.json", CONTENT_TYPE_JSON);
         assertJavascript("Hello", content, "out.println(data.text)");
     }
 
     public void testMoveNodeExistingFail() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/exist/" + System.currentTimeMillis();
         Map<String, String> props = new HashMap<String, String>();
         props.put("text", "Hello");
         testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
@@ -101,6 +102,7 @@
     }
 
     public void testMoveNodeExistingReplace() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/replace/" + System.currentTimeMillis();
         Map<String, String> props = new HashMap<String, String>();
         props.put("text", "Hello");
         testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);

Modified: incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/RequestProperty.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/RequestProperty.java?rev=632955&r1=632954&r2=632955&view=diff
==============================================================================
--- incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/RequestProperty.java
(original)
+++ incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/RequestProperty.java
Sun Mar  2 22:55:35 2008
@@ -30,59 +30,43 @@
 
     public static final String DEFAULT_NULL = UjaxPostServlet.RP_PREFIX + "null";
 
-    private final String typeHint;
+    private final String path;
 
-    private final String relPath;
-
-    private final String propName;
+    private final String name;
 
     private final String parentPath;
 
     private final RequestParameter[] values;
 
-    private RequestParameter[] defaultValues;
-
-    public RequestProperty(UjaxPostProcessor ctx, String relPath,
-                           RequestParameter[] values) {
-        this.relPath = relPath;
-        this.values = values;
+    private String[] stringValues;
 
-        // split the relative path identifying the property to be saved
-        if (this.relPath.indexOf("/")>=0) {
-            parentPath = this.relPath.substring(0, this.relPath.lastIndexOf("/"));
-            propName = this.relPath.substring(this.relPath.lastIndexOf("/") + 1);
-        } else {
-            parentPath = "";
-            propName = this.relPath;
-        }
+    private String typeHint;
 
-        // @TypeHint example
-        // <input type="text" name="./age" />
-        // <input type="hidden" name="./age@TypeHint" value="long" />
-        // causes the setProperty using the 'long' property type
-        final String thName = ctx.getSavePrefix() + this.relPath + UjaxPostServlet.TYPE_HINT_SUFFIX;
-        final RequestParameter rp = ctx.getRequest().getRequestParameter(thName);
-        typeHint = rp == null ? null : rp.getString();
-
-        // @DefaultValue
-        final String dvName = ctx.getSavePrefix() + this.relPath + UjaxPostServlet.DEFAULT_VALUE_SUFFIX;
-        defaultValues = ctx.getRequest().getRequestParameters(dvName);
-        if (defaultValues == null) {
-            defaultValues = EMPTY_PARAM_ARRAY;
-        }
+    private RequestParameter[] defaultValues = EMPTY_PARAM_ARRAY;
 
+    public RequestProperty(String path, RequestParameter[] values) {
+        assert path.startsWith("/");
+        this.path = path;
+        this.values = values;
+        this.parentPath = path.substring(0, path.lastIndexOf("/"));
+        this.name = path.substring(path.lastIndexOf("/") + 1);
     }
 
     public String getTypeHint() {
         return typeHint;
     }
 
-    public String getRelPath() {
-        return relPath;
+
+    public void setTypeHint(String typeHint) {
+        this.typeHint = typeHint;
+    }
+
+    public String getPath() {
+        return path;
     }
 
     public String getName() {
-        return propName;
+        return name;
     }
 
     public String getParentPath() {
@@ -97,6 +81,14 @@
         return defaultValues;
     }
 
+    public void setDefaultValues(RequestParameter[] defaultValues) {
+        if (defaultValues == null) {
+            this.defaultValues = EMPTY_PARAM_ARRAY;
+        } else {
+            this.defaultValues = defaultValues;
+        }
+    }
+
     public boolean isFileUpload() {
         return !values[0].isFormField();
     }
@@ -130,28 +122,31 @@
      *         removed.
      */
     public String[] getStringValues() {
-        if (values.length > 1) {
-            // TODO: how the default values work for MV props is not very clear
-            String[] ret = new String[values.length];
-            for (int i=0; i<ret.length; i++) {
-                ret[i] = values[i].getString();
-            }
-            return ret;
-        }
-        String value = values[0].getString();
-        if (value.equals("")) {
-            if (defaultValues.length == 1) {
-                String defValue = defaultValues[0].getString();
-                if (defValue.equals(DEFAULT_IGNORE)) {
-                    // ignore means, do not create empty values
-                    return new String[0];
-                } else if (defValue.equals(DEFAULT_NULL)) {
-                    // null means, remove property if exist
-                    return null;
+        if (stringValues == null) {
+            if (values.length > 1) {
+                // TODO: how the default values work for MV props is not very clear
+                stringValues = new String[values.length];
+                for (int i=0; i<stringValues.length; i++) {
+                    stringValues[i] = values[i].getString();
+                }
+            } else {
+                String value = values[0].getString();
+                if (value.equals("")) {
+                    if (defaultValues.length == 1) {
+                        String defValue = defaultValues[0].getString();
+                        if (defValue.equals(DEFAULT_IGNORE)) {
+                            // ignore means, do not create empty values
+                            return new String[0];
+                        } else if (defValue.equals(DEFAULT_NULL)) {
+                            // null means, remove property if exist
+                            return null;
+                        }
+                        value = defValue;
+                    }
                 }
-                value = defValue;
+                stringValues = new String[]{value};
             }
         }
-        return new String[]{value};
+        return stringValues;
     }
 }

Modified: incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java?rev=632955&r1=632954&r2=632955&view=diff
==============================================================================
--- incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java
(original)
+++ incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java
Sun Mar  2 22:55:35 2008
@@ -17,6 +17,7 @@
 package org.apache.sling.ujax;
 
 import java.util.Map;
+import java.util.LinkedHashMap;
 
 import javax.jcr.NamespaceException;
 import javax.jcr.Node;
@@ -33,7 +34,7 @@
 import org.slf4j.LoggerFactory;
 
 /**
- * Holds various states and encapsulates method that are neede to handle a
+ * Holds various states and encapsulates methods that are needed to handle a
  * ujax post request.
  */
 public class UjaxPostProcessor {
@@ -43,7 +44,6 @@
      */
     private static final Logger log = LoggerFactory.getLogger(UjaxPostProcessor.class);
 
-
     /**
      * log that records the changes applied during the processing of the
      * post request.
@@ -107,6 +107,12 @@
     private Exception error;
 
     /**
+     * map of properties that form the content
+     */
+    private Map<String, RequestProperty> reqProperties = new LinkedHashMap<String,
RequestProperty>();
+
+
+    /**
      * Creates a new post processor
      * @param request the request to operate on
      * @param session jcr session to operate on
@@ -267,9 +273,7 @@
         return ret.toString();
     }
 
-
-
-    /**
+   /**
      * Returns any recorded error or <code>null</code>
      * @return an error or null
      */
@@ -286,14 +290,43 @@
     }
 
     /**
-     * Processes the actions defined by the request
+     * Resolves the given path with respect to the current root path.
+     *
+     * @param path the path to resolve
+     * @return the given path if it starts with a '/';
+     *         a resolved path otherwise.
+     */
+    public String resolvePath(String path) {
+        if (path.startsWith("/")) {
+            return path;
+        }
+        if (currentPath == null) {
+            return rootPath + "/" + path;
+        }
+        return currentPath + "/" + path;
+    }
+
+    /**
+     * Processes the actions defined by the request in the followin order
+     * <ol>
+     * <li>calculate the 'currentPath' respecting a 'create suffix'
+     * <li>collect all content properties included in the request
+     * <li>create new node
+     * <li>perform 'moves'
+     * <li>perform 'deletes'
+     * <li>write back content
+     * <li>process node ordering
+     * </ol>
      */
     public void run()  {
         try {
+            // do not change order unless you have a very good reason.
+            initCurrentPath();
+            collectContent();
             processCreate();
             processMoves();
             processDeletes();
-            processContent();
+            writeContent();
             processOrder();
             if (session.hasPendingChanges()) {
                 session.save();
@@ -313,23 +346,6 @@
     }
 
     /**
-     * Resolves the given path with respect to the current root path.
-     *
-     * @param path the path to resolve
-     * @return the given path if it starts with a '/';
-     *         a resolved path otherwise.
-     */
-    public String resolvePath(String path) {
-        if (path.startsWith("/")) {
-            return path;
-        }
-        if (currentPath == null) {
-            return rootPath + "/" + path;
-        }
-        return currentPath + "/" + path;
-    }
-
-    /**
      * Delete Items at the provided paths
      *
      * @throws RepositoryException if a repository error occurs
@@ -409,11 +425,13 @@
     }
 
     /**
-     * Create node(s) according to current request
+     * Initialize the current path. If this is a create request, a new node
+     * name is generated.
+     *
      * @throws RepositoryException if a repository error occurs
      * @throws ServletException if an internal error occurs
      */
-    private void processCreate() throws RepositoryException, ServletException {
+    private void initCurrentPath() throws RepositoryException, ServletException {
         // get desired path.
         currentPath = rootPath;
 
@@ -437,17 +455,50 @@
             if (session.itemExists(currentPath)) {
                 throw new ServletException("Collision in generated node names for path="
+ currentPath);
             }
-            deepGetOrCreateNode(null, currentPath, true);
         }
     }
 
     /**
-     * Create or update node(s) according to current request
+     * Create node(s) according to current request
+     * @throws RepositoryException if a repository error occurs
+     * @throws ServletException if an internal error occurs
+     */
+    private void processCreate() throws RepositoryException, ServletException {
+        // create new node in any case
+        deepGetOrCreateNode(currentPath);
+    }
+
+    /**
+     * Writes back the content
+     *
+     * @throws RepositoryException if a repository error occurs
+     * @throws ServletException if an internal error occurs
+     */
+    private void writeContent() throws RepositoryException, ServletException {
+        for (RequestProperty prop: reqProperties.values()) {
+            Node parent = deepGetOrCreateNode(prop.getParentPath());
+            // skip jcr special propeties
+            if (prop.getName().equals("jcr:primaryType") ||
+                    prop.getName().equals("jcr:mixinTypes")) {
+                continue;
+            }
+            if (prop.isFileUpload()) {
+                uploadHandler.setFile(parent, prop);
+            } else {
+                propHandler.setProperty(parent, prop);
+            }
+        }
+    }
+
+    /**
+     * Collects the properties that form the content to be written back to the
+     * repository.
+     *
      * @throws RepositoryException if a repository error occurs
      * @throws ServletException if an internal error occurs
      */
-    private void processContent() throws RepositoryException, ServletException {
-        // walk the request parameters, create and save nodes and properties
+    private void collectContent() throws RepositoryException, ServletException {
+        // walk the request parameters and collect the properties
         for (Map.Entry<String, RequestParameter[]>  e: request.getRequestParameterMap().entrySet())
{
             final String paramName = e.getKey();
 
@@ -455,16 +506,16 @@
             if(paramName.startsWith(UjaxPostServlet.RP_PREFIX)) {
                 continue;
             }
-            // ignore field with a '@TypeHint' suffix. this is dealt in RequestProperty
+            // ignore field with a '@TypeHint' suffix. this is dealt with later
             if (paramName.endsWith(UjaxPostServlet.TYPE_HINT_SUFFIX)) {
                 continue;
             }
-            // ignore field with a '@DefaultValue' suffix. this is dealt in RequestProperty
+            // ignore field with a '@DefaultValue' suffix. this is dealt with later
             if (paramName.endsWith(UjaxPostServlet.DEFAULT_VALUE_SUFFIX)) {
                 continue;
             }
-            // skip FormEncoding parameter
-            if ( paramName.equals("FormEncoding") ) {
+            // SLING-298: skip FormEncoding parameter
+            if (paramName.equals("FormEncoding")) {
                 continue;
             }
             // skip parameters that do not start with the save prefix
@@ -496,82 +547,99 @@
                     continue;
                 }
             }
-            // create property helper and get parent node
-            RequestProperty prop = new RequestProperty(this, propertyName, values);
-            Node parent = deepGetOrCreateNode(currentPath, prop.getParentPath(), true);
+            // create property helper and add it to the list
+            String propPath = propertyName;
+            if (!propPath.startsWith("/")) {
+                propPath = currentPath + "/" + propertyName;
+            }
+            RequestProperty prop = new RequestProperty(propPath, values);
 
-            // call handler
-            if (prop.isFileUpload()) {
-                uploadHandler.setFile(parent, prop);
-            } else {
-                propHandler.setProperty(parent, prop);
+            // @TypeHint example
+            // <input type="text" name="./age" />
+            // <input type="hidden" name="./age@TypeHint" value="long" />
+            // causes the setProperty using the 'long' property type
+            final String thName = getSavePrefix() + propertyName + UjaxPostServlet.TYPE_HINT_SUFFIX;
+            final RequestParameter rp = request.getRequestParameter(thName);
+            if (rp != null) {
+                prop.setTypeHint(rp.getString());
             }
+
+            // @DefaultValue
+            final String dvName = getSavePrefix() + propertyName + UjaxPostServlet.DEFAULT_VALUE_SUFFIX;
+            prop.setDefaultValues(request.getRequestParameters(dvName));
+
+            reqProperties.put(propPath, prop);
         }
     }
 
     /**
+     * Checks the collected content for a jcr:primaryType property at the
+     * specified path.
+     * @param path path to check
+     * @return the primary type or <code>null</code>
+     */
+    private String getPrimaryType(String path) {
+        RequestProperty prop = reqProperties.get(path + "/jcr:primaryType");
+        return prop == null ? null : prop.getStringValues()[0];
+    }
+
+    /**
+     * Checks the collected content for a jcr:mixinTypes property at the
+     * specified path.
+     * @param path path to check
+     * @return the mixin types or <code>null</code>
+     */
+    private String[] getMixinTypes(String path) {
+        RequestProperty prop = reqProperties.get(path + "/jcr:mixinTypes");
+        return prop == null ? null : prop.getStringValues();
+    }
+
+    /**
      * Deep gets or creates a node, parent-padding with default nodes nodes.
      * If the path is empty, the given parent node is returned.
      *
-     * @param parent path to the parent node, may be null if path is absolute
      * @param path path to node that needs to be deep-created
-     * @param isCreate is this a node creation
      * @return node at path
      * @throws RepositoryException if an error occurs
      * @throws IllegalArgumentException if the path is relative and parent
      *         is <code>null</code>
      */
-    private Node deepGetOrCreateNode(String parent, String path, boolean isCreate)
+    private Node deepGetOrCreateNode(String path)
             throws RepositoryException {
         if (log.isDebugEnabled()) {
-            log.debug("Deep-creating Node '{}/{}'", parent, path);
+            log.debug("Deep-creating Node '{}'", path);
         }
-        if (path.equals("")) {
-            if (parent == null || !parent.startsWith("/")) {
-                throw new IllegalArgumentException("parent must be an absolute path for relative
paths.");
-            }
-            path = parent;
-        } else if (path.charAt(0) != '/') {
-            // prepend parent path if path is relative
-            if (parent == null || !parent.startsWith("/")) {
-                throw new IllegalArgumentException("parent must be an absolute path for relative
paths.");
-            }
-            if (parent.endsWith("/")) {
-                path = parent + path;
-            } else {
-                path = parent + "/" + path;
-            }
+        if (path == null || !path.startsWith("/")) {
+            throw new IllegalArgumentException("path must be an absolute path.");
         }
-
-        String[] pathelems = path.substring(1).split("/");
+        int from = 1;
         Node node = session.getRootNode();
-
-        for(int i=0; i<pathelems.length; i++) {
-            final String name = pathelems[i];
+        while (from > 0) {
+            final int to = path.indexOf('/', from);
+            final String name = to < 0
+                    ? path.substring(from)
+                    : path.substring(from, to);
             if (node.hasNode(name)) {
                 node = node.getNode(name);
             } else {
-                boolean isLast = (i == pathelems.length - 1);
-                if ( isLast && isCreate ) {
-                    // check for node type
-                    final String nodeType = request.getParameter(UjaxPostServlet.RP_NODE_TYPE);
-                    if ( nodeType != null ) {
-                        node = node.addNode(name, nodeType);
-                    } else {
-                        node = node.addNode(name);
-                    }
-                    // check for mixin types
-                    final String[] mixinTypes = request.getParameterValues(UjaxPostServlet.RP_MIXIN_TYPES);
-                    if ( mixinTypes != null ) {
-                        for(int m=0; m<mixinTypes.length; m++) {
-                            node.addMixin(mixinTypes[m]);
-                        }
-                    }
+                final String tmpPath = to < 0 ? path : path.substring(0, to);
+                // check for node type
+                final String nodeType = getPrimaryType(tmpPath);
+                if (nodeType != null) {
+                    node = node.addNode(name, nodeType);
                 } else {
                     node = node.addNode(name);
                 }
+                // check for mixin types
+                final String[] mixinTypes = getMixinTypes(tmpPath);
+                if (mixinTypes != null) {
+                    for (String mix: mixinTypes) {
+                        node.addMixin(mix);
+                    }
+                }
                 changeLog.onCreated(node.getPath());
             }
+            from = to + 1;
         }
         return node;
     }
@@ -614,7 +682,7 @@
         final String orderCode = request.getParameter(UjaxPostServlet.RP_ORDER);
         if  (orderCode!=null) {
             if (UjaxPostServlet.ORDER_ZERO.equals(orderCode)) {
-                final Node n = deepGetOrCreateNode(null, currentPath, false);
+                final Node n = deepGetOrCreateNode(currentPath);
                 final Node parent = n.getParent();
                 final String beforename=parent.getNodes().nextNode().getName();
                 parent.orderBefore(n.getName(), beforename);

Modified: incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java?rev=632955&r1=632954&r2=632955&view=diff
==============================================================================
--- incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
(original)
+++ incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
Sun Mar  2 22:55:35 2008
@@ -150,18 +150,6 @@
     public static final String DEFAULT_VALUE_SUFFIX = "@DefaultValue";
 
     /**
-     * Optional request parameter: if provided and a new node is created it
-     * specifies the node type of the newly created node.
-     */
-    public static final String RP_NODE_TYPE = RP_PREFIX + "nodeType";
-
-    /**
-     * Optional request parameter: if provided and a new node is created it
-     * specifies the additional mixin types of the newly created node.
-     */
-    public static final String RP_MIXIN_TYPES = RP_PREFIX + "mixinTypes";
-
-    /**
      * utility class for generating node names
      */
     private final NodeNameGenerator nodeNameGenerator = new NodeNameGenerator();



Mime
View raw message