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 */ 017package org.apache.camel.impl; 018 019import org.apache.camel.Exchange; 020import org.apache.camel.InvalidPayloadException; 021import org.apache.camel.Message; 022import org.apache.camel.TypeConverter; 023 024/** 025 * A base class for implementation inheritance providing the core 026 * {@link Message} body handling features but letting the derived class deal 027 * with headers. 028 * 029 * Unless a specific provider wishes to do something particularly clever with 030 * headers you probably want to just derive from {@link DefaultMessage} 031 * 032 * @version 033 */ 034public abstract class MessageSupport implements Message { 035 private Exchange exchange; 036 private Object body; 037 private String messageId; 038 039 public Object getBody() { 040 if (body == null) { 041 body = createBody(); 042 } 043 return body; 044 } 045 046 public <T> T getBody(Class<T> type) { 047 return getBody(type, getBody()); 048 } 049 050 public Object getMandatoryBody() throws InvalidPayloadException { 051 Object answer = getBody(); 052 if (answer == null) { 053 throw new InvalidPayloadException(getExchange(), Object.class, this); 054 } 055 return answer; 056 } 057 058 protected <T> T getBody(Class<T> type, Object body) { 059 // eager same instance type test to avoid the overhead of invoking the type converter 060 // if already same type 061 if (type.isInstance(body)) { 062 return type.cast(body); 063 } 064 065 Exchange e = getExchange(); 066 if (e != null) { 067 TypeConverter converter = e.getContext().getTypeConverter(); 068 069 // lets first try converting the body itself first 070 // as for some types like InputStream v Reader its more efficient to do the transformation 071 // from the body itself as its got efficient implementations of them, before trying the message 072 T answer = converter.convertTo(type, e, body); 073 if (answer != null) { 074 return answer; 075 } 076 077 // fallback and try the message itself (e.g. used in camel-http) 078 answer = converter.tryConvertTo(type, e, this); 079 if (answer != null) { 080 return answer; 081 } 082 } 083 084 // not possible to convert 085 return null; 086 } 087 088 public <T> T getMandatoryBody(Class<T> type) throws InvalidPayloadException { 089 // eager same instance type test to avoid the overhead of invoking the type converter 090 // if already same type 091 if (type.isInstance(body)) { 092 return type.cast(body); 093 } 094 095 Exchange e = getExchange(); 096 if (e != null) { 097 TypeConverter converter = e.getContext().getTypeConverter(); 098 try { 099 return converter.mandatoryConvertTo(type, e, getBody()); 100 } catch (Exception cause) { 101 throw new InvalidPayloadException(e, type, this, cause); 102 } 103 } 104 throw new InvalidPayloadException(e, type, this); 105 } 106 107 public void setBody(Object body) { 108 this.body = body; 109 } 110 111 public <T> void setBody(Object value, Class<T> type) { 112 Exchange e = getExchange(); 113 if (e != null) { 114 T v = e.getContext().getTypeConverter().convertTo(type, e, value); 115 if (v != null) { 116 value = v; 117 } 118 } 119 setBody(value); 120 } 121 122 public Message copy() { 123 Message answer = newInstance(); 124 answer.copyFrom(this); 125 return answer; 126 } 127 128 public void copyFrom(Message that) { 129 if (that == this) { 130 // the same instance so do not need to copy 131 return; 132 } 133 134 setMessageId(that.getMessageId()); 135 setBody(that.getBody()); 136 setFault(that.isFault()); 137 138 // the headers may be the same instance if the end user has made some mistake 139 // and set the OUT message with the same header instance of the IN message etc 140 boolean sameHeadersInstance = false; 141 if (hasHeaders() && that.hasHeaders() && getHeaders() == that.getHeaders()) { 142 sameHeadersInstance = true; 143 } 144 145 if (!sameHeadersInstance) { 146 if (hasHeaders()) { 147 // okay its safe to clear the headers 148 getHeaders().clear(); 149 } 150 if (that.hasHeaders()) { 151 getHeaders().putAll(that.getHeaders()); 152 } 153 } 154 155 copyAttachments(that); 156 } 157 158 public Exchange getExchange() { 159 return exchange; 160 } 161 162 public void setExchange(Exchange exchange) { 163 this.exchange = exchange; 164 } 165 166 public void copyAttachments(Message that) { 167 // the attachments may be the same instance if the end user has made some mistake 168 // and set the OUT message with the same attachment instance of the IN message etc 169 boolean sameAttachments = false; 170 if (hasAttachments() && that.hasAttachments() && getAttachments() == that.getAttachments()) { 171 sameAttachments = true; 172 } 173 174 if (!sameAttachments) { 175 if (hasAttachments()) { 176 // okay its safe to clear the attachments 177 getAttachments().clear(); 178 } 179 if (that.hasAttachments()) { 180 getAttachments().putAll(that.getAttachments()); 181 } 182 } 183 } 184 185 /** 186 * Returns a new instance 187 */ 188 public abstract Message newInstance(); 189 190 /** 191 * A factory method to allow a provider to lazily create the message body 192 * for inbound messages from other sources 193 * 194 * @return the value of the message body or null if there is no value 195 * available 196 */ 197 protected Object createBody() { 198 return null; 199 } 200 201 public String getMessageId() { 202 if (messageId == null) { 203 messageId = createMessageId(); 204 } 205 return this.messageId; 206 } 207 208 public void setMessageId(String messageId) { 209 this.messageId = messageId; 210 } 211 212 /** 213 * Allow implementations to auto-create a messageId 214 */ 215 protected String createMessageId() { 216 String uuid = null; 217 if (exchange != null) { 218 uuid = exchange.getContext().getUuidGenerator().generateUuid(); 219 } 220 // fall back to the simple UUID generator 221 if (uuid == null) { 222 uuid = new SimpleUuidGenerator().generateUuid(); 223 } 224 return uuid; 225 } 226}