package org.camunda.bpm.extension.osgi.scripting.impl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import org.camunda.bpm.extension.osgi.scripting.ScriptEngineResolver;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceRegistration;
public class BundleScriptEngineResolver implements ScriptEngineResolver {
private static final Logger LOGGER = Logger
.getLogger(BundleScriptEngineResolver.class.getName());
private final Bundle bundle;
private ServiceRegistration<ScriptEngineResolver> reg;
private final URL configFile;
public BundleScriptEngineResolver(Bundle bundle, URL configFile) {
this.bundle = bundle;
this.configFile = configFile;
}
public void register() {
if (bundle.getBundleContext() != null) {
reg = bundle.getBundleContext().registerService(
ScriptEngineResolver.class, this, null);
}
}
public void unregister() {
if (reg != null) {
reg.unregister();
}
}
@Override
public ScriptEngine resolveScriptEngine(String name) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
configFile.openStream()));
String className = removeCommentsFromInput(in);
in.close();
Class<?> cls = bundle.loadClass(className);
if (!ScriptEngineFactory.class.isAssignableFrom(cls)) {
throw new IllegalStateException("Invalid ScriptEngineFactory: "
+ cls.getName());
}
ScriptEngineFactory factory = (ScriptEngineFactory) cls
.newInstance();
List<String> names = factory.getNames();
for (String n : names) {
if (n.equals(name)) {
ClassLoader old = Thread.currentThread()
.getContextClassLoader();
ScriptEngine engine;
try {
// JRuby seems to require the correct TCCL to call
// getScriptEngine
Thread.currentThread().setContextClassLoader(
factory.getClass().getClassLoader());
engine = factory.getScriptEngine();
} finally {
Thread.currentThread().setContextClassLoader(old);
}
LOGGER.finest("Resolved ScriptEngineFactory: " + engine
+ " for expected name: " + name);
return engine;
}
}
LOGGER.fine("ScriptEngineFactory: " + factory.getEngineName()
+ " does not match expected name: " + name);
return null;
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Cannot create ScriptEngineFactory: "
+ e.getClass().getName(), e);
return null;
}
}
/**
* Takes the input stream and ignores lines starting with a # and everything after a #
*/
private String removeCommentsFromInput(BufferedReader in) throws IOException {
String l = in.readLine();
//remove lines that start with a comment
while(l.startsWith("#")){
l = in.readLine();
}
if(l.contains("#")){
l = l.substring(0, l.indexOf("#"));
}
return l.trim();
}
@Override
public String toString() {
return "OSGi script engine resolver for " + bundle.getSymbolicName();
}
}