You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/05/05 09:26:00 UTC

svn commit: r653326 - in /incubator/sling/trunk: launchpad/webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ sling/servlet-resolver/ sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/ sling/servlet-resolver/sr...

Author: fmeschbe
Date: Mon May  5 00:26:00 2008
New Revision: 653326

URL: http://svn.apache.org/viewvc?rev=653326&view=rev
Log:
SLING-387 First stab at redoing servlet/script resolution process. This
still needs some code cleanup and tests for error handling
SLING-419 fix last reference of an integration test to HTML renderer

 Plus: Remove dependency to jcr/resource because the ResourceUtil is
       now part of the Sling API

Added:
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationIterator.java
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationResource.java
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtil.java
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtilGet.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationIteratorTest.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationResourceTest.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationTestBase.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilCreateLocationResourceTest.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilGetServletsTest.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResource.java
Modified:
    incubator/sling/trunk/launchpad/webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java
    incubator/sling/trunk/sling/servlet-resolver/pom.xml
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResource.java
    incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResourceProvider.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/SlingServletResolverTest.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockRequestPathInfo.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResourceResolver.java
    incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockSlingHttpServletRequest.java

Modified: incubator/sling/trunk/launchpad/webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/launchpad/webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java (original)
+++ incubator/sling/trunk/launchpad/webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java Mon May  5 00:26:00 2008
@@ -59,7 +59,7 @@
 
     public void testWithoutScriptHtml() throws IOException {
         final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
-        assertTrue("Content contains default rendering",content.contains("Node dumped by DefaultHtmlRenderer"));
+        assertTrue("Content contains default rendering",content.contains("Node dumped by HtmlRendererServlet"));
     }
 
     public void testEspHtml() throws IOException {
@@ -128,10 +128,10 @@
     }
 
     public void testEspHtmlWithSelectors() throws IOException {
+        testClient.mkdirs(WEBDAV_BASE_URL, scriptPath + "/a4");
         final String toDeleteA = uploadTestScript("rendering-test.esp","html.esp");
-        testClient.mkdirs(WEBDAV_BASE_URL, scriptPath + "/a4/print");
-        final String toDeleteB = uploadTestScript(scriptPath + "/a4","rendering-test-2.esp","html.esp");
-        final String toDeleteC = uploadTestScript(scriptPath + "/a4/print","rendering-test-3.esp","html.esp");
+        final String toDeleteB = uploadTestScript("rendering-test-2.esp","a4.esp");
+        final String toDeleteC = uploadTestScript("rendering-test-3.esp","a4/print.esp");
         
         try {
             String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);

Modified: incubator/sling/trunk/sling/servlet-resolver/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/pom.xml?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/pom.xml (original)
+++ incubator/sling/trunk/sling/servlet-resolver/pom.xml Mon May  5 00:26:00 2008
@@ -98,11 +98,6 @@
         </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.adapter</artifactId>
             <version>2.0.0-incubator-SNAPSHOT</version>
         </dependency>

Modified: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java Mon May  5 00:26:00 2008
@@ -22,7 +22,6 @@
 import static org.apache.sling.api.SlingConstants.ERROR_SERVLET_NAME;
 import static org.apache.sling.api.SlingConstants.ERROR_STATUS;
 import static org.apache.sling.core.CoreConstants.SLING_CURRENT_SERVLET_NAME;
-import static org.apache.sling.servlet.resolver.ServletResolverConstants.DEFAULT_SERVLET_NAME;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -51,14 +50,15 @@
 import org.apache.sling.api.scripting.SlingScript;
 import org.apache.sling.api.scripting.SlingScriptResolver;
 import org.apache.sling.api.servlets.HttpConstants;
-import org.apache.sling.api.servlets.ServletResolver;
 import org.apache.sling.api.servlets.OptingServlet;
+import org.apache.sling.api.servlets.ServletResolver;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.core.servlets.AbstractServiceReferenceConfig;
 import org.apache.sling.core.servlets.ErrorHandler;
-import org.apache.sling.jcr.resource.JcrResourceUtil;
 import org.apache.sling.servlet.resolver.defaults.DefaultErrorHandlerServlet;
 import org.apache.sling.servlet.resolver.defaults.DefaultServlet;
+import org.apache.sling.servlet.resolver.helper.LocationResource;
+import org.apache.sling.servlet.resolver.helper.LocationUtil;
 import org.apache.sling.servlet.resolver.helper.PathIterator;
 import org.apache.sling.servlet.resolver.helper.SlingServletConfig;
 import org.apache.sling.servlet.resolver.resource.ServletResourceProvider;
@@ -71,7 +71,7 @@
 
 /**
  * The <code>SlingServletResolver</code> TODO
- *
+ * 
  * @scr.component label="%servletresolver.name"
  *                description="%servletresolver.description"
  * @scr.property name="service.description" value="Sling Servlet Resolver and
@@ -121,65 +121,38 @@
 
     // ---------- ServletResolver interface -----------------------------------
 
-    /**
-     * @see org.apache.sling.api.servlets.ServletResolver#resolveServlet(org.apache.sling.api.SlingHttpServletRequest)
-     */
     public Servlet resolveServlet(SlingHttpServletRequest request) {
 
         Servlet servlet = null;
 
-        ResourceResolver resolver = request.getResourceResolver();
-        String[] path = resolver.getSearchPath();
-        String baseName = getScriptBaseName(request);
-
-        // (1) default script name and according to resource type and selectors
-        PathIterator pathIterator = new PathIterator(
-            request.getResource().getResourceType(),
-            request.getRequestPathInfo().getSelectorString(), path);
-        servlet = getServlet(resolver, pathIterator, baseName, request);
-
-        // (2) GET/HEAD and according to resource type and selectors
-        if (servlet == null && !baseName.equals(request.getMethod())) {
-            pathIterator.reset();
-            servlet = getServlet(resolver, pathIterator, request.getMethod(), request);
-        }
-
-        // (3) Repeate steps (1) and (2) for the super type hierarchy
-        if (servlet == null) {
-            String resourceSuperType = request.getResource().getResourceSuperType();
-            while (resourceSuperType != null && servlet == null) {
-
-                // (3a) default script name and according to resource type and selectors
-                pathIterator.reset(resourceSuperType);
-                servlet = getServlet(resolver, pathIterator, baseName, request);
-
-                // (3b) GET/HEAD and according to resource type and selectors
-                if (servlet == null && !baseName.equals(request.getMethod())) {
-                    pathIterator.reset();
-                    servlet = getServlet(resolver, pathIterator, request.getMethod(), request);
-                }
-
-                // the next supertype or null
-                if (servlet == null) {
-                    resourceSuperType = JcrResourceUtil.getResourceSuperType(
-                        resolver, resourceSuperType);
-                }
+        // first check whether the type of a resource is the absolute
+        // path of a servlet (or script)
+        String type = request.getResource().getResourceType();
+        if (type.charAt(0) == '/') {
+            Resource res = request.getResourceResolver().getResource(type);
+            if (res != null) {
+                servlet = res.adaptTo(Servlet.class);
             }
         }
-
-        // (4) default script name and default servlet name and selectors
+        
         if (servlet == null) {
-            pathIterator.reset(DEFAULT_SERVLET_NAME);
-            servlet = getServlet(resolver, pathIterator, baseName, request);
-
-            // (5) GET/HEAD and default servlet name and selectors
-            if (servlet == null && !baseName.equals(request.getMethod())) {
-                pathIterator.reset();
-                servlet = getServlet(resolver, pathIterator, request.getMethod(), request);
+            LocationUtil lu = LocationUtil.create(request);
+            Collection<LocationResource> candidates = lu.getScripts(request);
+            Iterator<LocationResource> lri = candidates.iterator();
+            while (lri.hasNext() && servlet == null) {
+                Resource candidateResource = lri.next().getResource();
+                Servlet candidate = candidateResource.adaptTo(Servlet.class);
+                if (candidate != null) {
+                    boolean servletAcceptsRequest = !(candidate instanceof OptingServlet)
+                        || ((OptingServlet) candidate).accepts(request);
+                    if (servletAcceptsRequest) {
+                        servlet = candidate;
+                    }
+                }
             }
         }
 
-        // (6) last resort, use the core bundle default servlet
+        // last resort, use the core bundle default servlet
         if (servlet == null) {
             servlet = getCoreDefaultServlet();
         }

Added: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationIterator.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationIterator.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationIterator.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationIterator.java Mon May  5 00:26:00 2008
@@ -0,0 +1,138 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+import org.apache.sling.servlet.resolver.ServletResolverConstants;
+
+public class LocationIterator implements Iterator<String> {
+
+    private final Resource resource;
+
+    private final ResourceResolver resolver;
+
+    private final String[] searchPath;
+
+    private String resourceType;
+
+    private String relPath;
+
+    private int pathCounter;
+
+    private String nextLocation;
+
+    public LocationIterator(SlingHttpServletRequest request) {
+        resource = request.getResource();
+        resolver = request.getResourceResolver();
+
+        String[] tmpPath = resolver.getSearchPath();
+        if (tmpPath == null || tmpPath.length == 0) {
+            tmpPath = new String[] { "/" };
+        } else {
+            for (int i=0; i< tmpPath.length; i++) {
+                if (!tmpPath[i].endsWith("/")) {
+                    tmpPath[i] = tmpPath[i].concat("/");
+                }
+            }
+        }
+        searchPath = tmpPath;
+
+        resourceType = resource.getResourceType();
+
+        nextLocation = seek();
+    }
+
+    public boolean hasNext() {
+        return nextLocation != null;
+    }
+
+    public String next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+
+        String result = nextLocation;
+        nextLocation = seek();
+        return result;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    private String seek() {
+
+        if (relPath == null) {
+
+            if (resourceType == null) {
+                return null;
+            }
+            
+            String typePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+            if (typePath.startsWith("/")) {
+                resourceType = getResourceSuperType();
+                return typePath;
+            }
+
+            relPath = typePath;
+        }
+
+        String result = searchPath[pathCounter].concat(relPath);
+
+        pathCounter++;
+        if (pathCounter >= searchPath.length) {
+            relPath = null;
+            resourceType = getResourceSuperType();
+            pathCounter = 0;
+        }
+
+        return result;
+    }
+
+    private String getResourceSuperType() {
+
+        // if the current resource type is the default value, there are no more
+        if (resourceType == ServletResolverConstants.DEFAULT_SERVLET_NAME) {
+            return null;
+        }
+
+        // get the super type of the current resource type
+        String superType;
+        if (resourceType == resource.getResourceType()) {
+            superType = resource.getResourceSuperType();
+        } else {
+            superType = JcrResourceUtil.getResourceSuperType(resolver,
+                resourceType);
+        }
+
+        // use default resource type if there is no super type any more
+        if (superType == null) {
+            superType = ServletResolverConstants.DEFAULT_SERVLET_NAME;
+        }
+
+        return superType;
+    }
+
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationResource.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationResource.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationResource.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationResource.java Mon May  5 00:26:00 2008
@@ -0,0 +1,104 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import org.apache.sling.api.resource.Resource;
+
+public class LocationResource implements Comparable<LocationResource> {
+
+    static final int WEIGHT_NONE = 0;
+
+    static final int WEIGHT_LAST_RESSORT = -1;
+
+    static final int WEIGHT_PREFIX = 1;
+
+    static final int WEIGHT_EXTENSION = 2;
+
+    private final int ordinal;
+
+    private final Resource resource;
+
+    private final int numSelectors;
+
+    private int methodPrefixWeight;
+
+    public LocationResource(int ordinal, Resource resource, int numSelectors,
+            int methodPrefixWeight) {
+        this.ordinal = ordinal;
+        this.resource = resource;
+        this.numSelectors = numSelectors;
+        this.methodPrefixWeight = methodPrefixWeight;
+    }
+
+    public int getOrdinal() {
+        return ordinal;
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+
+    public int getNumSelectors() {
+        return numSelectors;
+    }
+
+    public int getMethodPrefixWeight() {
+        return methodPrefixWeight;
+    }
+
+    @Override
+    public int hashCode() {
+        return ordinal;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return obj == this;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getOrdinal() + "]: "
+            + getResource() + ", #selectors=" + getNumSelectors()
+            + ", methodPrefixWeight=" + getMethodPrefixWeight();
+    }
+
+    public int compareTo(LocationResource o) {
+        if (equals(o)) {
+            return 0;
+        }
+
+        // compare by the number of selectors (more selectors wins)
+        if (numSelectors > o.numSelectors) {
+            return -1;
+        } else if (numSelectors < o.numSelectors) {
+            return 1;
+        }
+
+        // selectors are equal, check method/extension weight (higher wins)
+        if (methodPrefixWeight > o.methodPrefixWeight) {
+            return -1;
+        } else if (methodPrefixWeight < o.methodPrefixWeight) {
+            return 1;
+        }
+
+        // extensions are equal, compare ordinal (lower ordinal wins)
+        return (ordinal < o.ordinal) ? -1 : 1;
+    }
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtil.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtil.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtil.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtil.java Mon May  5 00:26:00 2008
@@ -0,0 +1,149 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.api.servlets.HttpConstants;
+
+public class LocationUtil {
+
+    private final ResourceResolver resolver;
+
+    private final String methodName;
+
+    public static LocationUtil create(SlingHttpServletRequest request) {
+        if (HttpConstants.METHOD_GET.equals(request.getMethod())
+            || HttpConstants.METHOD_HEAD.equals(request.getMethod())) {
+            return new LocationUtilGet(request);
+        }
+
+        return new LocationUtil(request);
+    }
+
+    protected LocationUtil(SlingHttpServletRequest request) {
+        resolver = request.getResourceResolver();
+        methodName = request.getMethod();
+    }
+
+    public Collection<LocationResource> getScripts(
+            SlingHttpServletRequest request) {
+
+        SortedSet<LocationResource> resources = new TreeSet<LocationResource>();
+
+        int ordinal = 0;
+
+        Iterator<String> locations = new LocationIterator(request);
+        while (locations.hasNext()) {
+            String location = locations.next();
+
+            // get the location resource, use a synthetic resource if there
+            // is no real location. There may still be children at this
+            // location
+            Resource locationRes = getResource(null, location);
+            ordinal = getLocationResources(ordinal, locationRes, resources);
+        }
+
+        return resources;
+    }
+
+    protected int getLocationResources(int ordinal, Resource location,
+            Set<LocationResource> resources) {
+
+        // now list the children and check them
+        Iterator<Resource> children = getResolver().listChildren(location);
+        while (children.hasNext()) {
+            Resource child = children.next();
+
+            String name = ResourceUtil.getName(child.getPath());
+            String[] parts = name.split("\\.");
+
+            // require method name plus script extension
+            if (parts.length == 2 && getMethodName().equals(parts[0])) {
+                LocationResource lr = new LocationResource(ordinal, child, 0,
+                    LocationResource.WEIGHT_NONE);
+                resources.add(lr);
+                ordinal++;
+            }
+        }
+        
+        // special treatment for servlets registered with neither a method
+        // name nor extensions and selectors
+        String path = location.getPath();
+        String label = ResourceUtil.getName(path);
+        location = getResource(null, ResourceUtil.getParent(path));
+        children = getResolver().listChildren(location);
+        while (children.hasNext()) {
+            Resource child = children.next();
+
+            String name = ResourceUtil.getName(child.getPath());
+            String[] parts = name.split("\\.");
+
+            // require base name plus script extension
+            if (parts.length == 2 && label.equals(parts[0])) {
+                LocationResource lr = new LocationResource(ordinal, child, 0,
+                    LocationResource.WEIGHT_LAST_RESSORT);
+                resources.add(lr);
+                ordinal++;
+            }
+        }
+
+        return ordinal;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    public ResourceResolver getResolver() {
+        return resolver;
+    }
+
+    protected Resource getResource(Resource base, String path) {
+        Resource res;
+        if (base == null) {
+            res = getResolver().getResource(path);
+        } else {
+            res = getResolver().getResource(base, path);
+        }
+
+        if (res == null) {
+            if (!path.startsWith("/")) {
+                if (base == null) {
+                    path = "/".concat(path);
+                } else {
+                    path = base.getPath() + "/" + path;
+                }
+            }
+
+            res = new SyntheticResource(resolver, path, "$synthetic$");
+        }
+
+        return res;
+    }
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtilGet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtilGet.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtilGet.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/helper/LocationUtilGet.java Mon May  5 00:26:00 2008
@@ -0,0 +1,176 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LocationUtilGet extends LocationUtil {
+
+    /** default log */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private final String selectors;
+
+    private final int numSelectors;
+
+    private final String extension;
+
+    private final boolean isGetHtmlRequest;
+
+    protected LocationUtilGet(SlingHttpServletRequest request) {
+        super(request);
+
+        selectors = request.getRequestPathInfo().getSelectorString();
+        numSelectors = request.getRequestPathInfo().getSelectors().length;
+        extension = request.getRequestPathInfo().getExtension();
+        isGetHtmlRequest = "html".equals(request.getRequestPathInfo().getExtension());
+    }
+
+    @Override
+    protected int getLocationResources(int ordinal, Resource location,
+            Set<LocationResource> resources) {
+
+        // print/a4.html.esp
+        // print.html.esp
+        if (selectors != null && selectors.length() > 0) {
+            String relString = selectors.replace('.', '/');
+            int numSelectors = this.numSelectors;
+            while (relString.length() > 0) {
+
+                String parent;
+                String name;
+                Resource loc;
+
+                int slash = relString.lastIndexOf('/');
+                if (slash > 0) {
+                    parent = relString.substring(0, slash);
+                    name = relString.substring(slash + 1);
+                    loc = getResource(location, parent);
+                } else {
+                    parent = "";
+                    name = relString;
+                    loc = location;
+                }
+
+                ordinal = getLocationResources(ordinal, loc, name, false,
+                    numSelectors, resources);
+                relString = parent;
+
+                numSelectors--;
+            }
+        }
+
+        // sample.html.esp
+        // sample.esp
+        // html.esp
+        ordinal = getLocationResources(ordinal, location,
+            ResourceUtil.getName(location.getPath()), true, 0, resources);
+
+        // base class implementation supporting the method name
+        return super.getLocationResources(ordinal, location, resources);
+    }
+
+    protected int getLocationResources(int ordinal, Resource location,
+            String locationPrefix, boolean optionalLocationPrefix,
+            int numSelectors, Set<LocationResource> resources) {
+
+        // now list the children and check them
+        Iterator<Resource> children = getResolver().listChildren(location);
+        while (children.hasNext()) {
+            Resource child = children.next();
+            LocationResource lr = createLocationResource(ordinal,
+                locationPrefix, optionalLocationPrefix, child, numSelectors);
+            if (lr != null) {
+                resources.add(lr);
+                ordinal++;
+            }
+        }
+
+        return ordinal;
+    }
+
+    protected LocationResource createLocationResource(int ordinal,
+            String locationPrefix, boolean optionalLocationPrefix,
+            Resource resource, int numSelectors) {
+
+        // split the remaing name to ease further checks
+        String resPath = resource.getPath();
+        String name = ResourceUtil.getName(resPath);
+        String[] parts = name.split("\\.");
+        int i = 0;
+
+        // flag whether we require the request extension in the script name
+        // to begin with, this is only required for non-html requests
+        boolean requireExtension = !isGetHtmlRequest;
+
+        int methodExtensionWeight = LocationResource.WEIGHT_NONE;
+        
+        // expect locationPrefix being the last part of the selector
+        if (i >= parts.length || !locationPrefix.equals(parts[i])) {
+            if (!optionalLocationPrefix) {
+                log.debug(
+                    "createLocationResource: Ignoring Resource {}: Name does not start with {}",
+                    resource, locationPrefix);
+                return null;
+            }
+
+            log.debug(
+                "createLocationResource: Resource {} does not start with {}",
+                resource, locationPrefix);
+
+            // flag that the request extension is required in the name
+            requireExtension = true;
+        } else {
+            // increment counter, we have the locationPrefix
+            i++;
+            methodExtensionWeight += LocationResource.WEIGHT_PREFIX;
+        }
+
+        // next may be extension name
+        boolean hasExtension = false;
+        if (extension != null) {
+            if (i < parts.length && extension.equals(parts[i])) {
+                i++;
+                methodExtensionWeight += LocationResource.WEIGHT_EXTENSION;
+            } else if (requireExtension) {
+                log.debug(
+                    "createLocationResource: Ignoring Resource {} because request extension {} is missing in the name",
+                    resource, extension);
+                return null;
+            }
+        }
+
+        // next would be script extension
+        if ((i + 1) != parts.length) {
+            // more than one more part, we expect just a single one or none
+            return null;
+        }
+
+        return new LocationResource(ordinal, resource, numSelectors,
+            methodExtensionWeight);
+    }
+
+}

Modified: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResource.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResource.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResource.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResource.java Mon May  5 00:26:00 2008
@@ -32,6 +32,8 @@
     private final Servlet servlet;
 
     private final String path;
+    
+    private final String resourceType;
 
     private final ResourceMetadata metadata;
 
@@ -40,7 +42,8 @@
         this.resourceResolver = resourceResolver;
         this.servlet = servlet;
         this.path = path;
-
+        this.resourceType = ServletResourceProvider.ensureServletNameExtension(path);
+        
         this.metadata = new ResourceMetadata();
         metadata.setResolutionPath(path);
     }
@@ -54,8 +57,7 @@
     }
 
     public String getResourceType() {
-        // the resource type of a servlet is the servlet's path
-        return path;
+        return resourceType;
     }
 
     /** Servlet Resources have no super type */

Modified: incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResourceProvider.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResourceProvider.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResourceProvider.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/resource/ServletResourceProvider.java Mon May  5 00:26:00 2008
@@ -24,11 +24,8 @@
 import static org.apache.sling.servlet.resolver.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES;
 import static org.apache.sling.servlet.resolver.ServletResolverConstants.SLING_SERVLET_SELECTORS;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Set;
 
 import javax.servlet.Servlet;
@@ -43,6 +40,8 @@
 
 public class ServletResourceProvider implements ResourceProvider {
 
+    public static final String SERVLET_PATH_EXTENSION = ".servlet";
+    
     private final Servlet servlet;
 
     private Set<String> resourcePaths;
@@ -53,13 +52,19 @@
         // check whether explicit paths are set
         String[] paths = OsgiUtil.toStringArray(ref.getProperty(SLING_SERVLET_PATHS));
         if (paths != null && paths.length > 0) {
-            for (int i = 0; i < paths.length; i++) {
-                if (!paths[i].startsWith("/")) {
-                    paths[i] = servletRoot + paths[i];
+          Set<String> pathSet = new HashSet<String>();
+          for (String path : paths) {
+                if (!path.startsWith("/")) {
+                    path = servletRoot.concat(path);
                 }
 
+                // add the unmodified path
+                pathSet.add(path);
+
+                // ensure we have another entry which has the .servlet ext.
+                pathSet.add(ensureServletNameExtension(path));
             }
-            return new ServletResourceProvider(paths, servlet);
+            return new ServletResourceProvider(pathSet, servlet);
         }
 
         // now, we fall back to resource types, extensions and methods
@@ -84,7 +89,7 @@
         // return null;
         // }
 
-        List<String> pathList = new ArrayList<String>();
+        Set<String> pathSet = new HashSet<String>();
         for (String type : types) {
 
             // ensure namespace prefixes are converted to slashes
@@ -105,7 +110,7 @@
 
                 String selPath = type;
                 if (selector != null && selector.length() > 0) {
-                    selPath += selector.replace('.', '/') + "/";
+                    selPath += selector.replace('.', '/') + ".";
                 }
 
                 boolean pathAdded = false;
@@ -113,7 +118,7 @@
                 // create paths with extensions
                 if (extensions != null) {
                     for (String ext : extensions) {
-                        pathList.add(selPath + ext);
+                        pathSet.add(selPath + ext + SERVLET_PATH_EXTENSION);
                         pathAdded = true;
                     }
                 }
@@ -121,25 +126,33 @@
                 // create paths with method names
                 if (methods != null) {
                     for (String method : methods) {
-                        pathList.add(selPath + method);
+                        pathSet.add(selPath + method + SERVLET_PATH_EXTENSION);
                         pathAdded = true;
                     }
                 }
 
                 // if neither methods nore extensions were added
                 if (!pathAdded) {
-                    pathList.add(selPath.substring(0, selPath.length() - 1));
+                    pathSet.add(selPath.substring(0, selPath.length() - 1)
+                        + SERVLET_PATH_EXTENSION);
                 }
             }
         }
 
-        paths = pathList.toArray(new String[pathList.size()]);
-        return new ServletResourceProvider(paths, servlet);
+        return new ServletResourceProvider(pathSet, servlet);
     }
 
-    private ServletResourceProvider(String[] paths, Servlet servlet) {
+    static String ensureServletNameExtension(String servletPath) {
+        if (servletPath.endsWith(SERVLET_PATH_EXTENSION)) {
+            return servletPath;
+        }
+        
+        return servletPath.concat(SERVLET_PATH_EXTENSION);
+    }
+    
+    private ServletResourceProvider(Set<String> resourcePaths, Servlet servlet) {
         this.servlet = servlet;
-        this.resourcePaths = new HashSet<String>(Arrays.asList(paths));
+        this.resourcePaths = resourcePaths;
     }
 
     public Resource getResource(ResourceResolver resourceResolver,
@@ -171,5 +184,4 @@
         return resourcePaths.toArray(new String[resourcePaths.size()]);
     }
 
-
 }

Modified: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/SlingServletResolverTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/SlingServletResolverTest.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/SlingServletResolverTest.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/SlingServletResolverTest.java Mon May  5 00:26:00 2008
@@ -18,16 +18,22 @@
  */
 package org.apache.sling.servlet.resolver;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.servlet.Servlet;
 import javax.servlet.http.HttpServlet;
 
 import junit.framework.TestCase;
 
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.servlets.OptingServlet;
 import org.apache.sling.core.CoreConstants;
 import org.apache.sling.servlet.resolver.mock.MockBundle;
 import org.apache.sling.servlet.resolver.mock.MockComponentContext;
+import org.apache.sling.servlet.resolver.mock.MockResource;
 import org.apache.sling.servlet.resolver.mock.MockResourceResolver;
 import org.apache.sling.servlet.resolver.mock.MockServiceReference;
 import org.apache.sling.servlet.resolver.mock.MockSlingHttpServletRequest;
@@ -45,7 +51,7 @@
 
     private static final String ROOT = "/";
 
-    private static final String SERVLET_EXTENSION = ".";
+    private static final String SERVLET_EXTENSION = "html";
 
     private MockResourceResolver mockResourceResolver;
 
@@ -70,15 +76,29 @@
         servletResolver.bindServlet(serviceReference);
         servletResolver.activate(mockComponentContext);
         mockResourceResolver = new MockResourceResolver();
-        mockResourceResolver.setSearchPath(new String[] { "/" });
-        mockResourceResolver.addResource("/"
-            + MockSlingHttpServletRequest.RESOURCE_TYPE,
-            new MockServletResource(mockResourceResolver, servlet, ROOT));
+        mockResourceResolver.setSearchPath("/");
+
+        String path = "/"
+            + MockSlingHttpServletRequest.RESOURCE_TYPE
+            + "/"
+            + ResourceUtil.getName(MockSlingHttpServletRequest.RESOURCE_TYPE)
+            + ".servlet";
+        MockServletResource res = new MockServletResource(mockResourceResolver,
+            servlet, path);
+        mockResourceResolver.addResource(res);
+
+        MockResource parent = new MockResource(mockResourceResolver,
+            ResourceUtil.getParent(res.getPath()), "nt:folder");
+        mockResourceResolver.addResource(parent);
+
+        List<Resource> childRes = new ArrayList<Resource>();
+        childRes.add(res);
+        mockResourceResolver.addChildren(parent, childRes);
     }
 
     public void testAcceptsRequest() {
         MockSlingHttpServletRequest secureRequest = new MockSlingHttpServletRequest(
-            SERVLET_PATH, "", SERVLET_EXTENSION, "", "");
+            SERVLET_PATH, null, SERVLET_EXTENSION, null, null);
         secureRequest.setResourceResolver(mockResourceResolver);
         secureRequest.setSecure(true);
         Servlet result = servletResolver.resolveServlet(secureRequest);
@@ -87,7 +107,7 @@
 
     public void testIgnoreRequest() {
         MockSlingHttpServletRequest insecureRequest = new MockSlingHttpServletRequest(
-            SERVLET_PATH, "", SERVLET_EXTENSION, "", "");
+            SERVLET_PATH, null, SERVLET_EXTENSION, null, null);
         insecureRequest.setResourceResolver(mockResourceResolver);
         insecureRequest.setSecure(false);
         Servlet result = servletResolver.resolveServlet(insecureRequest);

Added: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationIteratorTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationIteratorTest.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationIteratorTest.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationIteratorTest.java Mon May  5 00:26:00 2008
@@ -0,0 +1,362 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import static org.apache.sling.servlet.resolver.ServletResolverConstants.DEFAULT_SERVLET_NAME;
+
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+
+public class LocationIteratorTest extends LocationTestBase {
+
+    public void testSearchPathEmpty() {
+        // expect path gets { "/" }
+        resourceResolver.setSearchPath((String[]) null);
+        
+        LocationIterator li = new LocationIterator(request);
+        
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals("/" + resourceTypePath, li.next());
+        
+        // 2. /sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals("/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 3. finished
+        assertFalse(li.hasNext());
+    }
+    
+    public void testSearchPath1Element() {
+        String root0 = "/apps";
+        resourceResolver.setSearchPath(root0);
+        
+        LocationIterator li = new LocationIterator(request);
+        
+        // 1. /apps/foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceTypePath, li.next());
+        
+        // 2. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 3. finished
+        assertFalse(li.hasNext());
+    }
+    
+    public void testSearchPath2Elements() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+        
+        LocationIterator li = new LocationIterator(request);
+        
+        // 1. /apps/foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceTypePath, li.next());
+        
+        // 2. /libs/foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + resourceTypePath, li.next());
+        
+        // 3. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 4. /libs/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 5. finished
+        assertFalse(li.hasNext());
+    }
+    
+    public void testSearchPathEmptyAbsoluteType() {
+        // expect path gets { "/" }
+        resourceResolver.setSearchPath((String[]) null);
+        
+        // absolute resource type
+        resourceType = "/foo/bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+        resource.setResourceType(resourceType);
+        
+        LocationIterator li = new LocationIterator(request);
+        
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(resourceTypePath, li.next());
+        
+        // 2. /sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals("/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 3. finished
+        assertFalse(li.hasNext());
+    }
+    
+    public void testSearchPath1ElementAbsoluteType() {
+        String root0 = "/apps";
+        resourceResolver.setSearchPath(root0);
+        
+        // absolute resource type
+        resourceType = "/foo/bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+        resource.setResourceType(resourceType);
+        
+        LocationIterator li = new LocationIterator(request);
+        
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(resourceTypePath, li.next());
+        
+        // 2. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 3. finished
+        assertFalse(li.hasNext());
+    }
+    
+    public void testSearchPath2ElementsAbsoluteType() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+        
+        // absolute resource type
+        resourceType = "/foo/bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+        resource.setResourceType(resourceType);
+        
+        LocationIterator li = new LocationIterator(request);
+        
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(resourceTypePath, li.next());
+        
+        // 2. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 3. /libs/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        
+        // 4. finished
+        assertFalse(li.hasNext());
+    }
+
+    public void testSearchPathEmptyWithSuper() {
+        // expect path gets { "/" }
+        resourceResolver.setSearchPath((String[]) null);
+
+        // set resource super type
+        resourceSuperType = "foo:superBar";
+        resourceSuperTypePath = JcrResourceUtil.resourceTypeToPath(resourceSuperType);
+        resource.setResourceSuperType(resourceSuperType);
+        
+        LocationIterator li = new LocationIterator(request);
+
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals("/" + resourceTypePath, li.next());
+        
+        // 2. /foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals("/" + resourceSuperTypePath, li.next());
+
+        // 3. /sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals("/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 4. finished
+        assertFalse(li.hasNext());
+    }
+
+    public void testSearchPath1ElementWithSuper() {
+        String root0 = "/apps";
+        resourceResolver.setSearchPath(root0);
+
+        // set resource super type
+        resourceSuperType = "foo:superBar";
+        resourceSuperTypePath = JcrResourceUtil.resourceTypeToPath(resourceSuperType);
+        resource.setResourceSuperType(resourceSuperType);
+        
+        LocationIterator li = new LocationIterator(request);
+
+        // 1. /apps/foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceTypePath, li.next());
+
+        // 2. /apps/foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceSuperTypePath, li.next());
+
+        // 3. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 4. finished
+        assertFalse(li.hasNext());
+    }
+
+    public void testSearchPath2ElementsWithSuper() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+
+        // set resource super type
+        resourceSuperType = "foo:superBar";
+        resourceSuperTypePath = JcrResourceUtil.resourceTypeToPath(resourceSuperType);
+        resource.setResourceSuperType(resourceSuperType);
+        
+        LocationIterator li = new LocationIterator(request);
+
+        // 1. /apps/foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceTypePath, li.next());
+
+        // 2. /libs/foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + resourceTypePath, li.next());
+
+        // 3. /apps/foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceSuperTypePath, li.next());
+
+        // 4. /libs/foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + resourceSuperTypePath, li.next());
+
+        // 5. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 6. /libs/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 7. finished
+        assertFalse(li.hasNext());
+    }
+
+    public void testSearchPathEmptyAbsoluteTypeWithSuper() {
+        // expect path gets { "/" }
+        resourceResolver.setSearchPath((String[]) null);
+
+        // absolute resource type
+        resourceType = "/foo/bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+        resource.setResourceType(resourceType);
+
+        // set resource super type
+        resourceSuperType = "foo:superBar";
+        resourceSuperTypePath = JcrResourceUtil.resourceTypeToPath(resourceSuperType);
+        resource.setResourceSuperType(resourceSuperType);
+        
+        LocationIterator li = new LocationIterator(request);
+
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(resourceTypePath, li.next());
+
+        // 2. /foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals("/" + resourceSuperTypePath, li.next());
+
+        // 3. /sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals("/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 4. finished
+        assertFalse(li.hasNext());
+    }
+
+    public void testSearchPath1ElementAbsoluteTypeWithSuper() {
+        String root0 = "/apps";
+        resourceResolver.setSearchPath(root0);
+
+        // absolute resource type
+        resourceType = "/foo/bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+        resource.setResourceType(resourceType);
+
+        // set resource super type
+        resourceSuperType = "foo:superBar";
+        resourceSuperTypePath = JcrResourceUtil.resourceTypeToPath(resourceSuperType);
+        resource.setResourceSuperType(resourceSuperType);
+        
+        LocationIterator li = new LocationIterator(request);
+
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(resourceTypePath, li.next());
+
+        // 2. /apps/foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceSuperTypePath, li.next());
+
+        // 3. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 4. finished
+        assertFalse(li.hasNext());
+    }
+
+    public void testSearchPath2ElementsAbsoluteTypeWithSuper() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+
+        // absolute resource type
+        resourceType = "/foo/bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+        resource.setResourceType(resourceType);
+
+        // set resource super type
+        resourceSuperType = "foo:superBar";
+        resourceSuperTypePath = JcrResourceUtil.resourceTypeToPath(resourceSuperType);
+        resource.setResourceSuperType(resourceSuperType);
+        
+        LocationIterator li = new LocationIterator(request);
+
+        // 1. /foo/bar
+        assertTrue(li.hasNext());
+        assertEquals(resourceTypePath, li.next());
+
+        // 2. /apps/foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + resourceSuperTypePath, li.next());
+
+        // 3. /libs/foo/superBar
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + resourceSuperTypePath, li.next());
+
+        // 4. /apps/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 5. /libs/sling/servlet/default
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + DEFAULT_SERVLET_NAME, li.next());
+
+        // 6. finished
+        assertFalse(li.hasNext());
+    }
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationResourceTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationResourceTest.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationResourceTest.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationResourceTest.java Mon May  5 00:26:00 2008
@@ -0,0 +1,86 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import junit.framework.TestCase;
+
+public class LocationResourceTest extends TestCase {
+
+    public void testEquality() {
+        LocationResource lr1 = new LocationResource(0, null, 0, LocationResource.WEIGHT_NONE);
+        LocationResource lr2 = new LocationResource(0, null, 0, LocationResource.WEIGHT_NONE);
+        
+        // expect same objects to be equal
+        assertTrue(lr1.equals(lr1));
+        
+        // expect different instances to not be equal
+        assertFalse(lr1.equals(lr2));
+        assertFalse(lr2.equals(lr1));
+        assertFalse(lr1.equals(null));
+        assertFalse(lr2.equals(null));
+    }
+    
+    public void testCompareToSelectors() {
+        LocationResource lr1 = new LocationResource(0, null, 1, LocationResource.WEIGHT_NONE);
+        LocationResource lr2 = new LocationResource(1, null, 0, LocationResource.WEIGHT_NONE);
+        
+        // expect the same objects to compare equal
+        assertEquals(0, lr1.compareTo(lr1));
+        assertEquals(0, lr2.compareTo(lr2));
+        
+        assertTrue(lr1.compareTo(lr2) < 0);
+        assertTrue(lr2.compareTo(lr1) > 0);
+    }
+    
+    public void testCompareToPrefix() {
+        LocationResource lr1 = new LocationResource(0, null, 2, LocationResource.WEIGHT_PREFIX);
+        LocationResource lr2 = new LocationResource(1, null, 2, LocationResource.WEIGHT_NONE);
+        
+        // expect the same objects to compare equal
+        assertEquals(0, lr1.compareTo(lr1));
+        assertEquals(0, lr2.compareTo(lr2));
+        
+        assertTrue(lr1.compareTo(lr2) < 0);
+        assertTrue(lr2.compareTo(lr1) > 0);
+    }
+    
+    public void testCompareToExtension() {
+        LocationResource lr1 = new LocationResource(0, null, 2, LocationResource.WEIGHT_EXTENSION);
+        LocationResource lr2 = new LocationResource(1, null, 2, LocationResource.WEIGHT_NONE);
+        
+        // expect the same objects to compare equal
+        assertEquals(0, lr1.compareTo(lr1));
+        assertEquals(0, lr2.compareTo(lr2));
+        
+        assertTrue(lr1.compareTo(lr2) < 0);
+        assertTrue(lr2.compareTo(lr1) > 0);
+    }
+ 
+    public void testCompareToOrdinal() {
+        LocationResource lr1 = new LocationResource(0, null, 0, LocationResource.WEIGHT_NONE);
+        LocationResource lr2 = new LocationResource(1, null, 0, LocationResource.WEIGHT_NONE);
+        
+        // expect the same objects to compare equal
+        assertEquals(0, lr1.compareTo(lr1));
+        assertEquals(0, lr2.compareTo(lr2));
+        
+        assertTrue(lr1.compareTo(lr2) < 0);
+        assertTrue(lr2.compareTo(lr1) > 0);
+    }
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationTestBase.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationTestBase.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationTestBase.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationTestBase.java Mon May  5 00:26:00 2008
@@ -0,0 +1,76 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import junit.framework.TestCase;
+
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+import org.apache.sling.servlet.resolver.mock.MockResource;
+import org.apache.sling.servlet.resolver.mock.MockResourceResolver;
+import org.apache.sling.servlet.resolver.mock.MockSlingHttpServletRequest;
+
+public abstract class LocationTestBase extends TestCase {
+
+    protected MockResourceResolver resourceResolver;
+
+    protected MockSlingHttpServletRequest request;
+
+    protected MockResource resource;
+
+    protected String resourcePath;
+
+    protected String resourceType;
+
+    protected String resourceTypePath;
+
+    protected String resourceSuperType;
+
+    protected String resourceSuperTypePath;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        resourceResolver = new MockResourceResolver();
+        resourceResolver.setSearchPath("/apps", "/libs");
+
+        resourceType = "foo:bar";
+        resourceTypePath = JcrResourceUtil.resourceTypeToPath(resourceType);
+
+        resourcePath = "/content/page";
+        resource = new MockResource(resourceResolver, resourcePath,
+            resourceType);
+        resourceResolver.addResource(resource);
+
+        request = new MockSlingHttpServletRequest(resourcePath, "print.a4",
+            "html", null, null);
+        request.setResourceResolver(resourceResolver);
+        request.setResource(resource);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        resourceResolver = null;
+        request = null;
+        resource = null;
+    }
+    
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilCreateLocationResourceTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilCreateLocationResourceTest.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilCreateLocationResourceTest.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilCreateLocationResourceTest.java Mon May  5 00:26:00 2008
@@ -0,0 +1,155 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import junit.framework.TestCase;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.servlet.resolver.mock.MockResource;
+import org.apache.sling.servlet.resolver.mock.MockSlingHttpServletRequest;
+
+public class LocationUtilCreateLocationResourceTest extends TestCase {
+
+    private static final String LOCATION_NAME = "sample";
+
+    private static final String LOCATION_PREFIX = LOCATION_NAME;
+
+    private static final String LOCATION = "/apps/sling/" + LOCATION_NAME;
+
+    private static final String SCRIPT_BASE = LOCATION + "/" + LOCATION_NAME;
+
+    private static final String SCRIPT_BASE_INVALID = LOCATION + "/invalid";
+
+    public void testCreateLocationResourceGET() {
+
+        final MockResource res0 = new MockResource(null, SCRIPT_BASE, "foo:bar");
+
+        // this resource has no extension, we require one
+        final LocationResource lr0 = createLocationResource(res0, "GET", null,
+            "html");
+        assertNull(lr0);
+
+        // this resource has no extension, we require one
+        final LocationResource lr1 = createLocationResource(res0, "GET", null,
+            "foo");
+        assertNull(lr1);
+    }
+
+    public void testCreateLocationResourceGETEsp() {
+
+        final MockResource res1 = new MockResource(null, SCRIPT_BASE + ".esp",
+            "foo:bar");
+
+        // allow simple name for GET and html
+        final LocationResource lr10 = createLocationResource(res1, "GET", null,
+            "html");
+        assertNotNull(lr10);
+        assertEquals(0, lr10.getNumSelectors());
+        assertEquals(LocationResource.WEIGHT_PREFIX, lr10.getMethodPrefixWeight());
+
+        // this resource has no extension, we require one
+        final LocationResource lr11 = createLocationResource(res1, "GET", null,
+            "foo");
+        assertNull(lr11);
+    }
+
+    public void testCreateLocationResourceGETHtmlEsp() {
+        final MockResource res2 = new MockResource(null, SCRIPT_BASE
+            + ".html.esp", "foo:bar");
+
+        // allow simple name for GET and html
+        final LocationResource lr20 = createLocationResource(res2, "GET", null,
+            "html");
+        assertNotNull(lr20);
+        assertEquals(0, lr20.getNumSelectors());
+        assertEquals(LocationResource.WEIGHT_PREFIX+LocationResource.WEIGHT_EXTENSION, lr20.getMethodPrefixWeight());
+
+        // script does not match for .foo request
+        final LocationResource lr21 = createLocationResource(res2, "GET", null,
+            "foo");
+        assertNull(lr21);
+    }
+
+    public void testCreateLocationResourceGETFooEsp() {
+        final MockResource res3 = new MockResource(null, SCRIPT_BASE
+            + ".foo.esp", "foo:bar");
+
+        // script does not match for .html request
+        final LocationResource lr30 = createLocationResource(res3, "GET", null,
+            "html");
+        assertNull(lr30);
+
+        // allow simple name for GET and foo
+        final LocationResource lr31 = createLocationResource(res3, "GET", null,
+            "foo");
+        assertNotNull(lr31);
+        assertEquals(0, lr31.getNumSelectors());
+        assertEquals(LocationResource.WEIGHT_PREFIX+LocationResource.WEIGHT_EXTENSION, lr31.getMethodPrefixWeight());
+    }
+
+    public void testCreateLocationResourceGETGET() {
+
+        final MockResource res0 = new MockResource(null, SCRIPT_BASE + ".GET",
+            "foo:bar");
+
+        // side-effect: .GET is assumed to be the script extension
+        final LocationResource lr0 = createLocationResource(res0, "GET", null,
+            "html");
+        assertNotNull(lr0);
+        assertEquals(LocationResource.WEIGHT_PREFIX, lr0.getMethodPrefixWeight());
+
+        // this resource has no extension, we require one
+        final LocationResource lr1 = createLocationResource(res0, "GET", null,
+            "foo");
+        assertNull(lr1);
+    }
+
+    public void testCreateLocationResourceGETGETEsp() {
+        final MockResource res1 = new MockResource(null, SCRIPT_BASE
+            + ".GET.esp", "foo:bar");
+
+        // GET would be the extension and is not allowed like this
+        final LocationResource lr10 = createLocationResource(res1, "GET", null,
+            "html");
+        assertNull(lr10);
+
+        // GET would be the extension and is not allowed like this
+        final LocationResource lr11 = createLocationResource(res1, "GET", null,
+            "foo");
+        assertNull(lr11);
+    }
+
+    private LocationResource createLocationResource(
+            final Resource scriptResource, final String method,
+            final String selectorString, final String extension) {
+
+        final SlingHttpServletRequest request = new MockSlingHttpServletRequest(
+            "", selectorString, extension, null, null) {
+            @Override
+            public String getMethod() {
+                return method;
+            }
+        };
+        final LocationUtilGet locationUtil = new LocationUtilGet(request);
+        return locationUtil.createLocationResource(0, LOCATION_PREFIX, true,
+            scriptResource, 0);
+
+    }
+}

Added: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilGetServletsTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilGetServletsTest.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilGetServletsTest.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/helper/LocationUtilGetServletsTest.java Mon May  5 00:26:00 2008
@@ -0,0 +1,150 @@
+/*
+ * 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.servlet.resolver.helper;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.servlet.resolver.mock.MockResource;
+
+public class LocationUtilGetServletsTest extends LocationTestBase {
+
+    private String label;
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        label = ResourceUtil.getName(resourceTypePath);
+    }
+    
+    public void testGetServlets0() {
+        String[] names = { "/" + label + ".esp", // 0
+                "/GET.esp", // 1
+                "/" + label + ".html.esp", // 2
+                "/html.esp", // 3
+                "/print.esp", // 4
+                "/print/a4.esp", // 5
+                "/print.html.esp", // 6
+                "/print/a4.html.esp", // 7
+        };
+        
+        int[] baseIdxs = { 0, 1, 1, 0, 0, 1, 0, 1 };
+        int[] indices  = { 7, 5, 6, 4, 2, 3, 0, 1 };
+        
+        effectiveTest(names, baseIdxs, indices);
+    }
+    
+    public void testGetServlets1() {
+        String[] names = { "/" + label + ".esp", // 0
+                "/GET.esp", // 1
+                "/" + label + ".html.esp", // 2
+                "/print.esp", // 3
+                "/print.other.esp", // 4
+                "/print/other.esp", // 5
+                "/print.html.esp", // 6
+                "/print/a4.html.esp", // 7
+        };
+        
+        int[] baseIdxs = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
+        int[] indices = { 7, 6, 3, 2, 0, 1 };
+        
+        effectiveTest(names, baseIdxs, indices);
+    }
+    
+    public void testGetServlets2() {
+        String[] names = { "/" + label + ".esp", // 0
+                "/GET.esp", // 1
+                "/" + label + ".html.esp", // 2
+                "/html.esp", // 3
+                "/image.esp", // 4
+                "/print/other.esp", // 5
+                "/print.other.esp", // 6
+                "/print.html.esp", // 7
+                "/print/a4.html.esp", // 8
+        };
+        
+        int[] baseIdxs = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
+        int[] indices = { 8, 7, 2, 3, 0, 1 };
+        
+        effectiveTest(names, baseIdxs, indices);
+    }
+    
+    public void testGetServlets3() {
+        String[] names = { ".servlet", // 0
+                "/" + label + ".esp", // 1
+                "/GET.esp", // 2
+                "/" + label + ".html.esp", // 3
+                "/html.esp", // 4
+                "/image.esp", // 5
+                "/print/other.esp", // 6
+                "/print.other.esp", // 7
+                "/print.html.esp", // 8
+                "/print/a4.html.esp", // 9
+        };
+        
+        int[] baseIdxs = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
+        int[] indices = { 9, 8, 3, 4, 1, 2, 0 };
+        
+        effectiveTest(names, baseIdxs, indices);
+    }
+    
+    protected void effectiveTest(String[] names, int[] baseIdxs, int[] indices) {
+
+        String[] base = { "/apps/" + resourceTypePath,
+            "/libs/" + resourceTypePath };
+
+        @SuppressWarnings("unchecked")
+        Map<String, String> pathMap = new HashMap<String, String>();
+
+        for (int i=0; i < names.length; i++) {
+            String name = names[i];
+            int baseIdx = baseIdxs[i];
+            String path = base[baseIdx] + name;
+            createScriptResource(path, "nt:file");
+            pathMap.put(name, path);
+        }
+        
+        LocationUtil lu = LocationUtil.create(request);
+        Collection<LocationResource> res = lu.getScripts(request);
+        Iterator<LocationResource> rIter = res.iterator();
+
+        for (int index : indices) {
+            assertTrue(rIter.hasNext());
+
+            LocationResource lr = rIter.next();
+
+            String name = names[index];
+            String path = pathMap.get(name);
+
+            assertEquals(path, lr.getResource().getPath());
+        }
+
+        assertFalse(rIter.hasNext());
+    }
+
+    protected MockResource createScriptResource(String path, String type) {
+        MockResource res = new MockResource(resourceResolver, path, type);
+        resourceResolver.addResource(res);
+        return res;
+    }
+}

Modified: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockRequestPathInfo.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockRequestPathInfo.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockRequestPathInfo.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockRequestPathInfo.java Mon May  5 00:26:00 2008
@@ -48,7 +48,7 @@
 
     public String[] getSelectors() {
         return (getSelectorString() != null)
-                ? getSelectorString().split(".")
+                ? getSelectorString().split("\\.")
                 : new String[0];
     }
 

Added: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResource.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResource.java?rev=653326&view=auto
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResource.java (added)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResource.java Mon May  5 00:26:00 2008
@@ -0,0 +1,60 @@
+/*
+ * 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.servlet.resolver.mock;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+
+public class MockResource extends SyntheticResource {
+
+    private String resourceType;
+    private String resourceSuperType;
+    
+    public MockResource(ResourceResolver resourceResolver, String path,
+            String resourceType) {
+        this(resourceResolver, path, resourceType, null);
+    }
+    
+    public MockResource(ResourceResolver resourceResolver, String path,
+            String resourceType, String resourceSuperType) {
+        super(resourceResolver, path, resourceType);
+        
+        setResourceType(resourceType);
+        setResourceSuperType(resourceSuperType);
+    }
+
+    @Override
+    public String getResourceType() {
+        return resourceType;
+    }
+    
+    @Override
+    public void setResourceType(String resourceType) {
+        this.resourceType = resourceType;
+    }
+    
+    @Override
+    public String getResourceSuperType() {
+        return resourceSuperType;
+    }
+    
+    public void setResourceSuperType(String resourceSuperType) {
+        this.resourceSuperType = resourceSuperType;
+    }
+}

Modified: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResourceResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResourceResolver.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResourceResolver.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockResourceResolver.java Mon May  5 00:26:00 2008
@@ -18,9 +18,11 @@
  */
 package org.apache.sling.servlet.resolver.mock;
 
-import java.util.HashMap;
+import java.util.Collection;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.NoSuchElementException;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -31,10 +33,16 @@
 
     private String[] searchPath;
 
-    private HashMap<String, Resource> resources = new HashMap<String, Resource>();
+    private Map<String, Resource> resources = new LinkedHashMap<String, Resource>();
 
-    public void addResource(String path, Resource resource) {
-        this.resources.put(path, resource);
+    private Map<String, Collection<Resource>> children = new LinkedHashMap<String, Collection<Resource>>();
+
+    public void addResource(Resource resource) {
+        this.resources.put(resource.getPath(), resource);
+    }
+
+    public void addChildren(Resource parent, Collection<Resource> children) {
+        this.children.put(parent.getPath(), children);
     }
 
     public Resource resolve(HttpServletRequest request) {
@@ -57,8 +65,10 @@
     }
 
     public Resource getResource(Resource base, String path) {
-        throw new UnsupportedOperationException("Not implemented");
-
+        if (!path.startsWith("/")) {
+            path = base.getPath() + "/" + path;
+        }
+        return getResource(path);
     }
 
     public String[] getSearchPath() {
@@ -67,19 +77,47 @@
 
     }
 
-    public Iterator<Resource> listChildren(Resource parent) {
+    public Iterator<Resource> listChildren(final Resource parent) {
+        Collection<Resource> childCollection = children.get(parent.getPath());
+        if (childCollection != null) {
+            return childCollection.iterator();
+        }
+
         return new Iterator<Resource>() {
+            final String parentPath = parent.getPath() + "/";
 
-            public boolean hasNext() {
-                return false;
+            final Iterator<Resource> elements = resources.values().iterator();
 
+            Resource nextResource = seek();
+
+            public boolean hasNext() {
+                return nextResource != null;
             }
 
             public Resource next() {
-                return null;
+                if (!hasNext()) {
+                    throw new NoSuchElementException();
+                }
+
+                Resource result = nextResource;
+                nextResource = seek();
+                return result;
             }
 
             public void remove() {
+                throw new UnsupportedOperationException();
+            }
+
+            private Resource seek() {
+                while (elements.hasNext()) {
+                    Resource next = elements.next();
+                    String path = next.getPath();
+                    if (path.startsWith(parentPath)
+                        && path.indexOf('/', parentPath.length()) < 0) {
+                        return next;
+                    }
+                }
+                return null;
             }
         };
     }
@@ -100,7 +138,7 @@
 
     }
 
-    public void setSearchPath(String[] searchPath) {
+    public void setSearchPath(String... searchPath) {
         this.searchPath = searchPath;
     }
 }

Modified: incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockSlingHttpServletRequest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockSlingHttpServletRequest.java?rev=653326&r1=653325&r2=653326&view=diff
==============================================================================
--- incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockSlingHttpServletRequest.java (original)
+++ incubator/sling/trunk/sling/servlet-resolver/src/test/java/org/apache/sling/servlet/resolver/mock/MockSlingHttpServletRequest.java Mon May  5 00:26:00 2008
@@ -47,8 +47,10 @@
  */
 public class MockSlingHttpServletRequest implements SlingHttpServletRequest {
 
-    private final Resource resource;
+    private Resource resource;
 
+    private String method;
+    
     private final RequestPathInfo requestPathInfo;
 
     private final String queryString;
@@ -57,8 +59,6 @@
 
     private MockResourceResolver mockResourceResolver;
 
-    private static final String METHOD = "GET";
-
     public static final String RESOURCE_TYPE = "foo/bar";
 
     MockSlingHttpServletRequest() {
@@ -71,16 +71,26 @@
         this.requestPathInfo = new MockRequestPathInfo(selectors, extension,
             suffix);
         this.queryString = queryString;
+        
+        setMethod(null);
     }
 
     public void setResourceResolver(MockResourceResolver resolver) {
         this.mockResourceResolver = resolver;
     }
-
+    
+    public void setResource(Resource resource) {
+        this.resource = resource;
+    }
+    
     public void setSecure(boolean secure) {
         this.secure = secure;
     }
 
+    public void setMethod(String method) {
+        this.method = (method == null) ? "GET" : method.toUpperCase();
+    }
+    
     public Cookie getCookie(String name) {
         return null;
     }
@@ -176,7 +186,7 @@
     }
 
     public String getMethod() {
-        return METHOD;
+        return method;
     }
 
     public String getPathInfo() {