You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2004/01/31 14:29:50 UTC

cvs commit: avalon/repository/cli/src/java/org/apache/avalon/repository/cli Main.java Resources.properties package.html

mcconnell    2004/01/31 05:29:50

  Added:       repository/cli/src/java/org/apache/avalon/repository/cli
                        Main.java Resources.properties package.html
  Log:
  Update build procedure to include:
    1. consitent deliverable naming convention
    2. automation of MD5 and ASC file creation for jar and distribution artifacts
  System changes encompassing:
    1. updates to the InitialContext and Builder interface and implementation to support target class retrival and bar exansion
    2. addition of a commandline interface supporting bar file retrival
    3. implementation of bar expansion via the InitialContext
  Admin updates include ASL 2.0 in main license file
  
  Revision  Changes    Path
  1.1                  avalon/repository/cli/src/java/org/apache/avalon/repository/cli/Main.java
  
  Index: Main.java
  ===================================================================
  /* 
   * Copyright 2004 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.avalon.repository.cli;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Map;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.util.Enumeration;
  import java.util.Locale;
  import java.util.ArrayList;
  import java.util.StringTokenizer;
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationTargetException;
  import java.net.URL;
  
  import javax.naming.directory.Attributes;
  
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  
  import org.apache.avalon.repository.Artifact;
  import org.apache.avalon.repository.provider.Builder;
  import org.apache.avalon.repository.provider.InitialContext;
  import org.apache.avalon.repository.provider.Factory;
  import org.apache.avalon.repository.RepositoryException;
  import org.apache.avalon.repository.main.DefaultInitialContext;
  import org.apache.avalon.repository.main.DefaultBuilder;
  import org.apache.avalon.repository.meta.ArtifactDescriptor;
  import org.apache.avalon.repository.util.RepositoryUtils;
  import org.apache.avalon.util.env.Env;
  import org.apache.avalon.util.exception.ExceptionHelper;
  
  import org.apache.commons.cli.BasicParser;
  import org.apache.commons.cli.CommandLine;
  import org.apache.commons.cli.CommandLineParser;
  import org.apache.commons.cli.HelpFormatter;
  import org.apache.commons.cli.Option;
  import org.apache.commons.cli.OptionBuilder;
  import org.apache.commons.cli.Options;
  
  
  /**
   * Merlin command line handler.
   * 
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $
   */
  public class Main 
  {
      //----------------------------------------------------------
      // static
      //----------------------------------------------------------
  
      private static Resources REZ =
          ResourceManager.getPackageResources( Main.class );
  
      private static final File USER_HOME = 
        new File( System.getProperty( "user.home" ) );
  
      private static final String AVALON_PROPERTIES = "avalon.properties";
  
      private static final String IMPLEMENTATION_KEY = "avalon.repository.implementation";
  
      private static Options CL_OPTIONS = buildCommandLineOptions();
  
      private static Options buildCommandLineOptions()
      {
          Options options = new Options();
  
          Option help = new Option(
             "help",
             REZ.getString( "cli-help-description" ) );
  
          Option version = new Option(
             "version",
             REZ.getString( "cli-version-description" ) );
  
          Option locale = OptionBuilder
             .hasArg()
             .withArgName( "code" )
             .withDescription( REZ.getString( "cli-language-description" )  )
             .create( "lang" );
  
          Option info = new Option(
             "info",
             REZ.getString( "cli-info-description" ) );
  
          Option implementation = OptionBuilder
             .hasArg()
             .withArgName( "artifact" )
             .withDescription( REZ.getString( "cli-implementation-description" )  )
             .create( "impl" );
  
          Option home = OptionBuilder
             .hasArg()
             .withArgName( REZ.getString( "directory" ) )
             .withDescription( REZ.getString( "cli-home-description" ) )
             .create( "home" );
  
          Option cache = OptionBuilder
             .hasArg()
             .withArgName( REZ.getString( "directory" ) )
             .withDescription( REZ.getString( "cli-cache-description" ) )
             .create( "cache" );
  
          Option hosts = OptionBuilder
             .hasArg()
             .withArgName( REZ.getString( "urls" ) )
             .withDescription( REZ.getString( "cli-hosts-description" ) )
             .create( "hosts" );
  
          Option install = OptionBuilder
             .hasArg()
             .withArgName( REZ.getString( "url" ) )
             .withDescription( REZ.getString( "cli-install-description" ) )
             .create( "install" );
  
          options.addOption( help );
          options.addOption( locale );
          options.addOption( version );
          options.addOption( info );
          options.addOption( implementation );
          options.addOption( install );
          options.addOption( home );
          options.addOption( cache );
          options.addOption( hosts );
          return options;
      }
  
      private static Main MAIN = null;
  
     /**
      * Main command line enty point.
      * @param args the command line arguments
      */
      public static void main( String[] args )
      {
          try
          {
              //
              // parse the commandline
              //
  
              CommandLineParser parser = new BasicParser();
              CommandLine line = parser.parse( CL_OPTIONS, args );
  
              File dir = getWorkingDirectory( line );
              File cache = getCacheDirectory( line );
              Artifact artifact = getDefaultImplementation( dir, line );
  
              if( line.hasOption( "version" ) )
              {
                  Main.printVersionInfo( cache, artifact );
                  return;     
              }
              else if( line.hasOption( "help" ) )
              {
                  if( line.hasOption( "lang" ) )
                  {
                      ResourceManager.clearResourceCache();
                      String language = line.getOptionValue( "lang" );
                      Locale locale = new Locale( language, "" );
                      Locale.setDefault( locale );
                      REZ = ResourceManager.getPackageResources( Main.class );
                  }
  
                  HelpFormatter formatter = new HelpFormatter();
                  formatter.printHelp( 
                    "repository [artifact]", 
                    " ", 
                    buildCommandLineOptions(), 
                    "", 
                    true );
                  return;
              }
              else
              {
                  //
                  // setup the initial context
                  //
  
                  ClassLoader parent = Main.class.getClassLoader();
                  String[] hosts = getHostsPath( line );
                  
                  InitialContext context = 
                     new DefaultInitialContext( 
                       dir, parent, artifact, cache, hosts );
  
                  //
                  // process the commandline and do the real work
                  //
  
                  MAIN = new Main( context, line );
              }
          }
          catch( Throwable e )
          {
              String msg = 
                ExceptionHelper.packException( e, true );
              System.err.println( msg );
              System.exit( -1 );
          }
      }
  
      //----------------------------------------------------------
      // constructor
      //----------------------------------------------------------
  
     /**
      * Creation of a new kernel cli handler.
      * @param context the repository inital context
      * @param artifact the merlin implementation artifact
      * @param line the command line construct
      * @exception Exception if an error occurs
      */
      public Main( 
        InitialContext context, CommandLine line ) throws Exception
      {
          if( line.hasOption( "info" ) )
          {
              StringBuffer buffer = 
                new StringBuffer( InitialContext.LINE );
              buffer.append( "\nAvalon Repository" );
              buffer.append( InitialContext.LINE );
              prepareInfoListing( buffer, context );
              buffer.append( InitialContext.LINE );
              System.out.println( buffer.toString() );
          }
  
          if( line.hasOption( "install" ) )
          {
              doInstall( context, line );
          }
      }
  
      private void prepareInfoListing( StringBuffer buffer, InitialContext context )
      {
          buffer.append( "\n${avalon.repository.cache} = " );
          buffer.append( context.getInitialCacheDirectory() );
          buffer.append( "\n${avalon.dir} = " );
          buffer.append( context.getInitialWorkingDirectory() );
          String[] hosts = context.getInitialHosts();
          buffer.append( "\n${avalon.repository.hosts} = (" );
          buffer.append( hosts.length );
          buffer.append( ")" );
          for( int i=0; i<hosts.length; i++ )
          {
              buffer.append( "\n  " + hosts[i] );
          }
      }
  
      private void doInstall( InitialContext context, CommandLine line ) 
        throws Exception
      {
          final URL url = getInstallTarget( line );
          try
          {
              context.install( url );
          }
          catch( Throwable e )
          {
              final String error = 
                "Install failure: " 
                + url;
              throw new RepositoryException( error, e );
          }
      }
  
      //----------------------------------------------------------
      // implementation
      //----------------------------------------------------------
  
     /**
      * Resolve the merlin.dir value.
      * @param line the command line construct
      * @return the working directory
      */
      private static File getWorkingDirectory( CommandLine line ) throws Exception
      {
          if( line.hasOption( "home" ) )
          {
              String dir = line.getOptionValue( "home" );
              return new File( dir ).getCanonicalFile();
          }
          else
          {
              return getBaseDirectory();
          }
      }
  
      private static String[] getHostsPath( CommandLine line )
      {
          if( line.hasOption( "hosts" ) )
          {
              String hosts = line.getOptionValue( "hosts" );
              return expandHosts( hosts );
          }
          else
          {
              return null;
          }
      }
  
      private static String[] expandHosts( String arg )
      {
          ArrayList list = new ArrayList();
          StringTokenizer tokenizer = new StringTokenizer( arg, "," );
          while( tokenizer.hasMoreTokens() )
          {
              list.add( tokenizer.nextToken() );
          }
          return (String[]) list.toArray( new String[0] );
      }
  
     /**
      * Return the url from the install parameter.
      * @param line the command line construct
      * @return the install target url
      */
      private URL getInstallTarget( CommandLine line ) throws IOException
      {
          String spec = line.getOptionValue( "install" );
          return new URL( spec );
      }
  
     /**
      * Resolve the default implementation taking into account 
      * command line arguments, local and hom properties, and 
      * application defaults.
      * @param line the command line construct
      * @return the artifact reference
      */
      private static Artifact getDefaultImplementation( 
        File base, CommandLine line ) throws Exception
      {
          if( line.hasOption( "impl" ) )
          {
              String spec = line.getOptionValue( "impl" );
              return Artifact.createArtifact( spec );
          }
          else
          {
              return DefaultBuilder.createImplementationArtifact( 
                  Main.class.getClassLoader(), 
                  getAvalonHome(),
                  getBaseDirectory(), 
                  AVALON_PROPERTIES, 
                  IMPLEMENTATION_KEY );
          }
      }
  
     /**
      * Print out version information to System.out.  This function is 
      * invoked in response to the inclusion of the -version switch on
      * the command line.
      *
      * @param cache the local system cache
      * @param artifact the merlin implementation artifact descriptor
      */
      private static void printVersionInfo( File cache, Artifact artifact )
      {
          try
          {
              Attributes attr = RepositoryUtils.getAttributes( cache, artifact );
              ArtifactDescriptor desc = new ArtifactDescriptor( attr );
              System.out.println( "\n  Implementation: " 
                + artifact.getGroup() 
                + ":" + artifact.getName() 
                + ";" + artifact.getVersion() 
                + " (" + desc.getBuild() + ")"
              );
          }
          catch( Throwable e )
          {
              System.out.println( "\nImplementation: " 
                + artifact.getGroup() 
                + ":" + artifact.getName() 
                + ";" + artifact.getVersion() );
          }
      }
  
     /**
      * Return the avalon repository cache directory taking into 
      * account the supplied command-line, and avalon.properties files in 
      * the current and home directories.
      *
      * @param line the command line construct
      * @return the merlin system root repository directory
      */
      private static File getCacheDirectory( CommandLine line )
      {
          if( line.hasOption( "cache" ) )
          {
              String system = line.getOptionValue( "cache" );
              return new File( system );
          }
          else
          {
              return new File( getAvalonHome( ), "repository" );
          }
      }
  
     /**
      * Return the avalon home directory.
      * @return the avalon home directory
      */
      private static File getAvalonHome()
      {
          return new File( getAvalonHomePath() );
      }
  
     /**
      * Return the merlin home directory path.
      * @return the merlin install directory path
      */
      private static String getAvalonHomePath()
      {
          try
          {
              String avalon = 
                System.getProperty( 
                  "avalon.home", 
                  Env.getEnvVariable( "AVALON_HOME" ) );
              if( null != avalon ) return avalon;
              return System.getProperty( "user.home" ) 
                + File.separator + ".avalon";
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to access AVALON_HOME environment.";
              final String message = 
                ExceptionHelper.packException( error, e, true );
              throw new RuntimeException( message );
          }
      }
  
     /**
      * Return the functional base directory.  The implementation looks
      * for the ${avalon.dir} system property and if not found, looks for 
      * the ${basedir} system property, and as a last resort, returns the 
      * JVM ${user.dir} value.
      *
      * @return the merlin install directory
      */
      private static File getBaseDirectory()
      {
          final String path = System.getProperty( "avalon.dir" );
          if( null != path )
          {
              return new File( path );
          }
          final String base = System.getProperty( "basedir" );
          if( null != base )
          {
              return new File( base );
          }
          return new File( System.getProperty( "user.dir" ) );
      }
  
     /**
      * Return a property file from a fir with a supplied filename.
      * @param dir the directory
      * @param filename the filename
      * @return a possibly empty properties instance
      */
      private static Properties getLocalProperties( 
        File dir, String filename ) 
      {
          Properties properties = new Properties();
          if( null == dir ) return properties;
          File file = new File( dir, filename );
          if( !file.exists() ) return properties;
          try
          {
              properties.load( new FileInputStream( file ) );
              return properties;
          }
          catch( Throwable e )
          {
              final String error = 
                "Unexpected exception while attempting to read properties from: " 
                + file + ". Cause: " + e.toString();
              throw new IllegalStateException( error );
          }
      }
  }
  
  
  
  1.1                  avalon/repository/cli/src/java/org/apache/avalon/repository/cli/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  
  url=url
  
  urls=urls
  
  directory=directory
  
  file=file
  
  artifact=artifact
  
  cli-help-description=Prints this message.
  
  cli-version-description=Print version information and return.
  
  cli-language-description=A two-letter language code.
  
  cli-info-description=Lists info about the runtime context.
  
  cli-implementation-description=An artifact specification that overrides the default implementation.
  
  cli-home-description=A relative or absolute path to a working home directory. If not supplied, the system will default to the current directory.
  
  cli-cache-description=The filename of local directory that will be used as a resource cache.
  
  cli-hosts-description=A comma seperated sequence of host urls each referring to a remote repository.
  
  cli-install-description=Install a block archive into the local repository.
  
  
  
  1.1                  avalon/repository/cli/src/java/org/apache/avalon/repository/cli/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>
  The repository main package is the main end-user deliverable providing support for the deynamic resolution and pluging-in of an repository implementation compliance with the Repository SPI Specification.</p>
  <p>Key features include:</p>
  <ul>
  <li>an initial repository factory supporting plugable implementations</li>
  <li>small footprit (28k)</li>
  <li>application bootstrapping service</li>
  <li>integral proxy support</li>
  </ul>  
  </body>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org