/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed 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.bodington.servlet;

import java.security.cert.X509Certificate;

import javax.servlet.http.HttpServletRequest;

import org.bodington.server.BuildingServerException;
import org.bodington.server.NavigationSession;

/**
 * Class that handles session initialization via X509 certificates.
 * @see X509Certificate
 * @author Alexis O'Connor
 */
class X509SessionInitializer extends AbstractSessionInitializer
{
    // TODO If we only have one instance (in the chain) then we can't use this
    // instance variable?
    private X509Certificate[] certificates = null;
    
    /**
     * Find a session associated with the request. This implementation of the
     * method looks for an array of {@link X509Certificate} instances
     * associated with the request as attributes. If such an array exists, it
     * looks for an existing session keyed on it, otherwise it creates a new
     * one. If there is no certificate, this method returns <code>null</code>.
     * @param request {@inheritDoc}
     * @see X509Certificate
     */
    protected HttpSession findHttpSession( Request request )
    {
        if ( !request.isSecure() ) 
            return null;

        Object obj = request.getAttribute( 
            "javax.servlet.request.X509Certificate" );
        
        if (obj == null || !(obj instanceof X509Certificate[]))
            return null;
        
        certificates = (X509Certificate[])obj;
        if ( certificates.length > 0 )
        {
            // If there was a successful previous login with this certificate
            // and the http session is still alive it should be indexed...
            HttpSession session 
                = HttpSession.findSessionByCertificate( certificates[0] );
            // if this cert has not been seen before start a new session
            // and make sure that it is keyed against the certificate for later
            // requests. (even if we don't accept the cert.)
            if ( session == null )
            {
                session = 
                    (org.bodington.servlet.HttpSession)request.getSession( true );
                session.setCertificate( certificates[0] );
            }
            return session;
        }

        return null;
    }

    protected boolean initialize( Request request, 
        HttpSession session, NavigationSession navigation )
    {
        try
        {
            navigation.setClientX509( certificates[0] );
        }
        catch ( BuildingServerException e )
        {
        }

        return true;
    }

    protected void postInitialize( HttpSession session, Request request )
    {
        super.postInitialize( session, request );
        session.setAuthType( HttpServletRequest.CLIENT_CERT_AUTH );
    }
}
