001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: $
023: */
024: package com.bostechcorp.cbesb.runtime.ccsl.nmhandler;
025:
026: import java.util.UUID;
027: import java.util.Vector;
028:
029: import javax.activation.DataSource;
030: import javax.xml.namespace.QName;
031: import javax.xml.parsers.DocumentBuilder;
032: import javax.xml.parsers.DocumentBuilderFactory;
033: import javax.xml.parsers.ParserConfigurationException;
034: import javax.xml.transform.Source;
035: import javax.xml.transform.Transformer;
036: import javax.xml.transform.TransformerConfigurationException;
037: import javax.xml.transform.TransformerException;
038: import javax.xml.transform.TransformerFactory;
039: import javax.xml.transform.dom.DOMResult;
040: import javax.xml.transform.dom.DOMSource;
041:
042: import org.apache.commons.logging.Log;
043: import org.apache.commons.logging.LogFactory;
044: import org.w3c.dom.Document;
045: import org.w3c.dom.Element;
046: import org.w3c.dom.Node;
047:
048: import com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.ServiceDescriptionHandler;
049:
050: /**
051: * Implementation of a javax.xml.transform.Source to use
052: * as the NormalizedMessage content for ChainBuilder ESB
053: * components. This class will provide the JBI WSDL 1.1
054: * wrapper functionality as well as the ability to contain
055: * multiple "records".
056: *
057: * @author mpreston
058: *
059: */
060: public class DataEnvelopeSource extends DOMSource {
061:
062: //Constants used in JBI Wrapper XML
063: protected static final String JBI_WRAPPER_NS = "http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper";
064: protected static final String JBI_NS_PREFIX = "jbi";
065: protected static final String JBI_MESSAGE = "message";
066: protected static final String JBI_VERSION = "version";
067: protected static final String JBI_TYPE = "type";
068: protected static final String JBI_PART = "part";
069:
070: protected static final String DATA_ENVELOPE_NS = "http://cbesb.bostechcorp.com/dataenvelope/1.0";
071: protected static final String DATA_ENVELOPE_NS_PREFIX = "de";
072: protected static final String DATA_ENVELOPE = "DataEnvelope";
073: protected static final String XML_RECORD = "XMLRecord";
074: protected static final String BINARY_RECORD = "BinaryRecord";
075: protected static final String STRING_RECORD = "StringRecord";
076:
077: private transient final Log logger = LogFactory.getLog(this
078: .getClass());
079:
080: private Vector<RecordEntry> records;
081: private ServiceDescriptionHandler svcDescHandler;
082:
083: private class RecordEntry {
084: public String contentId;
085: public DataSource ds;
086:
087: public RecordEntry(String contentId, DataSource ds) {
088: this .contentId = contentId;
089: this .ds = ds;
090: }
091:
092: /**
093: * @return the contentId
094: */
095: public String getContentId() {
096: return contentId;
097: }
098:
099: /**
100: * @return the ds
101: */
102: public DataSource getDataSource() {
103: return ds;
104: }
105:
106: }
107:
108: /**
109: *
110: */
111: public DataEnvelopeSource() {
112: records = new Vector<RecordEntry>();
113: svcDescHandler = null;
114: }
115:
116: public DataEnvelopeSource(ServiceDescriptionHandler svcDescHandler) {
117: records = new Vector<RecordEntry>();
118: this .svcDescHandler = svcDescHandler;
119: }
120:
121: public ServiceDescriptionHandler getSvcDescHandler() {
122: return svcDescHandler;
123: }
124:
125: public void setSvcDescHandler(
126: ServiceDescriptionHandler svcDescHandler) {
127: this .svcDescHandler = svcDescHandler;
128: }
129:
130: /**
131: * Returns the number of individual data records are in the message.
132: * @return
133: */
134: public int getRecordCount() {
135: return records.size();
136: }
137:
138: public void addRecord(Source src) {
139: DataSource ds = null;
140: String contentId = generateContentId();
141: if (src instanceof DOMSource) {
142: ds = new DOMDataSource((DOMSource) src, contentId);
143: } else if (src instanceof StringSource) {
144: ds = new StringDataSource(((StringSource) src).getText(),
145: "text/plain", contentId);
146: } else if (src instanceof ByteArraySource) {
147: ds = new ByteArrayDataSource(((ByteArraySource) src)
148: .getBytes(), "application/octet-stream", contentId);
149: } else {
150: ds = new DOMDataSource(sourceToDOMSource(src), contentId);
151: }
152:
153: records.add(new RecordEntry(contentId, ds));
154: }
155:
156: public void addRecord(String contentId, DataSource ds) {
157: records.add(new RecordEntry(contentId, ds));
158: }
159:
160: public void removeAllRecords() {
161: records.clear();
162: }
163:
164: public Source getRecordAsSource(int index) {
165: DataSource ds = records.elementAt(index).getDataSource();
166: if (ds instanceof DOMDataSource) {
167: return ((DOMDataSource) ds).getSrc();
168: } else if (ds instanceof StringDataSource) {
169: return new StringSource(((StringDataSource) ds).getData());
170: } else if (ds instanceof ByteArrayDataSource) {
171: return new ByteArraySource(((ByteArrayDataSource) ds)
172: .getData());
173: }
174: return null;
175: }
176:
177: public DataSource getRecordAsDataSource(int index) {
178: return records.elementAt(index).getDataSource();
179: }
180:
181: public String getRecordContentId(int index) {
182: return records.elementAt(index).getContentId();
183: }
184:
185: /**
186: * Override getNode() to construct the NormalizedMessage
187: * content as a DOM tree on demand. In normal use, this
188: * should only be called when debugging.
189: */
190: public Node getNode() {
191: Document doc = null;
192: try {
193: DocumentBuilderFactory dbf = DocumentBuilderFactory
194: .newInstance();
195: dbf.setNamespaceAware(true);
196: DocumentBuilder docBuilder = dbf.newDocumentBuilder();
197:
198: doc = docBuilder.newDocument();
199:
200: Element dataEnvelope;
201:
202: if (svcDescHandler != null && svcDescHandler.isWsdl11()) {
203: // Create the JBI WSDL 1.1 wrapper
204: QName msgType = svcDescHandler
205: .getInputMessageQName(svcDescHandler
206: .getFirstOperation());
207: Element jbiMessage = doc.createElementNS(
208: JBI_WRAPPER_NS, JBI_MESSAGE);
209:
210: doc.appendChild(jbiMessage);
211:
212: //Add namespace decl for msgType namespace
213: jbiMessage.setAttribute("xmlns:ns0", msgType
214: .getNamespaceURI());
215:
216: jbiMessage.setPrefix(JBI_NS_PREFIX);
217: jbiMessage.setAttribute(JBI_VERSION, "1.0");
218:
219: jbiMessage.setAttribute(JBI_TYPE, "ns0:"
220: + msgType.getLocalPart());
221:
222: Element jbiPart = doc.createElementNS(JBI_WRAPPER_NS,
223: JBI_PART);
224: jbiPart.setPrefix(JBI_NS_PREFIX);
225: jbiMessage.appendChild(jbiPart);
226:
227: dataEnvelope = doc.createElementNS(DATA_ENVELOPE_NS,
228: DATA_ENVELOPE);
229: dataEnvelope.setPrefix(DATA_ENVELOPE_NS_PREFIX);
230: jbiPart.appendChild(dataEnvelope);
231:
232: } else {
233: // JBI WSDL 1.1 wrapper is not needed
234: dataEnvelope = doc.createElementNS(DATA_ENVELOPE_NS,
235: DATA_ENVELOPE);
236: dataEnvelope.setPrefix(DATA_ENVELOPE_NS_PREFIX);
237: doc.appendChild(dataEnvelope);
238: }
239:
240: //Add records to DataEnvelope
241: for (int i = 0; i < records.size(); i++) {
242: DataSource record = records.elementAt(i)
243: .getDataSource();
244: String contentId = records.elementAt(i).getContentId();
245: if (record instanceof DOMDataSource) {
246: Element xmlRecord = doc.createElementNS(
247: DATA_ENVELOPE_NS, XML_RECORD);
248: xmlRecord.setPrefix(DATA_ENVELOPE_NS_PREFIX);
249: dataEnvelope.appendChild(xmlRecord);
250: xmlRecord.setTextContent(contentId);
251:
252: } else if (record instanceof StringDataSource) {
253: Element stringRecord = doc.createElementNS(
254: DATA_ENVELOPE_NS, STRING_RECORD);
255: stringRecord.setPrefix(DATA_ENVELOPE_NS_PREFIX);
256: dataEnvelope.appendChild(stringRecord);
257: stringRecord.setTextContent(contentId);
258:
259: } else if (record instanceof ByteArrayDataSource) {
260: Element binaryRecord = doc.createElementNS(
261: DATA_ENVELOPE_NS, BINARY_RECORD);
262: binaryRecord.setPrefix(DATA_ENVELOPE_NS_PREFIX);
263: dataEnvelope.appendChild(binaryRecord);
264: binaryRecord.setTextContent(contentId);
265:
266: }
267: }
268:
269: } catch (ParserConfigurationException e) {
270: logger.error("Unable to create DOM Document.", e);
271: }
272: return doc;
273: }
274:
275: private DOMSource sourceToDOMSource(Source src) {
276: try {
277: TransformerFactory tf = TransformerFactory.newInstance();
278: Transformer t = tf.newTransformer();
279: DOMResult dr = new DOMResult();
280: t.transform(src, dr);
281: return new DOMSource(dr.getNode());
282: } catch (TransformerConfigurationException e) {
283: logger.error("Caught exception creating DOMSource: ", e);
284: } catch (TransformerException e) {
285: logger.error("Caught exception creating DOMSource: ", e);
286: }
287: return null;
288: }
289:
290: private String generateContentId() {
291: UUID uuid = UUID.randomUUID();
292: return "cid:urn:" + uuid.toString() + "@cbesb.com";
293: }
294:
295: }
|