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