mcconnell    2003/02/16 05:02:02

  Modified:    merlin-bootstrap/src/java Merlin.java Resources.properties
  Log:
  Optimization of the kernel/block seperation and enhanced command line 
management.
  
  Revision  Changes    Path
  1.2       +299 -81   avalon-sandbox/merlin-bootstrap/src/java/Merlin.java
  
  Index: Merlin.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/merlin-bootstrap/src/java/Merlin.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Merlin.java       12 Feb 2003 11:51:18 -0000      1.1
  +++ Merlin.java       16 Feb 2003 13:02:02 -0000      1.2
  @@ -57,6 +57,8 @@
   import java.util.Date;
   import java.util.List;
   import java.util.ArrayList;
  +import java.util.Map;
  +import java.util.Hashtable;
   import java.util.Locale;
   import java.net.URL;
   import java.net.URLClassLoader;
  @@ -84,9 +86,9 @@
       // static
       
//--------------------------------------------------------------------------
   
  -    private static final String PRODUCT = "Merlin";
  +    private static final String PRODUCT = "Merlin CLI";
   
  -    private static final String VERSION = "2.1";
  +    private static final String VERSION = "1.0";
   
       private static final File HOME = new File( System.getProperty( 
"user.dir" ) );
   
  @@ -139,18 +141,32 @@
              .withDescription( I18N.getString( "cli-system-description" ) )
              .create( "system" );
   
  -        Option profile = OptionBuilder
  +        Option block = OptionBuilder
              .hasArg()
              .withArgName( I18N.getString( "file" ) )
  -           .withDescription( I18N.getString( "cli-profile-description" ) )
  -           .create( "profile" );
  +           .withDescription( I18N.getString( "cli-block-description" ) )
  +           .create( "block" );
  +
  +        Option config = OptionBuilder
  +           .hasArg()
  +           .withArgName( I18N.getString( "file" ) )
  +           .withDescription( I18N.getString( "cli-config-description" ) )
  +           .create( "config" );
  +
  +        Option kernel = OptionBuilder
  +           .hasArg()
  +           .withArgName( I18N.getString( "file" ) )
  +           .withDescription( I18N.getString( "cli-kernel-description" ) )
  +           .create( "kernel" );
   
           options.addOption( help );
           options.addOption( version );
           options.addOption( debug );
           options.addOption( system );
           options.addOption( home );
  -        options.addOption( profile );
  +        options.addOption( block );
  +        options.addOption( config );
  +        options.addOption( kernel );
           options.addOption( locale );
   
           return options;
  @@ -172,6 +188,8 @@
       */
       public static void main( String[] args )
       {
  +        Map map = new Hashtable();
  +
           CommandLineParser parser = new BasicParser();
           try
           {
  @@ -199,95 +217,116 @@
                   return;
               }
   
  +            if( !line.hasOption( "block" ) )
  +            {
  +                doHelp();
  +                return;
  +            }
  +
  +            boolean debug = line.hasOption( "debug" );
  +
               //
  -            // it's this is a genuine deployment scenario - we need to 
resolve
  +            // this is a genuine deployment scenario - we need to resolve
               // the home and system directories, and the filename of the 
kernel
  -            // profile we are using
  +            // and block profiles we are using
               //
   
  -            File home = getHomePath( line );
  -            File system = getSystemPath( line );
  -            File profile = getProfile( home, line );
  +            //
  +            // the the system directory that we use internally to build the 
  +            // classloaders
  +            File system = getSystemPath( line ); 
   
  -            if( !profile.exists() )
  -            {
  -                File base = profile.getParentFile();
  -                if( !base.exists() )
  -                {
  -                    final String error = 
  -                      "Deployment path directory does not exist.\ndirectory: 
" + base;
  -                    throw new IllegalArgumentException( error );
  -                }
  -                else
  -                {
  -                    final String error = 
  -                      "Deployment profile does not exist\nfile: " + profile;
  -                    throw new IllegalArgumentException( error );
  -                }
  -            }
  +            //
  +            // the working home directory 
  +            File home = getHomePath( system, line );
   
  -            if( !system.exists() )
  +            //
  +            // the actual block base URL
  +            File base = getBlockPath( system, home, line );
  +
  +            URL block = null;
  +            if( base.toString().endsWith(".jar") )
               {
  -                final String error = 
  -                  "System directory does not exist.\ndirectory: " + system;
  -                    throw new IllegalArgumentException( error );
  +                block = new URL( "jar:" + base.toURL() + "!/" );
               }
  -
  -            if( !home.exists() )
  +            else
               {
  -                final String error = 
  -                  "Home directory does not exist.\ndirectory: " + home;
  -                    throw new IllegalArgumentException( error );
  +                block = base.toURL();
               }
   
               //
  -            // if we get this far we have a valid system, home and profile
  -            // so we can not go ahead with bootstrap classpath construction
  +            // an optional configuration override
  +            File config = getConfigPath( base, line );
  +
  +            //
  +            // the kernel configuration (used by the kernel loader)
  +            File kernel = getKernelPath( system, line );
  +
  +            //
  +            // build the classloaders
               //
   
  -            BASE = home;
  -            PROFILE = profile;
  -            boolean debug = line.hasOption( "debug" );
  +            File lib = new File( system, "lib" );
  +            File shared = new File( lib, "shared" );
  +            File sys = new File( lib, "system" );
  +            URL[] targets = getJarFiles( shared );
  +            URL[] libs = getJarFiles( sys, targets );
  +            ClassLoader current = 
Thread.currentThread().getContextClassLoader();
  +            COMMON = new URLClassLoader( targets, current );
  +            CLASSLOADER =  new URLClassLoader( libs, current );
  +
  +            //
  +            // build the kernel loader context
  +            //
  +
  +            map.put( "urn:merlin:classloader.common", COMMON );
  +            map.put( "urn:merlin:classloader.system", CLASSLOADER);
  +            map.put( "urn:merlin:home", home );
  +            map.put( "urn:merlin:kernel.profile", kernel );
  +            map.put( "urn:merlin:block.url", block );
               if( debug )
               {
  -                System.out.println( "\n  " + getVersionString()  );
  -                System.out.println( "  " + new Date()  );
  -                System.out.println( "\n  urn:merlin:system.dir: " + system  
);
  -                System.out.println( "  urn:merlin:system.profile: " + 
profile );
  -                System.out.println( "  urn:merlin:home.dir: " + home );
  +                map.put( "urn:merlin:debug", "debug" );
               }
  +            if( config != null )
  +            {
  +                map.put( "urn:merlin:block.config", config.toURL() );
  +            }
  +
  +            //
  +            // if the -debug switch is on then dump the context information
  +            // that we will supply to the kernel loader
  +            //
   
  -            File common = new File( system, "common" );
  -            URL[] targets = getJarFiles( common );
  -            COMMON = new URLClassLoader( targets );
               if( debug )
               {
  +                System.out.println( "\n  " + getVersionString()  );
  +                System.out.println( "  " + new Date() + "\n" );
  +                System.out.println( "  urn:merlin:system.dir:     " + system 
 );
  +                System.out.println( "  urn:merlin:kernel.profile: " + kernel 
);
  +
  +                System.out.println( "  urn:merlin:block.url:     " + block );
  +                if( config != null )
  +                {
  +                    System.out.println( "  urn:merlin:block.config:   " + 
config.toURL() );
  +                }
  +                System.out.println( "  urn:merlin:home:           " + home );
  +                System.out.println( "\n " );
  +
                   System.out.println( "\n  shared libraries:\n" );
  -                for( int i=0; i<targets.length; i++ )
  +                URL[] list = COMMON.getURLs();
  +                for( int i=0; i<list.length; i++ )
                   {
  -                    System.out.println("  " + targets[i] );
  +                    System.out.println("  " + list[i] );
                   }
  -            }
  -            
  -            File lib = new File( system, "lib" );
  -            URL[] libs = getJarFiles( lib );
  -            CLASSLOADER = new URLClassLoader( libs, COMMON );
  -            if( debug )
  -            {
                   System.out.println( "\n  system libraries:\n" );
  -                for( int i=0; i<libs.length; i++ )
  +                list = CLASSLOADER.getURLs();
  +                for( int i=0; i<list.length; i++ )
                   {
  -                    System.out.println("  " + libs[i] );
  +                    System.out.println("  " + list[i] );
                   }
  -            }
  -
  -            if( debug )
  -            {
                   System.out.println( "\n" );
               }
  -
  -            Thread.currentThread().setContextClassLoader( CLASSLOADER );
  -
           }
           catch( ParseException e )
           {
  @@ -313,7 +352,20 @@
               System.err.println( error );
               return;
           }
  +        catch( Throwable e )
  +        {
  +            final String error = "\n" + e.toString();
  +            System.err.println( error );
  +            e.printStackTrace();
  +            return;
  +        }
  +
  +        //
  +        // if we get this far we have a valid system, home and profile
  +        // so we can not go ahead with bootstrap classpath construction
  +        //
   
  +        Thread.currentThread().setContextClassLoader( CLASSLOADER );
           Object kernelLoader = null;
           Class clazz;
           try
  @@ -330,8 +382,8 @@
           try
           {
               Constructor constructor = clazz.getConstructor(
  -                new Class[]{ClassLoader.class, ClassLoader.class, 
File.class, File.class } );
  -            kernelLoader = constructor.newInstance( new Object[]{ 
CLASSLOADER,  COMMON, BASE, PROFILE } );
  +                new Class[]{ Map.class } );
  +            kernelLoader = constructor.newInstance( new Object[]{ map } );
           }
           catch( Throwable e )
           {
  @@ -353,6 +405,162 @@
           formatter.printHelp( "merlin", CL_OPTIONS );
       }
   
  +    private static File getConfigPath( File block, CommandLine command ) 
throws IOException
  +    {
  +        String filename = null;
  +        final String key = "config";
  +        if( command.hasOption( key ) )
  +        {
  +            filename = command.getOptionValue( key );
  +        }
  +        else
  +        {
  +            filename = "config.xml";
  +        }
  +        File file = getFile( HOME, filename );
  +        if( file.exists() )
  +        {
  +             return file;
  +        }
  +        else
  +        {
  +             File info = new File( block, "block-inf" );
  +             File config = new File( info, "config.xml" );
  +             if( config.exists() )
  +             {
  +                 return config;
  +             }
  +             else
  +             {
  +                 return null;
  +             }
  +        }
  +    }
  +
  +    private static File getKernelPath( File system, CommandLine command ) 
throws IOException
  +    {
  +        String filename = null;
  +        final String key = "kernel";
  +        if( command.hasOption( key ) )
  +        {
  +            filename = command.getOptionValue( key );
  +            File file = getFile( HOME, filename );
  +            if( file.exists() )
  +            {
  +                return file;
  +            }
  +            else
  +            {
  +                final String error =
  +                  "Supplied kernel configuration file does not exist: "
  +                  + file;
  +                throw new IOException( error );
  +            }
  +        }
  +        else
  +        {
  +            File conf = new File( system, "config" );
  +            File kernel = new File( conf, "kernel.xml" );
  +            if( !kernel.exists() )
  +            {
  +                final String error = 
  +                  "Could not locate the kernel configuration 
${merlin.kernel}/config/kernel.xml";
  +                throw new IOException( error );
  +            }
  +            else
  +            {
  +                return kernel;
  +            }
  +        }
  +    }
  +
  +    private static File getBlockPath( File system, File home, CommandLine 
command ) throws IOException
  +    {
  +        boolean flag = false;
  +        String filename = null;
  +        final String key = "block";
  +        if( command.hasOption( key ) )
  +        {
  +            filename = command.getOptionValue( key );
  +        }
  +        else
  +        {
  +            // check if there is a file in the current directory called 
block.xml
  +            // and if so, we will use that as the deployment scanario
  +
  +            filename = "block.xml";
  +            File local = getFile( HOME, "block.xml" );
  +            if( local.exists() )
  +            {
  +                //
  +                // the current directory is equivalent to the info directory
  +                // so the base directory is the parent of the current 
directory
  +                
  +                return local.getParentFile();
  +            }
  +        }
  +
  +        //
  +        // if the filename is a jar file then return the filename as a URL
  +        //
  +
  +        boolean resolved = false;
  +        File file = getFile( HOME, filename );
  +        if( file.exists() )
  +        {
  +            return file;
  +        }
  +
  +        /*
  +        if( file.exists() )
  +        {
  +            if( file.isDirectory() )
  +            {
  +                //
  +                // this is a simulated block - makle sure the structure is 
valid
  +                // before return the URL
  +                //
  +
  +                File info = new File( file, "block-inf" );
  +                if( info.isDirectory() )
  +                {
  +                    // check for the block.xml file
  +
  +                    File block = new File( info, "block.xml" );
  +                    if( block.exists() )
  +                    {
  +                        // its a good reference
  +                        return file;
  +                    }
  +                    else
  +                    {
  +                        final String error = 
  +                          "Invalid block simulation - the supplied directory 
'" 
  +                          + file + "' does not contain a 
'block-inf/block.xml' defintion.";
  +                        throw new IllegalArgumentException( error );
  +                    }
  +
  +                }
  +                else
  +                {
  +                    final String error = 
  +                      "Invalid block simulation - the supplied directory '" 
  +                      + file + "' does not contain a 'block-inf' 
subdirectory.";
  +                    throw new IllegalArgumentException( error );
  +                }
  +            }
  +            else
  +            {
  +                // its an existing file
  +                return file;
  +            }
  +        }
  +        */
  +        final String error =
  +           "Unable to locate a block defintion relative to the paths: " + 
file;
  +        throw new IllegalArgumentException( error );
  +    }
  +
       private static File getProfile( File home, CommandLine command ) throws 
IOException
       {
           boolean flag = false;
  @@ -386,7 +594,16 @@
           }
       }
   
  -    private static File getHomePath( CommandLine command ) throws IOException
  +   /**
  +    * Return the directory to be used as the working home directory.  If not 
command line 
  +    * argument is supplied, the home directory defaults to 
${merlin.system.dir}/home.
  +    *
  +    * @param system the fallback system directory
  +    * @param command the command line arguments
  +    * @return the home directory
  +    * @exception IOException if an error occurs in directory resolution
  +    */
  +    private static File getHomePath( File system, CommandLine command ) 
throws IOException
       {
           String path = null;
           File file = null;
  @@ -394,13 +611,12 @@
           if( command.hasOption( key ) )
           {
               path = command.getOptionValue( key );
  -            file = getFile( HOME, path );
  +            return getFile( HOME, path );
           }
           else
           {
  -            file = HOME;
  +            return system;
           }
  -        return file;
       }
   
       private static File getSystemPath( CommandLine command ) throws 
IOException
  @@ -418,13 +634,6 @@
                 "Supplied system path does not refer to a directory: " + file;
               throw new IllegalArgumentException( error );
           }
  -        File common = new File( file, "common" );
  -        if( !common.exists() )
  -        {
  -            final String error = 
  -              "Supplied system path does not contain a 'common' 
subdirectory: " + file;
  -            throw new IllegalArgumentException( error );
  -        }
           File lib = new File( file, "lib" );
           if( !lib.exists() )
           {
  @@ -483,7 +692,16 @@
   
       private static URL[] getJarFiles( File base )
       {
  +        return getJarFiles( base, new URL[0] );
  +    }
  +
  +    private static URL[] getJarFiles( File base, URL[] urls )
  +    {
           List list = new ArrayList();
  +        for( int i=0; i<urls.length; i++ )
  +        {
  +            list.add( urls[i] );
  +        }
           populateJars( list, base );
           return (URL[]) list.toArray( new URL[0] );
       }
  @@ -505,7 +723,7 @@
           catch( Throwable e )
           {
               final String error =
  -              "Unexpected error while scanning files in common directory: " 
+ base;
  +              "Unexpected error while scanning files in shared directory: " 
+ base;
               throw new RuntimeException( error, e );
           }
       }
  
  
  
  1.2       +14 -2     
avalon-sandbox/merlin-bootstrap/src/java/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin-bootstrap/src/java/Resources.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Resources.properties      12 Feb 2003 11:51:18 -0000      1.1
  +++ Resources.properties      16 Feb 2003 13:02:02 -0000      1.2
  @@ -1,12 +1,24 @@
   
   directory=directory
  +
   file=file
   
   cli-help-description=Prints this message.
  +
   cli-language-description=A two-letter language code.
  -cli-version-description=Prints the Merlin system version number.
  +
  +cli-version-description=Prints Merlin version information.
  +
   cli-debug-description=Enable debug messages during the bootstrap phase.
  +
   cli-home-description=A relative or absolute path to a working home 
directory. If not suppled, the system will default to the current directory. If 
the resolved home path does not exist it will be created.
  +
  +cli-kernel-description=The filename of the kernel configuration.  The value 
defaults to the system kernel.xml file.
  +
  +cli-block-description=An absolute or relative filename of a block descriptor 
or block jar file (required).
  +
  +cli-config-description=The filename of the block configuration.  If not 
specified the value defaults to a file name config.xml in the same directory as 
the block.
  +
   cli-system-description=An absolute or relative path to the directory 
containining the /common and /lib system directories. If not supplied the 
default value shall correspond to the value System "user.work". A relative path 
name will be resolved relative the System "user.work" directory.
  -cli-profile-description=An absolute or relative filename of a configuration 
containing the kernel and block deployment information. If the supplied 
filename is relative it will resolved relative to the home directory. If not 
supplied, the system will attempt to locate a file named "profile.xml" in the 
home directory.
  +
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to