com.adito.replacementproxy.RequestProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.adito.replacementproxy.RequestProcessor.java

Source

/*
*  Adito
*
*  Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; either version 2 of
*  the License, or (at your option) any later version.
*  This program 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 General Public License for more details.
*
*  You should have received a copy of the GNU General Public
*  License along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package com.adito.replacementproxy;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.adito.boot.HttpConstants;
import com.adito.boot.PropertyList;
import com.adito.boot.RequestHandlerRequest;
import com.adito.boot.Util;
import com.adito.core.RequestParameterMap;
import com.adito.core.RequestParameterMap.ProxyURIDetails;
import com.adito.core.stringreplacement.VariableReplacement;
import com.adito.policyframework.LaunchSession;
import com.adito.security.SessionInfo;
import com.adito.webforwards.ReplacementProxyWebForward;

/**
 * This class handles the first stage in the replacement proxy process in that
 * it gathers information sent from the clients browser, locates the session
 * the request is attached to and extracts the parameters required for passing
 * on to the next stage (the {@link ProxiedRequestDispatcher}).
 */
public class RequestProcessor {
    final static Log log = LogFactory.getLog(RequestProcessor.class);

    private ContentCache cache;
    private boolean getFromCache;
    private ReplacementProxyWebForward webForward;
    private RequestParameterMap requestParameters;
    private RequestHandlerRequest request;
    private HeaderMap headerMap;
    private LaunchSession launchSession;
    private URL requestBaseURL;
    private ProxyURIDetails proxyURIDetails;

    /**
     * Constructor.
     *
     * @param cache cache for storing cacheable pages
     * @param maxAge maximum age of objects in the cach
     * @param request the request
     * @param launchSession the session the web forward was launched under     * @param proxiedUrl the proxied (or target) URL
     */
    public RequestProcessor(ContentCache cache, int maxAge, RequestHandlerRequest request,
            LaunchSession launchSession) throws MalformedURLException {
        this.cache = cache;
        this.request = request;
        this.launchSession = launchSession;
        this.webForward = (ReplacementProxyWebForward) launchSession.getResource();

        /* Get the base URL as requested by the client (i.e. the location of the
         * Adito server as the client sees it
         */
        StringBuffer buf = new StringBuffer();
        buf.append(request.isSecure() ? "https" : "http");
        buf.append("://");
        buf.append(request.getHost());
        if (request.getPort() > 0 && ((request.isSecure() && request.getPort() != 443)
                || (!request.isSecure() && request.getPort() != 80))) {
            buf.append(":");
            buf.append(request.getPort());
        }
        requestBaseURL = new URL(buf.toString());
    }

    /**
     * Get the base URL as requested by the client (i.e. the location of the
     * Adito server as the client sees it
     * 
     * @return request base URL
     */
    public URL getRequestBaseURL() {
        return requestBaseURL;
    }

    /**
     * Get the ID of the {@link LaunchSession} this web forward was launched
     * under.
     * 
     * @return launch ID
     */
    public String getLaunchId() {
        return launchSession.getId();
    }

    public LaunchSession getLaunchSession() {
        return launchSession;
    }

    /**
     * Get the HTTP method used by the client (e.g. GET or POST).
     *  
     * @return method
     */
    public String getMethod() {
        return request.getMethod();
    }

    /**
     * Get the request.
     * 
     * @return request
     */
    public RequestHandlerRequest getRequest() {
        return request;
    }

    /**
     * Get the session this request was made under.
     * 
     * @return session
     */
    public SessionInfo getSessionInfo() {
        return launchSession.getSession();
    }

    /**
     * Get the request parameter map.
     * 
     * @return request parameter map.
     */
    public RequestParameterMap getRequestParameters() {
        return requestParameters;
    }

    /**
     * Get if the page may be retrieved from the cache.
     * @return
     */
    public boolean isGetFromCache() {
        return getFromCache;
    }

    /**
     * Get the path of the URI for the request, including any request 
     * parameters.
     * 
     * @return base URI
     */
    public String getUriEncoded() {
        String uriEncoded = Util
                .isNullOrTrimmedBlank(requestParameters.getProxiedURIDetails().getProxiedURL().getFile()) ? "/"
                        : requestParameters.getProxiedURIDetails().getProxiedURL().getFile();
        if (log.isDebugEnabled())
            log.debug("Returning URI " + uriEncoded);
        return uriEncoded;
    }

    public void processRequest() throws Exception {

        // Create our own map of headers so they can be edited
        headerMap = new HeaderMap();
        for (Enumeration e = request.getFieldNames(); e.hasMoreElements();) {
            String n = (String) e.nextElement();
            for (Enumeration e2 = request.getFieldValues(n); e2.hasMoreElements();) {
                String v = (String) e2.nextElement();
                headerMap.putHeader(n, v);
            }
        }

        // Build up the parameter map
        requestParameters = new RequestParameterMap(request);
        proxyURIDetails = requestParameters.getProxiedURIDetails();

        VariableReplacement r = new VariableReplacement();
        r.setRequest(request);
        r.setSession(launchSession.getSession());
        r.setPolicy(launchSession.getPolicy());
        String actualURL = r.replace(webForward.getDestinationURL());

        if (proxyURIDetails.getProxiedURL() == null) {
            throw new Exception("No sslex_url parameter provided.");
        }

        if (log.isDebugEnabled())
            log.debug("Proxying [" + request.getMethod() + "] " + proxyURIDetails.getProxiedURL());

        URL proxiedURLBase = proxyURIDetails.getProxiedURLBase();
        if (log.isDebugEnabled())
            log.debug("Proxied URL base " + proxiedURLBase.toExternalForm());

        // The web forward may restrict access to the target URL
        PropertyList restrictTo = webForward.getRestrictToHosts();
        if (!restrictTo.isEmpty()) {
            boolean found = proxiedURLBase.getHost().equals(new URL(actualURL).getHost());
            for (Iterator i = restrictTo.iterator(); !found && i.hasNext();) {
                String host = (String) i.next();
                if (proxiedURLBase.getHost().matches(Util.parseSimplePatternToRegExp(host))) {
                    found = true;
                }
            }
            if (!found) {
                throw new Exception("This resource (" + proxiedURLBase.toExternalForm()
                        + ") is restricted to a list of target hosts. This host is not in the list.");
            }

        }

        // Determine if the page can be retrieved from cache

        getFromCache = false;
        Date expiryDate = null;
        if (cache != null && HttpConstants.METHOD_GET.equals(request.getMethod())
                && cache.contains(proxyURIDetails.getProxiedURL())) {
            getFromCache = true;

            // HTTP 1.0
            String cacheControl = request.getField(HttpConstants.HDR_PRAGMA);
            if (cacheControl != null && cacheControl.equalsIgnoreCase("no-cache")) {
                getFromCache = false;
            } else {
                String ifModifiedSince = request.getField(HttpConstants.HDR_IF_MODIFIED_SINCE);
                if (ifModifiedSince != null) {
                    try {
                        // Dont get from cache if
                        getFromCache = false;
                    } catch (Exception e) {
                    }
                }
            }

            // HTTP 1.1
            if (getFromCache) {
                cacheControl = request.getField(HttpConstants.HDR_CACHE_CONTROL);
                if (cacheControl != null) {
                    StringTokenizer tok = new StringTokenizer(cacheControl, ";");
                    while (tok.hasMoreTokens()) {
                        String t = tok.nextToken().trim();
                        String tl = t.toLowerCase();
                        if (t.startsWith("no-cache") || t.startsWith("no-store")) {
                            getFromCache = false;
                        } else if (tl.startsWith("max-age")) {
                            expiryDate = new Date();
                            try {
                                expiryDate.setTime(
                                        expiryDate.getTime() - (Integer.parseInt(Util.valueOfNameValuePair(tl))));
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }

            // Check expiry
            if (getFromCache) {
                CacheingOutputStream cos = (CacheingOutputStream) cache.retrieve(proxyURIDetails.getProxiedURL());
                if (expiryDate == null || (expiryDate != null && cos.getCachedDate().after(expiryDate))) {
                    // Still ok
                } else {
                    if (log.isDebugEnabled())
                        log.debug("Page expired");
                    getFromCache = false;
                }
            } else {
                if (log.isDebugEnabled())
                    log.debug("Not using cached page.");
            }
        }
    }

    public ReplacementProxyWebForward getWebForward() {
        return webForward;
    }

    /**
     * @return
     */
    public String getRequestMethod() {
        return request.getMethod();
    }

    /**
     * @return
     */
    public HttpSession getSession() {
        return getSessionInfo().getHttpSession();
    }

    /**
     * @param hdr
     * @return
     */
    public String getHeader(String hdr) {
        Enumeration e = headerMap.getHeaders(hdr);
        return e == null ? null : (String) e.nextElement();
    }

    /**
     * @return
     */
    public Enumeration getHeaderNames() {
        return headerMap.keys();
    }

    /**
     * @param hdr
     * @return
     */
    public Enumeration getHeaders(String hdr) {
        return headerMap.getHeaders(hdr);
    }

    class HeaderMap extends Hashtable {

        private static final long serialVersionUID = -6768313767635812871L;

        HeaderMap() {

        }

        void putHeader(String name, String value) {
            Vector l = (Vector) get(name);
            if (l == null) {
                l = new Vector();
                put(name, l);
            }
            l.addElement(value);
        }

        void setHeader(String name, String value) {
            Vector l = new Vector();
            l.addElement(value);
            put(name, l);
        }

        Enumeration getHeaders(String hdr) {
            Vector l = (Vector) get(hdr);
            return l == null ? null : l.elements();

        }
    }
}