| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.cocoon.components.expression.javascript; |
| |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.io.StringReader; |
| |
| import org.apache.avalon.framework.CascadingRuntimeException; |
| import org.apache.cocoon.components.expression.AbstractExpression; |
| import org.apache.cocoon.components.expression.ExpressionContext; |
| import org.apache.cocoon.components.expression.ExpressionException; |
| import org.apache.cocoon.components.expression.jexl.JSIntrospector; |
| import org.apache.cocoon.components.flow.javascript.JavaScriptFlowHelper; |
| import org.apache.cocoon.template.environment.FlowObjectModelHelper; |
| import org.apache.commons.jexl.util.introspection.Info; |
| import org.mozilla.javascript.Context; |
| import org.mozilla.javascript.Script; |
| import org.mozilla.javascript.Scriptable; |
| |
| public class JavaScriptExpression extends AbstractExpression { |
| |
| private Script script; |
| private JSIntrospector introspector; |
| |
| public JavaScriptExpression(String language, String expression) { |
| super(language, expression); |
| compile(); |
| } |
| |
| private void compile() { |
| Context ctx = Context.enter(); |
| try { |
| // Note: used compileReader instead of compileString to work with the older Rhino in C2.1 |
| this.script = ctx.compileReader(FlowObjectModelHelper.getScope(), new StringReader(getExpression()), "", 1, null); |
| } catch (Exception e) { |
| // Note: this catch block is only needed for the Rhino in C2.1 where the older |
| // Rhino does not throw RuntimeExceptions |
| if (e instanceof RuntimeException) { |
| throw (RuntimeException)e; |
| } else{ |
| throw new CascadingRuntimeException("Runtime exception.", e); |
| } |
| } finally { |
| Context.exit(); |
| } |
| } |
| |
| public Object evaluate(ExpressionContext context) throws ExpressionException { |
| Context ctx = Context.enter(); |
| try { |
| Scriptable scope = ctx.newObject(FlowObjectModelHelper.getScope()); |
| // Populate the scope |
| Iterator iter = context.entrySet().iterator(); |
| while (iter.hasNext()) { |
| Map.Entry entry = (Map.Entry) iter.next(); |
| String key = (String) entry.getKey(); |
| Object value = entry.getValue(); |
| scope.put(key, scope, Context.toObject(value, scope)); |
| } |
| |
| Object result = this.script.exec(ctx, scope); |
| return JavaScriptFlowHelper.unwrap(result); |
| } catch (Exception e) { |
| // Note: this catch block is only needed for the Rhino in C2.1 where the older |
| // Rhino does not throw RuntimeExceptions |
| if (e instanceof RuntimeException) { |
| throw (RuntimeException)e; |
| } else { |
| throw new CascadingRuntimeException("Runtime exception", e); |
| } |
| } finally { |
| Context.exit(); |
| } |
| } |
| |
| public Iterator iterate(ExpressionContext context) throws ExpressionException { |
| Object result = evaluate(context); |
| if (result == null) |
| return EMPTY_ITER; |
| |
| if (this.introspector == null) |
| introspector = new JSIntrospector(); |
| |
| Iterator iter = null; |
| try { |
| iter = introspector.getIterator(result, new Info("Unknown", 0, 0)); |
| } catch (Exception e) { |
| throw new ExpressionException("Couldn't get an iterator from expression " + getExpression(), e); |
| } |
| |
| if (iter == null) |
| iter = EMPTY_ITER; |
| return iter; |
| } |
| |
| public void assign(ExpressionContext context, Object value) throws ExpressionException { |
| throw new UnsupportedOperationException("assignment not implemented for javascript expressions"); |
| } |
| |
| public Object getNode(ExpressionContext context) throws ExpressionException { |
| return evaluate(context); |
| } |
| } |