Package flex.messaging.services

Source Code of flex.messaging.services.HTTPProxyService

/*************************************************************************
*
* 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;

import flex.management.runtime.messaging.services.HTTPProxyServiceControl;
import flex.management.runtime.messaging.services.http.HTTPProxyDestinationControl;
import flex.messaging.Destination;
import flex.messaging.FlexRemoteCredentials;
import flex.messaging.MessageBroker;
import flex.messaging.MessageException;
import flex.messaging.FlexContext;
import flex.messaging.messages.HTTPMessage;
import flex.messaging.messages.Message;
import flex.messaging.messages.SOAPMessage;
import flex.messaging.services.http.HTTPProxyDestination;
import flex.messaging.services.http.proxy.ProxyException;
import flex.messaging.util.SettingsReplaceUtil;
import flex.messaging.util.StringUtils;
import flex.messaging.log.LogCategories;
import flex.messaging.log.Log;

import java.util.List;
import javax.servlet.http.HttpServletRequest;

/**
* The HttpProxyService replaces the Flex 1.5 Proxy. It decouples
* the details of how the client contacts the message broker
* by accepting an HTTPMessage type which can be sent over
* any channel.
*
* @author Cathy Murphy
* @author Glen Daniels
* @author Brian Deitte
* @author Sean Neville
* @author Peter Farland
*
* @see flex.messaging.messages.HTTPMessage
*/
public class HTTPProxyService extends AbstractService
{
    /** Log category for <code>HTTPProxyService</code>. */
    public static final String LOG_CATEGORY = LogCategories.SERVICE_HTTP;

    // Errors
    private static final int DOT_DOT_NOT_ALLOWED = 10700;
    private static final int MULTIPLE_DOMAIN_PORT = 10701;
    private static final int DYNAMIC_NOT_CONFIGURED = 10702;

    private HTTPProxyServiceControl controller;

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructs an unmanaged <code>HTTPProxyService</code>.
     */
    public HTTPProxyService()
    {
        this(false);
    }

    /**
     * Constructs a <code>HTTPProxyService</code> with the indicated management.
     *
     * @param enableManagement <code>true</code> if the <code>HTTPProxyService</code>
     * is manageable; otherwise <code>false</code>.
     */
    public HTTPProxyService(boolean enableManagement)
    {
        super(enableManagement);
    }

    //--------------------------------------------------------------------------
    //
    // Public Getters and Setters for HTTPProxyService properties
    //
    //--------------------------------------------------------------------------

    /**
     * Creates a <code>HTTPProxyDestination</code> instance, sets its id,
     * sets it manageable if the <code>AbstractService</code> that created it is
     * manageable, and sets its <code>Service</code> to the <code>AbstractService</code>
     * that created it.
     *
     * @param id The id of the <code>HTTPProxyDestination</code>.
     * @return The <code>Destination</code> instanced created.
     */
    @Override
    public Destination createDestination(String id)
    {
        HTTPProxyDestination destination = new HTTPProxyDestination();
        destination.setId(id);
        destination.setManaged(isManaged());
        destination.setService(this);

        return destination;
    }

    /**
     * Casts the <code>Destination</code> into <code>HTTPProxyDestination</code>
     * and calls super.addDestination.
     *
     * @param destination The <code>Destination</code> instance to be added.
     */
    @Override
    public void addDestination(Destination destination)
    {
        HTTPProxyDestination proxyDestination = (HTTPProxyDestination)destination;
        super.addDestination(proxyDestination);
    }

    //--------------------------------------------------------------------------
    //
    // Other Public APIs
    //
    //--------------------------------------------------------------------------

    /**
     * Processes messages of type <code>HTTPMessage</code> by invoking the
     * requested destination's adapter.
     *
     * @param msg The message sent by the MessageBroker.
     * @return The result of the service.
     */
    @Override
    public Object serviceMessage(Message msg)
    {
        if (!(msg instanceof HTTPMessage))
        {
            // The 'HTTPProxy' Service can only process messages of type 'HTTPMessage'.
            ServiceException e = new ServiceException();
            e.setMessage(UNKNOWN_MESSAGE_TYPE, new Object[]{"HTTPProxy", "HTTPMessage"});
            throw e;
        }

        HTTPMessage message = (HTTPMessage)msg;

        String destination = message.getDestination();
        HTTPProxyDestination dest = (HTTPProxyDestination)destinations.get(destination);

        //use the remote settings if the message didn't specify them
        FlexRemoteCredentials remoteCredentials =
            FlexContext.getFlexSession().getRemoteCredentials(getId(), destination);
        if (remoteCredentials != null)
        {
            message.setRemoteUsername(remoteCredentials.getUsername());
            message.setRemotePassword((String)remoteCredentials.getCredentials());
        }
        else if (dest.getRemoteUsername() != null && dest.getRemotePassword() != null)
        {
            message.setRemoteUsername(dest.getRemoteUsername());
            message.setRemotePassword(dest.getRemotePassword());
        }

        ServiceAdapter adapter = dest.getAdapter();

        Object result;

        if (message instanceof SOAPMessage)
        {
            result = invokeSoap(adapter, (SOAPMessage)message, dest);
        }
        else
        {
            result = invokeHttp(adapter, message, dest);
        }

        if (Log.isDebug())
        {
            String debugResult =
                StringUtils.prettifyString(String.valueOf(result));
            Log.getLogger(getLogCategory()).debug
            ("HTTP request: " +
                    message + StringUtils.NEWLINE +
                    "  response: " + StringUtils.NEWLINE +
                    debugResult + StringUtils.NEWLINE);
        }

        return result;
    }

    //--------------------------------------------------------------------------
    //
    // Protected/private APIs
    //
    //--------------------------------------------------------------------------

    protected Object invokeSoap(ServiceAdapter adapter, SOAPMessage message, HTTPProxyDestination destination)
    {
        if (isManaged())
        {
            HTTPProxyDestinationControl destinationControl = (HTTPProxyDestinationControl)destination.getControl();
            if (destinationControl != null)
                destinationControl.incrementInvokeSOAPCount();
        }

        String dynamicUrl = message.getUrl();

        String contextPath = null;
        String serverName = null;
        String serverPort = null;
        String protocol = null;
        HttpServletRequest req = FlexContext.getHttpRequest();
        if (req != null)
        {
            contextPath = req.getContextPath();
            protocol = req.getScheme();
            serverName = req.getServerName();
            int port = req.getServerPort();
            if (port != 0)
            {
                serverPort = Integer.valueOf(req.getServerPort()).toString();
            }
        }

        if (dynamicUrl != null && dynamicUrl.length() > 0)
        {
            checkUrl(dynamicUrl, contextPath, destination, serverName, serverPort, protocol, message.getRemoteUsername() != null);
        }
        else
        {
            //TODO: QUESTION: Pete Support default soap endpoints?
            //String url = settings.getParsedDefaultUrl(contextPath);
            //message.setUrl(url);

            // FIXME: Need a better error here!
            throw new MessageException("A SOAP endpoint was not provided.");
        }

        return adapter.invoke(message);
    }

    protected void checkUrl(String url, String contextPath, HTTPProxyDestination destination, String serverName,
            String serverPort, String serverProtocol, boolean authSupplied)
    {
        String originalUrl = url;

        String defaultUrl = destination.getParsedDefaultUrl(contextPath, serverName, serverPort, serverProtocol);
        List dynamicUrls = destination.getParsedDynamicUrls(contextPath);

        //If we find ".." in a URL provided by the client, someone's likely
        //trying to trick us.  Ask them to do it another way if so.

        int i = url.indexOf("/..");
        while (i != -1)
        {
            if (i == (url.length() - 3) || url.charAt(i + 3) == '/')
            {
                throw new ProxyException(DOT_DOT_NOT_ALLOWED);
            }
            i = url.indexOf("/..", i + 1);
        }

        //Next, check if the URL is exactly the default URL
        url = url.toLowerCase();

        // In IPv6, update to long form, if required.
        url = SettingsReplaceUtil.updateIPv6(url);

        if (defaultUrl != null && defaultUrl.equalsIgnoreCase(url))
            return;

        char[] urlChars = url.toCharArray();

        // Next, check that the URL matches a dynamic URL pattern
        for (i = 0; i < dynamicUrls.size(); i++)
        {
            char[] pattern = (char[])dynamicUrls.get(i);
            boolean matches = StringUtils.findMatchWithWildcard(urlChars, pattern);

            if (matches)
            {
                if (!authSupplied || destination.allowsDynamicAuthentication())
                    return;
                throw new ProxyException(MULTIPLE_DOMAIN_PORT);
            }
        }

        ProxyException exception = new ProxyException();
        exception.setMessage
        (DYNAMIC_NOT_CONFIGURED, new Object[] {originalUrl, destination.getId()});
        throw exception;
    }

    /**
     * Returns the log category of the <code>HTTPProxyService</code>.
     *
     * @return The log category of the component.
     */
    @Override
    protected String getLogCategory()
    {
        return LOG_CATEGORY;
    }

    protected Object invokeHttp(ServiceAdapter adapter, HTTPMessage message, HTTPProxyDestination destination)
    {
        if (isManaged())
        {
            HTTPProxyDestinationControl destinationControl = (HTTPProxyDestinationControl)destination.getControl();
            if (destinationControl != null)
                destinationControl.incrementInvokeHTTPCount();
        }

        String dynamicUrl = message.getUrl();

        String contextPath = null;
        String serverName = null;
        String serverPort = null;
        String protocol = null;
        HttpServletRequest req = FlexContext.getHttpRequest();

        if (req != null)
        {
            contextPath = req.getContextPath();
            protocol = req.getScheme();
            serverName = req.getServerName();
            int port = req.getServerPort();
            if (port != 0)
            {
                serverPort = Integer.toString(req.getServerPort());
            }
        }

        if (dynamicUrl != null && !"".equals(dynamicUrl))
        {
            checkUrl(dynamicUrl, contextPath, destination, serverName, serverPort, protocol, message.getRemoteUsername() != null);
        }
        else
        {
            String url = destination.getParsedDefaultUrl(contextPath, serverName, serverPort, protocol);
            message.setUrl(url);
        }

        return adapter.invoke(message);
    }

    /**
     * This method is invoked to allow the <code>HTTPProxyService</code> to instantiate and register its
     * MBean control.
     *
     * @param broker The <code>MessageBroker</code> to pass to the <code>HTTPProxyServiceControl</code> constructor.
     */
    @Override
    protected void setupServiceControl(MessageBroker broker)
    {
        controller = new HTTPProxyServiceControl(this, broker.getControl());
        controller.register();
        setControl(controller);
    }
}
TOP

Related Classes of flex.messaging.services.HTTPProxyService

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.