001    /**
002     *
003     * Licensed to the Apache Software Foundation (ASF) under one or more
004     * contributor license agreements.  See the NOTICE file distributed with
005     * this work for additional information regarding copyright ownership.
006     * The ASF licenses this file to You under the Apache License, Version 2.0
007     * (the "License"); you may not use this file except in compliance with
008     * the License.  You may obtain a copy of the License at
009     *
010     * http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.camel.builder.xpath;
019    
020    import org.apache.camel.Exchange;
021    import org.apache.camel.Expression;
022    import org.apache.camel.Message;
023    import org.apache.camel.Predicate;
024    import org.apache.camel.util.ObjectHelper;
025    import org.xml.sax.InputSource;
026    
027    import javax.xml.namespace.QName;
028    import javax.xml.xpath.XPathConstants;
029    import javax.xml.xpath.XPathExpression;
030    import javax.xml.xpath.XPathExpressionException;
031    import java.io.StringReader;
032    
033    /**
034     * An {@link Expression} which uses XPath to perform the evaluation
035     *
036     * @version $Revision: 521180 $
037     */
038    public class ExchangeXPathExpression<E extends Exchange> implements Expression<E>, Predicate<E> {
039        private final XPathExpression expression;
040        private final MessageVariableResolver variableResolver;
041        private Class documentType;
042        private String text;
043        private QName resultType;
044    
045        public ExchangeXPathExpression(XPathBuilder builder, XPathExpression expression, MessageVariableResolver variableResolver) {
046            this.expression = expression;
047            this.variableResolver = variableResolver;
048            this.documentType = builder.getDocumentType();
049            this.text = builder.getText();
050            this.resultType = builder.getResultType();
051        }
052    
053        public boolean matches(E exchange) {
054            return ObjectHelper.toBoolean(evaluateAs(exchange, XPathConstants.BOOLEAN));
055        }
056    
057        public Object evaluate(E exchange) {
058            return evaluateAs(exchange, resultType);
059        }
060    
061        public Class getDocumentType() {
062            return documentType;
063        }
064    
065        public String getText() {
066            return text;
067        }
068    
069        public MessageVariableResolver getVariableResolver() {
070            return variableResolver;
071        }
072    
073        /**
074         * Evaluates the expression as the given result type
075         */
076        protected synchronized Object evaluateAs(E exchange, QName resultType) {
077            variableResolver.setExchange(exchange);
078            try {
079                Object document = getDocument(exchange);
080                if (resultType != null) {
081                    if (document instanceof InputSource) {
082                        InputSource inputSource = (InputSource) document;
083                        return expression.evaluate(inputSource, resultType);
084                    }
085                    else {
086                        return expression.evaluate(document, resultType);
087                    }
088                }
089                else {
090                    if (document instanceof InputSource) {
091                        InputSource inputSource = (InputSource) document;
092                        return expression.evaluate(inputSource);
093                    }
094                    else {
095                        return expression.evaluate(document);
096                    }
097                }
098            }
099            catch (XPathExpressionException e) {
100                throw new InvalidXPathExpression(getText(), e);
101            }
102        }
103    
104        /**
105         * Strategy method to extract the document from the exchange
106         */
107        protected Object getDocument(E exchange) {
108            Message in = exchange.getIn();
109            Class type = getDocumentType();
110            Object answer = null;
111            if (type != null) {
112                answer = in.getBody(type);
113            }
114            if (answer == null) {
115                answer = in.getBody();
116            }
117    
118            // lets try coerce some common types into something JAXP can deal with
119            if (answer instanceof String) {
120                answer = new InputSource(new StringReader(answer.toString()));
121            }
122            return answer;
123        }
124    }
125