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