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 2007/11/22 14:17:04 UTC

svn commit: r597404 - in /incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core: auth/ impl/ impl/auth/ impl/helper/

Author: fmeschbe
Date: Thu Nov 22 05:17:02 2007
New Revision: 597404

URL: http://svn.apache.org/viewvc?rev=597404&view=rev
Log:
SLING-103 Register SlingServletContext as a ServletContext service for servlets and scripts
SLING-108 Implement OSGi HttpContext.handleSecurity using the Sling Authenticator. As such the
Sling authentication mechanism is always called before even calling the main Sling servlet.

Added:
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationInfo.java
Modified:
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationHandler.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpContext.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/AuthorizationHeaderAuthenticationHandler.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/SlingAuthenticator.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/helper/SlingServletContext.java

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationHandler.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationHandler.java?rev=597404&r1=597403&r2=597404&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationHandler.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationHandler.java Thu Nov 22 05:17:02 2007
@@ -18,7 +18,8 @@
  */
 package org.apache.sling.core.auth;
 
-import javax.jcr.Credentials;
+import java.io.IOException;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -31,22 +32,7 @@
 public interface AuthenticationHandler {
 
     /**
-     * Returned by {@link #authenticate} to indicate an ongoing authentication
-     * transaction.
-     */
-    static final Credentials DOING_AUTH = new Credentials() {
-    };
-
-    // TODO
-    // @return true this handler can authenticate the request
-    boolean handles(HttpServletRequest request);
-
-    /**
-     * Extracts credential data from the request if at all contained. This check
-     * must basically be based on the original request object with the exception
-     * of the request URI, which may be gotten from the request object through
-     * the {@link DeliveryHttpServletRequest#getRealRequestURI()}, which
-     * returns the request URI with the context path removed.
+     * Extracts credential data from the request if at all contained.
      * <p>
      * The method returns any of the following values : <table>
      * <tr>
@@ -54,16 +40,17 @@
      * <th>description</tr>
      * <tr>
      * <td><code>null</code>
-     * <td>no user details were contained in the request </tr>
+     * <td>no user details were contained in the request or the handler is not
+     * capable or willing to extract credentials from the request</tr>
      * <tr>
      * <td>{@link #DOING_AUTH}
      * <td>the handler is in an ongoing authentication transaction with the
-     * client. Further request handling in the DeliveryModule should not take
-     * place.
+     * client. Request processing should be aborted at this stage.
      * <tr>
      * <tr>
-     * <td><code>Credentials</code> object
-     * <td>The user sent credentials.</tr>
+     * <td><code>AuthenticationInfo</code> object
+     * <td>The user sent credentials. The returned object contains the
+     * credentials as well as the type of authentication transmission employed.</tr>
      * </table>
      * <p>
      * The method must not request credential information from the client, if
@@ -73,14 +60,14 @@
      *            authentication.
      * @param response The response object which may be used to send the
      *            information on the request failure to the user.
-     * @return A valid <code>Credentials</code> instance identifying the
-     *         request user, {@link #DOING_AUTH} if the handler is in an
+     * @return A valid <code>AuthenticationInfo</code> instance identifying
+     *         the request user, {@link #DOING_AUTH} if the handler is in an
      *         authentication transaction with the client or null if the request
      *         does not contain authentication information. In case of
      *         {@link #DOING_AUTH}, the method must have sent a response
      *         indicating that fact to the client.
      */
-    Credentials authenticate(HttpServletRequest request,
+    AuthenticationInfo authenticate(HttpServletRequest request,
             HttpServletResponse response);
 
     /**
@@ -95,13 +82,12 @@
      *
      * @param request The request object.
      * @param response The response object to which to send the request.
-     * @param addInfo Additional information string from the configuration. This
-     *            may for example be used as the realm name for HTTP header
-     *            authentication. TODO: handler configuration
-     * @return <code>true</code> if the information could be requested or
-     *         <code>false</code>, if the request should fail with the
-     *         appropriate error status.
+     * @return <code>true</code> if the handler is able to end an
+     *         authentication inquiry for the given request. <code>false</code>
+     *         otherwise.
+     * @throws IOException If an error occurrs sending the authentication
+     *             inquiry to the client.
      */
     boolean requestAuthentication(HttpServletRequest request,
-            HttpServletResponse response);
+            HttpServletResponse response) throws IOException;
 }

Added: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationInfo.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationInfo.java?rev=597404&view=auto
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationInfo.java (added)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/auth/AuthenticationInfo.java Thu Nov 22 05:17:02 2007
@@ -0,0 +1,83 @@
+/*
+ * 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.core.auth;
+
+import javax.jcr.Credentials;
+
+/**
+ * The <code>AuthenticationInfo</code> defines the data returned from the
+ * {@link AuthenticationHandler#authenticate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method.
+ */
+public class AuthenticationInfo {
+
+    /**
+     * This object is returned by the
+     * {@link AuthenticationHandler#authenticate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+     * method to indicate an ongoing authentication transaction.
+     */
+    public static final AuthenticationInfo DOING_AUTH = new AuthenticationInfo();
+
+    /** The type of authentication */
+    private final String authType;
+
+    /** The <code>javax.jcr.Credentials</code> extracted from the request */
+    private final Credentials credentials;
+
+    /** Creates an empty instance, used for the {@link #DOING_AUTH} constants */
+    private AuthenticationInfo() {
+        authType = null;
+        credentials = null;
+    }
+
+    /**
+     * Creates an instance of this class with the given authentication type and
+     * credentials.
+     *
+     * @param authType The authentication type, must not be <code>null</code>.
+     * @param credentials The credentials, must not be <code>null</code>.
+     * @see #getAuthType()
+     * @see #getCredentials()
+     */
+    public AuthenticationInfo(String authType, Credentials credentials) {
+        this.authType = authType;
+        this.credentials = credentials;
+    }
+
+    /**
+     * Returns type of authentication provisioning.
+     * <p>
+     * If authentication is taking place through one of the standard ways, such
+     * as Basic or Digest, the return value is one of the predefined constants
+     * of the <code>HttpServletRequest</code> interface. Otherwise the value
+     * may be specific to the {@link AuthenticationHandler} implementation.
+     */
+    public String getAuthType() {
+        return authType;
+    }
+
+    /**
+     * Returns the credentials extracted from the client request to use for
+     * authentication.
+     */
+    public Credentials getCredentials() {
+        return credentials;
+    }
+
+}

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpContext.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpContext.java?rev=597404&r1=597403&r2=597404&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpContext.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpContext.java Thu Nov 22 05:17:02 2007
@@ -18,13 +18,13 @@
  */
 package org.apache.sling.core.impl;
 
-import java.io.InputStream;
 import java.net.URL;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.core.impl.auth.SlingAuthenticator;
 import org.osgi.service.http.HttpContext;
 
 /**
@@ -34,66 +34,44 @@
  */
 public class SlingHttpContext implements HttpContext {
 
+    /**
+     * The name of the request attribute set by the {@link SlingAuthenticator}
+     * when authenticating the request user. Existence of this attribute in the
+     * request, provided it is a JCR Session, signals that authentication has
+     * already taken place. This may be used when including through the servlet
+     * container.
+     */
+    public static final String SESSION = "org.apache.sling.core.session";
+
+    /** The helper to map MIME types */
     private MimeTypeService mimeTypeService;
 
-    SlingHttpContext(MimeTypeService mimeTypeService) {
-        this.mimeTypeService = mimeTypeService;
-    }
+    /** The helper to authenticate requests */
+    private final SlingAuthenticator slingAuthenticator;
 
-    void dispose() {
-        // replace the official implementation with a dummy one to prevent NPE
-        this.mimeTypeService = new MimeTypeService() {
-            public String getMimeType(String name) {
-                return null;
-            }
-
-            public String getExtension(String mimeType) {
-                return null;
-            }
-
-            public void registerMimeType(InputStream mimeTabStream) {
-            }
-
-            public void registerMimeType(String mimeType, String... extensions) {
-            }
-        };
+    /**
+     * Creates an instance of this OSGi HttpContext implementation using the
+     * give MIME type and authentication helpers.
+     */
+    SlingHttpContext(MimeTypeService mimeTypeService,
+            SlingAuthenticator slingAuthenticator) {
+        this.mimeTypeService = mimeTypeService;
+        this.slingAuthenticator = slingAuthenticator;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.osgi.service.http.HttpContext#getMimeType(java.lang.String)
-     */
+    /** Asks the MimeTypeService for the MIME type mapping */
     public String getMimeType(String name) {
         return this.mimeTypeService.getMimeType(name);
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.osgi.service.http.HttpContext#getResource(java.lang.String)
-     */
+    /** Always returns <code>null</code>, we have no resources here */
     public URL getResource(String name) {
-        // This context cannot provide any resources, so we just return nothing
         return null;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.osgi.service.http.HttpContext#handleSecurity(javax.servlet.http.HttpServletRequest,
-     *      javax.servlet.http.HttpServletResponse)
-     */
+    /** Asks the SlingAuthenticator to authenticate the request */
     public boolean handleSecurity(HttpServletRequest request,
             HttpServletResponse response) {
-
-        /*
-         * Currently we do not handle security in the context but in the
-         * SlingServlet as an SlingAuthenticator. It might be worth it
-         * considering to move the authentication from the SlingAuthenticator
-         * to this context.
-         */
-
-        return true;
+        return slingAuthenticator.authenticate(request, response);
     }
 }

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java?rev=597404&r1=597403&r2=597404&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java Thu Nov 22 05:17:02 2007
@@ -19,6 +19,7 @@
 package org.apache.sling.core.impl;
 
 import java.io.IOException;
+import java.net.URL;
 import java.security.AccessControlException;
 import java.util.ArrayList;
 import java.util.Dictionary;
@@ -64,6 +65,7 @@
 import org.osgi.framework.Version;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.ComponentException;
+import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.HttpService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -76,8 +78,7 @@
  * @scr.property name="sling.root" value="/" private="true"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
  * @scr.property name="service.description" value="Sling Servlet"
- * @scr.reference name="ComponentFilter"
- *                interface="org.apache.sling.component.ComponentFilter"
+ * @scr.reference name="Filter" interface="javax.servlet.Filter"
  *                cardinality="0..n" policy="dynamic"
  */
 public class SlingMainServlet extends GenericServlet {
@@ -87,15 +88,15 @@
 
     /**
      * The name of the product to report in the {@link #getServerInfo()} method
-     * (value is "Apache Sling").
+     * (value is "ApacheSling").
      */
-    private static String PRODUCT_NAME = "Apache Sling";
+    private static String PRODUCT_NAME = "ApacheSling";
 
     /**
-     * The name of the Declarative Services reference to the ComponentFilter
-     * services (value is "ComponentFilter").
+     * The name of the Declarative Services reference to the Servlet API Filter
+     * services (value is "Filter").
      */
-    private static String COMPONENT_FILTER_NAME = "ComponentFilter";
+    private static String FILTER_NAME = "Filter";
 
     private SlingServletContext slingServletContext;
 
@@ -123,8 +124,6 @@
     /** @scr.reference cardinality="0..1" policy="dynamic" */
     private MimeTypeService mimeTypeService;
 
-    private SlingHttpContext slingHttpContext;
-
     private SlingFilterChainHelper requestFilterChain = new SlingFilterChainHelper();
 
     private SlingFilterChainHelper innerFilterChain = new SlingFilterChainHelper();
@@ -159,8 +158,7 @@
     public void service(HttpServletRequest clientRequest,
             HttpServletResponse clientResponse) throws IOException {
 
-        Session session = getSlingAuthenticator().authenticate(clientRequest,
-            clientResponse);
+        Session session = (Session) clientRequest.getAttribute(SlingHttpContext.SESSION);
         if (session != null) {
             RequestData requestData = null;
             try {
@@ -188,12 +186,8 @@
             } catch (AccessControlException ace) {
 
                 // try to request authentication fail, if not possible
-                if (!getSlingAuthenticator().requestAuthentication(
-                    clientRequest, clientResponse)) {
-                    getErrorHandler().handleError(
-                        HttpServletResponse.SC_FORBIDDEN, "Access Denied",
-                        clientRequest, clientResponse);
-                }
+                getSlingAuthenticator().requestAuthentication(clientRequest,
+                    clientResponse);
 
             } catch (HttpStatusCodeException hsce) {
                 // convert the status code exception to sendError
@@ -353,14 +347,28 @@
         // setup servlet request processing helpers
         this.slingServiceLocator = new ServiceLocatorImpl(bundleContext);
         this.slingAuthenticator = new SlingAuthenticator(bundleContext);
-        this.servletResolver = new SlingServletResolver(bundleContext, slingServletContext);
+        this.servletResolver = new SlingServletResolver(bundleContext,
+            slingServletContext);
         this.errorHandler = new ErrorHandler(bundleContext, slingServletContext);
 
         // register the servlet and resources
         try {
-            this.slingHttpContext = new SlingHttpContext(this.mimeTypeService);
+            HttpContext httpContext = new HttpContext() {
+                public String getMimeType(String name) {
+                    return mimeTypeService.getMimeType(name);
+                }
+
+                public URL getResource(String name) {
+                    return null;
+                }
+
+                public boolean handleSecurity(HttpServletRequest request,
+                        HttpServletResponse response) {
+                    return slingAuthenticator.authenticate(request, response);
+                }
+            };
             this.httpService.registerServlet(this.slingRoot, this,
-                configuration, this.slingHttpContext);
+                configuration, httpContext);
 
             log.info("{} ready to serve requests", this.getServerInfo());
 
@@ -397,6 +405,9 @@
 
     protected void deactivate(ComponentContext componentContext) {
 
+        // first of all, we have to unregister
+        httpService.unregister(this.slingRoot);
+
         destroyFilters(innerFilterChain);
         destroyFilters(requestFilterChain);
 
@@ -417,19 +428,13 @@
             slingServiceLocator = null;
         }
 
-        this.httpService.unregister(this.slingRoot);
-
-        if (this.slingHttpContext != null) {
-            this.slingHttpContext.dispose();
-        }
-
         this.slingServletContext = null;
         this.osgiComponentContext = null;
 
         log.info(this.getServerInfo() + " shut down");
     }
 
-    protected void bindComponentFilter(ServiceReference ref) {
+    protected void bindFilter(ServiceReference ref) {
         synchronized (this) {
             if (osgiComponentContext == null) {
                 if (delayedComponentFilters == null) {
@@ -442,7 +447,7 @@
         }
     }
 
-    protected void unbindComponentFilter(ServiceReference ref) {
+    protected void unbindFilter(ServiceReference ref) {
         // service id
         Object serviceId = ref.getProperty(Constants.SERVICE_ID);
 
@@ -459,8 +464,7 @@
     }
 
     private void initFilter(ComponentContext osgiContext, ServiceReference ref) {
-        Filter filter = (Filter) osgiContext.locateService(
-            COMPONENT_FILTER_NAME, ref);
+        Filter filter = (Filter) osgiContext.locateService(FILTER_NAME, ref);
 
         // require a name for the filter
         String filterName = AbstractServiceReferenceConfig.getName(ref);

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/AuthorizationHeaderAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/AuthorizationHeaderAuthenticationHandler.java?rev=597404&r1=597403&r2=597404&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/AuthorizationHeaderAuthenticationHandler.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/AuthorizationHeaderAuthenticationHandler.java Thu Nov 22 05:17:02 2007
@@ -29,25 +29,26 @@
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.sling.core.auth.AuthenticationHandler;
+import org.apache.sling.core.auth.AuthenticationInfo;
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 /**
- * The <code>AuthorizationHeaderAuthenticationHandler</code> class implements the
- * authorization steps based on the Authorization header of the HTTP request.
- * This authenticator should eventually support both BASIC and DIGEST
+ * The <code>AuthorizationHeaderAuthenticationHandler</code> class implements
+ * the authorization steps based on the Authorization header of the HTTP
+ * request. This authenticator should eventually support both BASIC and DIGEST
  * authentication methods.
  *
  * @scr.component immediate="false" label="%auth.http.name"
  *                description="%auth.http.description"
- * @scr.property name="service.description"
- *          value="HTTP Header Authentication Handler"
+ * @scr.property name="service.description" value="HTTP Header Authentication
+ *               Handler"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
  * @scr.service
  */
-public class AuthorizationHeaderAuthenticationHandler implements AuthenticationHandler {
+public class AuthorizationHeaderAuthenticationHandler implements
+        AuthenticationHandler {
 
     /**
      * @scr.property value="Sling (Development)"
@@ -73,10 +74,6 @@
 
     // ----------- AuthenticationHandler interface ----------------------------
 
-    public boolean handles(HttpServletRequest request) {
-        return true;
-    }
-
     /**
      * Extracts credential data from the request if at all contained. This check
      * is only based on the original request object, no URI translation has
@@ -117,7 +114,7 @@
      *         information. In case of DOING_AUTH, the method must have sent a
      *         response indicating that fact to the client.
      */
-    public Credentials authenticate(HttpServletRequest request,
+    public AuthenticationInfo authenticate(HttpServletRequest request,
             HttpServletResponse response) {
         return this.extractAuthentication(request);
     }
@@ -126,41 +123,33 @@
      * Sends status <code>401</code> (Unauthorized) with a
      * <code>WWW-Authenticate</code> requesting standard HTTP header
      * authentication with the <code>Basic</code> scheme and the configured
-     * realm name.
-     * <p>
-     * Returns <code>true</code> if the response could successfully be sent to
-     * the client. Otherwise <code>false</code> is returned.
+     * realm name. If the response is already committed, an error message is
+     * logged but the 401 status is not sent.
      *
      * @param request The request object
      * @param response The response object to which to send the request
-     * @param addInfo Additional information string from the configuration. This
-     *            may for example be used as the realm name for HTTP header
-     *            authentication. TODO configuration
-     * @return true if the information could be requested or false, if the
-     *         request should fail with the appropriate error status
+     * @return <code>true</code> is always returned by this handler
+     * @throws IOException if an error occurrs sending back the response.
      */
     public boolean requestAuthentication(HttpServletRequest request,
-            HttpServletResponse response) {
+            HttpServletResponse response) throws IOException {
 
         // if the response is already committed, we have a problem !!
-        if (response.isCommitted()) {
-            log.warn("requestAuthentication: response already committed");
-            return false;
-        }
+        if (!response.isCommitted()) {
 
-        response.setHeader(HEADER_WWW_AUTHENTICATE,
-            AUTHENTICATION_SCHEME_BASIC + " realm=\"" + this.realm + "\"");
+            response.setHeader(HEADER_WWW_AUTHENTICATE,
+                AUTHENTICATION_SCHEME_BASIC + " realm=\"" + this.realm + "\"");
 
-        try {
             response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-            return true;
-        } catch (IOException ioe) {
-            log.info("requestAuthentication: Cannot send the error: {0}",
-                ioe.toString());
+
+        } else {
+
+            log.error("requestAuthentication: Response is committed, cannot request authentication");
+
+
         }
 
-        // got a problem with sending the error
-        return false;
+        return true;
     }
 
     // ---------- SCR Integration ----------------------------------------------
@@ -182,7 +171,8 @@
     /**
      * Extract the Base64 authentication string from the request
      */
-    protected Credentials extractAuthentication(HttpServletRequest request) {
+    protected AuthenticationInfo extractAuthentication(
+            HttpServletRequest request) {
 
         // Return immediately if the header is missing
         String authHeader = request.getHeader(HEADER_AUTHORIZATION);
@@ -237,12 +227,15 @@
             return null;
         }
 
+        Credentials creds;
         int colIdx = decoded.indexOf(':');
         if (colIdx < 0) {
-            return new SimpleCredentials(decoded, new char[0]);
+            creds = new SimpleCredentials(decoded, new char[0]);
+        } else {
+            creds = new SimpleCredentials(decoded.substring(0, colIdx),
+                decoded.substring(colIdx + 1).toCharArray());
         }
 
-        return new SimpleCredentials(decoded.substring(0, colIdx),
-            decoded.substring(colIdx + 1).toCharArray());
+        return new AuthenticationInfo(HttpServletRequest.BASIC_AUTH, creds);
     }
 }

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/SlingAuthenticator.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/SlingAuthenticator.java?rev=597404&r1=597403&r2=597404&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/SlingAuthenticator.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/auth/SlingAuthenticator.java Thu Nov 22 05:17:02 2007
@@ -33,11 +33,14 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.core.auth.AuthenticationHandler;
+import org.apache.sling.core.auth.AuthenticationInfo;
+import org.apache.sling.core.impl.SlingHttpContext;
 import org.apache.sling.jcr.api.TooManySessionsException;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ManagedService;
+import org.osgi.service.http.HttpContext;
 import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -197,43 +200,49 @@
      *         be assumed, that during this method enough response information
      *         has been sent to the client.
      */
-    public Session authenticate(HttpServletRequest req, HttpServletResponse res) {
+    public boolean authenticate(HttpServletRequest req, HttpServletResponse res) {
 
-        // 0. Get package for request and be anonymous if none configured
-        AuthenticationHandler handler = this.getAuthHandler(req);
-        if (handler == null) {
-            log.debug("authenticate: no authentication needed, anonymous access");
-            return this.getAnonymousSession(req, res);
+        // 0. Nothing to do, if the session is also in the request
+        // this might be the case if the request is handled as a result
+        // of a servlet container include inside another Sling request
+        Object sessionAttr = req.getAttribute(SlingHttpContext.SESSION);
+        if (sessionAttr instanceof Session) {
+            log.debug("authenticate: Request already authenticated, nothing to do");
+            return true;
+        } else if (sessionAttr != null) {
+            // warn and remove existing non-session
+            log.warn(
+                "authenticate: Overwriting existing Session attribute ({})",
+                sessionAttr);
+            req.removeAttribute(SlingHttpContext.SESSION);
         }
 
-        // 1. Check request login session - only if we have sessions
-        // not any more :-)
-
-        // 2. Ask the packages handler for the credentials
-        Credentials creds = handler.authenticate(req, res);
+        // 1. Ask all authentication handlers to try to extract credentials
+        AuthenticationInfo authInfo = getAuthenticationInfo(req, res);
 
         // 3. Check Credentials
-        if (creds == AuthenticationHandler.DOING_AUTH) {
+        if (authInfo == AuthenticationInfo.DOING_AUTH) {
 
             log.debug("authenticate: ongoing authentication in the handler");
-            // is this the correct return value ??
-            return null;
+            return false;
 
-        } else if (creds == null) {
+        } else if (authInfo == null) {
 
             log.debug("authenticate: no credentials in the request, anonymous");
-            return this.getAnonymousSession(req, res);
+            return getAnonymousSession(req, res);
 
         } else {
             // try to connect
             try {
                 log.debug("authenticate: credentials, trying to get a ticket");
-                Session session = getRepository().login(creds, null);
+                Session session = getRepository().login(
+                    authInfo.getCredentials(), null);
 
                 // handle impersonation
-                session = this.handleImpersonation(req, res, session);
+                session = handleImpersonation(req, res, session);
+                setAttributes(session, authInfo.getAuthType(), req);
 
-                return session;
+                return true;
 
             } catch (TooManySessionsException se) {
                 log.info("Too many sessions for user: {}", se.getMessage());
@@ -244,13 +253,11 @@
             }
 
             // request authentication information and send 403 (Forbidden)
-            // if the handler cannot request authentication information.
-            if (!handler.requestAuthentication(req, res)) {
-                this.sendFailure(res);
-            }
+            // if no handler can request authentication information.
+            requestAuthentication(req, res);
 
             // end request
-            return null;
+            return false;
         }
     }
 
@@ -266,22 +273,30 @@
      *
      * @param req The request object
      * @param res The response object to which to send the request
-     * @return true if the information could be requested or false, if the
-     *         request should fail with the appropriate error status
      */
-    public boolean requestAuthentication(HttpServletRequest req,
-            HttpServletResponse res) {
+    public void requestAuthentication(HttpServletRequest request,
+            HttpServletResponse response) {
 
-        AuthenticationHandler handler = this.getAuthHandler(req);
-        if (handler != null) {
-            log.debug("requestAuthentication: requesting authentication using "
-                + "handler: {0}", handler);
+        AuthenticationHandler[] handlers = getAuthenticationHandlers();
+        boolean done = false;
+        for (int i = 0; !done && i < handlers.length; i++) {
+            log.debug(
+                "requestAuthentication: requesting authentication using handler: {0}",
+                handlers[i]);
 
-            return handler.requestAuthentication(req, res);
+            try {
+                done = handlers[i].requestAuthentication(request, response);
+            } catch (IOException ioe) {
+                log.error(
+                    "requestAuthentication: Failed sending authentication request through handler "
+                        + handlers[i] + ", access forbidden", ioe);
+                done = true;
+            }
         }
 
-        log.info("requestAuthentication: no handler found for request");
-        return false;
+        // no handler could send an authentication request, fail with FORBIDDEN
+        log.info("requestAuthentication: No handler for request, sending FORBIDDEN");
+        sendFailure(response);
     }
 
     // ----------- ManagedService interface -----------------------------------
@@ -337,43 +352,31 @@
         return authHandlerCache;
     }
 
-    private AuthenticationHandler getAuthHandler(HttpServletRequest req) {
+    private AuthenticationInfo getAuthenticationInfo(
+            HttpServletRequest request, HttpServletResponse response) {
         AuthenticationHandler[] local = getAuthenticationHandlers();
         for (int i = 0; i < local.length; i++) {
-            if (local[i].handles(req)) {
-                return local[i];
+            AuthenticationInfo authInfo = local[i].authenticate(request,
+                response);
+            if (authInfo != null) {
+                return authInfo;
             }
         }
 
         // no handler found for the request ....
+        log.debug("getCredentials: no handler could extract credentials");
         return null;
     }
 
-    // private AuthPackage getAuthPackage(HttpServletRequest req) {
-    //
-    // // Get the request URI from the request or from the include
-    // String requestURI = req.getRequestURI();
-    // log.debug("getAuthPackage: Check for {0}", requestURI);
-    //
-    // // Look in the packages list
-    // for (int i = 0; i < numPackages; i++) {
-    // if (packages[i].contains(requestURI)) {
-    // return packages[i];
-    // }
-    // }
-    // // invariant: returned or no package found
-    //
-    // // if no package is responsible
-    // return null;
-    // }
-
     // TODO
-    private Session getAnonymousSession(HttpServletRequest req,
+    private boolean getAnonymousSession(HttpServletRequest req,
             HttpServletResponse res) {
         // login anonymously, log the exact cause in case of failure
         if (this.anonymousAllowed) {
             try {
-                return getRepository().login();
+                Session session = getRepository().login();
+                setAttributes(session, null, req);
+                return true;
             } catch (TooManySessionsException se) {
                 log.error(
                     "getAnonymousSession: Too many anonymous users active", se);
@@ -390,12 +393,10 @@
         }
 
         // request authentication now, and fail if not possible
-        if (!this.requestAuthentication(req, res)) {
-            this.sendFailure(res);
-        }
+        requestAuthentication(req, res);
 
         // fallback to no session
-        return null;
+        return false;
     }
 
     // TODO
@@ -409,62 +410,18 @@
     }
 
     /**
-     * Tries to instantiate a handler from the given handler configuration.
-     *
-     * @param defaultPackage The name of the package for the handler class if
-     *            the class name is not a fully qualified class name.
-     * @param className The name of the class. If this is not fully qualified,
-     *            the class is assumed to be in the defaultPackage.
-     * @param configPath The path name (handle) of the handler configuration or
-     *            <code>null</code> if the handler has no configuration.
-     * @throws ServiceException if the handler cannot be instantiated and
-     *             initialized.
-     */
-    // private AuthenticationHandler getHandlerInstance(String defaultPackage,
-    // String className, String configPath) {
-    //
-    // // check fully qualified classname
-    // if (className.indexOf('.') < 0 && defaultPackage != null) {
-    // className = defaultPackage + "." + className;
-    // }
-    //
-    // Exception e = null;
-    // try {
-    // // Read the configuration
-    // Config config = (configPath != null) ? MutableConfig.createFromXml(
-    // null, ticket, configPath) : null;
-    //
-    // // get the instance
-    // Class clazz = classLoader.loadClass(className);
-    // AuthenticationHandler handler = (AuthenticationHandler)
-    // clazz.newInstance();
-    //
-    // // initialize the handler
-    // handler.init(ticket, config);
-    //
-    // // return the handler
-    // return handler;
-    //
-    // } catch (ContentBusException cbe) {
-    // // MutableConfig.createFromXml()
-    // e = cbe;
-    // } catch (ClassNotFoundException cnfe) {
-    // // Class.forName()
-    // e = cnfe;
-    // } catch (InstantiationException ie) {
-    // // newInstance()
-    // e = ie;
-    // } catch (IllegalAccessException iae) {
-    // // newInstance()
-    // e = iae;
-    // } catch (ClassCastException cce) {
-    // // clazz is not an AuthenticationHandler
-    // e = cce;
-    // }
-    //
-    // // invariant : e != null if we get here
-    // throw new ServiceException(e.getMessage(), e);
-    // }
+     * Sets the request attributes required by the OSGi HttpContext interface
+     * specification for the <code>handleSecurity</code> method. In addition
+     * the {@link SlingHttpContext#SESSION} request attribute is set with the
+     * JCR Session.
+     */
+    private void setAttributes(Session session, String authType,
+            HttpServletRequest request) {
+        request.setAttribute(HttpContext.REMOTE_USER, session.getUserID());
+        request.setAttribute(HttpContext.AUTHENTICATION_TYPE, authType);
+        request.setAttribute(SlingHttpContext.SESSION, session);
+    }
+
     /**
      * Sends the session cookie for the name session with the given age in
      * seconds. This sends a Version 1 cookie.
@@ -583,107 +540,4 @@
         return session;
     }
 
-    // ---------- internal class -----------------------------------------------
-
-    /**
-     * The <code>AuthPackage</code> class implements the
-     * {@link ContentPackage} package providing additional information for
-     * handler detection.
-     */
-    // private class AuthPackage implements ContentPackage {
-    //
-    // /**
-    // * The name of the configuration attribute defining the handler to use
-    // * for requests matching this package.
-    // */
-    // private static final String HANDLER_ATTR = "handler";
-    //
-    // /**
-    // * The name of the configuration attribute defining the parameter the
-    // * handler may use when requesting authentication.
-    // */
-    // private static final String PARAM_ATTR = "param";
-    //
-    // /**
-    // * The default value of the parameter attribute
-    // *
-    // * @see #PARAM_ATTR
-    // */
-    // private static final String DEFAULT_PARAM = "";
-    //
-    // /** the name of the handler */
-    // private final String handler;
-    //
-    // /** the addInfo parameter for the requestAuthentication call */
-    // private final String param;
-    //
-    // private final ContentPackage delegatee;
-    //
-    // /**
-    // * Create the package from the configuration element using the given
-    // * handler name as the default handler name
-    // *
-    // * @param config The configuration element on which to base the package
-    // * definition and authentication configuration.
-    // * @param defaultHandler The defualt authentication handler name to use
-    // * if none is specified in the configuration.
-    // */
-    // AuthPackage(Configuration config, String defaultHandler) throws
-    // RepositoryException {
-    // FilterContentPackageBuilder builder = new FilterContentPackageBuilder();
-    // builder.addFilters((Session) null, config);
-    // delegatee = builder.createContentPackage();
-    //
-    // this.handler = config.getString(HANDLER_ATTR, defaultHandler);
-    // this.param = config.getString(PARAM_ATTR, DEFAULT_PARAM);
-    // }
-    //
-    // /**
-    // * Returns the name of the handler to use for requests matching this
-    // * package.
-    // *
-    // * @return The name of the handler to use.
-    // */
-    // String getHandler() {
-    // return handler;
-    // }
-    //
-    // /**
-    // * The parameter to provide to the handler when requesting
-    // * authentication.
-    // *
-    // * @return The authentication request parameter for the handler.
-    // */
-    // String getParam() {
-    // return param;
-    // }
-    //
-    // /**
-    // * @see ContentPackage#contains(String)
-    // */
-    // public boolean contains(String handle) {
-    // return delegatee.contains(handle);
-    // }
-    //
-    // /**
-    // * @see ContentPackage#contains(Ticket, String)
-    // */
-    // public boolean contains(Session session, String handle) {
-    // return delegatee.contains(session, handle);
-    // }
-    //
-    // /**
-    // * @see ContentPackage#contains(Page)
-    // */
-    // public boolean contains(Item item) {
-    // return delegatee.contains(item);
-    // }
-    //
-    // /**
-    // * @see ContentPackage#getTraversingStartPoints()
-    // */
-    // public String[] getTraversingStartPoints() {
-    // return delegatee.getTraversingStartPoints();
-    // }
-    // }
 }

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/helper/SlingServletContext.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/helper/SlingServletContext.java?rev=597404&r1=597403&r2=597404&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/helper/SlingServletContext.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/helper/SlingServletContext.java Thu Nov 22 05:17:02 2007
@@ -21,7 +21,10 @@
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Collections;
+import java.util.Dictionary;
 import java.util.Enumeration;
+import java.util.Hashtable;
 import java.util.Set;
 
 import javax.servlet.RequestDispatcher;
@@ -29,74 +32,191 @@
 import javax.servlet.ServletContext;
 
 import org.apache.sling.core.impl.SlingMainServlet;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The <code>SlingServletContext</code> TODO
+ * The <code>SlingServletContext</code> class is the
+ * <code>ServletContext</code> which is registered as a service usable by
+ * servlets and helpers inside Sling. Most methods just call into the servlet
+ * context in which the {@link SlingMainServlet} is running.
+ * <dl>
+ * <dt><b>MIME Type Mapping</b></dt>
+ * <dd>Just forwards to the servlet context of the {@link SlingMainServlet} for
+ * MIME type mapping.</dd>
+ * <dt><b>Resources</b></dt>
+ * <dd>This class provides access to the resources in the web application by
+ * means of the respective resource accessor methods. These are not the same
+ * resources as available through the <code>ResourceResolver</code>.</dd>
+ * <dt><b>Request Dispatcher</b></dt>
+ * <dd>The {@link #getRequestDispatcher(String)} method returns a
+ * {@link SlingRequestDispatcher} which may dispatch a request inside sling
+ * without going through the servlet container. The
+ * {@link #getNamedDispatcher(String)} method returns a servlet container
+ * request dispatcher which always goes through the servlet container.</dd>
+ * <dt><b>Parameters and Attributes</b></dt>
+ * <dd>Initialization parameters and context attributes are shared with the
+ * servlet context in which the {@link SlingMainServlet} is running.</dd>
+ * <dt><b>Logging</b></dt>
+ * <dd>Logging is diverted to a logger whose name is the fully qualified name
+ * of this class.</dd>
+ * </dl>
  */
 public class SlingServletContext implements ServletContext {
 
     /** default log */
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    SlingMainServlet requestHandler;
+    /** The {@link SlingMainServlet} to which some calls are delegated */
+    private final SlingMainServlet requestHandler;
 
+    /** The service registration of this service as a ManagedService */
+    private final ServiceRegistration registration;
+
+    /**
+     * Creates an instance of this class delegating some methods to the given
+     * {@link SlingMainServlet}. In addition the new instance is registered as
+     * a <code>ManagedService</code> and <code>ServletContext</code> to
+     * receive configuration information.
+     */
     public SlingServletContext(SlingMainServlet requestHandler) {
         this.requestHandler = requestHandler;
+
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(Constants.SERVICE_PID, getClass().getName());
+        props.put(Constants.SERVICE_DESCRIPTION, "Sling ServletContext");
+        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+        registration = requestHandler.getBundleContext().registerService(
+            ServletContext.class.getName(), this, props);
     }
 
     /**
-     * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
+     * Disposes of this servlet context by just unregistering as a service.
      */
-    public Object getAttribute(String name) {
-        return getServletContext().getAttribute(name);
+    public void dispose() {
+        if (registration != null) {
+            registration.unregister();
+        }
     }
 
+    // ---------- Web App configuration ----------------------------------------
+
     /**
-     * @see javax.servlet.ServletContext#getAttributeNames()
+     * Returns the name of the servlet context in which Sling is configured.
+     * This method calls on the <code>ServletContext</code> in which the
+     * {@link SlingMainServlet} is running.
      */
-    @SuppressWarnings("unchecked")
-    public Enumeration<String> getAttributeNames() {
-        return getServletContext().getAttributeNames();
+    public String getServletContextName() {
+        return getServletContext().getServletContextName();
     }
 
     /**
-     * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
+     * Returns the init-param of the servlet context in which Sling is
+     * configured. This method calls on the <code>ServletContext</code> in
+     * which the {@link SlingMainServlet} is running.
      */
     public String getInitParameter(String name) {
         return getServletContext().getInitParameter(name);
     }
 
     /**
-     * @see javax.servlet.ServletContext#getInitParameterNames()
+     * Returns the names of the init-params of the servlet context in which
+     * Sling is configured. This method calls on the <code>ServletContext</code>
+     * in which the {@link SlingMainServlet} is running.
      */
     @SuppressWarnings("unchecked")
     public Enumeration<String> getInitParameterNames() {
         return getServletContext().getInitParameterNames();
     }
 
+    // ---------- attributes ---------------------------------------------------
+
     /**
-     * @see javax.servlet.ServletContext#getMajorVersion()
+     * Returns the named servlet context attribute. This method calls on the
+     * <code>ServletContext</code> in which the {@link SlingMainServlet} is
+     * running.
      */
-    public int getMajorVersion() {
-        return getServletContext().getMajorVersion();
+    public Object getAttribute(String name) {
+        return getServletContext().getAttribute(name);
     }
 
     /**
-     * @see javax.servlet.ServletContext#getMimeType(java.lang.String)
+     * Returns the names of all servlet context attributes. This method calls on
+     * the <code>ServletContext</code> in which the {@link SlingMainServlet}
+     * is running.
      */
-    public String getMimeType(String file) {
-        return getServletContext().getMimeType(file);
+    @SuppressWarnings("unchecked")
+    public Enumeration<String> getAttributeNames() {
+        return getServletContext().getAttributeNames();
+    }
+
+    /**
+     * Removes the named servlet context attribute. This method calls on the
+     * <code>ServletContext</code> in which the {@link SlingMainServlet} is
+     * running.
+     */
+    public void removeAttribute(String name) {
+        getServletContext().removeAttribute(name);
     }
 
     /**
-     * @see javax.servlet.ServletContext#getMinorVersion()
+     * Sets the name servlet context attribute to the requested value. This
+     * method calls on the <code>ServletContext</code> in which the
+     * {@link SlingMainServlet} is running.
+     */
+    public void setAttribute(String name, Object object) {
+        getServletContext().removeAttribute(name);
+    }
+
+    // ---------- Servlet Container information --------------------------------
+
+    /**
+     * Returns the Sling server info string. This is not the same server info
+     * string as returned by the servlet context in which Sling is configured.
+     */
+    public String getServerInfo() {
+        return requestHandler.getServerInfo();
+    }
+
+    /**
+     * Returns the major version number of the Servlet API supported by the
+     * servlet container in which Sling is running. This method calls on the
+     * <code>ServletContext</code> in which the {@link SlingMainServlet} is
+     * running.
+     */
+    public int getMajorVersion() {
+        return getServletContext().getMajorVersion();
+    }
+
+    /**
+     * Returns the minor version number of the Servlet API supported by the
+     * servlet container in which Sling is running. This method calls on the
+     * <code>ServletContext</code> in which the {@link SlingMainServlet} is
+     * running.
      */
     public int getMinorVersion() {
         return getServletContext().getMinorVersion();
     }
 
+    // ---------- MIME type mapping --------------------------------------------
+
+    /**
+     * Returns a MIME type for the extension of the given file name. This method
+     * calls on the <code>ServletContext</code> in which the
+     * {@link SlingMainServlet} is running.
+     */
+    public String getMimeType(String file) {
+        return getServletContext().getMimeType(file);
+    }
+
+    // ---------- Request Dispatcher -------------------------------------------
+
+    /**
+     * Returns a {@link SlingRequestDispatcher} for the given path if not
+     * <code>null</code>. Otherwise <code>null</code> is returned.
+     */
     public RequestDispatcher getRequestDispatcher(String path) {
         // return no dispatcher if content is null
         if (path == null) {
@@ -107,91 +227,110 @@
         return new SlingRequestDispatcher(path);
     }
 
+    /**
+     * Returns a servlet container request dispatcher for the named servlet.
+     * This method calls on the <code>ServletContext</code> in which the
+     * {@link SlingMainServlet} is running.
+     */
+    public RequestDispatcher getNamedDispatcher(String name) {
+        return getServletContext().getNamedDispatcher(name);
+    }
+
+    // ---------- Resource Access ----------------------------------------------
+
+    /**
+     * Returns the URI for the given path. This method calls on the
+     * <code>ServletContext</code> in which the {@link SlingMainServlet} is
+     * running.
+     */
     public URL getResource(String path) throws MalformedURLException {
-        // TODO Auto-generated method stub
-        return null;
+        return getServletContext().getResource(path);
     }
 
+    /**
+     * Returns an input stream to the given path. This method calls on the
+     * <code>ServletContext</code> in which the {@link SlingMainServlet} is
+     * running.
+     */
     public InputStream getResourceAsStream(String path) {
-        // TODO Auto-generated method stub
-        return null;
+        return getServletContext().getResourceAsStream(path);
     }
 
-    public Set getResourcePaths(String arg0) {
-        // TODO Auto-generated method stub
-        return null;
+    /**
+     * Returns a set of names for path entries considered children of the given
+     * path. This method calls on the <code>ServletContext</code> in which the
+     * {@link SlingMainServlet} is running.
+     */
+    @SuppressWarnings("unchecked")
+    public Set<String> getResourcePaths(String parentPath) {
+        return getServletContext().getResourcePaths(parentPath);
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see javax.servlet.ServletContext#getServerInfo()
+    /**
+     * Returns the real file inside the web application to which the given path
+     * maps or <code>null</code> if no such file exists. This method calls on
+     * the <code>ServletContext</code> in which the {@link SlingMainServlet}
+     * is running.
      */
-    public String getServerInfo() {
-        return requestHandler.getServerInfo();
+    public String getRealPath(String path) {
+        return getServletContext().getRealPath(path);
     }
 
+    // ---------- logging ------------------------------------------------------
+
+    /** Logs the message and optional throwable at error level to the logger */
     public void log(String message, Throwable throwable) {
         log.error(message, throwable);
     }
 
-    public void log(String msg) {
-        log.info(msg);
+    /** Logs the message at info level to the logger */
+    public void log(String message) {
+        log.info(message);
     }
 
-    public void log(Exception exception, String msg) {
-        log(msg, exception);
+    /** Logs the message and optional exception at error level to the logger */
+    @Deprecated
+    public void log(Exception exception, String message) {
+        log(message, exception);
     }
 
-    /**
-     * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
-     */
-    public void removeAttribute(String name) {
-        getServletContext().removeAttribute(name);
-    }
+    // ---------- foreign Servlets ---------------------------------------------
 
     /**
-     * @see javax.servlet.ServletContext#setAttribute(java.lang.String,
-     *      java.lang.Object)
+     * Returns the servlet context from the servlet container in which sling is
+     * running. This method calls on the <code>ServletContext</code> in which
+     * the {@link SlingMainServlet} is running.
      */
-    public void setAttribute(String name, Object object) {
-        getServletContext().removeAttribute(name);
-    }
-
-    private ServletContext getServletContext() {
-        return requestHandler.getServletContext();
-    }
-
     public ServletContext getContext(String uripath) {
-        // check whether to return ComponentContext ??
         return getServletContext().getContext(uripath);
     }
 
-    public RequestDispatcher getNamedDispatcher(String name) {
-        return getServletContext().getNamedDispatcher(name);
-    }
-
-    public String getRealPath(String path) {
-        return getServletContext().getRealPath(path);
-    }
-
-    public String getServletContextName() {
-        return getServletContext().getServletContextName();
-    }
-
+    /** Returns <code>null</code> as defined in Servlet API 2.4 */
     @Deprecated
     public Servlet getServlet(String name) {
         return null;
     }
 
+    /** Returns <code>null</code> as defined in Servlet API 2.4 */
     @Deprecated
     public Enumeration<?> getServletNames() {
-        return null;
+        return Collections.enumeration(Collections.emptyList());
     }
 
+    /** Returns <code>null</code> as defined in Servlet API 2.4 */
     @Deprecated
     public Enumeration<?> getServlets() {
-        return null;
+        return Collections.enumeration(Collections.emptyList());
+    }
+
+    // ---------- internal -----------------------------------------------------
+
+    /**
+     * Returns the real servlet context of the servlet container in which the
+     * Sling Servlet is running.
+     */
+    private ServletContext getServletContext() {
+        return requestHandler.getServletContext();
     }
 
 }