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 2010/01/06 08:55:12 UTC

svn commit: r896345 [2/3] - in /sling/trunk/bundles/commons/auth: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/commons/ src/main/java/org/apache/sling/commo...

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,906 @@
+/*
+ * 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.commons.auth.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.commons.auth.AuthenticationSupport;
+import org.apache.sling.commons.auth.Authenticator;
+import org.apache.sling.commons.auth.NoAuthenticationHandlerException;
+import org.apache.sling.commons.auth.impl.engine.EngineAuthenticationHandlerHolder;
+import org.apache.sling.commons.auth.spi.AuthenticationHandler;
+import org.apache.sling.commons.auth.spi.AuthenticationInfo;
+import org.apache.sling.commons.osgi.OsgiUtil;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.api.TooManySessionsException;
+import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
+import org.osgi.framework.AllServiceListener;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.http.HttpContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>SlingAuthenticator</code> class is the default implementation for
+ * handling authentication. This class supports :
+ * <ul>
+ * <li>Support for login sessions where session ids are exchanged with cookies
+ * <li>Support for multiple authentication handlers, which must implement the
+ * {@link AuthenticationHandler} interface.
+ * <li>
+ * <p>
+ * Currently this class does not support multiple handlers for any one request
+ * URL.
+ * <p>
+ * Clients of this class use {@link #authenticate} method to create a
+ * {@link AuthenticationInfo} for the handling of the request. This method uses
+ * any of the handlers to extract the user information from the request. Next an
+ * object is created for this user information. If no user information is
+ * contained in the request (according to the handler), the anonymous info is
+ * used.
+ * <p>
+ *
+ * @scr.component name="org.apache.sling.engine.impl.auth.SlingAuthenticator"
+ *                label="%auth.name" description="%auth.description"
+ *                modified="modified" immediate="true" Register for three
+ *                services
+ * @scr.service interface="org.apache.sling.commons.auth.AuthenticationSupport"
+ * @scr.service interface="org.apache.sling.commons.auth.Authenticator"
+ * @scr.service interface="javax.servlet.ServletRequestListener"
+ * @scr.property name="service.description" value="Sling Request Authenticator"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ * @scr.reference name="authHandler"
+ *                interface="org.apache.sling.commons.auth.spi.AuthenticationHandler"
+ *                policy="dynamic" cardinality="0..n" bind="bindAuthHandler"
+ *                unbind="unbindAuthHandler"
+ * @scr.reference name="engineAuthHandler"
+ *                interface="org.apache.sling.engine.auth.AuthenticationHandler"
+ *                policy="dynamic" cardinality="0..n"
+ *                bind="bindEngineAuthHandler" unbind="unbindEngineAuthHandler"
+ */
+public class SlingAuthenticator implements Authenticator,
+        AuthenticationSupport, ServletRequestListener {
+
+    static final String REQUEST_ATTRIBUTE_SESSION = "javax.jcr.Session";
+
+    /** default log */
+    private static final Logger log = LoggerFactory.getLogger(SlingAuthenticator.class);
+
+    /**
+     * @scr.property valueRef="DEFAULT_IMPERSONATION_COOKIE"
+     */
+    public static final String PAR_IMPERSONATION_COOKIE_NAME = "auth.sudo.cookie";
+
+    /**
+     * @scr.property valueRef="DEFAULT_IMPERSONATION_PARAMETER"
+     */
+    public static final String PAR_IMPERSONATION_PAR_NAME = "auth.sudo.parameter";
+
+    /**
+     * @scr.property valueRef="DEFAULT_ANONYMOUS_ALLOWED" type="Boolean"
+     */
+    public static final String PAR_ANONYMOUS_ALLOWED = "auth.annonymous";
+
+    /**
+     * @scr.property type="String" cardinality="+"
+     */
+    private static final String PAR_AUTH_REQ = "sling.auth.requirements";
+
+    /** The default impersonation parameter name */
+    private static final String DEFAULT_IMPERSONATION_PARAMETER = "sudo";
+
+    /** The default impersonation cookie name */
+    private static final String DEFAULT_IMPERSONATION_COOKIE = "sling.sudo";
+
+    /** The default value for allowing anonymous access */
+    private static final boolean DEFAULT_ANONYMOUS_ALLOWED = true;
+
+    private static ArrayList<AbstractAuthenticationHandlerHolder> EMPTY_INFO = new ArrayList<AbstractAuthenticationHandlerHolder>();
+
+    /** @scr.reference */
+    private SlingRepository repository;
+
+    /** @scr.reference */
+    private JcrResourceResolverFactory resourceResolverFactory;
+
+    private PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authHandlerCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
+
+    // package protected for access in inner class ...
+    PathBasedHolderCache<AuthenticationRequirementHolder> authRequiredCache = new PathBasedHolderCache<AuthenticationRequirementHolder>();
+
+    /** The name of the impersonation parameter */
+    private String sudoParameterName;
+
+    /** The name of the impersonation cookie */
+    private String sudoCookieName;
+
+    /** Cache control flag */
+    private boolean cacheControl;
+
+    /** Web Console Plugin service registration */
+    private ServiceRegistration webConsolePlugin;
+
+    /**
+     * The listener for services registered with "sling.auth.requirements" to
+     * update the internal authentication requirements
+     */
+    private ServiceListener serviceListener;
+
+    // ---------- SCR integration
+
+    @SuppressWarnings("unused")
+    private void activate(final BundleContext bundleContext,
+            final Map<String, Object> properties) {
+        modified(properties);
+
+        AuthenticatorWebConsolePlugin plugin = new AuthenticatorWebConsolePlugin(
+            this);
+        Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put("felix.webconsole.label", plugin.getLabel());
+        props.put("felix.webconsole.title", plugin.getTitle());
+        props.put("service.description",
+            "Sling Request Authenticator WebConsole Plugin");
+        props.put("service.vendor", properties.get("service.vendor"));
+
+        webConsolePlugin = bundleContext.registerService(
+            "javax.servlet.Servlet", plugin, props);
+
+        serviceListener = SlingAuthenticatorServiceListener.createListener(
+            bundleContext, this);
+    }
+
+    private void modified(Map<String, Object> properties) {
+        if (properties == null) {
+            properties = new HashMap<String, Object>();
+        }
+
+        String newCookie = (String) properties.get(PAR_IMPERSONATION_COOKIE_NAME);
+        if (newCookie == null || newCookie.length() == 0) {
+            newCookie = DEFAULT_IMPERSONATION_COOKIE;
+        }
+        if (!newCookie.equals(this.sudoCookieName)) {
+            log.info("Setting new cookie name for impersonation {} (was {})",
+                newCookie, this.sudoCookieName);
+            this.sudoCookieName = newCookie;
+        }
+
+        String newPar = (String) properties.get(PAR_IMPERSONATION_PAR_NAME);
+        if (newPar == null || newPar.length() == 0) {
+            newPar = DEFAULT_IMPERSONATION_PARAMETER;
+        }
+        if (!newPar.equals(this.sudoParameterName)) {
+            log.info(
+                "Setting new parameter name for impersonation {} (was {})",
+                newPar, this.sudoParameterName);
+            this.sudoParameterName = newPar;
+        }
+
+        authRequiredCache.clear();
+
+        boolean flag = OsgiUtil.toBoolean(
+            properties.get(PAR_ANONYMOUS_ALLOWED), DEFAULT_ANONYMOUS_ALLOWED);
+        authRequiredCache.addHolder(new AuthenticationRequirementHolder("/",
+            !flag));
+
+        String[] authReqs = OsgiUtil.toStringArray(properties.get(PAR_AUTH_REQ));
+        if (authReqs != null) {
+            for (String authReq : authReqs) {
+                if (authReq != null && authReq.length() > 0) {
+                    authRequiredCache.addHolder(AuthenticationRequirementHolder.fromConfig(authReq));
+                }
+            }
+        }
+
+        // don't require authentication for login/logout servlets
+        authRequiredCache.addHolder(new AuthenticationRequirementHolder(
+            LoginServlet.SERVLET_PATH, false));
+        authRequiredCache.addHolder(new AuthenticationRequirementHolder(
+            LogoutServlet.SERVLET_PATH, false));
+    }
+
+    @SuppressWarnings("unused")
+    private void deactivate(final BundleContext bundleContext) {
+        if (serviceListener != null) {
+            bundleContext.removeServiceListener(serviceListener);
+            serviceListener = null;
+        }
+
+        if (webConsolePlugin != null) {
+            webConsolePlugin.unregister();
+            webConsolePlugin = null;
+        }
+    }
+
+    // --------- AuthenticationSupport interface
+
+    /**
+     * Checks the authentication contained in the request. This check is only
+     * based on the original request object, no URI translation has taken place
+     * yet.
+     * <p>
+     *
+     * @param req The request object containing the information for the
+     *            authentication.
+     * @param res The response object which may be used to send the information
+     *            on the request failure to the user.
+     */
+    public boolean handleSecurity(HttpServletRequest request,
+            HttpServletResponse response) {
+
+        // 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 = request.getAttribute(REQUEST_ATTRIBUTE_RESOLVER);
+        if (sessionAttr instanceof ResourceResolver) {
+            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 ResourceResolver attribute ({})",
+                sessionAttr);
+            request.removeAttribute(REQUEST_ATTRIBUTE_RESOLVER);
+        }
+
+        // 1. Ask all authentication handlers to try to extract credentials
+        AuthenticationInfo authInfo = getAuthenticationInfo(request, response);
+
+        // 3. Check Credentials
+        if (authInfo == AuthenticationInfo.DOING_AUTH) {
+
+            log.debug("authenticate: ongoing authentication in the handler");
+            return false;
+
+        } else if (authInfo == null) {
+
+            log.debug("authenticate: no credentials in the request, anonymous");
+            return getAnonymousSession(request, response);
+
+        } else {
+            // try to connect
+            try {
+                log.debug("authenticate: credentials, trying to get a session");
+                Session session = repository.login(authInfo.getCredentials(),
+                    authInfo.getWorkspaceName());
+
+                // handle impersonation
+                session = handleImpersonation(request, response, session);
+                setAttributes(session, authInfo.getAuthType(), request);
+
+                return true;
+
+            } catch (RepositoryException re) {
+
+                handleLoginFailure(request, response, re);
+
+            }
+
+            // end request
+            return false;
+        }
+    }
+
+    // ---------- Authenticator interface
+
+    /**
+     * Requests authentication information from the client. Returns
+     * <code>true</code> if the information has been requested and request
+     * processing can be terminated. Otherwise the request information could not
+     * be requested and the request should be terminated with a 403/FORBIDDEN
+     * response.
+     * <p>
+     * Any response sent by the handler is also handled by the error handler
+     * infrastructure.
+     *
+     * @param request The request object
+     * @param response The response object to which to send the request
+     * @throws IllegalStateException If response is already committed
+     * @throws NoAuthenticationHandlerException If no authentication handler
+     *             claims responsibility to authenticate the request.
+     */
+    public void login(HttpServletRequest request, HttpServletResponse response) {
+
+        // ensure the response is not committed yet
+        if (response.isCommitted()) {
+            throw new IllegalStateException("Response already committed");
+        }
+
+        // select path used for authentication handler selection
+        final ArrayList<AbstractAuthenticationHandlerHolder> holderList = findApplicableAuthenticationHandlers(request);
+        final String path = getHandlerSelectionPath(request);
+        boolean done = false;
+        for (int i = 0; !done && i < holderList.size(); i++) {
+            final AbstractAuthenticationHandlerHolder holder = holderList.get(i);
+            if (path.startsWith(holder.path)) {
+                log.debug("login: requesting authentication using handler: {}",
+                    holder);
+
+                try {
+                    done = holder.requestAuthentication(request, response);
+                } catch (IOException ioe) {
+                    log.error(
+                        "login: Failed sending authentication request through handler "
+                            + holder + ", access forbidden", ioe);
+                    done = true;
+                }
+            }
+        }
+
+        // no handler could send an authentication request, throw
+        if (!done) {
+            log.info("login: No handler for request ({} handlers available)",
+                holderList.size());
+            throw new NoAuthenticationHandlerException();
+        }
+    }
+
+    /**
+     * Logs out the user calling all applicable
+     * {@link org.apache.sling.engine.auth.AuthenticationHandler2}
+     * authentication handlers.
+     *
+     * @since 2.1
+     */
+    public void logout(HttpServletRequest request, HttpServletResponse response) {
+
+        // ensure the response is not committed yet
+        if (response.isCommitted()) {
+            throw new IllegalStateException("Response already committed");
+        }
+
+        final ArrayList<AbstractAuthenticationHandlerHolder> holderList = findApplicableAuthenticationHandlers(request);
+        final String path = getHandlerSelectionPath(request);
+        for (int i = 0; i < holderList.size(); i++) {
+            AbstractAuthenticationHandlerHolder holder = holderList.get(i);
+            if (path.startsWith(holder.path)) {
+                log.debug("logout: dropping authentication using handler: {}",
+                    holder);
+
+                try {
+                    holder.dropAuthentication(request, response);
+                } catch (IOException ioe) {
+                    log.error(
+                        "logout: Failed dropping authentication through handler "
+                            + holder, ioe);
+                }
+            }
+        }
+    }
+
+    // ---------- ServletRequestListener
+
+    public void requestInitialized(ServletRequestEvent sre) {
+        // don't care
+    }
+
+    public void requestDestroyed(ServletRequestEvent sre) {
+        ServletRequest request = sre.getServletRequest();
+        Object sessionAttr = request.getAttribute(SlingAuthenticatorSession.ATTR_NAME);
+        if (sessionAttr instanceof SlingAuthenticatorSession) {
+            ((SlingAuthenticatorSession) sessionAttr).logout();
+
+            request.removeAttribute(REQUEST_ATTRIBUTE_RESOLVER);
+            request.removeAttribute(REQUEST_ATTRIBUTE_SESSION);
+            request.removeAttribute(SlingAuthenticatorSession.ATTR_NAME);
+        }
+    }
+
+    // ---------- WebConsolePlugin support
+
+    ArrayList<AbstractAuthenticationHandlerHolder> getAuthenticationHandler() {
+        return authHandlerCache.getHolders();
+    }
+
+    ArrayList<AuthenticationRequirementHolder> getAuthenticationRequirements() {
+        return authRequiredCache.getHolders();
+    }
+
+    // ---------- internal
+
+    private ArrayList<AbstractAuthenticationHandlerHolder> findApplicableAuthenticationHandlers(
+            HttpServletRequest request) {
+
+        final ArrayList<AbstractAuthenticationHandlerHolder> infos = authHandlerCache.findApplicableHolder(request);
+        if (infos != null) {
+            return infos;
+        }
+
+        return EMPTY_INFO;
+    }
+
+    @SuppressWarnings("unused")
+    private void bindAuthHandler(final AuthenticationHandler handler,
+            Map<String, Object> properties) {
+        final String paths[] = OsgiUtil.toStringArray(properties.get(AuthenticationHandler.PATH_PROPERTY));
+        if (paths != null && paths.length > 0) {
+            for (int m = 0; m < paths.length; m++) {
+                if (paths[m] != null && paths[m].length() > 0) {
+                    final AuthenticationHandlerHolder holder = new AuthenticationHandlerHolder(
+                        paths[m], handler);
+                    authHandlerCache.addHolder(holder);
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private void unbindAuthHandler(AuthenticationHandler handler,
+            Map<String, Object> properties) {
+        final String paths[] = OsgiUtil.toStringArray(properties.get(AuthenticationHandler.PATH_PROPERTY));
+        if (paths != null && paths.length > 0) {
+            for (int m = 0; m < paths.length; m++) {
+                if (paths[m] != null && paths[m].length() > 0) {
+                    final AuthenticationHandlerHolder holder = new AuthenticationHandlerHolder(
+                        paths[m], handler);
+                    authHandlerCache.removeHolder(holder);
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings( { "unused", "deprecation" })
+    private void bindEngineAuthHandler(
+            org.apache.sling.engine.auth.AuthenticationHandler handler,
+            Map<String, Object> properties) {
+        final String paths[] = OsgiUtil.toStringArray(properties.get(AuthenticationHandler.PATH_PROPERTY));
+        if (paths != null && paths.length > 0) {
+            for (int m = 0; m < paths.length; m++) {
+                if (paths[m] != null && paths[m].length() > 0) {
+                    final EngineAuthenticationHandlerHolder holder = new EngineAuthenticationHandlerHolder(
+                        paths[m], handler);
+                    authHandlerCache.addHolder(holder);
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings( { "unused", "deprecation" })
+    private void unbindEngineAuthHandler(
+            org.apache.sling.engine.auth.AuthenticationHandler handler,
+            Map<String, Object> properties) {
+        final String paths[] = OsgiUtil.toStringArray(properties.get(AuthenticationHandler.PATH_PROPERTY));
+        if (paths != null && paths.length > 0) {
+            for (int m = 0; m < paths.length; m++) {
+                if (paths[m] != null && paths[m].length() > 0) {
+                    final EngineAuthenticationHandlerHolder holder = new EngineAuthenticationHandlerHolder(
+                        paths[m], handler);
+                    authHandlerCache.removeHolder(holder);
+                }
+            }
+        }
+    }
+
+    private AuthenticationInfo getAuthenticationInfo(
+            HttpServletRequest request, HttpServletResponse response) {
+
+        // Get the path used to select the authenticator, if the SlingServlet
+        // itself has been requested without any more info, this will be null
+        // and we assume the root (SLING-722)
+        String pathInfo = request.getPathInfo();
+        if (pathInfo == null || pathInfo.length() == 0) {
+            pathInfo = "/";
+        }
+
+        ArrayList<AbstractAuthenticationHandlerHolder> local = findApplicableAuthenticationHandlers(request);
+        for (int i = 0; i < local.size(); i++) {
+            AbstractAuthenticationHandlerHolder holder = local.get(i);
+            if (pathInfo.startsWith(holder.path)) {
+                final AuthenticationInfo authInfo = holder.authenticate(
+                    request, response);
+                if (authInfo != null) {
+                    return authInfo;
+                }
+            }
+        }
+
+        // no handler found for the request ....
+        log.debug("getCredentials: no handler could extract credentials");
+        return null;
+    }
+
+    /** Try to acquire an anonymous Session */
+    private boolean getAnonymousSession(HttpServletRequest req,
+            HttpServletResponse res) {
+
+        // Get an anonymous session if allowed, or if we are handling
+        // a request for the login servlet
+        if (isAnonAllowed(req)) {
+            try {
+                Session session = repository.login();
+                setAttributes(session, null, req);
+                return true;
+            } catch (RepositoryException re) {
+                // cannot login > fail login, do not try to authenticate
+                handleLoginFailure(req, res, re);
+                return false;
+            }
+        }
+
+        // If we get here, anonymous access is not allowed: redirect
+        // to the login servlet
+        log.info("getAnonymousSession: Anonymous access not allowed by configuration - redirecting to login");
+        login(req, res);
+
+        // fallback to no session
+        return false;
+    }
+
+    private boolean isAnonAllowed(HttpServletRequest request) {
+
+        String pathInfo = request.getPathInfo();
+        if (pathInfo == null || pathInfo.length() == 0) {
+            pathInfo = "/";
+        }
+
+        ArrayList<AuthenticationRequirementHolder> holderList = authRequiredCache.findApplicableHolder(request);
+        if (holderList != null && !holderList.isEmpty()) {
+            for (int i = 0; i < holderList.size(); i++) {
+                AuthenticationRequirementHolder holder = holderList.get(i);
+                if (pathInfo.startsWith(holder.path)) {
+                    return !holder.requiresAuthentication();
+                }
+            }
+        }
+
+        if (LoginServlet.SERVLET_PATH.equals(pathInfo)) {
+            return true;
+        }
+
+        // fallback to anonymous not allowed (aka authentication required)
+        return false;
+    }
+
+    private void handleLoginFailure(HttpServletRequest request,
+            HttpServletResponse response, Exception reason) {
+
+        if (reason instanceof TooManySessionsException) {
+
+            // to many users, send a 503 Service Unavailable
+            log.info("authenticate: Too many sessions for user: {}",
+                reason.getMessage());
+
+            try {
+                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
+                    "SlingAuthenticator: Too Many Users");
+            } catch (IOException ioe) {
+                log.error("authenticate: Cannot send status 503 to client", ioe);
+            }
+
+        } else if (reason instanceof LoginException) {
+
+            // request authentication information and send 403 (Forbidden)
+            // if no handler can request authentication information.
+            log.info("authenticate: Unable to authenticate: {}",
+                reason.getMessage());
+            log.debug("authenticate", reason);
+
+            login(request, response);
+
+        } else {
+
+            // general problem, send a 500 Internal Server Error
+            log.error("authenticate: Unable to authenticate", reason);
+
+            try {
+                response.sendError(
+                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "SlingAuthenticator: data access error, reason="
+                        + reason.getClass().getSimpleName());
+            } catch (IOException ioe) {
+                log.error("authenticate: Cannot send status 500 to client", ioe);
+            }
+        }
+
+    }
+
+    /**
+     * 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(final Session session, final String authType,
+            final HttpServletRequest request) {
+
+        final ResourceResolver resolver = resourceResolverFactory.getResourceResolver(session);
+        final SlingAuthenticatorSession sas = new SlingAuthenticatorSession(
+            session);
+
+        // HttpService API required attributes
+        request.setAttribute(HttpContext.REMOTE_USER, session.getUserID());
+        request.setAttribute(HttpContext.AUTHENTICATION_TYPE, authType);
+
+        // resource resolver for down-stream use
+        request.setAttribute(REQUEST_ATTRIBUTE_RESOLVER, resolver);
+        request.setAttribute(SlingAuthenticatorSession.ATTR_NAME, sas);
+
+        // JCR session for backwards compatibility
+        request.setAttribute(REQUEST_ATTRIBUTE_SESSION, session);
+
+        log.debug(
+            "ResourceResolver stored as request attribute: user={}, workspace={}",
+            session.getUserID(), session.getWorkspace().getName());
+    }
+
+    /**
+     * Sends the session cookie for the name session with the given age in
+     * seconds. This sends a Version 1 cookie.
+     *
+     * @param response The {@link DeliveryHttpServletResponse} on which to send
+     *            back the cookie.
+     * @param name The name of the cookie to send.
+     * @param value The value of cookie.
+     * @param maxAge The maximum age of the cookie in seconds. Positive values
+     *            are persisted on the browser for the indicated number of
+     *            seconds, setting the age to 0 (zero) causes the cookie to be
+     *            deleted in the browser and using a negative value defines a
+     *            temporary cookie to be deleted when the browser exits.
+     * @param path The cookie path to use. If empty or <code>null</code> the
+     */
+    private void sendCookie(HttpServletResponse response, String name,
+            String value, int maxAge, String path) {
+
+        if (path == null || path.length() == 0) {
+            log.debug("sendCookie: Using root path ''/''");
+            path = "/";
+        }
+
+        Cookie cookie = new Cookie(name, value);
+        cookie.setMaxAge(maxAge);
+        cookie.setPath(path);
+        response.addCookie(cookie);
+
+        // Tell a potential proxy server that this cookie is uncacheable
+        if (this.cacheControl) {
+            response.addHeader("Cache-Control", "no-cache=\"Set-Cookie\"");
+        }
+    }
+
+    /**
+     * Handles impersonation based on the request parameter for impersonation
+     * (see {@link #sudoParameterName}) and the current setting in the sudo
+     * cookie.
+     * <p>
+     * If the sudo parameter is empty or missing, the current cookie setting for
+     * impersonation is used. Else if the parameter is <code>-</code>, the
+     * current cookie impersonation is removed and no impersonation will take
+     * place for this request. Else the parameter is assumed to contain the
+     * handle of a user page acceptable for the {@link Session#impersonate}
+     * method.
+     *
+     * @param req The {@link DeliveryHttpServletRequest} optionally containing
+     *            the sudo parameter.
+     * @param res The {@link DeliveryHttpServletResponse} to send the
+     *            impersonation cookie.
+     * @param session The real {@link Session} to optionally replace with an
+     *            impersonated session.
+     * @return The impersonated session or the input session.
+     * @throws LoginException thrown by the {@link Session#impersonate} method.
+     * @throws ContentBusException thrown by the {@link Session#impersonate}
+     *             method.
+     * @see Session#impersonate for details on the user configuration
+     *      requirements for impersonation.
+     */
+    private Session handleImpersonation(HttpServletRequest req,
+            HttpServletResponse res, Session session) throws LoginException,
+            RepositoryException {
+
+        // the current state of impersonation
+        String currentSudo = null;
+        Cookie[] cookies = req.getCookies();
+        if (cookies != null) {
+            for (int i = 0; currentSudo == null && i < cookies.length; i++) {
+                if (sudoCookieName.equals(cookies[i].getName())) {
+                    currentSudo = cookies[i].getValue();
+                }
+            }
+        }
+
+        /**
+         * sudo parameter : empty or missing to continue to use the setting
+         * already stored in the session; or "-" to remove impersonationa
+         * altogether (also from the session); or the handle of a user page to
+         * impersonate as that user (if possible)
+         */
+        String sudo = req.getParameter(this.sudoParameterName);
+        if (sudo == null || sudo.length() == 0) {
+            sudo = currentSudo;
+        } else if ("-".equals(sudo)) {
+            sudo = null;
+        }
+
+        // sudo the session if needed
+        if (sudo != null && sudo.length() > 0) {
+            Credentials creds = new SimpleCredentials(sudo, new char[0]);
+            session = session.impersonate(creds);
+        }
+        // invariant: same session or successful impersonation
+
+        // set the (new) impersonation
+        if (sudo != currentSudo) {
+            if (sudo == null) {
+                // Parameter set to "-" to clear impersonation, which was
+                // active due to cookie setting
+
+                // clear impersonation
+                this.sendCookie(res, this.sudoCookieName, "", 0,
+                    req.getContextPath());
+
+            } else if (currentSudo == null || !currentSudo.equals(sudo)) {
+                // Parameter set to a name. As the cookie is not set yet
+                // or is set to another name, send the cookie with current sudo
+
+                // (re-)set impersonation
+                this.sendCookie(res, this.sudoCookieName, sudo, -1,
+                    req.getContextPath());
+            }
+        }
+
+        // return the session
+        return session;
+    }
+
+    /**
+     * Returns the path to be used to select the authentication handler to login
+     * or logout with.
+     * <p>
+     * This method uses the {@link Authenticator#LOGIN_RESOURCE} request
+     * attribute. If this attribute is not set (or is not a string), the request
+     * path info is used. If this is not set either, or is the empty string, "/"
+     * is returned.
+     *
+     * @param request The request providing the request attribute or path info.
+     * @return The path as set by the request attribute or the path info or "/"
+     *         if neither is set.
+     */
+    private String getHandlerSelectionPath(HttpServletRequest request) {
+        final Object loginPathO = request.getAttribute(Authenticator.LOGIN_RESOURCE);
+        String path = (loginPathO instanceof String)
+                ? (String) loginPathO
+                : request.getPathInfo();
+        if (path == null || path.length() == 0) {
+            path = "/";
+        }
+        return path;
+    }
+
+    private static class SlingAuthenticatorSession {
+
+        static final String ATTR_NAME = "$$org.apache.sling.commons.auth.impl.SlingAuthenticatorSession$$";
+
+        private Session session;
+
+        SlingAuthenticatorSession(final Session session) {
+            this.session = session;
+        }
+
+        void logout() {
+            if (session != null) {
+                try {
+                    // logout if session is still alive (and not logged out)
+                    if (session.isLive()) {
+                        session.logout();
+                    }
+                } catch (Throwable t) {
+                    // TODO: log
+                } finally {
+                    session = null;
+                }
+            }
+        }
+
+        @Override
+        protected void finalize() {
+            logout();
+        }
+    }
+
+    private static class SlingAuthenticatorServiceListener implements
+            AllServiceListener {
+
+        private final SlingAuthenticator authenticator;
+
+        private final HashMap<Object, String[]> props = new HashMap<Object, String[]>();
+
+        static ServiceListener createListener(final BundleContext context,
+                final SlingAuthenticator authenticator) {
+            SlingAuthenticatorServiceListener listener = new SlingAuthenticatorServiceListener(
+                authenticator);
+            try {
+                final String filter =  "(" + PAR_AUTH_REQ + "=*)";
+                context.addServiceListener(listener,filter);
+                ServiceReference[] refs = context.getAllServiceReferences(null, filter);
+                if (refs != null) {
+                    for (ServiceReference ref : refs) {
+                        listener.addService(ref);
+                    }
+                }
+                return listener;
+            } catch (InvalidSyntaxException ise) {
+            }
+            return null;
+        }
+
+        private SlingAuthenticatorServiceListener(
+                final SlingAuthenticator authenticator) {
+            this.authenticator = authenticator;
+        }
+
+        public void serviceChanged(ServiceEvent event) {
+
+            // modification of service properties, unregistration of the
+            // service or service properties does not contain requirements
+            // property any longer (new event with type 8 added in OSGi Core
+            // 4.2)
+            if ((event.getType() & (ServiceEvent.MODIFIED
+                | ServiceEvent.UNREGISTERING | 8)) != 0) {
+                removeService(event.getServiceReference());
+            }
+
+            // add requirements for newly registered services and for
+            // updated services
+            if ((event.getType() & (ServiceEvent.REGISTERED | ServiceEvent.MODIFIED)) != 0) {
+                addService(event.getServiceReference());
+            }
+        }
+
+        private void addService(final ServiceReference ref) {
+            String[] authReqs = OsgiUtil.toStringArray(ref.getProperty(PAR_AUTH_REQ));
+            for (String authReq : authReqs) {
+                if (authReq != null && authReq.length() > 0) {
+                    authenticator.authRequiredCache.addHolder(AuthenticationRequirementHolder.fromConfig(authReq));
+                }
+            }
+            props.put(ref.getProperty(Constants.SERVICE_ID), authReqs);
+        }
+
+        private void removeService(final ServiceReference ref) {
+            String[] authReqs = props.remove(ref.getProperty(Constants.SERVICE_ID));
+            for (String authReq : authReqs) {
+                if (authReq != null && authReq.length() > 0) {
+                    authenticator.authRequiredCache.removeHolder(AuthenticationRequirementHolder.fromConfig(authReq));
+                }
+            }
+        }
+    };
+
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,96 @@
+/*
+ * 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.commons.auth.impl.engine;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.auth.impl.AbstractAuthenticationHandlerHolder;
+import org.apache.sling.commons.auth.spi.AuthenticationInfo;
+import org.apache.sling.engine.auth.AuthenticationHandler;
+
+/**
+ * The <code>EngineAuthenticationHandlerHolder</code> class represents an
+ * old-style Sling {@link AuthenticationHandler} service in the internal data
+ * structure of the
+ * {@link org.apache.sling.commons.auth.impl.SlingAuthenticator}.
+ */
+@SuppressWarnings("deprecation")
+public final class EngineAuthenticationHandlerHolder extends
+        AbstractAuthenticationHandlerHolder {
+
+    // the actual authentication handler
+    private final AuthenticationHandler handler;
+
+    public EngineAuthenticationHandlerHolder(final String fullPath,
+            final AuthenticationHandler handler) {
+        super(fullPath);
+        this.handler = handler;
+    }
+
+    public AuthenticationInfo doAuthenticate(HttpServletRequest request,
+            HttpServletResponse response) {
+
+        org.apache.sling.engine.auth.AuthenticationInfo engineAuthInfo = handler.authenticate(
+            request, response);
+        if (engineAuthInfo == null) {
+            return null;
+        } else if (engineAuthInfo == org.apache.sling.engine.auth.AuthenticationInfo.DOING_AUTH) {
+            return AuthenticationInfo.DOING_AUTH;
+        }
+
+        return new AuthenticationInfo(engineAuthInfo.getAuthType(),
+            engineAuthInfo.getCredentials(), engineAuthInfo.getWorkspaceName());
+
+    }
+
+    public boolean doRequestAuthentication(HttpServletRequest request,
+            HttpServletResponse response) throws IOException {
+        return handler.requestAuthentication(request, response);
+    }
+
+    public void doDropAuthentication(HttpServletRequest request,
+            HttpServletResponse response) {
+        // Engine AuthenticationHandler does not have this method
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+
+        // equality is the base class equality (based on the fullpath)
+        // and the encapsulated holders being the same.
+        if (super.equals(obj)) {
+            if (obj.getClass() == getClass()) {
+                EngineAuthenticationHandlerHolder other = (EngineAuthenticationHandlerHolder) obj;
+                return other.handler == handler;
+            }
+        }
+
+        // handlers are not the same, so the holders are not the same
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return handler.toString() + " (Legacy API Handler)";
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineSlingAuthenticator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineSlingAuthenticator.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineSlingAuthenticator.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineSlingAuthenticator.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,54 @@
+/*
+ * 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.commons.auth.impl.engine;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.engine.auth.Authenticator;
+
+/**
+ * The <code>EngineSlingAuthenticator</code> class is a simple proxy service
+ * providing the old Sling Engine {@link Authenticator} service calling into the
+ * new standalone Apache Sling
+ * {@link org.apache.sling.commons.auth.Authenticator} service.
+ *
+ * @scr.component metatype="no"
+ * @scr.service interface="org.apache.sling.engine.auth.Authenticator"
+ * @scr.property name="service.description"
+ *               value="Apache Sling Request Authenticator (Legacy Bridge)"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ */
+@SuppressWarnings("deprecation")
+public class EngineSlingAuthenticator implements Authenticator {
+
+    /**
+     * @scr.reference
+     */
+    private org.apache.sling.commons.auth.Authenticator slingAuthenticator;
+
+    public void login(HttpServletRequest request, HttpServletResponse response) {
+        slingAuthenticator.login(request, response);
+    }
+
+    public void logout(HttpServletRequest request, HttpServletResponse response) {
+        slingAuthenticator.logout(request, response);
+    }
+
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineSlingAuthenticator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineSlingAuthenticator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationHandler.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationHandler.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationHandler.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.auth.spi;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The <code>AuthenticationHandler</code> interface defines the service API used
+ * by the authentication implementation to support plugin various ways of
+ * extracting credentials from the request.
+ */
+public interface AuthenticationHandler {
+
+    /**
+     * The name under which an implementation of this interface must be
+     * registered to be used as an authentication handler.
+     */
+    static final String SERVICE_NAME = "org.apache.sling.commons.auth.AuthenticationHandler";
+
+    /**
+     * The name of the service registration property listing one or more URL
+     * paths for which the authentication handler is to be used. The property
+     * may be a single string value or an array of strings or a Collection of
+     * strings.
+     * <p>
+     * Each string value may either be an absolute path (e.g. /content) or an
+     * absolute URL (e.g. http://thehost/content) to assign the authentication
+     * handler to authenticate request for a select virtual host.
+     * <p>
+     * Authentication handlers without a <code>path</code> service registration
+     * property are ignored.
+     */
+    static final String PATH_PROPERTY = "path";
+
+    /**
+     * Extracts credential data from the request if at all contained.
+     * <p>
+     * The method returns any of the following values :
+     * <table>
+     * <tr>
+     * <th>value
+     * <th>description
+     * </tr>
+     * <tr>
+     * <td><code>null</code>
+     * <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 AuthenticationInfo#DOING_AUTH}
+     * <td>the handler is in an ongoing authentication transaction with the
+     * client. Request processing should be aborted at this stage.
+     * <tr>
+     * <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
+     * they are not found in the request.
+     * <p>
+     * The value of {@link #PATH_PROPERTY} service registration property value
+     * triggering this call is available as the <code>path</code> request
+     * attribute. If the service is registered with multiple path values, the
+     * value of the <code>path</code> request attribute may be used to implement
+     * specific handling.
+     *
+     * @param request The request object containing the information for the
+     *            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>AuthenticationInfo</code> instance identifying the
+     *         request user, {@link AuthenticationInfo#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 AuthenticationInfo#DOING_AUTH}, the method must
+     *         have sent a response indicating that fact to the client.
+     */
+    AuthenticationInfo authenticate(HttpServletRequest request,
+            HttpServletResponse response);
+
+    /**
+     * Requests authentication information from the client. Returns
+     * <code>true</code> if the information has been requested and request
+     * processing can be terminated normally. Otherwise the authorization
+     * information could not be requested.
+     * <p>
+     * The <code>HttpServletResponse.sendError</code> methods should not be used
+     * by the implementation because these responses might be post-processed by
+     * the servlet container's error handling infrastructure thus preventing the
+     * correct operation of the authentication handler. To convey a HTTP
+     * response status the <code>HttpServletResponse.setStatus</code> method
+     * should be used.
+     * <p>
+     * The value of {@link #PATH_PROPERTY} service registration property value
+     * triggering this call is available as the <code>path</code> request
+     * attribute. If the service is registered with multiple path values, the
+     * value of the <code>path</code> request attribute may be used to implement
+     * specific handling.
+     *
+     * @param request The request object.
+     * @param response The response object to which to send the request.
+     * @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) throws IOException;
+
+    /**
+     * Drops any credential and authentication details from the request and asks
+     * the client to do the same.
+     *
+     * @param request The request object.
+     * @param response The response object to which to send the request.
+     * @throws IOException If an error occurrs asking the client to drop any
+     *             authentication traces.
+     */
+    void dropAuthentication(HttpServletRequest request,
+            HttpServletResponse response) throws IOException;
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationInfo.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationInfo.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationInfo.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,323 @@
+/*
+ * 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.commons.auth.spi;
+
+import java.util.HashMap;
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+
+/**
+ * The <code>AuthenticationInfo</code> conveys any authentication credentials
+ * and/or details extracted by the
+ * {@link AuthenticationHandler#authenticate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method from the request.
+ * <p>
+ * {@link AuthenticationHandler} implementations must return instances of this
+ * class which may be constructed through any of the provided public
+ * constructors.
+ * <p>
+ * Internally all values are stored in the map where some property names have
+ * special semantics and the data type of the properties are ensured by the
+ * {@link #put(String, Object)} method implementation.
+ */
+@SuppressWarnings("serial")
+public class AuthenticationInfo extends HashMap<String, Object> {
+
+    /**
+     * A special instance of this class which is returned by the
+     * {@link AuthenticationHandler#authenticate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+     * method to inform the caller, that a response has been sent to the client
+     * to request for credentials.
+     * <p>
+     * If this value is returned, the request should be considered finished and
+     * no further actions should be taken on this request.
+     */
+    public static final AuthenticationInfo DOING_AUTH = new AuthenticationInfo();
+
+    /**
+     * The name of the special property providing the authentication type
+     * provided by the {@link AuthenticationHandler}. This value must be
+     * supplied to one of the constructors and is ultimately used as the value
+     * of the <code>HttpServletRequest.getAuthType</code> method.
+     * <p>
+     * This property is always present (and cannot be removed) in this map and
+     * is of <code>String</code> type.
+     */
+    public static final String AUTH_TYPE = "sling.authType";
+
+    /**
+     * The name of the property providing the name of the user on whose behalf
+     * the request is being handled. This property is set by the
+     * {@link #AuthenticationInfo(String, String, char[], String)} constructor
+     * and may be <code>null</code> if this instance is created by either the
+     * {@link #AuthenticationInfo(String, Credentials)} or
+     * {@link #AuthenticationInfo(String, Credentials, String)} constructors.
+     * <p>
+     * The type of this property, if present, is <code>String</code>.
+     */
+    public static final String USER = "user.name";
+
+    /**
+     * The name of the property providing the password of the user on whose
+     * behalf the request is being handled. This property is set by the
+     * {@link #AuthenticationInfo(String, String, char[], String)} constructor
+     * and may be <code>null</code> if this instance is created by either the
+     * {@link #AuthenticationInfo(String, Credentials)} or
+     * {@link #AuthenticationInfo(String, Credentials, String)} constructors.
+     * <p>
+     * The type of this property, if present, is <code>char[]</code>.
+     */
+    public static final String PASSWORD = "user.password";
+
+    /**
+     * The name of the property providing the JCR credentials. These credentials
+     * are preset to the credentials given to the
+     * {@link #AuthenticationInfo(String, Credentials)} or
+     * {@link #AuthenticationInfo(String, Credentials, String)} constructors. If
+     * the {@link #AuthenticationInfo(String, String, char[], String)}
+     * constructor is used the credentials property is set to a JCR
+     * <code>SimpleCredentials</code> instance containing the user id and
+     * password passed to the constructor.
+     */
+    public static final String CREDENTIALS = "user.jcr.credentials";
+
+    /**
+     * The name of the property providing the name of the JCR workspace to which
+     * the request should be connected. This property may be set by any of the
+     * constructors. If this property is not set, the user will be connected to
+     * a default workspace as defined by the JCR repository to which the request
+     * is connected.
+     * <p>
+     * The type of this property, if present, is <code>String</code>.
+     */
+    public static final String WORKSPACE = "user.jcr.workspace";
+
+    /** Creates an empty instance, used for the {@link #DOING_AUTH} constant */
+    private AuthenticationInfo() {
+        super.put(AUTH_TYPE, "Authentication in Progress");
+    }
+
+    /**
+     * Creates an instance of this class with the given authentication type and
+     * credentials connecting to the default workspace as if the
+     * {@link #AuthenticationInfo(String, Credentials, String)} method would be
+     * called with a <code>null</code> workspace name.
+     *
+     * @param authType The authentication type, must not be <code>null</code>.
+     * @param credentials The credentials, must not be <code>null</code>.
+     * @throws NullPointerException if <code>authType</code> is
+     *             <code>null</code> .
+     */
+    public AuthenticationInfo(final String authType,
+            final Credentials credentials) {
+        this(authType, 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>.
+     * @param workspaceName The name of the workspace to connect to, may be
+     *            <code>null</code> to connect to the default workspace.
+     * @throws NullPointerException if <code>authType</code> is
+     *             <code>null</code> .
+     */
+    public AuthenticationInfo(final String authType,
+            final Credentials credentials, final String workspaceName) {
+        if (authType == null) {
+            throw new NullPointerException("authType");
+        }
+
+        super.put(AUTH_TYPE, authType);
+        putIfNotNull(CREDENTIALS, credentials);
+        putIfNotNull(WORKSPACE, workspaceName);
+    }
+
+    /**
+     * 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>.
+     * @param workspaceName The name of the workspace to connect to, may be
+     *            <code>null</code> to connect to the default workspace.
+     * @throws NullPointerException if <code>authType</code> is
+     *             <code>null</code>
+     */
+    public AuthenticationInfo(final String authType, final String userId,
+            final char[] password, final String workspaceName) {
+        if (authType == null) {
+            throw new NullPointerException("authType");
+        }
+
+        super.put(AUTH_TYPE, authType);
+        putIfNotNull(USER, userId);
+        putIfNotNull(PASSWORD, password);
+        putIfNotNull(WORKSPACE, workspaceName);
+
+        // also store credentials if the user id is not null/empty
+        if (userId != null && userId.length() > 0) {
+            final char[] pwd = (password == null) ? new char[0] : password;
+            super.put(CREDENTIALS, new SimpleCredentials(userId, pwd));
+        }
+    }
+
+    /**
+     * Returns the authentication type stored as the {@link #AUTH_TYPE} property
+     * in this map. This value is expected to never be <code>null</code>.
+     * <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 (String) get(AUTH_TYPE);
+    }
+
+    /**
+     * Returns the user name stored as the {@link #USER} property or
+     * <code>null</code> if the user is not set in this map.
+     */
+    public String getUser() {
+        return (String) get(USER);
+    }
+
+    /**
+     * Returns the password stored as the {@link #PASSWORD} property or
+     * <code>null</code> if the password is not set in this map.
+     */
+    public char[] getPassword() {
+        return (char[]) get(PASSWORD);
+    }
+
+    /**
+     * Returns the workspace name stored as the {@link #WORKSPACE} property or
+     * <code>null</code> if the workspace name is not set in this map.
+     */
+    public String getWorkspaceName() {
+        return (String) get(WORKSPACE);
+    }
+
+    /**
+     * Returns the JCR credentials stored as the {@link #CREDENTIALS} property
+     * or <code>null</code> if the credentials are not set in this map.
+     */
+    public Credentials getCredentials() {
+        return (Credentials) get(CREDENTIALS);
+    }
+
+    /**
+     * Sets or resets a property with the given <code>key</code> to a new
+     * <code>value</code>. Some keys have special meanings and their values are
+     * required to have predefined as listed in the following table:
+     * <table>
+     * <tr>
+     * <td>{@link #AUTH_TYPE}</td>
+     * <td><code>String</code></td>
+     * </tr>
+     * <tr>
+     * <td>{@link #USER}</td>
+     * <td><code>String</code></td>
+     * </tr>
+     * <tr>
+     * <td>{@link #PASSWORD}</td>
+     * <td><code>char[]</code></td>
+     * </tr>
+     * <tr>
+     * <td>{@link #CREDENTIALS}</td>
+     * <td><code>javax.jcr.Credentials</code></td>
+     * </tr>
+     * <tr>
+     * <td>{@link #WORKSPACE}</td>
+     * <td><code>String</code></td>
+     * </tr>
+     * </table>
+     * <p>
+     * If the value for the special key does not match the required type an
+     * <code>IllegalArgumentException</code> is thrown.
+     *
+     * @param key The name of the property to set
+     * @param value The value of the property which must be of a special type if
+     *            the <code>key</code> designates one of the predefined
+     *            properties.
+     * @return The value previously set for the given <code>key</code>.
+     * @throws IllegalArgumentException if <code>key</code> designates one of
+     *             the special properties and the <code>value</code> does not
+     *             have the correct type for the respective key.
+     */
+    @Override
+    public Object put(final String key, final Object value) {
+
+        if (AUTH_TYPE.equals(key) && !(value instanceof String)) {
+            throw new IllegalArgumentException(AUTH_TYPE
+                + " property must be a String");
+        }
+
+        if (USER.equals(key) && !(value instanceof String)) {
+            throw new IllegalArgumentException(USER
+                + " property must be a String");
+        }
+
+        if (PASSWORD.equals(key) && !(value instanceof char[])) {
+            throw new IllegalArgumentException(PASSWORD
+                + " property must be a char[]");
+        }
+
+        if (CREDENTIALS.equals(key) && !(value instanceof String)) {
+            throw new IllegalArgumentException(CREDENTIALS
+                + " property must be a javax.jcr.Credentials instance");
+        }
+
+        if (WORKSPACE.equals(key) && !(value instanceof String)) {
+            throw new IllegalArgumentException(WORKSPACE
+                + " property must be a String");
+        }
+
+        return super.put(key, value);
+    }
+
+    /**
+     * Removes the entry with the given <code>key</code> and returns its former
+     * value (if existing). If the <code>key</code> is {@link #AUTH_TYPE} the
+     * value is not actually removed and <code>null</code> is always returned.
+     *
+     * @param key Removes the value associated with this key.
+     * @return The former value associated with the key.
+     */
+    @Override
+    public Object remove(Object key) {
+
+        // don't return the auth type from the map
+        if (!AUTH_TYPE.equals(key)) {
+            return null;
+        }
+
+        return super.remove(key);
+    }
+
+    // helper to only set the property if the value is not null
+    private void putIfNotNull(final String key, final Object value) {
+        if (value != null) {
+            super.put(key, value);
+        }
+    }
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationInfo.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationHandler.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationHandler.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationHandler.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,117 @@
+/*
+ * 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.engine.auth;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The <code>AuthenticationHandler</code> interface defines the service API used
+ * by the authentication implementation to support plugin various ways of
+ * extracting credentials from the request.
+ *
+ * @deprecated use
+ *             {@link org.apache.sling.commons.auth.spi.AuthenticationHandler}
+ *             instead
+ */
+public interface AuthenticationHandler {
+
+    /**
+     * An authentication handler is associated with url paths. If the handler is
+     * not configured with a path, it is regarded as inactive. If the handler
+     * should be used for all requests, the path should be '/'.
+     */
+    String PATH_PROPERTY = "path";
+
+    /**
+     * Extracts credential data from the request if at all contained.
+     * <p>
+     * The method returns any of the following values :
+     * <table>
+     * <tr>
+     * <th>value
+     * <th>description
+     * </tr>
+     * <tr>
+     * <td><code>null</code>
+     * <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 AuthenticationInfo#DOING_AUTH}
+     * <td>the handler is in an ongoing authentication transaction with the
+     * client. Request processing should be aborted at this stage.
+     * <tr>
+     * <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
+     * they are not found in the request.
+     * <p>
+     * The value of {@link #PATH_PROPERTY} service registration property value
+     * triggering this call is available as the <code>path</code> request
+     * attribute. If the service is registered with multiple path values, the
+     * value of the <code>path</code> request attribute may be used to implement
+     * specific handling.
+     *
+     * @param request The request object containing the information for the
+     *            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>AuthenticationInfo</code> instance identifying the
+     *         request user, {@link AuthenticationInfo#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 AuthenticationInfo#DOING_AUTH}, the method must
+     *         have sent a response indicating that fact to the client.
+     */
+    AuthenticationInfo authenticate(HttpServletRequest request,
+            HttpServletResponse response);
+
+    /**
+     * Requests authentication information from the client. Returns
+     * <code>true</code> if the information has been requested and request
+     * processing can be terminated normally. Otherwise the authorization
+     * information could not be requested.
+     * <p>
+     * Any response sent by the handler though the <code>sendError</code> method
+     * is also handled by the error handler infrastructure.
+     * <p>
+     * The value of {@link #PATH_PROPERTY} service registration property value
+     * triggering this call is available as the <code>path</code> request
+     * attribute. If the service is registered with multiple path values, the
+     * value of the <code>path</code> request attribute may be used to implement
+     * specific handling.
+     *
+     * @param request The request object.
+     * @param response The response object to which to send the request.
+     * @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) throws IOException;
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationInfo.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationInfo.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationInfo.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,117 @@
+/*
+ * 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.engine.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.
+ *
+ * @deprecated see {@link AuthenticationHandler}
+ */
+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;
+
+    /**
+     * The name of the workspace this user is wishing to login,
+     * <code>null</code> means the default workspace.
+     */
+    private final String workspaceName;
+
+    /** Creates an empty instance, used for the {@link #DOING_AUTH} constants */
+    private AuthenticationInfo() {
+        this(null, null, null);
+    }
+
+    /**
+     * Creates an instance of this class with the given authentication type and
+     * credentials connecting to the default workspace as if the
+     * {@link #AuthenticationInfo(String, Credentials, String)} method would be
+     * called with a <code>null</code> workspace name.
+     *
+     * @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, 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>.
+     * @param workspaceName The name of the workspace to connect to, may be
+     *            <code>null</code> to connect to the default workspace.
+     * @see #getAuthType()
+     * @see #getCredentials()
+     */
+    public AuthenticationInfo(String authType, Credentials credentials,
+            String workspaceName) {
+        this.authType = authType;
+        this.credentials = credentials;
+        this.workspaceName = workspaceName;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Returns the name of the workspace the user contained in this instance
+     * wishes to connect to. This may be <code>null</code>, in which case the
+     * user is connected to the default workspace.
+     */
+    public String getWorkspaceName() {
+        return workspaceName;
+    }
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/AuthenticationInfo.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/Authenticator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/Authenticator.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/Authenticator.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/Authenticator.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,62 @@
+/*
+ * 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.engine.auth;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The <code>Authenticator</code> interface defines the service interface of the
+ * authenticator used by the Sling engine. This service provides a method to
+ * find an {@link AuthenticationHandler} and call its
+ * {@link AuthenticationHandler#requestAuthentication(HttpServletRequest, HttpServletResponse)}
+ * method.
+ * <p>
+ * This interface is not intended to be implemented by applications but may be
+ * used to initiate the authentication process form a request processing servlet
+ * or script.
+ *
+ * @since 2.0.4
+ * @deprecated use {@link org.apache.sling.commons.auth.Authenticator} instead
+ */
+public interface Authenticator {
+
+    /**
+     * Finds an {@link AuthenticationHandler} for the given request and call its
+     * {@link AuthenticationHandler#requestAuthentication(HttpServletRequest, HttpServletResponse)}
+     * method to initiate an authentication process with the client to login to
+     * Sling.
+     * <p>
+     * This method must be called on an uncommitted response since the
+     * implementation may want to reset the response to start the authentication
+     * process with a clean response. If the response is already committed an
+     * <code>IllegalStateException</code> is thrown.
+     * <p>
+     * After this method has finished, request processing should be terminated
+     * and the response be considered committed and finished.
+     *
+     * @param request The object representing the client request.
+     * @param response The object representing the response to the client.
+     * @throws NoAuthenticationHandlerException If no authentication handler
+     *             claims responsibility to authenticate the request.
+     * @throws IllegalStateException If the response has already been committed.
+     */
+    public void login(HttpServletRequest request, HttpServletResponse response);
+
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/Authenticator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/Authenticator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/NoAuthenticationHandlerException.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/NoAuthenticationHandlerException.java?rev=896345&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/NoAuthenticationHandlerException.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/NoAuthenticationHandlerException.java Wed Jan  6 07:55:01 2010
@@ -0,0 +1,44 @@
+/*
+ * 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.engine.auth;
+
+import org.apache.sling.api.SlingException;
+
+/**
+ * The <code>NoAuthenticationHandlerException</code> is thrown to indicate that
+ * there is no {@link AuthenticationHandler} willing to handle the request.
+ * <p>
+ * This exception is thrown without a message. The caller of the
+ * {@link Authenticator} method called is expected to immediately handle this
+ * exception and not to forward it up the call chain.
+ * <p>
+ * This exception is not intended to be thrown by client code but is used by the
+ * {@link Authenticator} implementation to indicate, that no
+ * {@link AuthenticationHandler} is available to login.
+ *
+ * @deprecated see {@link Authenticator}
+ */
+@SuppressWarnings("serial")
+public class NoAuthenticationHandlerException extends SlingException {
+
+    public NoAuthenticationHandlerException() {
+        super();
+    }
+
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/NoAuthenticationHandlerException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/engine/auth/NoAuthenticationHandlerException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url