Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2008-2018, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.osgi.impl;
import com.hazelcast.logging.ILogger;
import com.hazelcast.logging.Logger;
import com.hazelcast.nio.ClassLoaderUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/*
Imported from Apache Felix project.
http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java
*/
/**
* This class acts as a delegate for all the available ScriptEngineManagers. Unluckily, the standard did not
* define it as an interface, so we need to extend it to allow polymorphism. However, no calls to super are used.
* It wraps all available ScriptEngineManagers in the OSGi ServicePlatform into a merged ScriptEngineManager.
*
* Internally, what this class does is creating ScriptEngineManagers for each bundle
* that contains a ScriptEngineFactory and includes a META-INF/services/javax.script.ScriptEngineFactory file.
* It assumes that the file contains a list of {@link ScriptEngineFactory} classes. For each bundle, it creates a
* ScriptEngineManager, then merges them. {@link ScriptEngineFactory} objects are wrapped
* into @link OSGiScriptEngineFactory objects to deal with problems of context class loader:
* Those scripting engines that rely on the ContextClassloader for finding resources need to use this wrapper
* and the @link OSGiScriptFactory. Mainly, jruby does.
*
* Note that even if no context classloader issues arose, it would still be needed to search manually for the
* factories and either use them directly (losing the mimeType/extension/shortName mechanisms for finding engines
* or manually registering them) or still use this class, which would be smarter. In the latter case,
* it would only be needed to remove the hack that temporarily sets the context classloader to the appropriate,
* bundle-related, class loader.
*
* Caveats:
*
* All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines are not wrapped,
* calls like
*
* ScriptEngineManager osgiManager=new OSGiScriptEngineManager(context);
* ScriptEngine engine=osgiManager.getEngineByName("ruby");
* ScriptEngineFactory factory=engine.getFactory() //this does not return the OSGiFactory wrapper
* factory.getScriptEngine(); //this might fail, as it does not use OSGiScriptEngineFactory wrapper
*
* might result in unexpected errors. Future versions may wrap the ScriptEngine with a OSGiScriptEngine to solve this
* issue, but for the moment it is not needed.
*
*/
public class OSGiScriptEngineManager extends ScriptEngineManager {
private static final String RHINO_SCRIPT_ENGINE_FACTORY = "com.sun.script.javascript.RhinoScriptEngineFactory";
private static final String NASHORN_SCRIPT_ENGINE_FACTORY = "jdk.nashorn.api.scripting.NashornScriptEngineFactory";
private final ILogger logger = Logger.getLogger(getClass());
private Bindings bindings;
private List scriptEngineManagerInfoList;
private BundleContext context;
public OSGiScriptEngineManager(BundleContext context) {
this.context = context;
bindings = new SimpleBindings();
this.scriptEngineManagerInfoList = findManagers(context);
}
private static final class ScriptEngineManagerInfo {
private final ScriptEngineManager scriptEngineManager;
private final ClassLoader classloader;
private ScriptEngineManagerInfo(ScriptEngineManager scriptEngineManager, ClassLoader classloader) {
this.scriptEngineManager = scriptEngineManager;
this.classloader = classloader;
}
}
/**
* This method is the only one that is visible and not part of the ScriptEngineManager class.
* Its purpose is to find new managers that weren't available before, but keeping the globalScope bindings
* set.
* If you want to clean the bindings you can either get a fresh instance of OSGiScriptManager or
* setting up a new bindings object.
* This can be done with:
*
* ScriptEngineManager manager=new OSGiScriptEngineManager(context);
* (...)//do stuff
* osgiManager=(OSGiScriptEngineManager)manager;//cast to ease reading
* osgiManager.reloadManagers();
*
* manager.setBindings(new OSGiBindings());//or you can use your own bindings implementation
*
*
*/
public void reloadManagers() {
this.scriptEngineManagerInfoList = findManagers(context);
}
@Override
public Object get(String key) {
return bindings.get(key);
}
@Override
public Bindings getBindings() {
return bindings;
}
/**
* Follows the same behavior of @link javax.script.ScriptEngineManager#setBindings(Bindings)
* This means that the same bindings are applied to all the underlying managers.
*
* @param bindings
*/
@Override
public void setBindings(Bindings bindings) {
this.bindings = bindings;
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
info.scriptEngineManager.setBindings(bindings);
}
}
@Override
public ScriptEngine getEngineByExtension(String extension) {
// TODO this is a hack to deal with context classloader issues
ScriptEngine engine = null;
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
Thread currentThread = Thread.currentThread();
ClassLoader old = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(info.classloader);
engine = info.scriptEngineManager.getEngineByExtension(extension);
currentThread.setContextClassLoader(old);
if (engine != null) {
break;
}
}
return engine;
}
@Override
public ScriptEngine getEngineByMimeType(String mimeType) {
// TODO this is a hack to deal with context classloader issues
ScriptEngine engine = null;
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
Thread currentThread = Thread.currentThread();
ClassLoader old = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(info.classloader);
engine = info.scriptEngineManager.getEngineByMimeType(mimeType);
currentThread.setContextClassLoader(old);
if (engine != null) {
break;
}
}
return engine;
}
@Override
public ScriptEngine getEngineByName(String shortName) {
// TODO this is a hack to deal with context classloader issues
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
Thread currentThread = Thread.currentThread();
ClassLoader old = currentThread.getContextClassLoader();
ClassLoader contextClassLoader = info.classloader;
currentThread.setContextClassLoader(contextClassLoader);
ScriptEngine engine = info.scriptEngineManager.getEngineByName(shortName);
currentThread.setContextClassLoader(old);
if (engine != null) {
OSGiScriptEngineFactory factory = new OSGiScriptEngineFactory(engine.getFactory(), contextClassLoader);
return new OSGiScriptEngine(engine, factory);
}
}
return null;
}
@Override
public List getEngineFactories() {
List osgiFactories = new ArrayList();
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
for (ScriptEngineFactory factory : info.scriptEngineManager.getEngineFactories()) {
OSGiScriptEngineFactory scriptEngineFactory = new OSGiScriptEngineFactory(factory, info.classloader);
osgiFactories.add(scriptEngineFactory);
}
}
return osgiFactories;
}
@Override
public void put(String key, Object value) {
bindings.put(key, value);
}
@Override
public void registerEngineExtension(String extension, ScriptEngineFactory factory) {
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
info.scriptEngineManager.registerEngineExtension(extension, factory);
}
}
@Override
public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
info.scriptEngineManager.registerEngineMimeType(type, factory);
}
}
@Override
public void registerEngineName(String name, ScriptEngineFactory factory) {
for (ScriptEngineManagerInfo info : scriptEngineManagerInfoList) {
info.scriptEngineManager.registerEngineName(name, factory);
}
}
private List findManagers(BundleContext context) {
List scriptEngineManagerInfos = new ArrayList();
try {
for (String factoryName : findFactoryCandidates(context)) {
ClassLoader factoryClassLoader = loadScriptEngineFactoryClassLoader(factoryName);
if (factoryClassLoader == null) {
continue;
}
ScriptEngineManagerInfo scriptEngineManagerInfo =
createScriptEngineManagerInfo(factoryName, factoryClassLoader);
if (scriptEngineManagerInfo != null) {
scriptEngineManagerInfos.add(scriptEngineManagerInfo);
}
}
return scriptEngineManagerInfos;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
private ClassLoader loadScriptEngineFactoryClassLoader(String factoryName) {
// We do not really need the class, but we need the classloader
try {
return ClassLoaderUtil.tryLoadClass(factoryName).getClassLoader();
} catch (ClassNotFoundException cnfe) {
// may fail if script implementation is not in environment
logger.warning("Found ScriptEngineFactory candidate for "
+ factoryName + ", but cannot load class! -> " + cnfe);
if (logger.isFinestEnabled()) {
logger.finest(cnfe);
}
return null;
}
}
private ScriptEngineManagerInfo createScriptEngineManagerInfo(String factoryName, ClassLoader factoryLoader) {
try {
ScriptEngineManager manager = new ScriptEngineManager(factoryLoader);
manager.setBindings(bindings);
return new ScriptEngineManagerInfo(manager, factoryLoader);
} catch (Exception e) {
// May fail if script implementation is not in environment
logger.warning("Found ScriptEngineFactory candidate for " + factoryName
+ ", but could not load ScripEngineManager! -> " + e);
if (logger.isFinestEnabled()) {
logger.finest(e);
}
return null;
}
}
/**
* Iterates through all bundles to get the available {@link ScriptEngineFactory} classes
*
* @return the names of the available ScriptEngineFactory classes
* @throws IOException
*/
private List findFactoryCandidates(BundleContext context) throws IOException {
Bundle[] bundles = context.getBundles();
List factoryCandidates = new ArrayList();
for (Bundle bundle : bundles) {
if (bundle == null) {
continue;
}
if ("system.bundle".equals(bundle.getSymbolicName())) {
continue;
}
Enumeration urls = bundle.findEntries("META-INF/services", "javax.script.ScriptEngineFactory", false);
if (urls == null) {
continue;
}
while (urls.hasMoreElements()) {
URL u = (URL) urls.nextElement();
BufferedReader reader = new BufferedReader(
new InputStreamReader(u.openStream(), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (!line.startsWith("#") && line.length() > 0) {
factoryCandidates.add(line);
}
}
reader.close();
}
}
// Add java built in JavaScript ScriptEngineFactory's
addJavaScriptEngine(factoryCandidates);
return factoryCandidates;
}
/**
* Adds the JDK build-in JavaScript engine into the given list of scripting engine factories.
*
* @param factoryCandidates List of scripting engine factories
*/
private void addJavaScriptEngine(List factoryCandidates) {
// Add default script engine manager
factoryCandidates.add(OSGiScriptEngineFactory.class.getName());
// Rhino is available in java < 8, Nashorn is available in java >= 8
if (ClassLoaderUtil.isClassDefined(RHINO_SCRIPT_ENGINE_FACTORY)) {
factoryCandidates.add(RHINO_SCRIPT_ENGINE_FACTORY);
} else if (ClassLoaderUtil.isClassDefined(NASHORN_SCRIPT_ENGINE_FACTORY)) {
factoryCandidates.add(NASHORN_SCRIPT_ENGINE_FACTORY);
} else {
logger.warning("No built-in JavaScript ScriptEngineFactory found.");
}
}
public String printScriptEngines() {
StringBuilder msg = new StringBuilder("Available script engines are:\n");
for (ScriptEngineFactory scriptEngineFactory : getEngineFactories()) {
msg.append("\t- ").append(scriptEngineFactory.getEngineName()).append('\n');
}
return msg.toString();
}
}