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.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
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     * messge, exchange as well as making system properties and environment
039     * properties available.
040     *
041     * @version $Revision: 45030 $
042     */
043    public class MessageVariableResolver implements XPathVariableResolver {
044        private static final transient Log LOG = LogFactory.getLog(MessageVariableResolver.class);
045    
046        private Exchange exchange;
047        private Map<String, Object> variables = new HashMap<String, Object>();
048    
049        public Exchange getExchange() {
050            return exchange;
051        }
052    
053        public void setExchange(Exchange exchange) {
054            this.exchange = exchange;
055        }
056    
057        public Object resolveVariable(QName name) {
058            String uri = name.getNamespaceURI();
059            String localPart = name.getLocalPart();
060            Object answer = null;
061    
062            Message in = exchange.getIn();
063            if (uri == null || uri.length() == 0) {
064                answer = variables.get(localPart);
065                if (answer == null) {
066                    Message message = in;
067                    if (message != null) {
068                        answer = message.getHeader(localPart);
069                    }
070                    if (answer == null) {
071                        answer = exchange.getProperty(localPart);
072                    }
073                }
074            } else if (uri.equals(SYSTEM_PROPERTIES_NAMESPACE)) {
075                try {
076                    answer = System.getProperty(localPart);
077                } catch (Exception e) {
078                    LOG.debug("Security exception evaluating system property: " + localPart
079                              + ". Reason: " + e, e);
080                }
081            } else if (uri.equals(ENVIRONMENT_VARIABLES)) {
082                answer = System.getenv().get(localPart);
083            } else if (uri.equals(EXCHANGE_PROPERTY)) {
084                answer = exchange.getProperty(localPart);
085            } else if (uri.equals(IN_NAMESPACE)) {
086                answer = in.getHeader(localPart);
087                if (answer == null && localPart.equals("body")) {
088                    answer = in.getBody();
089                }
090            } else if (uri.equals(OUT_NAMESPACE)) {
091                Message out = exchange.getOut(false);
092                if (out != null) {
093                    answer = out.getHeader(localPart);
094                    if (answer == null && localPart.equals("body")) {
095                        answer = out.getBody();
096                    }
097                }
098            }
099    
100            // TODO support exposing CamelContext properties/resources via XPath?
101    
102            // If we can't find an answer we must return void.
103            // We can't return null then the xpath engine will throw a NullPointerException
104            if (answer == null) {
105                return Void.class;
106            } else {
107                return answer;
108            }
109        }
110    
111        public void addVariable(String localPart, Object value) {
112            variables.put(localPart, value);
113        }
114    }