/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bstefanescu */ package org.eclipse.ecr.automation.core.scripting; import groovy.lang.Binding; import java.io.InputStream; import java.io.Serializable; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.ecr.automation.OperationContext; import org.eclipse.ecr.automation.OperationException; import org.eclipse.ecr.core.api.DocumentModel; import org.eclipse.ecr.core.api.NuxeoPrincipal; import org.eclipse.ecr.runtime.api.Framework; import org.mvel2.MVEL; import org.nuxeo.common.utils.FileUtils; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class Scripting { protected static final Map<String, Script> cache = new ConcurrentHashMap<String, Script>(); protected static final GroovyScripting gscripting = new GroovyScripting(); public static Expression newExpression(String expr) { return new MvelExpression(expr); } public static Expression newTemplate(String expr) { return new MvelTemplate(expr); } public static void run(OperationContext ctx, URL script) throws Exception { String key = script.toExternalForm(); Script cs = cache.get(key); if (cs != null) { cs.eval(ctx); return; } String path = script.getPath(); int p = path.lastIndexOf('.'); if (p == -1) { throw new OperationException( "Script files must have an extension: " + script); } String ext = path.substring(p + 1).toLowerCase(); if ("mvel".equals(ext)) { InputStream in = script.openStream(); try { Serializable c = MVEL.compileExpression(FileUtils.read(in)); cs = new MvelScript(c); } finally { in.close(); } } else if ("groovy".equals(ext)) { // Script gs = new GroovyScript(); } else { throw new OperationException("Unsupported script file: " + script + ". Only mvel and groovy scripts are supported"); } cache.put(key, cs); cs.eval(ctx); } public static Map<String, Object> initBindings(OperationContext ctx) { Object input = ctx.getInput(); // get last output Map<String, Object> map = new HashMap<String, Object>(ctx); map.put("CurrentDate", new DateWrapper()); map.put("Context", ctx); map.put("This", input); map.put("Session", ctx.getCoreSession()); map.put("CurrentUser", new PrincipalWrapper((NuxeoPrincipal) ctx.getPrincipal())); map.put("Env", Framework.getProperties()); map.put("Fn", Functions.getInstance()); if (input instanceof DocumentModel) { map.put("Document", new DocumentWrapper(ctx.getCoreSession(), (DocumentModel) input)); } return map; } public interface Script { // protected long lastModified; Object eval(OperationContext ctx) throws Exception; } public static class MvelScript implements Script { final Serializable c; public static MvelScript compile(String script) { return new MvelScript(MVEL.compileExpression(script)); } public MvelScript(Serializable c) { this.c = c; } public Object eval(OperationContext ctx) throws Exception { return MVEL.executeExpression(c, Scripting.initBindings(ctx)); } } public static class GroovyScript implements Script { final groovy.lang.Script c; public GroovyScript(String c) { this.c = gscripting.getScript(c, new Binding()); } public Object eval(OperationContext ctx) throws Exception { Binding binding = new Binding(); for (Map.Entry<String, Object> entry : initBindings(ctx).entrySet()) { binding.setVariable(entry.getKey(), entry.getValue()); } c.setBinding(binding); return c.run(); } } }