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    }