| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.camel.impl; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| import javax.activation.DataHandler; |
| |
| import org.apache.camel.Exchange; |
| import org.apache.camel.Message; |
| import org.apache.camel.util.CaseInsensitiveMap; |
| import org.apache.camel.util.EndpointHelper; |
| import org.apache.camel.util.MessageHelper; |
| |
| /** |
| * The default implementation of {@link org.apache.camel.Message} |
| * <p/> |
| * This implementation uses a {@link org.apache.camel.util.CaseInsensitiveMap} storing the headers. |
| * This allows us to be able to lookup headers using case insensitive keys, making it easier for end users |
| * as they do not have to be worried about using exact keys. |
| * See more details at {@link org.apache.camel.util.CaseInsensitiveMap}. |
| * |
| * @version $Revision$ |
| */ |
| public class DefaultMessage extends MessageSupport { |
| private boolean fault; |
| private Map<String, Object> headers; |
| private Map<String, DataHandler> attachments; |
| |
| @Override |
| public String toString() { |
| return MessageHelper.extractBodyForLogging(this); |
| } |
| |
| @Override |
| public void copyFrom(Message that) { |
| super.copyFrom(that); |
| fault = that.isFault(); |
| } |
| |
| public boolean isFault() { |
| return fault; |
| } |
| |
| public void setFault(boolean fault) { |
| this.fault = fault; |
| } |
| |
| public Object getHeader(String name) { |
| return getHeaders().get(name); |
| } |
| |
| public Object getHeader(String name, Object defaultValue) { |
| Object answer = getHeaders().get(name); |
| return answer != null ? answer : defaultValue; |
| } |
| |
| public <T> T getHeader(String name, Class<T> type) { |
| Object value = getHeader(name); |
| if (value == null) { |
| return null; |
| } |
| |
| // eager same instance type test to avoid the overhead of invoking the type converter |
| // if already same type |
| if (type.isInstance(value)) { |
| return type.cast(value); |
| } |
| |
| Exchange e = getExchange(); |
| if (e != null) { |
| return e.getContext().getTypeConverter().convertTo(type, e, value); |
| } else { |
| return type.cast(value); |
| } |
| } |
| |
| public <T> T getHeader(String name, Object defaultValue, Class<T> type) { |
| Object value = getHeader(name, defaultValue); |
| |
| // eager same instance type test to avoid the overhead of invoking the type converter |
| // if already same type |
| if (type.isInstance(value)) { |
| return type.cast(value); |
| } |
| |
| Exchange e = getExchange(); |
| if (e != null) { |
| return e.getContext().getTypeConverter().convertTo(type, e, value); |
| } else { |
| return type.cast(value); |
| } |
| } |
| |
| public void setHeader(String name, Object value) { |
| if (headers == null) { |
| headers = createHeaders(); |
| } |
| headers.put(name, value); |
| } |
| |
| public Object removeHeader(String name) { |
| if (!hasHeaders()) { |
| return null; |
| } |
| return headers.remove(name); |
| } |
| |
| public boolean removeHeaders(String pattern) { |
| if (!hasHeaders()) { |
| return false; |
| } |
| |
| boolean matches = false; |
| for (Map.Entry<String, Object> entry : headers.entrySet()) { |
| String key = entry.getKey(); |
| if (EndpointHelper.matchPattern(key, pattern)) { |
| matches = true; |
| headers.remove(entry.getKey()); |
| } |
| } |
| return matches; |
| } |
| |
| public Map<String, Object> getHeaders() { |
| if (headers == null) { |
| headers = createHeaders(); |
| } |
| return headers; |
| } |
| |
| public void setHeaders(Map<String, Object> headers) { |
| if (headers instanceof CaseInsensitiveMap) { |
| this.headers = headers; |
| } else { |
| // wrap it in a case insensitive map |
| this.headers = new CaseInsensitiveMap(headers); |
| } |
| } |
| |
| public boolean hasHeaders() { |
| if (!hasPopulatedHeaders()) { |
| // force creating headers |
| getHeaders(); |
| } |
| return headers != null && !headers.isEmpty(); |
| } |
| |
| public DefaultMessage newInstance() { |
| return new DefaultMessage(); |
| } |
| |
| /** |
| * A factory method to lazily create the headers to make it easy to create |
| * efficient Message implementations which only construct and populate the |
| * Map on demand |
| * |
| * @return return a newly constructed Map possibly containing headers from |
| * the underlying inbound transport |
| */ |
| protected Map<String, Object> createHeaders() { |
| Map<String, Object> map = new CaseInsensitiveMap(); |
| populateInitialHeaders(map); |
| return map; |
| } |
| |
| /** |
| * A factory method to lazily create the attachments to make it easy to |
| * create efficient Message implementations which only construct and |
| * populate the Map on demand |
| * |
| * @return return a newly constructed Map |
| */ |
| protected Map<String, DataHandler> createAttachments() { |
| Map<String, DataHandler> map = new HashMap<String, DataHandler>(); |
| populateInitialAttachments(map); |
| return map; |
| } |
| |
| /** |
| * A strategy method populate the initial set of headers on an inbound |
| * message from an underlying binding |
| * |
| * @param map is the empty header map to populate |
| */ |
| protected void populateInitialHeaders(Map<String, Object> map) { |
| // do nothing by default |
| } |
| |
| /** |
| * A strategy method populate the initial set of attachments on an inbound |
| * message from an underlying binding |
| * |
| * @param map is the empty attachment map to populate |
| */ |
| protected void populateInitialAttachments(Map<String, DataHandler> map) { |
| // do nothing by default |
| } |
| |
| public void addAttachment(String id, DataHandler content) { |
| if (attachments == null) { |
| attachments = createAttachments(); |
| } |
| attachments.put(id, content); |
| } |
| |
| public DataHandler getAttachment(String id) { |
| return getAttachments().get(id); |
| } |
| |
| public Set<String> getAttachmentNames() { |
| if (attachments == null) { |
| attachments = createAttachments(); |
| } |
| return attachments.keySet(); |
| } |
| |
| public void removeAttachment(String id) { |
| if (attachments != null && attachments.containsKey(id)) { |
| attachments.remove(id); |
| } |
| } |
| |
| public Map<String, DataHandler> getAttachments() { |
| if (attachments == null) { |
| attachments = createAttachments(); |
| } |
| return attachments; |
| } |
| |
| public void setAttachments(Map<String, DataHandler> attachments) { |
| this.attachments = attachments; |
| } |
| |
| public boolean hasAttachments() { |
| if (attachments == null) { |
| attachments = createAttachments(); |
| } |
| return this.attachments != null && this.attachments.size() > 0; |
| } |
| |
| /** |
| * Returns true if the headers have been mutated in some way |
| */ |
| protected boolean hasPopulatedHeaders() { |
| return headers != null; |
| } |
| |
| public String createExchangeId() { |
| return null; |
| } |
| } |