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.io.Serializable; 020 import java.util.LinkedHashMap; 021 import java.util.Map; 022 023 import org.apache.camel.Exchange; 024 import org.apache.commons.logging.Log; 025 import org.apache.commons.logging.LogFactory; 026 027 /** 028 * Holder object for sending an exchange over a remote wire as a serialized object. 029 * This is usually configured using the <tt>transferExchange=true</tt> option on the endpoint. 030 * <p/> 031 * As opposed to normal usage where only the body part of the exchange is transfered over the wire, 032 * this holder object serializes the following fields over the wire: 033 * <ul> 034 * <li>in body</li> 035 * <li>out body</li> 036 * <li>in headers</li> 037 * <li>out headers</li> 038 * <li>fault body </li> 039 * <li>fault headers</li> 040 * <li>exchange properties</li> 041 * <li>exception</li> 042 * </ul> 043 * Any object that is not serializable will be skipped and Camel will log this at WARN level. 044 * 045 * @version $Revision: 769448 $ 046 */ 047 public class DefaultExchangeHolder implements Serializable { 048 049 private static final long serialVersionUID = 1L; 050 private static final transient Log LOG = LogFactory.getLog(DefaultExchangeHolder.class); 051 052 private Object inBody; 053 private Object outBody; 054 private Object faultBody; 055 private final Map<String, Object> inHeaders = new LinkedHashMap<String, Object>(); 056 private final Map<String, Object> outHeaders = new LinkedHashMap<String, Object>(); 057 private final Map<String, Object> properties = new LinkedHashMap<String, Object>(); 058 private final Map<String, Object> faultHeaders = new LinkedHashMap<String, Object>(); 059 private Exception exception; 060 061 /** 062 * Creates a payload object with the information from the given exchange. 063 * Only marshal the Serializable object 064 * 065 * @param exchange the exchange 066 * @return the holder object with information copied form the exchange 067 */ 068 public static DefaultExchangeHolder marshal(Exchange exchange) { 069 DefaultExchangeHolder payload = new DefaultExchangeHolder(); 070 071 payload.inBody = checkSerializableObject("in body", exchange, exchange.getIn().getBody()); 072 payload.inHeaders.putAll(checkMapSerializableObjects("in headers", exchange, exchange.getIn().getHeaders())); 073 if (exchange.hasOut()) { 074 payload.outBody = checkSerializableObject("out body", exchange, exchange.getOut().getBody()); 075 payload.outHeaders.putAll(checkMapSerializableObjects("out headers", exchange, exchange.getOut().getHeaders())); 076 } 077 if (exchange.hasFault()) { 078 payload.faultBody = checkSerializableObject("fault body", exchange, exchange.getFault().getBody()); 079 payload.faultHeaders.putAll(checkMapSerializableObjects("fault headers", exchange, exchange.getFault().getHeaders())); 080 } 081 payload.properties.putAll(checkMapSerializableObjects("exchange properties", exchange, exchange.getProperties())); 082 payload.exception = exchange.getException(); 083 084 return payload; 085 } 086 087 /** 088 * Transfers the information from the payload to the exchange. 089 * 090 * @param exchange the exchange to set values from the payload 091 * @param payload the payload with the values 092 */ 093 public static void unmarshal(Exchange exchange, DefaultExchangeHolder payload) { 094 exchange.getIn().setBody(payload.inBody); 095 exchange.getIn().setHeaders(payload.inHeaders); 096 if (payload.outBody != null) { 097 exchange.getOut().setBody(payload.outBody); 098 exchange.getOut().setHeaders(payload.outHeaders); 099 } 100 if (payload.faultBody != null) { 101 exchange.getFault().setBody(payload.faultBody); 102 exchange.getFault().setHeaders(payload.faultHeaders); 103 } 104 for (String key : payload.properties.keySet()) { 105 exchange.setProperty(key, payload.properties.get(key)); 106 } 107 exchange.setException(payload.exception); 108 } 109 110 public String toString() { 111 StringBuilder sb = new StringBuilder("DefaultExchangeHolder["); 112 sb.append("inBody=").append(inBody).append(", outBody=").append(outBody); 113 sb.append(", inHeaders=").append(inHeaders).append(", outHeaders=").append(outHeaders); 114 sb.append(", faultBody=").append(faultBody).append(", faultHeaders=").append(faultHeaders); 115 sb.append(", properties=").append(properties).append(", exception=").append(exception); 116 return sb.append(']').toString(); 117 } 118 119 private static Object checkSerializableObject(String type, Exchange exchange, Object object) { 120 if (object == null) { 121 return null; 122 } 123 124 Serializable converted = exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, object); 125 if (converted != null) { 126 return converted; 127 } else { 128 LOG.warn(type + " containig object: " + object + " of type: " + object.getClass().getCanonicalName() + " cannot be serialized, it will be excluded by the holder"); 129 return null; 130 } 131 } 132 133 private static Map<String, Object> checkMapSerializableObjects(String type, Exchange exchange, Map<String, Object> map) { 134 if (map == null) { 135 return null; 136 } 137 138 Map<String, Object> result = new LinkedHashMap<String, Object>(); 139 for (Map.Entry<String, Object> entry : map.entrySet()) { 140 Serializable converted = exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, entry.getValue()); 141 if (converted != null) { 142 result.put(entry.getKey(), converted); 143 } else { 144 LOG.warn(type + " containing object: " + entry.getValue() + " with key: " + entry.getKey() 145 + " cannot be serialized, it will be excluded by the holder"); 146 } 147 } 148 149 return result; 150 } 151 152 }