Return-Path: Delivered-To: apmail-incubator-sling-commits-archive@minotaur.apache.org Received: (qmail 26214 invoked from network); 15 Apr 2009 08:35:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 15 Apr 2009 08:35:26 -0000 Received: (qmail 56528 invoked by uid 500); 15 Apr 2009 08:35:26 -0000 Delivered-To: apmail-incubator-sling-commits-archive@incubator.apache.org Received: (qmail 56468 invoked by uid 500); 15 Apr 2009 08:35:25 -0000 Mailing-List: contact sling-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sling-dev@incubator.apache.org Delivered-To: mailing list sling-commits@incubator.apache.org Received: (qmail 56459 invoked by uid 99); 15 Apr 2009 08:35:25 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 Apr 2009 08:35:25 +0000 X-ASF-Spam-Status: No, hits=-1999.3 required=10.0 tests=ALL_TRUSTED,FRT_LEVITRA X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 Apr 2009 08:35:18 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 835382388975; Wed, 15 Apr 2009 08:34:58 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r765086 - in /incubator/sling/trunk/bundles/servlets/resolver/src: main/java/org/apache/sling/servlets/resolver/internal/ main/java/org/apache/sling/servlets/resolver/internal/resource/ test/java/org/apache/sling/servlets/resolver/internal/... Date: Wed, 15 Apr 2009 08:34:58 -0000 To: sling-commits@incubator.apache.org From: cziegeler@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090415083458.835382388975@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: cziegeler Date: Wed Apr 15 08:34:57 2009 New Revision: 765086 URL: http://svn.apache.org/viewvc?rev=765086&view=rev Log: SLING-910 : Add new configuration property "sling.servlet.prefix" for a servlet which specifies the prefix path for mounting the servlet. This can either be an absolute path or an index in the search path array of the resource reslver. Modified: incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/SlingServletResolverTest.java incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java Modified: incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java?rev=765086&r1=765085&r2=765086&view=diff ============================================================================== --- incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java (original) +++ incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java Wed Apr 15 08:34:57 2009 @@ -21,9 +21,9 @@ public class ServletResolverConstants { /** - * The name of the service registration property of a Servlet registered as + * The name of the service registration property of a servlet registered as * a service providing the absolute paths under which the servlet is - * accessible as a Resource (value is "sling.servlet.paths") + * accessible as a resource (value is "sling.servlet.paths") *

* The type of this property is a String or String[] (array of strings) * denoting the resource types. @@ -31,7 +31,7 @@ public static final String SLING_SERVLET_PATHS = "sling.servlet.paths"; /** - * The name of the service registration property of a Servlet registered as + * The name of the service registration property of a servlet registered as * a service containing the resource type(s) supported by the servlet (value * is "sling.servlet.resourceTypes"). *

@@ -43,6 +43,26 @@ public static final String SLING_SERVLET_RESOURCE_TYPES = "sling.servlet.resourceTypes"; /** + * The name of the service registration property of a servlet registered as + * a service providing the prefix/index to be used to register this servlet. + * If the value of this property is a number, it defines the index of the search + * path entries from the resource resolver. The defined search path is used as + * a prefix to mount this servlet. The number can be -1 which always points to the + * last search entry. If the specified value is higher than than the highest index + * of the search paths, the last entry is used. The index starts with 0. + * If the value of this property is a string and parseable as a number, the above + * logic is used. + * If the value of this property is a string starting with "/", this value is applied + * as a prefix, regardless of the configured search paths! + * If the value is anything else, it is ignored. + * If this property is not specified, it defaults to the default configuration of the + * sling servlet resolver. + *

+ * The type of this property is either String or a Number. + */ + public static final String SLING_SERVLET_PREFIX = "sling.servlet.prefix"; + + /** * The name of the service registration property of a Servlet registered as * a service containing the request URL selectors supported by the servlet * (value is "sling.servlet.selectors"). The selectors must be configured as Modified: incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java?rev=765086&r1=765085&r2=765086&view=diff ============================================================================== --- incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java (original) +++ incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java Wed Apr 15 08:34:57 2009 @@ -52,10 +52,10 @@ import org.apache.sling.api.scripting.SlingScriptResolver; 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.engine.RequestUtil; import org.apache.sling.engine.servlets.AbstractServiceReferenceConfig; import org.apache.sling.engine.servlets.ErrorHandler; +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.ResourceCollector; @@ -71,7 +71,7 @@ /** * The SlingServletResolver TODO - * + * * @scr.component name="org.apache.sling.servlets.resolver.SlingServletResolver" * label="%servletresolver.name" * description="%servletresolver.description" @@ -100,6 +100,9 @@ /** @scr.reference */ private ServletContext servletContext; + /** @scr.reference */ + private JcrResourceResolverFactory resourceResolverFactory; + private Map servletsByReference = new HashMap(); private List pendingServlets = new ArrayList(); @@ -133,7 +136,7 @@ if(log.isDebugEnabled()) { log.debug("resolveServlet called for Resource {}", request.getResource()); } - + // first check whether the type of a resource is the absolute // path of a servlet (or script) if (type.charAt(0) == '/') { @@ -150,7 +153,7 @@ if (servlet == null) { ResourceCollector locationUtil = ResourceCollector.create(request); servlet = getServlet(locationUtil, request, resource); - + if(log.isDebugEnabled()) { log.debug("getServlet returns Servlet {}", RequestUtil.getServletName(servlet)); } @@ -357,7 +360,7 @@ * because the error occurred before the resource could be set (e.g. during * resource resolution) a synthetic resource is returned whose type is * {@link ServletResolverConstants#ERROR_HANDLER_PATH}. - * + * * @param request The request whose resource is to be returned. */ private Resource getErrorResource(SlingHttpServletRequest request) { @@ -377,7 +380,7 @@ * actually willing to handle the request in case the servlet is an * OptingServlet. The first servlet willing to handle the * request is used. - * + * * @param locationUtil The helper used to find appropriate servlets ordered * by matching priority. * @param request The request used to give to any OptingServlet @@ -394,7 +397,7 @@ private Servlet getServlet(ResourceCollector locationUtil, SlingHttpServletRequest request, Resource resource) { Collection candidates = locationUtil.getServlets(resource); - + if(log.isDebugEnabled()) { if(candidates.isEmpty()) { log.debug("No Servlet candidates found"); @@ -405,10 +408,10 @@ } } } - + for (Resource candidateResource : candidates) { if(log.isDebugEnabled()) { - log.debug("Checking if candidate Resource {} adapts to Servlet and accepts request", + log.debug("Checking if candidate Resource {} adapts to Servlet and accepts request", candidateResource.getPath()); } Servlet candidate = candidateResource.adaptTo(Servlet.class); @@ -417,14 +420,13 @@ || ((OptingServlet) candidate).accepts(request); if (servletAcceptsRequest) { return candidate; - } else { - if(log.isDebugEnabled()) { - log.debug("Candidate {} does not accept request, ignored", candidateResource.getPath()); - } } + if(log.isDebugEnabled()) { + log.debug("Candidate {} does not accept request, ignored", candidateResource.getPath()); + } } else { if(log.isDebugEnabled()) { - log.debug("Candidate {} does not adapt to a Servlet, ignored", candidateResource.getPath()); + log.debug("Candidate {} does not adapt to a Servlet, ignored", candidateResource.getPath()); } } } @@ -508,8 +510,10 @@ // from configuration if available Dictionary properties = context.getProperties(); - String servletRoot = OsgiUtil.toString( - properties.get(PROP_SERVLET_ROOT), DEFAULT_SERVLET_ROOT); + Object servletRoot = properties.get(PROP_SERVLET_ROOT); + if ( servletRoot == null ) { + servletRoot = DEFAULT_SERVLET_ROOT; + } Collection refs; synchronized (this) { @@ -518,7 +522,7 @@ pendingServlets = new ArrayList(); servletResourceProviderFactory = new ServletResourceProviderFactory( - servletRoot); + servletRoot, this.resourceResolverFactory.getResourceResolver(null).getSearchPath()); // register servlets immediately from now on this.context = context; @@ -535,7 +539,7 @@ synchronized (this) { refs = new ArrayList(servletsByReference.keySet()); } - + // destroy all servlets destroyAllServlets(refs); this.context = null; @@ -599,7 +603,7 @@ // assign the servlet to the provider provider.setServlet(servlet); - + // initialize now try { servlet.init(new SlingServletConfig(servletContext, reference, name)); @@ -659,4 +663,14 @@ } } } + + protected void bindResourceResolverFactory(JcrResourceResolverFactory factory) { + this.resourceResolverFactory = factory; + } + + protected void unbindResourceResolverFactory(JcrResourceResolverFactory factory) { + if ( this.resourceResolverFactory == factory) { + this.resourceResolverFactory = null; + } + } } Modified: incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java?rev=765086&r1=765085&r2=765086&view=diff ============================================================================== --- incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java (original) +++ incubator/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java Wed Apr 15 08:34:57 2009 @@ -21,6 +21,7 @@ import static org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_EXTENSIONS; import static org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_METHODS; import static org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_PATHS; +import static org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_PREFIX; import static org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES; import static org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_SELECTORS; @@ -57,6 +58,16 @@ */ private final String servletRoot; + /** + * The index of the search path to be used as servlet root path + */ + private final int servletRootIndex; + + /** + * The search paths + */ + private final String[] searchPaths; + static String ensureServletNameExtension(String servletPath) { if (servletPath.endsWith(SERVLET_PATH_EXTENSION)) { return servletPath; @@ -65,17 +76,44 @@ return servletPath.concat(SERVLET_PATH_EXTENSION); } - public ServletResourceProviderFactory(String servletRoot) { - - // ensure the root starts and ends with a slash - if (!servletRoot.startsWith("/")) { - servletRoot = "/" + servletRoot; - } - if (!servletRoot.endsWith("/")) { - servletRoot += "/"; + /** + * Constructor + * @param servletRoot The default value for the servlet root + */ + public ServletResourceProviderFactory(Object servletRoot, String[] paths) { + this.searchPaths = paths; + String value = servletRoot.toString(); + // check if servlet root specifies a number + boolean isNumber = false; + int index = -1; + if ( servletRoot instanceof Number ) { + isNumber = true; + index = ((Number)servletRoot).intValue(); + } else { + if (!value.startsWith("/") ) { + try { + index = Integer.valueOf(value); + isNumber = true; + } catch (NumberFormatException nfe) { + // ignore + } + } } + if ( !isNumber ) { + // ensure the root starts and ends with a slash + if (!value.startsWith("/")) { + value = "/" + value; + } + if (!value.endsWith("/")) { + value += "/"; + } - this.servletRoot = servletRoot; + this.servletRoot = value; + this.servletRootIndex = -1; + } else { + this.servletRoot = null; + this.servletRootIndex = index; + } } public ServletResourceProvider create(ServiceReference ref) { @@ -101,16 +139,65 @@ log.debug("create({}): Registering servlet for paths {}", getServiceIdentifier(ref), pathSet); } - + return new ServletResourceProvider(pathSet); } + /** + * Get the mount prefix. + */ + private String getPrefix(final ServiceReference ref) { + Object value = ref.getProperty(SLING_SERVLET_PREFIX); + if ( value == null ) { + if ( this.servletRoot != null ) { + return this.servletRoot; + } + value = this.servletRootIndex; + } + int index = -1; + if ( value instanceof Number ) { + index = ((Number)value).intValue(); + } else { + String s = value.toString(); + if ( !s.startsWith("/") ) { + boolean isNumber = false; + try { + index = Integer.valueOf(s); + isNumber = true; + } catch (NumberFormatException nfe) { + // ignore + } + if ( !isNumber ) { + if (log.isDebugEnabled()) { + log.debug("getPrefix({}): Configuration property is ignored {}", + getServiceIdentifier(ref), value); + } + if ( this.servletRoot != null ) { + return this.servletRoot; + } + index = this.servletRootIndex; + } + } else { + return s; + } + } + if ( index == -1 || index >= this.searchPaths.length ) { + index = this.searchPaths.length - 1; + } + return this.searchPaths[index]; + } + + /** + * Add a servlet by path. + * @param pathSet + * @param ref + */ private void addByPath(Set pathSet, ServiceReference ref) { String[] paths = OsgiUtil.toStringArray(ref.getProperty(SLING_SERVLET_PATHS)); if (paths != null && paths.length > 0) { for (String path : paths) { if (!path.startsWith("/")) { - path = servletRoot.concat(path); + path = getPrefix(ref).concat(path); } // add the unmodified path @@ -122,6 +209,11 @@ } } + /** + * Add a servlet by type + * @param pathSet + * @param ref + */ private void addByType(Set pathSet, ServiceReference ref) { String[] types = OsgiUtil.toStringArray(ref.getProperty(SLING_SERVLET_RESOURCE_TYPES)); if (types == null || types.length == 0) { @@ -144,7 +236,7 @@ // handle the methods property specially (SLING-430) String[] methods = OsgiUtil.toStringArray(ref.getProperty(SLING_SERVLET_METHODS)); if (methods == null || methods.length == 0) { - + // SLING-512 only, set default methods if no extensions are declared if (extensions == null || extensions.length == 0) { if (log.isInfoEnabled()) { @@ -154,7 +246,7 @@ } methods = DEFAULT_SERVLET_METHODS; } - + } else if (methods.length == 1 && ALL_METHODS.equals(methods[0])) { if (log.isInfoEnabled()) { log.info("addByType({}): Assuming all methods for '*'", @@ -170,7 +262,7 @@ // make absolute if relative if (!type.startsWith("/")) { - type = servletRoot + type; + type = this.getPrefix(ref) + type; } // ensure trailing slash for full path building Modified: incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/SlingServletResolverTest.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/SlingServletResolverTest.java?rev=765086&r1=765085&r2=765086&view=diff ============================================================================== --- incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/SlingServletResolverTest.java (original) +++ incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/SlingServletResolverTest.java Wed Apr 15 08:34:57 2009 @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import javax.jcr.Session; import javax.servlet.Servlet; import javax.servlet.http.HttpServlet; @@ -28,6 +29,7 @@ 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.servlets.OptingServlet; import org.apache.sling.commons.testing.osgi.MockBundle; @@ -37,6 +39,7 @@ import org.apache.sling.commons.testing.sling.MockResourceResolver; import org.apache.sling.commons.testing.sling.MockSlingHttpServletRequest; import org.apache.sling.engine.EngineConstants; +import org.apache.sling.jcr.resource.JcrResourceResolverFactory; import org.apache.sling.servlets.resolver.internal.resource.MockServletResource; import org.osgi.framework.Constants; @@ -55,8 +58,20 @@ protected void setUp() throws Exception { super.setUp(); + mockResourceResolver = new MockResourceResolver(); + mockResourceResolver.setSearchPath("/"); + + final JcrResourceResolverFactory factory = new JcrResourceResolverFactory() { + + public ResourceResolver getResourceResolver(Session session) { + return mockResourceResolver; + } + }; + servlet = new MockSlingRequestHandlerServlet(); servletResolver = new SlingServletResolver(); + servletResolver.bindResourceResolverFactory(factory); + MockBundle bundle = new MockBundle(1L); MockComponentContext mockComponentContext = new MockComponentContext( bundle, SlingServletResolverTest.this.servlet); @@ -73,8 +88,6 @@ servletResolver.bindServlet(serviceReference); servletResolver.activate(mockComponentContext); - mockResourceResolver = new MockResourceResolver(); - mockResourceResolver.setSearchPath("/"); String path = "/" + MockSlingHttpServletRequest.RESOURCE_TYPE @@ -115,7 +128,7 @@ /** * This sample servlet will only handle secure requests. - * + * * @see org.apache.sling.api.servlets.OptingServlet#accepts */ private static class MockSlingRequestHandlerServlet extends HttpServlet Modified: incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java?rev=765086&r1=765085&r2=765086&view=diff ============================================================================== --- incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java (original) +++ incubator/sling/trunk/bundles/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java Wed Apr 15 08:34:57 2009 @@ -48,7 +48,7 @@ private static final String RES_TYPE_PATH = JcrResourceUtil.resourceTypeToPath(RES_TYPE); private ServletResourceProviderFactory factory = new ServletResourceProviderFactory( - ROOT); + ROOT, new String[] {"/apps/"}); public void testCreateMethodsDefault() { MockServiceReference msr = new MockServiceReference(null);