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.apache.servicemix.jms;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import java.io.InputStream;
022: import java.util.Date;
023: import java.util.Iterator;
024: import java.util.Map;
025:
026: import javax.jms.BytesMessage;
027: import javax.jms.Message;
028: import javax.jms.ObjectMessage;
029: import javax.jms.Session;
030: import javax.jms.TextMessage;
031:
032: import org.apache.servicemix.soap.SoapHelper;
033: import org.apache.servicemix.soap.marshalers.SoapMessage;
034: import org.apache.servicemix.soap.marshalers.SoapWriter;
035:
036: /**
037: * Encapsulates the conversion to and from JMS messages
038: */
039: public class DefaultJmsMarshaler implements JmsMarshaler {
040: public static final String CONTENT_TYPE = "MimeContentType";
041:
042: private JmsEndpoint endpoint;
043:
044: public DefaultJmsMarshaler(JmsEndpoint endpoint) {
045: this .endpoint = endpoint;
046: }
047:
048: /**
049: * Converts an {@link Exception} into an JMS message. This method will be
050: * invoked when the {@link MessageExchange} contains an error.
051: *
052: * @param e
053: * Exception to convert
054: * @param session
055: * JMS session used to create JMS messages
056: * @return JMS message
057: * @see MessageExchange#getError()
058: */
059: public Message toJMS(Exception e, Session session) throws Exception {
060: return session.createObjectMessage(e);
061: }
062:
063: /**
064: * Template method to allow custom functionality. Custom JmsMarshallers
065: * should override this method.
066: *
067: * @param message Source message
068: * @param session JMS session used to create JMS messages
069: * @return JMS version of the specified source SOAP message
070: * @throws Exception if an IO error occurs
071: * @throws JMSException if a JMS error occurs
072: */
073: protected Message toJMS(SoapMessage message, Session session)
074: throws Exception {
075: SoapHelper soapHelper = new SoapHelper(endpoint);
076:
077: // turn SOAP message into byte array/string
078: ByteArrayOutputStream baos = new ByteArrayOutputStream();
079: SoapWriter writer = soapHelper.getSoapMarshaler().createWriter(
080: message);
081: writer.write(baos);
082:
083: // create text message
084: TextMessage msg = session.createTextMessage();
085: msg.setText(baos.toString());
086:
087: // overwrite whatever content-type was passed on to us with the one
088: // the SoapWriter constructed
089: msg.setStringProperty(CONTENT_TYPE, writer.getContentType());
090:
091: return msg;
092: }
093:
094: /**
095: * Converts a SOAP message to a JMS message, including any message headers.
096: *
097: * @param message
098: * message to convert
099: * @param headers
100: * protocol headers present in the NormalizedMessage
101: * @param session
102: * JMS session used to create JMS messages
103: * @throws Exception if something bad happens
104: * @return JMS message
105: */
106: public Message toJMS(SoapMessage message, Map headers,
107: Session session) throws Exception {
108: // create message
109: Message msg = toJMS(message, session);
110:
111: // add protocol headers to message
112: if (headers != null) {
113: for (Iterator it = headers.keySet().iterator(); it
114: .hasNext();) {
115: String name = (String) it.next();
116: Object value = headers.get(name);
117: if (shouldIncludeHeader(name, value)) {
118: msg.setObjectProperty(name, value);
119: }
120: }
121: }
122:
123: return msg;
124: }
125:
126: /**
127: * Template method to allow custom functionality. Custom JmsMarshalers
128: * should override this method.
129: *
130: * @param message
131: * Message to be turned into XML/SOAP
132: * @return Stream containing either the whole SOAP envelope or just the
133: * payload of the body.
134: * @throws Exception
135: * if JMS message is an ObjectMessage containing an Exception
136: * (the containing exception is thrown.)
137: * @throws JMSException
138: * if a JMS problem occurs
139: * @throws UnsupportedOperationException
140: * if the JMS message is an ObjectMessage which contains
141: * something other than an Exception
142: * @throws IllegalArgumentException
143: * if the message is anything other than a TextMessage or
144: * BytesMessage
145: */
146: protected InputStream toXmlInputStream(Message message)
147: throws Exception {
148: InputStream is = null;
149: if (message instanceof ObjectMessage) {
150: Object o = ((ObjectMessage) message).getObject();
151: if (o instanceof Exception) {
152: throw (Exception) o;
153: } else {
154: throw new UnsupportedOperationException(
155: "Can not handle objects of type "
156: + o.getClass().getName());
157: }
158: } else if (message instanceof TextMessage) {
159: is = new ByteArrayInputStream(((TextMessage) message)
160: .getText().getBytes());
161: } else if (message instanceof BytesMessage) {
162: int length = (int) ((BytesMessage) message).getBodyLength();
163: byte[] bytes = new byte[length];
164: ((BytesMessage) message).readBytes(bytes);
165: is = new ByteArrayInputStream(bytes);
166: } else {
167: throw new IllegalArgumentException(
168: "JMS message should be a text or bytes message");
169: }
170:
171: return is;
172: }
173:
174: /**
175: * Converts a JMS message into a SOAP message
176: *
177: * @param message
178: * JMS message to convert
179: * @return SOAP representation of the specified JMS message
180: * @throws Exception
181: * if an IO exception occurs
182: */
183: public SoapMessage toSOAP(Message message) throws Exception {
184: SoapHelper soapHelper = new SoapHelper(endpoint);
185:
186: InputStream is = toXmlInputStream(message);
187: String contentType = message.getStringProperty(CONTENT_TYPE);
188: SoapMessage soap = soapHelper.getSoapMarshaler().createReader()
189: .read(is, contentType);
190:
191: return soap;
192: }
193:
194: private boolean shouldIncludeHeader(String name, Object value) {
195: return (value instanceof String || value instanceof Number || value instanceof Date)
196: && (!endpoint.isNeedJavaIdentifiers() || isJavaIdentifier(name));
197: }
198:
199: private static boolean isJavaIdentifier(String s) {
200: int n = s.length();
201: if (n == 0) {
202: return false;
203: }
204: if (!Character.isJavaIdentifierStart(s.charAt(0))) {
205: return false;
206: }
207: for (int i = 1; i < n; i++) {
208: if (!Character.isJavaIdentifierPart(s.charAt(i))) {
209: return false;
210: }
211: }
212: return true;
213: }
214: }
|