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 */
017package org.apache.activemq.filter;
018
019import org.apache.activemq.command.Message;
020import org.apache.activemq.util.ByteArrayInputStream;
021import org.w3c.dom.Document;
022import org.xml.sax.InputSource;
023
024import javax.jms.BytesMessage;
025import javax.jms.JMSException;
026import javax.jms.TextMessage;
027import javax.xml.parsers.DocumentBuilder;
028import javax.xml.xpath.XPath;
029import javax.xml.xpath.XPathConstants;
030import javax.xml.xpath.XPathFactory;
031import java.io.StringReader;
032
033public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
034
035    private static final XPathFactory FACTORY = XPathFactory.newInstance();
036    private final String xpathExpression;
037    private final DocumentBuilder builder;
038    private final XPath xpath = FACTORY.newXPath();
039
040    public JAXPXPathEvaluator(String xpathExpression, DocumentBuilder builder) throws Exception {
041        this.xpathExpression = xpathExpression;
042        if (builder != null) {
043            this.builder = builder;
044        } else {
045            throw new RuntimeException("No document builder available");
046        }
047    }
048
049    public boolean evaluate(Message message) throws JMSException {
050        if (message instanceof TextMessage) {
051            String text = ((TextMessage)message).getText();
052            return evaluate(text);
053        } else if (message instanceof BytesMessage) {
054            BytesMessage bm = (BytesMessage)message;
055            byte data[] = new byte[(int)bm.getBodyLength()];
056            bm.readBytes(data);
057            return evaluate(data);
058        }
059        return false;
060    }
061
062    private boolean evaluate(byte[] data) {
063        try {
064            InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
065            Document inputDocument = builder.parse(inputSource);
066            return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
067        } catch (Exception e) {
068            return false;
069        }
070    }
071
072    private boolean evaluate(String text) {
073        try {
074            InputSource inputSource = new InputSource(new StringReader(text));
075            Document inputDocument = builder.parse(inputSource);
076            return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
077        } catch (Exception e) {
078            return false;
079        }
080    }
081
082    @Override
083    public String toString() {
084        return xpathExpression;
085    }
086}