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 }