| /* |
| * 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.openejb.util; |
| |
| import org.apache.openejb.AppContext; |
| import org.apache.openejb.OpenEJBRuntimeException; |
| import org.apache.openejb.loader.SystemInstance; |
| import org.apache.openejb.spi.ContainerSystem; |
| |
| import javax.enterprise.inject.spi.Bean; |
| import javax.enterprise.inject.spi.BeanManager; |
| import javax.script.Bindings; |
| import javax.script.ScriptContext; |
| import javax.script.ScriptEngine; |
| import javax.script.ScriptEngineFactory; |
| import javax.script.ScriptEngineManager; |
| import javax.script.ScriptException; |
| import javax.script.SimpleScriptContext; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| public class OpenEJBScripter { |
| private static final Map<String, ScriptEngineFactory> ENGINE_FACTORIES = new ConcurrentHashMap<String, ScriptEngineFactory>(); |
| private static final ThreadLocal<Map<String, ScriptEngine>> ENGINES = new ThreadLocal<Map<String, ScriptEngine>>() { |
| @Override |
| protected Map<String, ScriptEngine> initialValue() { |
| return new HashMap<String, ScriptEngine>(); |
| } |
| }; |
| |
| static { |
| final ScriptEngineManager mgr = new ScriptEngineManager(); |
| for (ScriptEngineFactory factory : mgr.getEngineFactories()) { |
| if (factory.getParameter("THREADING") != null) { // thread safe |
| for (String ext : factory.getExtensions()) { |
| ENGINE_FACTORIES.put(ext, factory); |
| } |
| } |
| } |
| } |
| |
| public static Set<String> getSupportedLanguages() { |
| return ENGINE_FACTORIES.keySet(); |
| } |
| |
| public Object evaluate(final String language, final String script) throws ScriptException { |
| return evaluate(language, script, null); |
| } |
| |
| public Object evaluate(final String language, final String script, final ScriptContext context) throws ScriptException { |
| if (!ENGINE_FACTORIES.containsKey(language)) { |
| throw new IllegalArgumentException("can't find factory for language " + language + ". You probably need to add the jar to openejb libs."); |
| } |
| |
| ScriptContext executionContext = context; |
| if (executionContext == null) { |
| executionContext = new SimpleScriptContext(); |
| } |
| |
| //we bind local variables (per execution) every time we execute a script |
| bindLocal(executionContext); |
| |
| final ScriptEngine engine = engine(language); |
| return engine.eval(script, executionContext); |
| } |
| |
| private static ScriptEngine engine(final String language) { |
| ScriptEngine engine = ENGINES.get().get(language); |
| if (engine == null) { |
| final ScriptEngineFactory factory = ENGINE_FACTORIES.get(language); |
| engine = factory.getScriptEngine(); |
| ENGINES.get().put(language, engine); |
| } |
| return engine; |
| } |
| |
| public static void clearEngines() { |
| ENGINES.get().clear(); |
| } |
| |
| private static void bindLocal(final ScriptContext context) { |
| final Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE); |
| |
| bindings.put("bm", new BeanManagerHelper()); |
| } |
| |
| public static class BeanManagerHelper { |
| public Object beanFromClass(final String appName, final String classname) { |
| final AppContext appContext = appContext(appName); |
| final BeanManager bm = appContext.getBeanManager(); |
| final Class<?> clazz; |
| try { |
| clazz = appContext.getClassLoader().loadClass(classname); |
| } catch (ClassNotFoundException e) { |
| throw new OpenEJBRuntimeException(e); |
| } |
| final Set<Bean<?>> beans = bm.getBeans(clazz); |
| return instance(bm, beans, clazz); |
| } |
| |
| public Object beanFromName(final String appName, final String name) { |
| final BeanManager bm = beanManager(appName); |
| final Set<Bean<?>> beans = bm.getBeans(name); |
| return instance(bm, beans, Object.class); |
| } |
| |
| private <T> T instance(final BeanManager bm, final Set<Bean<?>> beans, final Class<T> clazz) { |
| final Bean<?> bean = bm.resolve(beans); |
| return (T) bm.getReference(bean, clazz, bm.createCreationalContext(bean)); |
| } |
| |
| private BeanManager beanManager(final String appName) { |
| return appContext(appName).getBeanManager(); |
| } |
| |
| private AppContext appContext(final String appName) { |
| final ContainerSystem cs = SystemInstance.get().getComponent(ContainerSystem.class); |
| final AppContext appContext = cs.getAppContext(appName); |
| if (appContext == null) { |
| throw new OpenEJBRuntimeException("can't find application " + appName); |
| } |
| return appContext; |
| } |
| } |
| } |
| |