Initial commit of mishell. Mishell is a scripting environment and console for remote jmx management. 
See README.txt for details.

git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@442641 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/mishell/src/main/java/org/apache/felix/mishell/Activator.java b/mishell/src/main/java/org/apache/felix/mishell/Activator.java
new file mode 100644
index 0000000..a879a69
--- /dev/null
+++ b/mishell/src/main/java/org/apache/felix/mishell/Activator.java
@@ -0,0 +1,31 @@
+package org.apache.felix.mishell;

+

+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.

+		console = new Console("javascript", null);

+		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();

+

+	}

+

+}

diff --git a/mishell/src/main/java/org/apache/felix/mishell/Command.java b/mishell/src/main/java/org/apache/felix/mishell/Command.java
new file mode 100644
index 0000000..648428e
--- /dev/null
+++ b/mishell/src/main/java/org/apache/felix/mishell/Command.java
@@ -0,0 +1,9 @@
+package org.apache.felix.mishell;

+

+import java.io.PrintStream;

+

+public interface Command {

+	public void executeCommand(String cmd, PrintStream out) throws Exception;

+	public String getName();

+	public String getHelp();

+}

diff --git a/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java b/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java
new file mode 100644
index 0000000..9da9126
--- /dev/null
+++ b/mishell/src/main/java/org/apache/felix/mishell/CommandNotFoundException.java
@@ -0,0 +1,5 @@
+package org.apache.felix.mishell;

+

+public class CommandNotFoundException extends Exception {

+

+}

diff --git a/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java b/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java
new file mode 100644
index 0000000..3e8b05b
--- /dev/null
+++ b/mishell/src/main/java/org/apache/felix/mishell/EngineNotFoundException.java
@@ -0,0 +1,9 @@
+package org.apache.felix.mishell;

+

+public class EngineNotFoundException extends Exception {

+

+	public EngineNotFoundException(String language) {

+		super(language);

+	}

+

+}

diff --git a/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java b/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java
new file mode 100644
index 0000000..73a545f
--- /dev/null
+++ b/mishell/src/main/java/org/apache/felix/mishell/JMoodProxyManager.java
@@ -0,0 +1,27 @@
+package org.apache.felix.mishell;

+

+import java.util.List;

+

+import javax.management.MBeanServerConnection;

+

+import org.apache.felix.jmxintrospector.MBean;

+import org.apache.felix.jmxintrospector.MBeanProxyManager;

+

+public class JMoodProxyManager extends MBeanProxyManager {

+	public List<Object> getControllers(){

+		return findAll("type=controller");

+	}

+	public List<Object> getBundlesAt(Object controller){

+		MBeanServerConnection server=((MBean)controller).getMBeanServer();

+		return findAll("type=bundle", server);

+	}

+	public List<Object> getServicesAt(Object controller){

+		MBeanServerConnection server=((MBean)controller).getMBeanServer();

+		return findAll("type=service", server);

+	}

+	public List<Object> getPackagesAt(Object controller){

+		MBeanServerConnection server=((MBean)controller).getMBeanServer();

+		return findAll("type=package", server);

+	}

+	

+}

diff --git a/mishell/src/main/resources/logging.properties b/mishell/src/main/resources/logging.properties
new file mode 100644
index 0000000..65f94dd
--- /dev/null
+++ b/mishell/src/main/resources/logging.properties
@@ -0,0 +1,54 @@
+############################################################

+#  	Default Logging Configuration File

+#

+# You can use a different file by specifying a filename

+# with the java.util.logging.config.file system property.  

+# For example java -Djava.util.logging.config.file=myfile

+############################################################

+

+############################################################

+#  	Global properties

+############################################################

+

+# "handlers" specifies a comma separated list of log Handler 

+# classes.  These handlers will be installed during VM startup.

+# Note that these classes must be on the system classpath.

+# By default we only configure a ConsoleHandler, which will only

+# show messages at the INFO and above levels.

+handlers= java.util.logging.ConsoleHandler

+

+# To also add the FileHandler, use the following line instead.

+#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

+

+# Default global logging level.

+# This specifies which kinds of events are logged across

+# all loggers.  For any given facility this global level

+# can be overriden by a facility specific level

+# Note that the ConsoleHandler also has a separate level

+# setting to limit messages printed to the console.

+.level= FINEST

+

+############################################################

+# Handler specific properties.

+# Describes specific configuration info for Handlers.

+############################################################

+

+# default file output is in user's home directory.

+java.util.logging.FileHandler.pattern = %h/java%u.log

+java.util.logging.FileHandler.limit = 50000

+java.util.logging.FileHandler.count = 1

+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

+

+# Limit the message that are printed on the console to INFO and above.

+java.util.logging.ConsoleHandler.level = FINE

+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

+

+

+############################################################

+# Facility specific properties.

+# Provides extra control for each logger.

+############################################################

+

+# For example, set the com.xyz.foo logger to only log SEVERE

+# messages:

+com.xyz.foo.level = SEVERE

diff --git a/mishell/src/test/java/org/apache/felix/mishell/FelixLauncher.java b/mishell/src/test/java/org/apache/felix/mishell/FelixLauncher.java
new file mode 100644
index 0000000..d2a085f
--- /dev/null
+++ b/mishell/src/test/java/org/apache/felix/mishell/FelixLauncher.java
@@ -0,0 +1,157 @@
+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.

+ *

+ */

+

+import java.io.BufferedReader;

+import java.io.File;

+import java.io.InputStreamReader;

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+import java.util.logging.Logger;

+

+import javax.management.MBeanServerConnection;

+

+import org.apache.felix.framework.Felix;

+import org.apache.felix.framework.util.MutablePropertyResolver;

+import org.apache.felix.framework.util.MutablePropertyResolverImpl;

+import org.osgi.framework.Constants;

+public class FelixLauncher {

+

+    private MutablePropertyResolver props;

+	private Felix framework;

+	private List bundles;

+	private List packages;

+	private File cacheDir;

+	public FelixLauncher() {

+        super();

+    	cacheDir = new File("./cache");

+    	System.out.println(cacheDir.getAbsolutePath());

+		clearCache(cacheDir);

+    	cacheDir.mkdir();

+        

+        framework = new Felix();

+		Map m=new HashMap();

+		bundles=new ArrayList();

+		packages=new ArrayList();

+

+        props = new MutablePropertyResolverImpl(m);

+        props.put("felix.cache.profiledir", cacheDir.getAbsolutePath());

+

+    }

+	public void addBundle(String url){

+		if (!bundles.contains(url))

+		bundles.add(url);

+	}

+	public void addPackage(String packageName){

+		if(!packages.contains(packageName))

+		packages.add(packageName);

+	}

+	public void start(){

+		StringBuffer autostart=new StringBuffer();

+		for (int i=0; i<bundles.size(); i++){

+			String bundle=(String)bundles.get(i);

+			autostart.append(bundle).append(" ");

+		}

+		props.put("felix.auto.start.1", autostart.toString());

+		StringBuffer spkg=new StringBuffer((String)packages.get(0));

+		packages.remove(0);

+		for (int i=0; i<packages.size(); i++){

+			String pkg=(String)packages.get(i);

+			spkg.append(", "+pkg);

+		}

+		

+		

+        props.put(Constants.FRAMEWORK_SYSTEMPACKAGES, spkg.toString());

+

+        framework.start(props,null);

+	}

+	public void blockingStart() throws Exception{

+		this.start();

+        int to=0;

+        while(framework.getStatus()!=Felix.RUNNING_STATUS) {

+            Thread.sleep(10);

+            to++;

+            if(to>100) throw new Exception("timeout");

+        }

+

+	}

+	public void shutdown(){

+		framework.shutdown();

+		clearCache(cacheDir);

+	}

+

+	private void clearCache(File cacheDir) {

+		if(!isCache(cacheDir)){

+			System.out.println("not valid cache");

+			return;

+		}

+		File[] files=cacheDir.listFiles();

+		for(int i=0; i<files.length; i++){

+			recursiveDelete(files[i]);

+		}

+	}

+	private void recursiveDelete(File file){

+	   if(file.isDirectory()){

+			File[] files=file.listFiles();

+			for(int i=0; i<files.length; i++){

+				File f=files[i];	

+				recursiveDelete(f);

+		   }

+	   }

+	   file.delete();

+	}

+	private boolean isCache(File cacheDir){

+		if(!cacheDir.exists()||!cacheDir.isDirectory()) return false;

+		else{

+			String[] names=cacheDir.list();

+			for(int i=0;i<names.length;i++){

+				String name=names[i];

+				if(!name.startsWith("bundle")) return false;

+			}

+			return true;

+		}

+	}

+

+    /**

+     * @param args

+     */

+    public static void main(String[] args) throws Exception{

+    	FelixLauncher launcher=new FelixLauncher();

+        String jmood="file:../org.apache.felix.jmood_trunk/target/org.apache.felix.jmood-0.8.0-SNAPSHOT.jar";

+        String jmxintrospector="file:../org.apache.felix.mishell/target/org.apache.felix.mishell-0.8.0-SNAPSHOT.jar";

+    	launcher.addBundle(jmood);

+    	launcher.addBundle(jmxintrospector);

+        launcher.addPackage("org.osgi.framework");

+        launcher.addPackage("org.osgi.util.tracker");

+        launcher.addPackage("org.osgi.service.log");

+        launcher.addPackage("org.osgi.service.packageadmin");

+        launcher.addPackage("org.osgi.service.startlevel");

+        launcher.addPackage("org.osgi.service.permissionadmin");

+        launcher.addPackage("org.osgi.service.useradmin");

+        launcher.addPackage("org.osgi.service.cm");

+        launcher.addPackage("javax.management");

+        launcher.addPackage("javax.management.remote");

+        launcher.addPackage("javax.management.openmbean");  

+        launcher.addPackage("javax.script");

+    	launcher.start();

+    }

+	public Felix getFramework() {

+		return framework;

+	}

+}

diff --git a/mishell/src/test/java/org/apache/felix/mishell/TypeTest.java b/mishell/src/test/java/org/apache/felix/mishell/TypeTest.java
new file mode 100644
index 0000000..8e34067
--- /dev/null
+++ b/mishell/src/test/java/org/apache/felix/mishell/TypeTest.java
@@ -0,0 +1,19 @@
+package org.apache.felix.mishell;

+

+import org.objectweb.asm.Type;

+

+public class TypeTest {

+

+	/**

+	 * @param args

+	 */

+	public static void main(String[] args) {

+		StringBuffer s=new StringBuffer();

+		s.append("bolean type: ");

+		s.append(Type.BOOLEAN_TYPE.getDescriptor()+"\n");

+		s.append("String: "+Type.getType((new String()).getClass()));

+		System.out.println(s);

+

+	}

+

+}