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    }