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.language.jxpath;
018
019 import org.apache.camel.Exchange;
020 import org.apache.camel.ExpressionEvaluationException;
021 import org.apache.camel.impl.ExpressionSupport;
022 import org.apache.commons.jxpath.CompiledExpression;
023 import org.apache.commons.jxpath.JXPathContext;
024 import org.apache.commons.jxpath.JXPathException;
025
026 /**
027 * <a href="http://commons.apache.org/jxpath/">JXPath</a> {@link Expression} support
028 */
029 public class JXPathExpression extends ExpressionSupport {
030
031 private final String expression;
032 private CompiledExpression compiledExpression;
033 private final Class<?> type;
034
035 /**
036 * Creates a new JXPathExpression instance
037 *
038 * @param expression the JXPath expression to be evaluated
039 * @param type the expected result type
040 */
041 public JXPathExpression(String expression, Class<?> type) {
042 super();
043 this.expression = expression;
044 this.type = type;
045 }
046
047 public <T> T evaluate(Exchange exchange, Class<T> tClass) {
048 try {
049 JXPathContext context = JXPathContext.newContext(exchange);
050 Object result = getJXPathExpression().getValue(context, type);
051 assertResultType(exchange, result);
052 return exchange.getContext().getTypeConverter().convertTo(tClass, result);
053 } catch (JXPathException e) {
054 throw new ExpressionEvaluationException(this, exchange, e);
055 }
056 }
057
058 /*
059 * Check if the result is of the specified type
060 */
061 private void assertResultType(Exchange exchange, Object result) {
062 if (result != null && !type.isAssignableFrom(result.getClass())) {
063 throw new JXPathException("JXPath result type is " + result.getClass() + " instead of required type " + type);
064 }
065 }
066
067 @Override
068 protected String assertionFailureMessage(Exchange exchange) {
069 return expression;
070 }
071
072 /*
073 * Get a compiled expression instance for better performance
074 */
075 private synchronized CompiledExpression getJXPathExpression() {
076 if (compiledExpression == null) {
077 compiledExpression = JXPathContext.compile(expression);
078 }
079 return compiledExpression;
080 }
081
082 @Override
083 public String toString() {
084 return "JXpath[" + expression + "]";
085 }
086 }