You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2017/04/16 22:32:35 UTC

[44/72] [abbrv] [partial] flex-blazeds git commit: - Major code scrub

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ClientConfigurationParser.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ClientConfigurationParser.java b/common/src/main/java/flex/messaging/config/ClientConfigurationParser.java
new file mode 100644
index 0000000..cff5d47
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ClientConfigurationParser.java
@@ -0,0 +1,951 @@
+/*
+ * 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.config;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * A special mxmlc compiler specific implentation of the configuration
+ * parser for JDK 1.4. Only a small subset of the configuration is
+ * processed to generate the information that the client needs at runtime,
+ * such as channel definitions and service destination properties.
+ *
+ *
+ */
+public abstract class ClientConfigurationParser extends AbstractConfigurationParser
+{
+    protected void parseTopLevelConfig(Document doc)
+    {
+        Node root = selectSingleNode(doc, "/" + SERVICES_CONFIG_ELEMENT);
+
+        if (root != null)
+        {
+            // Validation
+            allowedChildElements(root, SERVICES_CONFIG_CHILDREN);
+
+            // Channels (parse before services)
+            channelsSection(root);
+
+            // Services
+            services(root);
+
+            // Clustering
+            clusters(root);
+
+            // FlexClient
+            flexClient(root);
+        }
+    }
+
+    private void channelsSection(Node root)
+    {
+        Node channelsNode = selectSingleNode(root, CHANNELS_ELEMENT);
+        if (channelsNode != null)
+        {
+            // Validation
+            allowedAttributesOrElements(channelsNode, CHANNELS_CHILDREN);
+
+            NodeList channels = selectNodeList(channelsNode, CHANNEL_DEFINITION_ELEMENT);
+            for (int i = 0; i < channels.getLength(); i++)
+            {
+                Node channel = channels.item(i);
+                channelDefinition(channel);
+            }
+            NodeList includes = selectNodeList(channelsNode, CHANNEL_INCLUDE_ELEMENT);
+            for (int i = 0; i < includes.getLength(); i++)
+            {
+                Node include = includes.item(i);
+                channelInclude(include);
+            }
+        }
+    }
+
+    private void channelDefinition(Node channel)
+    {
+        // Validation
+        requiredAttributesOrElements(channel, CHANNEL_DEFINITION_REQ_CHILDREN);
+        allowedAttributesOrElements(channel, CHANNEL_DEFINITION_CHILDREN);
+
+        String id = getAttributeOrChildElement(channel, ID_ATTR).trim();
+        if (isValidID(id))
+        {
+            // Don't allow multiple channels with the same id
+            if (config.getChannelSettings(id) != null)
+            {
+                // Cannot have multiple channels with the same id ''{0}''.
+                ConfigurationException e = new ConfigurationException();
+                e.setMessage(DUPLICATE_CHANNEL_ERROR, new Object[]{id});
+                throw e;
+            }
+
+            ChannelSettings channelSettings = new ChannelSettings(id);
+
+            // Endpoint
+            Node endpoint = selectSingleNode(channel, ENDPOINT_ELEMENT);
+            if (endpoint != null)
+            {
+                // Endpoint Validation
+                allowedAttributesOrElements(endpoint, ENDPOINT_CHILDREN);
+
+                // The url attribute may also be specified by the deprecated uri attribute
+                String uri = getAttributeOrChildElement(endpoint, URL_ATTR);
+                if (uri == null || EMPTY_STRING.equals(uri))
+                    uri = getAttributeOrChildElement(endpoint, URI_ATTR);
+                channelSettings.setUri(uri);
+
+                config.addChannelSettings(id, channelSettings);
+            }
+
+            channelServerOnlyAttribute(channel, channelSettings);
+
+            // Add the channel properties that the client needs namely polling-enabled,
+            // polling-interval-millis, piggybacking-enabled, login-after-disconnect,
+            // record-message-sizes, record-message-times, connect-timeout-seconds,
+            // polling-interval-seconds (deprecated), and client-load-balancing.
+            addProperty(channel, channelSettings, POLLING_ENABLED_ELEMENT);
+            addProperty(channel, channelSettings, POLLING_INTERVAL_MILLIS_ELEMENT);
+            addProperty(channel, channelSettings, PIGGYBACKING_ENABLED_ELEMENT);
+            addProperty(channel, channelSettings, LOGIN_AFTER_DISCONNECT_ELEMENT);
+            addProperty(channel, channelSettings, RECORD_MESSAGE_SIZES_ELEMENT);
+            addProperty(channel, channelSettings, RECORD_MESSAGE_TIMES_ELEMENT);
+            addProperty(channel, channelSettings, CONNECT_TIMEOUT_SECONDS_ELEMENT);
+            addProperty(channel, channelSettings, POLLING_INTERVAL_SECONDS_ELEMENT); // deprecated.
+            addProperty(channel, channelSettings, CLIENT_LOAD_BALANCING_ELEMENT);
+            addProperty(channel, channelSettings, REQUEST_TIMEOUT_SECONDS_ELEMENT);
+
+            // enable-small-messages.
+            NodeList properties = selectNodeList(channel, PROPERTIES_ELEMENT + "/" + SERIALIZATION_ELEMENT);
+            if (properties.getLength() > 0)
+            {
+                ConfigMap map = properties(properties, getSourceFileOf(channel));
+                ConfigMap serialization = map.getPropertyAsMap(SERIALIZATION_ELEMENT, null);
+                if (serialization != null)
+                {
+                    // enable-small-messages.
+                    String enableSmallMessages = serialization.getProperty(ENABLE_SMALL_MESSAGES_ELEMENT);
+                    if (enableSmallMessages != null)
+                    {
+                        ConfigMap clientMap = new ConfigMap();
+                        clientMap.addProperty(ENABLE_SMALL_MESSAGES_ELEMENT, enableSmallMessages);
+                        channelSettings.addProperty(SERIALIZATION_ELEMENT, clientMap);
+                    }
+                }
+            }
+        }
+        else
+        {
+            // Invalid {CHANNEL_DEFINITION_ELEMENT} id '{id}'.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(INVALID_ID, new Object[]{CHANNEL_DEFINITION_ELEMENT, id});
+            String details = "An id must be non-empty and not contain any list delimiter characters, i.e. commas, semi-colons or colons.";
+            ex.setDetails(details);
+            throw ex;
+        }
+    }
+
+    private void channelServerOnlyAttribute(Node channel, ChannelSettings channelSettings)
+    {
+        String clientType = getAttributeOrChildElement(channel, CLASS_ATTR);
+        clientType = clientType.length() > 0? clientType : null;
+
+        String serverOnlyString = getAttributeOrChildElement(channel, SERVER_ONLY_ATTR);
+        boolean serverOnly = serverOnlyString.length() > 0 && Boolean.valueOf(serverOnlyString).booleanValue();
+
+        if (clientType == null && !serverOnly) // None set.
+        {
+            String url = channelSettings.getUri();
+            boolean serverOnlyProtocol = (url.startsWith("samfsocket") || url.startsWith("amfsocket") || url.startsWith("ws"));
+            if (!serverOnlyProtocol)
+            {
+                // Endpoint ''{0}'' needs to have either class or server-only attribute defined.
+                ConfigurationException ce = new ConfigurationException();
+                ce.setMessage(CLASS_OR_SERVER_ONLY_ERROR, new Object[]{channelSettings.getId()});
+                throw ce;
+            }
+            channelSettings.setServerOnly(true);
+        }
+        else if (clientType != null && serverOnly) // Both set.
+        {
+            // Endpoint ''{0}'' cannot have both class and server-only attribute defined.
+            ConfigurationException ce = new ConfigurationException();
+            ce.setMessage(CLASS_AND_SERVER_ONLY_ERROR, new Object[]{channelSettings.getId()});
+            throw ce;
+        }
+        else // One of them set.
+        {
+            if (serverOnly)
+                channelSettings.setServerOnly(true);
+            else
+                channelSettings.setClientType(clientType);
+        }
+    }
+
+    private void addProperty(Node channel, ChannelSettings channelSettings, String property)
+    {
+        NodeList properties = selectNodeList(channel, PROPERTIES_ELEMENT + "/" + property);
+        if (properties.getLength() > 0)
+        {
+            ConfigMap map = properties(properties, getSourceFileOf(channel));
+            if (CLIENT_LOAD_BALANCING_ELEMENT.equals(property))
+            {
+                ConfigMap clientLoadBalancingMap = map.getPropertyAsMap(CLIENT_LOAD_BALANCING_ELEMENT, null);
+                if (clientLoadBalancingMap == 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, channelSettings.getId()});
+                    throw ce;
+                }
+                List urls = clientLoadBalancingMap.getPropertyAsList(URL_ATTR, null);
+                addClientLoadBalancingUrls(urls, channelSettings.getId());
+            }
+            channelSettings.addProperties(map);
+        }
+    }
+
+    // Add client load balancing urls after necessary validation checks.
+    private void addClientLoadBalancingUrls(List urls, String endpointId)
+    {
+        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, endpointId});
+            throw ce;
+        }
+
+        Set clientLoadBalancingUrls = new HashSet();
+        for (Iterator iterator = urls.iterator(); iterator.hasNext();)
+        {
+            String url = (String) iterator.next();
+            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, endpointId});
+                throw ce;
+            }
+
+            if (TokenReplacer.containsTokens(url))
+            {
+                // Invalid {0} configuration for endpoint ''{1}''; cannot add url with tokens.
+                ConfigurationException  ce = new ConfigurationException();
+                ce.setMessage(ERR_MSG_CLIENT_LOAD_BALANCING_URL_WITH_TOKEN, new Object[]{CLIENT_LOAD_BALANCING_ELEMENT, endpointId});
+                throw ce;
+            }
+
+            if (clientLoadBalancingUrls.contains(url))
+                iterator.remove();
+            else
+                clientLoadBalancingUrls.add(url);
+        }
+
+    }
+
+    private void channelInclude(Node channelInclude)
+    {
+        // Validation
+        allowedAttributesOrElements(channelInclude, CHANNEL_INCLUDE_CHILDREN);
+
+        String src = getAttributeOrChildElement(channelInclude, SRC_ATTR);
+        String dir = getAttributeOrChildElement(channelInclude, DIRECTORY_ATTR);
+        if (src.length() > 0)
+        {
+            channelIncludeFile(src);
+        }
+        else if (dir.length() > 0)
+        {
+            channelIncludeDirectory(dir);
+        }
+        else
+        {
+            // The include element ''{0}'' must specify either the ''{1}'' or ''{2}'' attribute.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(MISSING_INCLUDE_ATTRIBUTES, new Object[]{channelInclude.getNodeName(), SRC_ATTR, DIRECTORY_ATTR});
+            throw ex;
+        }
+    }
+
+    private void channelIncludeFile(String src)
+    {
+        Document doc = loadDocument(src, fileResolver.getIncludedFile(src));
+        if (fileResolver instanceof LocalFileResolver)
+        {
+            LocalFileResolver local = (LocalFileResolver)fileResolver;
+            ((ClientConfiguration)config).addConfigPath(local.getIncludedPath(src), local.getIncludedLastModified(src));
+        }
+
+        doc.getDocumentElement().normalize();
+
+        // Check for multiple channels in a single file.
+        Node channelsNode = selectSingleNode(doc, CHANNELS_ELEMENT);
+        if (channelsNode != null)
+        {
+            allowedChildElements(channelsNode, CHANNELS_CHILDREN);
+            NodeList channels = selectNodeList(channelsNode, CHANNEL_DEFINITION_ELEMENT);
+            for (int a = 0; a < channels.getLength(); a++)
+            {
+                Node service = channels.item(a);
+                channelDefinition(service);
+            }
+            fileResolver.popIncludedFile();
+        }
+        else // Check for single channel in the file.
+        {
+            Node channel = selectSingleNode(doc, "/" + CHANNEL_DEFINITION_ELEMENT);
+            if (channel != null)
+            {
+                channelDefinition(channel);
+                fileResolver.popIncludedFile();
+            }
+            else
+            {
+                // The {0} root element in file {1} must be '{CHANNELS_ELEMENT}' or '{CHANNEL_ELEMENT}'.
+                ConfigurationException ex = new ConfigurationException();
+                ex.setMessage(INVALID_INCLUDE_ROOT, new Object[]{CHANNEL_INCLUDE_ELEMENT, src, CHANNELS_ELEMENT, CHANNEL_DEFINITION_ELEMENT});
+                throw ex;
+            }
+        }
+    }
+
+    private void channelIncludeDirectory(String dir)
+    {
+        List files = fileResolver.getFiles(dir);
+        for (int i = 0; i < files.size(); i++)
+        {
+            String src = (String) files.get(i);
+            channelIncludeFile(src);
+        }
+    }
+
+    private void services(Node root)
+    {
+        Node servicesNode = selectSingleNode(root, SERVICES_ELEMENT);
+        if (servicesNode != null)
+        {
+            // Validation
+            allowedChildElements(servicesNode, SERVICES_CHILDREN);
+
+            // Default Channels for the application
+            Node defaultChannels = selectSingleNode(servicesNode, DEFAULT_CHANNELS_ELEMENT);
+            if (defaultChannels != null)
+            {
+                allowedChildElements(defaultChannels, DEFAULT_CHANNELS_CHILDREN);
+                NodeList channels = selectNodeList(defaultChannels, CHANNEL_ELEMENT);
+                for (int c = 0; c < channels.getLength(); c++)
+                {
+                    Node chan = channels.item(c);
+                    allowedAttributes(chan, new String[] {REF_ATTR});
+                    defaultChannel(chan);
+                }
+            }
+
+            // Service Includes
+            NodeList services = selectNodeList(servicesNode, SERVICE_INCLUDE_ELEMENT);
+            for (int i = 0; i < services.getLength(); i++)
+            {
+                Node service = services.item(i);
+                serviceInclude(service);
+            }
+
+            // Service
+            services = selectNodeList(servicesNode, SERVICE_ELEMENT);
+            for (int i = 0; i < services.getLength(); i++)
+            {
+                Node service = services.item(i);
+                service(service);
+            }
+        }
+    }
+
+    private void clusters(Node root)
+    {
+        Node clusteringNode = selectSingleNode(root, CLUSTERS_ELEMENT);
+        if (clusteringNode != null)
+        {
+            allowedAttributesOrElements(clusteringNode, CLUSTERING_CHILDREN);
+
+            NodeList clusters = selectNodeList(clusteringNode, CLUSTER_DEFINITION_ELEMENT);
+            for (int i = 0; i < clusters.getLength(); i++)
+            {
+                Node cluster = clusters.item(i);
+                requiredAttributesOrElements(cluster, CLUSTER_DEFINITION_CHILDREN);
+                String clusterName = getAttributeOrChildElement(cluster, ID_ATTR);
+                if (isValidID(clusterName))
+                {
+                    String propsFileName = getAttributeOrChildElement(cluster, CLUSTER_PROPERTIES_ATTR);
+                    ClusterSettings clusterSettings = new ClusterSettings();
+                    clusterSettings.setClusterName(clusterName);
+                    clusterSettings.setPropsFileName(propsFileName);
+                    String defaultValue = getAttributeOrChildElement(cluster, ClusterSettings.DEFAULT_ELEMENT);
+                    if (defaultValue != null && defaultValue.length() > 0)
+                    {
+                        if (defaultValue.equalsIgnoreCase("true"))
+                            clusterSettings.setDefault(true);
+                        else if (!defaultValue.equalsIgnoreCase("false"))
+                        {
+                            ConfigurationException e = new ConfigurationException();
+                            e.setMessage(10215, new Object[] {clusterName, defaultValue});
+                            throw e;
+                        }
+                    }
+                    String ulb = getAttributeOrChildElement(cluster, ClusterSettings.URL_LOAD_BALANCING);
+                    if (ulb != null && ulb.length() > 0)
+                    {
+                        if (ulb.equalsIgnoreCase("false"))
+                            clusterSettings.setURLLoadBalancing(false);
+                        else if (!ulb.equalsIgnoreCase("true"))
+                        {
+                            ConfigurationException e = new ConfigurationException();
+                            e.setMessage(10216, new Object[] {clusterName, ulb});
+                            throw e;
+                        }
+                    }
+                    ((ClientConfiguration)config).addClusterSettings(clusterSettings);
+                }
+            }
+        }
+    }
+
+    private void serviceInclude(Node serviceInclude)
+    {
+        // Validation
+        allowedAttributesOrElements(serviceInclude, SERVICE_INCLUDE_CHILDREN);
+
+        String src = getAttributeOrChildElement(serviceInclude, SRC_ATTR);
+        String dir = getAttributeOrChildElement(serviceInclude, DIRECTORY_ATTR);
+        if (src.length() > 0)
+        {
+            serviceIncludeFile(src);
+        }
+        else if (dir.length() > 0)
+        {
+            serviceIncludeDirectory(dir);
+        }
+        else
+        {
+            // The include element ''{0}'' must specify either the ''{1}'' or ''{2}'' attribute.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(MISSING_INCLUDE_ATTRIBUTES, new Object[]{serviceInclude.getNodeName(), SRC_ATTR, DIRECTORY_ATTR});
+            throw ex;
+        }
+    }
+
+    private void serviceIncludeFile(String src)
+    {
+        Document doc = loadDocument(src, fileResolver.getIncludedFile(src));
+        if (fileResolver instanceof LocalFileResolver)
+        {
+            LocalFileResolver local = (LocalFileResolver)fileResolver;
+            ((ClientConfiguration)config).addConfigPath(local.getIncludedPath(src), local.getIncludedLastModified(src));
+        }
+
+        doc.getDocumentElement().normalize();
+
+        // Check for multiple services defined in file.
+        Node servicesNode = selectSingleNode(doc, SERVICES_ELEMENT);
+        if (servicesNode != null)
+        {
+            allowedChildElements(servicesNode, SERVICES_CHILDREN);
+            NodeList services = selectNodeList(servicesNode, SERVICES_ELEMENT);
+            for (int a = 0; a < services.getLength(); a++)
+            {
+                Node service = services.item(a);
+                service(service);
+            }
+            fileResolver.popIncludedFile();
+        }
+        else // Check for single service in file.
+        {
+            Node service = selectSingleNode(doc, "/" + SERVICE_ELEMENT);
+            if (service != null)
+            {
+                service(service);
+                fileResolver.popIncludedFile();
+            }
+            else
+            {
+                // The {0} root element in file {1} must be ''{2}'' or ''{3}''.
+                ConfigurationException ex = new ConfigurationException();
+                ex.setMessage(INVALID_INCLUDE_ROOT, new Object[]{SERVICE_INCLUDE_ELEMENT, src, SERVICES_ELEMENT, SERVICE_ELEMENT});
+                throw ex;
+            }
+        }
+    }
+
+    private void serviceIncludeDirectory(String dir)
+    {
+        List files = fileResolver.getFiles(dir);
+        for (int i = 0; i < files.size(); i++)
+        {
+            String src = (String) files.get(i);
+            serviceIncludeFile(src);
+        }
+    }
+
+    private void service(Node service)
+    {
+        // Validation
+        requiredAttributesOrElements(service, SERVICE_REQ_CHILDREN);
+        allowedAttributesOrElements(service, SERVICE_CHILDREN);
+
+        String id = getAttributeOrChildElement(service, ID_ATTR);
+        if (isValidID(id))
+        {
+            ServiceSettings serviceSettings = config.getServiceSettings(id);
+            if (serviceSettings == null)
+            {
+                serviceSettings = new ServiceSettings(id);
+                // Service Properties
+                NodeList properties = selectNodeList(service, PROPERTIES_ELEMENT + "/*");
+                if (properties.getLength() > 0)
+                {
+                    ConfigMap map = properties(properties, getSourceFileOf(service));
+                    serviceSettings.addProperties(map);
+                }
+                config.addServiceSettings(serviceSettings);
+            }
+            else
+            {
+                // Duplicate service definition '{0}'.
+                ConfigurationException e = new ConfigurationException();
+                e.setMessage(DUPLICATE_SERVICE_ERROR, new Object[]{id});
+                throw e;
+            }
+
+            // Service Class Name
+            String className = getAttributeOrChildElement(service, CLASS_ATTR);
+            if (className.length() > 0)
+            {
+                serviceSettings.setClassName(className);
+            }
+            else
+            {
+                // Class not specified for {SERVICE_ELEMENT} '{id}'.
+                ConfigurationException ex = new ConfigurationException();
+                ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{SERVICE_ELEMENT, id});
+                throw ex;
+            }
+
+            //Service Message Types - deprecated
+
+            // Default Channels
+            Node defaultChannels = selectSingleNode(service, DEFAULT_CHANNELS_ELEMENT);
+            if (defaultChannels != null)
+            {
+                allowedChildElements(defaultChannels, DEFAULT_CHANNELS_CHILDREN);
+                NodeList channels = selectNodeList(defaultChannels, CHANNEL_ELEMENT);
+                for (int c = 0; c < channels.getLength(); c++)
+                {
+                    Node chan = channels.item(c);
+                    allowedAttributes(chan, new String[] {REF_ATTR});
+                    defaultChannel(chan, serviceSettings);
+                }
+            }
+            // Fall back on application's default channels
+            else if (config.getDefaultChannels().size() > 0)
+            {
+                for (Iterator iter = config.getDefaultChannels().iterator(); iter.hasNext();)
+                {
+                    String channelId = (String)iter.next();
+                    ChannelSettings channel = config.getChannelSettings(channelId);
+                    serviceSettings.addDefaultChannel(channel);
+                }
+            }
+
+            // Destinations
+            NodeList list = selectNodeList(service, DESTINATION_ELEMENT);
+            for (int i = 0; i < list.getLength(); i++)
+            {
+                Node dest = list.item(i);
+                destination(dest, serviceSettings);
+            }
+
+            // Destination Includes
+            list = selectNodeList(service, DESTINATION_INCLUDE_ELEMENT);
+            for (int i = 0; i < list.getLength(); i++)
+            {
+                Node dest = list.item(i);
+                destinationInclude(dest, serviceSettings);
+            }
+        }
+        else
+        {
+            //Invalid {SERVICE_ELEMENT} id '{id}'.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(INVALID_ID, new Object[]{SERVICE_ELEMENT, id});
+            throw ex;
+        }
+    }
+
+    /**
+     * Flex application can declare default channels for its services. If a
+     * service specifies its own list of channels it overrides these defaults.
+     * <p>
+     * &lt;default-channels&gt;<br />
+     * ;&lt;channel ref="channel-id" /&gt;<br />
+     * &lt;default-channels&gt;
+     * </p>
+     * @param chan the channel node
+     */
+    private void defaultChannel(Node chan)
+    {
+        String ref = getAttributeOrChildElement(chan, REF_ATTR);
+
+        if (ref.length() > 0)
+        {
+            ChannelSettings channel = config.getChannelSettings(ref);
+            if (channel != null)
+            {
+                config.addDefaultChannel(channel.getId());
+            }
+            else
+            {
+                // {0} not found for reference '{1}'
+                ConfigurationException e = new ConfigurationException();
+                e.setMessage(REF_NOT_FOUND, new Object[]{CHANNEL_ELEMENT, ref});
+                throw e;
+            }
+        }
+        else
+        {
+            //A default channel was specified without a reference for service '{0}'.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(INVALID_DEFAULT_CHANNEL, new Object[]{"MessageBroker"});
+            throw ex;
+        }
+    }
+
+    /**
+     * A service can declare default channels for its destinations. If a destination
+     * specifies its own list of channels it overrides these defaults.
+     * <p>
+     * &lt;default-channels&gt;<br />
+     * &lt;channel ref="channel-id" /&gt;<br />
+     * &lt;default-channels&gt;
+     * </p>
+     * @param chan the channel node
+     * @param serviceSettings service settings
+     */
+    private void defaultChannel(Node chan, ServiceSettings serviceSettings)
+    {
+        String ref = getAttributeOrChildElement(chan, REF_ATTR).trim();
+
+        if (ref.length() > 0)
+        {
+            ChannelSettings channel = config.getChannelSettings(ref);
+            if (channel != null)
+            {
+                serviceSettings.addDefaultChannel(channel);
+            }
+            else
+            {
+                // {0} not found for reference '{1}'
+                ConfigurationException e = new ConfigurationException();
+                e.setMessage(REF_NOT_FOUND, new Object[]{CHANNEL_ELEMENT, ref});
+                throw e;
+            }
+        }
+        else
+        {
+            //A default channel was specified without a reference for service '{0}'.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(INVALID_DEFAULT_CHANNEL, new Object[]{serviceSettings.getId()});
+            throw ex;
+        }
+    }
+
+    private void destinationInclude(Node destInclude, ServiceSettings serviceSettings)
+    {
+        // Validation
+        allowedAttributesOrElements(destInclude, DESTINATION_INCLUDE_CHILDREN);
+
+        String src = getAttributeOrChildElement(destInclude, SRC_ATTR);
+        String dir = getAttributeOrChildElement(destInclude, DIRECTORY_ATTR);
+        if (src.length() > 0)
+        {
+            destinationIncludeFile(serviceSettings, src);
+        }
+        else if (dir.length() > 0)
+        {
+            destinationIncludeDirectory(serviceSettings, dir);
+        }
+        else
+        {
+            // The include element ''{0}'' must specify either the ''{1}'' or ''{2}'' attribute.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(MISSING_INCLUDE_ATTRIBUTES, new Object[]{destInclude.getNodeName(), SRC_ATTR, DIRECTORY_ATTR});
+            throw ex;
+        }
+    }
+
+    private void destinationIncludeDirectory(ServiceSettings serviceSettings, String dir)
+    {
+        List files = fileResolver.getFiles(dir);
+        for (int i = 0; i < files.size(); i++)
+        {
+            String src = (String) files.get(i);
+            destinationIncludeFile(serviceSettings, src);
+        }
+    }
+
+    private void destinationIncludeFile(ServiceSettings serviceSettings, String src)
+    {
+        Document doc = loadDocument(src, fileResolver.getIncludedFile(src));
+        if (fileResolver instanceof LocalFileResolver)
+        {
+            LocalFileResolver local = (LocalFileResolver)fileResolver;
+            ((ClientConfiguration)config).addConfigPath(local.getIncludedPath(src), local.getIncludedLastModified(src));
+        }
+
+        doc.getDocumentElement().normalize();
+
+        // Check for multiple destination defined in file.
+        Node destinationsNode = selectSingleNode(doc, DESTINATIONS_ELEMENT);
+        if (destinationsNode != null)
+        {
+            allowedChildElements(destinationsNode, DESTINATIONS_CHILDREN);
+            NodeList destinations = selectNodeList(destinationsNode, DESTINATION_ELEMENT);
+            for (int a = 0; a < destinations.getLength(); a++)
+            {
+                Node dest = destinations.item(a);
+                destination(dest, serviceSettings);
+            }
+            fileResolver.popIncludedFile();
+        }
+        else // Check for single destination definition.
+        {
+            Node dest = selectSingleNode(doc, "/" + DESTINATION_ELEMENT);
+            if (dest != null)
+            {
+                destination(dest, serviceSettings);
+                fileResolver.popIncludedFile();
+            }
+            else
+            {
+                // The {0} root element in file {1} must be ''{2}'' or ''{3}''.
+                ConfigurationException ex = new ConfigurationException();
+                ex.setMessage(INVALID_INCLUDE_ROOT, new Object[]{DESTINATION_INCLUDE_ELEMENT, src, DESTINATIONS_ELEMENT, DESTINATION_ELEMENT});
+                throw ex;
+            }
+        }
+    }
+
+    private void destination(Node dest, ServiceSettings serviceSettings)
+    {
+        // Validation
+        requiredAttributesOrElements(dest, DESTINATION_REQ_CHILDREN);
+        allowedAttributes(dest, DESTINATION_ATTR);
+        allowedChildElements(dest, DESTINATION_CHILDREN);
+
+        String serviceId = serviceSettings.getId();
+
+        DestinationSettings destinationSettings;
+        String id = getAttributeOrChildElement(dest, ID_ATTR);
+        if (isValidID(id))
+        {
+            destinationSettings = (DestinationSettings)serviceSettings.getDestinationSettings().get(id);
+            if (destinationSettings != null)
+            {
+                // Duplicate destination definition '{id}' in service '{serviceId}'.
+                ConfigurationException e = new ConfigurationException();
+                e.setMessage(DUPLICATE_DESTINATION_ERROR, new Object[]{id, serviceId});
+                throw e;
+            }
+
+            destinationSettings = new DestinationSettings(id);
+            serviceSettings.addDestinationSettings(destinationSettings);
+        }
+        else
+        {
+            //Invalid {DESTINATION_ELEMENT} id '{id}' for service '{serviceId}'.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(INVALID_ID_IN_SERVICE, new Object[]{DESTINATION_ELEMENT, id, serviceId});
+            throw ex;
+        }
+
+        // Destination Properties
+        NodeList properties = selectNodeList(dest, PROPERTIES_ELEMENT + "/*");
+        if (properties.getLength() > 0)
+        {
+            ConfigMap map = properties(properties, getSourceFileOf(dest));
+            destinationSettings.addProperties(map);
+        }
+
+        // Channels
+        destinationChannels(dest, destinationSettings, serviceSettings);
+
+    }
+
+    private void destinationChannels(Node dest, DestinationSettings destinationSettings, ServiceSettings serviceSettings)
+    {
+        String destId = destinationSettings.getId();
+
+        // Channels attribute
+        String channelsList = evaluateExpression(dest, "@" + CHANNELS_ATTR).toString().trim();
+        if (channelsList.length() > 0)
+        {
+            StringTokenizer st = new StringTokenizer(channelsList, LIST_DELIMITERS);
+            while (st.hasMoreTokens())
+            {
+                String ref = st.nextToken().trim();
+                ChannelSettings channel = config.getChannelSettings(ref);
+                if (channel != null)
+                {
+                    destinationSettings.addChannelSettings(channel);
+                }
+                else
+                {
+                    // {CHANNEL_ELEMENT} not found for reference '{ref}' in destination '{destId}'.
+                    ConfigurationException ex = new ConfigurationException();
+                    ex.setMessage(REF_NOT_FOUND_IN_DEST, new Object[]{CHANNEL_ELEMENT, ref, destId});
+                    throw ex;
+                }
+            }
+        }
+        else
+        {
+            // Channels element
+            Node channelsNode = selectSingleNode(dest, CHANNELS_ELEMENT);
+            if (channelsNode != null)
+            {
+                allowedChildElements
+                    (channelsNode, DESTINATION_CHANNELS_CHILDREN);
+                NodeList channels = selectNodeList(channelsNode, CHANNEL_ELEMENT);
+                if (channels.getLength() > 0)
+                {
+                    for (int c = 0; c < channels.getLength(); c++)
+                    {
+                        Node chan = channels.item(c);
+
+                        // Validation
+                        requiredAttributesOrElements(chan, DESTINATION_CHANNEL_REQ_CHILDREN);
+
+                        String ref = getAttributeOrChildElement(chan, REF_ATTR).trim();
+                        if (ref.length() > 0)
+                        {
+                            ChannelSettings channel = config.getChannelSettings(ref);
+                            if (channel != null)
+                            {
+                                destinationSettings.addChannelSettings(channel);
+                            }
+                            else
+                            {
+                                // {CHANNEL_ELEMENT} not found for reference '{ref}' in destination '{destId}'.
+                                ConfigurationException ex = new ConfigurationException();
+                                ex.setMessage(REF_NOT_FOUND_IN_DEST, new Object[]{CHANNEL_ELEMENT, ref, destId});
+                                throw ex;
+                            }
+                        }
+                        else
+                        {
+                            //Invalid {0} ref '{1}' in destination '{2}'.
+                            ConfigurationException ex = new ConfigurationException();
+                            ex.setMessage(INVALID_REF_IN_DEST, new Object[]{CHANNEL_ELEMENT, ref, destId});
+                            throw ex;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // Finally, we fall back to the service's default channels
+                List defaultChannels = serviceSettings.getDefaultChannels();
+                Iterator it = defaultChannels.iterator();
+                while (it.hasNext())
+                {
+                    ChannelSettings channel = (ChannelSettings)it.next();
+                    destinationSettings.addChannelSettings(channel);
+                }
+            }
+        }
+
+        if (destinationSettings.getChannelSettings().size() <= 0)
+        {
+            // Destination '{id}' must specify at least one channel.
+            ConfigurationException ex = new ConfigurationException();
+            ex.setMessage(DEST_NEEDS_CHANNEL, new Object[]{destId});
+            throw ex;
+        }
+    }
+
+    private void flexClient(Node root)
+    {
+        Node flexClient = selectSingleNode(root, FLEX_CLIENT_ELEMENT);
+        if (flexClient != null)
+        {
+            FlexClientSettings flexClientSettings = new FlexClientSettings();
+            // Reliable reconnect duration millis
+            String reliableReconnectDurationMillis = getAttributeOrChildElement(flexClient, FLEX_CLIENT_RELIABLE_RECONNECT_DURATION_MILLIS);
+            if (reliableReconnectDurationMillis.length() > 0)
+            {
+                try
+                {
+                    int millis = Integer.parseInt(reliableReconnectDurationMillis);
+                    if (millis < 0)
+                    {
+                        ConfigurationException e = new ConfigurationException();
+                        e.setMessage(INVALID_FLEX_CLIENT_RELIABLE_RECONNECT_DURATION_MILLIS, new Object[]{reliableReconnectDurationMillis});
+                        throw e;
+                    }
+                    flexClientSettings.setReliableReconnectDurationMillis(millis);
+                }
+                catch (NumberFormatException nfe)
+                {
+                    ConfigurationException e = new ConfigurationException();
+                    e.setMessage(INVALID_FLEX_CLIENT_RELIABLE_RECONNECT_DURATION_MILLIS, new Object[]{reliableReconnectDurationMillis});
+                    throw e;
+                }
+            }
+            else
+            {
+                flexClientSettings.setReliableReconnectDurationMillis(0); // Default is 0.
+            }
+            // heartbeat interval millis
+            String heartbeatIntervalMillis = getAttributeOrChildElement(flexClient, FLEX_CLIENT_HEARTBEAT_INTERVAL_MILLIS);
+            if (heartbeatIntervalMillis.length() > 0)
+            {
+                try
+                {
+                    int millis = Integer.parseInt(heartbeatIntervalMillis);
+                    if (millis < 0)
+                    {
+                        ConfigurationException e = new ConfigurationException();
+                        e.setMessage(INVALID_FLEX_CLIENT_HEARTBEAT_INTERVAL_MILLIS, new Object[] {heartbeatIntervalMillis});
+                        throw e;
+                    }
+                    flexClientSettings.setHeartbeatIntervalMillis(millis);
+                }
+                catch (NumberFormatException nfe)
+                {
+                    ConfigurationException e = new ConfigurationException();
+                    e.setMessage(INVALID_FLEX_CLIENT_HEARTBEAT_INTERVAL_MILLIS, new Object[] {heartbeatIntervalMillis});
+                    throw e;
+                }
+            }
+            ((ClientConfiguration)config).setFlexClientSettings(flexClientSettings);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ClusterSettings.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ClusterSettings.java b/common/src/main/java/flex/messaging/config/ClusterSettings.java
new file mode 100644
index 0000000..beb64fd
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ClusterSettings.java
@@ -0,0 +1,152 @@
+/*
+ * 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.config;
+
+/**
+ *
+ */
+public class ClusterSettings extends PropertiesSettings
+{
+    public static final String CLUSTER_ELEMENT = "cluster";
+    public static final String REF_ATTR = "ref";
+    public static final String SHARED_BACKEND_ATTR = "shared-backend";
+    public static final String DEFAULT_ELEMENT = "default";
+    public static final String URL_LOAD_BALANCING = "url-load-balancing";
+    public static final String IMPLEMENTATION_CLASS = "class";
+
+    public static final String JGROUPS_CLUSTER = "flex.messaging.cluster.JGroupsCluster";
+
+    private String clusterName;
+    private String propsFileName;
+    private String implementationClass;
+    private boolean def;
+    private boolean urlLoadBalancing;
+
+    /**
+     * Creates a new <code>ClusterSettings</code> with default settings.
+     */
+    public ClusterSettings()
+    {
+        def = false;
+        urlLoadBalancing = true;
+        implementationClass = JGROUPS_CLUSTER;
+    }
+
+    /**
+     * Returns the name of the cluster.
+     *
+     * @return The name of the cluster.
+     */
+    public String getClusterName()
+    {
+        return clusterName;
+    }
+
+    /**
+     * Sets the name of the cluster.
+     *
+     * @param clusterName The name of the cluster.
+     */
+    public void setClusterName(String clusterName)
+    {
+        this.clusterName = clusterName;
+    }
+
+    /**
+     * Returns whether the cluster is default or not.
+     *
+     * @return <code>true</code> is the cluster is default; otherwise <code>false</code>.
+     */
+    public boolean isDefault()
+    {
+        return def;
+    }
+
+    /**
+     * Sets whether the cluster is default or not.
+     *
+     * @param def <code>true</code> is the cluster is default; otherwise <code>false</code>.
+     */
+    public void setDefault(boolean def)
+    {
+        this.def = def;
+    }
+
+    /**
+     * Returns the properties file of the cluster.
+     *
+     * @return The properties file of the cluster.
+     */
+    public String getPropsFileName()
+    {
+        return propsFileName;
+    }
+
+    /**
+     * Sets the properties file of the cluster.
+     *
+     * @param propsFileName The properties file of the cluster.
+     */
+    public void setPropsFileName(String propsFileName)
+    {
+        this.propsFileName = propsFileName;
+    }
+
+    /**
+     * Returns whether url load balancing is enabled or not.
+     *
+     * @return <code>true</code> if the url load balancing is enabled; otherwise <code>false</code>.
+     */
+    public boolean getURLLoadBalancing()
+    {
+        return urlLoadBalancing;
+    }
+
+    /**
+     * Sets whether url load balancing is enabled or not.
+     *
+     * @param ulb <code>true</code> if the url load balancing is enabled; otherwise <code>false</code>.
+     */
+    public void setURLLoadBalancing(boolean ulb)
+    {
+        urlLoadBalancing = ulb;
+    }
+
+    /**
+     * Sets the name of the cluster implementation class.
+     * The default is 'flex.messaging.cluster.JGroupsCluster'.
+     *
+     * @param className name of the cluster implementation class
+     *
+     */
+    public void setImplementationClass(String className)
+    {
+        this.implementationClass = className;
+    }
+
+    /**
+     * Get the name of the cluster implementation class.
+     * The class must support the flex.messaging.cluster.Cluster interface.
+     *
+     * @return The implementation class name.
+     *
+     */
+    public String getImplementationClass()
+    {
+        return implementationClass;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ConfigMap.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ConfigMap.java b/common/src/main/java/flex/messaging/config/ConfigMap.java
new file mode 100644
index 0000000..c2bd780
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ConfigMap.java
@@ -0,0 +1,469 @@
+/*
+ * 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.config;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The ConfigMap class is a helper implementation of Map that makes it easier
+ * to handle properties that can appear one or more times. If a property is set
+ * more than once, it is converted to a List and added as another property
+ * rather than replacing the existing property. It also provides utility APIs
+ * for getting properties from the Map, cast to a certain type and allows a
+ * default to be specified in the event that the property is missing.
+ */
+public class ConfigMap extends LinkedHashMap
+{
+    /**
+     * This number was generated using the 'serialver' command line tool.
+     * This number should remain consistent with the version used by
+     * ColdFusion to communicate with the message broker over RMI.
+     */
+    private static final long serialVersionUID = 8913604659150919550L;
+
+    /**
+     * This error is thrown when a property unexpectedly contains multiple values.
+     */
+    private static final int UNEXPECTED_MULTIPLE_VALUES = 10169;
+
+    /**
+     * An *undocumented* system property can be used to revert to legacy config property handling:
+     *   Legacy behavior - config property values were not trimmed, retaining leading/trailing whitespace which
+     *                     proved problematic for customers.
+     *   New default behavior - config property values are trimmed.
+     */
+    private static final String SYSPROPNAME_TRIM_CONFIG_PROPERTY_VALUES = "flex.trim-config-property-values";    
+    private static final boolean TRIM_CONFIG_PROPERTY_VALUES = Boolean.valueOf(System.getProperty(SYSPROPNAME_TRIM_CONFIG_PROPERTY_VALUES, "true")).booleanValue();
+    
+    /**
+     * Map to keep track of accessed properties.
+     */
+    private HashSet accessedKeys = new HashSet();
+
+    /**
+     * Constructs an empty <code>ConfigMap</code> with the default initial
+     * capacity of 10.
+     */
+    public ConfigMap()
+    {
+        super();
+    }
+
+    /**
+     * Constructs a new <code>ConfigMap</code> with the initial
+     * capacity specified.
+     *
+     * @param  initialCapacity the initial capacity.
+     */
+    public ConfigMap(int initialCapacity)
+    {
+        super(initialCapacity);
+    }
+
+    /**
+     * Constructs a new <code>ConfigMap</code> and copies the values
+     * from the supplied map to this map.
+     *
+     * @param m a <code>ConfigMap</code> whose properties are to be added to
+     * this <code>ConfigMap</code>.
+     */
+    public ConfigMap(ConfigMap m)
+    {
+        this();
+        addProperties(m);
+    }
+
+    /**
+     * Adds all properties from a map to this map.
+     *
+     * @param p a <code>ConfigMap</code> whose properties are to be added to
+     * this <code>ConfigMap</code>.
+     */
+    public void addProperties(ConfigMap p)
+    {
+        Iterator it = p.entrySet().iterator();
+        while (it.hasNext())
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            if (value instanceof ValueList)
+            {
+                addProperties(key, (ValueList) value);
+            }
+            else
+            {
+                addPropertyLogic(key, value);
+            }
+        }
+    }
+
+    /**
+     * Helper method to add a list of values under a key.
+     *
+     * @param key The key to add the values under.
+     * @param values The list of values to add.
+     */
+    private void addProperties(Object key, ValueList values)
+    {
+        ValueList list = getValueList(key);
+        if (list == null)
+        {
+            put(key, values.clone());
+        }
+        else
+        {
+            list.addAll(values);
+        }
+    }
+
+    /**
+     * Helper method to add a value under a key.
+     *
+     * @param key The key to add the value under.
+     * @param value The value to add.
+     */
+    private void addPropertyLogic(Object key, Object value)
+    {
+        ValueList list = getValueList(key);
+        if (list == null)
+        {
+            put(key, value);
+        }
+        else
+        {
+            list.add(value);
+        }
+    }
+
+    private static class ValueList extends ArrayList
+    {
+        /**
+         * Serial version id.
+         */
+        static final long serialVersionUID = -5637755312744414675L;
+    }
+
+    /**
+     * Given a key, returns a list of values associated with that key.
+     *
+     * @param key The key.
+     * @return A list of values associated with the key.
+     */
+    private ValueList getValueList(Object key)
+    {
+        ValueList list;
+        Object old = super.get(key);
+        if (old instanceof ValueList)
+        {
+            list = (ValueList) old;
+        }
+        else if (old != null)
+        {
+            list = new ValueList();
+            list.add(old);
+            put(key, list);
+        }
+        else
+        {
+            list = null;
+        }
+        return list;
+    }
+
+    /**
+     * Adds a <code>String</code> value to this map for the given property
+     * name.
+     *
+     * @param name  the property name
+     * @param value the property value
+     */
+    public void addProperty(String name, String value)
+    {
+        addPropertyLogic(name, TRIM_CONFIG_PROPERTY_VALUES && value != null ? value.trim() : value);
+    }
+
+    /**
+     * Adds a <code>ConfigMap</code> value to this map for the given property
+     * name.
+     *
+     * @param name  the property name
+     * @param value the property value
+     */
+    public void addProperty(String name, ConfigMap value)
+    {
+        addPropertyLogic(name, value);
+    }
+
+    /**
+     * Gets the set of property names contained in this map.
+     *
+     * @return a <code>Set</code> of property name <code>String</code>s.
+     */
+    public Set propertyNames()
+    {
+        return keySet();
+    }
+
+    /**
+     * Sets a property name as allowed without needing to access the property
+     * value. This marks a property as allowed for validation purposes.
+     *
+     * @param name  the property name to allow
+     */
+    public void allowProperty(String name)
+    {
+        accessedKeys.add(name);
+    }
+
+    /**
+     * Gets the value for the given property name. Also records that this
+     * property was accessed.
+     *
+     * @param name  the property name
+     * @return the value for the property, or null if property does not exist
+     * in this map.
+     */
+    public Object get(Object name)
+    {
+        accessedKeys.add(name);
+        return super.get(name);
+    }
+
+    /**
+     * Helper method to get the property with the specified name as a string if possible.
+     *
+     * @param name The property name.
+     * @return The property object.
+     */
+    private Object getSinglePropertyOrFail(Object name)
+    {
+        Object result = get(name);
+        if (result instanceof ValueList)
+        {
+            ConfigurationException exception = new ConfigurationException();
+            exception.setMessage
+                (UNEXPECTED_MULTIPLE_VALUES, new Object[] {name});
+            throw exception;
+        }
+        return result;
+    }
+
+    /**
+     * Gets the property with the specified name as a string if possible.
+     *
+     * @param name The property name.
+     * @return The property name.
+     */
+    public String getProperty(String name)
+    {
+        return getPropertyAsString(name, null);
+    }
+
+    /**
+     * Gets the property with the specified name as a ConfigMap if possible,
+     * or returns the default value if the property is undefined.
+     *
+     * @param name the property name
+     * @param defaultValue the default value
+     * @return ConfigMap the ConfigMap object of the property
+     */
+    public ConfigMap getPropertyAsMap(String name, ConfigMap defaultValue)
+    {
+        Object prop = getSinglePropertyOrFail(name);
+        if (prop instanceof ConfigMap)
+        {
+            return (ConfigMap)prop;
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the property with the specified name as a String if possible,
+     * or returns the default value if the property is undefined.
+     *
+     * @param name the property name
+     * @param defaultValue the default value
+     * @return String the String value of the property
+     */
+    public String getPropertyAsString(String name, String defaultValue)
+    {
+        Object prop = getSinglePropertyOrFail(name);
+        if (prop instanceof String)
+        {
+            return (String)prop;
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets a property (or set of properties) as a List. If only one
+     * property exists it is added as the only entry to a new List.
+     *
+     * @param name  the property name
+     * @param defaultValue  the value to return if the property is not found
+     * @return the value for the property as a List if it exists in this map,
+     * otherwise the defaultValue is returned.
+     */
+    public List getPropertyAsList(String name, List defaultValue)
+    {
+        Object prop = get(name);
+        if (prop != null)
+        {
+            if (prop instanceof List)
+            {
+                return (List) prop;
+            }
+            else
+            {
+                List list = new ArrayList();
+                list.add(prop);
+                return list;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the property with the specified name as a boolean if possible,
+     * or returns the default value if the property is undefined.
+     *
+     * @param name the property name
+     * @param defaultValue the default value
+     * @return boolean the boolean value of the property
+     */
+    public boolean getPropertyAsBoolean(String name, boolean defaultValue)
+    {
+        Object prop = getSinglePropertyOrFail(name);
+        if (prop instanceof String)
+        {
+            return Boolean.valueOf((String)prop).booleanValue();
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the property with the specified name as an int if possible,
+     * or returns the default value if the property is undefined.
+     *
+     * @param name the property name
+     * @param defaultValue the default value
+     * @return int the int value of the property
+     */
+    public int getPropertyAsInt(String name, int defaultValue)
+    {
+        Object prop = getSinglePropertyOrFail(name);
+        if (prop instanceof String)
+        {
+            try
+            {
+                return Integer.parseInt((String)prop);
+            }
+            catch (NumberFormatException ex)
+            {
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the property with the specified name as a long if possible,
+     * or returns the default value if the property is undefined.
+     *
+     * @param name the property name
+     * @param defaultValue the default value
+     * @return long the long value of the property
+     */
+    public long getPropertyAsLong(String name, long defaultValue)
+    {
+        Object prop = getSinglePropertyOrFail(name);
+        if (prop instanceof String)
+        {
+            try
+            {
+                return Long.parseLong((String)prop);
+            }
+            catch (NumberFormatException ex)
+            {
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Returns a list of qualified property names that have not been accessed
+     * by one of the get*() methods.
+     *
+     * @return List a list of unused properties
+     */
+    public List findAllUnusedProperties()
+    {
+        List result = new ArrayList();
+        findUnusedProperties("", true, result);
+        return result;
+    }
+
+    /**
+     * Gathers a collection of properties that exist in the map but have not
+     * been explicitly accessed nor marked as allowed. This list is helpful
+     * in validating a set of properties as one can detect those that are
+     * unknown or unexpected.
+     *
+     * @param parentPath Used to track the depth of property in a potential
+     * hierarchy of <code>ConfigMap</code>s.
+     * @param recurse Whether sub maps should be recursively searched.
+     * @param result the collection of unused properties in this map.
+     */
+    public void findUnusedProperties
+        (String parentPath, boolean recurse, Collection result)
+    {
+        Iterator itr = entrySet().iterator();
+        while (itr.hasNext())
+        {
+            Map.Entry entry = (Map.Entry) itr.next();
+            Object key = entry.getKey();
+            String currentPath = parentPath + '/' + String.valueOf(key);
+            if (!accessedKeys.contains(key))
+            {
+                result.add(currentPath);
+            }
+            else if (recurse)
+            {
+                Object value = entry.getValue();
+                List values = value instanceof List ?
+                              (List) value : Collections.singletonList(value);
+                for (int i = 0; i < values.size(); i++)
+                {
+                    Object child = values.get(i);
+                    if (child instanceof ConfigMap)
+                    {
+                        ((ConfigMap) child).findUnusedProperties
+                            (currentPath, recurse, result);
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ConfigurationConstants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ConfigurationConstants.java b/common/src/main/java/flex/messaging/config/ConfigurationConstants.java
new file mode 100644
index 0000000..35fcf34
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ConfigurationConstants.java
@@ -0,0 +1,467 @@
+/*
+ * 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.config;
+
+/**
+ *
+ */
+public interface ConfigurationConstants
+{
+    String CONTEXT_PATH_TOKEN = "{context.root}";
+    String CONTEXT_PATH_ALT_TOKEN = "{context-root}";
+    String SLASH_CONTEXT_PATH_TOKEN = "/{context.root}";
+    String EMPTY_STRING = "";
+    String TRUE_STRING = "true";
+    String FALSE_STRING = "false";
+    String SERVER_NAME_TOKEN = "{server.name}";
+    String SERVER_PORT_TOKEN = "{server.port}";
+
+    // ELEMENTS
+
+    // Top Level
+    String SERVICES_CONFIG_ELEMENT = "services-config";
+
+    // Services
+    String SERVICES_ELEMENT = "services";
+    String SERVICE_ELEMENT = "service";
+    String SERVICE_INCLUDE_ELEMENT = "service-include";
+
+    String SRC_ATTR = "file-path";
+    String DIRECTORY_ATTR = "directory-path";
+    String ID_ATTR = "id";
+    String CLASS_ATTR = "class";
+    String PER_CLIENT_AUTH="per-client-authentication";
+    String MESSAGE_TYPES_ATTR = "messageTypes";
+
+    String PROPERTIES_ELEMENT = "properties";
+
+    String METADATA_ELEMENT = "metadata";
+
+    String ADAPTERS_ELEMENT = "adapters";
+    String ADAPTER_DEFINITION_ELEMENT = "adapter-definition";
+    String ADAPTER_INCLUDE_ELEMENT = "adapter-include";
+    String DEFAULT_ATTR = "default";
+
+    String DEFAULT_CHANNELS_ELEMENT = "default-channels";
+    String CHANNEL_ELEMENT = "channel";
+    String REF_ATTR = "ref";
+
+    String DEFAULT_SECURITY_CONSTRAINT_ELEMENT = "default-security-constraint";
+
+    String DESTINATION_ELEMENT = "destination";
+    String DESTINATIONS_ELEMENT = "destinations";
+    String DESTINATION_INCLUDE_ELEMENT = "destination-include";
+    String ADAPTER_ELEMENT = "adapter";
+    String ADAPTER_ATTR = "adapter";
+    String CHANNELS_ATTR = "channels";
+    String SECURITY_CONSTRAINT_ELEMENT = "security-constraint";
+    String SECURITY_CONSTRAINT_ATTR = "security-constraint";
+    String SECURITY_CONSTRAINTS_ELEMENT = "security-constraints";  // for includes only
+
+    // Security
+    String SECURITY_ELEMENT = "security";
+    String SECURITY_CONSTRAINT_DEFINITION_ELEMENT = "security-constraint";
+    String CONSTRAINT_INCLUDE_ELEMENT = "constraint-include";
+    String AUTH_METHOD_ELEMENT = "auth-method";
+    String ROLES_ELEMENT = "roles";
+    String ROLE_ELEMENT = "role";
+    String LOGIN_COMMAND_ELEMENT = "login-command";
+    String SERVER_ATTR = "server";
+    String RECREATE_HTTPSESSION_AFTER_LOGIN_ELEMENT = "recreate-httpsession-after-login";
+
+    // SocketServers
+    String SERVERS_ELEMENT = "servers";
+    String SERVER_ELEMENT = "server";
+    String IP_ADDRESS_PATTERN = "ip-address-pattern";
+
+    // Channels
+    String CHANNELS_ELEMENT = "channels";
+    String CHANNEL_DEFINITION_ELEMENT = "channel-definition";
+    String CHANNEL_INCLUDE_ELEMENT = "channel-include";
+    String REMOTE_ATTR = "remote";
+    String SERVER_ONLY_ATTR = "server-only";
+    String ENDPOINT_ELEMENT = "endpoint";
+    // Deprecated, use URL_ATTR instead.
+    String URI_ATTR = "uri";
+    String URL_ATTR = "url";
+    String POLLING_ENABLED_ELEMENT = "polling-enabled";
+    String POLLING_INTERVAL_MILLIS_ELEMENT = "polling-interval-millis";
+    String PIGGYBACKING_ENABLED_ELEMENT = "piggybacking-enabled";
+    String LOGIN_AFTER_DISCONNECT_ELEMENT = "login-after-disconnect";
+    String RECORD_MESSAGE_SIZES_ELEMENT = "record-message-sizes";
+    String RECORD_MESSAGE_TIMES_ELEMENT = "record-message-times";
+    String SERIALIZATION_ELEMENT = "serialization";
+    String ENABLE_SMALL_MESSAGES_ELEMENT = "enable-small-messages";
+    // Deprecated, use POLLING_INTERVAL_MILLIS_ELEMENT instead.
+    String POLLING_INTERVAL_SECONDS_ELEMENT = "polling-interval-seconds";
+    String CONNECT_TIMEOUT_SECONDS_ELEMENT = "connect-timeout-seconds";
+    String CLIENT_LOAD_BALANCING_ELEMENT = "client-load-balancing";
+    String REQUEST_TIMEOUT_SECONDS_ELEMENT = "request-timeout-seconds";
+
+    // Clusters
+    String CLUSTERS_ELEMENT = "clusters";
+    String CLUSTER_DEFINITION_ELEMENT = "cluster";
+    String CLUSTER_PROPERTIES_ATTR = "properties";
+
+    // Logging
+    String LOGGING_ELEMENT = "logging";
+    String TARGET_ELEMENT = "target";
+    String FILTERS_ELEMENT = "filters";
+    String PATTERN_ELEMENT = "pattern";
+    String LEVEL_ATTR = "level";
+
+    // System
+    String SYSTEM_ELEMENT = "system";
+    String ENFORCE_ENDOINT_VALIDATION ="enforce-endpoint-validation";
+    String LOCALE_ELEMENT = "locale";
+    String MANAGEABLE_ELEMENT = "manageable";
+    String DEFAULT_LOCALE_ELEMENT = "default-locale";
+    String REDEPLOY_ELEMENT = "redeploy";
+    String ENABLED_ELEMENT = "enabled";
+    String WATCH_INTERVAL_ELEMENT = "watch-interval";
+    String WATCH_FILE_ELEMENT = "watch-file";
+    String TOUCH_FILE_ELEMENT = "touch-file";
+    String FACTORIES_ELEMENT = "factories";
+    String FACTORY_ELEMENT = "factory";
+    String UUID_GENERATOR_ELEMENT = "uuid-generator";
+    String DOTNET_FRAMEWORK_VERSION = "dotnet-framework-version";
+
+    // FlexClient
+    String FLEX_CLIENT_ELEMENT = "flex-client";
+    String FLEX_CLIENT_TIMEOUT_MINUTES_ELEMENT = "timeout-minutes";
+    String FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_ELEMENT = "flex-client-outbound-queue-processor";
+    String ADAPTIVE_FREQUENCY = "adaptive-frequency";
+    String FLEX_CLIENT_RELIABLE_RECONNECT_DURATION_MILLIS = "reliable-reconnect-duration-millis";
+    String FLEX_CLIENT_HEARTBEAT_INTERVAL_MILLIS = "heartbeat-interval-millis";
+
+    // Message filters
+    String ASYNC_MESSAGE_FILTERS_ELEMENT = "async-message-filters";
+    String SYNC_MESSAGE_FILTERS_ELEMENT = "sync-message-filters";
+    String FILTER_ELEMENT = "filter";
+
+    // Validators
+    String VALIDATORS_ELEMENT = "validators";
+    String VALIDATOR_ELEMENT = "validator";
+    String TYPE_ATTR = "type";
+
+    // CHILD ELEMENTS
+
+    // Top Level
+    String[] SERVICES_CONFIG_CHILDREN = {
+        SERVICES_ELEMENT, SECURITY_ELEMENT, SERVERS_ELEMENT, CHANNELS_ELEMENT, LOGGING_ELEMENT,
+        SYSTEM_ELEMENT, CLUSTERS_ELEMENT, FACTORIES_ELEMENT, FLEX_CLIENT_ELEMENT,
+        ASYNC_MESSAGE_FILTERS_ELEMENT, SYNC_MESSAGE_FILTERS_ELEMENT, VALIDATORS_ELEMENT
+    };
+
+    // Services
+    String[] SERVICES_CHILDREN = {
+        SERVICE_ELEMENT, SERVICE_INCLUDE_ELEMENT, DEFAULT_CHANNELS_ELEMENT
+    };
+
+    String[] SERVICE_INCLUDE_CHILDREN = {
+        SRC_ATTR, DIRECTORY_ATTR
+    };
+
+    String[] SERVICE_CHILDREN = {
+        ID_ATTR, CLASS_ATTR, MESSAGE_TYPES_ATTR, PROPERTIES_ELEMENT,
+        ADAPTERS_ELEMENT, DEFAULT_CHANNELS_ELEMENT, DEFAULT_SECURITY_CONSTRAINT_ELEMENT,
+        DESTINATION_INCLUDE_ELEMENT, DESTINATION_ELEMENT
+    };
+
+    String[] SERVICE_REQ_CHILDREN = {
+        ID_ATTR, CLASS_ATTR
+    };
+
+    String[] ADAPTER_DEFINITION_CHILDREN = {
+        ID_ATTR, CLASS_ATTR, DEFAULT_ATTR, PROPERTIES_ELEMENT
+    };
+
+    String[] ADAPTER_DEFINITION_REQ_CHILDREN = {
+        ID_ATTR, CLASS_ATTR
+    };
+
+    String[] DESTINATION_INCLUDE_CHILDREN = {
+        SRC_ATTR, DIRECTORY_ATTR
+    };
+
+    String[] ADAPTERS_CHILDREN = {
+        ADAPTER_DEFINITION_ELEMENT, ADAPTER_INCLUDE_ELEMENT
+    };
+
+    String[] ADAPTER_INCLUDE_CHILDREN = {
+        SRC_ATTR, DIRECTORY_ATTR
+    };
+
+    String[] DEFAULT_CHANNELS_CHILDREN = {
+        CHANNEL_ELEMENT
+    };
+
+    String[] FLEX_CLIENT_CHILDREN = {
+        FLEX_CLIENT_TIMEOUT_MINUTES_ELEMENT, FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_ELEMENT,
+        ADAPTIVE_FREQUENCY, FLEX_CLIENT_RELIABLE_RECONNECT_DURATION_MILLIS, FLEX_CLIENT_HEARTBEAT_INTERVAL_MILLIS
+    };
+
+    String[] FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_REQ_CHILDREN = {
+        CLASS_ATTR
+    };
+
+    // Security
+    String[] SECURITY_CHILDREN = {
+        SECURITY_CONSTRAINT_DEFINITION_ELEMENT, LOGIN_COMMAND_ELEMENT, RECREATE_HTTPSESSION_AFTER_LOGIN_ELEMENT,
+        CONSTRAINT_INCLUDE_ELEMENT
+    };
+
+    String[] EMBEDDED_SECURITY_CHILDREN = {
+        SECURITY_CONSTRAINT_DEFINITION_ELEMENT
+    };
+
+    String[] SECURITY_CONSTRAINT_DEFINITION_CHILDREN = {
+        REF_ATTR, ID_ATTR, AUTH_METHOD_ELEMENT, ROLES_ELEMENT
+    };
+
+    String[] ROLES_CHILDREN = {
+        ROLE_ELEMENT
+    };
+
+    String[] LOGIN_COMMAND_CHILDREN = {
+        SERVER_ATTR, CLASS_ATTR, PER_CLIENT_AUTH
+    };
+
+    String[] LOGIN_COMMAND_REQ_CHILDREN = {
+        SERVER_ATTR, CLASS_ATTR
+    };
+
+    String[] SECURITY_CONSTRAINTS_CHILDREN = {
+        SECURITY_CONSTRAINT_ELEMENT
+    };
+
+    String[] CONSTRAINT_INCLUDE_CHILDREN = {
+        SRC_ATTR, DIRECTORY_ATTR
+    };
+
+    // Servers
+    String[] SERVERS_CHILDREN = {SERVER_ELEMENT};
+
+    String[] SERVER_REQ_CHILDREN = {
+        ID_ATTR, CLASS_ATTR
+    };
+
+    String [] SERVER_CHILDREN = {
+        ID_ATTR, CLASS_ATTR, PROPERTIES_ELEMENT
+    };
+
+    // Channels
+    String[] CHANNELS_CHILDREN = {
+        CHANNEL_DEFINITION_ELEMENT, CHANNEL_INCLUDE_ELEMENT
+    };
+
+    String[] CHANNEL_DEFINITION_REQ_CHILDREN = {
+        ENDPOINT_ELEMENT, ID_ATTR
+    };
+
+    String[] CHANNEL_DEFINITION_CHILDREN = {
+        ENDPOINT_ELEMENT, PROPERTIES_ELEMENT, SECURITY_ELEMENT, SERVER_ELEMENT,
+        SECURITY_CONSTRAINT_ATTR, CLASS_ATTR, ID_ATTR, REMOTE_ATTR, SERVER_ONLY_ATTR
+    };
+
+    String[] CHANNEL_DEFINITION_SERVER_REQ_CHILDREN = {
+        REF_ATTR
+    };
+
+    String[] CHANNEL_INCLUDE_CHILDREN = {
+        SRC_ATTR, DIRECTORY_ATTR
+    };
+
+    String[] ENDPOINT_CHILDREN = {
+        URI_ATTR, URL_ATTR, CLASS_ATTR
+    };
+
+    String[] DESTINATION_REQ_CHILDREN = {
+        ID_ATTR
+    };
+
+    String[] DESTINATION_CHILDREN = {
+        ID_ATTR, PROPERTIES_ELEMENT, CHANNELS_ELEMENT, SECURITY_ELEMENT, ADAPTER_ELEMENT,
+        CHANNELS_ATTR, ADAPTER_ATTR, SECURITY_CONSTRAINT_ATTR
+    };
+
+    String[] DESTINATIONS_CHILDREN = {
+        DESTINATION_ELEMENT
+    };
+
+    String[] DESTINATION_ATTR = {
+            ID_ATTR, PROPERTIES_ELEMENT, CHANNELS_ELEMENT, ADAPTER_ELEMENT,
+            CHANNELS_ATTR, ADAPTER_ATTR, SECURITY_CONSTRAINT_ATTR
+    };
+
+    String[] DESTINATION_CHANNEL_REQ_CHILDREN = {
+        REF_ATTR
+    };
+
+    String[] DESTINATION_CHANNELS_CHILDREN = {
+        CHANNEL_ELEMENT
+    };
+
+    String[] DESTINATION_ADAPTER_CHILDREN = {
+        REF_ATTR
+    };
+
+    // Clustering
+    String[] CLUSTERING_CHILDREN = {
+        CLUSTER_DEFINITION_ELEMENT
+    };
+
+    String[] CLUSTER_DEFINITION_CHILDREN = {
+        ID_ATTR, CLUSTER_PROPERTIES_ATTR
+    };
+
+    // Logging
+
+    String[] LOGGING_CHILDREN = {
+        PROPERTIES_ELEMENT, LEVEL_ATTR, TARGET_ELEMENT,
+    };
+
+    String[] TARGET_CHILDREN = {
+        CLASS_ATTR, LEVEL_ATTR, PROPERTIES_ELEMENT, FILTERS_ELEMENT
+    };
+
+    String[] TARGET_REQ_CHILDREN = {
+        CLASS_ATTR
+    };
+
+    String[] FILTERS_CHILDREN = {
+        PATTERN_ELEMENT
+    };
+
+    // System
+
+    String[] SYSTEM_CHILDREN = {
+        LOCALE_ELEMENT, ENFORCE_ENDOINT_VALIDATION, REDEPLOY_ELEMENT, MANAGEABLE_ELEMENT, UUID_GENERATOR_ELEMENT, DOTNET_FRAMEWORK_VERSION
+    };
+
+    String[] REDEPLOY_CHILDREN = {
+        ENABLED_ELEMENT, WATCH_INTERVAL_ELEMENT, WATCH_FILE_ELEMENT, TOUCH_FILE_ELEMENT
+    };
+
+    String[] LOCALE_CHILDREN = {
+        DEFAULT_LOCALE_ELEMENT
+    };
+
+    // Factories
+    String[] FACTORIES_CHILDREN = {
+        FACTORY_ELEMENT
+    };
+
+    String[] FACTORY_REQ_CHILDREN = {
+        ID_ATTR, CLASS_ATTR
+    };
+
+    // Message filters
+    String[] ASYNC_MESSAGE_FILTERS_ELEMENT_CHILDREN = {
+        FILTER_ELEMENT
+    };
+
+    String[] SYNC_MESSAGE_FILTERS_ELEMENT_CHILDREN = {
+        FILTER_ELEMENT
+    };
+
+    String[] FILTER_CHILDREN = {
+        ID_ATTR, CLASS_ATTR, PROPERTIES_ELEMENT
+    };
+
+    String[] FILTER_REQ_CHILDREN = {
+        ID_ATTR, CLASS_ATTR
+    };
+
+    // UUID Generator
+    String[] UUID_GENERATOR_REQ_CHILDREN = {
+            CLASS_ATTR
+         };
+
+    // Validators
+    String[] VALIDATORS_CHILDREN = {
+        VALIDATOR_ELEMENT
+    };
+
+    String[] VALIDATOR_CHILDREN = {
+        CLASS_ATTR, TYPE_ATTR, PROPERTIES_ELEMENT
+    };
+
+    String[] VALIDATOR_REQ_CHILDREN = {
+        CLASS_ATTR
+     };
+
+    // UTILS
+    String LIST_DELIMITERS = ",;:";
+
+    // TOKEN REPLACEMENT
+    String UNKNOWN_SOURCE_FILE = "uknown file";
+
+
+    // EXCEPTION MESSAGES
+
+    int PARSER_INIT_ERROR = 10100;
+    int PARSER_INTERNAL_ERROR = 10101;
+    int XML_PARSER_ERROR = 10102;
+    int INVALID_SERVICES_ROOT = 10103;
+    int MISSING_ELEMENT = 10104;
+    int MISSING_ATTRIBUTE = 10105;
+    int UNEXPECTED_ELEMENT = 10106;
+    int UNEXPECTED_ATTRIBUTE = 10107;
+    int TOO_MANY_OCCURRENCES = 10108;
+    int REF_NOT_FOUND = 10109;
+    int INVALID_ID = 10110;
+    int INVALID_ENDPOINT_PORT = 10111;
+    int INVALID_INCLUDE_ROOT = 10112;
+    int DUPLICATE_SERVICE_ERROR = 10113;
+    int CLASS_NOT_SPECIFIED = 10114;
+    int INVALID_DEFAULT_CHANNEL = 10116;
+    int DUPLICATE_DEFAULT_ADAPTER = 10117;
+    int MISSING_INCLUDE_ATTRIBUTES = 10118;
+    int INVALID_ID_IN_SERVICE = 10119;
+    int REF_NOT_FOUND_IN_DEST = 10120;
+    int INVALID_REF_IN_DEST = 10121;
+    int DUPLICATE_DESTINATION_ERROR = 10122;
+    int DEST_NEEDS_CHANNEL = 10123;
+    int DEST_NEEDS_ADAPTER = 10127;
+    int REF_NOT_FOUND_IN_CHANNEL = 10132;
+    int UNEXPECTED_TEXT = 11104;
+
+    int NULL_COMPONENT = 11110;
+    int NULL_COMPONENT_ID = 11111;
+    int DUPLICATE_COMPONENT_ID = 11112;
+    int UNREGISTERED_ADAPTER = 11114;
+    int DUPLICATE_DEST_ID = 11119;
+
+    int UNDEFINED_CONTEXT_ROOT = 11120;
+    int INVALID_FLEX_CLIENT_TIMEOUT = 11123;
+    int INVALID_SECURITY_CONSTRAINT_REF = 11124;
+    int IRREPLACABLE_TOKEN = 11125;
+    int INVALID_VALUE_FOR_PROPERTY_OF_COMPONENT_WITH_ID = 11126;
+    int DUPLICATE_CHANNEL_ERROR = 11127;
+    int INVALID_FLEX_CLIENT_RELIABLE_RECONNECT_DURATION_MILLIS = 11137;
+    int INVALID_FLEX_CLIENT_HEARTBEAT_INTERVAL_MILLIS = 11146;
+
+    int REQUIRE_ADVANCED_MESSAGING_SUPPORT = 11129;
+    int CLASS_OR_SERVER_ONLY_ERROR = 11139;
+    int CLASS_AND_SERVER_ONLY_ERROR = 11140;
+    int ERR_MSG_EMPTY_CLIENT_LOAD_BALANCING_ELEMENT = 11141;
+    int ERR_MSG_EMTPY_CLIENT_LOAD_BALACNING_URL = 11142;
+    int ERR_MSG_CLIENT_LOAD_BALANCING_URL_WITH_TOKEN = 11147;
+
+    int EXTERNAL_ENTITY_NOT_ALLOW = 11149;
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ConfigurationException.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ConfigurationException.java b/common/src/main/java/flex/messaging/config/ConfigurationException.java
new file mode 100644
index 0000000..49e5285
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ConfigurationException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.config;
+
+import flex.messaging.LocalizedException;
+
+/**
+ * The server throws this exception type on encountering
+ * errors while parsing the configuration. Other classes
+ * may also throw this exception type during initialization
+ * in the event that the configuration settings used to
+ * initialize the component was invalid.
+ */
+public class ConfigurationException extends LocalizedException
+{
+    /**
+     * This number was generated using the 'serialver' command line tool.
+     * This number should remain consistent with the version used by
+     * ColdFusion to communicate with the message broker over RMI.
+     */
+    private static final long serialVersionUID = -6999307106348525358L;
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ConfigurationFileResolver.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ConfigurationFileResolver.java b/common/src/main/java/flex/messaging/config/ConfigurationFileResolver.java
new file mode 100644
index 0000000..8336d2b
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ConfigurationFileResolver.java
@@ -0,0 +1,32 @@
+/*
+ * 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.config;
+
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ *
+ */
+public interface ConfigurationFileResolver
+{
+    InputStream getConfigurationFile(String path);
+    InputStream getIncludedFile(String path);
+    void popIncludedFile();
+
+    List getFiles(String dir);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/ConfigurationParser.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/ConfigurationParser.java b/common/src/main/java/flex/messaging/config/ConfigurationParser.java
new file mode 100644
index 0000000..ef8aaeb
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/ConfigurationParser.java
@@ -0,0 +1,30 @@
+/*
+ * 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.config;
+
+/**
+ * Configuration parser for Flex Data Services. The parser reads in
+ * a configuration file and populates a ServicesConfiguration instance.
+ *
+ *
+ */
+public interface ConfigurationParser
+{
+    void parse(String path, ConfigurationFileResolver fileResolver, ServicesConfiguration config);
+
+    void reportTokens();
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/config/DestinationSettings.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/config/DestinationSettings.java b/common/src/main/java/flex/messaging/config/DestinationSettings.java
new file mode 100644
index 0000000..3cd0e2f
--- /dev/null
+++ b/common/src/main/java/flex/messaging/config/DestinationSettings.java
@@ -0,0 +1,188 @@
+/*
+ * 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.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Destinations are configured for a particular <code>Service</code>. A
+ * destination's configuration includes an <code>id</code> attribute to provide
+ * a public name for clients to use when sending messages.
+ * <p>
+ * The configuration also specifies which channels are valid to contact the
+ * destination, as well as which adapter a service must use to process
+ * client messages for this destination and any security constraints that need
+ * to be enforced.
+ * </p>
+ */
+public class DestinationSettings extends PropertiesSettings
+{
+    /**
+     *
+     */
+    public static final String SERVER_ELEMENT = "server";
+
+    private final String id;
+    private String sourceFile;
+    private List channelSettings;
+    private AdapterSettings adapterSettings;
+    private SecurityConstraint constraint;
+
+    /**
+     * Used to construct a new set of properties to describe a destination.
+     * Note that an identity is required in order for clients to refer to a
+     * destination.
+     *
+     * @param id A string representing the unique identity of this destination.
+     */
+    public DestinationSettings(String id)
+    {
+        this.id = id;
+        channelSettings = new ArrayList();
+    }
+
+    /**
+     * Gets the unique identity used by clients to target a destination.
+     *
+     * @return String the destination's id.
+     */
+    public String getId()
+    {
+        return id;
+    }
+
+    /**
+     * Internal use only.
+     *
+     */
+    String getSourceFile()
+    {
+        return sourceFile;
+    }
+
+    /**
+     * Internal use only.
+     *
+     */
+    void setSourceFile(String sourceFile)
+    {
+        this.sourceFile = sourceFile;
+    }
+
+    /*
+     *  CHANNEL SETTINGS
+     */
+
+    /**
+     * Adds a channel to the set of channels that should be used to contact
+     * this destination. The order in which channels are added is significant
+     * (clients use this order to locate an available channel and failover to
+     * the next in the list on failure).
+     *
+     * @param c the <code>ChannelSettings</code> to add to the set of
+     * channel definitions for this destination.
+     */
+    public void addChannelSettings(ChannelSettings c)
+    {
+        if (c != null)
+        {
+            channelSettings.add(c);
+        }
+    }
+
+    /**
+     * Overrides the set of channels that can be used to contact this
+     * destination.
+     *
+     * @param settings A List of <code>ChannelSettings</code>.
+     */
+    public void setChannelSettings(List settings)
+    {
+        channelSettings = settings;
+    }
+
+    /**
+     * Gets the set of channels that can be used to contact this destination.
+     *
+     * @return a <code>java.util.List</code> of <code>ChannelSetting</code>s
+     * describing the channels that can be used to contact this destination.
+     */
+    public List getChannelSettings()
+    {
+        return channelSettings;
+    }
+
+
+    /*
+     *  SECURITY
+     */
+
+    /**
+     * Gets the <code>SecurityConstraint</code> that will be applied to this
+     * destination, or <code>null</code> if no constraint has been registered.
+     *
+     * @return the <code>SecurityConstraint</code> for this destination.
+     */
+    public SecurityConstraint getConstraint()
+    {
+        return constraint;
+    }
+
+    /**
+     * Sets the security constraint to be applied to this destination. Security
+     * constraints restrict which clients can contact this destination. Use
+     * <code>null</code> to remove an existing constraint.
+     *
+     * @param sc the <code>SecurityConstraint</code> to apply to this
+     * destination.
+     */
+    public void setConstraint(SecurityConstraint sc)
+    {
+        constraint = sc;
+    }
+
+    /*
+     *  SERVICE ADAPTER
+     */
+
+    /**
+     * Sets the service adapter to be used when the managing service is
+     * processing messages bound for this destination.
+     *
+     * @param a The <code>AdapterSettings</code> that describe the adapter
+     * to use for this destination.
+     */
+    public void setAdapterSettings(AdapterSettings a)
+    {
+        adapterSettings = a;
+    }
+
+    /**
+     * Gets the adapter to be used for this destination.
+     *
+     * @return <code>AdapterSettings</code> for this destinations adapter.
+     * A <code>null</code> value implies the the default service adapter should
+     * be used.
+     */
+    public AdapterSettings getAdapterSettings()
+    {
+        return adapterSettings;
+    }
+
+
+}