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.juel;
018
019 import java.io.IOException;
020 import java.util.Properties;
021
022 import javax.el.ArrayELResolver;
023 import javax.el.CompositeELResolver;
024 import javax.el.ELContext;
025 import javax.el.ELResolver;
026 import javax.el.ExpressionFactory;
027 import javax.el.ListELResolver;
028 import javax.el.MapELResolver;
029 import javax.el.ResourceBundleELResolver;
030 import javax.el.ValueExpression;
031 import de.odysseus.el.ExpressionFactoryImpl;
032 import de.odysseus.el.util.SimpleContext;
033
034 import org.apache.camel.CamelContext;
035 import org.apache.camel.Exchange;
036 import org.apache.camel.Message;
037 import org.apache.camel.impl.ExpressionSupport;
038 import org.apache.camel.spi.FactoryFinder;
039 import org.apache.commons.logging.Log;
040 import org.apache.commons.logging.LogFactory;
041
042 /**
043 * The <a href="http://camel.apache.org/el.html">EL Language from JSP and JSF</a>
044 * using the <a href="http://camel.apache.org/juel.html">JUEL library</a>
045 *
046 * @version $Revision: 887107 $
047 */
048 public class JuelExpression extends ExpressionSupport {
049 public static final String DEFAULT_EXPRESSION_FACTORY_IMPL_CLASS = "de.odysseus.el.ExpressionFactoryImpl";
050 private static final Log LOG = LogFactory.getLog(JuelExpression.class);
051
052 private final String expression;
053 private final Class<?> type;
054 private ExpressionFactory expressionFactory;
055
056 public JuelExpression(String expression, Class<?> type) {
057 this.expression = expression;
058 this.type = type;
059 }
060
061 public static JuelExpression el(String expression) {
062 return new JuelExpression(expression, Object.class);
063 }
064
065 public <T> T evaluate(Exchange exchange, Class<T> tClass) {
066 // TODO we could use caching here but then we'd have possible concurrency issues
067 // so lets assume that the provider caches
068
069 // Create (if needed) the ExpressionFactory first from the CamelContext using FactoryFinder
070 ExpressionFactory factory = getExpressionFactory(exchange.getContext());
071 ELContext context = populateContext(createContext(), exchange);
072 ValueExpression valueExpression = factory.createValueExpression(context, expression, type);
073 Object value = valueExpression.getValue(context);
074 return exchange.getContext().getTypeConverter().convertTo(tClass, value);
075 }
076
077 public ExpressionFactory getExpressionFactory(CamelContext context) {
078 if (expressionFactory == null && context != null) {
079 try {
080 FactoryFinder finder = context.getFactoryFinder("META-INF/services/org/apache/camel/language/");
081 Class<?> clazz = finder.findClass("el", "impl.");
082 if (clazz != null) {
083 expressionFactory = (ExpressionFactory)clazz.newInstance();
084 }
085 } catch (ClassNotFoundException e) {
086 LOG.debug("'impl.class' not found", e);
087 } catch (IOException e) {
088 LOG.debug("No impl class for juel ExpressionFactory defined in 'META-INF/services/org/apache/camel/language/el'", e);
089 } catch (InstantiationException e) {
090 LOG.debug("Failed to instantiate juel ExpressionFactory implementation class.", e);
091 } catch (IllegalAccessException e) {
092 LOG.debug("Failed to instantiate juel ExpressionFactory implementation class.", e);
093 }
094 }
095 return getExpressionFactory();
096 }
097
098 public ExpressionFactory getExpressionFactory() {
099 if (expressionFactory == null) {
100 expressionFactory = new ExpressionFactoryImpl();
101 }
102 return expressionFactory;
103 }
104
105 public void setExpressionFactory(ExpressionFactory expressionFactory) {
106 this.expressionFactory = expressionFactory;
107 }
108
109 protected ELContext populateContext(ELContext context, Exchange exchange) {
110 setVariable(context, "exchange", exchange, Exchange.class);
111 setVariable(context, "in", exchange.getIn(), Message.class);
112 if (exchange.hasOut()) {
113 setVariable(context, "out", exchange.getOut(), Message.class);
114 }
115 return context;
116 }
117
118 protected void setVariable(ELContext context, String name, Object value, Class<?> type) {
119 ValueExpression valueExpression = getExpressionFactory().createValueExpression(value, type);
120 SimpleContext simpleContext = (SimpleContext) context;
121 simpleContext.setVariable(name, valueExpression);
122 }
123
124 /**
125 * Factory method to create the EL context
126 */
127 protected ELContext createContext() {
128 ELResolver resolver = new CompositeELResolver() {
129 {
130 //add(methodResolver);
131 add(new ArrayELResolver(false));
132 add(new ListELResolver(false));
133 add(new MapELResolver(false));
134 add(new ResourceBundleELResolver());
135 add(new BeanAndMethodELResolver());
136 }
137 };
138 return new SimpleContext(resolver);
139 }
140
141 protected String assertionFailureMessage(Exchange exchange) {
142 return expression;
143 }
144 }