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 2015/12/20 14:13:44 UTC
[04/51] [partial] flex-blazeds git commit: Removed legacy directories
and made the content of the modules directory the new root - Please use the
maven build for now as the Ant build will no longer work untill it is
adjusted to the new directory structur
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/bf2e1dc9/core/src/flex/messaging/config/ServerConfigurationParser.java
----------------------------------------------------------------------
diff --git a/core/src/flex/messaging/config/ServerConfigurationParser.java b/core/src/flex/messaging/config/ServerConfigurationParser.java
new file mode 100644
index 0000000..9ff3e1c
--- /dev/null
+++ b/core/src/flex/messaging/config/ServerConfigurationParser.java
@@ -0,0 +1,1920 @@
+/*
+ * 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 org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import flex.messaging.config.ThrottleSettings.Policy;
+import flex.messaging.util.LocaleUtils;
+
+/**
+ * Processes DOM representation of a messaging configuration file.
+ * <p>
+ * Note: Since reference ids are used between elements, certain
+ * sections of the document need to be parsed first.
+ * </p>
+ *
+ *
+ */
+public abstract class ServerConfigurationParser extends AbstractConfigurationParser
+{
+ /**
+ * Used to verify that advanced messaging support has been registered if necessary.
+ * If other configuration requires it, but it was not registered a ConfigurationException is thrown.
+ */
+ private boolean verifyAdvancedMessagingSupport = false;
+ private boolean advancedMessagingSupportRegistered = false;
+
+ @Override
+ protected void parseTopLevelConfig(Document doc)
+ {
+ Node root = selectSingleNode(doc, "/" + SERVICES_CONFIG_ELEMENT);
+
+ if (root != null)
+ {
+ allowedChildElements(root, SERVICES_CONFIG_CHILDREN);
+
+ securitySection(root); // Parse security before channels.
+
+ serversSection(root);
+
+ channelsSection(root);
+
+ services(root);
+
+ clusters(root);
+
+ logging(root);
+
+ system(root);
+
+ flexClient(root);
+
+ factories(root);
+
+ messageFilters(root);
+
+ validators(root);
+
+ // Validate that any dependencies on advanced messaging support can be satisified at runtime.
+ if (verifyAdvancedMessagingSupport && !advancedMessagingSupportRegistered)
+ {
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(REQUIRE_ADVANCED_MESSAGING_SUPPORT);
+ throw e;
+ }
+ }
+ else
+ {
+ // The services configuration root element must be '{SERVICES_CONFIG_ELEMENT}'.
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(INVALID_SERVICES_ROOT, new Object[]{SERVICES_CONFIG_ELEMENT});
+ throw e;
+ }
+ }
+
+ 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))
+ continue;
+
+ String propsFileName = getAttributeOrChildElement(cluster, CLUSTER_PROPERTIES_ATTR);
+ ClusterSettings clusterSettings = new ClusterSettings();
+ clusterSettings.setClusterName(clusterName);
+ clusterSettings.setPropsFileName(propsFileName);
+ String className = getAttributeOrChildElement(cluster, CLASS_ATTR);
+ if (className != null && className.length() > 0)
+ clusterSettings.setImplementationClass(className);
+
+ String defaultValue = getAttributeOrChildElement(cluster, ClusterSettings.DEFAULT_ELEMENT);
+ if (defaultValue != null && defaultValue.length() > 0)
+ {
+ if (defaultValue.equalsIgnoreCase(TRUE_STRING))
+ clusterSettings.setDefault(true);
+ else if (!defaultValue.equalsIgnoreCase(FALSE_STRING))
+ {
+ 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_STRING))
+ {
+ clusterSettings.setURLLoadBalancing(false);
+ }
+ else if (!ulb.equalsIgnoreCase(TRUE_STRING))
+ {
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(10216, new Object[] {clusterName, ulb});
+ throw e;
+ }
+ }
+
+ NodeList properties = selectNodeList(cluster, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(cluster));
+ clusterSettings.addProperties(map);
+ }
+
+ ((MessagingConfiguration)config).addClusterSettings(clusterSettings);
+
+ }
+ }
+ }
+
+
+ private void securitySection(Node root)
+ {
+ Node security = selectSingleNode(root, SECURITY_ELEMENT);
+
+ if (security == null)
+ return;
+
+ allowedChildElements(security, SECURITY_CHILDREN);
+
+ NodeList list = selectNodeList(security, SECURITY_CONSTRAINT_DEFINITION_ELEMENT);
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Node constraint = list.item(i);
+ securityConstraint(constraint, false);
+ }
+
+ list = selectNodeList(security, CONSTRAINT_INCLUDE_ELEMENT);
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Node include = list.item(i);
+ securityConstraintInclude(include);
+ }
+
+ list = selectNodeList(security, LOGIN_COMMAND_ELEMENT);
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Node login = list.item(i);
+ LoginCommandSettings loginCommandSettings= new LoginCommandSettings();
+ requiredAttributesOrElements(login, LOGIN_COMMAND_REQ_CHILDREN);
+ allowedAttributesOrElements(login, LOGIN_COMMAND_CHILDREN);
+
+ String server = getAttributeOrChildElement(login, SERVER_ATTR);
+ if (server.length() == 0)
+ {
+ // Attribute '{SERVER_ATTR}' must be specified for element '{LOGIN_COMMAND_ELEMENT}'
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(MISSING_ATTRIBUTE, new Object[]{SERVER_ATTR, LOGIN_COMMAND_ELEMENT});
+ throw e;
+ }
+ loginCommandSettings.setServer(server);
+
+ String loginClass = getAttributeOrChildElement(login, CLASS_ATTR);
+ if (loginClass.length() == 0)
+ {
+ // Attribute '{CLASS_ATTR}' must be specified for element '{LOGIN_COMMAND_ELEMENT}'
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(MISSING_ATTRIBUTE, new Object[]{CLASS_ATTR, LOGIN_COMMAND_ELEMENT});
+ throw e;
+ }
+ loginCommandSettings.setClassName(loginClass);
+
+ boolean isPerClientAuth = Boolean.valueOf(getAttributeOrChildElement(login, PER_CLIENT_AUTH));
+ loginCommandSettings.setPerClientAuthentication(isPerClientAuth);
+
+ ((MessagingConfiguration)config).getSecuritySettings().addLoginCommandSettings(loginCommandSettings);
+ }
+
+ boolean recreateHttpSessionAfterLogin = Boolean.valueOf(getAttributeOrChildElement(security, RECREATE_HTTPSESSION_AFTER_LOGIN_ELEMENT));
+ ((MessagingConfiguration)config).getSecuritySettings().setRecreateHttpSessionAfterLogin(recreateHttpSessionAfterLogin);
+ }
+
+ private SecurityConstraint securityConstraint(Node constraint, boolean inline)
+ {
+ SecurityConstraint sc;
+
+ // Validation
+ allowedAttributesOrElements(constraint, SECURITY_CONSTRAINT_DEFINITION_CHILDREN);
+
+ // Constraint by reference
+ String ref = getAttributeOrChildElement(constraint, REF_ATTR);
+ if (ref.length() > 0)
+ {
+ allowedAttributesOrElements(constraint, new String[] {REF_ATTR});
+
+ sc = ((MessagingConfiguration)config).getSecuritySettings().getConstraint(ref);
+ if (sc == null)
+ {
+ // {SECURITY_CONSTRAINT_DEFINITION_ELEMENT} not found for reference '{ref}'.
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(REF_NOT_FOUND, new Object[]{SECURITY_CONSTRAINT_DEFINITION_ELEMENT, ref});
+ throw e;
+ }
+ }
+ else
+ {
+ // New security constraint
+ String id = getAttributeOrChildElement(constraint, ID_ATTR);
+
+ // If not inline, we must have a valid id to register the constraint!
+ if (inline)
+ {
+ sc = new SecurityConstraint("");
+ }
+ else if (isValidID(id))
+ {
+ sc = new SecurityConstraint(id);
+ ((MessagingConfiguration)config).getSecuritySettings().addConstraint(sc);
+ }
+ else
+ {
+ //Invalid {SECURITY_CONSTRAINT_DEFINITION_ELEMENT} id '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(INVALID_ID, new Object[]{SECURITY_CONSTRAINT_DEFINITION_ELEMENT, id});
+ ex.setDetails(INVALID_ID);
+ throw ex;
+ }
+
+ // Authentication Method
+ String method = getAttributeOrChildElement(constraint, AUTH_METHOD_ELEMENT);
+ sc.setMethod(method);
+
+ // Roles
+ Node rolesNode = selectSingleNode(constraint, ROLES_ELEMENT);
+ if (rolesNode != null)
+ {
+ allowedChildElements(rolesNode, ROLES_CHILDREN);
+ NodeList roles = selectNodeList(rolesNode, ROLE_ELEMENT);
+ for (int r = 0; r < roles.getLength(); r++)
+ {
+ Node roleNode = roles.item(r);
+ String role = evaluateExpression(roleNode, ".").toString().trim();
+ if (role.length() > 0)
+ {
+ sc.addRole(role);
+ }
+ }
+ }
+ }
+
+ return sc;
+ }
+
+ private void securityConstraintInclude(Node constraintInclude)
+ {
+ // Validation
+ allowedAttributesOrElements(constraintInclude, CONSTRAINT_INCLUDE_CHILDREN);
+
+ String src = getAttributeOrChildElement(constraintInclude, SRC_ATTR);
+ String dir = getAttributeOrChildElement(constraintInclude, DIRECTORY_ATTR);
+ if (src.length() > 0)
+ {
+ constraintIncludeFile(src);
+ }
+ else if (dir.length() > 0)
+ {
+ constraintIncludeDirectory(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[]{constraintInclude.getNodeName(), SRC_ATTR, DIRECTORY_ATTR});
+ throw ex;
+ }
+ }
+
+ private void constraintIncludeFile(String src)
+ {
+ Document doc = loadDocument(src, fileResolver.getIncludedFile(src));
+ doc.getDocumentElement().normalize();
+
+ // Check for <security-constraints> wrapping more than one definition
+ Node servicesNode = selectSingleNode(doc, SECURITY_CONSTRAINTS_ELEMENT);
+ if (servicesNode != null)
+ {
+ allowedChildElements(servicesNode, SECURITY_CONSTRAINTS_CHILDREN);
+ NodeList constraints = selectNodeList(servicesNode, SECURITY_CONSTRAINT_ELEMENT);
+ for (int a = 0; a < constraints.getLength(); a++)
+ {
+ Node constraint = constraints.item(a);
+ securityConstraint(constraint, false);
+ }
+ fileResolver.popIncludedFile();
+ }
+ else // Check for single <security-constraint>
+ {
+ Node constraint = selectSingleNode(doc, "/" + SECURITY_CONSTRAINT_ELEMENT);
+ if (constraint != null)
+ {
+ securityConstraint(constraint, false);
+ 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[]{CONSTRAINT_INCLUDE_ELEMENT, src, SECURITY_CONSTRAINTS_ELEMENT, SECURITY_CONSTRAINT_ELEMENT});
+ throw ex;
+ }
+ }
+ }
+
+ private void constraintIncludeDirectory(String dir)
+ {
+ List files = fileResolver.getFiles(dir);
+ for (int i = 0; i < files.size(); i++)
+ {
+ String src = (String) files.get(i);
+ constraintIncludeFile(src);
+ }
+ }
+
+ private void serversSection(Node root)
+ {
+ // Only MessagingConfiguration supports the servers element configuration.
+ // The general ServicesConfiguration interface does not.
+ if (!(config instanceof MessagingConfiguration))
+ return;
+
+ Node serversNode = selectSingleNode(root, SERVERS_ELEMENT);
+ if (serversNode != null)
+ {
+ // Validation
+ allowedAttributesOrElements(serversNode, SERVERS_CHILDREN);
+
+ NodeList servers = selectNodeList(serversNode, SERVER_ELEMENT);
+ for (int i = 0; i < servers.getLength(); i++)
+ {
+ Node server = servers.item(i);
+ serverDefinition(server);
+ }
+ }
+ }
+
+ private void serverDefinition(Node server)
+ {
+ // Validation
+ requiredAttributesOrElements(server, SERVER_REQ_CHILDREN);
+ allowedAttributesOrElements(server, SERVER_CHILDREN);
+
+ String id = getAttributeOrChildElement(server, ID_ATTR);
+ if (isValidID(id))
+ {
+ SharedServerSettings settings = new SharedServerSettings();
+ settings.setId(id);
+ settings.setSourceFile(getSourceFileOf(server));
+ String className = getAttributeOrChildElement(server, CLASS_ATTR);
+ if (className.length() > 0)
+ {
+ settings.setClassName(className);
+ // Custom server properties.
+ NodeList properties = selectNodeList(server, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(server));
+ settings.addProperties(map);
+ }
+ ((MessagingConfiguration)config).addSharedServerSettings(settings);
+ }
+ else
+ {
+ // Class not specified for {MESSAGE_FILTER_ELEMENT} '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{SERVER_ELEMENT, id});
+ throw ex;
+ }
+ }
+ }
+
+ 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);
+ 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);
+ channelSettings.setSourceFile(getSourceFileOf(channel));
+
+ // Note whether the channel-definition was for a remote endpoint
+ String remote = getAttributeOrChildElement(channel, REMOTE_ATTR);
+ channelSettings.setRemote(Boolean.valueOf(remote));
+
+ // Endpoint
+ Node endpoint = selectSingleNode(channel, ENDPOINT_ELEMENT);
+ if (endpoint != null)
+ {
+ // Endpoint Validation
+ allowedAttributesOrElements(endpoint, ENDPOINT_CHILDREN);
+
+ String type = getAttributeOrChildElement(endpoint, CLASS_ATTR);
+ channelSettings.setEndpointType(type);
+
+ // 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);
+
+ // Server reference
+ Node server = selectSingleNode(channel, SERVER_ELEMENT);
+ if (server != null)
+ {
+ requiredAttributesOrElements(server, CHANNEL_DEFINITION_SERVER_REQ_CHILDREN);
+
+ String serverId = getAttributeOrChildElement(server, REF_ATTR);
+ channelSettings.setServerId(serverId);
+ }
+
+ // Channel Properties
+ NodeList properties = selectNodeList(channel, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(channel));
+ channelSettings.addProperties(map);
+
+ // Sniff for adaptive-frequency under flex-client-queue-processor hich requires advanced messaging support.
+ if (!verifyAdvancedMessagingSupport)
+ {
+ ConfigMap outboundQueueProcessor = map.getPropertyAsMap(FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_ELEMENT, null);
+ if (outboundQueueProcessor != null)
+ {
+ // Flex client queue processor properties
+ ConfigMap queueProcessorProperties = outboundQueueProcessor.getPropertyAsMap(PROPERTIES_ELEMENT, null);
+ if (queueProcessorProperties != null)
+ {
+ // Sniff for adaptive-frequency which requires advanced messaging support.
+ boolean adaptiveFrequency = queueProcessorProperties.getPropertyAsBoolean(ADAPTIVE_FREQUENCY, false);
+ if (adaptiveFrequency)
+ verifyAdvancedMessagingSupport = true;
+ }
+ }
+ }
+ }
+
+ // Channel Security
+
+ // Security-constraint short-cut attribute
+ String ref = evaluateExpression(channel, "@" + SECURITY_CONSTRAINT_ATTR).toString().trim();
+ if (ref.length() > 0)
+ {
+ SecurityConstraint sc = ((MessagingConfiguration)config).getSecuritySettings().getConstraint(ref);
+ if (sc != null)
+ {
+ channelSettings.setConstraint(sc);
+ }
+ else
+ {
+ // {SECURITY_CONSTRAINT_ELEMENT} not found for reference '{ref}' in channel '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(REF_NOT_FOUND_IN_CHANNEL, new Object[]{SECURITY_CONSTRAINT_ATTR, ref, id});
+ throw ex;
+ }
+ }
+ else
+ {
+ // Inline security element
+ Node security = selectSingleNode(channel, SECURITY_ELEMENT);
+ if (security != null)
+ {
+ allowedChildElements(security, EMBEDDED_SECURITY_CHILDREN);
+ Node constraint = selectSingleNode(security, SECURITY_CONSTRAINT_ELEMENT);
+ if (constraint != null)
+ {
+ SecurityConstraint sc = securityConstraint(constraint, true);
+ channelSettings.setConstraint(sc);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Invalid {CHANNEL_DEFINITION_ELEMENT} id '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(INVALID_ID, new Object[]{CHANNEL_DEFINITION_ELEMENT, id});
+ ex.setDetails(INVALID_ID);
+ 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) : false;
+
+ 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 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));
+ 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 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));
+ doc.getDocumentElement().normalize();
+
+ // Check for multiple services defined in a <services> tag
+ Node servicesNode = selectSingleNode(doc, SERVICES_ELEMENT);
+ if (servicesNode != null)
+ {
+ allowedChildElements(servicesNode, SERVICES_CHILDREN);
+ NodeList services = selectNodeList(servicesNode, SERVICE_ELEMENT);
+ for (int a = 0; a < services.getLength(); a++)
+ {
+ Node service = services.item(a);
+ service(service);
+ }
+ fileResolver.popIncludedFile();
+ }
+ else // Check for single <service> definition.
+ {
+ 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);
+ serviceSettings.setSourceFile(getSourceFileOf(service));
+ 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);
+
+ // Sniff for AdvancedMessagingSupport.
+ if (className.equals("flex.messaging.services.AdvancedMessagingSupport"))
+ advancedMessagingSupportRegistered = true;
+ }
+ 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
+
+ // Service Properties
+ NodeList properties = selectNodeList(service, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(service));
+ serviceSettings.addProperties(map);
+ }
+
+ // 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);
+ }
+ }
+
+ // Default Security Constraint
+ Node defaultSecurityConstraint = selectSingleNode(service, DEFAULT_SECURITY_CONSTRAINT_ELEMENT);
+ if (defaultSecurityConstraint != null)
+ {
+ // Validation
+ requiredAttributesOrElements(defaultSecurityConstraint, new String[] {REF_ATTR});
+ allowedAttributesOrElements(defaultSecurityConstraint, new String[] {REF_ATTR});
+
+ String ref = getAttributeOrChildElement(defaultSecurityConstraint, REF_ATTR);
+ if (ref.length() > 0)
+ {
+ SecurityConstraint sc = ((MessagingConfiguration)config).getSecuritySettings().getConstraint(ref);
+ if (sc == null)
+ {
+ // {SECURITY_CONSTRAINT_DEFINITION_ELEMENT} not found for reference '{ref}'.
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(REF_NOT_FOUND, new Object[]{SECURITY_CONSTRAINT_DEFINITION_ELEMENT, ref});
+ throw e;
+ }
+ serviceSettings.setConstraint(sc);
+ }
+ else
+ {
+ //Invalid default-security-constraint reference ''{0}'' in service ''{1}''.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(INVALID_SECURITY_CONSTRAINT_REF, new Object[]{ref, id});
+ throw ex;
+ }
+ }
+
+ // Adapter Definitions
+ Node adapters = selectSingleNode(service, ADAPTERS_ELEMENT);
+ if (adapters != null)
+ {
+ allowedChildElements(adapters, ADAPTERS_CHILDREN);
+ NodeList serverAdapters = selectNodeList(adapters, ADAPTER_DEFINITION_ELEMENT);
+ for (int a = 0; a < serverAdapters.getLength(); a++)
+ {
+ Node adapter = serverAdapters.item(a);
+ adapterDefinition(adapter, serviceSettings);
+ }
+ NodeList adapterIncludes = selectNodeList(adapters, ADAPTER_INCLUDE_ELEMENT);
+ for (int a = 0; a < adapterIncludes.getLength(); a++)
+ {
+ Node include = adapterIncludes.item(a);
+ adapterInclude(include, serviceSettings);
+ }
+ }
+
+ // 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;
+ }
+ }
+
+ /**
+ * A 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);
+
+ 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 adapterDefinition(Node adapter, ServiceSettings serviceSettings)
+ {
+ // Validation
+ requiredAttributesOrElements(adapter, ADAPTER_DEFINITION_REQ_CHILDREN);
+ allowedChildElements(adapter, ADAPTER_DEFINITION_CHILDREN);
+
+ String serviceId = serviceSettings.getId();
+
+ String id = getAttributeOrChildElement(adapter, ID_ATTR);
+ if (isValidID(id))
+ {
+ AdapterSettings adapterSettings = new AdapterSettings(id);
+ adapterSettings.setSourceFile(getSourceFileOf(adapter));
+ String className = getAttributeOrChildElement(adapter, CLASS_ATTR);
+
+ if (className.length() > 0)
+ {
+ adapterSettings.setClassName(className);
+
+ // Default Adapter Check
+ boolean isDefault = Boolean.valueOf(getAttributeOrChildElement(adapter, DEFAULT_ATTR));
+ if (isDefault)
+ {
+ adapterSettings.setDefault(isDefault);
+
+ AdapterSettings defaultAdapter;
+ defaultAdapter = serviceSettings.getDefaultAdapter();
+
+ if (defaultAdapter != null)
+ {
+ // Duplicate default adapter '{0}' in service '{1}'. '{2}' has already been selected as the default.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(DUPLICATE_DEFAULT_ADAPTER, new Object[]{id, serviceId, defaultAdapter.getId()});
+ throw ex;
+ }
+ }
+
+ serviceSettings.addAdapterSettings(adapterSettings);
+
+ // Adapter Properties
+ NodeList properties = selectNodeList(adapter, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(adapter));
+ adapterSettings.addProperties(map);
+ }
+ }
+ else
+ {
+ // Class not specified for {ADAPTER_DEFINITION_ELEMENT} '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{ADAPTER_DEFINITION_ELEMENT, id});
+ throw ex;
+ }
+ }
+ else
+ {
+ //Invalid {ADAPTER_DEFINITION_ELEMENT} id '{id}' for service '{serviceId}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(INVALID_ID_IN_SERVICE, new Object[]{ADAPTER_DEFINITION_ELEMENT, id, serviceId});
+ throw ex;
+ }
+ }
+
+ private void adapterInclude(Node adapterInclude, ServiceSettings serviceSettings)
+ {
+ // Validation
+ allowedAttributesOrElements(adapterInclude, ADAPTER_INCLUDE_CHILDREN);
+
+ String src = getAttributeOrChildElement(adapterInclude, SRC_ATTR);
+ String dir = getAttributeOrChildElement(adapterInclude, DIRECTORY_ATTR);
+ if (src.length() > 0)
+ {
+ adapterIncludeFile(serviceSettings, src);
+ }
+ else if (dir.length() > 0)
+ {
+ adapterIncludeDirectory(serviceSettings, dir);
+ }
+ else
+ {
+ // Attribute '{0}' must be specified for element '{1}'
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(MISSING_INCLUDE_ATTRIBUTES, new Object[]{adapterInclude.getNodeName(), SRC_ATTR, DIRECTORY_ATTR});
+ throw ex;
+ }
+ }
+
+ private void adapterIncludeDirectory(ServiceSettings serviceSettings, String dir)
+ {
+ List files = fileResolver.getFiles(dir);
+ for (int i = 0; i < files.size(); i++)
+ {
+ String src = (String) files.get(i);
+ adapterIncludeFile(serviceSettings, src);
+ }
+ }
+
+ private void adapterIncludeFile(ServiceSettings serviceSettings, String src)
+ {
+ Document doc = loadDocument(src, fileResolver.getIncludedFile(src));
+ doc.getDocumentElement().normalize();
+
+ // Check for multiple adapters defined in file wrapped in an <adapters> element
+ Node adaptersNode = selectSingleNode(doc, ADAPTERS_ELEMENT);
+ if (adaptersNode != null)
+ {
+ allowedChildElements(adaptersNode, ADAPTERS_CHILDREN);
+ NodeList adapters = selectNodeList(adaptersNode, ADAPTER_DEFINITION_ELEMENT);
+ for (int a = 0; a < adapters.getLength(); a++)
+ {
+ Node adapter = adapters.item(a);
+ adapterDefinition(adapter, serviceSettings);
+ }
+ fileResolver.popIncludedFile();
+ }
+ else // Check for single adapter
+ {
+ Node adapter = selectSingleNode(doc, "/" + ADAPTER_DEFINITION_ELEMENT);
+ if (adapter != null)
+ {
+ adapterDefinition(adapter, 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[]{ADAPTER_INCLUDE_ELEMENT, src, ADAPTERS_ELEMENT, ADAPTER_DEFINITION_ELEMENT});
+ 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));
+ 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);
+ destinationSettings.setSourceFile(getSourceFileOf(dest));
+ 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);
+
+ // Sniff for <network><reliable>true|false</reliable></network> setting.
+ // Also sniff for inbound and outbound throttle policies of buffer and conflate.
+ // All these features are only supported when advanced messaging support is enabled.
+ if (!verifyAdvancedMessagingSupport)
+ {
+ ConfigMap networkSettings = map.getPropertyAsMap(NetworkSettings.NETWORK_ELEMENT, null);
+ if (networkSettings != null)
+ {
+ String reliable = networkSettings.getPropertyAsString(NetworkSettings.RELIABLE_ELEMENT, null);
+ if (reliable != null && Boolean.valueOf(reliable))
+ {
+ verifyAdvancedMessagingSupport = true;
+ }
+ else
+ {
+ ConfigMap inbound = networkSettings.getPropertyAsMap(ThrottleSettings.ELEMENT_INBOUND, null);
+ if (inbound != null)
+ {
+ String policy = inbound.getPropertyAsString(ThrottleSettings.ELEMENT_POLICY, null);
+ if (policy != null && (Policy.BUFFER.toString().equalsIgnoreCase(policy)
+ || Policy.CONFLATE.toString().equalsIgnoreCase(policy)))
+ verifyAdvancedMessagingSupport = true;
+ }
+ if (!verifyAdvancedMessagingSupport)
+ {
+ ConfigMap outbound = networkSettings.getPropertyAsMap(ThrottleSettings.ELEMENT_OUTBOUND, null);
+ if (outbound != null)
+ {
+ String policy = outbound.getPropertyAsString(ThrottleSettings.ELEMENT_POLICY, null);
+ if (policy != null && (Policy.BUFFER.toString().equalsIgnoreCase(policy)
+ || Policy.CONFLATE.toString().equalsIgnoreCase(policy)))
+ verifyAdvancedMessagingSupport = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Channels
+ destinationChannels(dest, destinationSettings, serviceSettings);
+
+ // Security
+ destinationSecurity(dest, destinationSettings, serviceSettings);
+
+ // Service Adapter
+ destinationAdapter(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);
+ 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);
+ 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 destinationSecurity(Node dest, DestinationSettings destinationSettings, ServiceSettings serviceSettings)
+ {
+ String destId = destinationSettings.getId();
+
+ // Security-constraint short-cut attribute
+ String ref = evaluateExpression(dest, "@" + SECURITY_CONSTRAINT_ATTR).toString().trim();
+ if (ref.length() > 0)
+ {
+ SecurityConstraint sc = ((MessagingConfiguration)config).getSecuritySettings().getConstraint(ref);
+ if (sc != null)
+ {
+ destinationSettings.setConstraint(sc);
+ }
+ else
+ {
+ // {SECURITY_CONSTRAINT_ELEMENT} not found for reference '{ref}' in destination '{destId}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(REF_NOT_FOUND_IN_DEST, new Object[]{SECURITY_CONSTRAINT_ATTR, ref, destId});
+ throw ex;
+ }
+ }
+ else
+ {
+ // Inline security element
+ Node security = selectSingleNode(dest, SECURITY_ELEMENT);
+ if (security != null)
+ {
+ allowedChildElements(security, EMBEDDED_SECURITY_CHILDREN);
+ Node constraint = selectSingleNode(security, SECURITY_CONSTRAINT_ELEMENT);
+ if (constraint != null)
+ {
+ SecurityConstraint sc = securityConstraint(constraint, true);
+ destinationSettings.setConstraint(sc);
+ }
+ }
+ else
+ {
+ // Finally, we fall back to the service's default security constraint
+ SecurityConstraint sc = serviceSettings.getConstraint();
+ if (sc != null)
+ {
+ destinationSettings.setConstraint(sc);
+ }
+ }
+ }
+ }
+
+ private void destinationAdapter(Node dest, DestinationSettings destinationSettings, ServiceSettings serviceSettings)
+ {
+ String destId = destinationSettings.getId();
+
+ // Adapter attribute
+ String ref = evaluateExpression(dest, "@" + ADAPTER_ATTR).toString().trim();
+ if (ref.length() > 0)
+ {
+ adapterReference(ref, destinationSettings, serviceSettings);
+ }
+ else
+ {
+ Node adapter = selectSingleNode(dest, ADAPTER_ELEMENT);
+
+ // Adapter element
+ if (adapter != null)
+ {
+ allowedAttributesOrElements(adapter, DESTINATION_ADAPTER_CHILDREN);
+ ref = getAttributeOrChildElement(adapter, REF_ATTR);
+ adapterReference(ref, destinationSettings, serviceSettings);
+ }
+ else
+ {
+ // Default Adapter (optionally set at the service level)
+ AdapterSettings adapterSettings = serviceSettings.getDefaultAdapter();
+ if (adapterSettings != null)
+ {
+ destinationSettings.setAdapterSettings(adapterSettings);
+ }
+ }
+ }
+
+ if (destinationSettings.getAdapterSettings() == null)
+ {
+ // Destination '{id}' must specify at least one adapter.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(DEST_NEEDS_ADAPTER, new Object[]{destId});
+ throw ex;
+ }
+ }
+
+ private void adapterReference(String ref, DestinationSettings destinationSettings, ServiceSettings serviceSettings)
+ {
+ String destId = destinationSettings.getId();
+ if (ref.length() > 0)
+ {
+ AdapterSettings adapterSettings = serviceSettings.getAdapterSettings(ref);
+ if (adapterSettings != null)
+ {
+ destinationSettings.setAdapterSettings(adapterSettings);
+ }
+ else
+ {
+ // {ADAPTER_ELEMENT} not found for reference '{ref}' in destination '{destId}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(REF_NOT_FOUND_IN_DEST, new Object[]{ADAPTER_ELEMENT, ref, destId});
+ throw ex;
+ }
+ }
+ else
+ {
+ //Invalid {ADAPTER_ELEMENT} ref '{ref}' in destination '{destId}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(INVALID_REF_IN_DEST, new Object[]{ADAPTER_ELEMENT, ref, destId});
+ throw ex;
+ }
+ }
+
+ private void logging(Node root)
+ {
+ Node logging = selectSingleNode(root, LOGGING_ELEMENT);
+ if (logging != null)
+ {
+ // Validation
+ allowedAttributesOrElements(logging, LOGGING_CHILDREN);
+
+ LoggingSettings settings = new LoggingSettings();
+
+ // Log Properties
+ NodeList properties = selectNodeList(logging, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(logging));
+ settings.addProperties(map);
+ }
+
+ NodeList targets = selectNodeList(logging, TARGET_ELEMENT);
+ for (int i = 0; i < targets.getLength(); i++)
+ {
+ Node targetNode = targets.item(i);
+
+ // Target Validation
+ requiredAttributesOrElements(targetNode, TARGET_REQ_CHILDREN);
+ allowedAttributesOrElements(targetNode, TARGET_CHILDREN);
+
+ String className = getAttributeOrChildElement(targetNode, CLASS_ATTR);
+
+ if (className.length() > 0)
+ {
+ TargetSettings targetSettings = new TargetSettings(className);
+ String targetLevel = getAttributeOrChildElement(targetNode, LEVEL_ATTR);
+
+ if (targetLevel.length() > 0)
+ targetSettings.setLevel(targetLevel);
+
+ // Filters
+ Node filtersNode = selectSingleNode(targetNode, FILTERS_ELEMENT);
+ if (filtersNode != null)
+ {
+ allowedChildElements(filtersNode, FILTERS_CHILDREN);
+ NodeList filters = selectNodeList(filtersNode, PATTERN_ELEMENT);
+ for (int f = 0; f < filters.getLength(); f++)
+ {
+ Node pattern = filters.item(f);
+ String filter = evaluateExpression(pattern, ".").toString().trim();
+ targetSettings.addFilter(filter);
+ }
+ }
+
+ // Target Properties
+ properties = selectNodeList(targetNode, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(targetNode));
+ targetSettings.addProperties(map);
+ }
+
+ settings.addTarget(targetSettings);
+ }
+ }
+
+ config.setLoggingSettings(settings);
+ }
+ }
+
+ private void system(Node root)
+ {
+ Node system = selectSingleNode(root, SYSTEM_ELEMENT);
+ if (system == null)
+ {
+ // Create a default instance of SystemSettings which by default has setManagable as true
+ // and has setRedeployEnabled as false.
+ ((MessagingConfiguration)config).setSystemSettings(new SystemSettings());
+ return;
+ }
+
+ allowedAttributesOrElements(system, SYSTEM_CHILDREN);
+
+ SystemSettings settings = new SystemSettings();
+
+ settings.setEnforceEndpointValidation(getAttributeOrChildElement(system, ENFORCE_ENDOINT_VALIDATION));
+ locale(system, settings);
+ settings.setManageable(getAttributeOrChildElement(system, MANAGEABLE_ELEMENT));
+ settings.setDotNetFrameworkVersion(getAttributeOrChildElement(system, DOTNET_FRAMEWORK_VERSION));
+ redeploy(system, settings);
+ uuidGenerator(system, settings);
+
+ ((MessagingConfiguration)config).setSystemSettings(settings);
+ }
+
+ private void redeploy(Node system, SystemSettings settings)
+ {
+ Node redeployNode = selectSingleNode(system, REDEPLOY_ELEMENT);
+ if (redeployNode == null)
+ return;
+
+ allowedAttributesOrElements(redeployNode, REDEPLOY_CHILDREN);
+
+ String enabled = getAttributeOrChildElement(redeployNode, ENABLED_ELEMENT);
+ settings.setRedeployEnabled(enabled);
+
+ String interval = getAttributeOrChildElement(redeployNode, WATCH_INTERVAL_ELEMENT);
+ if (interval.length() > 0)
+ {
+ settings.setWatchInterval(interval);
+ }
+
+ NodeList watches = selectNodeList(redeployNode, WATCH_FILE_ELEMENT);
+ for (int i = 0; i < watches.getLength(); i++)
+ {
+ Node watchNode = watches.item(i);
+ String watch = evaluateExpression(watchNode, ".").toString().trim();
+ if (watch.length() > 0)
+ {
+ settings.addWatchFile(watch);
+ }
+ }
+
+ NodeList touches = selectNodeList(redeployNode, TOUCH_FILE_ELEMENT);
+ for (int i = 0; i < touches.getLength(); i++)
+ {
+ Node touchNode = touches.item(i);
+ String touch = evaluateExpression(touchNode, ".").toString().trim();
+ if (touch.length() > 0)
+ {
+ settings.addTouchFile(touch);
+ }
+ }
+ }
+
+ private void locale(Node system, SystemSettings settings)
+ {
+ Node localeNode = selectSingleNode(system, LOCALE_ELEMENT);
+ if (localeNode == null)
+ return;
+
+ allowedAttributesOrElements(localeNode, LOCALE_CHILDREN);
+
+ String defaultLocaleString = getAttributeOrChildElement(localeNode, DEFAULT_LOCALE_ELEMENT);
+ Locale defaultLocale = defaultLocaleString.length() > 0? LocaleUtils.buildLocale(defaultLocaleString) : LocaleUtils.buildLocale(null);
+ settings.setDefaultLocale(defaultLocale);
+ }
+
+ private void uuidGenerator(Node system, SystemSettings settings)
+ {
+ Node uuidGenerator = selectSingleNode(system, UUID_GENERATOR_ELEMENT);
+ if (uuidGenerator == null)
+ return;
+
+ requiredAttributesOrElements(uuidGenerator, UUID_GENERATOR_REQ_CHILDREN);
+
+ String className = getAttributeOrChildElement(uuidGenerator, CLASS_ATTR);
+ if (className.length() == 0)
+ {
+ // Class not specified for {UUID_GENERATOR_ELEMENT} '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{UUID_GENERATOR_ELEMENT, ""});
+ throw ex;
+ }
+
+ settings.setUUIDGeneratorClassName(className);
+ }
+
+ private void flexClient(Node root)
+ {
+ Node flexClient = selectSingleNode(root, FLEX_CLIENT_ELEMENT);
+ if (flexClient != null)
+ {
+ // Validation
+ allowedChildElements(flexClient, FLEX_CLIENT_CHILDREN);
+
+ FlexClientSettings flexClientSettings = new FlexClientSettings();
+
+ // Timeout
+ String timeout = getAttributeOrChildElement(flexClient, FLEX_CLIENT_TIMEOUT_MINUTES_ELEMENT);
+ if (timeout.length() > 0)
+ {
+ try
+ {
+ long timeoutMinutes = Long.parseLong(timeout);
+ if (timeoutMinutes < 0)
+ {
+ // Invalid timeout minutes value ''{0}'' in the <flex-client> configuration section. Please specify a positive value or leave the element undefined in which case flex client instances on the server will be timed out when all associated sessions/connections have shut down.
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(INVALID_FLEX_CLIENT_TIMEOUT, new Object[]{timeout});
+ throw e;
+ }
+ flexClientSettings.setTimeoutMinutes(timeoutMinutes);
+ }
+ catch (NumberFormatException nfe)
+ {
+ // Invalid timeout minutes value ''{0}'' in the <flex-client> configuration section. Please specify a positive value or leave the element undefined in which case flex client instances on the server will be timed out when all associated sessions/connections have shut down.
+ ConfigurationException e = new ConfigurationException();
+ e.setMessage(INVALID_FLEX_CLIENT_TIMEOUT, new Object[]{timeout});
+ throw e;
+ }
+ }
+ else
+ {
+ flexClientSettings.setTimeoutMinutes(0); // Default to 0; in this case FlexClients are invalidated when all associated sessions have been invalidated.
+ }
+
+ // Flex client queue processor
+ Node outboundQueueProcessor = selectSingleNode(flexClient, FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_ELEMENT);
+ if (outboundQueueProcessor != null)
+ {
+ // Validation
+ requiredAttributesOrElements(outboundQueueProcessor, FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_REQ_CHILDREN);
+
+ // Flex client queue processor class
+ String outboundQueueProcessClass = getAttributeOrChildElement(outboundQueueProcessor, CLASS_ATTR);
+ if (outboundQueueProcessClass.length() > 0)
+ {
+ flexClientSettings.setFlexClientOutboundQueueProcessorClassName(outboundQueueProcessClass);
+ }
+ else
+ {
+ // Class not specified for {FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_ELEMENT} '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{FLEX_CLIENT_OUTBOUND_QUEUE_PROCESSOR_ELEMENT, ""});
+ throw ex;
+ }
+
+ // Flex client queue processor properties
+ NodeList properties = selectNodeList(outboundQueueProcessor, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(outboundQueueProcessor));
+ flexClientSettings.setFlexClientOutboundQueueProcessorProperties(map);
+ // Sniff for adaptive-frequency which requires advanced messaging support.
+ boolean adaptiveFrequency = map.getPropertyAsBoolean(ADAPTIVE_FREQUENCY, false);
+ if (adaptiveFrequency)
+ verifyAdvancedMessagingSupport = true;
+ }
+ }
+ ((MessagingConfiguration)config).setFlexClientSettings(flexClientSettings);
+ }
+ }
+
+ private void factories(Node root)
+ {
+ Node factories = selectSingleNode(root, FACTORIES_ELEMENT);
+ if (factories != null)
+ {
+ // Validation
+ allowedAttributesOrElements(factories, FACTORIES_CHILDREN);
+
+ NodeList factoryList = selectNodeList(factories, FACTORY_ELEMENT);
+ for (int i = 0; i < factoryList.getLength(); i++)
+ {
+ Node factory = factoryList.item(i);
+ factory(factory);
+ }
+ }
+ }
+
+ private void factory(Node factory)
+ {
+ // Validation
+ requiredAttributesOrElements(factory, FACTORY_REQ_CHILDREN);
+
+ String id = getAttributeOrChildElement(factory, ID_ATTR);
+ String className = getAttributeOrChildElement(factory, CLASS_ATTR);
+ if (isValidID(id))
+ {
+ FactorySettings factorySettings = new FactorySettings(id, className);
+
+ // Factory Properties
+ NodeList properties = selectNodeList(factory, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(factory));
+ factorySettings.addProperties(map);
+ }
+ ((MessagingConfiguration)config).addFactorySettings(id, factorySettings);
+ }
+ else
+ {
+ // Invalid {FACTORY_ELEMENT} id '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(INVALID_ID, new Object[]{FACTORY_ELEMENT, id});
+ ex.setDetails(INVALID_ID);
+ throw ex;
+ }
+ }
+
+ private void messageFilters(Node root)
+ {
+ typedMessageFilters(root, ASYNC_MESSAGE_FILTERS_ELEMENT, ASYNC_MESSAGE_FILTERS_ELEMENT_CHILDREN);
+ typedMessageFilters(root, SYNC_MESSAGE_FILTERS_ELEMENT, SYNC_MESSAGE_FILTERS_ELEMENT_CHILDREN);
+ }
+
+ private void typedMessageFilters(Node root, String filterTypeElement, String[] childrenElements)
+ {
+ Node messageFiltersNode = selectSingleNode(root, filterTypeElement);
+ if (messageFiltersNode == null)
+ return;
+
+ // Validation
+ allowedChildElements(messageFiltersNode, childrenElements);
+
+ // Message filter
+ NodeList messageFilters = selectNodeList(messageFiltersNode, FILTER_ELEMENT);
+ for (int i = 0; i < messageFilters.getLength(); i++)
+ {
+ Node messageFilter = messageFilters.item(i);
+ messageFilter(messageFilter, filterTypeElement);
+ }
+ }
+
+ private void messageFilter(Node messageFilter, String filterType)
+ {
+ // Validation
+ requiredAttributesOrElements(messageFilter, FILTER_REQ_CHILDREN);
+ allowedAttributesOrElements(messageFilter, FILTER_CHILDREN);
+
+ String id = getAttributeOrChildElement(messageFilter, ID_ATTR);
+ if (isValidID(id))
+ {
+ // Message filter class name
+ String className = getAttributeOrChildElement(messageFilter, CLASS_ATTR);
+ if (className.length() > 0)
+ {
+ MessageFilterSettings messageFilterSettings = new MessageFilterSettings();
+ messageFilterSettings.setId(id);
+ messageFilterSettings.setClassName(className);
+ // Record type of filter.
+ MessageFilterSettings.FilterType type = filterType.equals(ASYNC_MESSAGE_FILTERS_ELEMENT) ?
+ MessageFilterSettings.FilterType.ASYNC :
+ MessageFilterSettings.FilterType.SYNC;
+ messageFilterSettings.setFilterType(type);
+ // Custom server properties.
+ NodeList properties = selectNodeList(messageFilter, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(messageFilter));
+ messageFilterSettings.addProperties(map);
+ }
+ ((MessagingConfiguration)config).addMessageFilterSettings(messageFilterSettings);
+ }
+ else
+ {
+ // Class not specified for {FILTER_ELEMENT} '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{FILTER_ELEMENT, id});
+ throw ex;
+ }
+ }
+ }
+
+ private void validators(Node root)
+ {
+ Node validatorsNode = selectSingleNode(root, VALIDATORS_ELEMENT);
+ if (validatorsNode == null)
+ return;
+
+ // Validation
+ allowedChildElements(validatorsNode, VALIDATORS_CHILDREN);
+
+ // Validator
+ NodeList validators = selectNodeList(validatorsNode, VALIDATOR_ELEMENT);
+ for (int i = 0; i < validators.getLength(); i++)
+ {
+ Node validator = validators.item(i);
+ validator(validator);
+ }
+ }
+
+ private void validator(Node validator)
+ {
+ // Validation
+ requiredAttributesOrElements(validator, VALIDATOR_REQ_CHILDREN);
+ allowedAttributesOrElements(validator, VALIDATOR_CHILDREN);
+
+ ValidatorSettings validatorSettings = new ValidatorSettings();
+
+ // Validator class name
+ String className = getAttributeOrChildElement(validator, CLASS_ATTR);
+ if (className.length() > 0)
+ {
+ validatorSettings.setClassName(className);
+ }
+ else
+ {
+ // Class not specified for {VALIDATOR_ELEMENT} '{id}'.
+ ConfigurationException ex = new ConfigurationException();
+ ex.setMessage(CLASS_NOT_SPECIFIED, new Object[]{VALIDATOR_ELEMENT, ""});
+ throw ex;
+ }
+
+ // Validator type
+ String type = getAttributeOrChildElement(validator, TYPE_ATTR);
+ if (type.length() > 0)
+ validatorSettings.setType(type);
+
+ // Validator properties
+ NodeList properties = selectNodeList(validator, PROPERTIES_ELEMENT + "/*");
+ if (properties.getLength() > 0)
+ {
+ ConfigMap map = properties(properties, getSourceFileOf(validator));
+ validatorSettings.addProperties(map);
+ }
+
+ ((MessagingConfiguration)config).addValidatorSettings(validatorSettings);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/bf2e1dc9/core/src/flex/messaging/config/ServerSettings.java
----------------------------------------------------------------------
diff --git a/core/src/flex/messaging/config/ServerSettings.java b/core/src/flex/messaging/config/ServerSettings.java
new file mode 100644
index 0000000..77f61e9
--- /dev/null
+++ b/core/src/flex/messaging/config/ServerSettings.java
@@ -0,0 +1,231 @@
+/*
+ * 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.services.messaging.MessagingConstants;
+
+/**
+ * Server settings for a message destination.
+ */
+public class ServerSettings
+{
+ // Errors
+ private static final int INVALID_CLUSTER_MESSAGE_ROUTING = 11121;
+
+ private boolean allowSubtopics;
+ private boolean disallowWildcardSubtopics;
+ private long messageTTL = -1; //We need to keep track of uninitialized value
+ private boolean isDurable;
+ private int priority = -1;
+ private String subtopicSeparator;
+ private RoutingMode routingMode = RoutingMode.SERVER_TO_SERVER;
+
+ public static enum RoutingMode {NONE,BROADCAST,SERVER_TO_SERVER};
+
+ /**
+ * Creates a default <code>ServerSettings</code> instance.
+ */
+ public ServerSettings()
+ {
+ isDurable = false;
+ subtopicSeparator = MessagingConstants.DEFAULT_SUBTOPIC_SEPARATOR;
+ }
+
+ /**
+ * Returns <code>allow-subtopics</code> property.
+ *
+ * @return a boolean specifying whether or not the server has the <code>allow-subtopics</code> property.
+ */
+ public boolean getAllowSubtopics()
+ {
+ return allowSubtopics;
+ }
+
+ /**
+ * Sets <code>allow-subtopics</code> property.
+ *
+ * @param value The value for <code>allow-subtopics</code> property.
+ */
+ public void setAllowSubtopics(boolean value)
+ {
+ allowSubtopics = value;
+ }
+
+ /**
+ * Returns <code>cluster-message-routing</code> property.
+ *
+ * @return a boolean specifying whether or not the server has the <code>cluster-message-routing</code> property.
+ */
+ public boolean isBroadcastRoutingMode()
+ {
+ return routingMode == RoutingMode.BROADCAST;
+ }
+
+ /**
+ * Returns the routing mode configured.
+ *
+ * @return The configured routing mode.
+ */
+ public RoutingMode getRoutingMode()
+ {
+ return routingMode;
+ }
+
+ /**
+ * Sets the <code>cluster-message-routing</code> property.
+ *
+ * @param routingMode <code>server-to-server</code>(default)
+ * or <code>broadcast</code>.
+ */
+ public void setBroadcastRoutingMode(String routingMode)
+ {
+ if (routingMode.equalsIgnoreCase("broadcast"))
+ this.routingMode = RoutingMode.BROADCAST;
+ else if (routingMode.equalsIgnoreCase("server-to-server"))
+ this.routingMode = RoutingMode.SERVER_TO_SERVER;
+ else if (routingMode.equalsIgnoreCase("none"))
+ this.routingMode = RoutingMode.NONE;
+ else
+ {
+ ConfigurationException ce = new ConfigurationException();
+ ce.setMessage(INVALID_CLUSTER_MESSAGE_ROUTING, new Object[] {routingMode});
+ throw ce;
+ }
+ }
+
+ /**
+ * @deprecated Not used anymore.
+ */
+ public int getMaxCacheSize()
+ {
+ return 0;
+ }
+
+ /**
+ * @deprecated Not used anymore.
+ */
+ public void setMaxCacheSize(int size)
+ {
+ // No-op.
+ }
+
+ /**
+ * Returns the <code>message-time-to-live</code> property.
+ *
+ * @return the <code>message-time-to-live</code> property.
+ */
+ public long getMessageTTL()
+ {
+ return messageTTL;
+ }
+
+ /**
+ * Sets the <code>message-time-to-live</code> property. Default value is -1.
+ *
+ * @param ttl The value for <code>message-time-to-live</code> property.
+ */
+ public void setMessageTTL(long ttl)
+ {
+ messageTTL = ttl;
+ }
+
+ /**
+ * Returns true if wildcard subtopics are disallowed.
+ *
+ * @return true if wilcard subtopics are disallowed.
+ */
+ public boolean isDisallowWildcardSubtopics()
+ {
+ return disallowWildcardSubtopics;
+ }
+
+ /**
+ * Sets whether the wildcard subtopics are disallowed.
+ *
+ * @param value Whether the wildcard subtopics are disallowed.
+ */
+ public void setDisallowWildcardSubtopics(boolean value)
+ {
+ disallowWildcardSubtopics = value;
+ }
+
+ /**
+ * Returns whether destination is durable.
+ *
+ * @return <code>true</code> if destination is durable; otherwise <code>false</code>.
+ */
+ public boolean isDurable()
+ {
+ return isDurable;
+ }
+
+ /**
+ * Sets whether destination is durable. Default value is <code>false</code>.
+ *
+ * @param durable The value for <code>durable</code> property.
+ */
+ public void setDurable(boolean durable)
+ {
+ isDurable = durable;
+ }
+
+ /**
+ * Returns the default message priority for the destination which is a numerical
+ * value between 0 and 9 (and -1 means no default priority).
+ *
+ * @return The default message priority for the destination.
+ */
+ public int getPriority()
+ {
+ return priority;
+ }
+
+ /**
+ * Sets the default message priority of the destination which should be
+ * a numerical value between 0 and 9. Values less than 0 and greater than 9
+ * are treated as 0 and 9 respectively.
+ *
+ * @param priority The new value for the priority.
+ */
+ public void setPriority(int priority)
+ {
+ priority = priority < 0? 0 : priority > 9? 9 : priority;
+ this.priority = priority;
+ }
+
+
+ /**
+ * Returns the <code>subtopic-separator</code> property.
+ *
+ * @return the <code>subtopic-separator</code> property.
+ */
+ public String getSubtopicSeparator()
+ {
+ return subtopicSeparator;
+ }
+
+ /**
+ * Sets the <code>subtopic-separator</code> property.
+ * Optional; the default value is period.
+ *
+ * @param value The value for <code>subtopic-separator</code> property.
+ */
+ public void setSubtopicSeparator(String value)
+ {
+ subtopicSeparator = value;
+ }
+}