
org.ow2.frascati.implementation.script.FrascatiImplementationScriptProcessor Maven / Gradle / Ivy
The newest version!
/**
* OW2 FraSCAti: SCA Implementation Script
* Copyright (C) 2009-2010 INRIA, University of Lille 1
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: [email protected]
*
* Author: Philippe Merle
*
* Contributors: Nicolas Dolet, Christophe Demarey
*
*/
package org.ow2.frascati.implementation.script;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import javax.script.Invocable;
import javax.script.ScriptException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.eclipse.stp.sca.domainmodel.frascati.FrascatiPackage;
import org.eclipse.stp.sca.domainmodel.frascati.ScriptImplementation;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.factory.GenericFactory;
import org.objectweb.fractal.api.type.ComponentType;
import org.objectweb.fractal.api.type.InterfaceType;
import org.objectweb.fractal.api.type.TypeFactory;
import org.objectweb.fractal.util.Fractal;
import org.objectweb.fractal.julia.Julia;
import org.osoa.sca.annotations.Reference;
import org.ow2.frascati.assembly.factory.api.CompositeManager;
import org.ow2.frascati.assembly.factory.api.ProcessingContext;
import org.ow2.frascati.assembly.factory.api.ProcessorException;
import org.ow2.frascati.assembly.factory.processor.AbstractCompositeBasedImplementationProcessor;
/**
* OW2 FraSCAti SCA Implementation Script processor class.
*
* @author Philippe Merle
* @version 1.3
*/
public class FrascatiImplementationScriptProcessor
extends AbstractCompositeBasedImplementationProcessor {
// ======================================================================
// Internal state.
// ======================================================================
/**
* The script engine manager.
*/
private ScriptEngineManager scriptEngineManager;
/**
* The required composite manager.
*/
@Reference(name = "composite-manager")
private CompositeManager compositeManager;
// ======================================================================
// Internal methods.
// ======================================================================
/**
* @see org.ow2.frascati.assembly.factory.processor.AbstractProcessor#toStringBuilder(EObjectType, StringBuilder)
*/
@Override
protected final void toStringBuilder(ScriptImplementation scriptImplementation, StringBuilder sb) {
sb.append("frascati:implementation.script");
append(sb, "script", scriptImplementation.getScript());
append(sb, "language", scriptImplementation.getLanguage());
super.toStringBuilder(scriptImplementation, sb);
}
/**
* Initialize the script engine manager.
*/
private void initializeScriptEngineManager(ClassLoader classLoader) {
// Create the script engine manager with the runtime classloader.
// Let's note that this can't be done before (e.g., at the instantiation time
// of this component) because the runtime classloader could not be initialized too.
// Christophe pointed this when applying the FraSCAti MOJO plugin to execute
// 'mvn -Prun' on examples/helloworld-script/
scriptEngineManager = new ScriptEngineManager(classLoader);
// Log currently supported scripting engines.
StringBuffer buffer = new StringBuffer();
buffer.append("OW2 FraSCAti - Supported scripting engines:\n");
for(ScriptEngineFactory factory : scriptEngineManager.getEngineFactories()) {
buffer.append("* ");
buffer.append(factory.getEngineName());
buffer.append(' ');
buffer.append(factory.getEngineVersion());
buffer.append(' ');
buffer.append(factory.getExtensions());
buffer.append(' ');
buffer.append(factory.getNames());
buffer.append(' ');
buffer.append(factory.getLanguageName());
buffer.append(' ');
buffer.append(factory.getLanguageVersion());
buffer.append('\n');
}
log.info(buffer.toString());
}
/**
* @see org.ow2.frascati.assembly.factory.api.Processor#check(ElementType, ProcessingContext)
*/
@Override
protected final void doCheck(ScriptImplementation scriptImplementation, ProcessingContext processingContext)
throws ProcessorException
{
String scriptImplementationScript = scriptImplementation.getScript();
if(isNullOrEmpty(scriptImplementationScript)) {
error(processingContext, scriptImplementation, "The attribute 'script' must be set");
} else {
if(processingContext.getResource(scriptImplementationScript) == null) {
error(processingContext, scriptImplementation, "Script '", scriptImplementationScript, "' not found");
}
}
// TODO check that the required script engine is available?
// TODO evaluate the script to see it is correct
// check attributes 'policySets' and 'requires'.
checkImplementation(scriptImplementation, processingContext);
}
/**
* @see org.ow2.frascati.assembly.factory.api.Processor#instantiate(ElementType, ProcessingContext)
*/
@Override
protected final void doInstantiate(ScriptImplementation scriptImplementation, ProcessingContext processingContext)
throws ProcessorException
{
// Initialize the script engine manager if not already done.
// At this moment the FraSCAti assembly factory runtime classloader
// is initialized.
//
// TODO: Perhaps the script engine manager should be instantiated
// each time a ScriptEngine is instantiated in order to be sure that
// all script engines present in the runtime classloader are useable.
// For instance, we could imagine a reconfiguration scenario where
// we dynamically add a new script engine at runtime.
if(scriptEngineManager == null) {
initializeScriptEngineManager(processingContext.getClassLoader());
}
// Get the script.
String script = scriptImplementation.getScript();
log.info("Create an SCA component for and the Fractal component type "
+ getFractalComponentType(scriptImplementation, processingContext).toString());
// Obtain an input stream reader to the script.
// TODO: Could 'script' contain a url or filename, and not just a resource in the classpath?
// TODO move into check()
URL scriptUrl = processingContext.getResource(script);
if(scriptUrl == null) {
severe(new ProcessorException(scriptImplementation, "Script '" + script + "' not found"));
return;
}
InputStream scriptInputStream = null;
try {
scriptInputStream = scriptUrl.openStream();
} catch (IOException ioe) {
severe(new ProcessorException(scriptImplementation, "Script '" + script + "' not found", ioe));
return;
}
InputStreamReader scriptReader = new InputStreamReader(scriptInputStream);
// Obtain a scripting engine for evaluating the script.
// TODO: Use scriptImplementation.getLanguage() if not null
// TODO move into check
String scriptExtension = script.substring(script.lastIndexOf('.') + 1);
ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension(scriptExtension);
if(scriptEngine == null) {
severe(new ProcessorException(scriptImplementation, "ScriptEngine for '" + script + "' not found"));
return;
}
// Add a reference to the SCA domain into the script engine
scriptEngine.put("domain", compositeManager.getTopLevelDomainComposite());
// Switch the current thread class loader to the processing context class loader
// in order to be sure that the script will be evaluated into the right class loader.
ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(processingContext.getClassLoader());
// Evaluate the script.
try {
scriptEngine.eval(scriptReader);
} catch(ScriptException se) {
severe(new ProcessorException(scriptImplementation, "Error when evaluating '" + script + "'", se));
return;
} finally {
// Restore the previous class loader.
Thread.currentThread().setContextClassLoader(previousClassLoader);
}
// Create the Fractal component as a composite.
Component component = doInstantiate(scriptImplementation, processingContext, scriptEngine);
// Create a primitive component encapsulating the scripting engine.
try {
ScriptEngineComponent scriptEngineContent = new ScriptEngineComponent(component, scriptEngine);
// TODO Will not using Tinfi instead of Julia?
// TODO init the Fractal bootstrap component just one time.
HashMap hints = new HashMap();
hints.put("fractal.provider", Julia.class.getCanonicalName());
Component bootstrap = Fractal.getBootstrapComponent(hints);
TypeFactory typeFactory = Fractal.getTypeFactory(bootstrap);
GenericFactory genericFactory = Fractal.getGenericFactory(bootstrap);
ComponentType scriptEngineType = typeFactory.createFcType(new InterfaceType[] {
// type for attribute-controller
typeFactory.createFcItfType("attribute-controller",
ScriptEngineAttributes.class.getCanonicalName(),
false, false, false) });
Component scriptEngineComponent = genericFactory.newFcInstance(scriptEngineType,
"primitive", scriptEngineContent);
// add the scripting engine component as a sub component of the SCA composite.
addFractalSubComponent(component, scriptEngineComponent);
} catch(Exception exc) {
// This should not happen!
severe(new ProcessorException(scriptImplementation, "Internal Fractal error!", exc));
return;
}
}
/**
* AbstractCompositeBasedImplementationProcessor#getService(ContentType, String, Class>)
*/
@Override
protected final Object getService(ScriptEngine scriptEngine, String name, Class> interfaze) throws Exception
{
// Get a typed proxy from the script engine.
return ((Invocable)scriptEngine).getInterface(interfaze);
}
/**
* AbstractCompositeBasedImplementationProcessor#setReference(ContentType, String, Object, Class>)
*/
@Override
protected final void setReference(ScriptEngine scriptEngine, String name, Object delegate, Class> interfaze) throws Exception
{
// Put the reference into the script engine.
scriptEngine.put(name, delegate);
}
// ======================================================================
// Public methods.
// ======================================================================
/**
* @see org.ow2.frascati.assembly.factory.api.Processor#getProcessorID()
*/
public final String getProcessorID() {
return getID(FrascatiPackage.Literals.SCRIPT_IMPLEMENTATION);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy