Hi Marc,

I think i might have solved two problems that jboss had.
1. The minimum number of jars you need to boot jboss off the network 
includes all the jars in the \lib dir ~ 480K.
2. Integrating (or embeding) jboss into the process space of an existing app 
is hard since jboss does so much classloader juggling.

I crated a "Boot" class that lets you start multiple main(String[]) 
applications each with it's own classloader and in it's own threadgroup.  
The classpath to the applications are in URL format so we should be able to 
use this Boot class load the jboss minimum jars from the network (like 
crimson and jmxri).

Anyways..  I tested it out with JBoss, to see if my Boot class could boot 
the org.jboss.Main and it worked after a small tweak of the 
UnifiedClassLoader.

The commnd line of the jboss boot looks something like:
java -classpath mboot.jar chirino.mboot.Boot -cp 
file:../lib/jmxri.jar,file:../lib/jboss-boot.jar,file:../lib/jaxp.jar,file:../lib/getopt.jar,file:../lib/crimson.jar,file:run.jar
 
org.jboss.Main default

Yeah I know, I should read in the manifest to make it easier.

I'm going to attach the sources.  Let me know what you think.  Is it a value 
add to the jboss boot process??

Regards,
Hiram




_________________________________________________________________
Chat with friends online, try MSN Messenger: http://messenger.msn.com
package chirino.mboot;

import java.net.*;
import java.lang.reflect.*;
import java.io.*;
import java.util.*;

/**
* Starts multiple applications using seperate classloaders.
* This allows multiple applications to co-exist even if they typicaly could 
not due to
* class version problems.  Each application is started in it's own thread.
*
* Usage is Boot [-debug] -cp app-classpath app-class-name app-arguments ( , 
-cp app-classpath app-class-name app-arguments )*
*
* Where:
*       app-classpath is a comma seperated URL form classpath to the application 
classes.
*       app-class-name is the class that will be started
*       app-arguments will be the String[] that will be passed to the main method 
of the application class
*
* example:
*
* Main -mbuss-app -cp file:./app1.jar,file:./util.jar test.App1TEST arg1 
arg2 -mbuss-app -cp file:./app2.jar,file:./util.jar test.App2TEST arg1 arg2
* Would start two application class main methods:  App1TEST.main() and 
App2TEST.main()
*
*/
public class Boot {

        /**
         * Indicates whether this instance is running in debug mode.
         */
        protected boolean debug = false;
        protected LinkedList applicationBoots;

        // constants
        private static final String DEBUG = "-debug";
        private static final String BOOT_APP_SEPERATOR = 
System.getProperty("mbus.boot.BOOT_APP_SEPERATOR", ",");
        private static final String CP = "-cp";

        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
                try {
                        new Boot().run(args);
                } catch (Throwable e) {
                        System.err.println("Exception launching the application(s):");
                        e.printStackTrace(System.err);
                }
        }

        /**
         * Data that is extracted for each mbus app that is specified on the 
command line
         */
        class ApplicationBoot implements Runnable {

                LinkedList classpath = new LinkedList();
                String applicationClass;
                LinkedList passThruArgs = new LinkedList();
                URLClassLoader classloader;
                boolean isRunning;

                public void run() {
                        try {
                                boot();
                        } catch ( Throwable e ) {
                                System.err.println("Exception durring 
"+applicationClass+" application 
run: ");
                                e.printStackTrace(System.err);
                        }
                }

                public void boot() throws ClassNotFoundException, 
NoSuchMethodException, 
IllegalAccessException, InvocationTargetException {
                        URL urls[] = new URL[classpath.size()];
                        urls = (URL[])classpath.toArray(urls);

                        String args[] = new String[passThruArgs.size()];
                        args = (String[])passThruArgs.toArray(args);

                        classloader = new URLClassLoader(urls, 
Thread.currentThread().getContextClassLoader());
                        Class appClass = classloader.loadClass(applicationClass);
                        Method mainMethod = appClass.getMethod("main", new Class[] 
{String[].class} );

                        try {
                                isRunning = true;
                                mainMethod.invoke(null, new Object[] {args});
                        } catch (InvocationTargetException e) {
                                if (e.getTargetException() instanceof Error)
                                        throw (Error)e.getTargetException();
                                else
                                        throw e;
                        } finally {
                                isRunning = false;
                        }
                }
        }

        /**
         * Runs the applications to be launched.
         *
         * @param args the arguments to pass to the application
         * @exception thrown if a problem occurs during launching
         */
        public void run(String[] args) throws Exception {
                // Put the args in a linked list since it easier to work with.
                LinkedList llargs = new LinkedList();
                for( int i=0; i < args.length; i++ ) {
                        llargs.add(args[i]);
                }

                applicationBoots = processCommandLine(llargs);
                Iterator i = applicationBoots.iterator();
                while( i.hasNext() ) {
                        ApplicationBoot bootData = (ApplicationBoot)i.next();
                        bootApplication( bootData );
                }
        }

        public void bootApplication( ApplicationBoot bootData) throws Exception {
                ThreadGroup threads = new ThreadGroup(bootData.applicationClass);
        new Thread(threads, bootData, "main").start();
        }

        /**
         * Processes the command line arguments
         *
         * @return a linked list with ApplicationBoot objects
         * @param args the command line arguments
         */
        protected LinkedList processCommandLine(LinkedList args) throws Exception {
                LinkedList rc = new LinkedList();

                processBootOptions( args );
                while( args.size() > 0 ) {
                        ApplicationBoot d = processAppBootCommandLine( args );
                        if( d != null )
                                rc.add(d);
                }

                if( rc.size() == 0 ) {
                        throw new Exception("Invlid usage: An application class name 
must be 
provided.");
                }

                return rc;
        }

        protected void processBootOptions(LinkedList args) throws Exception {
                Iterator i = args.iterator();
                while( i.hasNext() ) {
                        String arg = (String)i.next();
                        if( arg.equalsIgnoreCase(DEBUG) ) {
                                debug = true;
                                i.remove();
                                continue;
                        }

                        // Didn't recognize it a boot option, then we must have 
started the 
application
                        // boot options.
                        return;
                }
        }

        protected ApplicationBoot processAppBootCommandLine(LinkedList args) throws 
Exception {
                ApplicationBoot rc = new ApplicationBoot();
                Iterator i = args.iterator();

                while( i.hasNext() ) {
                        String arg = (String)i.next();
                        i.remove();

                        if( rc.applicationClass == null ) {
                                if( arg.equalsIgnoreCase(CP) ) {
                                        if( !i.hasNext() )
                                                throw new Exception("Invalid option: 
classpath missing after the 
"+CP+" option.");
                                        String cp = (String)i.next();
                                        i.remove();

                                        StringTokenizer st = new StringTokenizer(cp, 
",", false);
                                        while( st.hasMoreTokens() ) {
                                                String t = st.nextToken();
                                                if( t.length() == 0 )
                                                        continue;
                                                try {
                                                        URL u = new URL(t);
                                                        rc.classpath.add(u);
                                                } catch ( MalformedURLException e ) {
                                                        throw new 
Exception("Application classpath value was invalid: 
"+e.getMessage());
                                                }
                                        }
                                        continue;
                                }

                                rc.applicationClass = arg;
                                continue;
                        } else {
                                if( arg.equalsIgnoreCase(BOOT_APP_SEPERATOR) ) {
                                        break;
                                }
                                rc.passThruArgs.add( arg );
                        }

                }

                if( rc.applicationClass == null )
                        return null;

                return rc;
        }
}

Reply via email to