felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From santil...@apache.org
Subject svn commit: r450629 - in /incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell: ./ console/
Date Wed, 27 Sep 2006 23:09:30 GMT
Author: santillan
Date: Wed Sep 27 16:09:28 2006
New Revision: 450629

URL: http://svn.apache.org/viewvc?view=rev&rev=450629
Log:
Some refactoring to decouple shell from engine logic and to wrap the javax.script classes
so that they work in OSGi

Added:
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Activator.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Command.java
      - copied, changed from r442641, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Command.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/CommandNotFoundException.java
      - copied, changed from r442641, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Commander.java
      - copied, changed from r441834, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Commander.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Console.java
      - copied, changed from r441834, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Console.java
Removed:
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Command.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Commander.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Console.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Main.java
Modified:
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMXEngineContext.java
    incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java

Added: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Activator.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Activator.java?view=auto&rev=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Activator.java (added)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Activator.java Wed
Sep 27 16:09:28 2006
@@ -0,0 +1,49 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell;
+
+import org.apache.felix.mishell.console.Console;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+	private Console console;
+
+	public void start(BundleContext context) throws Exception {
+		//NOTE: new javax.script.EngineManager() uses context class loader
+		//We've changed that to use EngineManager(ClassLoader loader)
+		//Alternatively, we could instantiate it in a separate thread with proper context class
loader set.
+		//TODO: not sure wether resources are correctly freed. A running script will probably keep
running, for example, if it has got threads
+		//but that would hang the console, which is quite primitive yet. (it would need a 'run
[script] &' idiom)
+		console = new Console(new JMXEngineContext("javascript", new OSGiScriptEngineManager(context)));
+		Thread t=new Thread(console);
+		//At least JRuby engine (maybe others too) uses context class loaders internally
+		//So this is to prevent  problems with that: context cl=console class loader which in turn
+		//loads the manager and therefore engine factory
+//		t.setContextClassLoader(this.getClass().getClassLoader());
+		t.setName("ConsoleThread");
+		t.start();
+
+	}
+
+	public void stop(BundleContext context) throws Exception {
+		console.stop();
+
+	}
+
+}

Modified: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java?view=diff&rev=450629&r1=450628&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java
(original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java
Wed Sep 27 16:09:28 2006
@@ -1,3 +1,19 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell;
 
 public class EngineNotFoundException extends Exception {

Modified: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMXEngineContext.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMXEngineContext.java?view=diff&rev=450629&r1=450628&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMXEngineContext.java
(original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMXEngineContext.java
Wed Sep 27 16:09:28 2006
@@ -1,54 +1,71 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.MalformedObjectNameException;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXServiceURL;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
-import javax.script.ScriptEngineManager;
-
-import org.apache.felix.jmxintrospector.MBeanProxyManager;
-
-//import org.apache.felix.jmood.core.CoreControllerMBean;
-//import org.apache.felix.jmood.core.FrameworkMBean;
-//import org.apache.felix.jmood.utils.ObjectNames;
 
+/**
+ * This class is in charge of most of the interesting stuff. Basically, it keeps the current
engine instance being used
+ * and creates the OSGiScriptEngineManager 'decorator' that handles the fact that engines
can be installed in 
+ * separate bundles and then the mechanism for finding engines used by the javax.script API
does not work.
+ *
+ */
 public class JMXEngineContext {
 	private ScriptEngine engine;
-	private ScriptEngineManager engineManager;
-
+	private OSGiScriptEngineManager engineManager;
+	private String language;
 
 	Logger log=Logger.getLogger(JMXEngineContext.class.getName());
 	Level l=Level.INFO;
-
-	public JMXEngineContext(String language)throws EngineNotFoundException{
-		engineManager=new ScriptEngineManager(this.getClass().getClassLoader());
-		log.log(l, "Available script engines are:");
+	public JMXEngineContext(String language) throws EngineNotFoundException{
+		this(language, null);
+	}
+	public JMXEngineContext(String lang, OSGiScriptEngineManager engineManager)throws EngineNotFoundException{
+		this.engineManager=engineManager;
+		if (log.isLoggable(l)){
+		StringBuffer msg=new StringBuffer("Available script engines are:");
+		log.log(l, "Available script engines are: \n");
 		for (ScriptEngineFactory sef : engineManager.getEngineFactories()) {
-			log.log(l, sef.getEngineName());
+			msg.append(sef.getEngineName()+"\n");
+		}
+		log.log(l, msg.toString());
 		}
-		engine=engineManager.getEngineByName(language);
-		if (engine==null) throw new EngineNotFoundException(language);
 		JMoodProxyManager manager=new JMoodProxyManager();
+		engine=engineManager.getEngineByName(lang);
+		this.language=engine.getFactory().getLanguageName();
 		String managerName=getVarName("manager");
-		engine.put(managerName, manager);
+		engineManager.put(managerName, manager);
+		for(String key: engineManager.getBindings().keySet()){
+			engine.put(getVarName(key), engineManager.get(key));
+			}
+		
+		if (engine==null) throw new EngineNotFoundException(language);
 	}
+	/**
+	 * This method is used because prior versions of jrbuy binding needed global variables
+	 * to be called '$'+name. Last version already do that automatically, so this is not needed
anymore
+	 * @param name
+	 * @return
+	 */
+	//TODO: remove this method when we update to latest version of jruby-engine
 	private String getVarName(String name){
 		if (engine.getFactory().getEngineName().equals("jruby")) name="$"+name;
 		return name;
@@ -60,14 +77,37 @@
 	public void setEngine(ScriptEngine engine) {
 		this.engine = engine;
 	}
-	public ScriptEngineManager getEngineManager() {
+	public OSGiScriptEngineManager getEngineManager() {
 		return engineManager;
 	}
-	public void setEngineManager(ScriptEngineManager engineManager) {
+	public void setEngineManager(OSGiScriptEngineManager engineManager) {
 		this.engineManager = engineManager;
 	}
+	/**
+	 * This methods changes the engine language. It reloads the ScriptEngineManagers to ensure
+	 * that any new engines (for example new bundles or updated ones) are discovered.  
+	 * @param name
+	 * @throws EngineNotFoundException
+	 */
+	public void setLanguage(String name) throws EngineNotFoundException{
+		OSGiScriptEngineManager manager=(OSGiScriptEngineManager)engineManager;
+		manager.reloadManagers();
+		ScriptEngine newEngine=manager.getEngineByName(name);
+		if(newEngine!=null) {
+			engine=newEngine;
+			language=engine.getFactory().getLanguageName();
+			for(String key: engineManager.getBindings().keySet()){
+				System.out.println(key);
+				engine.put(getVarName(key), engineManager.get(key));
+				}
+
+		}
+		else throw new EngineNotFoundException("name");
+	}
+	public String getLanguage(){
+		return language;
 	}
-	
+}	
 	
 	
 

Modified: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java?view=diff&rev=450629&r1=450628&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java
(original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java
Wed Sep 27 16:09:28 2006
@@ -1,3 +1,21 @@
+/* 
+ * 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.felix.mishell;
 
 import java.util.List;
@@ -7,6 +25,12 @@
 import org.apache.felix.jmxintrospector.MBean;
 import org.apache.felix.jmxintrospector.MBeanProxyManager;
 
+/**
+ * This class extends the MBeanProxyManager to include methods that are aware that they are
connecting
+ * to an MBeanServer that has JMood mbeans. This is the most natural place to add some utility
methods
+ * for script engines, since scripts will have a JMoodProxyManager named 'manager' as the
entry point.  
+ *
+ */
 public class JMoodProxyManager extends MBeanProxyManager {
 	public List<Object> getControllers(){
 		return findAll("type=controller");

Added: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java?view=auto&rev=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java
(added)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java
Wed Sep 27 16:09:28 2006
@@ -0,0 +1,77 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell;
+
+import java.io.Reader;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
+public class OSGiScriptEngine implements ScriptEngine{
+	private ScriptEngine engine;
+	private OSGiScriptEngineFactory factory;
+	public OSGiScriptEngine(ScriptEngine engine, OSGiScriptEngineFactory factory){
+		this.engine=engine;
+		this.factory=factory;
+	}
+	public Bindings createBindings() {
+		return engine.createBindings();
+	}
+	public Object eval(Reader reader, Bindings n) throws ScriptException {
+		return engine.eval(reader, n);
+	}
+	public Object eval(Reader reader, ScriptContext context) throws ScriptException {
+		return engine.eval(reader, context);
+	}
+	public Object eval(Reader reader) throws ScriptException {
+		return engine.eval(reader);
+	}
+	public Object eval(String script, Bindings n) throws ScriptException {
+		return engine.eval(script, n);
+	}
+	public Object eval(String script, ScriptContext context) throws ScriptException {
+		return engine.eval(script, context);
+	}
+	public Object eval(String script) throws ScriptException {
+		return engine.eval(script);
+	}
+	public Object get(String key) {
+		return engine.get(key);
+	}
+	public Bindings getBindings(int scope) {
+		return engine.getBindings(scope);
+	}
+	public ScriptContext getContext() {
+		return engine.getContext();
+	}
+	public ScriptEngineFactory getFactory() {
+		return factory;
+	}
+	public void put(String key, Object value) {
+		engine.put(key, value);
+	}
+	public void setBindings(Bindings bindings, int scope) {
+		engine.setBindings(bindings, scope);
+	}
+	public void setContext(ScriptContext context) {
+		engine.setContext(context);
+	}
+
+}

Added: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java?view=auto&rev=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java
(added)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java
Wed Sep 27 16:09:28 2006
@@ -0,0 +1,82 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell;
+
+import java.util.List;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+/**
+ * This is a wrapper class for the ScriptEngineFactory class that deals with context class
loader issues
+ * It is necessary because engines (at least ruby) use the context classloader to find their
resources (i.e., their "native" classes)
+ *
+ */
+public class OSGiScriptEngineFactory implements ScriptEngineFactory{
+	private ScriptEngineFactory factory;
+	private ClassLoader contextClassLoader;
+	public OSGiScriptEngineFactory (ScriptEngineFactory factory, ClassLoader contextClassLoader){
+		this.factory=factory;
+		this.contextClassLoader=contextClassLoader;
+	}
+	public String getEngineName() {
+		return factory.getEngineName();
+	}
+	public String getEngineVersion() {
+		return factory.getEngineVersion();
+	}
+	public List<String> getExtensions() {
+		return factory.getExtensions();
+	}
+	public String getLanguageName() {
+		return factory.getLanguageName();
+	}
+	public String getLanguageVersion() {
+		return factory.getLanguageVersion();
+	}
+	public String getMethodCallSyntax(String obj, String m, String... args) {
+		return factory.getMethodCallSyntax(obj, m, args);
+	}
+	public List<String> getMimeTypes() {
+		return factory.getMimeTypes();
+	}
+	public List<String> getNames() {
+		return factory.getNames();
+	}
+	public String getOutputStatement(String toDisplay) {
+		return factory.getOutputStatement(toDisplay);
+	}
+	public Object getParameter(String key) {
+		return factory.getParameter(key);
+	}
+	public String getProgram(String... statements) {
+		return factory.getProgram(statements);
+	}
+	public ScriptEngine getScriptEngine() {
+		ScriptEngine engine=null;
+		if(contextClassLoader!=null){
+		ClassLoader old=Thread.currentThread().getContextClassLoader();
+		Thread.currentThread().setContextClassLoader(contextClassLoader);
+		engine=factory.getScriptEngine();
+		Thread.currentThread().setContextClassLoader(old);
+		}
+		else engine=factory.getScriptEngine();
+		return engine;
+	}
+	
+
+}

Added: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java?view=auto&rev=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java
(added)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java
Wed Sep 27 16:09:28 2006
@@ -0,0 +1,237 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell;
+
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleBindings;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * 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:
+ * <ul><li>
+ * All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines are not
wrapped,
+ * calls like 
+ * <code>
+ * ScriptEngineManager osgiManager=new OSGiScriptEngineManager(context);<br>
+ * 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
+ * </code>
+ * 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.
+ * </li>
+ * 
+ */
+public class OSGiScriptEngineManager extends ScriptEngineManager{
+	private Bindings bindings;
+	private Map <ScriptEngineManager, ClassLoader> classLoaders;
+	private BundleContext context;
+	
+	public OSGiScriptEngineManager(BundleContext context){
+		this.context=context;
+		bindings=new SimpleBindings();
+		this.classLoaders=findManagers(context);
+	}
+	/**
+	 * 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:
+	 * <code>
+	 * 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
+	 * 
+	 * </code>   
+	 *
+	 */
+	public void reloadManagers(){
+		this.classLoaders=findManagers(context);
+	}
+	
+	public Object get(String key) {
+		return bindings.get(key);
+	}
+
+	public Bindings getBindings() {
+		return bindings;
+	}
+
+	public ScriptEngine getEngineByExtension(String extension) {
+		//TODO this is a hack to deal with context class loader issues
+		ScriptEngine engine=null;
+		for(ScriptEngineManager manager: classLoaders.keySet()){
+			ClassLoader old=Thread.currentThread().getContextClassLoader();
+			Thread.currentThread().setContextClassLoader(classLoaders.get(manager));
+			engine=manager.getEngineByExtension(extension);
+			Thread.currentThread().setContextClassLoader(old);
+			if (engine!=null) break;
+		}
+ 		return engine;
+	}
+
+	public ScriptEngine getEngineByMimeType(String mimeType) {
+		//TODO this is a hack to deal with context class loader issues
+		ScriptEngine engine=null;
+		for(ScriptEngineManager manager: classLoaders.keySet()){
+			ClassLoader old=Thread.currentThread().getContextClassLoader();
+			Thread.currentThread().setContextClassLoader(classLoaders.get(manager));
+			engine=manager.getEngineByMimeType(mimeType);
+			Thread.currentThread().setContextClassLoader(old);
+			if (engine!=null) break;
+		}
+ 		return engine;
+	}
+
+	public ScriptEngine getEngineByName(String shortName) {
+		//TODO this is a hack to deal with context class loader issues
+		for(ScriptEngineManager manager: classLoaders.keySet()){
+			ClassLoader old=Thread.currentThread().getContextClassLoader();
+			Thread.currentThread().setContextClassLoader(classLoaders.get(manager));
+			ScriptEngine engine=manager.getEngineByName(shortName);
+			Thread.currentThread().setContextClassLoader(old);
+			if (engine!=null){
+				return new OSGiScriptEngine(engine, new OSGiScriptEngineFactory(engine.getFactory(),
classLoaders.get(manager)));
+			}
+		}
+		return null;
+	}
+	public List<ScriptEngineFactory> getEngineFactories() {
+		List<ScriptEngineFactory> osgiFactories=new ArrayList<ScriptEngineFactory>();
+		for(ScriptEngineManager engineManager: classLoaders.keySet()){
+			for (ScriptEngineFactory factory : engineManager.getEngineFactories()){
+				osgiFactories.add(new OSGiScriptEngineFactory(factory, classLoaders.get(engineManager)));
+		}
+		}
+		return osgiFactories;
+	}
+
+	public void put(String key, Object value) {
+		bindings.put(key, value);
+	}
+
+	public void registerEngineExtension(String extension, ScriptEngineFactory factory) {
+		for(ScriptEngineManager engineManager: classLoaders.keySet())
+			engineManager.registerEngineExtension(extension, factory);
+	}
+
+	public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
+		for(ScriptEngineManager engineManager: classLoaders.keySet())
+		engineManager.registerEngineMimeType(type, factory);
+	}
+
+	public void registerEngineName(String name, ScriptEngineFactory factory) {
+		for(ScriptEngineManager engineManager: classLoaders.keySet())
+			engineManager.registerEngineName(name, factory);
+	}
+	/**
+	 * 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
+	 */
+	public void setBindings(Bindings bindings) {
+		this.bindings=bindings;
+		for(ScriptEngineManager manager: classLoaders.keySet()){
+			manager.setBindings(bindings);
+		}
+
+	}
+
+
+	private Map<ScriptEngineManager, ClassLoader> findManagers(BundleContext context)
{
+		Map<ScriptEngineManager, ClassLoader> managers=new HashMap<ScriptEngineManager,
ClassLoader>();
+		try {
+			for(String factoryName: findFactoryCandidates(context)){
+				//We do not really need the class, but we need the classloader 
+				ClassLoader factoryLoader=Class.forName(factoryName).getClassLoader();
+				ScriptEngineManager manager=new ScriptEngineManager(factoryLoader);
+				manager.setBindings(bindings);
+				managers.put(manager, factoryLoader);
+			}
+			return managers;
+		} catch (IOException ioe) {
+			throw new RuntimeException(ioe);
+		} catch (ClassNotFoundException cnfe) {
+			throw new RuntimeException(cnfe);
+		}
+	}
+	/**
+	 * Iterates through all bundles to get the available @link ScriptEngineFactory classes
+	 * @return the names of the available ScriptEngineFactory classes
+	 * @throws IOException
+	 */
+	private List<String> findFactoryCandidates(BundleContext context) throws IOException{
+		Bundle[] bundles = context.getBundles();
+		List<String> factoryCandidates = new ArrayList<String>();
+		for (Bundle bundle : bundles) {
+			System.out.println(bundle.getSymbolicName());
+			if(bundle.getSymbolicName().equals("system.bundle")) 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()));
+				String line;
+				while ((line = reader.readLine()) != null) {
+					factoryCandidates.add(line.trim());
+		}
+			}
+		}
+		return factoryCandidates;
+	}
+}

Copied: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Command.java
(from r442641, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Command.java)
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Command.java?view=diff&rev=450629&p1=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Command.java&r1=442641&p2=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Command.java&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Command.java (original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Command.java
Wed Sep 27 16:09:28 2006
@@ -1,4 +1,20 @@
-package org.apache.felix.mishell;
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell.console;
 
 import java.io.PrintStream;
 

Copied: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/CommandNotFoundException.java
(from r442641, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java)
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/CommandNotFoundException.java?view=diff&rev=450629&p1=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java&r1=442641&p2=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/CommandNotFoundException.java&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java
(original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/CommandNotFoundException.java
Wed Sep 27 16:09:28 2006
@@ -1,4 +1,20 @@
-package org.apache.felix.mishell;
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell.console;
 
 public class CommandNotFoundException extends Exception {
 

Copied: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Commander.java
(from r441834, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Commander.java)
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Commander.java?view=diff&rev=450629&p1=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Commander.java&r1=441834&p2=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Commander.java&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Commander.java (original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Commander.java
Wed Sep 27 16:09:28 2006
@@ -1,4 +1,20 @@
-package org.apache.felix.mishell;
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell.console;
 
 import java.io.PrintStream;
 import java.util.HashSet;
@@ -7,6 +23,7 @@
 import java.util.logging.Logger;
 
 import javax.script.ScriptContext;
+
 
 
 public class Commander extends HashSet<Command> implements Command{

Copied: incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Console.java
(from r441834, incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Console.java)
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Console.java?view=diff&rev=450629&p1=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Console.java&r1=441834&p2=incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Console.java&r2=450629
==============================================================================
--- incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/Console.java (original)
+++ incubator/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/console/Console.java
Wed Sep 27 16:09:28 2006
@@ -1,4 +1,20 @@
-package org.apache.felix.mishell;
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.felix.mishell.console;
 
 import java.io.BufferedReader;
 import java.io.FileNotFoundException;
@@ -18,12 +34,13 @@
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptException;
 
-import jline.ConsoleReader;
-import jline.ConsoleReaderInputStream;
+import org.apache.felix.mishell.EngineNotFoundException;
+import org.apache.felix.mishell.JMXEngineContext;
+
 
 public class Console implements Runnable{
 	public static final String DEFAULT_LANGUAGE = "javascript";
-Logger log = Logger.getLogger(this.getClass().getCanonicalName());
+	Logger log = Logger.getLogger(this.getClass().getCanonicalName());
 	Level l=Level.FINEST;
 	private String language=DEFAULT_LANGUAGE;
 	private String prompt;
@@ -32,70 +49,41 @@
 	private Commander commander;
 	private boolean stop = false;
 	private JMXEngineContext engineContext;
-	private String scriptPath;
-
-	public Console(String language, String scriptPath) throws IOException{
-		if (language != null) this.language=language;
-		prompt="mishell."+language+"$ ";
-		/*
-		 * Not used for the moment. It does not work inside Eclipse, and presents 
-		problems from the command line
-		*/
-		//useJline();
+	public Console(JMXEngineContext engineContext) throws IOException{
+		this.engineContext=engineContext;
+		prompt="mishell."+engineContext.getLanguage()+"$ ";
 		in=new BufferedReader(new InputStreamReader(System.in));
 		out=System.out;
 		commander= new Commander();
-		this.scriptPath=scriptPath;
 		addBuiltInCmds();
 		stop=false;	
 	}
-	private void useJline() throws IOException{
-		ConsoleReader cr=new ConsoleReader();
-		ConsoleReaderInputStream.setIn(cr);
-
-	}
-	private void initLanguage() throws Exception{
-		initLanguage(null);
-	}
-	private void initLanguage(String name) throws Exception{
-		if(name!=null) {
-			engineContext = new JMXEngineContext(name);
-		}
-		else {
-			engineContext=new JMXEngineContext(language);
-		}
+	private void setLanguage(String name)throws EngineNotFoundException{
+		engineContext.setLanguage(name);
 		language=engineContext.getEngine().getFactory().getLanguageName();
 		prompt="mishell."+language+"$ ";
+
 	}
 	public void run() {
 				try {
-					initLanguage();
-					if (scriptPath==null)
-					runConsole();
-					else engineContext.getEngine().eval(new FileReader(scriptPath));
+					out.println("Welcome to Apache Mishell!!");
+					out.println("For getting help type 'help' ");
+					out.print(prompt);
+					while (!stop) {
+						try {
+							String cmd = in.readLine();
+							executeCommand(cmd);
+							out.print(prompt);
+							out.flush();
+						} catch (IOException e) {
+							e.printStackTrace();
+						}
+					}
 				} catch (Exception e) {
 					e.printStackTrace();
 				}
 			}
 
-
-	private void runConsole() throws Exception {
-		out.println("Welcome to Apache Mishell!!");
-		out.println("For getting help type 'help' ");
-		out.print(prompt);
-		while (!stop) {
-			try {
-				String cmd = in.readLine();
-				executeCommand(cmd);
-				out.print(prompt);
-				out.flush();
-			} catch (IOException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-		}
-	}
-
 	public void stop() {
 		stop = true;
 	}
@@ -115,6 +103,17 @@
 			e.printStackTrace();
 		}
 	}
+	public void addCommand(Command cmd){
+		commander.add(cmd);
+	}
+	/**
+	 * This method is needed for non-trivial commands that could eventually be added, as 
+	 * they will need to use the engineContext to do useful things
+	 * @return
+	 */
+	public JMXEngineContext getEngineContext(){
+		return engineContext;
+	}
 	private void addBuiltInCmds(){
 		commander.add(new Command(){
 			public void executeCommand(String cmd, PrintStream out) throws Exception {
@@ -145,14 +144,16 @@
 		});
 		commander.add(new Command(){
 			public void executeCommand(String cmd, PrintStream out) throws Exception {
-				String[] args=cmd.split(" ");//TODO implement scape seqs
-				if(args.length>1)initLanguage(args[1]);
-				else for (ScriptEngineFactory factory: engineContext.getEngineManager().getEngineFactories())
{
-					out.print(factory.getLanguageName()+"; version "+factory.getLanguageVersion());
-					out.print("; AKA: ");
-					for(String alias: factory.getNames()) out.print(alias+" ");
-					out.print("\n");
-				
+				String[] args=cmd.split(" ");//TODO implement scape seqs, that is, if path contains spaces,
for example.
+				if(args.length>1){
+					setLanguage(args[1]);
+				} else{
+					for (ScriptEngineFactory factory: engineContext.getEngineManager().getEngineFactories())
{
+						out.print(factory.getLanguageName()+"; version "+factory.getLanguageVersion());
+						out.print("; AKA: ");
+						for(String alias: factory.getNames()) out.print(alias+" ");
+							out.print("\n");
+						}
 				}
 			}
 			public String getName() {



Mime
View raw message