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