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 }