You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2010/04/08 09:25:02 UTC

svn commit: r931805 - in /sling/trunk/bundles: api/src/main/java/org/apache/sling/api/servlets/ servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/hel...

Author: cziegeler
Date: Thu Apr  8 07:25:02 2010
New Revision: 931805

URL: http://svn.apache.org/viewvc?rev=931805&view=rev
Log:
SLING-585 : New functionality to resolve scripts by name

Added:
    sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java   (with props)
    sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java   (with props)
Modified:
    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/ServletResolver.java
    sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
    sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java
    sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/helper/LocationIteratorTest.java

Modified: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/ServletResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/ServletResolver.java?rev=931805&r1=931804&r2=931805&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/ServletResolver.java (original)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/ServletResolver.java Thu Apr  8 07:25:02 2010
@@ -21,6 +21,8 @@ package org.apache.sling.api.servlets;
 import javax.servlet.Servlet;
 
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
 
 /**
  * The <code>ServletResolver</code> defines the API for a service capable of
@@ -47,7 +49,7 @@ public interface ServletResolver {
      * implementing the {@link OptingServlet} interface and returning
      * <code>false</code> when the
      * {@link OptingServlet#accepts(SlingHttpServletRequest)} method is called.
-     * 
+     *
      * @param request The {@link SlingHttpServletRequest} object used to drive
      *            selection of the servlet.
      * @return The servlet whose <code>service</code> method may be called to
@@ -59,4 +61,59 @@ public interface ServletResolver {
      */
     Servlet resolveServlet(SlingHttpServletRequest request);
 
+    /**
+     * Resolves a <code>javax.servlet.Servlet</code> whose
+     * <code>service</code> method may be used to handle a request.
+     * <p>
+     * The returned servlet must be assumed to be initialized and ready to run.
+     * That is, the <code>init</code> nor the <code>destroy</code> methods
+     * must <em>NOT</em> be called on the returned servlet.
+     * <p>
+     * This method skips all {@link OptingServlet}s as there is no
+     * request object available.
+     *
+     * Basically this method searches a script with the <code>scriptName</code>
+     * for the resource type defined by the <code>resource</code>
+     * @param resource The {@link Resource} object used to drive
+     *            selection of the servlet.
+     * @param scriptName The name of the script - the script might have an
+     *                   extension. In this case only a script with the
+     *                   matching extension is used.
+     * @return The servlet whose <code>service</code> method may be called to
+     *         handle the request.
+     * @throws org.apache.sling.api.SlingException Is thrown if an error occurrs
+     *             while trying to find an appropriate servlet to handle the
+     *             request or if no servlet could be resolved to handle the
+     *             request.
+     * @since 2.1
+     */
+    Servlet resolveServlet(Resource resource, String scriptName);
+
+    /**
+     * Resolves a <code>javax.servlet.Servlet</code> whose
+     * <code>service</code> method may be used to handle a request.
+     * <p>
+     * The returned servlet must be assumed to be initialized and ready to run.
+     * That is, the <code>init</code> nor the <code>destroy</code> methods
+     * must <em>NOT</em> be called on the returned servlet.
+     * <p>
+     * This method skips all {@link OptingServlet}s as there is no
+     * request object available.
+     *
+     * Basically this method searches a script with the <code>scriptName</code>
+     * @param resolver The {@link ResourceResolver} object used to drive
+     *            selection of the servlet.
+     * @param scriptName The name of the script - the script might have an
+     *                   extension. In this case only a script with the
+     *                   matching extension is used.
+     * @return The servlet whose <code>service</code> method may be called to
+     *         handle the request.
+     * @throws org.apache.sling.api.SlingException Is thrown if an error occurrs
+     *             while trying to find an appropriate servlet to handle the
+     *             request or if no servlet could be resolved to handle the
+     *             request.
+     * @since 2.1
+     */
+    Servlet resolveServlet(ResourceResolver resolver, String scriptName);
+
 }

Modified: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java?rev=931805&r1=931804&r2=931805&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java (original)
+++ sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java Thu Apr  8 07:25:02 2010
@@ -68,6 +68,8 @@ import org.apache.sling.jcr.api.SlingRep
 import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
 import org.apache.sling.servlets.resolver.internal.defaults.DefaultErrorHandlerServlet;
 import org.apache.sling.servlets.resolver.internal.defaults.DefaultServlet;
+import org.apache.sling.servlets.resolver.internal.helper.AbstractResourceCollector;
+import org.apache.sling.servlets.resolver.internal.helper.NamedScriptResourceCollector;
 import org.apache.sling.servlets.resolver.internal.helper.ResourceCollector;
 import org.apache.sling.servlets.resolver.internal.helper.SlingServletConfig;
 import org.apache.sling.servlets.resolver.internal.resource.ServletResourceProvider;
@@ -187,7 +189,7 @@ public class SlingServletResolver implem
     // a request. This field is set on demand by getDefaultErrorServlet()
     private Servlet fallbackErrorServlet;
 
-    private Map<ResourceCollector, Servlet> cache;
+    private Map<AbstractResourceCollector, Servlet> cache;
 
     private ServiceRegistration eventHandlerReg;
 
@@ -263,7 +265,7 @@ public class SlingServletResolver implem
         // log the servlet found
         if (log.isDebugEnabled()) {
             if (servlet != null) {
-                log.info("Servlet {} found for resource={}", RequestUtil.getServletName(servlet), resource);
+                log.debug("Servlet {} found for resource={}", RequestUtil.getServletName(servlet), resource);
             } else {
                 log.debug("No servlet found for resource={}", resource);
             }
@@ -272,6 +274,86 @@ public class SlingServletResolver implem
         return servlet;
     }
 
+    /**
+     * @see org.apache.sling.api.servlets.ServletResolver#resolveServlet(org.apache.sling.api.resource.Resource, java.lang.String)
+     */
+    public Servlet resolveServlet(final Resource resource, final String scriptName) {
+        if ( resource == null ) {
+            throw new IllegalArgumentException("Resource must not be null");
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("resolveServlet called for resource {} with script name {}", resource, scriptName);
+        }
+
+        final Servlet servlet = resolveServlet(defaultScriptResolver, resource, scriptName);
+
+        // log the servlet found
+        if (log.isDebugEnabled()) {
+            if (servlet != null) {
+                log.debug("Servlet {} found for resource {} and script name {}", new Object[] {RequestUtil.getServletName(servlet), resource, scriptName});
+            } else {
+                log.debug("No servlet found for resource {} and script name {}", resource, scriptName);
+            }
+        }
+
+        return servlet;
+    }
+
+    /**
+     * @see org.apache.sling.api.servlets.ServletResolver#resolveServlet(org.apache.sling.api.resource.ResourceResolver, java.lang.String)
+     */
+    public Servlet resolveServlet(final ResourceResolver resolver, final String scriptName) {
+        if ( resolver == null ) {
+            throw new IllegalArgumentException("Resource resolver must not be null");
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("resolveServlet called for for script name {}", scriptName);
+        }
+
+        final Servlet servlet = resolveServlet(defaultScriptResolver, null, scriptName);
+
+        // log the servlet found
+        if (log.isDebugEnabled()) {
+            if (servlet != null) {
+                log.debug("Servlet {} found for script name {}", RequestUtil.getServletName(servlet), scriptName);
+            } else {
+                log.debug("No servlet found for script name {}", scriptName);
+            }
+        }
+
+        return servlet;
+    }
+
+    private Servlet resolveServlet(final ResourceResolver resolver,
+            final Resource resource,
+            final String scriptName) {
+        Servlet servlet = null;
+
+        // first check whether the type of a resource is the absolute
+        // path of a servlet (or script)
+        if (scriptName.charAt(0) == '/') {
+            final Resource res = resolver.getResource(scriptName);
+            if (res != null) {
+                servlet = res.adaptTo(Servlet.class);
+            }
+            if (servlet != null && log.isDebugEnabled()) {
+                log.debug("Servlet {} found using absolute resource type {}", RequestUtil.getServletName(servlet),
+                                scriptName);
+            }
+        }
+
+        // the resource type is not absolute, so lets go for the deep search
+        if (servlet == null) {
+            final NamedScriptResourceCollector locationUtil = NamedScriptResourceCollector.create(scriptName, resource);
+            servlet = getServlet(locationUtil, null, resolver);
+
+            if (log.isDebugEnabled()) {
+                log.debug("resolveServlet returns servlet {}", RequestUtil.getServletName(servlet));
+            }
+        }
+        return servlet;
+
+    }
     // ---------- ScriptResolver interface ------------------------------------
 
     public SlingScript findScript(ResourceResolver resourceResolver, String name) throws SlingException {
@@ -501,7 +583,8 @@ public class SlingServletResolver implem
      * @return a servlet for handling the request or <code>null</code> if no
      *         such servlet willing to handle the request could be found.
      */
-    private Servlet getServlet(final ResourceCollector locationUtil, final SlingHttpServletRequest request,
+    private Servlet getServlet(final AbstractResourceCollector locationUtil,
+            final SlingHttpServletRequest request,
             final ResourceResolver scriptResolver) {
         final Servlet scriptServlet = (this.cache != null ? this.cache.get(locationUtil) : null);
         if (scriptServlet != null) {
@@ -531,7 +614,7 @@ public class SlingServletResolver implem
             Servlet candidate = candidateResource.adaptTo(Servlet.class);
             if (candidate != null) {
                 final boolean isOptingServlet = candidate instanceof OptingServlet;
-                boolean servletAcceptsRequest = !isOptingServlet || ((OptingServlet) candidate).accepts(request);
+                boolean servletAcceptsRequest = !isOptingServlet || (request != null && ((OptingServlet) candidate).accepts(request));
                 if (servletAcceptsRequest) {
                     if (!hasOptingServlet && !isOptingServlet && this.cache != null) {
                         this.cache.put(locationUtil, candidate);
@@ -749,7 +832,7 @@ public class SlingServletResolver implem
         // create cache - if a cache size is configured
         final int cacheSize = OsgiUtil.toInteger(properties.get(PROP_CACHE_SIZE), DEFAULT_CACHE_SIZE);
         if (cacheSize > 5) {
-            this.cache = new ConcurrentHashMap<ResourceCollector, Servlet>(cacheSize);
+            this.cache = new ConcurrentHashMap<AbstractResourceCollector, Servlet>(cacheSize);
         }
         createAllServlets(refs);
 

Added: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java?rev=931805&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java (added)
+++ sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java Thu Apr  8 07:25:02 2010
@@ -0,0 +1,173 @@
+/*
+ * 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.servlets.resolver.internal.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.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+
+/**
+ * The <code>ResourceCollector</code> class provides a single public method -
+ * {@link #getServlets(ResourceResolver)} - which is used to find an ordered collection
+ * of <code>Resource</code> instances which may be used to find a servlet or
+ * script to handle a request to the given resource.
+ */
+public abstract class AbstractResourceCollector {
+
+    // the most generic resource type to use. This may be null in which
+    // case the default servlet name will be used as the base name
+    protected final String baseResourceType;
+
+    // the request extension or null if the request has no extension
+    protected final String extension;
+
+    protected int hashCode;
+
+    protected final String resourceType;
+
+    protected final String resourceSuperType;
+
+    public AbstractResourceCollector(final String baseResourceType,
+            final String resourceType,
+            final String resourceSuperType,
+            final String extension) {
+        this.baseResourceType = baseResourceType;
+        this.resourceType = resourceType;
+        this.resourceSuperType = resourceSuperType;
+        this.extension = extension;
+    }
+
+    public final Collection<Resource> getServlets(ResourceResolver resolver) {
+
+        final SortedSet<Resource> resources = new TreeSet<Resource>();
+        final Iterator<String> locations = new LocationIterator(resourceType, resourceSuperType,
+                                                                baseResourceType, resolver);
+        while (locations.hasNext()) {
+            final 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
+            final String path;
+            if ( location.endsWith("/") ) {
+                path = location.substring(0, location.length() - 1);
+            } else {
+                path = location;
+            }
+            final Resource locationRes = getResource(resolver, path);
+            getWeightedResources(resources, locationRes);
+        }
+
+        return resources;
+    }
+
+    abstract protected void getWeightedResources(final Set<Resource> resources,
+                                                 final Resource location);
+
+    /**
+     * Creates a {@link WeightedResource} and adds it to the set of resources.
+     * The number of resources already present in the set is used as the ordinal
+     * number for the newly created resource.
+     *
+     * @param resources The set of resource to which the
+     *            {@link WeightedResource} is added.
+     * @param resource The <code>Resource</code> on which the
+     *            {@link WeightedResource} is based.
+     * @param numSelectors The number of request selectors which are matched by
+     *            the name of the resource.
+     * @param methodPrefixWeight The method/prefix weight assigned to the
+     *            resource according to the resource name.
+     */
+    protected final void addWeightedResource(final Set<Resource> resources,
+            final Resource resource,
+            final int numSelectors,
+            final int methodPrefixWeight) {
+        final WeightedResource lr = new WeightedResource(resources.size(), resource,
+            numSelectors, methodPrefixWeight);
+        resources.add(lr);
+    }
+
+    /**
+     * Returns a resource for the given <code>path</code>.
+     * If no resource exists at the given path a
+     * <code>SyntheticResource</code> is returned.
+     *
+     * @param resolver The <code>ResourceResolver</code> used to access the
+     *            resource.
+     * @param path The absolute path of the resource to return.
+     * @return The actual resource at the given <code>path</code> or a
+     *         synthetic resource representing the path location.
+     */
+    protected final Resource getResource(final ResourceResolver resolver,
+                                         String path) {
+        Resource res = resolver.getResource(path);
+
+        if (res == null) {
+            if (!path.startsWith("/")) {
+                path = "/".concat(path);
+            }
+
+            res = new SyntheticResource(resolver, path, "$synthetic$");
+        }
+
+        return res;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if ( !(obj instanceof AbstractResourceCollector) ) {
+            return false;
+        }
+        if ( obj == this ) {
+            return true;
+        }
+        final AbstractResourceCollector o = (AbstractResourceCollector)obj;
+        if ( stringEquals(resourceType, o.resourceType)
+             && stringEquals(resourceSuperType, o.resourceSuperType)
+             && stringEquals(extension, o.extension)
+             && stringEquals(baseResourceType, o.baseResourceType)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.hashCode;
+    }
+
+    /**
+     * Helper method to compare two strings which can possibly be <code>null</code>
+     */
+    protected boolean stringEquals(final String s1, final String s2) {
+        if ( s1 == null && s2 == null ) {
+            return true;
+        }
+        if ( s1 == null || s2 == null ) {
+            return false;
+        }
+        return s1.equals(s2);
+    }
+}

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java?rev=931805&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java (added)
+++ sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java Thu Apr  8 07:25:02 2010
@@ -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.servlets.resolver.internal.helper;
+
+import java.util.Iterator;
+import java.util.Set;
+
+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.servlets.resolver.internal.ServletResolverConstants;
+
+/**
+ * The <code>ResourceCollector</code> class provides a single public method -
+ * {@link #getServlets(ResourceResolver)} - which is used to find an ordered collection
+ * of <code>Resource</code> instances which may be used to find a servlet or
+ * script to handle a request to the given resource.
+ */
+public class NamedScriptResourceCollector extends AbstractResourceCollector {
+
+    private final String scriptName;
+
+    public static NamedScriptResourceCollector create(final String name, final Resource resource) {
+        final String resourceType;
+        final String resourceSuperType;
+        final String baseResourceType;
+        final String extension;
+        final String scriptName;
+        if ( resource != null ) {
+            resourceType = resource.getResourceType();
+            resourceSuperType = resource.getResourceSuperType();
+            baseResourceType = ServletResolverConstants.DEFAULT_SERVLET_NAME;
+        } else {
+            resourceType = "";
+            resourceSuperType = null;
+            baseResourceType = "";
+        }
+        final int pos = name.indexOf('.');
+        if ( pos == -1 ) {
+            extension = null;
+            scriptName = name;
+        } else {
+            extension = name.substring(pos);
+            scriptName = name.substring(0, pos);
+        }
+        return new NamedScriptResourceCollector(baseResourceType,
+                resourceType,
+                resourceSuperType,
+                scriptName,
+                extension);
+    }
+
+    public NamedScriptResourceCollector(final String baseResourceType,
+                              final String resourceType,
+                              final String resourceSuperType,
+                              final String scriptName,
+                              final String extension) {
+        super(baseResourceType, resourceType, resourceSuperType, extension);
+        this.scriptName = scriptName;
+        // create the hash code once
+        final String key = baseResourceType + ':' + this.scriptName + ':' +
+            this.resourceType + ':' + (this.resourceSuperType == null ? "" : this.resourceSuperType) +
+            ':' + (this.extension == null ? "" : this.extension);
+        this.hashCode = key.hashCode();
+    }
+
+    protected void getWeightedResources(final Set<Resource> resources,
+                                        final Resource location) {
+        final ResourceResolver resolver = location.getResourceResolver();
+        // if extension is set, we just check the exact script
+        if ( this.extension != null ) {
+            final String path = location.getPath() + '/' + this.scriptName + this.extension;
+            final Resource current = resolver.getResource(path);
+            if ( current != null ) {
+                this.addWeightedResource(resources, current, 0, WeightedResource.WEIGHT_EXTENSION);
+            }
+        } else {
+            // if the script name denotes a path we have to get the denoted resource
+            // first
+            final Resource current;
+            final String name;
+            final int pos = this.scriptName.lastIndexOf('/');
+            if ( pos == -1 ) {
+                current = location;
+                name = this.scriptName;
+            } else {
+                current = getResource(resolver, location.getPath() + '/' + this.scriptName.substring(0, pos));
+                name = this.scriptName.substring(pos + 1);
+            }
+            final Iterator<Resource> children = resolver.listChildren(current);
+            while (children.hasNext()) {
+                final Resource child = children.next();
+
+                String scriptName = ResourceUtil.getName(child);
+                final int lastDot = scriptName.lastIndexOf('.');
+                if (lastDot < 0) {
+                    // no extension in the name, this is not a script
+                    continue;
+                }
+
+                scriptName = scriptName.substring(0, lastDot);
+
+                if ( scriptName.equals(name) ) {
+                    this.addWeightedResource(resources, child, 0, WeightedResource.WEIGHT_PREFIX);
+                    continue;
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if ( !(obj instanceof NamedScriptResourceCollector) ) {
+            return false;
+        }
+        if ( obj == this ) {
+            return true;
+        }
+        if ( super.equals(obj) ) {
+            final NamedScriptResourceCollector o = (NamedScriptResourceCollector)obj;
+            if ( stringEquals(scriptName, o.scriptName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java?rev=931805&r1=931804&r2=931805&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java (original)
+++ sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java Thu Apr  8 07:25:02 2010
@@ -18,18 +18,14 @@
  */
 package org.apache.sling.servlets.resolver.internal.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.request.RequestPathInfo;
 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.servlets.resolver.internal.ServletResolverConstants;
 import org.apache.sling.servlets.resolver.internal.resource.ServletResourceProviderFactory;
 
@@ -39,7 +35,7 @@ import org.apache.sling.servlets.resolve
  * of <code>Resource</code> instances which may be used to find a servlet or
  * script to handle a request to the given resource.
  */
-public class ResourceCollector {
+public class ResourceCollector extends AbstractResourceCollector {
 
     /**
      * The special value returned by
@@ -53,10 +49,6 @@ public class ResourceCollector {
     // the request method name used to indicate the script name
     private final String methodName;
 
-    // the most generic resource type to use. This may be null in which
-    // case the default servlet name will be used as the base name
-    private final String baseResourceType;
-
     // the request selectors as a string converted to a realtive path or
     // null if the request has no selectors
     private final String[] requestSelectors;
@@ -64,21 +56,12 @@ public class ResourceCollector {
     // the number of request selectors of the request or 0 if none
     private final int numRequestSelectors;
 
-    // the request extension or null if the request has no extension
-    private final String extension;
-
     // request is GET or HEAD
     private final boolean isGet;
 
     // request is GET or HEAD and extension is html
     private final boolean isHtml;
 
-    private final int hashCode;
-
-    private final String resourceType;
-
-    private final String resourceSuperType;
-
     private final String workspaceName;
 
     /**
@@ -113,15 +96,15 @@ public class ResourceCollector {
      * @param resource the resource to invoke, the resource type and resource super type are taken from this resource.
      */
     public ResourceCollector(String methodName, String baseResourceType, Resource resource, String workspaceName) {
+        super((baseResourceType != null ? baseResourceType : ServletResolverConstants.DEFAULT_SERVLET_NAME),
+                resource.getResourceType(),
+                resource.getResourceSuperType(),
+                null);
         this.methodName = methodName;
-        this.baseResourceType = (baseResourceType != null ? baseResourceType : ServletResolverConstants.DEFAULT_SERVLET_NAME);
         this.requestSelectors = new String[0];
         this.numRequestSelectors = 0;
-        this.extension = null;
         this.isGet = false;
         this.isHtml = false;
-        this.resourceType = resource.getResourceType();
-        this.resourceSuperType = resource.getResourceSuperType();
 
         this.workspaceName = workspaceName;
         // create the hash code once
@@ -145,16 +128,16 @@ public class ResourceCollector {
      *            is assumed.
      */
     private ResourceCollector(SlingHttpServletRequest request, String workspaceName) {
+        super(ServletResolverConstants.DEFAULT_SERVLET_NAME,
+                request.getResource().getResourceType(),
+                request.getResource().getResourceSuperType(),
+                request.getRequestPathInfo().getExtension());
         this.methodName = request.getMethod();
-        this.baseResourceType = ServletResolverConstants.DEFAULT_SERVLET_NAME;
-        this.resourceType = request.getResource().getResourceType();
-        this.resourceSuperType = request.getResource().getResourceSuperType();
 
         RequestPathInfo requestpaInfo = request.getRequestPathInfo();
 
         requestSelectors = requestpaInfo.getSelectors();
         numRequestSelectors = requestSelectors.length;
-        extension = request.getRequestPathInfo().getExtension();
 
         isGet = "GET".equals(methodName) || "HEAD".equals(methodName);
         isHtml = isGet && "html".equals(extension);
@@ -167,27 +150,8 @@ public class ResourceCollector {
         this.hashCode = key.hashCode();
     }
 
-    public final Collection<Resource> getServlets(ResourceResolver resolver) {
-
-        SortedSet<Resource> resources = new TreeSet<Resource>();
-
-        Iterator<String> locations = new LocationIterator(resourceType, resourceSuperType,
-            baseResourceType, resolver);
-        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(resolver, location);
-            getWeightedResources(resources, locationRes);
-        }
-
-        return resources;
-    }
-
-    protected void getWeightedResources(Set<Resource> resources,
-            Resource location) {
+    protected void getWeightedResources(final Set<Resource> resources,
+                                        Resource location) {
 
         ResourceResolver resolver = location.getResourceResolver();
         Resource current = location;
@@ -281,53 +245,6 @@ public class ResourceCollector {
         }
     }
 
-    /**
-     * Creates a {@link WeightedResource} and adds it to the set of resources.
-     * The number of resources already present in the set is used as the ordinal
-     * number for the newly created resource.
-     *
-     * @param resources The set of resource to which the
-     *            {@link WeightedResource} is added.
-     * @param resource The <code>Resource</code> on which the
-     *            {@link WeightedResource} is based.
-     * @param numSelectors The number of request selectors which are matched by
-     *            the name of the resource.
-     * @param methodPrefixWeight The method/prefix weight assigned to the
-     *            resource according to the resource name.
-     */
-    protected final void addWeightedResource(Set<Resource> resources,
-            Resource resource, int numSelectors, int methodPrefixWeight) {
-        WeightedResource lr = new WeightedResource(resources.size(), resource,
-            numSelectors, methodPrefixWeight);
-        resources.add(lr);
-    }
-
-    /**
-     * Returns a resource for the given <code>path</code>.
-     * If no resource exists at the given path a
-     * <code>SyntheticResource</code> is returned.
-     *
-     * @param resolver The <code>ResourceResolver</code> used to access the
-     *            resource.
-     * @param path The absolute path of the resource to return.
-     * @return The actual resource at the given <code>path</code> or a
-     *         synthetic resource representing the path location.
-     */
-    protected final Resource getResource(ResourceResolver resolver,
-            String path) {
-        Resource res = resolver.getResource(path);
-
-        if (res == null) {
-            if (!path.startsWith("/")) {
-                path = "/".concat(path);
-            }
-
-            res = new SyntheticResource(resolver, path, "$synthetic$");
-        }
-
-        return res;
-    }
-
     @Override
     public boolean equals(Object obj) {
         if ( !(obj instanceof ResourceCollector) ) {
@@ -336,42 +253,22 @@ public class ResourceCollector {
         if ( obj == this ) {
             return true;
         }
-        final ResourceCollector o = (ResourceCollector)obj;
-        if ( isGet == o.isGet
-             && isHtml == o.isHtml
-             && numRequestSelectors == o.numRequestSelectors
-             && stringEquals(resourceType, o.resourceType)
-             && stringEquals(resourceSuperType, o.resourceSuperType)
-             && stringEquals(extension, o.extension)
-             && stringEquals(baseResourceType, o.baseResourceType)
-             && stringEquals(methodName, o.methodName)
-             && stringEquals(workspaceName, o.workspaceName)) {
-            // now compare selectors
-            for(int i=0;i<numRequestSelectors;i++) {
-                if ( !stringEquals(requestSelectors[i], o.requestSelectors[i]) ) {
-                    return false;
+        if ( super.equals(obj) ) {
+            final ResourceCollector o = (ResourceCollector)obj;
+            if ( isGet == o.isGet
+                 && isHtml == o.isHtml
+                 && numRequestSelectors == o.numRequestSelectors
+                 && stringEquals(methodName, o.methodName)
+                 && stringEquals(workspaceName, o.workspaceName)) {
+                // now compare selectors
+                for(int i=0;i<numRequestSelectors;i++) {
+                    if ( !stringEquals(requestSelectors[i], o.requestSelectors[i]) ) {
+                        return false;
+                    }
                 }
+                return true;
             }
-            return true;
         }
         return false;
     }
-
-    @Override
-    public int hashCode() {
-        return this.hashCode;
-    }
-
-    /**
-     * Helper method to compare two strings which can possibly be <code>null</code>
-     */
-    private boolean stringEquals(final String s1, final String s2) {
-        if ( s1 == null && s2 == null ) {
-            return true;
-        }
-        if ( s1 == null || s2 == null ) {
-            return false;
-        }
-        return s1.equals(s2);
-    }
 }

Modified: sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/helper/LocationIteratorTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/helper/LocationIteratorTest.java?rev=931805&r1=931804&r2=931805&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/helper/LocationIteratorTest.java (original)
+++ sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/helper/LocationIteratorTest.java Thu Apr  8 07:25:02 2010
@@ -408,4 +408,61 @@ public class LocationIteratorTest extend
         // 6. finished
         assertFalse(li.hasNext());
     }
+
+    public void testScriptNameWithoutResourceType() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+        LocationIterator li = new LocationIterator("",
+                null,
+                "",
+                resourceResolver);
+        assertTrue(li.hasNext());
+        assertEquals("/apps/", li.next());
+        assertTrue(li.hasNext());
+        assertEquals("/libs/", li.next());
+        assertFalse(li.hasNext());
+    }
+
+    public void testScriptNameWithResourceType() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+        LocationIterator li = new LocationIterator("a/b",
+                null,
+                DEFAULT_SERVLET_NAME,
+                resourceResolver);
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/a/b", li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/a/b", li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        assertFalse(li.hasNext());
+    }
+
+    public void testScriptNameWithResourceTypeAndSuperType() {
+        String root0 = "/apps";
+        String root1 = "/libs";
+        resourceResolver.setSearchPath(root0, root1);
+        LocationIterator li = new LocationIterator("a/b",
+                "c/d",
+                DEFAULT_SERVLET_NAME,
+                resourceResolver);
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/a/b", li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/a/b", li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/c/d", li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/c/d", li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root0 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        assertTrue(li.hasNext());
+        assertEquals(root1 + "/" + DEFAULT_SERVLET_NAME, li.next());
+        assertFalse(li.hasNext());
+    }
 }