/*
 * 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 flex.messaging.endpoints;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import flex.management.ManageableComponent;
import flex.management.runtime.messaging.MessageBrokerControl;
import flex.management.runtime.messaging.endpoints.EndpointControl;
import flex.messaging.FlexContext;
import flex.messaging.FlexSession;
import flex.messaging.MessageBroker;
import flex.messaging.MessageException;
import flex.messaging.Server;
import flex.messaging.client.FlexClient;
import flex.messaging.client.FlexClientOutboundQueueProcessor;
import flex.messaging.client.FlushResult;
import flex.messaging.client.PollFlushResult;
import flex.messaging.client.UserAgentSettings;
import flex.messaging.config.ChannelSettings;
import flex.messaging.config.ConfigMap;
import flex.messaging.config.ConfigurationConstants;
import flex.messaging.config.ConfigurationException;
import flex.messaging.config.SecurityConstraint;
import flex.messaging.io.ClassAliasRegistry;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.TypeMarshaller;
import flex.messaging.io.TypeMarshallingContext;
import flex.messaging.io.amf.translator.ASTranslator;
import flex.messaging.log.Log;
import flex.messaging.log.LogCategories;
import flex.messaging.log.Logger;
import flex.messaging.messages.AcknowledgeMessage;
import flex.messaging.messages.AcknowledgeMessageExt;
import flex.messaging.messages.AsyncMessage;
import flex.messaging.messages.AsyncMessageExt;
import flex.messaging.messages.CommandMessage;
import flex.messaging.messages.CommandMessageExt;
import flex.messaging.messages.Message;
import flex.messaging.messages.SmallMessage;
import flex.messaging.security.SecurityException;
import flex.messaging.util.ClassUtil;
import flex.messaging.util.StringUtils;
import flex.messaging.util.UserAgentManager;
import flex.messaging.validators.DeserializationValidator;

/**
 * This is the default implementation of Endpoint, which provides a convenient
 * base for behavior and associations common to all endpoints.
 *
 * These properties that appear in the endpoint configuration are only used by the
 * client, therefore they have to be set on the appropriate client classes: connect-timeout-seconds set on Channel.
 *
 * @see flex.messaging.endpoints.Endpoint
 */
public abstract class AbstractEndpoint extends ManageableComponent
        implements Endpoint2, ConfigurationConstants
{
    /** Log category for <code>AbstractEndpoint</code>. */
    public static final String LOG_CATEGORY = LogCategories.ENDPOINT_GENERAL;

    /**
     * HTTP header field names.
     */
    public static final String HEADER_NAME_CACHE_CONTROL = "Cache-Control";
    public static final String HEADER_NAME_EXPIRES = "Expires";
    public static final String HEADER_NAME_PRAGMA = "Pragma";

    // Errors
    private static final int NONSECURE_PROTOCOL = 10066;
    private static final int REQUIRES_FLEXCLIENT_SUPPORT = 10030;
    private static final int ERR_MSG_INVALID_URL_SCHEME = 11100;

    // XML Configuration Properties
    private static final String SERIALIZATION = "serialization";
    private static final String CREATE_ASOBJECT_FOR_MISSING_TYPE = "create-asobject-for-missing-type";
    private static final String CUSTOM_DESERIALIZER = "custom-deserializer";
    private static final String CUSTOM_SERIALIZER = "custom-serializer";
    private static final String ENABLE_SMALL_MESSAGES = "enable-small-messages";
    private static final String TYPE_MARSHALLER = "type-marshaller";
    private static final String RESTORE_REFERENCES = "restore-references";
    private static final String INSTANTIATE_TYPES = "instantiate-types";
    private static final String SUPPORT_REMOTE_CLASS = "support-remote-class";
    private static final String LEGACY_COLLECTION = "legacy-collection";
    private static final String LEGACY_DICTIONARY = "legacy-dictionary";
    private static final String LEGACY_MAP = "legacy-map";
    private static final String LEGACY_XML = "legacy-xml";
    private static final String LEGACY_XML_NAMESPACES = "legacy-xml-namespaces";
    private static final String LEGACY_THROWABLE = "legacy-throwable";
    private static final String LEGACY_BIG_NUMBERS = "legacy-big-numbers";
    private static final String LEGACY_EXTERNALIZABLE = "legacy-externalizable";
    private static final String ALLOW_XML_DOCTYPE_DECLARATION = "allow-xml-doctype-declaration";
    private static final String ALLOW_XML_EXTERNAL_ENTITY_EXPANSION = "allow-xml-external-entity-expansion";

    private static final String LOG_PROPERTY_ERRORS = "log-property-errors";
    private static final String IGNORE_PROPERTY_ERRORS = "ignore-property-errors";
    private static final String INCLUDE_READ_ONLY = "include-read-only";
    private static final String GLOBAL_INCLUDE_READ_ONLY = "global-include-read-only";
    private static final String FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR = "flex-client-outbound-queue-processor";
    private static final String SHOW_STACKTRACES = "show-stacktraces";
    private static final String MAX_OBJECT_NEST_LEVEL = "max-object-nest-level";
    private static final String MAX_COLLECTION_NEST_LEVEL = "max-collection-nest-level";
    private static final String PREFER_VECTORS = "prefer-vectors";

    // Endpoint properties
    protected Set<String> clientLoadBalancingUrls;
    protected String clientType;
    protected int connectTimeoutSeconds;
    protected int requestTimeoutSeconds;
    protected FlexClientOutboundQueueProcessor flexClientOutboundQueueProcessor;
    protected SerializationContext serializationContext;
    protected Class<?> deserializerClass;
    protected Class<?> serializerClass;
    protected TypeMarshaller typeMarshaller;
    protected int port;
    private SecurityConstraint securityConstraint;
    protected String url;
    protected boolean recordMessageSizes;
    protected boolean recordMessageTimes;
    protected boolean remote;
    protected Server server;
    protected boolean serverOnly;

    // Endpoint internal
    protected String parsedUrl;
    // Keeps track of what context path parsedUrl has been parsed for. If it is
    // null, means parsedUrl has not been parsed already.
    protected String parsedForContext;
    protected boolean clientContextParsed;
    protected String parsedClientUrl;
    protected Logger log;

    protected Class<?> flexClientOutboundQueueProcessClass;
    protected ConfigMap flexClientOutboundQueueProcessorConfig;

    // Supported messaging version
    protected double messagingVersion = 1.0;

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

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

    /**
     * Constructs an <code>AbstractEndpoint</code> with the indicated management.
     *
     * @param enableManagement <code>true</code> if the <code>AbstractEndpoint</code>
     * is manageable; <code>false</code> otherwise.
     */
    public AbstractEndpoint(boolean enableManagement)
    {
        super(enableManagement);
        this.log = Log.getLogger(getLogCategory());
        serializationContext = new SerializationContext();
    }

    //--------------------------------------------------------------------------
    //
    // Initialize, validate, start, and stop methods.
    //
    //--------------------------------------------------------------------------

    /**
     * Initializes the <code>Endpoint</code> with the properties.
     * If subclasses override this method, they must call <code>super.initialize()</code>.
     *
     * @param id The ID of the <code>Endpoint</code>.
     * @param properties Properties for the <code>Endpoint</code>.
     */
    @Override
    public void initialize(String id, ConfigMap properties)
    {
        super.initialize(id, properties);

        if (properties == null || properties.size() == 0)
            return;

        // Client-targeted <client-load-balancing>
        initializeClientLoadBalancing(id, properties);

        // Client-targeted <connect-timeout-seconds/>
        connectTimeoutSeconds = properties.getPropertyAsInt(CONNECT_TIMEOUT_SECONDS_ELEMENT, 0);

        // Client-targeted <request-timeout-seconds/>
        requestTimeoutSeconds = properties.getPropertyAsInt(REQUEST_TIMEOUT_SECONDS_ELEMENT, 0);

        // Check for a custom FlexClient outbound queue processor.
        ConfigMap outboundQueueConfig = properties.getPropertyAsMap(FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR, null);
        if (outboundQueueConfig != null)
        {
            // Get nested props for the processor.
            flexClientOutboundQueueProcessorConfig = outboundQueueConfig.getPropertyAsMap(PROPERTIES_ELEMENT, null);

            String pClassName = outboundQueueConfig.getPropertyAsString(CLASS_ATTR, null);
            if (pClassName != null)
            {
                try
                {
                    flexClientOutboundQueueProcessClass = createClass(pClassName);
                    // And now create an instance and initialize to make sure the properties are valid.
                    setFlexClientOutboundQueueProcessorConfig(flexClientOutboundQueueProcessorConfig);
                }
                catch (Throwable t)
                {
                    if (Log.isWarn())
                        log.warn("Cannot register custom FlexClient outbound queue processor class {0}", new Object[]{pClassName}, t);
                }
            }
        }

        ConfigMap serialization = properties.getPropertyAsMap(SERIALIZATION, null);
        if (serialization != null)
        {
            // Custom deserializers
            List<?> deserializers = serialization.getPropertyAsList(CUSTOM_DESERIALIZER, null);
            if (deserializers != null && Log.isWarn())
                log.warn("Endpoint <custom-deserializer> functionality is no longer available. Please remove this entry from your configuration.");

            // Custom serializers
            List<?> serializers = serialization.getPropertyAsList(CUSTOM_SERIALIZER, null);
            if (serializers != null && Log.isWarn())
                log.warn("Endpoint <custom-serializer> functionality is no longer available. Please remove this entry from your configuration.");

            // Type Marshaller implementation
            String typeMarshallerClassName = serialization.getPropertyAsString(TYPE_MARSHALLER, null);
            if (typeMarshallerClassName != null && typeMarshallerClassName.length() > 0)
            {
                try
                {
                    Class<?> tmc = createClass(typeMarshallerClassName);
                    typeMarshaller = (TypeMarshaller)ClassUtil.createDefaultInstance(tmc, TypeMarshaller.class);
                }
                catch (Throwable t)
                {
                    if (Log.isWarn())
                        log.warn("Cannot register custom type marshaller for type {0}", new Object[]{typeMarshallerClassName}, t);
                }
            }

            // Boolean Serialization Flags
            serializationContext.createASObjectForMissingType = serialization.getPropertyAsBoolean(CREATE_ASOBJECT_FOR_MISSING_TYPE, false);
            serializationContext.enableSmallMessages = serialization.getPropertyAsBoolean(ENABLE_SMALL_MESSAGES, true);
            serializationContext.instantiateTypes = serialization.getPropertyAsBoolean(INSTANTIATE_TYPES, true);
            serializationContext.supportRemoteClass = serialization.getPropertyAsBoolean(SUPPORT_REMOTE_CLASS, false);
            serializationContext.legacyCollection = serialization.getPropertyAsBoolean(LEGACY_COLLECTION, false);
            serializationContext.legacyDictionary = serialization.getPropertyAsBoolean(LEGACY_DICTIONARY, false);
            serializationContext.legacyMap = serialization.getPropertyAsBoolean(LEGACY_MAP, false);
            serializationContext.legacyXMLDocument = serialization.getPropertyAsBoolean(LEGACY_XML, false);
            serializationContext.legacyXMLNamespaces = serialization.getPropertyAsBoolean(LEGACY_XML_NAMESPACES, false);
            serializationContext.legacyThrowable = serialization.getPropertyAsBoolean(LEGACY_THROWABLE, false);
            serializationContext.legacyBigNumbers = serialization.getPropertyAsBoolean(LEGACY_BIG_NUMBERS, false);
            serializationContext.legacyExternalizable = serialization.getPropertyAsBoolean(LEGACY_EXTERNALIZABLE, false);
            serializationContext.allowXmlDoctypeDeclaration = serialization.getPropertyAsBoolean(ALLOW_XML_DOCTYPE_DECLARATION, false);
            serializationContext.allowXmlExternalEntityExpansion = serialization.getPropertyAsBoolean(ALLOW_XML_EXTERNAL_ENTITY_EXPANSION, false);
            serializationContext.maxObjectNestLevel = (int)serialization.getPropertyAsLong(MAX_OBJECT_NEST_LEVEL, 512);
            serializationContext.maxCollectionNestLevel = (int)serialization.getPropertyAsLong(MAX_COLLECTION_NEST_LEVEL, 15);
            serializationContext.preferVectors = serialization.getPropertyAsBoolean(PREFER_VECTORS, false);

            boolean showStacktraces = serialization.getPropertyAsBoolean(SHOW_STACKTRACES, false);
            if (showStacktraces && Log.isWarn())
                log.warn("The " + SHOW_STACKTRACES + " configuration option is deprecated and non-functional. Please remove this from your configuration file.");
            serializationContext.restoreReferences = serialization.getPropertyAsBoolean(RESTORE_REFERENCES, false);
            serializationContext.logPropertyErrors = serialization.getPropertyAsBoolean(LOG_PROPERTY_ERRORS, false);
            serializationContext.ignorePropertyErrors = serialization.getPropertyAsBoolean(IGNORE_PROPERTY_ERRORS, true);
            serializationContext.includeReadOnly = serialization.getPropertyAsBoolean(INCLUDE_READ_ONLY, false);
        }

        recordMessageSizes = properties.getPropertyAsBoolean(ConfigurationConstants.RECORD_MESSAGE_SIZES_ELEMENT, false);

        if (recordMessageSizes && Log.isWarn())
            log.warn("Setting <record-message-sizes> to true affects application performance and should only be used for debugging");

        recordMessageTimes = properties.getPropertyAsBoolean(ConfigurationConstants.RECORD_MESSAGE_TIMES_ELEMENT, false);
    }

    /**
     * Starts the endpoint if its associated <code>MessageBroker</code> is started,
     * and if the endpoint is not already running. If subclasses override this method,
     * they must call <code>super.start()</code>.
     */
    @Override
    public void start()
    {
        if (isStarted())
            return;

        // Check if the MessageBroker is started
        MessageBroker broker = getMessageBroker();
        if (!broker.isStarted())
        {
            if (Log.isWarn())
            {
                Log.getLogger(getLogCategory()).warn("Endpoint with id '{0}' cannot be started" +
                        " when the MessageBroker is not started.",
                        new Object[]{getId()});
            }
            return;
        }

        // Set up management
        if (isManaged() && broker.isManaged())
        {
            setupEndpointControl(broker);
            MessageBrokerControl controller = (MessageBrokerControl)broker.getControl();
            if (getControl() != null)
                controller.addEndpoint(this);
        }

        // Setup Deserializer and Serializer for the SerializationContext
        if (deserializerClass == null)
            deserializerClass = createClass(getDeserializerClassName());

        if (serializerClass == null)
            serializerClass = createClass(getSerializerClassName());

        serializationContext.setDeserializerClass(deserializerClass);
        serializationContext.setSerializerClass(serializerClass);

        // Setup endpoint features
        ClassAliasRegistry registry = ClassAliasRegistry.getRegistry();
        registry.registerAlias(AsyncMessageExt.CLASS_ALIAS, AsyncMessageExt.class.getName());
        registry.registerAlias(AcknowledgeMessageExt.CLASS_ALIAS, AcknowledgeMessageExt.class.getName());
        registry.registerAlias(CommandMessageExt.CLASS_ALIAS, CommandMessageExt.class.getName());
        super.start();
    }

    /**
     * Stops the endpoint if it is running. If subclasses override this method, they must
     * call <code>super.stop()</code>.
     */
    @Override
    public void stop()
    {
        if (!isStarted())
            return;

        super.stop();

        // Remove management
        if (isManaged() && getMessageBroker().isManaged())
        {
            if (getControl() != null)
            {
                getControl().unregister();
                setControl(null);
            }
            setManaged(false);
        }
    }

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

    /**
     * Adds a client-load-balancing URL.
     *
     * @param url A client-load-balancing URL.
     * @return <code>false</code> if the set already contains the URL, <code>true</code> otherwise.
     *
     */
    public boolean addClientLoadBalancingUrl(String url)
    {
        if (clientLoadBalancingUrls == null)
            clientLoadBalancingUrls = new HashSet<String>();

        if (url == null || url.length() == 0)
        {
            // Invalid {0} configuration for endpoint ''{1}''; cannot add empty url.
            ConfigurationException  ce = new ConfigurationException();
            ce.setMessage(ERR_MSG_EMTPY_CLIENT_LOAD_BALACNING_URL, new Object[]{CLIENT_LOAD_BALANCING_ELEMENT, getId()});
            throw ce;
        }

        return clientLoadBalancingUrls.add(url);
    }

    /**
     * Removes the client-load-balancing URL.
     *
     * @param url The URL to remove.
     * @return <code>true</code> if the set contained the URL, <code>false</code> otherwise.
     */
    public boolean removeClientLoadBalancingUrl(String url)
    {
        if (clientLoadBalancingUrls != null)
            return clientLoadBalancingUrls.remove(url);
        return false;
    }

    /**
     * Retrieves a snapshot of the current client-load-balancing URLs.
     *
     * @return A snapshot of the current client-load-balancing URLs, or <code>null</code> if
     * no URL exists.
     */
    public Set<String> getClientLoadBalancingUrls()
    {
        return clientLoadBalancingUrls == null? null : new HashSet<String>(clientLoadBalancingUrls);
    }

    /**
     * Retrieves the corresponding client channel type for the endpoint.
     *
     * @return The corresponding client channel type for the endpoint.
     */
    public String getClientType()
    {
        return clientType;
    }

    /**
     * Sets the corresponding client channel type for the endpoint.
     *
     * @param type The corresponding client channel type for the endpoint.
     */
    public void setClientType(String type)
    {
        this.clientType = type;
    }

    /**
     * Retrieves the <code>FlexClientOutboundQueueProcessorClass</code> of the endpoint.
     *
     * @return The <code>FlexClientOutboundQueueProcessorClass</code> of the endpoint.
     */
    public Class<?> getFlexClientOutboundQueueProcessorClass()
    {
        return flexClientOutboundQueueProcessClass;
    }

    /**
     * Sets the the <code>FlexClientOutboundQueueProcessor</code> of the endpoint.
     *
     * @param flexClientOutboundQueueProcessorClass the Class of the Flex client outbound queue processor.
     */
    public void setFlexClientOutboundQueueProcessorClass(Class<?> flexClientOutboundQueueProcessorClass)
    {
        this.flexClientOutboundQueueProcessClass = flexClientOutboundQueueProcessorClass;
        if (flexClientOutboundQueueProcessClass != null && flexClientOutboundQueueProcessorConfig != null)
        {
            FlexClientOutboundQueueProcessor processor = (FlexClientOutboundQueueProcessor)ClassUtil.createDefaultInstance(flexClientOutboundQueueProcessClass, null);
            processor.initialize(flexClientOutboundQueueProcessorConfig);
        }
    }

    /**
     * Retrieves the properties for the <code>FlexClientOutboundQueueProcessor</code> of the endpoint.
     *
     * @return The properties for the <code>FlexClientOutboundQueueProcessor</code> of the endpoint.
     */
    public ConfigMap getFlexClientOutboundQueueProcessorConfig()
    {
        return flexClientOutboundQueueProcessorConfig;
    }

    /**
     * Sets the properties for the <code>FlexClientOutboundQueueProcessor</code> of the endpoint.
     *
     * @param flexClientOutboundQueueProcessorConfig The configuration map.
     */
    public void setFlexClientOutboundQueueProcessorConfig(ConfigMap flexClientOutboundQueueProcessorConfig)
    {
        this.flexClientOutboundQueueProcessorConfig = flexClientOutboundQueueProcessorConfig;
        if (flexClientOutboundQueueProcessorConfig != null && flexClientOutboundQueueProcessClass != null)
        {
            FlexClientOutboundQueueProcessor processor = (FlexClientOutboundQueueProcessor)ClassUtil.createDefaultInstance(flexClientOutboundQueueProcessClass, null);
            processor.initialize(flexClientOutboundQueueProcessorConfig);
        }
    }

    /**
     * Sets the ID of the <code>AbstractEndpoint</code>. If the <code>AbstractEndpoint</code>
     * has a <code>MessageBroker</code> assigned, it also updates the ID in the
     * <code>MessageBroker</code>.
     *
     * @param id The endpoint ID.
     */
    @Override
    public void setId(String id)
    {
        String oldId = getId();

        if (oldId != null && oldId.equals(id))
            return;

        super.setId(id);

        // Update the endpoint id in the broker
        MessageBroker broker = getMessageBroker();
        if (broker != null)
        {
            // broker must have the endpoint then
            broker.removeEndpoint(oldId);
            broker.addEndpoint(this);
        }
    }

    /**
     * Retrieves the <code>MessageBroker</code> of the <code>AbstractEndpoint</code>.
     *
     * @return The <code>MessageBroker</code> of the <code>AbstractEndpoint</code>.
     */
    public MessageBroker getMessageBroker()
    {
        return (MessageBroker)getParent();
    }

    /**
     * Sets the <code>MessageBroker</code> of the <code>AbstractEndpoint</code>.
     * Removes the <code>AbstractEndpoint</code> from the old broker
     * (if there was one) and adds to the list of endpoints in the new broker.
     *
     * @param broker The <code>MessageBroker</code> of the <code>AbstractEndpoint</code>.
     */
    public void setMessageBroker(MessageBroker broker)
    {
        MessageBroker oldBroker = getMessageBroker();

        setParent(broker);

        if (oldBroker != null)
            oldBroker.removeEndpoint(getId());

        // Add endpoint to the new broker if needed
        if (broker.getEndpoint(getId()) != this)
            broker.addEndpoint(this);
    }

    /**
     * Return the highest messaging version currently available via this
     * endpoint.
     * @return double the messaging version
     */
    public double getMessagingVersion()
    {
        return messagingVersion;
    }

    /**
     * Retrieves the port of the URL of the endpoint.
     * A return value of 0 denotes no port in the channel URL.
     *
     * @return The port of the URL of the endpoint, or 0 if the URL does not contain
     * a port number.
     */
    public int getPort()
    {
        return port;
    }

    /**
     * Determines whether the endpoint is secure.
     *
     * @return <code>false</code> by default.
     */
    public boolean isSecure()
    {
        return false;
    }

    /**
     * Determines if the endpoint clients connect to directly is mirrored and running
     * on a remote host, in which case this local instance is not started and will service no direct
     * client connections.
     *
     * @return <code>true</code> if this endpoint will not process direct client connections and is just
     * a local representation of a symmetric endpoint on a remote host that will, <code>false</code> otherwise.
     */
    public boolean isRemote()
    {
        return remote;
    }

    /**
     * Sets the remote status for this endpoint.
     *
     * @param value <code>true</code> if this endpoint will not process direct client connections and is just
     * a local representation of a symmetric endpoint on a remote host that will, <code>false</code> otherwise.
     */
    public void setRemote(boolean value)
    {
        remote = value;
    }

    /**
     * Retrieves the <tt>Server</tt> that the endpoint is using, or <code>null</code> if
     * no server has been assigned.
     * @return Server The Server object the endpoint is using.
     */
    public Server getServer()
    {
        return server;
    }

    /**
     * Sets the <tt>Server</tt> that the endpoint will use.
     * @param server The Server object.
     */
    public void setServer(Server server)
    {
        this.server = server;
    }

    /**
     * Determines whether the endpoint is server only.
     *
     * @return <code>true</code> if the endpoint is server only, <code>false</code> otherwise.
     */
    public boolean getServerOnly()
    {
        return serverOnly;
    }

    /**
     * Sets whether the endpoint is server only.
     *
     * @param serverOnly <code>true</code> if the endpoint is server only, <code>false</code> otherwise.
     */
    public void setServerOnly(boolean serverOnly)
    {
        this.serverOnly = serverOnly;
    }

    /**
     * Retrieves the <code>SecurityConstraint</code> of the <code>Endpoint</code>.
     *
     * @return The <code>SecurityConstraint</code> of the <code>Endpoint</code>.
     */
    public SecurityConstraint getSecurityConstraint()
    {
        return securityConstraint;
    }

    /**
     * Sets the <code>SecurityConstraint</code> of the <code>Endpoint</code>.
     *
     * @param securityConstraint The SecurityContraint object.
     */
    public void setSecurityConstraint(SecurityConstraint securityConstraint)
    {
        this.securityConstraint = securityConstraint;
    }

    /**
     * Retrieves the <code>SerializationContext</code> of the endpoint.
     *
     * @return The <code>SerializationContext</code> of the endpoint.
     */
    public SerializationContext getSerializationContext()
    {
        return serializationContext;
    }

    /**
     * Sets the <code>SerializationContext</code> of the endpoint.
     *
     * @param serializationContext The SerializationContext object.
     */
    public void setSerializationContext(SerializationContext serializationContext)
    {
        this.serializationContext = serializationContext;
    }

    /**
     * Retrieves the <code>TypeMarshaller</code> of the endpoint.
     *
     * @return The <code>TypeMarshaller</code> of the endpoint.
     */
    public TypeMarshaller getTypeMarshaller()
    {
        if (typeMarshaller == null)
            typeMarshaller = new ASTranslator();

        return typeMarshaller;
    }

    /**
     * Sets the <code>TypeMarshaller</code> of the endpoint.
     *
     * @param typeMarshaller The TypeMarshaller object.
     */
    public void setTypeMarshaller(TypeMarshaller typeMarshaller)
    {
        this.typeMarshaller = typeMarshaller;
    }

    /**
     * Retrieves the URL of the endpoint.
     *
     * @return The URL of the endpoint.
     */
    public String getUrl()
    {
        return url;
    }

    /**
     * Sets the URL of the endpoint.
     *
     * @param url The URL of the endpoint.
     */
    public void setUrl(String url)
    {
        this.url = url;
        port = internalParsePort(url);
        parsedForContext = null;
        clientContextParsed = false;
    }

    /**
     *
     * Returns the url of the endpoint parsed for the client.
     *
     * @return The url of the endpoint parsed for the client.
     */
    public String getUrlForClient()
    {
        if (!clientContextParsed)
        {
            HttpServletRequest req = FlexContext.getHttpRequest();
            if (req != null)
            {
                String contextPath = req.getContextPath();
                parseClientUrl(contextPath);
            }
            else
            {
                return url;
            }
        }
        return parsedClientUrl;
    }

    /**
     *
     * Returns the total throughput for the endpoint.
     *
     * @return The total throughput for the endpoint.
     */
    public long getThroughput()
    {
        EndpointControl control = (EndpointControl)getControl();

        return control.getBytesDeserialized().longValue() + control.getBytesSerialized().longValue();
    }

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


    public static void addNoCacheHeaders(HttpServletRequest req, HttpServletResponse res)
    {
        String userAgent = req.getHeader(UserAgentManager.USER_AGENT_HEADER_NAME);

        // For MSIE over HTTPS, set additional Cache-Control values.
        if (req.isSecure() && userAgent != null && userAgent.indexOf(UserAgentSettings.USER_AGENT_MSIE) != -1)
            res.addHeader(HEADER_NAME_CACHE_CONTROL, "no-store, no-cache, must-revalidate, post-check=0, pre-check=0, no-transform, private");
        else // For the rest, set no-cache header value only.
            res.addHeader(HEADER_NAME_CACHE_CONTROL, "no-cache");

        // Set an expiration date in the past as well.
        res.setDateHeader(HEADER_NAME_EXPIRES, 946080000000L); //Approx Jan 1, 2000

        // Set Pragma no-cache header if we're not MSIE over HTTPS
        if (!(req.isSecure() && userAgent != null && userAgent.indexOf(UserAgentSettings.USER_AGENT_MSIE) != -1))
            res.setHeader(HEADER_NAME_PRAGMA, "no-cache");
    }

    /**
     *
     */
    public Message convertToSmallMessage(Message message)
    {
        if (message instanceof SmallMessage)
        {
            Message smallMessage = ((SmallMessage)message).getSmallMessage();
            if (smallMessage != null)
                message = smallMessage;
        }

        return message;
    }

    /**
     * Retrieves a <code>ConfigMap</code> of the endpoint properties the client
     * needs. Subclasses should add additional properties to <code>super.describeDestination</code>,
     * or return <code>null</code> if they must not send their properties to the client.
     *
     * @return ConfigMap The ConfigMap object.
     */
    public ConfigMap describeEndpoint()
    {
        ConfigMap channelConfig = new ConfigMap();

        if (serverOnly) // Client does not need server only endpoints.
            return channelConfig;

        channelConfig.addProperty(ID_ATTR, getId());
        channelConfig.addProperty(TYPE_ATTR, getClientType());

        ConfigMap properties = new ConfigMap();

        boolean containsClientLoadBalancing = clientLoadBalancingUrls != null && !clientLoadBalancingUrls.isEmpty();
        if (containsClientLoadBalancing)
        {
            ConfigMap clientLoadBalancing = new ConfigMap();
            for (Iterator<String> iterator = clientLoadBalancingUrls.iterator(); iterator.hasNext();)
            {
                ConfigMap url = new ConfigMap();
                // Adding as a value rather than attribute to the parent.
                url.addProperty(EMPTY_STRING, iterator.next());
                clientLoadBalancing.addProperty(URL_ATTR, url);
            }
            properties.addProperty(CLIENT_LOAD_BALANCING_ELEMENT, clientLoadBalancing);
        }

        // Add endpoint uri only if no client-load-balancing urls are defined.
        if (!containsClientLoadBalancing)
        {
            ConfigMap endpointConfig = new ConfigMap();
            endpointConfig.addProperty(URI_ATTR, getUrlForClient());
            channelConfig.addProperty(ENDPOINT_ELEMENT, endpointConfig);
        }

        if (connectTimeoutSeconds > 0)
        {
            ConfigMap connectTimeoutConfig = new ConfigMap();
            connectTimeoutConfig.addProperty(EMPTY_STRING, String.valueOf(connectTimeoutSeconds));
            properties.addProperty(CONNECT_TIMEOUT_SECONDS_ELEMENT, connectTimeoutConfig);
        }

        if (requestTimeoutSeconds > 0)
        {
            ConfigMap requestTimeoutSeconds = new ConfigMap();
            requestTimeoutSeconds.addProperty(EMPTY_STRING, String.valueOf(requestTimeoutSeconds));
            properties.addProperty(REQUEST_TIMEOUT_SECONDS_ELEMENT, requestTimeoutSeconds);
        }

        if (recordMessageTimes)
        {
            ConfigMap recordMessageTimesMap = new ConfigMap();
            // Adding as a value rather than attribute to the parent
            recordMessageTimesMap.addProperty(EMPTY_STRING, TRUE_STRING);
            properties.addProperty(RECORD_MESSAGE_TIMES_ELEMENT, recordMessageTimesMap);
        }

        if (recordMessageSizes)
        {
            ConfigMap recordMessageSizesMap = new ConfigMap();
            // Adding as a value rather than attribute to the parent
            recordMessageSizesMap.addProperty(EMPTY_STRING, TRUE_STRING);
            properties.addProperty(RECORD_MESSAGE_SIZES_ELEMENT, recordMessageSizesMap);
        }

        ConfigMap serialization = new ConfigMap();
        serialization.addProperty(ENABLE_SMALL_MESSAGES_ELEMENT, Boolean.toString(serializationContext.enableSmallMessages));
        properties.addProperty(SERIALIZATION_ELEMENT, serialization);

        if (properties.size() > 0)
            channelConfig.addProperty(PROPERTIES_ELEMENT, properties);

        return channelConfig;
    }

    /**
     *
     * Make sure this matches with ChannelSettings.getParsedUri.
     */
    public String getParsedUrl(String contextPath)
    {
        parseUrl(contextPath);
        return parsedUrl;
    }

    /**
     *
     */
    public void handleClientMessagingVersion(Number version)
    {
        if (version != null)
        {
            boolean clientSupportsSmallMessages = version.doubleValue() >= messagingVersion;
            if (clientSupportsSmallMessages && getSerializationContext().enableSmallMessages)
            {
                FlexSession session = FlexContext.getFlexSession();
                if (session != null)
                    session.setUseSmallMessages(true);
            }
        }
    }

    /**
     * Default implementation of the Endpoint <code>service</code> method.
     * Subclasses should call <code>super.service</code> before their custom
     * code.
     *
     * @param req The HttpServletRequest object.
     * @param res The HttpServletResponse object.
     */
    public void service(HttpServletRequest req, HttpServletResponse res)
    {
        validateRequestProtocol(req);
    }

    /**
     * Typically invoked by subclasses, this method transforms decoded message data
     * into the appropriate Message object and routes the Message to the endpoint's broker.
     *
     * @param message The decoded message data.
     * @return Message The transformed message.
     */
    public Message serviceMessage(Message message)
    {
        if (isManaged())
        {
            ((EndpointControl) getControl()).incrementServiceMessageCount();
        }

        try
        {
            FlexContext.setThreadLocalEndpoint(this);
            Message ack = null;

            // Make sure this message is timestamped.
            if (message.getTimestamp() == 0)
            {
                message.setTimestamp(System.currentTimeMillis());
            }

            // Reset the endpoint header for inbound messages to the id for this endpoint
            // to guarantee that it's correct. Don't allow clients to spoof this.
            // However, if the endpoint id is passed as null we need to tag the message to
            // skip channel/endpoint validation at the destination level (MessageBroker.inspectChannel()).
            if (message.getHeader(Message.ENDPOINT_HEADER) != null)
                message.setHeader(Message.VALIDATE_ENDPOINT_HEADER, Boolean.TRUE);
            message.setHeader(Message.ENDPOINT_HEADER, getId());

            if (message instanceof CommandMessage)
            {
                CommandMessage command = (CommandMessage)message;

                // Apply channel endpoint level constraint; always allow login commands through.
                int operation = command.getOperation();
                if (operation != CommandMessage.LOGIN_OPERATION)
                    checkSecurityConstraint(message);

                // Handle general (not Consumer specific) poll requests here.
                // We need to fetch all outbound messages for client subscriptions over this endpoint.
                // We identify these general poll messages by their operation and a null clientId.
                if (operation == CommandMessage.POLL_OPERATION && message.getClientId() == null)
                {
                    verifyFlexClientSupport(command);


                    FlexClient flexClient = FlexContext.getFlexClient();
                    ack = handleFlexClientPollCommand(flexClient, command);
                }
                else if (operation == CommandMessage.DISCONNECT_OPERATION)
                {
                    ack = handleChannelDisconnect(command);
                }
                else if (operation == CommandMessage.TRIGGER_CONNECT_OPERATION)
                {
                    ack = new AcknowledgeMessage();
                    ((AcknowledgeMessage)ack).setCorrelationId(message.getMessageId());

                    boolean needsConfig = false;
                    if (command.getHeader(CommandMessage.NEEDS_CONFIG_HEADER) != null)
                        needsConfig = ((Boolean)(command.getHeader(CommandMessage.NEEDS_CONFIG_HEADER)));

                    // Send configuration information only if the client requested.
                    if (needsConfig)
                    {
                        ConfigMap serverConfig = getMessageBroker().describeServices(this);
                        if (serverConfig.size() > 0)
                            ack.setBody(serverConfig);
                    }
                }
                else
                {
                    // Block a subset of commands for legacy clients that need to be recompiled to
                    // interop with a 2.5+ server.
                    if (operation == CommandMessage.SUBSCRIBE_OPERATION || operation == CommandMessage.POLL_OPERATION)
                        verifyFlexClientSupport(command);

                    ack = getMessageBroker().routeCommandToService((CommandMessage) message, this);

                    // Look for client advertised features on initial connect.
                    if (operation == CommandMessage.CLIENT_PING_OPERATION || operation == CommandMessage.LOGIN_OPERATION)
                    {
                        Number clientVersion = (Number)command.getHeader(CommandMessage.MESSAGING_VERSION);
                        handleClientMessagingVersion(clientVersion);

                        // Also respond by advertising the messaging version on the
                        // acknowledgement.
                        ack.setHeader(CommandMessage.MESSAGING_VERSION, new Double(messagingVersion));
                    }
                }
            }
            else
            {
                // Block any AsyncMessages from a legacy client.
                if (message instanceof AsyncMessage)
                    verifyFlexClientSupport(message);

                // Apply channel endpoint level constraint.
                checkSecurityConstraint(message);

                ack = getMessageBroker().routeMessageToService(message, this);
            }

            return ack;
        }
        finally
        {
            FlexContext.setThreadLocalEndpoint(null);
        }
    }

   /**
    * Utility method that endpoint implementations (or associated classes)
    * should invoke when they receive an incoming message from a client but before
    * servicing it. This method looks up or creates the proper FlexClient instance
    * based upon the client the message came from and places it in the FlexContext.
    *
    * @param message The incoming message to process.
    *
    * @return The FlexClient, or <code>null</code> if the message did not contain a FlexClient ID value.
    */
   public FlexClient setupFlexClient(Message message)
   {
       FlexClient flexClient = null;
       if (message.getHeaders().containsKey(Message.FLEX_CLIENT_ID_HEADER))
       {
           String id = (String)message.getHeaders().get(Message.FLEX_CLIENT_ID_HEADER);
           // If the id is null, reset to the special token value that let's us differentiate
           // between legacy clients and 2.5+ clients.
           if (id == null)
               id = FlexClient.NULL_FLEXCLIENT_ID;
           flexClient = setupFlexClient(id);
       }
       return flexClient;
   }

   /**
    * Utility method that endpoint implementations (or associated classes)
    * should invoke when they receive an incoming message from a client but before
    * servicing it. This method looks up or creates the proper FlexClient instance
    * based upon the FlexClient ID value received from the client.
    * It also associates this FlexClient instance with the current FlexSession.
    *
    * @param id The FlexClient ID value from the client.
    *
    * @return The FlexClient or null if the provided ID was <code>null</code>.
    */
   public FlexClient setupFlexClient(String id)
   {
       FlexClient flexClient = null;
       if (id != null)
       {
           // This indicates that we're dealing with a non-legacy client that hasn't been
           // assigned a FlexClient Id yet. Reset to null to generate a fresh Id.
           if (id.equals(FlexClient.NULL_FLEXCLIENT_ID))
               id = null;

           flexClient = getMessageBroker().getFlexClientManager().getFlexClient(id);
           // Make sure the FlexClient and FlexSession are associated.
           FlexSession session = FlexContext.getFlexSession();
           flexClient.registerFlexSession(session);
           // And place the FlexClient in FlexContext for this request.
           FlexContext.setThreadLocalFlexClient(flexClient);
       }
       return flexClient;
   }

   /**
    *
    * Performance metrics gathering property
    */
    public boolean isRecordMessageSizes()
    {
        return recordMessageSizes;
    }

   /**
    *
    * Performance metrics gathering property
    */
    public boolean isRecordMessageTimes()
    {
        return recordMessageTimes;
    }

    /**
     *
     */
    public void setThreadLocals()
    {
        if (serializationContext != null)
        {
            SerializationContext context = (SerializationContext)serializationContext.clone();
            // Get the latest deserialization validator from the broker.
            MessageBroker broker = getMessageBroker();
            DeserializationValidator validator = broker == null? null : broker.getDeserializationValidator();
            context.setDeserializationValidator(validator);
            SerializationContext.setSerializationContext(context);
        }

        TypeMarshallingContext.setTypeMarshaller(getTypeMarshaller());
    }

    /**
     *
     */
    public void clearThreadLocals()
    {
        SerializationContext.clearThreadLocalObjects();
        TypeMarshallingContext.clearThreadLocalObjects();
    }

    //--------------------------------------------------------------------------
    //
    // Protected/private methods.
    //
    //--------------------------------------------------------------------------

    /**
     * Returns the log category of the <code>AbstractEndpoint</code>. Subclasses
     * can override to provide a more specific logging category.
     *
     * @return The log category.
     */
    @Override
    protected String getLogCategory()
    {
        return LOG_CATEGORY;
    }

    /**
     * Hook method invoked when a disconnect command is received from a client channel.
     * The response returned by this method is not guaranteed to get to the client, which
     * is free to terminate its physical connection at any point.
     *
     * @param disconnectCommand The disconnect command.
     * @return The response; by default an empty <tt>AcknowledgeMessage</tt>.
     */
    protected Message handleChannelDisconnect(CommandMessage disconnectCommand)
    {
        return new AcknowledgeMessage();
    }

    /**
     * Hook method for varying poll reply strategies for synchronous endpoints.
     * The default behavior performs a non-waited, synchronous poll for the FlexClient
     * and if any messages are currently queued they are returned immediately. If no
     * messages are queued an empty response is returned immediately.
     *
     * @param flexClient The FlexClient that issued the poll request.
     * @param pollCommand The poll command from the client.
     * @return The FlushResult response.
     */
    protected FlushResult handleFlexClientPoll(FlexClient flexClient, CommandMessage pollCommand)
    {
        return flexClient.poll(getId());
    }

    /**
     * Handles a general poll request from a FlexClient to this endpoint.
     * Subclasses may override to implement different poll handling strategies.
     *
     * @param flexClient The FlexClient that issued the poll request.
     * @param pollCommand The poll command from the client.
     * @return The poll response message; either for success or fault.
     */
    protected Message handleFlexClientPollCommand(FlexClient flexClient, CommandMessage pollCommand)
    {
        if (Log.isDebug())
            Log.getLogger(getMessageBroker().getLogCategory(pollCommand)).debug(
                 "Before handling general client poll request. " + StringUtils.NEWLINE +
                 "  incomingMessage: " + pollCommand + StringUtils.NEWLINE);

        FlushResult flushResult = handleFlexClientPoll(flexClient, pollCommand);
        Message pollResponse = null;

        // Generate a no-op poll response if necessary; prevents a single client from busy polling when the server
        // is doing wait()-based long-polls.
        if ((flushResult instanceof PollFlushResult) && ((PollFlushResult)flushResult).isClientProcessingSuppressed())
        {
            pollResponse = new CommandMessage(CommandMessage.CLIENT_SYNC_OPERATION);
            pollResponse.setHeader(CommandMessage.NO_OP_POLL_HEADER, Boolean.TRUE);
        }

        if (pollResponse == null)
        {
            List<Message> messagesToReturn = (flushResult != null) ? flushResult.getMessages() : null;
            if (messagesToReturn != null && !messagesToReturn.isEmpty())
            {
                pollResponse = new CommandMessage(CommandMessage.CLIENT_SYNC_OPERATION);
                pollResponse.setBody(messagesToReturn.toArray());
            }
            else
            {
                pollResponse = new AcknowledgeMessage();
            }
        }

        // Set the adaptive poll wait time if necessary.
        if (flushResult != null)
        {
            int nextFlushWaitTime = flushResult.getNextFlushWaitTimeMillis();
            if (nextFlushWaitTime > 0)
                pollResponse.setHeader(CommandMessage.POLL_WAIT_HEADER, new Integer(nextFlushWaitTime));
        }

        if (Log.isDebug())
        {
            String debugPollResult = Log.getPrettyPrinter().prettify(pollResponse);
            Log.getLogger(getMessageBroker().getLogCategory(pollCommand)).debug(
                 "After handling general client poll request. " + StringUtils.NEWLINE +
                 "  reply: " + debugPollResult + StringUtils.NEWLINE);
        }

        return pollResponse;
    }

    /**
     * Initializes the <code>Endpoint</code> with the client-load-balancing urls.
     *
     * @param id Id of the <code>Endpoint</code>.
     * @param properties Properties for the <code>Endpoint</code>.
     */

    protected void initializeClientLoadBalancing(String id, ConfigMap properties)
    {
        if (!properties.containsKey(CLIENT_LOAD_BALANCING_ELEMENT))
            return;

        ConfigMap clientLoadBalancing = properties.getPropertyAsMap(CLIENT_LOAD_BALANCING_ELEMENT, null);
        if (clientLoadBalancing == null)
        {
            // Invalid {0} configuration for endpoint ''{1}''; no urls defined.
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(ERR_MSG_EMPTY_CLIENT_LOAD_BALANCING_ELEMENT, new Object[]{CLIENT_LOAD_BALANCING_ELEMENT, getId()});
            throw ce;
        }

        @SuppressWarnings("unchecked")
        List<String> urls = clientLoadBalancing.getPropertyAsList(URL_ATTR, null);
        if (urls == null || urls.isEmpty())
        {
            // Invalid {0} configuration for endpoint ''{1}''; no urls defined.
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(ERR_MSG_EMPTY_CLIENT_LOAD_BALANCING_ELEMENT, new Object[]{CLIENT_LOAD_BALANCING_ELEMENT, getId()});
            throw ce;
        }

        for (Iterator<String> iterator = urls.iterator(); iterator.hasNext();)
        {
            String url = iterator.next();
            if (!addClientLoadBalancingUrl(url) && Log.isWarn())
                log.warn("Endpoint '{0}' is ignoring the url '{1}' as it's already in the set of client-load-balancing urls.", new Object[]{id, url});
        }
    }

    protected void checkSecurityConstraint(Message message)
    {
        if (securityConstraint != null)
        {
            getMessageBroker().getLoginManager().checkConstraint(securityConstraint);
        }
    }

    /**
     * Returns the deserializer class name used by the endpoint.
     *
     * @return The deserializer class name used by the endpoint.
     */
    protected abstract String getDeserializerClassName();

    /**
     * Returns the serializer class name used by the endpoint.
     *
     * @return The serializer class name used by the endpoint.
     */
    protected abstract String getSerializerClassName();

    /**
     * Returns the secure protocol scheme for the endpoint.
     *
     * @return The secure protocol scheme for the endpoint.
     */
    protected abstract String getSecureProtocolScheme();

    /**
     * Returns the insecure protocol scheme for the endpoint.
     *
     * @return The insecure protocol scheme for the endpoint.
     */
    protected abstract String getInsecureProtocolScheme();

    /**
     * Invoked automatically to allow the <code>AbstractEndpoint</code> to setup
     * its corresponding MBean control. Subclasses should override to setup and
     * register their MBean control. Manageable subclasses should override this
     * template method.
     *
     * @param broker The <code>MessageBroker</code> that manages this
     * <code>AbstractEndpoint</code>.
     */
    protected abstract void setupEndpointControl(MessageBroker broker);

    /**
     * Validates the endpoint url scheme.
     */
    protected void validateEndpointProtocol()
    {
        String scheme = isSecure()? getSecureProtocolScheme() : getInsecureProtocolScheme();
        if (!url.startsWith(scheme))
        {
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(ERR_MSG_INVALID_URL_SCHEME, new Object[] {url, scheme});
            throw ce;
        }
    }

    protected void validateRequestProtocol(HttpServletRequest req)
    {
        // Secure url can talk to secure or non-secure endpoint.
        // Non-secure url can only talk to non-secure endpoint.
        boolean secure = req.isSecure();
        if (!secure && isSecure())
        {
            // Secure endpoints must be contacted via a secure protocol.
            String endpointPath = req.getServletPath() + req.getPathInfo();
            SecurityException se = new SecurityException();
            se.setMessage(NONSECURE_PROTOCOL, new Object[]{endpointPath});
            throw se;
        }
    }

    /**
     *
     * Verifies that the remote client supports the FlexClient API.
     * Legacy clients that do not support this receive a message fault for any messages they send.
     *
     * @param message The message to verify.
     */
    protected void verifyFlexClientSupport(Message message)
    {
        if (FlexContext.getFlexClient() == null)
        {
            MessageException me = new MessageException();
            me.setMessage(REQUIRES_FLEXCLIENT_SUPPORT, new Object[] {message.getDestination()});
            throw me;
        }
    }

    /**
     *
     */
    protected Class<?> createClass(String className)
    {
        return ClassUtil.createClass(className, FlexContext.getMessageBroker() == null ? null :
                    FlexContext.getMessageBroker().getClassLoader());
    }

    // This should match with ChannelSetting.parseClientUri
    private void parseClientUrl(String contextPath)
    {
        if (!clientContextParsed)
        {
            String channelEndpoint = url.trim();

            // either {context-root} or {context.root} is legal
            channelEndpoint = StringUtils.substitute(channelEndpoint, "{context-root}", ConfigurationConstants.CONTEXT_PATH_TOKEN);

            if ((contextPath == null) && (channelEndpoint.indexOf(ConfigurationConstants.CONTEXT_PATH_TOKEN) != -1))
            {
                // context root must be specified before it is used
                ConfigurationException e = new ConfigurationException();
                e.setMessage(ConfigurationConstants.UNDEFINED_CONTEXT_ROOT, new Object[]{getId()});
                throw e;
            }

            // simplify the number of combinations to test by ensuring our
            // context path always starts with a slash
            if (contextPath != null && !contextPath.startsWith("/"))
            {
                contextPath = "/" + contextPath;
            }

            // avoid double-slashes from context root by replacing /{context.root}
            // in a single replacement step
            if (channelEndpoint.indexOf(ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN) != -1)
            {
                // but avoid double-slash for /{context.root}/etc when we have
                // the default context root
                if ("/".equals(contextPath) && !ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN.equals(channelEndpoint))
                    contextPath = "";

                channelEndpoint = StringUtils.substitute(channelEndpoint, ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN, contextPath);
            }
            // otherwise we have something like {server.name}:{server.port}{context.root}...
            else
            {
                // but avoid double-slash for {context.root}/etc when we have
                // the default context root
                if ("/".equals(contextPath) && !ConfigurationConstants.CONTEXT_PATH_TOKEN.equals(channelEndpoint))
                    contextPath = "";

                channelEndpoint = StringUtils.substitute(channelEndpoint, ConfigurationConstants.CONTEXT_PATH_TOKEN, contextPath);
            }

            parsedClientUrl = channelEndpoint;
            clientContextParsed = true;
        }
    }

    private int internalParsePort(String url)
    {
        int port = ChannelSettings.parsePort(url);
        // If there is no specified port, log an info message as urls without ports are supported
        if (port == 0 && Log.isInfo())
            log.info("No port specified in channel URL:  {0}", new Object[]{url});

        return port == -1? 0 : port; // Replace -1 with 0.
    }

    private void parseUrl(String contextPath)
    {
        // Parse again only if never parsed before or parsed for a different contextPath.
        if (parsedForContext == null || !parsedForContext.equals(contextPath))
        {
            String channelEndpoint = url.toLowerCase().trim();

            // Remove protocol and host info
            String insecureProtocol = getInsecureProtocolScheme() + "://";
            String secureProtocol = getSecureProtocolScheme() + "://";
            if (channelEndpoint.startsWith(secureProtocol) || channelEndpoint.startsWith(insecureProtocol))
            {
                int nextSlash = channelEndpoint.indexOf('/', 8);
                if (nextSlash > 0)
                {
                    channelEndpoint = channelEndpoint.substring(nextSlash);
                }
            }

            // either {context-root} or {context.root} is legal
            channelEndpoint = StringUtils.substitute(channelEndpoint, "{context-root}", ConfigurationConstants.CONTEXT_PATH_TOKEN);

            // Remove context path info
            if (channelEndpoint.startsWith(ConfigurationConstants.CONTEXT_PATH_TOKEN))
            {
                channelEndpoint = channelEndpoint.substring(ConfigurationConstants.CONTEXT_PATH_TOKEN.length());
            }
            else if (channelEndpoint.startsWith(ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN))
            {
                channelEndpoint = channelEndpoint.substring(ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN.length());
            }
            else if (contextPath.length() > 0)
            {
                if (channelEndpoint.startsWith(contextPath.toLowerCase()))
                {
                    channelEndpoint = channelEndpoint.substring(contextPath.length());
                }
            }

            // We also don't match on trailing slashes
            if (channelEndpoint.endsWith("/"))
            {
                channelEndpoint = channelEndpoint.substring(0, channelEndpoint.length() - 1);
            }

            parsedUrl = channelEndpoint;
            parsedForContext = contextPath;
        }
    }
}
