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>
+ * <default-channels><br />
+ * ;<channel ref="channel-id" /><br />
+ * <default-channels>
+ * </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>
+ * <default-channels><br />
+ * <channel ref="channel-id" /><br />
+ * <default-channels>
+ * </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;
+ }
+
+
+}