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.camel.impl;
018    
019    import java.util.HashMap;
020    import java.util.Map;
021    
022    import org.apache.camel.CamelContext;
023    import org.apache.camel.Exchange;
024    import org.apache.camel.ExchangePattern;
025    import org.apache.camel.Message;
026    import org.apache.camel.RuntimeCamelException;
027    import org.apache.camel.spi.UnitOfWork;
028    import org.apache.camel.util.UuidGenerator;
029    
030    /**
031     * A default implementation of {@link Exchange}
032     *
033     * @version $Revision: 37863 $
034     */
035    public class DefaultExchange implements Exchange {
036        private static final UuidGenerator DEFAULT_ID_GENERATOR = new UuidGenerator();
037        protected final CamelContext context;
038        private Map<String, Object> properties;
039        private Message in;
040        private Message out;
041        private Message fault;
042        private Throwable exception;
043        private String exchangeId;
044        private UnitOfWork unitOfWork;
045        private ExchangePattern pattern;
046    
047        public DefaultExchange(CamelContext context) {
048            this(context, ExchangePattern.InOnly);
049        }
050    
051        public DefaultExchange(CamelContext context, ExchangePattern pattern) {
052            this.context = context;
053            this.pattern = pattern;
054        }
055    
056        public DefaultExchange(DefaultExchange parent) {
057            this(parent.getContext(), parent.getPattern());
058            this.unitOfWork = parent.getUnitOfWork();
059        }
060    
061    
062        @Override
063        public String toString() {
064            return "Exchange[" + in + "]";
065        }
066    
067        public Exchange copy() {
068            Exchange exchange = newInstance();
069            exchange.copyFrom(this);
070            return exchange;
071        }
072    
073        public void copyFrom(Exchange exchange) {
074            if (exchange == this) {
075                return;
076            }
077            setProperties(safeCopy(exchange.getProperties()));
078    
079            // this can cause strangeness if we copy, say, a FileMessage onto an FtpExchange with overloaded getExchange() methods etc.
080            safeCopy(getIn(), exchange, exchange.getIn());
081            Message copyOut = exchange.getOut(false);
082            if (copyOut != null) {
083                safeCopy(getOut(true), exchange, copyOut);
084            }
085            Message copyFault = exchange.getFault(false);
086            if (copyFault != null) {
087                safeCopy(getFault(true), exchange, copyFault);
088            }
089            setException(exchange.getException());
090    
091            unitOfWork = exchange.getUnitOfWork();
092            pattern = exchange.getPattern();
093        }
094    
095        private static void safeCopy(Message message, Exchange exchange, Message that) {
096            if (message != null) {
097                message.copyFrom(that);
098            }
099        }
100    
101        private static Map<String, Object> safeCopy(Map<String, Object> properties) {
102            if (properties == null) {
103                return null;
104            }
105            return new HashMap<String, Object>(properties);
106        }
107    
108        private static Message safeCopy(Exchange exchange, Message message) {
109            if (message == null) {
110                return null;
111            }
112            Message answer = message.copy();
113            if (answer instanceof MessageSupport) {
114                MessageSupport messageSupport = (MessageSupport) answer;
115                messageSupport.setExchange(exchange);
116            }
117            return answer;
118        }
119    
120        public Exchange newInstance() {
121            return new DefaultExchange(this);
122        }
123    
124        public CamelContext getContext() {
125            return context;
126        }
127    
128        public Object getProperty(String name) {
129            if (properties != null) {
130                return properties.get(name);
131            }
132            return null;
133        }
134    
135        public <T> T getProperty(String name, Class<T> type) {
136            Object value = getProperty(name);
137            return getContext().getTypeConverter().convertTo(type, value);
138        }
139    
140        public void setProperty(String name, Object value) {
141            getProperties().put(name, value);
142        }
143    
144        public Object removeProperty(String name) {
145            return getProperties().remove(name);
146        }
147    
148        public Map<String, Object> getProperties() {
149            if (properties == null) {
150                properties = new HashMap<String, Object>();
151            }
152            return properties;
153        }
154    
155        public void setProperties(Map<String, Object> properties) {
156            this.properties = properties;
157        }
158    
159        public Message getIn() {
160            if (in == null) {
161                in = createInMessage();
162                configureMessage(in);
163            }
164            return in;
165        }
166    
167        public void setIn(Message in) {
168            this.in = in;
169            configureMessage(in);
170        }
171    
172        public Message getOut() {
173            return getOut(true);
174        }
175    
176        public Message getOut(boolean lazyCreate) {
177            if (out == null && lazyCreate) {
178                out = createOutMessage();
179                configureMessage(out);
180            }
181            return out;
182        }
183    
184        public void setOut(Message out) {
185            this.out = out;
186            configureMessage(out);
187        }
188    
189        public Throwable getException() {
190            return exception;
191        }
192    
193        public void setException(Throwable exception) {
194            this.exception = exception;
195        }
196    
197        public ExchangePattern getPattern() {
198            return pattern;
199        }
200    
201        public void setPattern(ExchangePattern pattern) {
202            this.pattern = pattern;
203        }
204    
205        public void throwException() throws Exception {
206            if (exception == null) {
207                return;
208            }
209            if (exception instanceof Exception) {
210                throw (Exception)exception;
211            }
212            if (exception instanceof RuntimeException) {
213                throw (RuntimeException)exception;
214            }
215            throw new RuntimeCamelException(exception);
216        }
217    
218        public Message getFault() {
219            return getFault(true);
220        }
221    
222        public Message getFault(boolean lazyCreate) {
223            if (fault == null && lazyCreate) {
224                fault = createFaultMessage();
225                configureMessage(fault);
226            }
227            return fault;
228        }
229    
230        public void setFault(Message fault) {
231            this.fault = fault;
232            configureMessage(fault);
233        }
234    
235        public String getExchangeId() {
236            if (exchangeId == null) {
237                exchangeId = DefaultExchange.DEFAULT_ID_GENERATOR.generateId();
238            }
239            return exchangeId;
240        }
241    
242        public void setExchangeId(String id) {
243            this.exchangeId = id;
244        }
245    
246        /**
247         * Returns true if this exchange failed due to either an exception or fault
248         *
249         * @see Exchange#getException()
250         * @see Exchange#getFault()
251         * @return true if this exchange failed due to either an exception or fault
252         */
253        public boolean isFailed() {
254            Message faultMessage = getFault(false);
255            if (faultMessage != null) {
256                Object faultBody = faultMessage.getBody();
257                if (faultBody != null) {
258                    return true;
259                }
260            }
261            return getException() != null;
262        }
263    
264        public UnitOfWork getUnitOfWork() {
265            return unitOfWork;
266        }
267    
268        public void setUnitOfWork(UnitOfWork unitOfWork) {
269            this.unitOfWork = unitOfWork;
270        }
271    
272        /**
273         * Factory method used to lazily create the IN message
274         */
275        protected Message createInMessage() {
276            return new DefaultMessage();
277        }
278    
279        /**
280         * Factory method to lazily create the OUT message
281         */
282        protected Message createOutMessage() {
283            return new DefaultMessage();
284        }
285    
286        /**
287         * Factory method to lazily create the FAULT message
288         */
289        protected Message createFaultMessage() {
290            return new DefaultMessage();
291        }
292    
293        /**
294         * Configures the message after it has been set on the exchange
295         */
296        protected void configureMessage(Message message) {
297            if (message instanceof MessageSupport) {
298                MessageSupport messageSupport = (MessageSupport)message;
299                messageSupport.setExchange(this);
300            }
301        }
302    
303    }