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.cocoon.components.expression.jexl;
018:
019: import java.lang.reflect.Field;
020: import java.util.Iterator;
021: import java.util.Map;
022:
023: import org.apache.cocoon.components.expression.AbstractExpression;
024: import org.apache.cocoon.components.expression.ExpressionContext;
025: import org.apache.cocoon.components.expression.ExpressionException;
026: import org.apache.commons.jexl.JexlContext;
027: import org.apache.commons.jexl.util.Introspector;
028: import org.apache.commons.jexl.util.introspection.Info;
029:
030: /**
031: * @version $Id: JexlExpression.java 449189 2006-09-23 06:52:29Z crossley $
032: */
033: public class JexlExpression extends AbstractExpression {
034:
035: private final org.apache.commons.jexl.Expression compiledExpression;
036:
037: public JexlExpression(String language, String expression)
038: throws ExpressionException {
039: super (language, expression);
040: try {
041: this .compiledExpression = org.apache.commons.jexl.ExpressionFactory
042: .createExpression(expression);
043: } catch (Exception e) {
044: throw new ExpressionException("Couldn't create expression "
045: + expression, e);
046: }
047: }
048:
049: public Object evaluate(ExpressionContext context)
050: throws ExpressionException {
051: try {
052: return this .compiledExpression.evaluate(new ContextAdapter(
053: context));
054: } catch (Exception e) {
055: throw new ExpressionException(
056: "Couldn't evaluate expression " + getExpression(),
057: e);
058: }
059: }
060:
061: public Iterator iterate(ExpressionContext context)
062: throws ExpressionException {
063: Iterator iter = null;
064: Object result = evaluate(context);
065: if (result != null) {
066: /*
067: * The Info object is supposed to contain the script location where
068: * the expression is invoked and use that in a warning log message
069: * if no iterator can be generated. This info is not available in
070: * the expression object and might not be relevant either as it can
071: * be used from a non script situation.
072: */
073: try {
074: iter = Introspector.getUberspect().getIterator(result,
075: new Info("Unknown", 0, 0));
076: } catch (Exception e) {
077: throw new ExpressionException(
078: "Couldn't get an iterator from expression "
079: + getExpression(), e);
080: }
081: }
082: if (iter == null) {
083: iter = EMPTY_ITER;
084: }
085: return iter;
086: }
087:
088: public void assign(ExpressionContext context, Object value)
089: throws ExpressionException {
090: throw new UnsupportedOperationException(
091: "Assign is not yet implemented for Jexl");
092: }
093:
094: public Object getNode(ExpressionContext context)
095: throws ExpressionException {
096: return evaluate(context);
097: }
098:
099: private static class ContextAdapter implements JexlContext {
100: private final ExpressionContext context;
101:
102: public ContextAdapter(ExpressionContext context) {
103: this .context = context;
104: }
105:
106: public Map getVars() {
107: return this .context.getVars();
108: }
109:
110: public void setVars(Map map) {
111: this .context.setVars(map);
112: }
113: }
114:
115: static {
116: // Hack: there's no _nice_ way to add my introspector to Jexl right now
117: try {
118: Field field = Introspector.class
119: .getDeclaredField("uberSpect");
120: field.setAccessible(true);
121: field.set(null, new JSIntrospector());
122: } catch (Exception e) {
123: e.printStackTrace();
124: }
125: }
126: }
|