incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bdelacre...@apache.org
Subject svn commit: r611825 - in /incubator/sling/trunk/usling: usling-servlets/ usling-servlets/src/main/java/org/apache/sling/ujax/ usling-servlets/src/main/java/org/apache/sling/usling/renderers/ usling-servlets/src/main/java/org/apache/sling/usling/servlet...
Date Mon, 14 Jan 2008 15:05:00 GMT
Author: bdelacretaz
Date: Mon Jan 14 07:04:53 2008
New Revision: 611825

URL: http://svn.apache.org/viewvc?rev=611825&view=rev
Log:
SLING-149 - merge usling into Sling - microjax POST protocol and usling default rendering, work in progress

Added:
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java   (with props)
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java   (with props)
    incubator/sling/trunk/usling/usling-webapp/README.txt   (with props)
Removed:
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingMainServlet.java
Modified:
    incubator/sling/trunk/usling/usling-servlets/   (props changed)
    incubator/sling/trunk/usling/usling-servlets/pom.xml
    incubator/sling/trunk/usling/usling-webapp/   (props changed)
    incubator/sling/trunk/usling/usling-webapp/pom.xml

Propchange: incubator/sling/trunk/usling/usling-servlets/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Jan 14 07:04:53 2008
@@ -2,3 +2,4 @@
 target
 .classpath
 .project
+.externalToolBuilders

Modified: incubator/sling/trunk/usling/usling-servlets/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/pom.xml?rev=611825&r1=611824&r2=611825&view=diff
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/pom.xml (original)
+++ incubator/sling/trunk/usling/usling-servlets/pom.xml Mon Jan 14 07:04:53 2008
@@ -53,12 +53,45 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package>org.apache.sling.usling.servlets.*</Private-Package>
+            <Private-Package>
+              org.apache.sling.usling.servlets.*,
+              org.apache.sling.usling.renderers.*,
+              org.apache.sling.ujax.*
+            </Private-Package>
           </instructions>
         </configuration>
       </plugin>
     </plugins>
   </build>
+  
+  <profiles>
+    <profile>
+      <!-- 
+        Use this profile to deploy the bundle automatically,
+        during development
+      -->
+      <id>autoDeployBundle</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>maven-sling-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>install-bundle</id>
+                <goals>
+                  <goal>install</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 
   <dependencies>
     <dependency>
@@ -72,6 +105,26 @@
     <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.api</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.core</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.servlet.resolver</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.mime</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
     </dependency>
   </dependencies>
 

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package org.apache.sling.ujax;
+
+/** Filter a String so that it can be used as a NodeName */
+public class NodeNameFilter {
+    
+    public static final String ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_";
+    public static final char REPLACEMENT_CHAR = '_';
+    
+    public String filter(String nodeName) {
+      final StringBuffer sb  = new StringBuffer();
+      char lastAdded = 0;
+      
+      nodeName = nodeName.toLowerCase();
+      for(int i=0; i < nodeName.length(); i++) {
+        final char c = nodeName.charAt(i);
+        char toAdd = c;
+        
+        if(ALLOWED_CHARS.indexOf(c)< 0) {
+          if(lastAdded == REPLACEMENT_CHAR) {
+            // do not add several _ in a row
+            continue;
+          }
+          toAdd = REPLACEMENT_CHAR;
+        }
+        
+        sb.append(toAdd);
+        lastAdded = toAdd;
+      }
+      
+      if(sb.length()==0) {
+        sb.append(REPLACEMENT_CHAR);
+      }
+      
+      return sb.toString();
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameFilter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+package org.apache.sling.ujax;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.request.RequestParameterMap;
+
+/** Generates a node name based on a set of well-known request parameters
+ *  like title, description, etc.
+ *  See SLING-128.
+ */
+public class NodeNameGenerator {
+    private List<String> parameterNames;
+    private final NodeNameFilter filter = new NodeNameFilter();
+    public static final int DEFAULT_MAX_NAME_LENGTH = 20;
+    private int maxLength = DEFAULT_MAX_NAME_LENGTH;
+    private int counter;
+    
+    public NodeNameGenerator() {
+        this(null);
+    }
+    
+    public NodeNameGenerator(List<String> parameterNames) {
+        if(parameterNames == null) {
+            this.parameterNames = new LinkedList<String>();
+            this.parameterNames.add("title");
+            this.parameterNames.add("name");
+            this.parameterNames.add("description");
+            this.parameterNames.add("abstract");
+        } else {
+            this.parameterNames = parameterNames;
+        }
+        
+    }
+    
+    /** Get a "nice" node name, if possible, based on given request 
+     *  @param savePrefix if provided, added in front of our parameterNames
+     *  when looking for request parameters
+     */
+    public String getNodeName(RequestParameterMap parameters, String prefix) {
+        String result = null;
+        if(prefix==null) {
+            prefix = "";
+        }
+        
+        // find the first request parameter that matches one of
+        // our parameterNames, in order, and has a value
+        String valueToUse = null;
+        if(parameters!=null) {
+            for(String param : parameterNames) {
+                if(valueToUse != null) {
+                    break;
+                }
+                
+                final RequestParameter[] pp = parameters.get(prefix + param);
+                if(pp!=null) {
+                    for(RequestParameter p : pp) {
+                        valueToUse = p.getString();
+                        if(valueToUse != null && valueToUse.length() > 0) {
+                            break;
+                        } else {
+                            valueToUse = null;
+                        }
+                    }
+                }
+            }
+        }
+        
+        // default value if none provided
+        if(result==null) {
+            result = (++counter) + "_" + System.currentTimeMillis();
+        }
+        
+        // filter value so that it works as a node name
+        if(valueToUse != null) {
+            result = filter.filter(valueToUse);
+        }
+
+        // max length
+        if(result.length() > maxLength) {
+            result = result.substring(0,maxLength);
+        }
+        
+        return result;
+    }
+
+    public int getMaxLength() {
+        return maxLength;
+    }
+
+    public void setMaxLength(int maxLength) {
+        this.maxLength = maxLength;
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/NodeNameGenerator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,455 @@
+/*
+ * 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.
+ */
+package org.apache.sling.ujax;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.HttpStatusCodeException;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.api.wrappers.SlingRequestPaths;
+import org.apache.sling.core.impl.SlingHttpContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** POST servlet that implements the ujax "protocol" */
+public class UjaxPostServlet extends SlingAllMethodsServlet {
+    private static final long serialVersionUID = 1837674988291697074L;
+
+    private static final Logger log = LoggerFactory.getLogger(UjaxPostServlet.class);
+    private final MicrojaxPropertyValueSetter propertyValueSetter = new MicrojaxPropertyValueSetter();
+    private final NodeNameGenerator nodeNameGenerator = new NodeNameGenerator();
+
+    /** Prefix for parameter names which control this POST
+     *  (ujax stands for "microjax", RP_ stands for "request param")
+     */
+    public static final String RP_PREFIX = "ujax:";
+
+    /** Optional request parameter: redirect to the specified URL after POST */
+    public static final String RP_REDIRECT_TO =  RP_PREFIX + "redirect";
+
+    /** Optional request parameter: delete the specified content paths */
+    public static final String RP_DELETE_PATH = RP_PREFIX + "delete";
+
+    /** Optional request parameter: only request parameters starting with this prefix are
+     *  saved as Properties when creating a Node. Active only if at least one parameter
+     *  starts with this prefix, and defaults to {@link #DEFAULT_SAVE_PARAM_PREFIX}.
+     */
+    public static final String RP_SAVE_PARAM_PREFIX = RP_PREFIX + "saveParamPrefix";
+
+    /** Default value for {@link #RP_SAVE_PARAM_PREFIX} */
+    public static final String DEFAULT_SAVE_PARAM_PREFIX = "./";
+
+    /** Optional request parameter: if value is 0, created node is ordered so as
+     *  to be the first child of its parent.
+     */
+    public static final String RP_ORDER = RP_PREFIX + "order";
+
+    /** Code value for RP_ORDER */
+    public static final String ORDER_ZERO = "0";
+
+    /** Optional request parameter: if provided, added at the end of the computed
+     *  (or supplied) redirect URL
+     */
+    public static final String RP_DISPLAY_EXTENSION = RP_PREFIX + "displayExtension";
+    
+    /** SLING-130, suffix that maps form field names to different JCR property names */
+    public static final String VALUE_FROM_SUFFIX = "@ValueFrom";
+
+    @Override
+    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws ServletException, IOException {
+
+        Session s = null;
+        try {
+
+            // select the Resource to process
+            Resource currentResource = request.getResource();
+            Node currentNode = currentResource.adaptTo(Node.class);
+
+            // need a Node, path and Session
+            String currentPath = null;
+            if(currentNode != null) {
+                currentPath = currentNode.getPath();
+                s = currentNode.getSession();
+            } else {
+                currentPath = SlingRequestPaths.getPathInfo(request);
+                s = (Session)request.getAttribute(SlingHttpContext.SESSION);
+            }
+            
+            if(s==null) {
+                throw new ServletException("No JCR Session available, currentNode=" + currentNode);
+            }
+
+            final String [] pathsToDelete = request.getParameterValues(RP_DELETE_PATH);
+            if(pathsToDelete!=null) {
+                // process deletes if any, and if so don't do anything else
+                deleteNodes(s, pathsToDelete, currentPath, response);
+            } else {
+                // if no deletes, create or update nodes
+                createOrUpdateNodesFromRequest(request, response, s);
+            }
+
+        } catch(RepositoryException re) {
+            throw new HttpStatusCodeException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,re.toString(),re);
+
+        } finally {
+            try {
+                if (s != null && s.hasPendingChanges()) {
+                    s.refresh(false);
+                }
+            } catch(RepositoryException re) {
+                log.warn("RepositoryException in finally block: "+ re.getMessage(),re);
+            }
+        }
+    }
+
+    /** Delete specified nodes, and send response */
+    protected void deleteNodes(Session s, String [] pathsToDelete, String currentPath, SlingHttpServletResponse response)
+    throws RepositoryException, IOException {
+        processDeletes(s, pathsToDelete, currentPath);
+        s.save();
+        response.setContentType(getServletContext().getMimeType("dummy.txt"));
+        final PrintWriter pw = new PrintWriter(new OutputStreamWriter(response.getOutputStream()));
+        pw.println("Nodes have been deleted(if they existed):");
+        for(String path : pathsToDelete) {
+            pw.println(path);
+        }
+        pw.flush();
+    }
+
+    /** Create or update node(s) according to current request , and send response */
+    protected void createOrUpdateNodesFromRequest(SlingHttpServletRequest request, SlingHttpServletResponse response, Session s)
+    throws RepositoryException, IOException {
+
+        // find out the actual "save prefix" to use - only parameters starting with
+        // this prefix are saved as Properties, when creating nodes, see setPropertiesFromRequest()
+        final String savePrefix = getSavePrefix(request);
+
+        // use the request path (disregarding resource resolution)
+        // but remove any extension or selectors
+        String currentPath = SlingRequestPaths.getPathInfo(request);
+        Node currentNode = null;
+        final int dotPos = currentPath.indexOf('.');
+        if(dotPos >= 0) {
+            currentPath = currentPath.substring(0,dotPos);
+        }
+
+        final String starSuffix = "/*";
+        if(currentPath.endsWith(starSuffix)) {
+            // If the path ends with a *, create a node under its parent, with
+            // a generated node name
+            currentPath = currentPath.substring(0, currentPath.length() - starSuffix.length());
+            currentPath += "/" + nodeNameGenerator.getNodeName(request.getRequestParameterMap(), savePrefix);
+            
+            // if resulting path exists, add a suffix until it's not the case anymore
+            if(s.itemExists(currentPath)) {
+                String newPath = currentPath;
+                for(int suffix = 0; suffix < 100; suffix++) {
+                    newPath = currentPath + "_" + suffix;
+                    if(!s.itemExists(newPath)) {
+                        currentPath = newPath;
+                        break;
+                    }
+                }
+            }
+            
+            if(s.itemExists(currentPath)) {
+                throw new HttpStatusCodeException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                        "Collision in generated node names for path=" + currentPath);
+            }
+
+        } else if(s.itemExists(currentPath)) {
+            // update to an existing node
+            final Item item = s.getItem(currentPath);
+            if(item.isNode()) {
+                currentNode = (Node)item;
+            } else {
+                throw new HttpStatusCodeException(HttpServletResponse.SC_CONFLICT,"Item at path " + currentPath + " is not a Node");
+            }
+
+        } else {
+            // request to create a new node at a specific path - use the supplied path as is
+        }
+
+        Set<Node> createdNodes = new HashSet<Node>();
+        if(currentNode == null) {
+            currentNode = deepCreateNode(s, currentPath, createdNodes);
+        }
+        currentPath = currentNode.getPath();
+
+        // process the "order" command if any
+        final String order = request.getParameter(RP_ORDER);
+        if(order!=null) {
+            processNodeOrder(currentNode,order);
+        }
+
+        // walk the request parameters, create and save nodes and properties
+        setPropertiesFromRequest(currentNode, request, savePrefix, createdNodes);
+
+        // sava data and send redirect
+        s.save();
+        response.sendRedirect(getRedirectUrl(request,currentNode.getPath()));
+    }
+    
+    /** compute redirect URL (SLING-126) */
+    protected String getRedirectUrl(SlingHttpServletRequest request, String currentNodePath) {
+        
+        // redirect param has priority (but see below, magic star)
+        String result = request.getParameter(RP_REDIRECT_TO);
+        final boolean magicStar = "*".equals(result);
+        
+        if(result==null || result.trim().length()==0) {
+            // try Referer
+            result = request.getHeader("Referer");
+        }
+        
+        // redirect param = star means "redirect to current node", useful in browsers
+        // when you don't want to use the Referer
+        if(magicStar || result==null || result.trim().length()==0) {
+            // use path of current node, with optional extension 
+            final String redirectExtension = request.getParameter(RP_DISPLAY_EXTENSION);
+            result = currentNodePath;
+            
+            if(redirectExtension!=null) {
+                if(redirectExtension.startsWith(".")) {
+                    result += redirectExtension;
+                } else {
+                    result += "." + redirectExtension;
+                }
+            }
+            
+            result =
+                SlingRequestPaths.getContextPath(request)
+                + SlingRequestPaths.getServletPath(request)
+                + result;
+        }
+        
+        if(log.isDebugEnabled()) {
+            log.debug("Will redirect to " + result);
+        }
+        
+        return result;
+    }
+
+    /** Set Node properties from current request
+     *  TODO should handle file uploads as well
+     */
+    private void setPropertiesFromRequest(Node n, SlingHttpServletRequest request,
+            String savePrefix, Set<Node> createdNodes)
+            throws RepositoryException {
+
+        for(Map.Entry<String, RequestParameter[]>  e : request.getRequestParameterMap().entrySet()) {
+            final String paramName = e.getKey();
+            
+            if(paramName.startsWith(RP_PREFIX)) {
+                // do not store parameters with names starting with ujax:  
+                continue;
+            }
+            
+            String propertyName = paramName;
+            if(savePrefix!=null) {
+                if(!paramName.startsWith(savePrefix)) {
+                    continue;
+                }
+                propertyName = paramName.substring(savePrefix.length());
+            }
+            
+            // SLING-130: VALUE_FROM_SUFFIX means take the value of this
+            // property from a different field
+            RequestParameter[] values = e.getValue();
+            final int vfIndex = propertyName.indexOf(VALUE_FROM_SUFFIX);
+            if(vfIndex >= 0) {
+                // @ValueFrom example:
+                // <input name="./Text@ValueFrom" type="hidden" value="fulltext" /> 
+                // causes the JCR Text property to be set to the value of the fulltext form field. 
+                propertyName = propertyName.substring(0, vfIndex);
+                final RequestParameter[] rp = request.getRequestParameterMap().get(paramName);
+                if(rp == null || rp.length > 1) {
+                    // @ValueFrom params must have exactly one value, else ignored
+                    continue;
+                }
+                String mappedName = rp[0].getString();
+                values = request.getRequestParameterMap().get(mappedName);
+                if(values==null) {
+                    // no value for "fulltext" in our example, ignore parameter
+                    continue;
+                }
+            }
+            
+            setProperty(n,request,propertyName,values,createdNodes);
+        }
+    }
+
+    /** Set a single Property on node N
+     * @throws RepositoryException */
+    private void setProperty(Node n, SlingHttpServletRequest request, String name,
+            RequestParameter[] values, Set<Node> createdNodes) throws RepositoryException {
+
+        // split the relative path identifying the property to be saved
+        String proppath = name;
+
+        // @ValueFrom can be used to define mappings between form fields and JCR properties
+// TODO
+//        final int vfIndex = name.indexOf("@ValueFrom");
+//        if (vfIndex >= 0) {
+//            // Indirect
+//            proppath = name.substring(0, vfIndex);
+//        } else if (name.indexOf("@") >= 0) {
+//            // skip "Hints"
+//            return;
+//        }
+
+        final String path = n.getPath();
+        String parentpath = "";
+        String propname=name;
+
+        if (propname.indexOf("/")>=0) {
+            parentpath=proppath.substring(0, name.lastIndexOf("/"));
+            propname = proppath.substring(name.lastIndexOf("/") + 1);
+        }
+
+        // if the whole thing ended in a slash -> skip
+        if (propname.equals("")) {
+            return;
+        }
+
+        // get or create the parent node
+        final Session s = n.getSession();
+        Node parent;
+        if(name.startsWith("/")) {
+            parent = deepCreateNode(s, parentpath, createdNodes);
+
+        } else if (!parentpath.equals("")) {
+            parent = (Node) s.getItem(path + "/" + parentpath);
+        } else {
+            parent = (Node) s.getItem(path);
+        }
+
+        // TODO String typehint = request.getParameter(proppath + "@TypeHint");
+        final String typeHint = null;
+        final boolean nodeIsNew = createdNodes.contains(parent);
+        propertyValueSetter.setProperty(parent, propname, values, typeHint, nodeIsNew);
+}
+
+    /**
+     * Deep creates a node, parent-padding with nt:unstructured nodes
+     *
+     * @param path absolute path to node that needs to be deep-created
+     */
+    private Node deepCreateNode(Session s, String path, Set<Node> createdNodes)
+            throws RepositoryException {
+        if(log.isDebugEnabled()) {
+            log.debug("Deep-creating Node '" + path + "'");
+        }
+
+        String[] pathelems = path.substring(1).split("/");
+        int i = 0;
+        String mypath = "";
+        Node parent = s.getRootNode();
+        while (i < pathelems.length) {
+            String name = pathelems[i];
+            mypath += "/" + name;
+            if (!s.itemExists(mypath)) {
+                createdNodes.add(parent.addNode(name));
+            }
+            parent = (Node) s.getItem(mypath);
+            i++;
+        }
+        return (parent);
+    }
+
+    /** Delete Items at the provided paths
+     *  @param pathsToDelete each path that does not start with / is
+     *      prepended with currentPath
+     */
+    private void processDeletes(Session s, String [] pathsToDelete, String currentPath)
+    throws RepositoryException {
+        for(String path : pathsToDelete) {
+            if(!path.startsWith("/")) {
+                path = currentPath + "/" + path;
+            }
+            if(s.itemExists(path)) {
+                s.getItem(path).remove();
+                if(log.isDebugEnabled()) {
+                    log.debug("Deleted item " + path);
+                }
+            } else {
+                if(log.isDebugEnabled()) {
+                    log.debug("Item '" + path + "' not found for deletion, ignored");
+                }
+            }
+        }
+    }
+
+    /** Return the "save prefix" to use, null if none */
+    private String getSavePrefix(SlingHttpServletRequest request) {
+        String prefix = request.getParameter(RP_SAVE_PARAM_PREFIX);
+        if(prefix==null) {
+            prefix = DEFAULT_SAVE_PARAM_PREFIX;
+        }
+
+        // if no parameters start with this prefix, it is not used
+        String result = null;
+        for(String name : request.getRequestParameterMap().keySet()) {
+            if(name.startsWith(prefix)) {
+                result = prefix;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /** If orderCode is ORDER_ZERO, move n so that it is the first
+     *  child of its parent
+     * @throws RepositoryException */
+    private void processNodeOrder(Node n, String orderCode) throws RepositoryException {
+        if(ORDER_ZERO.equals(orderCode)) {
+            final String path = n.getPath();
+            final Node parent=(Node) n.getSession().getItem(path.substring(0,path.lastIndexOf('/')));
+            final String myname=path.substring(path.lastIndexOf('/')+1);
+            final String beforename=parent.getNodes().nextNode().getName();
+            parent.orderBefore(myname, beforename);
+
+            if(log.isDebugEnabled()) {
+                log.debug("Node " + n.getPath() + " moved to be first child of its parent, due to orderCode=" + orderCode);
+            }
+
+        } else {
+            if(log.isDebugEnabled()) {
+                log.debug("orderCode '" + orderCode + "' invalid, ignored");
+            }
+        }
+    }
+}
+

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.sling.ujax;
+
+import java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.api.request.RequestParameter;
+
+/**
+ * Sets a Property on the given Node, in some cases with a specific type and
+ * value. For example, "lastModified" with an empty value is stored as the
+ * current Date.
+ */
+class MicrojaxPropertyValueSetter {
+    public static final String CREATED_FIELD = "created";
+    public static final String CREATED_BY_FIELD = "createdBy";
+    public static final String LAST_MODIFIED_FIELD = "lastModified";
+    public static final String LAST_MODIFIED_BY_FIELD = "lastModifiedBy";
+
+    /**
+     * Set property on given node, with some automatic values when user provides
+     * the field name but no value.
+     * 
+     * html example for testing: <input type="hidden" name="dateCreated"/>
+     * <input type="hidden" name="lastModified"/> <input type="hidden"
+     * name="createdBy"/> <input type="hidden" name="lastModifiedBy"/>
+     */
+    void setProperty(Node parent, String name, RequestParameter[] values, String typehint, boolean nodeWasJustCreated)
+            throws RepositoryException {
+
+        // set the same timestamp for all values, to ease testing
+        final Calendar now = Calendar.getInstance();
+        
+        if (valueProvided(values)) {
+            // if user provided a value, don't mess with it
+            setPropertyAsIs(parent, name, values, typehint);
+
+        } else if (CREATED_FIELD.equals(name)) {
+            if (nodeWasJustCreated) {
+                setCurrentDate(parent, name, now);
+            }
+
+        } else if (CREATED_BY_FIELD.equals(name)) {
+            if (nodeWasJustCreated) {
+                setCurrentUser(parent, name);
+            }
+
+        } else if (LAST_MODIFIED_FIELD.equals(name)) {
+            setCurrentDate(parent, name, now);
+
+        } else if (LAST_MODIFIED_BY_FIELD.equals(name)) {
+            setCurrentUser(parent, name);
+
+        } else {
+            // no magic field, set value as provided
+            setPropertyAsIs(parent, name, values, typehint);
+        }
+    }
+
+    /** set property to the current Date */
+    private void setCurrentDate(Node parent, String name, Calendar now) throws RepositoryException {
+        removePropertyIfExists(parent, name);
+        parent.setProperty(name, now);
+    }
+
+    /** set property to the current User id */
+    private void setCurrentUser(Node parent, String name) throws RepositoryException {
+        removePropertyIfExists(parent, name);
+        parent.setProperty(name, parent.getSession().getUserID());
+    }
+
+    private void removePropertyIfExists(Node parent, String name) throws RepositoryException {
+        if (parent.hasProperty(name)) {
+            Property prop = parent.getProperty(name);
+            prop.remove();
+        }
+    }
+
+    /** set property without processing, except for type hints */
+    private void setPropertyAsIs(Node parent, String name, RequestParameter[] values, String typehint) throws RepositoryException {
+        removePropertyIfExists(parent, name);
+
+        // no explicit typehint
+        if (typehint == null) {
+            // guess type based on mvp information from property
+            // TODO: use old property definition to guess aswell
+            if (values.length > 1) {
+                final String [] stringValues = new String[values.length];
+                int i = 0;
+                for(RequestParameter p : values) {
+                    stringValues[i++] = p.getString();
+                }
+                parent.setProperty(name, stringValues);
+            } else {
+                parent.setProperty(name, values[0].getString());
+            }
+        }
+
+        // explicit typehint Date
+        if ("Date".equals(typehint)) {
+            parent.setProperty(name, values[0].getString(), PropertyType.DATE);
+        }
+
+        // TODO: accept more typehints including mvp
+        // TODO: binary support
+    }
+
+    /** true if values contains at least one non-empty value */
+    private boolean valueProvided(RequestParameter[] values) {
+        boolean result = false;
+
+        for (RequestParameter p : values) {
+            final String val = p.getString();
+            if(val!=null && val.length() > 0) {
+                result = true;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPropertyValueSetter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+package org.apache.sling.usling.renderers;
+
+import java.io.PrintWriter;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.apache.sling.api.resource.Resource;
+
+/** Reusable default HTML rendering of a Node
+ */
+public class DefaultHtmlRenderer {
+
+    public void render(PrintWriter pw, Resource r, Node n) throws RepositoryException {
+        pw.println("<h1>Node dumped by " + getClass().getSimpleName() + "</h1>");
+        pw.println("<p>Node path: <b>" + n.getPath() + "</b></p>");
+        pw.println("<p>Resource metadata: <b>" + r.getResourceMetadata() + "</b></p>");
+
+        pw.println("<h2>Node properties</h2>");
+        for (PropertyIterator pi = n.getProperties(); pi.hasNext();) {
+            final Property p = pi.nextProperty();
+            printPropertyValue(pw, p);
+        }
+    }
+
+    /* TODO
+    public void render(PrintWriter pw, Resource r, SyntheticResourceData data) {
+        pw.println("<h1>SyntheticResourceData</h1>");
+        pw.println("<p>" + data.toString() + "</p>");
+    }
+    */
+
+    public void render(PrintWriter pw, Resource r, Property p) throws RepositoryException {
+        pw.print(p.getValue().getString());
+    }
+
+    protected void dump(PrintWriter pw, Resource r, Property p) throws RepositoryException {
+        pw.println("<h2>Property dumped by " + getClass().getSimpleName() + "</h1>");
+        pw.println("<p>Property path:" + p.getPath() + "</p>");
+        pw.println("<p>Resource metadata: " + r.getResourceMetadata() + "</p>");
+
+        printPropertyValue(pw, p);
+    }
+
+    protected void printPropertyValue(PrintWriter pw, Property p)
+            throws RepositoryException {
+
+        pw.print(p.getName() + ": <b>");
+
+        if (p.getDefinition().isMultiple()) {
+            Value[] values = p.getValues();
+            pw.print('[');
+            for (int i = 0; i < values.length; i++) {
+                if (i > 0) {
+                    pw.print(", ");
+                }
+                pw.print(values[i].getString());
+            }
+            pw.print(']');
+        } else {
+            pw.print(p.getValue().getString());
+        }
+
+        pw.print("</b><br/>");
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRenderer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.apache.sling.usling.renderers;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+
+/** A SlingSafeMethodsServlet that renders the current Resource
+ *  as simple HTML
+ */
+public class DefaultHtmlRendererServlet extends SlingSafeMethodsServlet {
+
+    private static final long serialVersionUID = -5815904221043005085L;
+    private final String responseContentType;
+    private final DefaultHtmlRenderer renderer;
+
+    public DefaultHtmlRendererServlet(String responseContentTypeHeaderValue) {
+        this.responseContentType = responseContentTypeHeaderValue;
+        this.renderer = new DefaultHtmlRenderer();
+    }
+
+    @Override
+    protected void doGet(SlingHttpServletRequest req,SlingHttpServletResponse resp)
+    throws ServletException,IOException
+    {
+        final Resource  r = req.getResource();
+
+        resp.setContentType(responseContentType);
+        final PrintWriter pw = resp.getWriter();
+
+        final Node node = r.adaptTo(Node.class);
+        /* TODO
+        final SyntheticResourceData srd = r.adaptTo(SyntheticResourceData.class);
+        */
+        final Property p = r.adaptTo(Property.class);
+
+        try {
+            /* TODO
+            if(srd != null) {
+                renderer.render(pw, r, srd);
+            } else */ 
+            if(node!=null) {
+                pw.println("<html><body>");
+                renderer.render(pw, r, node);
+                pw.println("</body></html>");
+            } else {
+                // for properties, we just output the String value
+                renderer.render(pw, r, p);
+            }
+
+        } catch (RepositoryException re) {
+            throw new ServletException("Cannot dump contents of "
+                + req.getResource().getPath(), re);
+        }
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/DefaultHtmlRendererServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+package org.apache.sling.usling.renderers;
+
+import java.io.Writer;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.io.JSONWriter;
+
+/** Dumps JCR Items as JSON data. The dump methods
+ *  are threadsafe.
+ */
+public class JsonItemWriter {
+    final Set<String> propertyNamesToIgnore;
+
+    /** Create a JsonItemWriter
+     *  @param propertyNamesToIgnore if not null, a property having a name from this
+     *  set of values is ignored.
+     *  TODO we should use a filtering interface to make the selection of which Nodes
+     *  and Properties to dump more flexible.
+     */
+    public JsonItemWriter(Set<String> propertyNamesToIgnore) {
+        this.propertyNamesToIgnore = propertyNamesToIgnore;
+    }
+
+    /** Dump all Nodes of given NodeIterator in JSON
+     * @throws JSONException */
+    public void dump(NodeIterator it, Writer out) throws RepositoryException, JSONException {
+        final JSONWriter w = new JSONWriter(out);
+        w.array();
+        while (it.hasNext()) {
+            dumpSingleNode(it.nextNode(), w, 1, 0);
+        }
+        w.endArray();
+    }
+
+    /** Dump given node in JSON, optionally recursing into its child nodes */
+    public void dump(Node node, Writer w, int maxRecursionLevels) throws RepositoryException, JSONException {
+        dump(node, new JSONWriter(w), 0, maxRecursionLevels);
+    }
+
+    /** Dump given property in JSON */
+    public void dump(Property p, Writer w) throws JSONException, ValueFormatException, RepositoryException {
+        final JSONWriter jw = new JSONWriter(w);
+        jw.object();
+        writeProperty(jw, 0, p);
+        jw.endObject();
+    }
+    
+    /** Dump given node in JSON, optionally recursing into its child nodes */
+    protected void dump(Node node, JSONWriter w, int currentRecursionLevel, int maxRecursionLevels)
+    throws RepositoryException, JSONException {
+
+        w.object();
+        PropertyIterator props = node.getProperties();
+
+        // the node's actual properties
+        while (props.hasNext()) {
+            Property prop = props.nextProperty();
+
+            if (propertyNamesToIgnore!=null && propertyNamesToIgnore.contains(prop.getName())) {
+                continue;
+            }
+
+            if (!prop.getDefinition().isMultiple()) {
+                writeProperty(w, currentRecursionLevel, prop);
+            } else {
+                w.array();
+                for(Value v : prop.getValues()) {
+                    w.value(convertValue(v));
+                }
+                w.endArray();
+            }
+        }
+
+        // the child nodes
+        if(recursionLevelActive(currentRecursionLevel, maxRecursionLevels)) {
+            final NodeIterator children = node.getNodes();
+            while(children.hasNext()) {
+                final Node n = children.nextNode();
+                dumpSingleNode(n, w, currentRecursionLevel, maxRecursionLevels);
+            }
+        }
+
+        w.endObject();
+    }
+
+    /** Dump a single node */
+    protected void dumpSingleNode(Node n, JSONWriter w, int currentRecursionLevel, int maxRecursionLevels)
+    throws RepositoryException, JSONException {
+        if (recursionLevelActive(currentRecursionLevel, maxRecursionLevels)) {
+            w.key(n.getName());
+            dump(n, w, currentRecursionLevel + 1, maxRecursionLevels);
+        }
+    }
+    
+    /** true if the current recursion level is active */
+    protected boolean recursionLevelActive(int currentRecursionLevel, int maxRecursionLevels) {
+        return currentRecursionLevel < maxRecursionLevels;
+    }
+
+    /**
+     * Write a single property
+     */
+    protected void writeProperty(JSONWriter w, int indent, Property p)
+    throws ValueFormatException, RepositoryException, JSONException {
+        if(p.getType() == PropertyType.BINARY) {
+            // TODO for now we mark binary properties with an initial star in their name
+            // (star is not allowed as a JCR property name)
+            // in the name, and the value should be the size of the binary data
+            w.key("*" + p.getName());
+
+        } else {
+            w.key(p.getName());
+        }
+
+        w.value(convertValue(p.getValue()));
+    }
+
+    /** Convert a Value for JSON output */
+    protected Object convertValue(Value v) throws ValueFormatException, IllegalStateException, RepositoryException {
+        if(v.getType() == PropertyType.BINARY) {
+            // TODO return the binary size
+            return new Integer(0);
+
+        } else if(v.getType() == PropertyType.DATE) {
+            final DateFormat fmt = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.US);
+            return fmt.format(v.getDate().getTime());
+
+        } else {
+            return v.getString();
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonItemWriter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+package org.apache.sling.usling.renderers;
+
+import java.io.IOException;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.HttpStatusCodeException;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.commons.json.JSONException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** A SlingSafeMethodsServlet that renders the current Resource
+ *  as a JSON data block
+ */
+public class JsonRendererServlet extends SlingSafeMethodsServlet {
+
+    private static final Logger log = LoggerFactory.getLogger(JsonRendererServlet.class);
+
+    private static final long serialVersionUID = 5577121546674133317L;
+    private final String responseContentType;
+    private final JsonItemWriter itemWriter;
+
+    /** This optional request parameter sets the recursion level
+     *  (into chldren) when dumping a node */
+    public static final String PARAM_RECURSION_LEVEL = "maxlevels";
+
+    public JsonRendererServlet(String responseContentTypeHeaderValue) {
+        this.responseContentType = responseContentTypeHeaderValue;
+        itemWriter = new JsonItemWriter(null);
+    }
+
+    @Override
+    protected void doGet(SlingHttpServletRequest req,SlingHttpServletResponse resp)
+    throws ServletException,IOException
+    {
+        // Access and check our data
+        final Resource  r = req.getResource();
+        if(r instanceof NonExistingResource) {
+            throw new HttpStatusCodeException(HttpServletResponse.SC_NOT_FOUND, "No data to dump");
+        }
+        
+        /* TODO
+        // Do we have a SyntheticResourceData?
+        if(r.adaptTo(SyntheticResourceData.class) != null) {
+            renderSyntheticResource(req, resp);
+            return;
+        }
+        */
+        
+        // Do we have a Property?
+        final Property p = r.adaptTo(Property.class);
+        if(p!=null) {
+            try {
+                renderProperty(p, resp);
+            } catch(JSONException je) {
+                reportException(je);
+            } catch(RepositoryException re) {
+                reportException(re);
+            }
+            return;
+        }
+        
+        // Do we have a Node?
+        final Node n = r.adaptTo(Node.class);
+        if(n == null) {
+            throw new HttpStatusCodeException(
+                HttpServletResponse.SC_NOT_IMPLEMENTED, "Can only dump nodes");
+        }
+
+        // how many levels deep?
+        int maxRecursionLevels = 0;
+        final String depth = req.getParameter(PARAM_RECURSION_LEVEL);
+        if (depth != null) {
+          try {
+            maxRecursionLevels = Integer.parseInt(depth);
+          } catch(Exception e) {
+            throw new HttpStatusCodeException(HttpServletResponse.SC_BAD_REQUEST,
+                    "Invalid value '" + depth + "' for request parameter '" + PARAM_RECURSION_LEVEL + "'"
+            );
+          }
+        }
+
+        // do the dump
+        resp.setContentType(responseContentType);
+        try {
+            itemWriter.dump(n, resp.getWriter(), maxRecursionLevels);
+        } catch(JSONException je) {
+            reportException(je);
+        } catch(RepositoryException re) {
+            reportException(re);
+        }
+    }
+    
+    /** Render a Property by dumping its String value */ 
+    private void renderProperty(Property p, SlingHttpServletResponse resp) throws JSONException, RepositoryException, IOException {
+        resp.setContentType(responseContentType);
+        new JsonItemWriter(null).dump(p, resp.getWriter());
+    }
+
+    /** Render synthetic resources as empty JSON objects */
+    private void renderSyntheticResource(SlingHttpServletRequest req,SlingHttpServletResponse resp) throws IOException {
+        resp.setContentType(responseContentType);
+        resp.getOutputStream().write("{}".getBytes());
+    }
+
+    private void reportException(Exception e) throws HttpStatusCodeException {
+        log.warn("Error in JsonRendererServlet: " + e.toString(),e);
+        throw new HttpStatusCodeException(
+                HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                e.toString(),
+                e
+        );
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/JsonRendererServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+package org.apache.sling.usling.renderers;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.servlet.ServletException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+
+/** A SlingSafeMethodsServlet that renders the current Resource
+ *  as plain text.
+ */
+public class PlainTextRendererServlet extends SlingSafeMethodsServlet {
+
+    private static final long serialVersionUID = -5815904221043005085L;
+    private final String responseContentType;
+
+    public PlainTextRendererServlet(String responseContentTypeHeaderValue) {
+        this.responseContentType = responseContentTypeHeaderValue;
+    }
+
+    @Override
+    protected void doGet(SlingHttpServletRequest req,SlingHttpServletResponse resp)
+    throws ServletException,IOException
+    {
+        final Resource  r = req.getResource();
+        /* TODO
+        if(srd != null) {
+            renderSyntheticResource(req, resp, srd);
+            return;
+        }
+        */
+        
+        resp.setContentType(responseContentType);
+        final PrintWriter pw = resp.getWriter();
+        try {
+            renderItem(pw, r);
+        } catch (RepositoryException re) {
+            throw new ServletException("Exception while rendering Resource " + req.getResource(), re);
+        }
+    }
+    
+    /** Render a Node or Property  */
+    private void renderItem(PrintWriter pw, Resource r) throws ServletException, RepositoryException {
+        Node n = null;
+        Property p = null;
+        
+        if ( (n = r.adaptTo(Node.class)) != null) {
+            dump(pw, r, n);
+            
+        } else if( (p = r.adaptTo(Property.class)) != null) {
+            dump(pw, r, p);
+            
+        } else {
+            throw new ServletException("Resource " + r + " does not adapt to a Node or a Property");
+        }
+    }
+
+    /** Render synthetic resource */ 
+    /* TODO
+    private void renderSyntheticResource(SlingHttpServletRequest req,SlingHttpServletResponse resp,SyntheticResourceData data) 
+    throws IOException {
+        resp.setContentType(responseContentType);
+        resp.getOutputStream().write(data.toString().getBytes());
+    }
+    */
+    
+    protected void dump(PrintWriter pw, Resource r, Node n) throws RepositoryException {
+        pw.println("** Node dumped by " + getClass().getSimpleName() + "**");
+        pw.println("Node path:" + n.getPath());
+        pw.println("Resource metadata: " + r.getResourceMetadata());
+
+        pw.println("\n** Node properties **");
+        for (PropertyIterator pi = n.getProperties(); pi.hasNext();) {
+            final Property p = pi.nextProperty();
+            printPropertyValue(pw, p, true);
+            pw.println();
+        }
+    }
+
+    protected void dump(PrintWriter pw, Resource r, Property p) throws RepositoryException {
+        printPropertyValue(pw, p, false);
+    }
+
+    protected void printPropertyValue(PrintWriter pw, Property p, boolean includeName)
+            throws RepositoryException {
+
+        if(includeName) {
+            pw.print(p.getName() + ": ");
+        }
+
+        if (p.getDefinition().isMultiple()) {
+            Value[] values = p.getValues();
+            pw.print('[');
+            for (int i = 0; i < values.length; i++) {
+                if (i > 0) {
+                    pw.print(", ");
+                }
+                pw.print(values[i].getString());
+            }
+            pw.print(']');
+        } else {
+            pw.print(p.getValue().getString());
+        }
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/renderers/PlainTextRendererServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java Mon Jan 14 07:04:53 2008
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+package org.apache.sling.usling.servlets;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.ujax.UjaxPostServlet;
+import org.apache.sling.usling.renderers.DefaultHtmlRendererServlet;
+import org.apache.sling.usling.renderers.JsonRendererServlet;
+import org.apache.sling.usling.renderers.PlainTextRendererServlet;
+
+/**
+ * Replaces the Sling default servlet (that bundle must NOT be
+ * active) for usling, by delegating to the default usling
+ * renderers for GET requests, and to the ujax POST servlet 
+ * for POST requests.
+ *
+ * @scr.service
+ *  interface="javax.servlet.Servlet"
+ *  
+ * @scr.component 
+ *  immediate="true" 
+ *  metatype="false"
+ *  
+ * @scr.property 
+ *  name="service.description"
+ *  value="usling default servlet"
+ *  
+ * @scr.property 
+ *  name="service.vendor" 
+ *  value="The Apache Software Foundation"
+ *
+ * Use this as the default servlet for Sling 
+ * @scr.property 
+ *  name="sling.core.resourceTypes" 
+ *  value="sling.core.servlet.default"
+ *  
+ */
+public class UslingDefaultServlet extends SlingAllMethodsServlet {
+    
+    private Servlet postServlet;
+    private Servlet defaultGetServlet;
+    private Map<String, Servlet> getServlets;
+    
+    @Override
+    public void init(ServletConfig config) throws ServletException {
+        
+        super.init(config);
+        
+        // setup our "internal" servlets
+        postServlet = new UjaxPostServlet();
+        postServlet.init(config);
+        
+        defaultGetServlet = new DefaultHtmlRendererServlet("text/html");
+        
+        getServlets = new HashMap<String, Servlet>();
+        getServlets.put("html", defaultGetServlet);
+        getServlets.put("json", new JsonRendererServlet("application/json"));
+        getServlets.put("txt", new PlainTextRendererServlet("text/plain"));
+    }
+
+    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException, ServletException {
+        final Resource resource = request.getResource();
+
+        // cannot handle the request for missing resources
+        if (resource instanceof NonExistingResource) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND,"Resource not found at path " + resource.getPath());
+            return;
+        }
+        
+        Servlet s = getServlets.get(request.getRequestPathInfo().getExtension());
+        if(s==null) {
+            s = defaultGetServlet;
+        }
+        s.service(request, response);
+    }
+
+
+    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) 
+    throws ServletException,IOException {
+        postServlet.service(request, response);
+    }
+}

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/usling/servlets/UslingDefaultServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Propchange: incubator/sling/trunk/usling/usling-webapp/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Jan 14 07:04:53 2008
@@ -4,3 +4,4 @@
 sling
 target
 .externalToolBuilders
+derby.log

Added: incubator/sling/trunk/usling/usling-webapp/README.txt
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-webapp/README.txt?rev=611825&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-webapp/README.txt (added)
+++ incubator/sling/trunk/usling/usling-webapp/README.txt Mon Jan 14 07:04:53 2008
@@ -0,0 +1,46 @@
+This webapp contains the necessary bundles to run usling.
+
+How to run this
+---------------
+
+1) Build all Sling bundles
+
+  cd <top of the Sling source code tree>
+  mvn clean install
+  
+2) Build the usling servlets
+
+  cd usling/usling-servlets
+  mvn clean install
+  cd -
+  
+3) Build and run this
+
+  cd usling
+  mvn clean package jetty:run
+  
+Once the webapp starts, http://localhost:8080/sling should display the Sling 
+web console.
+
+KNOWN PROBLEM: currently the org.apache.sling.jcr.jackrabbit.server bundle jar
+must be installed manually before running the tests shown below. For some reason 
+the bundle cannot be loaded automatically, see pom.xml
+
+Use the "install or update" button of http://localhost:8080/sling/list to load
+the bundle, and start it from that page.
+
+If the bundle is missing you'll get an error saying
+"No Repository available to SlingAuthenticator, cannot authenticate".
+
+4) Test node creation and display
+To create a node with curl:
+
+	 curl -D - -Ftitle=something http://admin:admin@localhost:8080/testing/this
+	 
+	 
+Then, http://admin:admin@localhost:8080/testing/this should display a default HTML
+representation, including the value of the "title" property.
+
+Add a txt or json extension to see other output formats.
+
+  	 	      

Propchange: incubator/sling/trunk/usling/usling-webapp/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/sling/trunk/usling/usling-webapp/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-webapp/pom.xml?rev=611825&r1=611824&r2=611825&view=diff
==============================================================================
--- incubator/sling/trunk/usling/usling-webapp/pom.xml (original)
+++ incubator/sling/trunk/usling/usling-webapp/pom.xml Mon Jan 14 07:04:53 2008
@@ -33,13 +33,14 @@
 
   <name>µsling Web Application</name>
   <description>
-    The µsling webapp packages the standard µsling components in a Sling
-    web application. See SLING-149. 
+    The µsling webapp packages the standard µsling components in a Sling web application. See SLING-149.
   </description>
 
   <scm>
     <connection>scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/usling/usling-webapp</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/usling/usling-webapp</developerConnection>
+    <developerConnection>
+      scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/usling/usling-webapp
+    </developerConnection>
     <url>http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-webapp</url>
   </scm>
 
@@ -58,29 +59,29 @@
   <build>
     <plugins>
 
-    <plugin>
-      <!-- 
-        The clean plugin deletes the sling work directory as well,
-        to avoid confusion with leftovers from previous runs
-      -->
-      <artifactId>maven-clean-plugin</artifactId>
-      <configuration>
-        <filesets>
-          <fileset>
-            <directory>sling</directory>
-          </fileset>
-        </filesets>
-      </configuration>
-    </plugin>
+      <plugin>
+        <!-- 
+          The clean plugin deletes the sling work directory as well,
+          to avoid confusion with leftovers from previous runs
+        -->
+        <artifactId>maven-clean-plugin</artifactId>
+        <configuration>
+          <filesets>
+            <fileset>
+              <directory>sling</directory>
+            </fileset>
+          </filesets>
+        </configuration>
+      </plugin>
 
-    <plugin>
+      <plugin>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>maven-jetty-plugin</artifactId>
         <version>6.1.5</version>
         <configuration>
           <contextPath>/</contextPath>
           <scanIntervalSeconds>${jetty.scan.interval.seconds}</scanIntervalSeconds>
-          
+
           <connectors>
             <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
               <port>8080</port>
@@ -88,7 +89,7 @@
               <port>${http.port}</port>
             </connector>
           </connectors>
-          
+
           <!-- 
             Use target/... as the webapp source, as we unpack stuff there from the
             Sling launcher modules
@@ -102,15 +103,15 @@
         <artifactId>maven-dependency-plugin</artifactId>
         <executions>
           <execution>
-            <!-- Unpack the sling-app launcher for inclusion in the web app -->
+            <!-- Unpack the sling-webapp launcher for inclusion in the web app -->
             <id>unpack-dependencies</id>
             <goals>
               <goal>unpack-dependencies</goal>
             </goals>
             <configuration>
-              <includeArtifactIds>org.apache.sling.launcher.app,servlet</includeArtifactIds>
+              <includeArtifactIds>org.apache.sling.launcher.webapp,servlet</includeArtifactIds>
               <excludeTransitive>true</excludeTransitive>
-              <outputDirectory>${project.build.directory}/launcher-app</outputDirectory>
+              <outputDirectory>${project.build.directory}/launcher-webapp</outputDirectory>
               <overWriteReleases>false</overWriteReleases>
               <overWriteSnapshots>true</overWriteSnapshots>
             </configuration>
@@ -122,17 +123,17 @@
               <goal>copy-dependencies</goal>
             </goals>
             <configuration>
-              <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/resources/bundles</outputDirectory>
+              <outputDirectory>
+                ${project.build.directory}/${project.build.finalName}/WEB-INF/resources/bundles
+              </outputDirectory>
               <excludeTransitive>true</excludeTransitive>
-              
-              <!-- List artifact names of bundles to install here -->
-              <includeArtifactIds>org.apache.sling.usling.servlets</includeArtifactIds>
+              <includeGroupIds>org.apache.felix,org.apache.sling</includeGroupIds>
             </configuration>
           </execution>
         </executions>
       </plugin>
 
-      <!-- Include sling-app launcher classes and resources -->
+      <!-- Include sling-webapp launcher classes and resources -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-war-plugin</artifactId>
@@ -140,7 +141,7 @@
           <webResources>
             <!-- the classes (except unneeded Main) -->
             <resource>
-              <directory>${basedir}/target/launcher-app</directory>
+              <directory>${basedir}/target/launcher-webapp</directory>
               <targetPath>WEB-INF/classes</targetPath>
               <excludes>
                 <exclude>org/apache/sling/launcher/app/main/**</exclude>
@@ -153,7 +154,7 @@
             </resource>
             <!-- the configuration resources -->
             <resource>
-              <directory>${basedir}/target/launcher-app</directory>
+              <directory>${basedir}/target/launcher-webapp</directory>
               <targetPath>WEB-INF</targetPath>
               <includes>
                 <include>resources/**</include>
@@ -169,7 +170,7 @@
           </webResources>
         </configuration>
       </plugin>
-      
+
     </plugins>
   </build>
 
@@ -194,12 +195,7 @@
       <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.launcher.webapp</artifactId>
       <version>2.0.0-incubator-SNAPSHOT</version>
-      <classifier>classes</classifier>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.sling</groupId>
-      <artifactId>org.apache.sling.launcher.app</artifactId>
-      <version>2.0.0-incubator-SNAPSHOT</version>
+      <type>war</type>
     </dependency>
     <dependency>
       <groupId>org.eclipse.equinox.http</groupId>
@@ -219,7 +215,111 @@
       <artifactId>org.apache.sling.usling.servlets</artifactId>
       <version>2.0.0-incubator-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.api</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.core</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.mime</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.api</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.resource</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.classloader</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.servlet.resolver</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.scripting.resolver</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.scripting.javascript</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+    <!--
+      TODO causes java.lang.ClassNotFoundException: org.apache.xerces.jaxp.SAXParserFactoryImpl
+      but works if started manually via the Sling web console 
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.jackrabbit.server</artifactId>
+      <version>2.0.0-incubator-SNAPSHOT</version>
+    </dependency>
+     -->
     
-  </dependencies>
+    <!--
+      Commons Dependencies provided by the Apache Felix project
+    -->
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.commons-io</artifactId>
+      <version>1.3.2-0002-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.commons-fileupload</artifactId>
+      <version>1.1.1-0001-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.commons-collections</artifactId>
+      <version>3.2.0-0001-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.commons-beanutils</artifactId>
+      <version>1.7.0-0001-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.commons-codec</artifactId>
+      <version>1.3.0-0001-SNAPSHOT</version>
+    </dependency>
 
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.jsp-api</artifactId>
+      <version>2.0.0-0001-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.commons-el</artifactId>
+      <version>1.0.0-0001-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.felix.commons</groupId>
+      <artifactId>org.apache.felix.commons.cglib-full</artifactId>
+      <version>2.0.2-0001-SNAPSHOT</version>
+    </dependency>
+
+  </dependencies>
 </project>



Mime
View raw message