/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2009-2011 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.web.tomcat6.osgi.httpservice;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletException;

import org.apache.catalina.Contained;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.valves.ValveBase;

import org.osgi.service.http.HttpContext;

/**
 * {@link org.apache.catalina.Wrapper} implementation for holding servlets deployed with
 * {@link HttpServiceImpl}. This implementation sets a specific {@link Valve} to
 * handle OSGI security mechanism.
 * @author Guillaume Porcher
 */
public class OSGIWrapper extends StandardWrapper {

    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = -749580021429740673L;

    /**
     * {@link Valve} implementation that checks before processing the invoke
     * method.
     * @author Guillaume Porcher
     */
    class OSGIWrapperValve extends ValveBase {

        /**
         * Default constructor.
         * @param delegate the proxied valve.
         */
        public OSGIWrapperValve(final Valve delegate) {
            this.setNext(delegate);
        }

        /**
         * Perform request processing. The security is checked by using
         * {@link HttpContext#handleSecurity(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
         * . If the request can be served, invoke the proxied valve to handle
         * the request normally.
         * @param request The servlet request to be processed
         * @param response The servlet response to be created
         * @throws IOException if an input/output error occurs, or is thrown by
         *         the proxied Valve
         * @throws ServletException if a servlet error is thrown by the proxied
         *         Valve
         */
        @Override
        public void invoke(final Request request, final Response response) throws IOException, ServletException {
            if (OSGIWrapper.this.httpContext.handleSecurity(request.getRequest(), response.getResponse())) {
                Valve next = this.getNext();
                if (next != null) {
                    if (next instanceof Contained) {
                        ((Contained) next).setContainer(this.getContainer());
                    }
                    this.getNext().invoke(request, response);
                }
            }
        }
    }

    /**
     * The {@link HttpContext} used during servlet or resource registration.
     */
    private final HttpContext httpContext;

    /**
     * Default constructor.
     * @param servlet the {@link Servlet} wrapped in this {@link Wrapper}.
     * @param context The HttpContext used during servlet or resource
     *        registration.
     */
    public OSGIWrapper(final Servlet servlet, final HttpContext context) {
        super();
        this.instance = servlet;
        this.httpContext = context;
        this.pipeline.setBasic(new OSGIWrapperValve(this.swValve));
    }


    /**
     * Update the mapping of the wrapper. When the context is already started
     * and a mapping is added, this mapping is not handled by the wrapper. This
     * function registers this wrapper to JMX
     */
    public void updateMapping() {
        registerJMX((OSGIContext) getParent());
    }
}
