/*
 * 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 flex.messaging.security;

import flex.messaging.log.Log;
import flex.messaging.log.LogCategories;
import flex.messaging.util.ExceptionUtil;

import java.io.IOException;
import java.security.Principal;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.catalina.Container;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Manager;
import org.apache.catalina.Realm;
import org.apache.catalina.Session;
import org.apache.catalina.Valve;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;

/**
 *
 * A Tomcat valve for allowing programmatic login.  This valve saves the container, 
 * something not available normally to a servlet, and allows login to the current realm. 
 * The pieces interacting with Tomcat are taken from org.apache.catalina.authenticator.AuthenticatorBase.
 * It would be nice if we could just extend that class or call some of its methods, 
 * but things aren't set up in that class in such a way that this is possible
 *
 * FIXME: Doesn't support Tomcat's SingleSignOn which is a way to write custom valves that associate
 * the principal to different web apps or locations. See AuthenticatorBase for details
 */
public class TomcatValve extends ValveBase implements Lifecycle
{
    private static final String AUTH_TYPE = "flexmessaging"; // was "flashgateway"
    private static final String AMF_MATCH = "/amfgateway";
    private static final String GATEWAY_MATCH = "/flashgateway";
    private static final String MESSAGEBROKER_MATCH = "/messagebroker"; 
    private static String CUSTOM_MATCH = System.getProperty("flex.tomcatValveMatch");

    public void invoke(Request request, Response response) throws IOException, ServletException
    {
        invokeServletRequest(request);

        Valve next = getNext();
        if (next != null)
            next.invoke(request, response);
    }

    private void invokeServletRequest(Request request)
    {
        ServletRequest servRequest = request.getRequest();
        if (!(servRequest instanceof HttpServletRequest))
            return;

        // We only set the TomcatLoginImpl for gateway paths
        HttpServletRequest hrequest = (HttpServletRequest)servRequest;
        boolean match = checkIfPathMatches(hrequest.getServletPath(), hrequest.getRequestURI());
        if (match)
            handleMatch(request, hrequest.getUserPrincipal());
    }

    private void handleMatch(Request request, Principal principal)
    {
        TomcatLoginHolder.setLogin(new TomcatLoginImpl(getContainer(), request));

        // Copy over user principal and auth type values, just like in AuthenticatorBase.invoke()
        if (principal != null)
            return;

        Session session = getSession(request, false);
        if (session == null)
            return;

        principal = session.getPrincipal();
        if (principal != null) 
        {
            request.setAuthType(session.getAuthType());
            request.setUserPrincipal(principal);
        }
    }

    private boolean checkIfPathMatches(String path, String uri)
    {
        if (path == null)
        {
            // We need to use a slighly-weaker uri match for 4.1
            return (uri != null &&
                    (uri.indexOf(MESSAGEBROKER_MATCH) != -1 ||
                            uri.indexOf(AMF_MATCH) != -1 ||
                            uri.indexOf(GATEWAY_MATCH) != -1 ||
                            (CUSTOM_MATCH != null && uri.indexOf(CUSTOM_MATCH) != -1)));
        }
        else
        {
            return (path.startsWith(MESSAGEBROKER_MATCH) ||
                    path.startsWith(AMF_MATCH) ||
                    path.startsWith(GATEWAY_MATCH) ||
                    (CUSTOM_MATCH != null && path.startsWith(CUSTOM_MATCH)));
        }
    }

    public void addLifecycleListener(LifecycleListener listener)
    {
        // No-op.
    }

    public LifecycleListener[] findLifecycleListeners()
    {
        return null;
    }

    public void removeLifecycleListener(LifecycleListener listener)
    {
        // No-op.
    }

    public void start() throws LifecycleException
    {
        // RTMP may not go through invoke so we need to put at least one TomcatLoginImpl in the holder.
        TomcatLogin login = new TomcatLoginImpl(getContainer(), null);
        TomcatLoginHolder.setLogin(login);
        // To avoid the thread processes the nio based endpoints does not match the thread start the valve (which is quite possible in Tomcat)
        // We set the singleton 
        TomcatLoginHolder.setNioBasedLogin(login);
    }

    public void stop() throws LifecycleException
    {
        // No-op.
    }

    // from AuthenticatorBase.getSession()
    static Session getSession(Request request, boolean create) 
    {

        HttpServletRequest hreq = (HttpServletRequest)request.getRequest();
        HttpSession hses = hreq.getSession(create);

        if (hses == null)
            return null;

        Manager manager = request.getContext().getManager();
        if (manager == null)
            return null;

        try 
        {
            return manager.findSession(hses.getId());
        }
        catch (IOException e) 
        {
            Log.getLogger(LogCategories.SECURITY).error("Error in TomcatValve getting session id " + hses.getId() + " : " + ExceptionUtil.toString(e));
            return null;
        }
    }

    class TomcatLoginImpl implements TomcatLogin
    {
        private Container container;
        private Request request;

        TomcatLoginImpl(Container container, Request request)
        {
            this.container = container;
            this.request = request;
        }

        // Authenticate the user and associate with the current session.
        // This is taken from AuthenticatorBase.register()
        public Principal login(String username, String password, HttpServletRequest servletRequest)
        {
            Realm realm = container.getRealm();
            if (realm == null)
                return null;

            Principal principal = realm.authenticate(username, password);
            if (principal == null)
                return null;

            if (servletRequestMatches(servletRequest))
            {
                request.setAuthType(AUTH_TYPE);
                request.setUserPrincipal(principal);

                Session session = getSession(request, true);

                // Cache the authentication information in our session.
                if (session != null) 
                {
                    session.setAuthType(AUTH_TYPE);
                    session.setPrincipal(principal);

                    if (username != null)
                        session.setNote(Constants.SESS_USERNAME_NOTE, username);
                    else
                        session.removeNote(Constants.SESS_USERNAME_NOTE);

                    if (password != null)
                        session.setNote(Constants.SESS_PASSWORD_NOTE, password);
                    else
                        session.removeNote(Constants.SESS_PASSWORD_NOTE);
                }
            }

            return principal;
        }

        public boolean authorize(Principal principal, List roles)
        {
            Realm realm = container.getRealm();
            Iterator iter = roles.iterator();
            while (iter.hasNext())
            {
                String role = (String)iter.next();
                if (realm.hasRole(principal, role))
                    return true;
            }
            return false;
        }

        public boolean logout(HttpServletRequest servletRequest)
        {
            if (servletRequestMatches(servletRequest))
            {
                Session session = getSession(request, false);
                if (session != null)
                {
                    session.setPrincipal(null);
                    session.setAuthType(null);
                    session.removeNote(Constants.SESS_USERNAME_NOTE);
                    session.removeNote(Constants.SESS_PASSWORD_NOTE);
                }
                return true;
            }
            return false;
        }

        private boolean servletRequestMatches(HttpServletRequest servletRequest)
        {
            return request != null && request.getRequest() == servletRequest;
        }
        
        /** {@inheritDoc} */
        public Principal convertPrincipal(Principal principal)
        {
            return principal;
        }
    }

}
