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.builder.xml;
018    
019    import java.util.HashMap;
020    import java.util.Map;
021    
022    import javax.xml.namespace.QName;
023    import javax.xml.xpath.XPathVariableResolver;
024    
025    import org.apache.camel.Exchange;
026    import org.apache.camel.Message;
027    import org.slf4j.Logger;
028    import org.slf4j.LoggerFactory;
029    
030    import static org.apache.camel.builder.xml.Namespaces.ENVIRONMENT_VARIABLES;
031    import static org.apache.camel.builder.xml.Namespaces.EXCHANGE_PROPERTY;
032    import static org.apache.camel.builder.xml.Namespaces.IN_NAMESPACE;
033    import static org.apache.camel.builder.xml.Namespaces.OUT_NAMESPACE;
034    import static org.apache.camel.builder.xml.Namespaces.SYSTEM_PROPERTIES_NAMESPACE;
035    
036    /**
037     * A variable resolver for XPath expressions which support properties on the
038     * message, exchange as well as making system properties and environment
039     * properties available.
040     * <p/>
041     * Implementations of this resolver must be thread safe
042     *
043     * @version 
044     */
045    public class MessageVariableResolver implements XPathVariableResolver {
046        private static final transient Logger LOG = LoggerFactory.getLogger(MessageVariableResolver.class);
047    
048        private Map<String, Object> variables = new HashMap<String, Object>();
049        private final ThreadLocal<Exchange> exchange;
050    
051        public MessageVariableResolver(ThreadLocal<Exchange> exchange) {
052            this.exchange = exchange;
053        }
054    
055        public Object resolveVariable(QName name) {
056            String uri = name.getNamespaceURI();
057            String localPart = name.getLocalPart();
058            Object answer = null;
059    
060            Message in = exchange.get().getIn();
061            if (uri == null || uri.length() == 0) {
062                answer = variables.get(localPart);
063                if (answer == null) {
064                    Message message = in;
065                    if (message != null) {
066                        answer = message.getHeader(localPart);
067                    }
068                    if (answer == null) {
069                        answer = exchange.get().getProperty(localPart);
070                    }
071                }
072            } else if (uri.equals(SYSTEM_PROPERTIES_NAMESPACE)) {
073                try {
074                    answer = System.getProperty(localPart);
075                } catch (Exception e) {
076                    LOG.debug("Security exception evaluating system property: " + localPart + ". Reason: " + e, e);
077                }
078            } else if (uri.equals(ENVIRONMENT_VARIABLES)) {
079                answer = System.getenv().get(localPart);
080            } else if (uri.equals(EXCHANGE_PROPERTY)) {
081                answer = exchange.get().getProperty(localPart);
082            } else if (uri.equals(IN_NAMESPACE)) {
083                answer = in.getHeader(localPart);
084                if (answer == null && localPart.equals("body")) {
085                    answer = in.getBody();
086                }
087            } else if (uri.equals(OUT_NAMESPACE)) {
088                if (exchange.get().hasOut()) {
089                    Message out = exchange.get().getOut();
090                    answer = out.getHeader(localPart);
091                    if (answer == null && localPart.equals("body")) {
092                        answer = out.getBody();
093                    }
094                }
095            }
096    
097            // if we can't find an answer we must return an empty String.
098            // if we return null, then the JDK default XPathEngine will throw an exception
099            if (answer == null) {
100                return "";
101            } else {
102                return answer;
103            }
104        }
105    
106        public void addVariable(String localPart, Object value) {
107            variables.put(localPart, value);
108        }
109    }