/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2010 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * Application Versioning System
 * Copyright (C) 2008 France Telecom R&D
 *
 * 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.web.tomcat7.versioning;

import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.catalina.connector.CoyoteAdapter;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.coyote.Constants;

/**
 * Versioning valve.
 *
 * @author Frederic Germaneau
 * @author S. Ali Tokmen
 */
public class VersioningValve extends ValveBase {

    private static final ThreadLocal<VersionedPathBean> THREAD_VPB = new ThreadLocal<VersionedPathBean>();


    public VersioningValve() {
        super(true);
    }

    @Override
    public void invoke(final Request request, final Response response) throws IOException, ServletException {
        VersionedPathBean vpb = THREAD_VPB.get();

        try {
            if (vpb == null) {
                try {
                    vpb = new VersionedPathBean();
                    vpb.setOriginalDecodedUri(request.getDecodedRequestURI());

                    THREAD_VPB.set(vpb);
                    response.setVersionedPathBean(vpb);

                    CoyoteAdapter adapter = (CoyoteAdapter) request.getConnector().getProtocolHandler().getAdapter();

                    final String requestURI = request.getRequestURI();
                    final String versionedURI = ContextFinder.getContextURI(requestURI, request, vpb);

                    if (!versionedURI.equals(requestURI)) {
                        String encoding = request.getConnector().getURIEncoding();
                        if (encoding == null) {
                            encoding = Constants.DEFAULT_CHARACTER_ENCODING;
                        }

                        request.getMappingData().recycle();
                        request.getCoyoteRequest().requestURI().setChars(versionedURI.toCharArray(), 0, versionedURI.length());
                        byte[] versionedURIBytes = versionedURI.getBytes(encoding);
                        request.getCoyoteRequest().requestURI().setBytes(versionedURIBytes, 0, versionedURIBytes.length);

                        try {
                            adapter.service(request.getCoyoteRequest(), response.getCoyoteResponse());
                        } catch (Exception e) {
                            throw new IOException(e);
                        }
                    } else {
                        getNext().invoke(request, response);
                    }
                } finally {
                    THREAD_VPB.remove();
                }
            } else {
                response.setVersionedPathBean(vpb);
                getNext().invoke(request, response);
            }
        } finally {
            response.setVersionedPathBean(null);
        }
    }
}
