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: JMSMarshaler.java 1206 2006-09-23 03:51:32Z fling $
023: */
024: package com.bostechcorp.cbesb.runtime.component.jms;
025:
026: import java.io.ByteArrayInputStream;
027: import java.io.ByteArrayOutputStream;
028: import java.io.CharArrayWriter;
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.io.PrintWriter;
032: import java.io.Reader;
033: import java.nio.charset.Charset;
034: import java.util.Enumeration;
035: import java.util.Iterator;
036:
037: import javax.jbi.messaging.MessageExchange;
038: import javax.jbi.messaging.MessagingException;
039: import javax.jbi.messaging.NormalizedMessage;
040: import javax.jms.BytesMessage;
041: import javax.jms.JMSException;
042: import javax.jms.Message;
043: import javax.jms.Session;
044: import javax.jms.TextMessage;
045: import javax.xml.transform.Source;
046: import javax.xml.transform.Transformer;
047: import javax.xml.transform.TransformerConfigurationException;
048: import javax.xml.transform.TransformerException;
049: import javax.xml.transform.TransformerFactory;
050: import javax.xml.transform.stream.StreamResult;
051:
052: import org.apache.commons.logging.Log;
053: import org.apache.commons.logging.LogFactory;
054:
055: import com.bostechcorp.cbesb.common.runtime.ConfigurationException;
056: import com.bostechcorp.cbesb.runtime.ccsl.lib.OutputWriter;
057: import com.bostechcorp.cbesb.runtime.ccsl.nmhandler.ByteArraySource;
058: import com.bostechcorp.cbesb.runtime.ccsl.nmhandler.NormalizedMessageHandler;
059: import com.bostechcorp.cbesb.runtime.ccsl.nmhandler.StringSource;
060:
061: /**
062: * Marshalls JMS messages into and out of NMS messages
063: *
064: */
065: // TODO : check message transformation changes
066: public class JMSMarshaler {
067:
068: protected static final transient Log logger = LogFactory
069: .getLog(JMSMarshaler.class);
070:
071: private static boolean needJavaIdentifiers = true;
072:
073: private final static String[] STYLES = { "Style", "raw", "newline" };
074:
075: // private final static int STYLE_RAW = 0;
076: private final static int STYLE_NEWLINE = 1;
077:
078: private final static String IDENTITY_CHARSET = "ISO8859-1";
079:
080: private static final String JMS_PREFIX = "jms.selector.";
081:
082: public static Message normalizedToJMS(NormalizedMessage m,
083: MessageExchange mex, String writeStyle, String charset,
084: Session jmsSession, boolean savaMetadata)
085: throws ConfigurationException, IOException,
086: TransformerException, TransformerConfigurationException,
087: JMSException {
088: // logger.info(writeStyle);
089: int style = findInArray(writeStyle, STYLES);
090: NormalizedMessageHandler nmh = new NormalizedMessageHandler(m);
091:
092: /*
093: * It the style is newline or any of the record are not binary then we
094: * need to make this a text message
095: */
096: boolean isText = (style == STYLE_NEWLINE);
097: for (int rec = 0; isText == false && rec < nmh.getRecordCount(); rec++) {
098: if (!(nmh.getRecordAtIndex(rec) instanceof ByteArraySource))
099: isText = true;
100: }
101:
102: ByteArrayOutputStream baos = null;
103: CharArrayWriter chw = null;
104: if (isText)
105: chw = new CharArrayWriter();
106: else
107: baos = new ByteArrayOutputStream();
108:
109: for (int rec = 0; rec < nmh.getRecordCount(); rec++) {
110: if (!isText)
111: baos.write(((ByteArraySource) (nmh
112: .getRecordAtIndex(rec))).getBytes());
113: else {
114: Source this Rec = nmh.getRecordAtIndex(rec);
115: if (this Rec instanceof ByteArraySource) {
116: ByteArraySource bs = (ByteArraySource) this Rec;
117: if (charset == null || charset.length() < 1)
118: charset = IDENTITY_CHARSET;
119: bs.setCharset(Charset.forName(charset));
120: Reader bsReader = bs.getReader();
121: char[] buf = new char[2048];
122: for (int l = 0; (l = bsReader.read(buf)) > 0;)
123: chw.write(buf, 0, l);
124: } else if (this Rec instanceof StringSource) {
125: chw.append(((StringSource) this Rec).getText());
126: } else {
127: StreamResult sr = new StreamResult(chw);
128: TransformerFactory tf = TransformerFactory
129: .newInstance();
130: Transformer t = tf.newTransformer();
131: t.transform(this Rec, sr);
132: }
133:
134: if (style == STYLE_NEWLINE) {
135: PrintWriter pw = new PrintWriter(chw);
136: pw.println();
137: }
138: }
139: }
140:
141: // construct the JMS message
142: Message result = null;
143: if (isText) {
144: TextMessage tm = jmsSession.createTextMessage(new String(
145: chw.toCharArray()));
146: result = tm;
147: } else {
148: BytesMessage bm = jmsSession.createBytesMessage();
149: bm.writeBytes(baos.toByteArray());
150: }
151: //set properties
152: logger.debug("WriteStyle=" + writeStyle);
153:
154: if (savaMetadata)
155: addJmsProperties(result, mex);
156:
157: //logger.debug("try to write message to jms: "+result.toString());
158:
159: return result;
160: }
161:
162: /**
163: * Marshalls the JMS message into an NMS message
164: *
165: * @throws MessagingException
166: */
167: public void toNMS(NormalizedMessage normalizedMessage,
168: MessageExchange mex, Message message, JMSEndpoint endpoint)
169: throws JMSException, MessagingException {
170:
171: addNmsProperties(mex, message);
172:
173: normalizedMessage.setContent(toSource(message, endpoint));
174: }
175:
176: public Source toSource(Message message, JMSEndpoint endpoint)
177: throws JMSException, MessagingException {
178: InputStream is = null;
179: if (message instanceof TextMessage) {
180: is = new ByteArrayInputStream(((TextMessage) message)
181: .getText().getBytes());
182: } else if (message instanceof BytesMessage) {
183: int length = (int) ((BytesMessage) message).getBodyLength();
184: byte[] bytes = new byte[length];
185: ((BytesMessage) message).readBytes(bytes);
186: is = new ByteArrayInputStream(bytes);
187: } else {
188: throw new JMSException(
189: "JMS message should be a text or bytes message");
190: }
191:
192: // int recordsPerMessage = 0;
193: // if (endpoint.getRecordsPerMessage() != null) {
194: // recordsPerMessage = (new Integer(endpoint.getRecordsPerMessage()))
195: // .intValue();
196: // }
197:
198: // Source source = InputReader.processInputStream(is, recordsPerMessage,
199: // endpoint.getReadStyle(), endpoint.getRecordType(), endpoint
200: // .getCharset());
201: Source source = new StringSource(is.toString());
202: return source;
203: }
204:
205: /**
206: * Marshalls the NMS message into a JMS message
207: *
208: * @param normalizedMessage
209: * @param session
210: * @return JMS Message
211: * @throws JMSException
212: * @throws TransformerException
213: */
214: public Message createMessage(NormalizedMessage normalizedMessage,
215: MessageExchange mex, Session session, JMSEndpoint endpoint,
216: boolean saveMetadata) throws JMSException,
217: TransformerException {
218:
219: TextMessage message = (TextMessage) createMessageFromSource(
220: normalizedMessage.getContent(), session, endpoint);
221: if (saveMetadata)
222: addJmsProperties(message, mex);
223:
224: return message;
225: }
226:
227: public Message createMessageFromSource(Source source,
228: Session session, JMSEndpoint endpoint) throws JMSException,
229: TransformerException {
230:
231: ByteArrayOutputStream baos = new ByteArrayOutputStream();
232: OutputWriter.processOutputStream(source, baos, endpoint
233: .getWriteStyle(), endpoint.getCharset());
234:
235: TextMessage message = session
236: .createTextMessage(baos.toString());
237:
238: return message;
239:
240: }
241:
242: /**
243: * Appends properties on the NMS to the JMS Message
244: *
245: * @param message
246: * JMS message
247: * @param mex
248: * NMS message
249: * @throws JMSException
250: */
251: protected static void addJmsProperties(Message message,
252: MessageExchange mex) throws JMSException {
253: for (Iterator iter = mex.getPropertyNames().iterator(); iter
254: .hasNext();) {
255: String name = (String) iter.next();
256: Object value = mex.getProperty(name);
257: // if (shouldIncludeHeader(name, value)) {
258: // message.setObjectProperty(name.toLowerCase().replaceFirst(JMS_PREFIX,""), value);
259: // }
260: try {
261: message.setObjectProperty(name, value);
262: } catch (Exception ex) {
263: logger.debug("Add propertis error:" + ex);
264: }
265: }
266: }
267:
268: /**
269: * Appends properties on the JMS to the NMS Message
270: *
271: * @param mex
272: * @param jmsMessage
273: * @throws JMSException
274: */
275: protected void addNmsProperties(MessageExchange mex,
276: Message jmsMessage) throws JMSException {
277:
278: Enumeration enumeration = jmsMessage.getPropertyNames();
279: while (enumeration.hasMoreElements()) {
280: String name = (String) enumeration.nextElement();
281: Object value = jmsMessage.getObjectProperty(name);
282: mex.setProperty(name, value);
283: }
284: }
285:
286: /**
287: * Decides whether or not the given header should be included in the JMS
288: * message. By default this includes all suitable typed values
289: *
290: * @param normalizedMessage
291: * @param name
292: * @param value
293: * @return
294: */
295: protected static boolean shouldIncludeHeader(String name,
296: Object value) {
297:
298: return name.toLowerCase().startsWith(JMS_PREFIX);
299: // return (value instanceof String ||
300: // value instanceof Number ||
301: // value instanceof Date)
302: // /*&& (!isNeedJavaIdentifiers() || isJavaIdentifier(name))*/;
303: }
304:
305: private static boolean isJavaIdentifier(String s) {
306: int n = s.length();
307: if (n == 0)
308: return false;
309: if (!Character.isJavaIdentifierStart(s.charAt(0)))
310: return false;
311: for (int i = 1; i < n; i++)
312: if (!Character.isJavaIdentifierPart(s.charAt(i)))
313: return false;
314: return true;
315: }
316:
317: /**
318: * @return Returns the needJavaIdentifiers.
319: */
320: public static boolean isNeedJavaIdentifiers() {
321: return needJavaIdentifiers;
322: }
323:
324: /**
325: * @param needJavaIdentifiers
326: * The needJavaIdentifiers to set.
327: */
328: public void setNeedJavaIdentifiers(boolean needJavaIdentifiers) {
329: this .needJavaIdentifiers = needJavaIdentifiers;
330: }
331:
332: private static int findInArray(String s, String arr[])
333: throws ConfigurationException {
334: for (int i = 1; i < arr.length; i++)
335: if (s.equals(arr[i]))
336: return i - 1;
337: throw new ConfigurationException("invalid " + arr[0] + " \""
338: + s + "\"");
339: }
340:
341: public static void addMetatataToJms(Message message,
342: MessageExchange exchange) throws JMSException {
343: try {
344: for (Object propName : exchange.getPropertyNames()) {
345: String name = propName.toString();
346: Object value = exchange.getProperty(name);
347: message.setObjectProperty(name, value);
348: }
349: } catch (JMSException e) {
350: JMSException jx = new JMSException(
351: "Exception during transfering Properties from MEssageExchange to JMSMessage");
352: jx.setLinkedException(jx);
353: throw jx;
354: }
355: }
356:
357: public static void addMetatataToNMExchange(
358: MessageExchange exchange, Message message)
359: throws JMSException {
360: try {
361: Enumeration propertyNames = message.getPropertyNames();
362: while (propertyNames.hasMoreElements()) {
363: String name = (String) propertyNames.nextElement();
364: Object value = message.getObjectProperty(name);
365: exchange.setProperty(name, value);
366: }
367: } catch (JMSException ex) {
368: JMSException jx = new JMSException(
369: "Exception during transfering Properties from JMSMessage to MessageExchange");
370: jx.setLinkedException(jx);
371: throw jx;
372: }
373: }
374:
375: }
|