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.javascript;
018:
019: import java.util.Iterator;
020: import java.util.Map;
021: import java.io.StringReader;
022:
023: import org.apache.avalon.framework.CascadingRuntimeException;
024: import org.apache.cocoon.components.expression.AbstractExpression;
025: import org.apache.cocoon.components.expression.ExpressionContext;
026: import org.apache.cocoon.components.expression.ExpressionException;
027: import org.apache.cocoon.components.expression.jexl.JSIntrospector;
028: import org.apache.cocoon.components.flow.javascript.JavaScriptFlowHelper;
029: import org.apache.cocoon.template.environment.FlowObjectModelHelper;
030: import org.apache.commons.jexl.util.introspection.Info;
031: import org.mozilla.javascript.Context;
032: import org.mozilla.javascript.Script;
033: import org.mozilla.javascript.Scriptable;
034:
035: public class JavaScriptExpression extends AbstractExpression {
036:
037: private Script script;
038: private JSIntrospector introspector;
039:
040: public JavaScriptExpression(String language, String expression) {
041: super (language, expression);
042: compile();
043: }
044:
045: private void compile() {
046: Context ctx = Context.enter();
047: try {
048: // Note: used compileReader instead of compileString to work with the older Rhino in C2.1
049: this .script = ctx.compileReader(FlowObjectModelHelper
050: .getScope(), new StringReader(getExpression()), "",
051: 1, null);
052: } catch (Exception e) {
053: // Note: this catch block is only needed for the Rhino in C2.1 where the older
054: // Rhino does not throw RuntimeExceptions
055: if (e instanceof RuntimeException) {
056: throw (RuntimeException) e;
057: } else {
058: throw new CascadingRuntimeException(
059: "Runtime exception.", e);
060: }
061: } finally {
062: Context.exit();
063: }
064: }
065:
066: public Object evaluate(ExpressionContext context)
067: throws ExpressionException {
068: Context ctx = Context.enter();
069: try {
070: Scriptable scope = ctx.newObject(FlowObjectModelHelper
071: .getScope());
072: // Populate the scope
073: Iterator iter = context.entrySet().iterator();
074: while (iter.hasNext()) {
075: Map.Entry entry = (Map.Entry) iter.next();
076: String key = (String) entry.getKey();
077: Object value = entry.getValue();
078: scope.put(key, scope, Context.toObject(value, scope));
079: }
080:
081: Object result = this .script.exec(ctx, scope);
082: return JavaScriptFlowHelper.unwrap(result);
083: } catch (Exception e) {
084: // Note: this catch block is only needed for the Rhino in C2.1 where the older
085: // Rhino does not throw RuntimeExceptions
086: if (e instanceof RuntimeException) {
087: throw (RuntimeException) e;
088: } else {
089: throw new CascadingRuntimeException(
090: "Runtime exception", e);
091: }
092: } finally {
093: Context.exit();
094: }
095: }
096:
097: public Iterator iterate(ExpressionContext context)
098: throws ExpressionException {
099: Object result = evaluate(context);
100: if (result == null)
101: return EMPTY_ITER;
102:
103: if (this .introspector == null)
104: introspector = new JSIntrospector();
105:
106: Iterator iter = null;
107: try {
108: iter = introspector.getIterator(result, new Info("Unknown",
109: 0, 0));
110: } catch (Exception e) {
111: throw new ExpressionException(
112: "Couldn't get an iterator from expression "
113: + getExpression(), e);
114: }
115:
116: if (iter == null)
117: iter = EMPTY_ITER;
118: return iter;
119: }
120:
121: public void assign(ExpressionContext context, Object value)
122: throws ExpressionException {
123: throw new UnsupportedOperationException(
124: "assignment not implemented for javascript expressions");
125: }
126:
127: public Object getNode(ExpressionContext context)
128: throws ExpressionException {
129: return evaluate(context);
130: }
131: }
|