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    }