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.common.util;
018
019 import java.io.ByteArrayOutputStream;
020 import java.io.IOException;
021 import java.io.Serializable;
022 import java.io.InputStream;
023 import java.io.OutputStream;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.Map;
027 import java.util.Set;
028
029 import javax.activation.DataHandler;
030 import javax.activation.DataSource;
031 import javax.jbi.messaging.Fault;
032 import javax.jbi.messaging.MessageExchange;
033 import javax.jbi.messaging.MessagingException;
034 import javax.jbi.messaging.NormalizedMessage;
035 import javax.mail.util.ByteArrayDataSource;
036 import javax.security.auth.Subject;
037 import javax.xml.parsers.ParserConfigurationException;
038 import javax.xml.transform.Source;
039 import javax.xml.transform.TransformerException;
040 import javax.xml.transform.sax.SAXSource;
041 import javax.xml.transform.stream.StreamSource;
042
043 import org.xml.sax.SAXException;
044
045 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
046 import org.apache.servicemix.jbi.jaxp.StringSource;
047
048 /**
049 * @author gnodet
050 * @version $Revision: 376451 $
051 */
052 public final class MessageUtil {
053
054 private MessageUtil() {
055 }
056
057 public static void transfer(NormalizedMessage source, NormalizedMessage dest) throws MessagingException {
058 dest.setContent(source.getContent());
059 for (Iterator it = source.getPropertyNames().iterator(); it.hasNext();) {
060 String name = (String) it.next();
061 dest.setProperty(name, source.getProperty(name));
062 }
063 for (Iterator it = source.getAttachmentNames().iterator(); it.hasNext();) {
064 String name = (String) it.next();
065 dest.addAttachment(name, source.getAttachment(name));
066 }
067 dest.setSecuritySubject(source.getSecuritySubject());
068 }
069
070 public static NormalizedMessage copy(NormalizedMessage source) throws MessagingException {
071 if (source instanceof Fault) {
072 return new FaultImpl((Fault) source);
073 } else {
074 return new NormalizedMessageImpl(source);
075 }
076 }
077
078 public static NormalizedMessage copyIn(MessageExchange exchange) throws MessagingException {
079 return copy(exchange.getMessage("in"));
080 }
081
082 public static NormalizedMessage copyOut(MessageExchange exchange) throws MessagingException {
083 return copy(exchange.getMessage("out"));
084 }
085
086 public static Fault copyFault(MessageExchange exchange) throws MessagingException {
087 return (Fault) copy(exchange.getMessage("fault"));
088 }
089
090 public static void transferInToIn(MessageExchange source, MessageExchange dest) throws MessagingException {
091 transferToIn(source.getMessage("in"), dest);
092 }
093
094 public static void transferOutToIn(MessageExchange source, MessageExchange dest) throws MessagingException {
095 transferToIn(source.getMessage("out"), dest);
096 }
097
098 public static void transferToIn(NormalizedMessage sourceMsg, MessageExchange dest) throws MessagingException {
099 transferTo(sourceMsg, dest, "in");
100 }
101
102 public static void transferOutToOut(MessageExchange source, MessageExchange dest) throws MessagingException {
103 transferToOut(source.getMessage("out"), dest);
104 }
105
106 public static void transferInToOut(MessageExchange source, MessageExchange dest) throws MessagingException {
107 transferToOut(source.getMessage("in"), dest);
108 }
109
110 public static void transferToOut(NormalizedMessage sourceMsg, MessageExchange dest) throws MessagingException {
111 transferTo(sourceMsg, dest, "out");
112 }
113
114 public static void transferFaultToFault(MessageExchange source, MessageExchange dest) throws MessagingException {
115 transferToFault(source.getFault(), dest);
116 }
117
118 public static void transferToFault(Fault fault, MessageExchange dest) throws MessagingException {
119 transferTo(fault, dest, "fault");
120 }
121
122 public static void transferTo(NormalizedMessage sourceMsg, MessageExchange dest, String name) throws MessagingException {
123 NormalizedMessage destMsg = (sourceMsg instanceof Fault) ? dest.createFault() : dest.createMessage();
124 transfer(sourceMsg, destMsg);
125 dest.setMessage(destMsg, name);
126 }
127
128 public static void transferTo(MessageExchange source, MessageExchange dest, String name) throws MessagingException {
129 NormalizedMessage sourceMsg = source.getMessage(name);
130 NormalizedMessage destMsg = (sourceMsg instanceof Fault) ? dest.createFault() : dest.createMessage();
131 transfer(sourceMsg, destMsg);
132 dest.setMessage(destMsg, name);
133 }
134
135 /**
136 * Convert the given {@link NormalizedMessage} instance's content to a re-readable {@link Source} This allows the
137 * content to be read more than once (e.g. for XPath evaluation or auditing).
138 *
139 * @param message
140 * the {@link NormalizedMessage} to convert the content for
141 * @throws MessagingException
142 */
143 public static void enableContentRereadability(NormalizedMessage message) throws MessagingException {
144 if (message.getContent() instanceof StreamSource
145 || message.getContent() instanceof SAXSource) {
146 try {
147 String content = new SourceTransformer().contentToString(message);
148 if (content != null) {
149 message.setContent(new StringSource(content));
150 }
151 } catch (TransformerException e) {
152 throw new MessagingException("Unable to convert message content into StringSource", e);
153 } catch (ParserConfigurationException e) {
154 throw new MessagingException("Unable to convert message content into StringSource", e);
155 } catch (IOException e) {
156 throw new MessagingException("Unable to convert message content into StringSource", e);
157 } catch (SAXException e) {
158 throw new MessagingException("Unable to convert message content into StringSource", e);
159 }
160 }
161 }
162
163 public static class NormalizedMessageImpl implements NormalizedMessage, Serializable {
164
165 private static final long serialVersionUID = -5813947566001096708L;
166
167 private Subject subject;
168 private Source content;
169 private Map properties = new HashMap();
170 private Map attachments = new HashMap();
171
172 public NormalizedMessageImpl() {
173 }
174
175 public NormalizedMessageImpl(NormalizedMessage message) throws MessagingException {
176 try {
177 String str = new SourceTransformer().contentToString(message);
178 if (str != null) {
179 this.content = new StringSource(str);
180 }
181 for (Iterator it = message.getPropertyNames().iterator(); it.hasNext();) {
182 String name = (String) it.next();
183 this.properties.put(name, message.getProperty(name));
184 }
185 for (Iterator it = message.getAttachmentNames().iterator(); it.hasNext();) {
186 String name = (String) it.next();
187 DataHandler dh = message.getAttachment(name);
188 DataSource ds = dh.getDataSource();
189 if (!(ds instanceof ByteArrayDataSource)) {
190 ByteArrayOutputStream baos = new ByteArrayOutputStream();
191 copyInputStream(ds.getInputStream(), baos);
192 ByteArrayDataSource bads = new ByteArrayDataSource(baos.toByteArray(), ds.getContentType());
193 bads.setName(ds.getName());
194 dh = new DataHandler(bads);
195 }
196 this.attachments.put(name, dh);
197 }
198 this.subject = message.getSecuritySubject();
199 } catch (MessagingException e) {
200 throw e;
201 } catch (Exception e) {
202 throw new MessagingException(e);
203 }
204 }
205
206 public void addAttachment(String id, DataHandler data) throws MessagingException {
207 this.attachments.put(id, data);
208 }
209
210 public Source getContent() {
211 return content;
212 }
213
214 public DataHandler getAttachment(String id) {
215 return (DataHandler) this.attachments.get(id);
216 }
217
218 public Set getAttachmentNames() {
219 return this.attachments.keySet();
220 }
221
222 public void removeAttachment(String id) throws MessagingException {
223 this.attachments.remove(id);
224 }
225
226 public void setContent(Source content) throws MessagingException {
227 this.content = content;
228 }
229
230 public void setProperty(String name, Object value) {
231 this.properties.put(name, value);
232 }
233
234 public void setSecuritySubject(Subject sub) {
235 this.subject = sub;
236 }
237
238 public Set getPropertyNames() {
239 return this.properties.keySet();
240 }
241
242 public Object getProperty(String name) {
243 return this.properties.get(name);
244 }
245
246 public Subject getSecuritySubject() {
247 return this.subject;
248 }
249
250 }
251
252 public static class FaultImpl extends NormalizedMessageImpl implements Fault {
253 private static final long serialVersionUID = -6076815664102825860L;
254
255 public FaultImpl() {
256 }
257
258 public FaultImpl(Fault fault) throws MessagingException {
259 super(fault);
260 }
261 }
262
263 public static void copyInputStream(InputStream in, OutputStream out) throws IOException {
264 byte[] buffer = new byte[8192];
265 int len = in.read(buffer);
266 while (len >= 0) {
267 out.write(buffer, 0, len);
268 len = in.read(buffer);
269 }
270 in.close();
271 out.close();
272 }
273 }