/* * 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.tuscany.sca.implementation.script; import java.io.StringReader; import java.security.AccessController; import java.security.PrivilegedAction; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.apache.axiom.om.OMElement; import org.apache.bsf.xml.XMLHelper; import org.apache.tuscany.sca.assembly.ComponentReference; import org.apache.tuscany.sca.assembly.ComponentType; import org.apache.tuscany.sca.assembly.Property; import org.apache.tuscany.sca.assembly.Reference; import org.apache.tuscany.sca.assembly.Service; import org.apache.tuscany.sca.core.factory.ObjectCreationException; import org.apache.tuscany.sca.core.factory.ObjectFactory; import org.apache.tuscany.sca.extension.helper.InvokerFactory; import org.apache.tuscany.sca.extension.helper.utils.PropertyValueObjectFactory; import org.apache.tuscany.sca.implementation.script.engines.TuscanyJRubyScriptEngine; import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.runtime.RuntimeComponent; /** * * @version $Rev$ $Date$ */ public class ScriptInvokerFactory implements InvokerFactory { protected ScriptEngine scriptEngine; protected XMLHelper xmlHelper; protected RuntimeComponent rc; protected ComponentType ct; protected ScriptImplementation implementation; protected PropertyValueObjectFactory propertyFactory; /** * @param rc * @param ct * @param implementation * @param propertyFactory */ public ScriptInvokerFactory(RuntimeComponent rc, ComponentType ct, ScriptImplementation implementation, PropertyValueObjectFactory propertyFactory) { super(); this.rc = rc; this.ct = ct; this.implementation = implementation; this.propertyFactory = propertyFactory; } public Invoker createInvoker(Operation operation) { init(rc, ct, implementation, propertyFactory); return new ScriptInvoker(scriptEngine, xmlHelper, operation); } protected synchronized void init(RuntimeComponent rc, ComponentType ct, ScriptImplementation implementation, PropertyValueObjectFactory propertyFactory) { if(scriptEngine!=null) { return; } try { scriptEngine = getScriptEngineByExtension(implementation.getScriptLanguage()); if (scriptEngine == null) { throw new ObjectCreationException("no script engine found for language: " + implementation.getScriptLanguage()); } if (!(scriptEngine instanceof Invocable)) { throw new ObjectCreationException("script engine does not support Invocable: " + scriptEngine); } for (Reference reference : ct.getReferences()) { scriptEngine.put(reference.getName(), createReferenceProxy(reference.getName(), rc)); } for (Property property : ct.getProperties()) { ObjectFactory propertyValueFactory = propertyFactory.createValueFactory(property); if ( propertyValueFactory != null) { scriptEngine.put(property.getName(), propertyValueFactory.getInstance()); } } scriptEngine.eval(new StringReader(implementation.getScriptSrc())); } catch (ScriptException e) { throw new ObjectCreationException(e); } // set the databinding and XMLHelper for WSDL interfaces for (Service service : rc.getServices()) { InterfaceContract ic = service.getInterfaceContract(); if ("org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract".equals(ic.getClass())) { // Set to use the Axiom data binding ic.getInterface().resetDataBinding(OMElement.class.getName()); xmlHelper = XMLHelper.getArgHelper(scriptEngine); } } } /** * TODO: RuntimeComponent should provide a method like this */ @SuppressWarnings("unchecked") protected Object createReferenceProxy(String name, RuntimeComponent component) { for (ComponentReference reference : component.getReferences()) { if (reference.getName().equals(name)) { Class iface = ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass(); return component.getComponentContext().getService(iface, name); } } throw new IllegalArgumentException("reference " + name + " not found on component: " + component); } /** * Hack for now to work around a problem with the JRuby script engine */ protected ScriptEngine getScriptEngineByExtension(String scriptExtn) { if ("rb".equals(scriptExtn)) { return new TuscanyJRubyScriptEngine(); } else { if ("py".equals(scriptExtn)) { pythonCachedir(); } // Allow privileged access to run access classes. Requires RuntimePermission // for accessClassInPackage.sun.misc. ScriptEngineManager scriptEngineManager = AccessController.doPrivileged(new PrivilegedAction() { public ScriptEngineManager run() { return new ScriptEngineManager(); } }); return scriptEngineManager.getEngineByExtension(scriptExtn); } } /** * If the Python home isn't set then let Tuscany suppress messages other than errors * See TUSCANY-1950 */ protected void pythonCachedir() { if (System.getProperty("python.home") == null) { System.setProperty("python.verbose", "error"); } } }