001 /** 002 * Copyright 2005 Hiram Chirino 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 **/ 017 package org.activemq.filter; 018 019 import java.lang.reflect.Constructor; 020 import java.lang.reflect.InvocationTargetException; 021 022 import javax.jms.JMSException; 023 import javax.jms.Message; 024 025 import org.apache.commons.logging.Log; 026 import org.apache.commons.logging.LogFactory; 027 028 /** 029 * Used to evaluate an XPath Expression in a JMS selector. 030 */ 031 public final class XPathExpression implements BooleanExpression { 032 033 private static final Log log = LogFactory.getLog(XPathExpression.class); 034 private static final String EVALUATOR_SYSTEM_PROPERTY = "org.activemq.XPathEvaluatorClassName"; 035 private static final String DEFAULT_EVALUATOR_CLASS_NAME=XalanXPathEvaluator.class.getName(); 036 037 private static final Constructor EVALUATOR_CONSTRUCTOR; 038 039 static { 040 String cn = System.getProperty(EVALUATOR_SYSTEM_PROPERTY, DEFAULT_EVALUATOR_CLASS_NAME); 041 Constructor m = null; 042 try { 043 try { 044 m = getXPathEvaluatorConstructor(cn); 045 } catch (Throwable e) { 046 log.warn("Invalid "+XPathEvaluator.class.getName()+" implementation: "+cn+", reason: "+e,e); 047 cn = DEFAULT_EVALUATOR_CLASS_NAME; 048 try { 049 m = getXPathEvaluatorConstructor(cn); 050 } catch (Throwable e2) { 051 log.error("Default XPath evaluator could not be loaded",e); 052 } 053 } 054 } finally { 055 EVALUATOR_CONSTRUCTOR = m; 056 } 057 } 058 059 private static Constructor getXPathEvaluatorConstructor(String cn) throws ClassNotFoundException, SecurityException, NoSuchMethodException { 060 Class c = XPathExpression.class.getClassLoader().loadClass(cn); 061 if( !XPathEvaluator.class.isAssignableFrom(c) ) { 062 throw new ClassCastException(""+c+" is not an instance of "+XPathEvaluator.class); 063 } 064 return c.getConstructor(new Class[]{String.class}); 065 } 066 067 private final String xpath; 068 private final XPathEvaluator evaluator; 069 070 static public interface XPathEvaluator { 071 public boolean evaluate(Message message) throws JMSException; 072 } 073 074 XPathExpression(String xpath) { 075 this.xpath = xpath; 076 this.evaluator = createEvaluator(xpath); 077 } 078 079 private XPathEvaluator createEvaluator(String xpath2) { 080 try { 081 return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[]{xpath}); 082 } catch (InvocationTargetException e) { 083 Throwable cause = e.getCause(); 084 if( cause instanceof RuntimeException ) { 085 throw (RuntimeException)cause; 086 } 087 throw new RuntimeException("Invalid XPath Expression: "+xpath+" reason: "+e.getMessage(), e); 088 } catch (Throwable e) { 089 throw new RuntimeException("Invalid XPath Expression: "+xpath+" reason: "+e.getMessage(), e); 090 } 091 } 092 093 public Object evaluate(Message message) throws JMSException { 094 return evaluator.evaluate(message) ? Boolean.TRUE : Boolean.FALSE; 095 } 096 097 public String toString() { 098 return "XPATH "+ConstantExpression.encodeString(xpath); 099 } 100 }