Package flex.messaging.services.http.proxy

Source Code of flex.messaging.services.http.proxy.ResponseFilter

/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
*  Copyright 2002 - 2007 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any.  The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated
* and its suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package flex.messaging.services.http.proxy;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.methods.OptionsMethod;
import flex.messaging.io.MessageIOConstants;

import javax.servlet.http.HttpServletResponse;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;

import flex.messaging.FlexContext;
import flex.messaging.services.HTTPProxyService;
import flex.messaging.log.Log;

/**
* @exclude
* Send the response to the client, including custom copying of headers and cookies.
*
* @author Brian Deitte
*/
public class ResponseFilter extends ProxyFilter
{
    // NOTE: any changes to this class should also be made to the corresponding version in the .NET.
    // The corresponding class is in src/dotNet/libs/FlexASPlib/Aspx/Proxy

    public static int RESPONSE_CHUNK = 4096;

    private static final int STATUS_ERROR = 10708;
    private static final int NULL_RESPONSE_STREAM = 10709;
    private static final int CANNOT_STREAM_NOT_HTTP = 10710;
    private static final int ERROR_WRITING_RESPONSE = 10711;

    public void invoke(ProxyContext context)
    {
        if (next != null)
        {
            next.invoke(context);
        }

        checkStatusCode(context);
        copyCookiesFromEndpoint(context);
        copyHeadersFromEndpoint(context);
        recordResponseHeaders(context);
        setupResponse(context);
    }

    protected void checkStatusCode(ProxyContext context)
    {
        int statusCode = context.getStatusCode();
        // FIXME: Why do this only for HTTP Proxy? Why not WebServices?
        if (statusCode >= 400 && statusCode != 401 & statusCode != 403 && !context.isSoapRequest())
        {
            StatusLine statusLine = context.getHttpMethod().getStatusLine();
            String reason = null;

            if (statusLine != null)
                reason = statusLine.toString();

            if (reason == null || "".equals(reason))
                reason = String.valueOf(statusCode);

            ProxyException pe = new ProxyException();
            pe.setMessage(STATUS_ERROR, new Object[] { reason });
            pe.setCode(ProxyException.CODE_SERVER_PROXY_REQUEST_FAILED);
            pe.setDetails(STATUS_ERROR, "1", new Object[] { reason });
            pe.setStatusCode(statusCode);
            throw pe;
        }
    }

    protected void copyCookiesFromEndpoint(ProxyContext context)
    {
        HttpServletResponse clientResponse = FlexContext.getHttpResponse();

        if (clientResponse != null)
        {
            Cookie[] cookies = context.getHttpClient().getState().getCookies();
            // We need to filter out the request cookies, we don't need to send back to the client
            Set requestCookies = context.getRequestCookies();
            for (int i = 0; i < cookies.length; i++)
            {
                if (requestCookies != null && requestCookies.contains(cookies[i]) && cookies[i].getExpiryDate() == null)
                {
                    // It means it is a request cookie and nothing changed, we need to skip it
                    continue;
                }
                // Process the cookie;
                String domain = cookies[i].getDomain();
                String path = cookies[i].getPath();
                String name = cookies[i].getName();
                String value = cookies[i].getValue();

                String clientName = ResponseUtil.getCookieName(context, path, name, domain);

                if (Log.isInfo())
                {
                    String str = "-- Cookie in response: domain = '" + domain + "', path = '" + path +
                            "', client name = '" + clientName + "', endpoint name = '" + name + "', value = '" + value;
                    Log.getLogger(HTTPProxyService.LOG_CATEGORY).debug(str);
                }

                javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(clientName, value);

                Date expiry = cookies[i].getExpiryDate();
                if (expiry != null)
                {
                    int maxAge = (int)((expiry.getTime() - System.currentTimeMillis()) / 1000);
                    cookie.setMaxAge(maxAge);
                }
                cookie.setSecure(cookies[i].getSecure());
                cookie.setPath("/");

                clientResponse.addCookie(cookie);
            }
        }
    }

    protected void copyHeadersFromEndpoint(ProxyContext context)
    {
        HttpServletResponse clientResponse = FlexContext.getHttpResponse();

        if (clientResponse != null)
        {
            Header[] headers = context.getHttpMethod().getResponseHeaders();
            for (int i = 0; i < headers.length; i++)
            {
                Header header = headers[i];
                String name = header.getName();
                String value = header.getValue();
                if (ResponseUtil.ignoreHeader(name, context))
                {
                    continue;
                }

                if ((name != null) && (value != null))
                {
                    clientResponse.addHeader(name, value);
                    if (Log.isInfo())
                    {
                        Log.getLogger(HTTPProxyService.LOG_CATEGORY).debug("-- Header in response: " + name + " : " + value);
                    }
                }
            }
            // set Pragma needed for ATG on HTTPS
            clientResponse.setHeader("Pragma", "public");
        }
    }

    protected void recordResponseHeaders(ProxyContext context)
    {
        String method = context.getMethod();
        if (context.getRecordHeaders() || ProxyConstants.METHOD_HEAD.equals(method))
        {
            Header[] headers = context.getHttpMethod().getResponseHeaders();
            HashMap responseHeaders = new HashMap();
            for (int i = 0; i < headers.length; i++)
            {
                Header header = headers[i];
                String headerName = header.getName();
                String headerValue = header.getValue();
                Object existingHeaderValue = responseHeaders.get(headerName);
                // Value(s) already exist for the header.
                if (existingHeaderValue != null)
                {
                    ArrayList headerValues;
                    // Only a single value exists.
                    if (existingHeaderValue instanceof String)
                    {
                        headerValues = new ArrayList();
                        headerValues.add(existingHeaderValue);
                        headerValues.add(headerValue);
                        responseHeaders.put(headerName, headerValues);
                    }
                    // Multiple values exist.
                    else if (existingHeaderValue instanceof ArrayList)
                    {
                        headerValues = (ArrayList)existingHeaderValue;
                        headerValues.add(headerValue);
                    }
                }
                else
                {
                    responseHeaders.put(headerName, headerValue);
                }
            }
            context.setResponseHeaders(responseHeaders);
        }
    }


    protected void setupResponse(ProxyContext context)
    {
        String method = context.getMethod();
        HttpMethodBase httpMethod = context.getHttpMethod();
        if (MessageIOConstants.METHOD_POST.equals(method))
        {
            writeResponse(context);
        }
        else if (ProxyConstants.METHOD_GET.equals(method))
        {
            writeResponse(context);
        }
        else if (ProxyConstants.METHOD_OPTIONS.equals(method))
        {
            OptionsMethod optionsMethod = (OptionsMethod)httpMethod;
            Enumeration options = optionsMethod.getAllowedMethods();
            if (options != null)
            {
                List ops = new ArrayList();
                while (options.hasMoreElements())
                {
                    Object option = options.nextElement();
                    ops.add(option);
                }
                Object[] o = ops.toArray();
                context.setResponse(o);
            }
        }
        else if (ProxyConstants.METHOD_TRACE.equals(method))
        {
            writeResponse(context);
        }
        else if (ProxyConstants.METHOD_DELETE.equals(method))
        {
            writeResponse(context);
        }
        else if (ProxyConstants.METHOD_HEAD.equals(method))
        {
            context.setResponse(context.getResponseHeaders());
        }
        else if (ProxyConstants.METHOD_PUT.equals(method))
        {
            writeResponse(context);
        }
    }

    protected void writeResponse(ProxyContext context)
    {
        try
        {
            InputStream in = context.getHttpMethod().getResponseBodyAsStream();

            if (in == null)
            {
                throw new ProxyException(NULL_RESPONSE_STREAM);
            }

            int length = (int)context.getHttpMethod().getResponseContentLength();

            // Stream response directly to client
            if (context.streamResponseToClient())
            {
                HttpServletResponse clientResponse = FlexContext.getHttpResponse();

                if (clientResponse != null)
                {
                    OutputStream out = clientResponse.getOutputStream();
                    if (length != -1)
                    {
                        clientResponse.setContentLength(length);
                    }

                    writeStreamedResponse(in, out, context);
                }
                else
                {
                    throw new ProxyException(CANNOT_STREAM_NOT_HTTP);
                }
            }
            else
            {
                writeResponseAsString(in, length, context);
            }
        }
        catch (IOException ioe)
        {
            ProxyException pe = new ProxyException();
            pe.setMessage(ERROR_WRITING_RESPONSE, new Object[] { ioe.getMessage() });
            throw pe;
        }
    }

    protected void writeStreamedResponse(InputStream inStream, OutputStream out, ProxyContext context) throws IOException
    {
        byte[] tmp = new byte[RESPONSE_CHUNK];
        int i = 0;

        while ((i = inStream.read(tmp)) >= 0)
        {
            out.write(tmp, 0, i);
        }
    }

    protected void writeResponseAsString(InputStream inStream, int length, ProxyContext context)
            throws IOException
    {
        char[] tmp = new char[RESPONSE_CHUNK];
        //int i = 0;
        StringBuffer sb = new StringBuffer( length < 0 ? 16 : length);
        BufferedInputStream bufferedIn = new BufferedInputStream(inStream);
        String charset = context.getHttpMethod().getResponseCharSet();

        bufferedIn.mark(4);

        // Check for BOM as InputStreamReader does not strip BOM in all cases.
        boolean hasBOM = false;
        int read = bufferedIn.read();
        if (read > 0)
        {
            // UTF-8 BOM is EF BB BF
            if (0xEF == (read & 0xFF))
            {
                read = bufferedIn.read();
                if (0xBB == (read & 0xFF))
                {
                    read = bufferedIn.read();
                    if (0xBF == (read & 0xFF))
                    {
                        hasBOM = true;
                        charset = "UTF-8";
                    }
                }
            }
            // UTF-16 Little Endian BOM is FF FE
            // UTF-32 Little Endian BOM is FF FE 00 00
            else if (0xFF == (read & 0xFF))
            {
                read = bufferedIn.read();
                if (0xFE == (read & 0xFF))
                {
                    hasBOM = true;
                    charset = "UTF16-LE";

                    // Check two more bytes incase we have UTF-32
                    bufferedIn.mark(2);
                    read = bufferedIn.read();
                    if (0x00 == (read & 0xFF))
                    {
                        read = bufferedIn.read();
                        if (0x00 == (read & 0xFF))
                        {
                            charset = "UTF32-LE";
                        }
                        else
                        {
                            bufferedIn.reset();
                        }
                    }
                    else
                    {
                        bufferedIn.reset();
                    }
                }
            }
            // UTF-16 Big Endian BOM is FE FF
            else if (0xFE == (read & 0xFF))
            {
                read = bufferedIn.read();
                if (0xFF == (read & 0xFF))
                {
                    hasBOM = true;
                    charset = "UTF16-BE";
                }
            }
            // UTF-32 Big Endian BOM is 00 00 FE FF
            else if (0x00 == (read & 0xFF))
            {
                read = bufferedIn.read();
                if (0x00 == (read & 0xFF))
                {
                    read = bufferedIn.read();
                    if (0xFE == (read & 0xFF))
                    {
                        read = bufferedIn.read();
                        if (0xFF == (read & 0xFF))
                        {
                            hasBOM = true;
                            charset = "UTF32-BE";
                        }
                    }
                }
            }

            // If we didn't find a BOM, all bytes should contribute to the content
            if (!hasBOM)
                bufferedIn.reset();
        }

        BufferedReader reader = new BufferedReader(new InputStreamReader(bufferedIn, charset));
        int charactersRead = -1;
        while ((charactersRead = reader.read(tmp, 0, tmp.length)) >= 0)
        {
            sb.append(new String(tmp, 0, charactersRead));
        }

        context.setResponse(sb.toString());
    }
}
TOP

Related Classes of flex.messaging.services.http.proxy.ResponseFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.