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
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 */
034 public 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 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 * Allow implementations to auto-create a messageId
190 */
191 protected String createMessageId() {
192 String uuid = null;
193 if (exchange != null) {
194 uuid = exchange.getContext().getUuidGenerator().generateUuid();
195 }
196 // fall back to the simple UUID generator
197 if (uuid == null) {
198 uuid = new SimpleUuidGenerator().generateUuid();
199 }
200 return uuid;
201 }
202 }