diff options
Diffstat (limited to '')
-rw-r--r-- | sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms/src/main/java/org/apache/tuscany/sca/binding/jms/JMSBindingProcessor.java | 1706 |
1 files changed, 1706 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms/src/main/java/org/apache/tuscany/sca/binding/jms/JMSBindingProcessor.java b/sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms/src/main/java/org/apache/tuscany/sca/binding/jms/JMSBindingProcessor.java new file mode 100644 index 0000000000..97dfd5f4cf --- /dev/null +++ b/sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms/src/main/java/org/apache/tuscany/sca/binding/jms/JMSBindingProcessor.java @@ -0,0 +1,1706 @@ +/* + * 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 org.apache.tuscany.sca.binding.jms; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.OperationSelector; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.WireFormat; +import org.apache.tuscany.sca.assembly.xml.ConfiguredOperationProcessor; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.assembly.xml.PolicySubjectProcessor; +import org.apache.tuscany.sca.binding.jms.operationselector.OperationSelectorJMSDefault; +import org.apache.tuscany.sca.binding.jms.wireformat.WireFormatJMSDefault; +import org.apache.tuscany.sca.binding.jms.wireformat.WireFormatJMSObject; +import org.apache.tuscany.sca.binding.jms.wireformat.WireFormatJMSText; +import org.apache.tuscany.sca.binding.jms.wireformat.WireFormatJMSTextXML; +import org.apache.tuscany.sca.common.xml.stax.StAXHelper; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * A processor to read the XML that describes the JMS binding... + * + * <binding.jms correlationScheme="string"? + * initialContextFactory="xs:anyURI"? + * jndiURL="xs:anyURI"? + * requestConnection="QName"? + * responseConnection="QName"? + * operationProperties="QName"? + * ...> + * + * <headers type="string"? + * deliveryMode="string"? + * timeToLive="int"? + * priority="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </headers>? + * + * <destination jndiName="xs:anyURI" type="string"? create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </destination>? + * + * <connectionFactory jndiName="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </connectionFactory>? + * + * <activationSpec name="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </activationSpec>? + * + * <response> + * <destination jndiName="xs:anyURI" type="string"? create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </destination>? + * + * <connectionFactory jndiName="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </connectionFactory>? + * + * <activationSpec name="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </activationSpec>? + * + * <wireFormat.someWireFormat/>? + * </response>? + * + * <complexType name="SubscriptionHeaders"> + * <attribute name="JMSSelector" type="string"/> + * </complexType> + * + * <resourceAdapter name="NMTOKEN">? + * <property name="NMTOKEN" type="NMTOKEN">* + * </resourceAdapter>? + * + * <operationProperties name="string" selectedOperation="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * <headers type="string"? + * deliveryMode="string"? + * timeToLive="int"? + * priority="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </headers>? + * </operationProperties>* + * + * <wireFormat.someWireFormat/>? + * </binding.jms> + * + * Parsing error messages are recorded locally and reported as validation exceptions. Parsing + * warnings do not cause validation exceptions. + * + * @version $Rev$ $Date$ + */ + +public class JMSBindingProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<JMSBinding> { + private PolicyFactory policyFactory; + private PolicySubjectProcessor policyProcessor; + private ConfiguredOperationProcessor configuredOperationProcessor; + protected StAXArtifactProcessor<Object> extensionProcessor; + + public JMSBindingProcessor(FactoryExtensionPoint modelFactories, StAXArtifactProcessor<Object> extensionProcessor) { + this.policyFactory = modelFactories.getFactory(PolicyFactory.class); + this.policyProcessor = new PolicySubjectProcessor(policyFactory); + + this.configuredOperationProcessor = + new ConfiguredOperationProcessor(modelFactories); + this.extensionProcessor = extensionProcessor; + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void warning(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "binding-jms-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report an error. + * One side effect is that error messages are saved for future validation calls. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "binding-jms-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + public QName getArtifactType() { + return JMSBindingConstants.BINDING_JMS_QNAME; + } + + public Class<JMSBinding> getModelType() { + return JMSBinding.class; + } + + public JMSBinding read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + Monitor monitor = context.getMonitor(); + JMSBinding jmsBinding = new JMSBinding(); + // Reset validation message to keep track of validation issues. + + // Read policies + policyProcessor.readPolicies(jmsBinding, reader); + + // Read binding name + String name = reader.getAttributeValue(null, "name"); + if (name != null) { + jmsBinding.setName(name); + } + + // Read binding URI + String uri = reader.getAttributeValue(null, "uri"); + if (uri != null && uri.length() > 0) { + parseURI(uri, jmsBinding, monitor); + } + + // Read correlation scheme + QName correlationScheme = StAXHelper.getAttributeAsQName(reader, "correlationScheme"); + if (correlationScheme != null) { + if (Base.SCA11_NS.equals(correlationScheme.getNamespaceURI()) && JMSBindingConstants.VALID_CORRELATION_SCHEMES.contains(correlationScheme.getLocalPart())) { + jmsBinding.setCorrelationScheme(correlationScheme.getLocalPart()); + } else { + error(monitor, "InvalidCorrelationScheme", reader, correlationScheme); + } + } + + // Read initial context factory + String initialContextFactory = getURIString(reader, "initialContextFactory"); + if (initialContextFactory != null && initialContextFactory.length() > 0) { + jmsBinding.setInitialContextFactoryName(initialContextFactory); + } + + // Read JNDI URL + String jndiURL = getURIString(reader, "jndiURL"); + if (jndiURL != null && jndiURL.length() > 0) { + jmsBinding.setJndiURL(jndiURL); + } + + // Read message processor class name + // TODO - maintain this for the time being but move over to + // configuring wire formats instead of message processors + String messageProcessorName = reader.getAttributeValue(null, "messageProcessor"); + if (messageProcessorName != null && messageProcessorName.length() > 0) { + if ("XMLTextMessage".equalsIgnoreCase(messageProcessorName)) { + // may be overwritten be real wire format later + jmsBinding.setRequestWireFormat(new WireFormatJMSTextXML()); + jmsBinding.setResponseWireFormat(jmsBinding.getRequestWireFormat()); + } else if ("TextMessage".equalsIgnoreCase(messageProcessorName)) { + // may be overwritten be real wire format later + jmsBinding.setRequestWireFormat(new WireFormatJMSText()); + jmsBinding.setResponseWireFormat(jmsBinding.getRequestWireFormat()); + } else if ("ObjectMessage".equalsIgnoreCase(messageProcessorName)) { + // may be overwritten be real wire format later + jmsBinding.setRequestWireFormat(new WireFormatJMSObject()); + jmsBinding.setResponseWireFormat(jmsBinding.getRequestWireFormat()); + } else { + jmsBinding.setRequestMessageProcessorName(messageProcessorName); + jmsBinding.setResponseMessageProcessorName(messageProcessorName); + // exploit the text wire format code to drive the user selected + // message processor + jmsBinding.setRequestWireFormat(new WireFormatJMSText()); + jmsBinding.setResponseWireFormat(jmsBinding.getRequestWireFormat()); + } + } + + String requestConnectionName = reader.getAttributeValue(null, "requestConnection"); + if (requestConnectionName != null && requestConnectionName.length() > 0) { + jmsBinding.setRequestConnectionName(getQNameValue(reader, requestConnectionName)); + } + String responseConnectionName = reader.getAttributeValue(null, "responseConnection"); + if (responseConnectionName != null && responseConnectionName.length() > 0) { + jmsBinding.setResponseConnectionName(getQNameValue(reader, responseConnectionName)); + } + + String operationPropertiesName = reader.getAttributeValue(null, "operationProperties"); + if (operationPropertiesName != null && operationPropertiesName.length() > 0) { + jmsBinding.setOperationPropertiesName(getQNameValue(reader, operationPropertiesName)); + } + + // Read sub-elements of binding.jms + boolean endFound = false; + while (!endFound) { + int fg = reader.next(); + switch (fg) { + case START_ELEMENT: + String elementName = reader.getName().getLocalPart(); + if ("destination".equals(elementName)) { + parseDestination(reader, jmsBinding, monitor); + } else if ("connectionFactory".equals(elementName)) { + parseConnectionFactory(reader, jmsBinding, monitor); + } else if ("activationSpec".equals(elementName)) { + parseActivationSpec(reader, jmsBinding, monitor); + } else if ("response".equals(elementName)) { + parseResponse(reader, jmsBinding, context); + } else if ("resourceAdapter".equals(elementName)) { + parseResourceAdapter(reader, jmsBinding, monitor); + } else if ("headers".equals(elementName)) { + parseHeaders(reader, jmsBinding, monitor); + } else if ("operationProperties".equals(elementName)) { + parseOperationProperties(reader, jmsBinding, monitor); + } else if ("messageSelection".equals(elementName)) { + parseSubscriptionHeaders(reader, jmsBinding); + } else if (Constants.OPERATION_QNAME.equals(reader.getName())) { + ConfiguredOperation confOp = configuredOperationProcessor.read(reader, context); + if (confOp != null) { + ((OperationsConfigurator)jmsBinding).getConfiguredOperations().add(confOp); + } + } else { + Object extension = extensionProcessor.read(reader, context); + if (extension != null) { + if (extension instanceof WireFormat) { + if (jmsBinding.getRequestWireFormat() == null) { + jmsBinding.setRequestWireFormat((WireFormat) extension); + } else { + error(monitor, "WireFormatAlreadyDefined", reader, extension.toString()); + } + } else if (extension instanceof OperationSelector) { + if (jmsBinding.getOperationSelector() == null) { + jmsBinding.setOperationSelector((OperationSelector) extension); + } else { + error(monitor, "OpSelectorAlreadyDefined", reader, extension.toString()); + } + + } else { + error(monitor, "UnexpectedElement", reader, extension.toString()); + } + } + } + //reader.next(); + break; + case END_ELEMENT: + QName x = reader.getName(); + if (Constants.OPERATION.equals(x.getLocalPart())) break; + // This assumption is not captured in schema, which isn't good, but will probably be fine for now. + // A better solution might be to require each processor to advance to its own END_ELEMENT. + if (x.getLocalPart().startsWith("wireFormat.") || x.getLocalPart().startsWith("operationSelector.")) { + break; + } + if (x.equals(JMSBindingConstants.BINDING_JMS_QNAME)) { + endFound = true; + } else { + error(monitor, "UnexpectedElement: expected " + JMSBindingConstants.BINDING_JMS_QNAME + ", found " + x.toString(), + reader, x.toString()); + } + } + } + + // if no operation selector is specified then assume the default + if (jmsBinding.getOperationSelector() == null){ + jmsBinding.setOperationSelector(new OperationSelectorJMSDefault()); + } + + // if no request wire format specified then assume the default + if (jmsBinding.getRequestWireFormat() == null){ + jmsBinding.setRequestWireFormat(new WireFormatJMSDefault()); + } + + // if no response wire format specific then assume the same as the request + if (jmsBinding.getResponseWireFormat() == null){ + jmsBinding.setResponseWireFormat(jmsBinding.getRequestWireFormat()); + } + + validate( jmsBinding, monitor ); + + return jmsBinding; + } + + protected void parseURI(String uri, JMSBinding jmsBinding, Monitor monitor) { + if (!(uri.startsWith("jms:jndi:") || uri.startsWith("jms:queue:") || uri.startsWith("jms:topic:"))) { + error(monitor, "MustStartWithSchema", jmsBinding, uri); + return; + } + int i = uri.indexOf('?'); + if (i >= 0) { + StringTokenizer st = new StringTokenizer(uri.substring(i+1),"&"); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + if (s.startsWith("jndiConnectionFactoryName=")) { + jmsBinding.setConnectionFactoryName(s.substring(26)); + } else if (s.startsWith("deliveryMode=")) { + jmsBinding.setURIJMSDeliveryMode("persistent".equals(s.substring(13))); + } else if (s.startsWith("priority=")) { + jmsBinding.setURIJMSPriority(Integer.parseInt(s.substring(9))); + } else if (s.startsWith("timeToLive=")) { + jmsBinding.setURIJMSTimeToLive(Long.parseLong(s.substring(11))); + } else if (s.startsWith("selector='")) { + String selector = s.substring(10); + if (selector.startsWith("\"") || selector.startsWith("'")) { + selector = selector.substring(1, selector.length()); + } + if (selector.endsWith("\"") || selector.endsWith("'")) { + selector = selector.substring(0, selector.length() - 1); + } + jmsBinding.setURIJMSSelector(selector); + } else if (s.startsWith("type")) { + String type = s.substring(5); + jmsBinding.setJMSURIType(type); + } else { + error(monitor, "UnknownTokenInURI", jmsBinding, s, uri); + return; + } + } + int j=uri.indexOf(':', 4); + jmsBinding.setDestinationName(uri.substring(j+1, i)); + jmsBinding.setDestinationType(uri.substring(4, j)); + } else { + int j=uri.indexOf(':', 4); + jmsBinding.setDestinationName(uri.substring(j+1)); + jmsBinding.setDestinationType(uri.substring(4, j)); + } + jmsBinding.setJMSURI(uri); + } + + public void resolve(JMSBinding model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + if (model.getRequestConnectionName() != null) { + model.setRequestConnectionBinding(getConnectionBinding(model, "requestConnection", model.getRequestConnectionName(), resolver, context)); + } + if (model.getResponseConnectionName() != null) { + model.setResponseConnectionBinding(getConnectionBinding(model, "responseConnection", model.getResponseConnectionName(), resolver, context)); + } + if (model.getOperationPropertiesName() != null) { + model.setOperationPropertiesBinding(getConnectionBinding(model, "operationProperties", model.getOperationPropertiesName(), resolver, context)); + } + } + + private JMSBinding getConnectionBinding(JMSBinding model, String attrName, QName bindingName, ModelResolver resolver, ProcessorContext context) { + JMSBinding binding = new JMSBinding(); + binding.setTargetNamespace(bindingName.getNamespaceURI()); + binding.setName(bindingName.getLocalPart()); + binding.setUnresolved(true); + binding = resolver.resolveModel(JMSBinding.class, binding, context); + if (binding.isUnresolved()) + error(context.getMonitor(), "BindingNotFound", model, attrName, bindingName); + return binding; + } + + private void parseDestination(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + jmsBinding.setIsDestinationSpecified(true); + String name = getURIString(reader, "jndiName"); + if (name != null && name.length() > 0) { + jmsBinding.setDestinationName(name); + } + + String type = reader.getAttributeValue(null, "type"); + if (type != null && type.length() > 0) { + if (JMSBindingConstants.DESTINATION_TYPE_QUEUE.equalsIgnoreCase(type)) { + jmsBinding.setDestinationType(JMSBindingConstants.DESTINATION_TYPE_QUEUE); + } else if (JMSBindingConstants.DESTINATION_TYPE_TOPIC.equalsIgnoreCase(type)) { + jmsBinding.setDestinationType(JMSBindingConstants.DESTINATION_TYPE_TOPIC); + } else { + error(monitor, "InvalidDestinationType", reader, type); + } + } + + String create = reader.getAttributeValue(null, "create"); + if (create != null && create.length() > 0) { + validateCreate(create, reader, monitor); + jmsBinding.setDestinationCreate(create); + } + + jmsBinding.getDestinationProperties().putAll(parseBindingProperties(reader, monitor)); + + if (jmsBinding.getDestinationCreate().equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_IF_NOT_EXIST", reader); + } + } + if (jmsBinding.getDestinationCreate().equals(JMSBindingConstants.CREATE_NEVER)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_NEVER", reader); + } + } + } + + private void parseConnectionFactory(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String name = getURIString(reader, "jndiName"); + if (name != null && name.length() > 0) { + jmsBinding.setConnectionFactoryName(name); + } else { + error(monitor, "MissingConnectionFactoryName", reader); + } + + String create = reader.getAttributeValue(null, "create"); + if (create != null && create.length() > 0) { + validateCreate(create, reader, monitor); + jmsBinding.setConnectionFactoryCreate(create); + } + if (jmsBinding.getConnectionFactoryCreate().equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_IF_NOT_EXIST", reader); + } + } + if (jmsBinding.getConnectionFactoryCreate().equals(JMSBindingConstants.CREATE_NEVER)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_NEVER", reader); + } + } + + jmsBinding.getConnectionFactoryProperties().putAll(parseBindingProperties(reader, monitor)); + } + + private void parseActivationSpec(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String name = reader.getAttributeValue(null, "jndiName"); + if (name != null && name.length() > 0) { + jmsBinding.setActivationSpecName(name); + } + + String create = reader.getAttributeValue(null, "create"); + if (create != null && create.length() > 0) { + validateCreate(create, reader, monitor); + jmsBinding.setActivationSpecCreate(create); + } + if (jmsBinding.getActivationSpecCreate().equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_IF_NOT_EXIST", reader); + } + } + if (jmsBinding.getActivationSpecCreate().equals(JMSBindingConstants.CREATE_NEVER)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_NEVER", reader); + } + } + + jmsBinding.getActivationSpecProperties().putAll(parseBindingProperties(reader, monitor)); + } + + private void parseResponseDestination(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String name = getURIString(reader, "jndiName"); + if (name != null && name.length() > 0) { + jmsBinding.setResponseDestinationName(name); + } + + String type = reader.getAttributeValue(null, "type"); + if (type != null && type.length() > 0) { + warning(monitor, "DoesntProcessResponseDestinationType", jmsBinding); + if (JMSBindingConstants.DESTINATION_TYPE_QUEUE.equalsIgnoreCase(type)) { + jmsBinding.setResponseDestinationType(JMSBindingConstants.DESTINATION_TYPE_QUEUE); + } else if (JMSBindingConstants.DESTINATION_TYPE_TOPIC.equalsIgnoreCase(type)) { + jmsBinding.setResponseDestinationType(JMSBindingConstants.DESTINATION_TYPE_TOPIC); + } else { + error(monitor, "InvalidResponseDestinationType", reader, type); + } + } + + String create = reader.getAttributeValue(null, "create"); + if (create != null && create.length() > 0) { + validateCreate(create, reader, monitor); + jmsBinding.setResponseDestinationCreate(create); + } + if (jmsBinding.getResponseDestinationCreate().equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_IF_NOT_EXIST", reader); + } + } + if (jmsBinding.getResponseDestinationCreate().equals(JMSBindingConstants.CREATE_NEVER)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_NEVER", reader); + } + } + + jmsBinding.getResponseDestinationProperties().putAll(parseBindingProperties(reader, monitor)); + } + + private void parseResponseConnectionFactory(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String name = getURIString(reader, "jndiName"); + if (name != null && name.length() > 0) { + jmsBinding.setResponseConnectionFactoryName(name); + } else { + warning(monitor, "MissingResponseConnectionFactory", reader); + } + String create = reader.getAttributeValue(null, "create"); + if (create != null && create.length() > 0) { + validateCreate(create, reader, monitor); + jmsBinding.setResponseConnectionFactoryCreate(create); + } + if (jmsBinding.getResponseConnectionFactoryCreate().equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_IF_NOT_EXIST", reader); + } + } + if (jmsBinding.getResponseConnectionFactoryCreate().equals(JMSBindingConstants.CREATE_NEVER)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_NEVER", reader); + } + } + jmsBinding.getResponseConnectionFactoryProperties().putAll(parseBindingProperties(reader, monitor)); + } + + private void parseResponseActivationSpec(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String name = reader.getAttributeValue(null, "jndiName"); + if (name != null && name.length() > 0) { + jmsBinding.setResponseActivationSpecName(name); + } + String create = reader.getAttributeValue(null, "create"); + if (create != null && create.length() > 0) { + validateCreate(create, reader, monitor); + jmsBinding.setResponseActivationSpecCreate(create); + } + if (jmsBinding.getResponseActivationSpecCreate().equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_IF_NOT_EXIST", reader); + } + } + if (jmsBinding.getResponseActivationSpecCreate().equals(JMSBindingConstants.CREATE_NEVER)) { + if (name == null || name.length() < 1) { + error(monitor, "MissingNameForCREATE_NEVER", reader); + } + } + jmsBinding.getResponseActivationSpecProperties().putAll(parseBindingProperties(reader, monitor)); + } + + private void validateCreate(String create, XMLStreamReader reader, Monitor monitor) { + if (JMSBindingConstants.CREATE_ALWAYS.equals(create)) { + return; + } + if (JMSBindingConstants.CREATE_NEVER.equals(create)) { + return; + } + if (JMSBindingConstants.CREATE_IF_NOT_EXIST.equals(create)) { + return; + } + error(monitor, "InvalidCreate", reader, create); + } + + private void parseResponse(XMLStreamReader reader, JMSBinding jmsBinding, ProcessorContext context) throws ContributionReadException, XMLStreamException { + // Read sub-elements of response + Monitor monitor = context.getMonitor(); + while (true) { + switch (reader.next()) { + case START_ELEMENT: + String elementName = reader.getName().getLocalPart(); + if ("destination".equals(elementName)) { + parseResponseDestination(reader, jmsBinding, context.getMonitor()); + } else if ("connectionFactory".equals(elementName)) { + parseResponseConnectionFactory(reader, jmsBinding, monitor); + } else if ("activationSpec".equals(elementName)) { + parseResponseActivationSpec(reader, jmsBinding, monitor); + } else { + Object extension = extensionProcessor.read(reader, context); + if (extension != null) { + if (extension instanceof WireFormat) { + if (jmsBinding.getResponseWireFormat() == null) { + jmsBinding.setResponseWireFormat((WireFormat)extension); + } else { + error(context.getMonitor(), "ResponseWireformatAlreadyDefined", reader, extension.toString()); + } + } else { + error(context.getMonitor(), "UnexpectedElement", reader, extension.toString()); + } + } + reader.next(); + } + //reader.next(); + break; + case END_ELEMENT: + QName x = reader.getName(); + if (x.getLocalPart().equals("response")) { + return; + } else { + error(context.getMonitor(), "UnexpectedResponseElement", reader, x.toString()); + } + } + } + } + + private void parseResourceAdapter(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String name = reader.getAttributeValue(null, "name"); + if (name != null && name.length() > 0) { + jmsBinding.setResourceAdapterName(name); + } else { + error(monitor, "MissingResourceAdapterName", reader); + } + jmsBinding.getResourceAdapterProperties().putAll(parseBindingProperties(reader, monitor)); + } + + /** + * <headers JMSType="string"? + * JMSCorrelationID="string"? + * JMSDeliveryMode="PERSISTENT or NON_PERSISTENT"? + * timeToLive="long"? + * JMSPriority="0 .. 9"?> + * <property name="NMTOKEN" type="NMTOKEN"?>* + * </headers>? + */ + private void parseHeaders(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + String jmsType = reader.getAttributeValue(null, "type"); + if (jmsType != null && jmsType.length() > 0) { + jmsBinding.setJMSHeaderType(jmsType); + } + + String jmsDeliveryMode = reader.getAttributeValue(null, "deliveryMode"); + if (jmsDeliveryMode != null && jmsDeliveryMode.length() > 0) { + if ("persistent".equalsIgnoreCase(jmsDeliveryMode)) { + jmsBinding.setJMSHeaderDeliveryMode(true); + } else if ("nonpersistent".equalsIgnoreCase(jmsDeliveryMode)) { + jmsBinding.setJMSHeaderDeliveryMode(false); + } else { + error(monitor, "InvalidJMSDeliveryMode", jmsBinding, jmsDeliveryMode); + } + } + + String jmsTimeToLive = reader.getAttributeValue(null, "timeToLive"); + if (jmsTimeToLive != null && jmsTimeToLive.length() > 0) { + jmsBinding.setJMSHeaderTimeToLive(Long.parseLong(jmsTimeToLive)); + } + + String jmsPriority = reader.getAttributeValue(null, "priority"); + if (jmsPriority != null && jmsPriority.length() > 0) { + try { + int p = Integer.parseInt(jmsPriority); + if (p >= 0 && p <= 9) { + jmsBinding.setJMSHeaderPriority(p); + } else { + warning(monitor, "InvalidJMSPriority", jmsBinding, jmsPriority); + } + } catch (NumberFormatException ex) { + error(monitor, "InvalidJMSPriority", jmsBinding, jmsPriority); + } + } + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + if (reader.getName().getLocalPart().equals("property")) { + parseProperty(reader, jmsBinding); + } + break; + case END_ELEMENT: + QName x = reader.getName(); + if (x.getLocalPart().equals("headers")) { + return; + } else { + error(monitor, "UnexpectedResponseElement", reader, x.toString()); + } + } + } + } + + private void parseProperty(XMLStreamReader reader, JMSBinding jmsBinding) throws XMLStreamException { + jmsBinding.setHeaders( true ); + String name = reader.getAttributeValue(null, "name"); + QName typeName = StAXHelper.getAttributeAsQName(reader, "type"); + String type = typeName == null ? null : typeName.getLocalPart(); + + if (name != null && name.length() > 0) { + Object value = reader.getElementText(); + + if ("boolean".equalsIgnoreCase(type)) { + value = Boolean.parseBoolean((String)value); + } else if ("byte".equalsIgnoreCase(type)) { + value = Byte.parseByte(((String)value)); + } else if ("short".equalsIgnoreCase(type)) { + value = Short.parseShort((String)value); + } else if ("int".equalsIgnoreCase(type)) { + value = Integer.parseInt((String)value); + } else if ("long".equalsIgnoreCase(type)) { + value = Long.parseLong((String)value); + } else if ("float".equalsIgnoreCase(type)) { + value = Float.parseFloat((String)value); + } else if ("double".equalsIgnoreCase(type)) { + value = Double.parseDouble((String)value); + } else if ("String".equalsIgnoreCase(type)) { + // its already a string + } + jmsBinding.setProperty(name, value); + } + } + + /** + * <operationProperties name="string" selectedOperation="string"?> + * <property name="NMTOKEN" type="NMTOKEN"?>* + * <headers JMSType="string"? + * JMSCorrelationID="string"? + * JMSDeliveryMode="PERSISTENT or NON_PERSISTENT"? + * timeToLive="long"? + * JMSPriority="0 .. 9"?> + * <property name="NMTOKEN" type="NMTOKEN"?>* + * </headers>? + * </operationProperties>* + */ + private void parseOperationProperties(XMLStreamReader reader, JMSBinding jmsBinding, Monitor monitor) throws XMLStreamException { + + if (jmsBinding.getOperationPropertiesName() != null) { + error(monitor, "DuplicateOperationProperties", jmsBinding); + } + + String opName = reader.getAttributeValue(null, "name"); + if (opName == null || opName.length() < 1) { + error(monitor, "MissingJMSOperationPropertyName", jmsBinding); + return; + } + // Since nativeOpName, headers, and property elements are optional, must add opName. + jmsBinding.addOperationName(opName); + String nativeOpName = reader.getAttributeValue(null, "selectedOperation"); // optional + if (nativeOpName != null && nativeOpName.length() > 0) { + jmsBinding.setNativeOperationName(opName, nativeOpName); + } + + Map<String, BindingProperty> props = new HashMap<String, BindingProperty>(); + while (true) { + switch (reader.next()) { + case START_ELEMENT: + if (reader.getName().getLocalPart().equals("headers")) { // optional + parseOperationHeaders(reader, jmsBinding, opName, monitor); + } else if (reader.getName().getLocalPart().equals("property")) { // optional + processProperty(reader, props, monitor); + } + break; + case END_ELEMENT: + if (reader.isEndElement()) { + QName x = reader.getName(); + if (x.getLocalPart().equals("headers")) { + break; + } + if (x.getLocalPart().equals("property")) { + break; + } + if (x.getLocalPart().equals("operationProperties")) { + jmsBinding.getOperationPropertiesProperties(opName).putAll(props); + return; + } else { + error(monitor, "UnexpectedResponseElement", reader, x.toString()); + } + } + } + } + } + + private void parseOperationHeaders(XMLStreamReader reader, JMSBinding jmsBinding, String opName, Monitor monitor) throws XMLStreamException { + String jmsType = reader.getAttributeValue(null, "type"); + if (jmsType != null && jmsType.length() > 0) { + jmsBinding.setOperationJMSType(opName, jmsType); + } + + String jmsDeliveryMode = reader.getAttributeValue(null, "deliveryMode"); + if (jmsDeliveryMode != null && jmsDeliveryMode.length() > 0) { + if ("persistent".equalsIgnoreCase(jmsDeliveryMode)) { + jmsBinding.setOperationJMSDeliveryMode(opName, true); + } else if ("nonpersistent".equalsIgnoreCase(jmsDeliveryMode)) { + jmsBinding.setOperationJMSDeliveryMode(opName, false); + } else { + error(monitor, "InvalidOPJMSDeliveryMode", jmsBinding, jmsDeliveryMode); + } + } + + String jmsTimeToLive = reader.getAttributeValue(null, "timeToLive"); + if (jmsTimeToLive != null && jmsTimeToLive.length() > 0) { + jmsBinding.setOperationJMSTimeToLive(opName, Long.parseLong(jmsTimeToLive)); + } + + String jmsPriority = reader.getAttributeValue(null, "priority"); + if (jmsPriority != null && jmsPriority.length() > 0) { + try { + int p = Integer.parseInt(jmsPriority); + if (p >= 0 && p <= 9) { + jmsBinding.setOperationJMSPriority(opName, p); + } else { + warning(monitor, "InvalidOPJMSPriority", jmsBinding, jmsPriority); + } + } catch (NumberFormatException ex) { + error(monitor, "InvalidOPJMSPriority", jmsBinding, jmsPriority); + } + } + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + if (reader.getName().getLocalPart().equals("property")) { + parseOperationPropertyProperties(reader, jmsBinding, opName); + } + break; + case END_ELEMENT: + QName x = reader.getName(); + if (x.getLocalPart().equals("headers")) { + return; + } else { + error(monitor, "UnexpectedResponseElement", reader, x.toString()); + } + } + } + } + + private void parseOperationPropertyProperties(XMLStreamReader reader, JMSBinding jmsBinding, String opName) throws XMLStreamException { + String propName = reader.getAttributeValue(null, "name"); + QName typeName = StAXHelper.getAttributeAsQName(reader, "type"); + String type = typeName == null ? null : typeName.getLocalPart(); + if (propName != null && propName.length() > 0) { + Object value = reader.getElementText(); + if ("boolean".equalsIgnoreCase(type)) { + value = Boolean.parseBoolean((String)value); + } else if ("byte".equalsIgnoreCase(type)) { + value = Byte.parseByte(((String)value)); + } else if ("short".equalsIgnoreCase(type)) { + value = Short.parseShort((String)value); + } else if ("int".equalsIgnoreCase(type)) { + value = Integer.parseInt((String)value); + } else if ("long".equalsIgnoreCase(type)) { + value = Long.parseLong((String)value); + } else if ("float".equalsIgnoreCase(type)) { + value = Float.parseFloat((String)value); + } else if ("double".equalsIgnoreCase(type)) { + value = Double.parseDouble((String)value); + } else if ("String".equalsIgnoreCase(type)) { + // its already a string + } + jmsBinding.setOperationProperty(opName, propName, value); + } + } + + private void parseSubscriptionHeaders(XMLStreamReader reader, JMSBinding jmsBinding) throws XMLStreamException { + String jmsSelector = reader.getAttributeValue(null, "selector"); + if (jmsSelector != null && jmsSelector.length() > 0 && jmsBinding.getJMSSelector() == null) { + jmsBinding.setJMSSelector(jmsSelector); + } + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && "messageSelection".equals(reader.getName().getLocalPart())) { + break; + } + } // end while + } + + private Map<String, BindingProperty> parseBindingProperties(XMLStreamReader reader, Monitor monitor) throws XMLStreamException { + Map<String, BindingProperty> props = new HashMap<String, BindingProperty>(); + String parentName = reader.getName().getLocalPart(); + // Parse for all the properties within this element, until the end of + // the element is reached. + boolean completed = false; + while (!completed) { + switch (reader.next()) { + case START_ELEMENT: + String elementName = reader.getName().getLocalPart(); + if ("property".equals(elementName)) { + processProperty(reader, props, monitor); + } + break; + case END_ELEMENT: + String endName = reader.getName().getLocalPart(); + if (parentName.equals(endName)) { + completed = true; + break; + } + } + } + return props; + } + + private void processProperty(XMLStreamReader reader, Map<String, BindingProperty> props, Monitor monitor) throws XMLStreamException { + String name = reader.getAttributeValue(null, "name"); + if (name == null || name.length() < 1) { + error(monitor, "InvalidPropertyElement", reader); + } + String type = reader.getAttributeValue(null, "type"); + String value = reader.getElementText(); + props.put(name, new BindingProperty(name, type, value)); + } + + /** + * Preserve an existing public method. The method validate() is a legacy method + * that was called from reading am XML stream via the read(XMLStreamReader) method above. + * However read(XMLStreamReader) now calls validate(JMSBinding jmsBinding) and + * passes in the jmsBinding model. + * The older validate() now calls validate(JMSBinding jmsBinding) with a null model. + */ + public void validate() { + validate( null, null ); + } + + /** + * Validates JMS parsing and JMSBinding model. + * Validation rules are taken from the binding schema and the OSOA and OASIS specs: + * http://www.oasis-open.org/committees/documents.php?wg_abbrev=sca-bindings + * (sca-binding-jms-1.1-spec-cd01-rev4.pdf) + * http://www.osoa.org/display/Main/Service+Component+Architecture+Specifications + * (SCA JMS Binding V1.00 ) + * @param jmsBinding an optional JMS binding model to check for validity. + * @since 1.4 + */ + protected void validate( JMSBinding jmsBinding, Monitor monitor ) { + // If no JMSBinding model is provided, that is all the validation we can do. + if ( jmsBinding == null ) { + return; + } + + // Connection factory should not contradict destination type. + String connectionFactoryName = jmsBinding.getConnectionFactoryName(); + if (( connectionFactoryName != null ) && ( connectionFactoryName.length() > 0 )) { + if (JMSBindingConstants.DESTINATION_TYPE_QUEUE == jmsBinding.getDestinationType()) { + if ( connectionFactoryName.contains( "topic" )) { + error(monitor, "DestinationQueueContradiction", jmsBinding, connectionFactoryName ); + } + } + if (JMSBindingConstants.DESTINATION_TYPE_TOPIC == jmsBinding.getDestinationType()) { + if ( connectionFactoryName.contains( "queue" )) { + error(monitor, "DestinationTopicContradiction", jmsBinding, connectionFactoryName ); + } + } + } + + // Connection factory and activation Specification are mutually exclusive. + if (( connectionFactoryName != null ) && ( connectionFactoryName.length() > 0 )) { + String activationSpecName = jmsBinding.getActivationSpecName(); + if ((activationSpecName != null) && (activationSpecName.length() > 0 )) { + error(monitor, "ConnectionFactoryActivationSpecContradiction", jmsBinding, connectionFactoryName, activationSpecName ); + } + } + + // If URI is specified, destination should not be present + if ( ( jmsBinding.getJMSURI() != null ) && ( jmsBinding.getJMSURI().length() > 0) && + (jmsBinding.isDestinationSpecified())) { + error(monitor, "DestinationURIContradiction", jmsBinding, jmsBinding.getJMSURI(), jmsBinding.getDestinationName()); + } + + // If activation spec and destination are both specified, they have to match + if ( ( jmsBinding.getActivationSpecName() != null ) && (jmsBinding.getActivationSpecName().length() > 0 ) && + (jmsBinding.getDestinationName() != null) && (jmsBinding.getDestinationName().length() > 0 ) ) { + if ( !jmsBinding.getActivationSpecName().equals(jmsBinding.getDestinationName())) { + error(monitor, "ActivationSpecAndDestinationMismatch", jmsBinding, jmsBinding.getActivationSpecName(), jmsBinding.getDestinationName()); + } + } + + if ( ( jmsBinding.getResponseActivationSpecName() != null ) && (jmsBinding.getResponseActivationSpecName().length() > 0 ) && + (jmsBinding.getResponseDestinationName() != null ) && (jmsBinding.getResponseDestinationName().length() > 0 ) ) { + if ( !jmsBinding.getResponseActivationSpecName().equals(jmsBinding.getResponseDestinationName())) { + error(monitor, "ActivationSpecAndDestinationMismatch", jmsBinding, jmsBinding.getResponseActivationSpecName(), jmsBinding.getResponseDestinationName()); + } + } + // If activation spec exists with create=always, a jndiName must be specified + if (JMSBindingConstants.CREATE_ALWAYS.equals(jmsBinding.getActivationSpecCreate()) && + (jmsBinding.getActivationSpecName() == null)) { + error(monitor, "ActivationSpecNameRequiredForCreateAlways", jmsBinding); + } + // If Connection factory specified then destination name must also be + if (( connectionFactoryName != null ) && ( connectionFactoryName.length() > 0 )) { + String destinationName = jmsBinding.getDestinationName(); + if ((destinationName == null) || (destinationName.length() < 1 )) { + error(monitor, "ConnectionFactoryDestinationContradiction", jmsBinding, connectionFactoryName); + } + } + + // Given a response connection name attribute, there must not be a response element. + // 156 /binding.jms/@responseConnection - identifies a binding.jms element that is present in a + // 157 definition document, whose response child element is used to define the values for this binding. In + // 158 this case this binding.jms element MUST NOT contain a response element. + QName responseConnectionName = jmsBinding.getResponseConnectionName(); + if (( responseConnectionName != null ) && ( responseConnectionName.getLocalPart().length() > 0 )) { + String responseDestinationName = jmsBinding.getResponseDestinationName(); + if (( responseDestinationName != null ) && (responseDestinationName.length() > 0)) { + error(monitor, "ResponseAttrElement", jmsBinding, responseConnectionName, responseDestinationName ); + } + } + + // [BJM30029] The value of the operationProperties/@selectedOperation attribute MUST be unique across the containing binding.jms element + Set<String> ops = new HashSet<String>(jmsBinding.getNativeOperationNames().values()); + if (ops.size() != jmsBinding.getNativeOperationNames().values().size()) { + error(monitor, "BJM30029", jmsBinding); + } + + + // Other jmsBinding model validation may be added here. + + } + + /** + * Given a valid JMSBinding, write it as XML using the given XML writer. + * + * This high-level method handles binding.jms element and its attributes. + * Sub elements have their own writer methods and are called from here. + * <binding.jms + * correlationScheme="string"? + * initialContextFactory="xs:anyURI"? + * jndiURL="xs:anyURI"? + * requestConnection="QName"? + * responseConnection="QName"? + * operationProperties="QName"? + * ...> + * @param writer an XMLStreamWriter that writes XML attributes and elements + * @param jmsBinding JMSBinding model + */ + public void write(JMSBinding jmsBinding, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, + XMLStreamException { + // Write a <binding.jms> + writeStart(writer, Constants.SCA11_NS, JMSBindingConstants.BINDING_JMS, + new XAttr("requestConnection", jmsBinding.getRequestConnectionName()), + new XAttr("responseConnection", jmsBinding.getResponseConnectionName()), + new XAttr("operationProperties", jmsBinding.getOperationPropertiesName())); + + if (jmsBinding.getName() != null) { + writer.writeAttribute("name", jmsBinding.getName()); + } + + if (jmsBinding.getJMSURI() != null) { + writer.writeAttribute("uri", jmsBinding.getJMSURI()); + writeEnd(writer); + return; + } + + //String dest = jmsBinding.getDestinationName(); + //if (dest != null) { + // if ( dest != null ) { + // writer.writeAttribute("uri", "jms:" + jmsBinding.getDestinationName()); + // } + //} + + String correlationScheme = jmsBinding.getCorrelationScheme(); + if ( correlationScheme != null ) { + if ( !correlationScheme.equals(JMSBindingConstants.CORRELATE_MSG_ID) ) { + writer.writeAttribute("correlationScheme", jmsBinding.getCorrelationScheme()); + } + } + + if ( jmsBinding.getInitialContextFactoryName() != null ) { + writer.writeAttribute("initialContextFactory", jmsBinding.getInitialContextFactoryName()); + } + + if ( jmsBinding.getJndiURL() != null ) { + writer.writeAttribute("jndiURL", jmsBinding.getJndiURL()); + } + + if ( jmsBinding.containsHeaders() ) { + writeHeaders( jmsBinding, writer); + } + + writeOperationProperties( jmsBinding, writer ); + + writeSubscriptionHeaders( jmsBinding, writer ); + + writeDestinationProperties( jmsBinding, writer ); + + writeConnectionFactoryProperties( jmsBinding, writer ); + + writeActivationSpecProperties( jmsBinding, writer ); + + // Write response info, if names are not defaults. + String responseDestName = jmsBinding.getResponseDestinationName(); + String responseCFName = jmsBinding.getResponseConnectionFactoryName(); + String responseASName = jmsBinding.getResponseActivationSpecName(); + if ( responseDestName != null || + responseCFName != null || + responseASName != null ) { + + writer.writeStartElement(Constants.SCA11_NS, "response"); + writeResponseDestinationProperties( jmsBinding, writer ); + writeResponseConnectionFactoryProperties( jmsBinding, writer ); + writeResponseActivationSpecProperties( jmsBinding, writer ); + + if ((jmsBinding.getResponseWireFormat() != null) && + !(jmsBinding.getResponseWireFormat() instanceof WireFormatJMSDefault)){ + writeWireFormat(jmsBinding.getResponseWireFormat(), writer, context); + } + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters( " " ); + } + + writeResourceAdapterProperties( jmsBinding, writer ); + + writeConfiguredOperations( jmsBinding, writer, context ); + + if ((jmsBinding.getRequestWireFormat() != null) && + !(jmsBinding.getRequestWireFormat() instanceof WireFormatJMSDefault)){ + writeWireFormat(jmsBinding.getRequestWireFormat(), writer, context); + } + + if ((jmsBinding.getOperationSelector() != null) && + !(jmsBinding.getOperationSelector() instanceof OperationSelectorJMSDefault)){ + writeOperationSelector(jmsBinding.getOperationSelector(), writer, context); + } + + writeEnd(writer); + } + + /** + * Writes headers element and its attributes. + * <headers JMSType="string"? + * JMSCorrelationID="string"? + * JMSDeliveryMode="PERSISTENT or NON_PERSISTENT"? + * timeToLive="long"? + * JMSPriority="0 .. 9"?> + * <property name="NMTOKEN" type="NMTOKEN"?>* + * </headers>? + */ + private void writeHeaders( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + + writer.writeStartElement(Constants.SCA11_NS, JMSBindingConstants.HEADERS); + + String jmsType = jmsBinding.getJMSHeaderType(); + if (jmsType != null && jmsType.length() > 0) { + writer.writeAttribute("type", jmsType); + } + + Boolean jmsDeliveryMode = jmsBinding.isHeaderDeliveryModePersistent(); + if (jmsDeliveryMode != null) { + if ( jmsDeliveryMode.booleanValue() ) + writer.writeAttribute("deliveryMode", "persistent"); + else + writer.writeAttribute("deliveryMode", "nonpersistent"); + } + + Long jmsTimeToLive = jmsBinding.getJMSHeaderTimeToLive(); + if (jmsTimeToLive != null) { + writer.writeAttribute("timeToLive", jmsTimeToLive.toString()); + } + + Integer jmsPriority = jmsBinding.getJMSHeaderPriority(); + if (jmsPriority != null) { + writer.writeAttribute("priority", jmsPriority.toString()); + } + + Map<String, Object> properties = jmsBinding.getProperties(); + writeProperties( properties, writer ); + //writer.writeCharacters( " " ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters( " " ); + } + + /** + * Writes a complete set of properties to the given XML stream writer. + * If the value is of type string, the property will be output: + * <property name="key">StringValue</property> + * If the value is of type box (e.g.Integer, Long) or BindingProperty, the output will be + * <property name="key" type="int">42</property> + */ + @SuppressWarnings("unchecked") + private void writeProperties(Map<String, Object> properties, XMLStreamWriter writer) throws XMLStreamException { + if (( properties == null ) || ( properties.size() == 0 )) { + return; + } + + // For both the keys and values of a map + for (Iterator it=properties.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = (Map.Entry)it.next(); + Object key = entry.getKey(); + Object value = entry.getValue(); + + writer.writeStartElement(Constants.SCA11_NS, "property" ); + writer.writeAttribute("name", key.toString()); + + if ( value instanceof String) { + writer.writeCharacters( value.toString() ); + } else if ( value instanceof BindingProperty ) { + BindingProperty property = (BindingProperty) value; + String type = property.getType(); + if ( type != null ) { + writer.writeAttribute("type", type); + } + writer.writeCharacters( property.getValue().toString() ); + } else if ( value instanceof Boolean ) { + writer.writeAttribute("type", "boolean"); + writer.writeCharacters( value.toString() ); + } else if ( value instanceof Byte ) { + writer.writeAttribute("type", "byte"); + writer.writeCharacters( value.toString() ); + } else if ( value instanceof Short ) { + writer.writeAttribute("type", "short"); + writer.writeCharacters( value.toString() ); + } else if ( value instanceof Integer ) { + writer.writeAttribute("type", "int"); + writer.writeCharacters( value.toString() ); + } else if ( value instanceof Long ) { + writer.writeAttribute("type", "long"); + writer.writeCharacters( value.toString() ); + } else if ( value instanceof Float ) { + writer.writeAttribute("type", "float"); + writer.writeCharacters( value.toString() ); + } else if ( value instanceof Double ) { + writer.writeAttribute("type", "double"); + writer.writeCharacters( value.toString() ); + } else { + writer.writeCharacters( value.toString() ); + } + writer.writeEndElement(); + } + } + + /** + * Writes operation properties if there are any. + * + * <operationProperties name="string" selectedOperation="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * <headers JMSType="string"? + * JMSCorrelationID="string"? + * JMSDeliveryMode="string"? + * timeToLive="int"? + * JMSPriority="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </headers>? + * </operationProperties>* + * </binding.jms> + */ + private void writeOperationProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + if (jmsBinding.getOperationPropertiesBinding() != null) { + return; + } + Set<String> operationNames = jmsBinding.getOperationNames(); + if (operationNames == null || (operationNames.size() < 1)) { + return; + } + + for(Iterator<String> it=operationNames.iterator(); it.hasNext(); ) { + String opName = it.next(); + + writer.writeStartElement(Constants.SCA11_NS, "operationProperties"); + writer.writeAttribute("name", opName); + + String nativeOperation = jmsBinding.getNativeOperationName(opName); + if (nativeOperation != null && nativeOperation.length() > 0) { + if ( !nativeOperation.equals( opName )) { + writer.writeAttribute("selectedOperation", nativeOperation); + } + } + + Map<String, BindingProperty> operationPropertiesProperties = + jmsBinding.getOperationPropertiesProperties(opName); + writeBindingProperties( operationPropertiesProperties, writer ); + + String jmsType = jmsBinding.getOperationJMSType(opName); + String jmsCorrelationId = jmsBinding.getOperationJMSCorrelationId(opName); + Boolean jmsDeliveryMode = jmsBinding.getOperationJMSDeliveryMode(opName); + Long jmsTimeToLive = jmsBinding.getOperationJMSTimeToLive(opName); + Integer jmsPriority = jmsBinding.getOperationJMSPriority(opName); + Map<String, Object> operationProperties = jmsBinding.getOperationProperties(opName); + + if (operationProperties != null){ + if ((jmsType != null && jmsType.length() > 0) || + (jmsCorrelationId != null && jmsCorrelationId.length() > 0) || + jmsDeliveryMode != null || jmsTimeToLive != null || + jmsPriority != null) { + + writer.writeStartElement(Constants.SCA11_NS, JMSBindingConstants.HEADERS); + + if (jmsType != null && jmsType.length() > 0) { + writer.writeAttribute("type", jmsType); + } + + if (jmsDeliveryMode != null) { + if (jmsDeliveryMode.booleanValue()) + writer.writeAttribute("deliveryMode", "persistent"); + else + writer.writeAttribute("deliveryMode", "nonpersistent"); + } + + if (jmsTimeToLive != null) { + writer.writeAttribute("timeToLive", jmsTimeToLive.toString()); + } + + if (jmsPriority != null) { + writer.writeAttribute("priority", jmsPriority.toString()); + } + + writeProperties( operationProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + // writer.writeCharacters( " " ); + } + } + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + } + + /** + * Writes a complete set of properties to the given XML stream writer. + * If the value is of type string, the property will be output: + * <property name="key">StringValue</property> + * If the value is of type box (e.g.Integer, Long) or BindingProperty, the output will be + * <property name="key" type="int">42</property> + */ + @SuppressWarnings("unchecked") + private void writeBindingProperties(Map<String, BindingProperty> properties, XMLStreamWriter writer) throws XMLStreamException { + if (( properties == null ) || ( properties.size() == 0 )) { + return; + } + + // For both the keys and values of a map + for (Iterator it=properties.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = (Map.Entry)it.next(); + Object key = entry.getKey(); + Object value = entry.getValue(); + + writer.writeStartElement(Constants.SCA11_NS, "property" ); + if (key != null){ + writer.writeAttribute("name", key.toString()); + } + + if ( value instanceof String) { + writer.writeCharacters( value.toString() ); + } else if ( value instanceof BindingProperty ) { + BindingProperty property = (BindingProperty) value; + String type = property.getType(); + if ( type != null ) { + writer.writeAttribute("type", type); + } + writer.writeCharacters( property.getValue().toString() ); + } else { + writer.writeCharacters( value.toString() ); + } + writer.writeEndElement(); + } + } + + /** + * Writes subscription headers if there are any. + * <complexType name="messageSelection"> + * <attribute name="selector" type="string"/> + * </complexType> + * + */ + private void writeSubscriptionHeaders( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String jmsSubscriptionHeaders = jmsBinding.getJMSSelector(); + if (jmsSubscriptionHeaders != null && jmsSubscriptionHeaders.length() > 0) { + writer.writeStartElement(Constants.SCA11_NS, "messageSelection"); + writer.writeAttribute("selector", jmsSubscriptionHeaders); + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + // writer.writeCharacters( " " ); + } + } + + /** + * Writes destination properties if there are any. + * <destination jndiName="xs:anyURI" type="string"? create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </destination>? + */ + private void writeDestinationProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String destinationName = jmsBinding.getDestinationName(); + if (destinationName == null || (destinationName.length() < 1)) { + return; + } + if (destinationName == null) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "destination"); + + if ( destinationName != null && destinationName.length() > 0) { + writer.writeAttribute("jndiName", destinationName); + } + + // Type not handled yet + // String destinationType = jmsBinding.getDestinationType(); + // if ( destinationType != null && destinationType.length() > 0) { + // writer.writeAttribute("type", destinationType); + // } + + String destinationCreate = jmsBinding.getDestinationCreate(); + if ( destinationCreate != null && destinationCreate.length() > 0 && + !destinationCreate.equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + writer.writeAttribute("create", destinationCreate); + } + + Map<String, BindingProperty> destinationProperties = + jmsBinding.getDestinationProperties(); + writeBindingProperties( destinationProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes connection factory properties if there are any. + * <connectionFactory jndiName="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </connectionFactory>? + */ + private void writeConnectionFactoryProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String cfName = jmsBinding.getConnectionFactoryName(); + if (cfName == null || (cfName.length() < 1)) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "connectionFactory"); + + if ( cfName != null && cfName.length() > 0) { + writer.writeAttribute("jndiName", cfName); + } + + String destinationCreate = jmsBinding.getConnectionFactoryCreate(); + if ( destinationCreate != null && destinationCreate.length() > 0 && + !destinationCreate.equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) { + writer.writeAttribute("create", destinationCreate); + } + + Map<String, BindingProperty> cfProperties = + jmsBinding.getConnectionFactoryProperties(); + writeBindingProperties( cfProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes activation Spec properties if there are any. + * <activationSpec name="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </activationSpec>? + * + */ + private void writeActivationSpecProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String asName = jmsBinding.getActivationSpecName(); + if (asName == null || (asName.length() < 1)) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "activationSpec"); + + if ( asName != null && asName.length() > 0) { + writer.writeAttribute("name", asName); + } + + String destinationCreate = jmsBinding.getActivationSpecCreate(); + if ( destinationCreate != null && destinationCreate.length() > 0) { + writer.writeAttribute("create", destinationCreate); + } + + Map<String, BindingProperty> cfProperties = + jmsBinding.getActivationSpecProperties(); + writeBindingProperties( cfProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes response destination properties if there are any. + * <destination jndiName="xs:anyURI" type="string"? create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </destination>? + */ + private void writeResponseDestinationProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String destinationName = jmsBinding.getResponseDestinationName(); + if (destinationName == null || (destinationName.length() < 1)) { + return; + } + if (destinationName == null) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "destination"); + + if ( destinationName != null && destinationName.length() > 0) { + writer.writeAttribute("jndiName", destinationName); + } + + // Type not handled yet + // String destinationType = jmsBinding.getDestinationType(); + // if ( destinationType != null && destinationType.length() > 0) { + // writer.writeAttribute("type", destinationType); + // } + + String destinationCreate = jmsBinding.getResponseDestinationCreate(); + if ( destinationCreate != null && destinationCreate.length() > 0) { + writer.writeAttribute("create", destinationCreate); + } + + Map<String, BindingProperty> destinationProperties = + jmsBinding.getResponseDestinationProperties(); + writeBindingProperties( destinationProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes response connection factory properties if there are any. + * <connectionFactory jndiName="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </connectionFactory>? + * + */ + private void writeResponseConnectionFactoryProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String cfName = jmsBinding.getResponseConnectionFactoryName(); + if (cfName == null || (cfName.length() < 1)) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "connectionFactory"); + + if ( cfName != null && cfName.length() > 0) { + writer.writeAttribute("jndiName", cfName); + } + + String destinationCreate = jmsBinding.getResponseConnectionFactoryCreate(); + if ( destinationCreate != null && destinationCreate.length() > 0) { + writer.writeAttribute("create", destinationCreate); + } + + Map<String, BindingProperty> cfProperties = + jmsBinding.getResponseConnectionFactoryProperties(); + writeBindingProperties( cfProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes response activation Spec properties if there are any. + * <activationSpec name="xs:anyURI" create="string"?> + * <property name="NMTOKEN" type="NMTOKEN">* + * </activationSpec>? + * + */ + private void writeResponseActivationSpecProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String asName = jmsBinding.getResponseActivationSpecName(); + if (asName == null || (asName.length() < 1)) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "activationSpec"); + + if ( asName != null && asName.length() > 0) { + writer.writeAttribute("name", asName); + } + + String destinationCreate = jmsBinding.getResponseActivationSpecCreate(); + if ( destinationCreate != null && destinationCreate.length() > 0) { + writer.writeAttribute("create", destinationCreate); + } + + Map<String, BindingProperty> cfProperties = + jmsBinding.getResponseActivationSpecProperties(); + writeBindingProperties( cfProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes resource adapter properties if there are any. + * <resourceAdapter name="NMTOKEN">? + * <property name="NMTOKEN" type="NMTOKEN">* + * </resourceAdapter>? + */ + private void writeResourceAdapterProperties( JMSBinding jmsBinding, XMLStreamWriter writer) throws XMLStreamException { + String asName = jmsBinding.getResourceAdapterName(); + if (asName == null || (asName.length() < 1)) { + return; + } + + writer.writeStartElement(Constants.SCA11_NS, "resourceAdapter"); + + if ( asName != null && asName.length() > 0) { + writer.writeAttribute("name", asName); + } + + Map<String, BindingProperty> cfProperties = + jmsBinding.getResourceAdapterProperties(); + writeBindingProperties( cfProperties, writer ); + + writer.writeEndElement(); + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Writes configured operations if there are any. + * <binding.jms uri=\"jms:testQueue\" >" + * <operationProperties name=\"op1\">" + * </operationProperties >" + * <operation name=\"op1\" requires=\"IntentOne IntentTwo\"/>" + * </binding.jms>" + */ + private void writeConfiguredOperations( JMSBinding jmsBinding, XMLStreamWriter writer, ProcessorContext context) throws XMLStreamException, ContributionWriteException { + List<ConfiguredOperation> configOps = jmsBinding.getConfiguredOperations(); + if (configOps == null || (configOps.size() < 1)) { + return; + } + + for( Iterator<ConfiguredOperation> it = configOps.iterator(); it.hasNext();) { + configuredOperationProcessor.write(it.next(), writer, context); + } + + // Strange bug. Without white space, headers end tag improperly read. + writer.writeCharacters(" "); + } + + /** + * Wire out a request or response wire format element. Uses extension processors + * to do this as wire format is an extension point + * + * @param wireFormat + * @param writer + */ + private void writeWireFormat(WireFormat wireFormat, XMLStreamWriter writer, ProcessorContext context ) throws XMLStreamException, ContributionWriteException { + extensionProcessor.write(wireFormat, writer, context); + } + + /** + * Wire out an operation selector element. Uses extension processors + * to do this as operation selector is an extension point + * + * @param operationSeletor + * @param writer + */ + private void writeOperationSelector(OperationSelector operationSeletor, XMLStreamWriter writer, ProcessorContext context ) throws XMLStreamException, ContributionWriteException{ + extensionProcessor.write(operationSeletor, writer, context); + } + +} |