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.ByteArrayInputStream;
020    import java.io.ByteArrayOutputStream;
021    import java.io.Externalizable;
022    import java.io.IOException;
023    import java.io.ObjectInput;
024    import java.io.ObjectInputStream;
025    import java.io.ObjectOutput;
026    import java.io.ObjectOutputStream;
027    import java.net.URI;
028    import java.util.Collections;
029    import java.util.HashMap;
030    import java.util.Map;
031    import java.util.Set;
032    
033    import javax.jbi.messaging.ExchangeStatus;
034    import javax.jbi.messaging.Fault;
035    import javax.jbi.messaging.MessagingException;
036    import javax.jbi.messaging.NormalizedMessage;
037    import javax.jbi.servicedesc.ServiceEndpoint;
038    import javax.transaction.Transaction;
039    import javax.xml.namespace.QName;
040    
041    import org.apache.servicemix.components.util.CopyTransformer;
042    import org.apache.servicemix.jbi.framework.ComponentNameSpace;
043    
044    /**
045     * ExchangePacket is responsible for carrying MessageExchange payloads
046     * 
047     * @version $Revision: 564607 $
048     */
049    public class ExchangePacket implements Externalizable {
050    
051        private static final long serialVersionUID = -9110837382914609624L;
052    
053        protected URI pattern;
054    
055        protected String exchangeId;
056    
057        protected ComponentNameSpace destinationId;
058    
059        protected ComponentNameSpace sourceId;
060    
061        protected ExchangeStatus status = ExchangeStatus.ACTIVE;
062    
063        protected QName serviceName;
064    
065        protected QName interfaceName;
066    
067        protected QName operationName;
068    
069        protected Exception error;
070    
071        protected Map properties;
072    
073        protected NormalizedMessageImpl in;
074    
075        protected NormalizedMessageImpl out;
076    
077        protected FaultImpl fault;
078    
079        protected ServiceEndpoint endpoint;
080    
081        protected transient Transaction transactionContext;
082    
083        protected Boolean persistent;
084    
085        protected boolean aborted;
086    
087        public ExchangePacket() {
088        }
089    
090        public ExchangePacket(ExchangePacket packet) throws MessagingException {
091            this.destinationId = packet.destinationId;
092            this.endpoint = null; // packet.endpoint;
093            this.error = null;
094            this.exchangeId = null; // ???;
095            this.interfaceName = packet.interfaceName;
096            CopyTransformer ct = new CopyTransformer();
097            if (packet.in != null) {
098                in = new NormalizedMessageImpl();
099                ct.transform(null, packet.in, in);
100            }
101            if (packet.out != null) {
102                out = new NormalizedMessageImpl();
103                ct.transform(null, packet.out, out);
104            }
105            if (packet.fault != null) {
106                fault = new FaultImpl();
107                ct.transform(null, packet.fault, fault);
108            }
109            this.operationName = packet.operationName;
110            this.pattern = packet.pattern;
111            if (packet.properties != null && packet.properties.size() > 0) {
112                getProperties().putAll(packet.properties);
113            }
114            this.serviceName = packet.serviceName;
115            this.sourceId = packet.sourceId;
116            this.status = packet.status;
117            this.transactionContext = packet.transactionContext;
118            this.persistent = packet.persistent;
119        }
120    
121        /**
122         * @return Returns the endpoint.
123         */
124        public ServiceEndpoint getEndpoint() {
125            return endpoint;
126        }
127    
128        /**
129         * @param endpoint
130         *            The endpoint to set.
131         */
132        public void setEndpoint(ServiceEndpoint endpoint) {
133            this.endpoint = endpoint;
134        }
135    
136        /**
137         * @return Returns the transactionContext.
138         */
139        public Transaction getTransactionContext() {
140            return transactionContext;
141        }
142    
143        /**
144         * @param transactionContext
145         *            The transactionContext to set.
146         */
147        public void setTransactionContext(Transaction transactionContext) {
148            this.transactionContext = transactionContext;
149        }
150    
151        /**
152         * @return Returns the interfaceName.
153         */
154        public QName getInterfaceName() {
155            return interfaceName;
156        }
157    
158        /**
159         * @param interfaceName
160         *            The interfaceName to set.
161         */
162        public void setInterfaceName(QName interfaceName) {
163            this.interfaceName = interfaceName;
164        }
165    
166        /**
167         * @return Returns the operationName.
168         */
169        public QName getOperationName() {
170            return operationName;
171        }
172    
173        /**
174         * @param operationName
175         *            The operationName to set.
176         */
177        public void setOperationName(QName operationName) {
178            this.operationName = operationName;
179        }
180    
181        /**
182         * @return Returns the serviceName.
183         */
184        public QName getServiceName() {
185            return serviceName;
186        }
187    
188        /**
189         * @param serviceName
190         *            The serviceName to set.
191         */
192        public void setServiceName(QName serviceName) {
193            this.serviceName = serviceName;
194        }
195    
196        /**
197         * @param status
198         *            The status to set.
199         */
200        public void setStatus(ExchangeStatus status) {
201            this.status = status;
202        }
203    
204        /**
205         * @return the status
206         */
207        public ExchangeStatus getStatus() {
208            return status;
209        }
210    
211        /**
212         * @return Returns the pattern.
213         */
214        public URI getPattern() {
215            return pattern;
216        }
217    
218        /**
219         * @param pattern
220         *            The pattern to set.
221         */
222        public void setPattern(URI pattern) {
223            this.pattern = pattern;
224        }
225    
226        /**
227         * @return Returns the error.
228         */
229        public Exception getError() {
230            return error;
231        }
232    
233        /**
234         * @param error
235         *            The error to set.
236         */
237        public void setError(Exception error) {
238            this.error = error;
239            this.status = ExchangeStatus.ERROR;
240        }
241    
242        /**
243         * @return Returns the exchangeId.
244         */
245        public String getExchangeId() {
246            return exchangeId;
247        }
248    
249        /**
250         * @param exchangeId
251         *            The exchangeId to set.
252         */
253        public void setExchangeId(String exchangeId) {
254            this.exchangeId = exchangeId;
255        }
256    
257        /**
258         * @return Returns the properties.
259         */
260        public Map getProperties() {
261            if (properties == null) {
262                // No need to have concurrent access, as the
263                // message exchange can only be used from a single thread at a time
264                properties = new HashMap();
265            }
266            return properties;
267        }
268    
269        /**
270         * @param name
271         * @return the property from the exchange
272         */
273        public Object getProperty(String name) {
274            if (properties != null) {
275                return properties.get(name);
276            }
277            return null;
278        }
279    
280        /**
281         * set a named property on the exchange
282         * 
283         * @param name
284         * @param value
285         */
286        public void setProperty(String name, Object value) {
287            if (value == null) {
288                if (properties != null) {
289                    properties.remove(name);
290                }
291            } else {
292                getProperties().put(name, value);
293            }
294        }
295    
296        /**
297         * @return property names
298         */
299        public Set getPropertyNames() {
300            if (properties != null) {
301                return Collections.unmodifiableSet(properties.keySet());
302            }
303            return Collections.EMPTY_SET;
304        }
305    
306        /**
307         * @return Returns the sourceId.
308         */
309        public ComponentNameSpace getSourceId() {
310            return sourceId;
311        }
312    
313        /**
314         * @param sourceId
315         *            The sourceId to set.
316         */
317        public void setSourceId(ComponentNameSpace sourceId) {
318            this.sourceId = sourceId;
319        }
320    
321        /**
322         * @return Returns the destinationId.
323         */
324        public ComponentNameSpace getDestinationId() {
325            return destinationId;
326        }
327    
328        /**
329         * @param destinationId
330         *            The destinationId to set.
331         */
332        public void setDestinationId(ComponentNameSpace destinationId) {
333            this.destinationId = destinationId;
334        }
335    
336        /**
337         * @return Returns the fault.
338         */
339        public Fault getFault() {
340            return fault;
341        }
342    
343        /**
344         * @param fault
345         *            The fault to set.
346         */
347        public void setFault(FaultImpl fault) {
348            this.fault = fault;
349        }
350    
351        /**
352         * @return Returns the in.
353         */
354        public NormalizedMessage getIn() {
355            return in;
356        }
357    
358        /**
359         * @param in
360         *            The in to set.
361         */
362        public void setIn(NormalizedMessageImpl in) {
363            this.in = in;
364        }
365    
366        /**
367         * @return Returns the out.
368         */
369        public NormalizedMessage getOut() {
370            return out;
371        }
372    
373        /**
374         * @param out
375         *            The out to set.
376         */
377        public void setOut(NormalizedMessageImpl out) {
378            this.out = out;
379        }
380    
381        /**
382         * @return pretty print
383         */
384        public String toString() {
385            return "ExchangePacket[: id=" + exchangeId + ", serviceDest=" + serviceName + ",endpoint=" + endpoint + "]";
386        }
387    
388        /**
389         * Write to a Stream
390         * 
391         * @param output
392         * @throws IOException
393         */
394        public void writeExternal(ObjectOutput output) throws IOException {
395            output.writeUTF(pattern.toString());
396            output.writeUTF(exchangeId != null ? exchangeId : "");
397            output.writeUTF(status.toString());
398            output.writeObject(destinationId);
399            output.writeObject(sourceId);
400            output.writeObject(serviceName);
401            output.writeObject(interfaceName);
402            output.writeObject(operationName);
403            output.writeObject(error);
404            output.writeObject(properties);
405            output.writeObject(in);
406            output.writeObject(out);
407            output.writeObject(fault);
408            output.writeObject(endpoint);
409            output.writeByte((persistent == null) ? 0 : persistent.booleanValue() ? 1 : 2);
410        }
411    
412        /**
413         * Read from a stream
414         * 
415         * @param input
416         * @throws IOException
417         * @throws ClassNotFoundException
418         */
419        public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
420            pattern = URI.create(input.readUTF());
421            exchangeId = input.readUTF();
422            status = ExchangeStatus.valueOf(input.readUTF());
423            destinationId = (ComponentNameSpace) input.readObject();
424            sourceId = (ComponentNameSpace) input.readObject();
425            serviceName = (QName) input.readObject();
426            interfaceName = (QName) input.readObject();
427            operationName = (QName) input.readObject();
428            error = (Exception) input.readObject();
429            properties = (Map) input.readObject();
430            in = (NormalizedMessageImpl) input.readObject();
431            out = (NormalizedMessageImpl) input.readObject();
432            fault = (FaultImpl) input.readObject();
433            endpoint = (ServiceEndpoint) input.readObject();
434            byte p = input.readByte();
435            persistent = (p == 0) ? null : p == 1 ? Boolean.TRUE : Boolean.FALSE;
436        }
437    
438        /**
439         * Creates a copy of the packet so it can be sent to another destination
440         * 
441         * @throws MessagingException
442         */
443        public ExchangePacket copy() throws MessagingException {
444            return new ExchangePacket(this);
445        }
446    
447        public Boolean getPersistent() {
448            return persistent;
449        }
450    
451        public void setPersistent(Boolean persistent) {
452            this.persistent = persistent;
453        }
454    
455        public boolean isAborted() {
456            return aborted;
457        }
458    
459        public void setAborted(boolean timedOut) {
460            this.aborted = timedOut;
461        }
462    
463        /**
464         * Retrieve the serialized from of this packet
465         * 
466         * @return the serialized packet
467         * @throws IOException
468         */
469        public byte[] getData() throws IOException {
470            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
471            ObjectOutputStream os = new ObjectOutputStream(buffer);
472            os.writeObject(this);
473            os.close();
474            return buffer.toByteArray();
475        }
476    
477        /**
478         * Deserialize an ExchangePacket.
479         * 
480         * @param data
481         *            the serialized packet
482         * @return the deserialized packet
483         * @throws IOException
484         * @throws ClassNotFoundException
485         */
486        public static ExchangePacket readPacket(byte[] data) throws IOException, ClassNotFoundException {
487            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
488            return (ExchangePacket) ois.readObject();
489        }
490    
491    }