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 // 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 if (hasAttachments()) { 156 getAttachments().clear(); 157 } 158 if (that.hasAttachments()) { 159 getAttachments().putAll(that.getAttachments()); 160 } 161 } 162 163 public Exchange getExchange() { 164 return exchange; 165 } 166 167 public void setExchange(Exchange exchange) { 168 this.exchange = exchange; 169 } 170 171 /** 172 * Returns a new instance 173 */ 174 public abstract Message newInstance(); 175 176 /** 177 * A factory method to allow a provider to lazily create the message body 178 * for inbound messages from other sources 179 * 180 * @return the value of the message body or null if there is no value 181 * available 182 */ 183 protected Object createBody() { 184 return null; 185 } 186 187 public String getMessageId() { 188 if (messageId == null) { 189 messageId = createMessageId(); 190 } 191 return this.messageId; 192 } 193 194 public void setMessageId(String messageId) { 195 this.messageId = messageId; 196 } 197 198 /** 199 * Allow implementations to auto-create a messageId 200 */ 201 protected String createMessageId() { 202 String uuid = null; 203 if (exchange != null) { 204 uuid = exchange.getContext().getUuidGenerator().generateUuid(); 205 } 206 // fall back to the simple UUID generator 207 if (uuid == null) { 208 uuid = new SimpleUuidGenerator().generateUuid(); 209 } 210 return uuid; 211 } 212 }