/*
 *  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.ajp.tomcat4;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
import java.util.TreeMap;

import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.Globals;
import org.apache.catalina.connector.HttpRequestBase;
import org.apache.catalina.util.StringParser;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.BaseRequest;
import org.apache.tomcat.util.http.Cookies;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.ServerCookie;

public class Ajp13Request extends HttpRequestBase {

    private static final String match =
	";" + Globals.SESSION_PARAMETER_NAME + "=";

    private static int id = 1;

    private Ajp13Logger logger = new Ajp13Logger();
    private int debug;

    public Ajp13Request(Ajp13Connector connector) {
        super();
        this.debug = connector.getDebug();
        this.logger.setConnector(connector);
        this.logger.setName("Ajp13Request[" + (id++) + "]");
    }

    public void recycle() {
        super.recycle();        
    }

    void setAjpRequest(BaseRequest ajp) throws UnsupportedEncodingException {
        // XXX make this guy wrap AjpRequest so
        // we're more efficient (that's the whole point of
        // all of the MessageBytes in AjpRequest)

        setMethod(ajp.method().toString());
        setProtocol(ajp.protocol().toString());
        setRequestURI(ajp.requestURI().toString());
        setRemoteAddr(ajp.remoteAddr().toString());
        setRemoteHost(ajp.remoteHost().toString());
        setServerName(ajp.serverName().toString());
        setServerPort(ajp.getServerPort());

        if ((!(((Ajp13Connector) connector).getTomcatAuthentication())) 
            && (ajp.remoteUser() != null)) {
            setUserPrincipal(new Ajp13Principal(ajp.remoteUser().toString()));
        } else {
            setUserPrincipal(null);
        }

        setAuthType(ajp.authType().toString());
        setAuthorization(ajp.authorization().toString());
        setQueryString(ajp.queryString().toString());
        setScheme(ajp.getScheme());
        setSecure(ajp.getSecure());
        setContentLength(ajp.getContentLength());

        String contentType = ajp.contentType().toString();
        if (contentType != null) {
            setContentType(contentType);
        }

        MimeHeaders mheaders = ajp.headers();
        int nheaders = mheaders.size();
        for (int i = 0; i < nheaders; ++i) {
            MessageBytes name = mheaders.getName(i);
            MessageBytes value = mheaders.getValue(i);
            addHeader(name.toString(), value.toString());
            if ("accept-language".equals(name.toString()))
                parseLocalesHeader(value.toString());	
        }

        Iterator itr = ajp.getAttributeNames();
        while (itr.hasNext()) {
            String name = (String)itr.next();
            setAttribute(name, ajp.getAttribute(name));
        }

        addCookies(ajp.cookies());
    }

//      public Object getAttribute(String name) {
//          return ajp.getAttribute(name);
//      }

//      public Enumeration getAttributeNames() {
//          return new Enumerator(ajp.getAttributeNames());
//      }

    public void setRequestURI(String uri) {
	int semicolon = uri.indexOf(match);
	if (semicolon >= 0) {
	    String rest = uri.substring(semicolon + match.length());
	    int semicolon2 = rest.indexOf(";");
	    if (semicolon2 >= 0) {
		setRequestedSessionId(rest.substring(0, semicolon2));
		rest = rest.substring(semicolon2);
	    } else {
		setRequestedSessionId(rest);
		rest = "";
	    }
	    setRequestedSessionURL(true);
	    uri = uri.substring(0, semicolon) + rest;
	    if (debug >= 1)
	        logger.log(" Requested URL session id is " +
                           ((HttpServletRequest) getRequest())
                           .getRequestedSessionId());
	} else {
	    setRequestedSessionId(null);
	    setRequestedSessionURL(false);
	}

        super.setRequestURI(uri);
    }

    private void addCookies(Cookies cookies) {
        int ncookies = cookies.getCookieCount();
        for (int j = 0; j < ncookies; j++) {
            ServerCookie scookie = cookies.getCookie(j);
            Cookie cookie = new Cookie(scookie.getName().toString(),
                                       scookie.getValue().toString());
            if (cookie.getName().equals(Globals.SESSION_COOKIE_NAME)) {
                // Override anything requested in the URL
                if (!isRequestedSessionIdFromCookie()) {
                                // Accept only the first session id cookie
                    setRequestedSessionId(cookie.getValue());
                    setRequestedSessionCookie(true);
                    setRequestedSessionURL(false);
                    if (debug > 0) {
                        logger.log(" Requested cookie session id is " +
                                   ((HttpServletRequest) getRequest())
                                   .getRequestedSessionId());
                    }
                }
            }
            if (debug > 0) {
                logger.log(" Adding cookie " + cookie.getName() + "=" +
                           cookie.getValue());
            }
            addCookie(cookie);                    
        }        
    }

    public ServletInputStream createInputStream() throws IOException {
        return (ServletInputStream)getStream();
    }


    /**
     * Parse accept-language header value.
     */
    protected void parseLocalesHeader(String value) {

        // Store the accumulated languages that have been requested in
        // a local collection, sorted by the quality value (so we can
        // add Locales in descending order).  The values will be ArrayLists
        // containing the corresponding Locales to be added
        TreeMap locales = new TreeMap();

        // Preprocess the value to remove all whitespace
        int white = value.indexOf(' ');
        if (white < 0)
            white = value.indexOf('\t');
        if (white >= 0) {
            StringBuffer sb = new StringBuffer();
            int len = value.length();
            for (int i = 0; i < len; i++) {
                char ch = value.charAt(i);
                if ((ch != ' ') && (ch != '\t'))
                    sb.append(ch);
            }
            value = sb.toString();
        }

        // Process each comma-delimited language specification
	StringParser parser = new StringParser();
        parser.setString(value);        
        int length = parser.getLength();
        while (true) {

            // Extract the next comma-delimited entry
            int start = parser.getIndex();
            if (start >= length)
                break;
            int end = parser.findChar(',');
            String entry = parser.extract(start, end).trim();
            parser.advance();   // For the following entry

            // Extract the quality factor for this entry
            double quality = 1.0;
            int semi = entry.indexOf(";q=");
            if (semi >= 0) {
                try {
                    quality = Double.parseDouble(entry.substring(semi + 3));
                } catch (NumberFormatException e) {
                    quality = 0.0;
                }
                entry = entry.substring(0, semi);
            }

            // Skip entries we are not going to keep track of
            if (quality < 0.00005)
                continue;       // Zero (or effectively zero) quality factors
            if ("*".equals(entry))
                continue;       // FIXME - "*" entries are not handled

            // Extract the language and country for this entry
            String language = null;
            String country = null;
            String variant = null;
            int dash = entry.indexOf('-');
            if (dash < 0) {
                language = entry;
                country = "";
                variant = "";
            } else {
                language = entry.substring(0, dash);
                country = entry.substring(dash + 1);
                int vDash = country.indexOf('-');
                if (vDash > 0) {
                    String cTemp = country.substring(0, vDash);
                    variant = country.substring(vDash + 1);
                    country = cTemp;
                } else {
                    variant = "";
                }
            }

            // Add a new Locale to the list of Locales for this quality level
            Locale locale = new Locale(language, country, variant);
            Double key = new Double(-quality);  // Reverse the order
            ArrayList values = (ArrayList) locales.get(key);
            if (values == null) {
                values = new ArrayList();
                locales.put(key, values);
            }
            values.add(locale);

        }

        // Process the quality values in highest->lowest order (due to
        // negating the Double value when creating the key)
        Iterator keys = locales.keySet().iterator();
        while (keys.hasNext()) {
            Double key = (Double) keys.next();
            ArrayList list = (ArrayList) locales.get(key);
            Iterator values = list.iterator();
            while (values.hasNext()) {
                Locale locale = (Locale) values.next();
                addLocale(locale);
            }
        }

    }
}

class Ajp13Principal implements java.security.Principal {
    String user;
    
    Ajp13Principal(String user) {
        this.user = user;
    }
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        } else if (!(o instanceof Ajp13Principal)) {
            return false;
        } else if (o == this) {
            return true;
        } else if (this.user == null && ((Ajp13Principal)o).user == null) {
            return true;
        } else if (user != null) {
            return user.equals( ((Ajp13Principal)o).user);
        } else {
            return false;
        }
    }
    
    public String getName() {
        return user;
    }
    
    public int hashCode() {
        if (user == null) return 0;
        else return user.hashCode();
    }
    
    public String toString() {
        return getName();
    }
}
