flex.messaging.config.ServerConfigurationParser Maven / Gradle / Ivy
/*
* 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.config.ThrottleSettings.Policy;
import flex.messaging.util.LocaleUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
/**
* Processes DOM representation of a messaging configuration file.
*
* Note: Since reference ids are used between elements, certain
* sections of the document need to be parsed first.
*
*/
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 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
{
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 (Object file : files) {
String src = (String) file;
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 (Object file : files) {
String src = (String) file;
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 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 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 (Object file : files) {
String src = (String) file;
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 (Object o : config.getDefaultChannels()) {
String channelId = (String) o;
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.
*
* <default-channels>
* <channel ref="channel-id"/>
* <default-channels>
*
*
* @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.
*
* <default-channels>
* <channel ref="channel-id"/>
* <default-channels>
*
*
* @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(true);
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 (Object file : files) {
String src = (String) file;
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 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 (Object file : files) {
String src = (String) file;
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 true|false 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();
for (Object defaultChannel : defaultChannels) {
ChannelSettings channel = (ChannelSettings) defaultChannel;
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 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 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);
if (validators.getLength() > 0) {
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);
}
}