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.jbi.messaging;
018:
019: import java.io.ByteArrayOutputStream;
020: import java.io.Externalizable;
021: import java.io.IOException;
022: import java.io.ObjectInput;
023: import java.io.ObjectOutput;
024: import java.util.Collections;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.Map;
028: import java.util.Set;
029:
030: import javax.activation.DataHandler;
031: import javax.activation.DataSource;
032: import javax.jbi.messaging.Fault;
033: import javax.jbi.messaging.MessageExchange;
034: import javax.jbi.messaging.MessagingException;
035: import javax.jbi.messaging.NormalizedMessage;
036: import javax.security.auth.Subject;
037: import javax.xml.transform.Source;
038: import javax.xml.transform.TransformerException;
039: import javax.xml.transform.sax.SAXSource;
040: import javax.xml.transform.stream.StreamSource;
041:
042: import org.apache.servicemix.client.Message;
043: import org.apache.servicemix.jbi.RuntimeJBIException;
044: import org.apache.servicemix.jbi.jaxp.BytesSource;
045: import org.apache.servicemix.jbi.jaxp.ResourceSource;
046: import org.apache.servicemix.jbi.jaxp.SourceTransformer;
047: import org.apache.servicemix.jbi.jaxp.StringSource;
048: import org.apache.servicemix.jbi.util.ByteArrayDataSource;
049: import org.apache.servicemix.jbi.util.FileUtil;
050:
051: /**
052: * Represents a JBI NormalizedMessage.
053: *
054: * @version $Revision: 631288 $
055: */
056: public class NormalizedMessageImpl implements NormalizedMessage,
057: Externalizable, Message {
058:
059: private static final long serialVersionUID = 9179194301410526549L;
060:
061: private static final SourceTransformer TRANSFORMER = new SourceTransformer();
062:
063: protected transient MessageExchangeImpl exchange;
064:
065: private transient Source content;
066:
067: private transient Object body;
068:
069: private Subject securitySubject;
070:
071: private Map properties;
072:
073: private Map attachments;
074:
075: /**
076: * Constructor
077: *
078: */
079: public NormalizedMessageImpl() {
080: }
081:
082: /**
083: * Constructor
084: *
085: * @param exchange
086: */
087: public NormalizedMessageImpl(MessageExchangeImpl exchange) {
088: this .exchange = exchange;
089: }
090:
091: /**
092: * @return the content of the message
093: */
094: public Source getContent() {
095: if (content == null && body != null) {
096: try {
097: getMarshaler().marshal(exchange, this , body);
098: } catch (MessagingException e) {
099: throw new RuntimeJBIException(e);
100: }
101: }
102: return content;
103: }
104:
105: /**
106: * set the content fo the message
107: *
108: * @param source
109: */
110: public void setContent(Source source) {
111: this .content = source;
112: }
113:
114: /**
115: * @return the security subject from the message
116: */
117: public Subject getSecuritySubject() {
118: return securitySubject;
119: }
120:
121: /**
122: * set the security subject
123: *
124: * @param securitySubject
125: */
126: public void setSecuritySubject(Subject securitySubject) {
127: this .securitySubject = securitySubject;
128: }
129:
130: /**
131: * get a named property
132: *
133: * @param name
134: * @return a property from the message
135: */
136: public Object getProperty(String name) {
137: if (properties != null) {
138: return properties.get(name);
139: }
140: return null;
141: }
142:
143: /**
144: * @return an iterator of property names
145: */
146: public Set getPropertyNames() {
147: if (properties != null) {
148: return Collections.unmodifiableSet(properties.keySet());
149: }
150: return Collections.EMPTY_SET;
151: }
152:
153: /**
154: * set a property
155: *
156: * @param name
157: * @param value
158: */
159: public void setProperty(String name, Object value) {
160: if (value == null) {
161: if (properties != null) {
162: properties.remove(name);
163: }
164: } else {
165: getProperties().put(name, value);
166: }
167: }
168:
169: /**
170: * Add an attachment
171: *
172: * @param id
173: * @param handler
174: */
175: public void addAttachment(String id, DataHandler handler) {
176: getAttachments().put(id, handler.getDataSource());
177: }
178:
179: /**
180: * Get a named attachement
181: *
182: * @param id the id of the stored attachment
183: * @return the specified attachment or null if no attachment found for id
184: */
185: public DataHandler getAttachment(String id) {
186: if (attachments != null && attachments.get(id) != null) {
187: return new DataHandler((DataSource) attachments.get(id));
188: }
189: return null;
190: }
191:
192: /**
193: * @return a list of identifiers for atachments
194: */
195: public Iterator listAttachments() {
196: if (attachments != null) {
197: return attachments.keySet().iterator();
198: }
199: return Collections.EMPTY_LIST.iterator();
200: }
201:
202: /**
203: * remove an identified attachment
204: *
205: * @param id
206: */
207: public void removeAttachment(String id) {
208: if (attachments != null) {
209: attachments.remove(id);
210: }
211: }
212:
213: /**
214: * Returns a list of identifiers for each attachment to the message.
215: *
216: * @return iterator over String attachment identifiers
217: */
218: public Set getAttachmentNames() {
219: if (attachments != null) {
220: return Collections.unmodifiableSet(attachments.keySet());
221: }
222: return Collections.EMPTY_SET;
223: }
224:
225: public String toString() {
226: return super .toString() + "{properties: " + getProperties()
227: + "}";
228: }
229:
230: // Scripting helper methods to add expressive power
231: // when using languages like Groovy, Velocity etc
232: // -------------------------------------------------------------------------
233:
234: public Object getBody() throws MessagingException {
235: if (body == null) {
236: body = getMarshaler().unmarshal(exchange, this );
237: }
238: return body;
239: }
240:
241: public Object getBody(PojoMarshaler marshaler)
242: throws MessagingException {
243: return marshaler.unmarshal(exchange, this );
244: }
245:
246: public void setBody(Object body) throws MessagingException {
247: this .body = body;
248: }
249:
250: public String getBodyText() throws TransformerException {
251: return TRANSFORMER.toString(getContent());
252: }
253:
254: public void setBodyText(String xml) {
255: setContent(new StringSource(xml));
256: }
257:
258: public PojoMarshaler getMarshaler() {
259: return exchange.getMarshaler();
260: }
261:
262: public MessageExchange getExchange() {
263: return exchange;
264: }
265:
266: public Fault createFault() throws MessagingException {
267: return getExchange().createFault();
268: }
269:
270: // Implementation methods
271: // -------------------------------------------------------------------------
272: protected Map getProperties() {
273: if (properties == null) {
274: properties = createPropertiesMap();
275: }
276: return properties;
277: }
278:
279: protected Map getAttachments() {
280: if (attachments == null) {
281: attachments = createAttachmentsMap();
282: }
283: return attachments;
284: }
285:
286: protected void setAttachments(Map attachments) {
287: this .attachments = attachments;
288: }
289:
290: protected void setProperties(Map properties) {
291: this .properties = properties;
292: }
293:
294: protected Map createPropertiesMap() {
295: // Normalized exchanges do not need to be thread-safe
296: return new HashMap();
297: }
298:
299: protected Map createAttachmentsMap() {
300: // Normalized exchanges do not need to be thread-safe
301: return new HashMap();
302: }
303:
304: /**
305: * Write to a Stream
306: *
307: * @param out
308: * @throws IOException
309: */
310: public void writeExternal(ObjectOutput out) throws IOException {
311: try {
312: convertAttachments();
313: out.writeObject(attachments);
314: out.writeObject(properties);
315: String src = TRANSFORMER.toString(content);
316: out.writeObject(src);
317: // We have read the source
318: // so now, ensure that it can be re-read
319: if ((content instanceof StreamSource || content instanceof SAXSource)
320: && !(content instanceof StringSource)
321: && !(content instanceof BytesSource)
322: && !(content instanceof ResourceSource)) {
323: content = new StringSource(src);
324: }
325: } catch (TransformerException e) {
326: throw (IOException) new IOException(
327: "Could not transform content to string")
328: .initCause(e);
329: }
330: }
331:
332: private void convertAttachments() throws IOException {
333: if (attachments != null) {
334: Map newAttachments = createAttachmentsMap();
335: for (Iterator it = attachments.keySet().iterator(); it
336: .hasNext();) {
337: String name = (String) it.next();
338: DataSource ds = (DataSource) attachments.get(name);
339: if (ds instanceof ByteArrayDataSource) {
340: newAttachments.put(name, ds);
341: } else {
342: ByteArrayOutputStream baos = new ByteArrayOutputStream();
343: FileUtil.copyInputStream(ds.getInputStream(), baos);
344: ByteArrayDataSource bads = new ByteArrayDataSource(
345: baos.toByteArray(), ds.getContentType());
346: bads.setName(ds.getName());
347: newAttachments.put(name, bads);
348: }
349: }
350: attachments = newAttachments;
351: }
352: }
353:
354: /**
355: * Read from a stream
356: *
357: * @param in
358: * @throws IOException
359: * @throws ClassNotFoundException
360: */
361: public void readExternal(ObjectInput in) throws IOException,
362: ClassNotFoundException {
363: attachments = (Map) in.readObject();
364: properties = (Map) in.readObject();
365: String src = (String) in.readObject();
366: if (src != null) {
367: content = new StringSource(src);
368: }
369: }
370:
371: }
|