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/01/14 15:18:26 UTC

svn commit: r611807 - in /incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver: pom.xml src/main/java/org/apache/sling/servlet/resolver/ServletResolverConstants.java src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java

Author: fmeschbe
Date: Mon Jan 14 06:18:23 2008
New Revision: 611807

URL: http://svn.apache.org/viewvc?rev=611807&view=rev
Log:
Make the servlet resolver also the script resolver and consolidate
path configuration for relative script/servlet paths.

Still need to figure out how to define the servlet paths for
servlets registered as OSGi services

Modified:
    incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/pom.xml
    incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/ServletResolverConstants.java
    incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java

Modified: incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/pom.xml?rev=611807&r1=611806&r2=611807&view=diff
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/pom.xml (original)
+++ incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/pom.xml Mon Jan 14 06:18:23 2008
@@ -68,6 +68,7 @@
                         <Private-Package>
                             org.apache.sling.servlet.resolver.*
                         </Private-Package>
+                        <!--
                         <Import-Package>
                             javax.servlet , javax.servlet.http ,
                             org.apache.commons.beanutils,
@@ -81,6 +82,7 @@
                             org.osgi.framework,
                             org.osgi.service.component, org.slf4j
                         </Import-Package>
+                        -->
                     </instructions>
                 </configuration>
             </plugin>

Modified: incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/ServletResolverConstants.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/ServletResolverConstants.java?rev=611807&r1=611806&r2=611807&view=diff
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/ServletResolverConstants.java (original)
+++ incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/ServletResolverConstants.java Mon Jan 14 06:18:23 2008
@@ -35,6 +35,8 @@
      * "sling.core.servlet.default"). If no servlet is registered under this
      * name, the {@link org.apache.sling.servlet.resolver.defaults.DefaultServlet} is used.
      */
-    public static final String DEFAULT_SERVLET_NAME = "sling.core.servlet.default";
+    public static final String DEFAULT_SERVLET_NAME = "sling/servlet/default";
+    
+    public static final String ERROR_HANDLER_PATH = "sling/servlet/errorhandler";
 
 }

Modified: incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java?rev=611807&r1=611806&r2=611807&view=diff
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java (original)
+++ incubator/sling/whiteboard/fmeschbe/resource/sling/servlet-resolver/src/main/java/org/apache/sling/servlet/resolver/SlingServletResolver.java Mon Jan 14 06:18:23 2008
@@ -18,15 +18,19 @@
  */
 package org.apache.sling.servlet.resolver;
 
-import static org.apache.sling.api.SlingConstants.*;
-import static org.apache.sling.core.CoreConstants.*;
-import static org.apache.sling.servlet.resolver.ServletResolverConstants.*;
+import static org.apache.sling.api.SlingConstants.ERROR_MESSAGE;
+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 static org.apache.sling.servlet.resolver.ServletResolverConstants.SLING_RESOURCE_TYPES;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -39,15 +43,18 @@
 import org.apache.sling.api.SlingConstants;
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.scripting.SlingScript;
 import org.apache.sling.api.scripting.SlingScriptResolver;
 import org.apache.sling.api.servlets.ServletResolver;
 import org.apache.sling.core.servlets.AbstractServiceReferenceConfig;
 import org.apache.sling.core.servlets.ErrorHandler;
+import org.apache.sling.osgi.commons.OsgiUtil;
 import org.apache.sling.servlet.resolver.defaults.DefaultErrorHandlerServlet;
 import org.apache.sling.servlet.resolver.defaults.DefaultServlet;
-import org.apache.sling.servlet.resolver.helper.ErrorSlingHttpServletRequest;
-import org.apache.sling.servlet.resolver.helper.SlingScriptServlet;
+import org.apache.sling.servlet.resolver.helper.PathSupport;
 import org.apache.sling.servlet.resolver.helper.SlingServletConfig;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
@@ -57,7 +64,7 @@
 
 /**
  * The <code>SlingServletResolver</code> TODO
- *
+ * 
  * @scr.component label="%servletresolver.name"
  *                description="%servletresolver.description"
  * @scr.property name="service.description" value="Sling Servlet Resolver and
@@ -67,13 +74,14 @@
  * @scr.reference name="Servlet" interface="javax.servlet.Servlet"
  *                cardinality="0..n" policy="dynamic"
  */
-public class SlingServletResolver implements ServletResolver, ErrorHandler {
+public class SlingServletResolver implements ServletResolver,
+        SlingScriptResolver, ErrorHandler {
 
     /** default log */
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     /**
-     * @scr.property values.1="/apps/components" values.2="/libs/components"
+     * @scr.property values.1="/apps" values.2="/libs"
      *               label="%resolver.path.name"
      *               description="%resolver.path.description"
      */
@@ -81,9 +89,6 @@
 
     private static final String REF_SERVLET = "Servlet";
 
-    /** @scr.reference cardinality="0..1" policy="dynamic" */
-    private SlingScriptResolver scriptResolver;
-
     /** @scr.reference */
     private ServletContext servletContext;
 
@@ -103,14 +108,22 @@
 
     // ---------- ServletResolver interface -----------------------------------
 
-    public Servlet resolveServlet(SlingHttpServletRequest request) {
+    public Servlet resolveServlet(SlingHttpServletRequest request)
+            throws SlingException {
+        ResourceResolver resolver = request.getResourceResolver();
+        String baseName = PathSupport.getScriptBaseName(request);
 
-        // resolve a servlet or script based on the request
-        Servlet servlet = resolveServletOrScript(request);
+        // search the servlet by absolute path and resource type
+        Iterator<String> pathIterator = PathSupport.getPathIterator(request,
+            path);
+        Servlet servlet = null;
+        while (servlet == null && pathIterator.hasNext()) {
+            servlet = getServletAt(resolver, pathIterator.next(), baseName);
+        }
 
-        // use default servlet, create one if missing
+        // fall back to default servlet for the request
         if (servlet == null) {
-            servlet = getServlet(DEFAULT_SERVLET_NAME);
+            servlet = getServletAt(resolver, DEFAULT_SERVLET_NAME, baseName);
         }
 
         // last resort, use the core bundle default servlet
@@ -118,144 +131,187 @@
             servlet = getCoreDefaultServlet();
         }
 
-        if (servlet != null && log.isDebugEnabled()) {
-            String name;
-            if (servlet.getServletConfig() != null) {
-                name = servlet.getServletConfig().getServletName();
+        if (log.isDebugEnabled()) {
+            if (servlet != null) {
+                String name;
+                if (servlet.getServletConfig() != null) {
+                    name = servlet.getServletConfig().getServletName();
+                } else {
+                    name = servlet.getServletInfo();
+                }
+                if (name == null) {
+                    name = servlet.getClass().getName();
+                }
+                log.info("Servlet {} found for Resource={}", name,
+                    request.getResource());
             } else {
-                name = servlet.getServletInfo();
+                log.debug("No servlet found for Resource={}",
+                    request.getResource());
             }
-            if (name == null) {
-                name = servlet.getClass().getName();
-            }
-            log.debug("Using Servlet {} for {}", name, path);
         }
 
         return servlet;
     }
 
+    // ---------- ScriptResolver interface ------------------------------------
+    
+    public SlingScript findScript(ResourceResolver resourceResolver, String name)
+            throws SlingException {
+        
+        if (name.startsWith("/")) {
+            Resource resource = resourceResolver.getResource(name);
+            return (resource != null)
+                    ? resource.adaptTo(SlingScript.class)
+                    : null;
+        }
+        
+        for (int i=0; i < path.length; i++) {
+            String scriptPath = path[i] + name;
+            Resource resource = resourceResolver.getResource(scriptPath);
+            if (resource != null) {
+                SlingScript script = resource.adaptTo(SlingScript.class);
+                if (script == null) {
+                    log.debug("findScript: Using script {} for {}",
+                        script.getScriptResource().getURI(), name);
+                    return script;
+                }
+            }
+        }
+        
+        log.info("findScript: No script {} found in path", name);
+        return null;
+    }
+    
     // ---------- ErrorHandler interface --------------------------------------
 
     public void handleError(int status, String message,
-            HttpServletRequest request, HttpServletResponse response)
+            SlingHttpServletRequest request, SlingHttpServletResponse response)
             throws IOException {
 
         // do not handle, if already handling ....
-        if (request.getAttribute(ERROR_REQUEST_URI) == null) {
-
-            // find the error handler component
-            ErrorSlingHttpServletRequest eRequest = new ErrorSlingHttpServletRequest(
-                request, String.valueOf(status));
-            Servlet servlet = resolveServletOrScript(eRequest);
-
-            if (servlet == null) {
-                servlet = getDefaultErrorServlet();
+        if (request.getAttribute(SlingConstants.ERROR_REQUEST_URI) != null) {
+            log.error("handleError: Recursive invocation. Not further handling status "
+                + status + "(" + message + ")");
+            return;
+        }
+
+        // find the error handler component
+        ResourceResolver resolver = request.getResourceResolver();
+        String baseName = String.valueOf(status);
+
+        // search the servlet by absolute path
+        Iterator<String> pathIterator = PathSupport.getPathIterator(
+            ServletResolverConstants.ERROR_HANDLER_PATH, path);
+        Servlet servlet = null;
+        while (servlet == null && pathIterator.hasNext()) {
+            String location = pathIterator.next();
+            try {
+                servlet = getServletAt(resolver, location, baseName);
+            } catch (SlingException se) {
+                log.warn("handleError: Problem resolving servlet at "
+                    + location + "/" + baseName, se);
             }
+        }
 
-            // set the message properties
-            request.setAttribute(ERROR_STATUS, new Integer(
-                status));
-            request.setAttribute(ERROR_MESSAGE, message);
-
-            // the servlet name for a sendError handling is still stored
-            // as the request attribute
-            Object servletName = request.getAttribute(SLING_CURRENT_SERVLET_NAME);
-            if (servletName instanceof String) {
-                request.setAttribute(ERROR_SERVLET_NAME, servletName);
-            }
+        if (servlet == null) {
+            servlet = getDefaultErrorServlet();
+        }
 
-            if (handleError(servlet, request, response)) {
-                return;
-            }
+        // set the message properties
+        request.setAttribute(ERROR_STATUS, new Integer(status));
+        request.setAttribute(ERROR_MESSAGE, message);
+
+        // the servlet name for a sendError handling is still stored
+        // as the request attribute
+        Object servletName = request.getAttribute(SLING_CURRENT_SERVLET_NAME);
+        if (servletName instanceof String) {
+            request.setAttribute(ERROR_SERVLET_NAME, servletName);
         }
 
-        // get here, if we have no handler, let the status go up the chain
-        // and if this causes and exception, so what ...
-        response.sendError(status, message);
+        handleError(servlet, request, response);
     }
 
-    public void handleError(Throwable throwable, HttpServletRequest request,
-            HttpServletResponse response) throws ServletException, IOException {
+    public void handleError(Throwable throwable,
+            SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws IOException {
 
         // do not handle, if already handling ....
-        if (request.getAttribute(SlingConstants.ERROR_REQUEST_URI) == null) {
-
-            // find the error handler component
-            Servlet servlet = null;
-            Class<?> tClass = throwable.getClass();
-            ErrorSlingHttpServletRequest eRequest = new ErrorSlingHttpServletRequest(
-                request, "");
-            while (servlet == null && tClass != Object.class) {
-                eRequest.setMethod(tClass.getSimpleName());
-                servlet = resolveServletOrScript(eRequest);
-
-                // go to the base class
-                tClass = tClass.getSuperclass();
-            }
-
-            if (servlet == null) {
-                servlet = getDefaultErrorServlet();
-            }
-
-            // set the message properties
-            request.setAttribute(SlingConstants.ERROR_EXCEPTION, throwable);
-            request.setAttribute(SlingConstants.ERROR_EXCEPTION_TYPE,
-                throwable.getClass());
-            request.setAttribute(SlingConstants.ERROR_MESSAGE,
-                throwable.getMessage());
-
-            if (handleError(servlet, request, response)) {
-                return;
+        if (request.getAttribute(SlingConstants.ERROR_REQUEST_URI) != null) {
+            log.error(
+                "handleError: Recursive invocation. Not further handling Throwable:",
+                throwable);
+            return;
+        }
+
+        // find the error handler component
+        Servlet servlet = null;
+        ResourceResolver resolver = request.getResourceResolver();
+
+        Class<?> tClass = throwable.getClass();
+        while (servlet == null && tClass != Object.class) {
+            String baseName = tClass.getSimpleName();
+
+            Iterator<String> pathIterator = PathSupport.getPathIterator(
+                ServletResolverConstants.ERROR_HANDLER_PATH, path);
+            while (servlet == null && pathIterator.hasNext()) {
+                String location = pathIterator.next();
+                try {
+                    servlet = getServletAt(resolver, location, baseName);
+                } catch (SlingException se) {
+                    log.warn("handleError: Problem resolving servlet at "
+                        + location + "/" + baseName, se);
+                }
             }
-        }
 
-        // get here, if we have no handler, let the throwable go up the chain
-        if (throwable instanceof IOException) {
-            throw (IOException) throwable;
-        } else if (throwable instanceof ServletException) {
-            throw (ServletException) throwable;
-        } else if (throwable instanceof RuntimeException) {
-            throw (RuntimeException) throwable;
-        } else {
-            throw new ServletException(throwable);
+            // go to the base class
+            tClass = tClass.getSuperclass();
         }
-    }
-
-    // ---------- internal helper ---------------------------------------------
-
-    Servlet resolveServletOrScript(SlingHttpServletRequest request) {
 
-        // get the servlet by resource type
-        Servlet servlet = getServlet(request.getResource().getResourceType());
-        if (servlet != null) {
-            return servlet;
+        if (servlet == null) {
+            servlet = getDefaultErrorServlet();
         }
 
-        // no typed servlet, so lets try scripting
-        try {
-            servlet = getScriptServlet(request);
-            if (servlet != null) {
-                return servlet;
-            }
-        } catch (SlingException se) {
-            log.error("resolveServlet: Error trying to find script", se);
-        }
+        // set the message properties
+        request.setAttribute(SlingConstants.ERROR_EXCEPTION, throwable);
+        request.setAttribute(SlingConstants.ERROR_EXCEPTION_TYPE,
+            throwable.getClass());
+        request.setAttribute(SlingConstants.ERROR_MESSAGE,
+            throwable.getMessage());
 
-        // no script either
-        return null;
+        handleError(servlet, request, response);
     }
 
-    private Servlet getScriptServlet(SlingHttpServletRequest request)
-            throws SlingException {
-        SlingScriptResolver ssr = scriptResolver;
-        if (ssr != null) {
-            SlingScript script = ssr.resolveScript(request);
-            if (script != null) {
-                return new SlingScriptServlet(script);
+    // ---------- internal helper ---------------------------------------------
+
+    private Servlet getServletAt(ResourceResolver resolver, String location,
+            String baseName) throws SlingException {
+        Servlet result = null;
+
+        Resource scriptRoot = resolver.getResource(location);
+        if (scriptRoot != null) {
+
+            log.debug("Looking for servlet with filename={} under {}",
+                baseName, scriptRoot.getURI());
+
+            // get the item and ensure it is a node
+            Iterator<Resource> children = resolver.listChildren(scriptRoot);
+            while (result == null && children.hasNext()) {
+                Resource resource = children.next();
+
+                // extract the name of the resource
+                int lastSlash = resource.getURI().lastIndexOf('/');
+                String name = resource.getURI().substring(lastSlash + 1);
+
+                // only accept it if it is equal to the base name or
+                // if there is just a single extension after the base name
+                if (name.startsWith(baseName)
+                    && (name.length() == baseName.length() || name.lastIndexOf('.') == baseName.length())) {
+                    result = resource.adaptTo(Servlet.class);
+                }
             }
         }
 
-        return null;
+        return result;
     }
 
     private Servlet getCoreDefaultServlet() {
@@ -288,8 +344,8 @@
         return defaultErrorServlet;
     }
 
-    private boolean handleError(Servlet errorHandler,
-            HttpServletRequest request, HttpServletResponse response) {
+    private void handleError(Servlet errorHandler, HttpServletRequest request,
+            HttpServletResponse response) throws IOException {
 
         request.setAttribute(SlingConstants.ERROR_REQUEST_URI,
             request.getRequestURI());
@@ -301,51 +357,52 @@
                 errorHandler.getServletConfig().getServletName());
         }
 
-        // find a component by
         try {
             errorHandler.service(request, response);
-            return true;
+        } catch (IOException ioe) {
+            // forware the IOException
+            throw ioe;
         } catch (Throwable t) {
-            log.error("Cannot handle error", t);
+            log.error("Calling the error handler resulted in an error", t);
         }
-
-        return false;
     }
 
     // ---------- SCR Integration ----------------------------------------------
 
     protected void activate(ComponentContext context) {
 
-        this.context = context;
-
         // empty path to begin with
         path = null;
 
         // from configuration if available
         Dictionary<?, ?> properties = context.getProperties();
         if (properties != null) {
-            Object pathObject = properties.get(PROP_PATH);
-            if (pathObject instanceof String[]) {
-                this.path = (String[]) pathObject;
-                for (int i = 0; i < this.path.length; i++) {
+            String[] tmpPath = OsgiUtil.toStringArray(properties.get(PROP_PATH));
+            if (tmpPath != null && tmpPath.length > 0) {
+                for (int i = 0; i < tmpPath.length; i++) {
                     // ensure leading slash
-                    if (!this.path[i].startsWith("/")) {
-                        this.path[i] = "/" + this.path[i];
+                    if (!tmpPath[i].startsWith("/")) {
+                        tmpPath[i] = "/" + tmpPath;
                     }
                     // ensure trailing slash
-                    if (!this.path[i].endsWith("/")) {
-                        this.path[i] += "/";
+                    if (!tmpPath[i].endsWith("/")) {
+                        tmpPath[i] += "/";
                     }
                 }
             }
+            path = tmpPath;
         }
-        
+
+        if (path == null) {
+            path = new String[] { "/" };
+        }
+
         Collection<ServiceReference> refs;
         synchronized (this) {
 
             refs = pendingServlets;
             pendingServlets = new ArrayList<ServiceReference>();
-            
+
             // register servlets immediately from now on
             this.context = context;
 
@@ -355,7 +412,7 @@
     }
 
     protected void deactivate(ComponentContext context) {
-        
+
         // destroy all active servlets
         Collection<ServiceReference> refs;
         synchronized (this) {
@@ -366,7 +423,7 @@
         // destroy all servlets
         destroyAllServlets(refs);
     }
-    
+
     protected synchronized void bindServlet(ServiceReference reference) {
         if (context == null) {
             pendingServlets.add(reference);