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")
* <p>
* 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").
* <p>
@@ -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.
+ * <p>
+ * 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 <code>SlingServletResolver</code> 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<ServiceReference, ServiceRegistration> servletsByReference =
new HashMap<ServiceReference, ServiceRegistration>();
private List<ServiceReference> pendingServlets = new
ArrayList<ServiceReference>();
@@ -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
* <code>OptingServlet</code>. 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
<code>OptingServlet</code>
@@ -394,7 +397,7 @@
private Servlet getServlet(ResourceCollector locationUtil,
SlingHttpServletRequest request, Resource resource) {
Collection<Resource> 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<ServiceReference> refs;
synchronized (this) {
@@ -518,7 +522,7 @@
pendingServlets = new ArrayList<ServiceReference>();
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<ServiceReference>(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<String> 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<String> 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);