001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.bpmscript.jbi;
018:
019: import java.io.ByteArrayOutputStream;
020: import java.io.IOException;
021: import java.util.Iterator;
022:
023: import javax.activation.DataHandler;
024: import javax.jbi.messaging.MessagingException;
025: import javax.jbi.messaging.NormalizedMessage;
026: import javax.xml.XMLConstants;
027: import javax.xml.parsers.ParserConfigurationException;
028: import javax.xml.soap.AttachmentPart;
029: import javax.xml.soap.MessageFactory;
030: import javax.xml.soap.MimeHeader;
031: import javax.xml.soap.SOAPBody;
032: import javax.xml.soap.SOAPElement;
033: import javax.xml.soap.SOAPEnvelope;
034: import javax.xml.soap.SOAPException;
035: import javax.xml.soap.SOAPMessage;
036: import javax.xml.soap.SOAPPart;
037: import javax.xml.transform.TransformerException;
038: import javax.xml.transform.dom.DOMSource;
039:
040: import org.apache.commons.logging.Log;
041: import org.apache.commons.logging.LogFactory;
042: import org.apache.servicemix.jbi.jaxp.SourceTransformer;
043: import org.w3c.dom.Attr;
044: import org.w3c.dom.Document;
045: import org.w3c.dom.NamedNodeMap;
046: import org.xml.sax.SAXException;
047:
048: /**
049: * @version $Revision: 1.1 $
050: */
051: public class SaajMarshaler {
052:
053: private static final transient Log log = LogFactory
054: .getLog(SaajMarshaler.class);
055:
056: protected SourceTransformer transformer = new SourceTransformer();
057: private MessageFactory messageFactory;
058:
059: public void toNMS(NormalizedMessage normalizedMessage,
060: SOAPMessage soapMessage) throws MessagingException,
061: SOAPException {
062:
063: if (log.isDebugEnabled()) {
064: try {
065: ByteArrayOutputStream buffer = new ByteArrayOutputStream();
066: soapMessage.writeTo(buffer);
067: log.debug(new String(buffer.toByteArray()));
068: } catch (Exception e) {
069: }
070: }
071:
072: addNmsProperties(normalizedMessage, soapMessage);
073:
074: SOAPPart soapPart = soapMessage.getSOAPPart();
075: SOAPBody soapBody = soapPart.getEnvelope().getBody();
076: SOAPElement elem = null;
077: for (Iterator it = soapBody.getChildElements(); it.hasNext();) {
078: Object child = it.next();
079: if (child instanceof SOAPElement) {
080: elem = (SOAPElement) child;
081: break;
082: }
083: }
084: if (elem == null) {
085: throw new IllegalStateException(
086: "Could not find any element in soap body");
087: }
088:
089: for (SOAPElement parent = elem.getParentElement(); parent != null; parent = parent
090: .getParentElement()) {
091: // The following code works with sun saaj implementation
092: NamedNodeMap attributes = parent.getAttributes();
093: if (attributes != null) {
094: for (int i = 0; i < attributes.getLength(); i++) {
095: Attr att = (Attr) parent.getAttributes().item(i);
096: if (att.getName().startsWith(
097: XMLConstants.XMLNS_ATTRIBUTE + ":")
098: && elem.getAttributeNodeNS(att
099: .getNamespaceURI(), att
100: .getLocalName()) == null) {
101: elem.addNamespaceDeclaration(att.getName()
102: .substring(
103: XMLConstants.XMLNS_ATTRIBUTE
104: .length() + 1), att
105: .getValue());
106: elem.setAttributeNS(att.getNamespaceURI(), att
107: .getName(), att.getValue());
108: }
109: }
110: }
111: // The following code works with axis saaj implementation
112: for (Iterator itNs = parent.getNamespacePrefixes(); itNs
113: .hasNext();) {
114: String prefix = (String) itNs.next();
115: String nsuri = parent.getNamespaceURI(prefix);
116: if (elem.getAttributeNS(
117: XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix) == null) {
118: elem.addNamespaceDeclaration(prefix, nsuri);
119: elem
120: .setAttributeNS(
121: XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
122: XMLConstants.XMLNS_ATTRIBUTE + ":"
123: + prefix, nsuri);
124: }
125: }
126: }
127:
128: if (log.isDebugEnabled()) {
129: try {
130: log.debug(transformer.toString(elem));
131: } catch (Exception e) {
132: }
133: }
134:
135: normalizedMessage.setContent(new DOMSource(elem));
136:
137: addNmsAttachments(normalizedMessage, soapMessage);
138: }
139:
140: public SOAPMessage createSOAPMessage(
141: NormalizedMessage normalizedMessage) throws SOAPException,
142: IOException, TransformerException, MessagingException,
143: ParserConfigurationException, SAXException {
144: SOAPMessage soapMessage = getMessageFactory().createMessage();
145:
146: addSoapProperties(soapMessage, normalizedMessage);
147:
148: SOAPPart soapPart = soapMessage.getSOAPPart();
149: SOAPEnvelope envelope = soapPart.getEnvelope();
150: SOAPBody body = envelope.getBody();
151:
152: // lets turn the payload into a DOM Node to avoid blatting over the envelope
153: // Do not use DOMResult to transform as namespaces are lost (why ?)
154: //DOMResult result = new DOMResult(null);
155: //transformer.toResult(normalizedMessage.getContent(), result);
156: //Document document = (Document) result.getNode();
157: Document document = transformer
158: .toDOMDocument(normalizedMessage);
159: body.addDocument(document);
160:
161: addSoapAttachments(soapMessage, normalizedMessage);
162:
163: return soapMessage;
164: }
165:
166: // Properties
167: //-------------------------------------------------------------------------
168: public MessageFactory getMessageFactory() throws SOAPException {
169: if (messageFactory == null) {
170: messageFactory = createMessageFactory();
171: }
172: return messageFactory;
173: }
174:
175: public void setMessageFactory(MessageFactory messageFactory) {
176: this .messageFactory = messageFactory;
177: }
178:
179: // Implementation methods
180: //-------------------------------------------------------------------------
181:
182: protected void addNmsProperties(
183: NormalizedMessage normalizedMessage, SOAPMessage soapMessage) {
184: Iterator iter = soapMessage.getMimeHeaders().getAllHeaders();
185: while (iter.hasNext()) {
186: MimeHeader header = (MimeHeader) iter.next();
187: normalizedMessage.setProperty(header.getName(), header
188: .getValue());
189: }
190: }
191:
192: protected void addNmsAttachments(
193: NormalizedMessage normalizedMessage, SOAPMessage soapMessage)
194: throws MessagingException, SOAPException {
195: Iterator iter = soapMessage.getAttachments();
196: while (iter.hasNext()) {
197: AttachmentPart attachment = (AttachmentPart) iter.next();
198: normalizedMessage.addAttachment(attachment.getContentId(),
199: asDataHandler(attachment));
200: }
201: }
202:
203: protected void addSoapProperties(SOAPMessage soapMessage,
204: NormalizedMessage normalizedMessage) throws SOAPException {
205: for (Iterator iter = normalizedMessage.getPropertyNames()
206: .iterator(); iter.hasNext();) {
207: String name = (String) iter.next();
208: Object value = normalizedMessage.getProperty(name);
209: if (shouldIncludeHeader(normalizedMessage, name, value)) {
210: soapMessage.getMimeHeaders().addHeader(name,
211: value.toString());
212: }
213: if (shouldIncludeProperty(normalizedMessage, name, value)) {
214: soapMessage.setProperty(name, value);
215: }
216: }
217: }
218:
219: protected void addSoapAttachments(SOAPMessage soapMessage,
220: NormalizedMessage normalizedMessage) throws IOException {
221: Iterator iterator = normalizedMessage.getAttachmentNames()
222: .iterator();
223: while (iterator.hasNext()) {
224: String name = (String) iterator.next();
225: DataHandler attachment = normalizedMessage
226: .getAttachment(name);
227: AttachmentPart attachmentPart = soapMessage
228: .createAttachmentPart(attachment.getContent(),
229: attachment.getContentType());
230: attachmentPart.setContentId(name);
231: soapMessage.addAttachmentPart(attachmentPart);
232: }
233: }
234:
235: /**
236: * Decides whether or not the given header should be included in the SAAJ message as a MimeHeader
237: */
238: protected boolean shouldIncludeHeader(
239: NormalizedMessage normalizedMessage, String name,
240: Object value) {
241: // TODO: remove http headers that may come from a consumer http BC
242: return true;
243: }
244:
245: /**
246: * Decides whether or not the given property should be included in the SAAJ message as a property
247: */
248: protected boolean shouldIncludeProperty(
249: NormalizedMessage normalizedMessage, String name,
250: Object value) {
251: return true;
252: }
253:
254: protected DataHandler asDataHandler(AttachmentPart attachment)
255: throws SOAPException {
256: return new DataHandler(attachment.getContent(), attachment
257: .getContentType());
258: }
259:
260: protected MessageFactory createMessageFactory()
261: throws SOAPException {
262: return MessageFactory.newInstance();
263: }
264: }
|