akarasulu    2003/11/15 21:45:05

  Added:       repository/api/src/java/org/apache/avalon/repository
                        Bootstrapper.java
  Log:
  
  
  Revision  Changes    Path
  1.1                  
avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/Bootstrapper.java
  
  Index: Bootstrapper.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.repository ;
  
  
  import java.text.ParseException ;
  
  import java.lang.reflect.Method ;
  import java.lang.reflect.InvocationTargetException ;
  
  
  /**
   * Application and component bootstrapper used to instantiate, and or invoke
   * Classes and their methods within newly constructed Repository ClassLoaders.
   * 
   * @author <a href="mailto:[EMAIL PROTECTED]">Alex Karasulu</a>
   * @author $Author: akarasulu $
   * @version $Revision: 1.1 $
   */
  public class Bootstrapper
  {
      /** The repository used by this bootstrapper */
      private final Repository m_repository ;
      /** The Jar artifact descriptor containing the target classes */
      private final JarDescriptor m_descriptor ;
      /** The ClassLoader used to load and instantiate target classes */
      private final ClassLoader m_loader ;
      
      
      /**
       * Creates a Bootstrapper for a specific target Jar artifact's classes.
       */
      public Bootstrapper( Repository a_repository, JarDescriptor a_descriptor )
          throws RepositoryException
      {
          m_repository = a_repository ;
          m_descriptor = a_descriptor ;
          m_loader = a_repository.getClassLoader( a_descriptor ) ;
      }
  
      
      /**
       * Gets the ClassLoader used by this Bootstrapper.
       * 
       * @return the ClassLoader built by the Repository
       */
      public ClassLoader getClassLoader()
      {
          return m_loader ;
      }
      
  
      /**
       * Invokes the main application entry point for a class.
       * 
       * @param a_fqcn the fully qualified class name
       * @param a_args the arguments to pass-thro to the main of the application
       * @throws RepositoryException on any class loading or invocation failures
       */
      public void main( String a_fqcn, String[] a_args )
          throws RepositoryException
      {
          Class l_clazz = null ;
          Method l_main = null ;
          
          try 
          {
              l_clazz = m_loader.loadClass( a_fqcn ) ;
              l_main = l_clazz.getMethod( a_fqcn, new Class[] {String[].class} ) ;
              
              if ( l_main.getReturnType() != Void.TYPE )
              {
                  throw new RepositoryException( "Invalid main() in " + a_fqcn 
                          + " has a non-void return type of " 
                          + l_main.getReturnType() ) ;
              }
              
              l_main.invoke( null, a_args ) ;
          }
          catch ( InvocationTargetException e )
          {
              throw new RepositoryException( "Failed to invoke target main()"
                      + " in class " + a_fqcn ) ;
          }
          catch ( IllegalAccessException e )
          {
              throw new RepositoryException( "Cannot invoke non-public main()"
                      + " in class " + a_fqcn ) ;
          }
          catch ( NoSuchMethodException e )
          {
              throw new RepositoryException( a_fqcn + " Does not contain a main "
                      + "method with a sole String [] argument.", e ) ; 
          }
          catch ( ClassNotFoundException e )
          {
              throw new RepositoryException( "ClassLoader for repository Jar "
                      + "artifact " + m_descriptor + " could not find " 
                      + a_fqcn, e ) ;
          }
      }
      
      
      /**
       * Instantiates a runnable using a default constructor and calls its run
       * method.
       * 
       * @param a_fqcn the fully qualified class name of the Runnable 
       * @throws RepositoryException on any class loading or invokation failures
       */
      public void run( String a_fqcn ) throws RepositoryException
      {
          Class l_clazz = null ;
          Runnable l_runnable = null ;
          
          try
          {
              l_clazz = m_loader.loadClass( a_fqcn ) ;
              l_runnable = ( Runnable ) l_clazz.newInstance() ;
              l_runnable.run() ;
          }
          catch ( ClassCastException e )
          {
              throw new RepositoryException( a_fqcn + " is not a Runnable", e ) ;
          }
          catch ( InstantiationException e )
          {
              throw new RepositoryException( a_fqcn + " in " + m_descriptor
                      + " does not contain a default constructor" ) ;
          }
          catch ( IllegalAccessException e )
          {
              throw new RepositoryException( "Cannot invoke non-public run()"
                      + " in class " + a_fqcn ) ;
          }
          catch ( ClassNotFoundException e )
          {
              throw new RepositoryException( "Could not find " + a_fqcn 
                      + " in repository jar artifact " + m_descriptor 
                      + " or in any one of its dependent Jars", e ) ;
          }
      }
  
  
      /**
       * Invokes a static method on a class.
       * 
       * @param a_fqcn the fully qualified class name
       * @param a_method the name of the method to invoke
       * @param a_types the fqcn of the parameters
       * @param a_args the arguments to the method
       * @return the methods return value if one exists, or null if method is void
       */
      public Object invoke( String a_fqcn, String a_method, String [] a_types, 
                            Object [] a_args )
          throws RepositoryException
      {
          Class l_clazz = loadClass( a_fqcn ) ;
          Class [] l_types = new Class[a_types.length] ;
          
          /** Get all the argument classes */
          for ( int ii = 0; ii < a_types.length; ii++ )
          {
              l_types[ii] = loadClass( a_types[ii] ) ;
          }
          
          Method l_method = null ;
          try
          {
              l_method = l_clazz.getMethod( a_method, l_types ) ;
              return l_method.invoke( null, a_args ) ;
          }
          catch ( InvocationTargetException e )
          {
              throw new RepositoryException( "Failed to invoke static target "
                      + toSignature( a_method, a_types ) + " in class " 
                      + a_fqcn ) ;
          }
          catch ( IllegalAccessException e )
          {
              throw new RepositoryException( "Cannot access static method " 
                      + toSignature( a_method, a_types ) + " in class "
                      + a_fqcn, e ) ;
          }
          catch ( NoSuchMethodException e )
          {
              throw new RepositoryException( "Could not find static method with"
                      + " matching signature " + toSignature( a_method, a_types ) 
                      + " for class " + a_fqcn, e ) ;
          }
      }
      
      
      /**
       * Creates a new instance of a class using the default constructor.
       * 
       * @param a_fqcn the fully qualified name of the class to create an inst of
       * @return the instance created
       * @throws RepositoryException if the instantiation fails
       */
      public Object newInstance( String a_fqcn ) throws RepositoryException
      {
          Class l_clazz = loadClass( a_fqcn ) ;
          
          try
          {
              return l_clazz.newInstance() ;
          }
          catch ( IllegalAccessException e )
          {
              throw new RepositoryException( "A public accessible default "
                      + "constructor dies not exist for " + a_fqcn, e ) ;
          }
          catch ( InstantiationException e )
          {
              throw new RepositoryException( "Failure while creating an"
                      + " instance of " + a_fqcn 
                      + " via the default constructor", e ) ;
          }
      }
      
      
      /**
       * Creates a new instance of a class using a constructor taking arguments.
       * 
       * @param a_fqcn the fully qualified name of the class to create an inst of
       * @param a_types the fully qualified names of constructor parameter types
       * @param a_args the arguments to the constructor
       * @return the newly created instance 
       * @throws RepositoryException if the instantiation fails
       */
      public Object newInstance( String a_fqcn, String[] a_types, Object[] args )
          throws RepositoryException
      {
          Class l_clazz = loadClass( a_fqcn ) ;
          
          for ( int ii = 0; ii < a_types.length; ii++ )
          {
              
          }
          
          throw new UnsupportedOperationException( "STUB" ) ;
      }
      
      
      /**
       * Gets the name of the constructor given the fully qualified class name.
       * 
       * @param a_fqcn the fully qualified class name
       * @return the name of the constructor
       */
      public String getConstructor( String a_fqcn )
      {
          int l_lastDot = a_fqcn.indexOf( '.' ) ;
          
          // Class is in default package so a_fqcn = cn = constructor
          if ( -1 == l_lastDot )
          {
              return a_fqcn ;
          }
          
          return a_fqcn.substring( l_lastDot + 1 ) ;
      }
      
  
      /**
       * Invokes a method on an object.
       * 
       * @param a_obj the object to invoke a method on
       * @param a_method the method to invoke
       * @param a_argTypes the fqcn of the parameters 
       * @param a_args the arguments to method
       * @return a return value if one is returned, otherwise null
       * @throws RepositoryException
       */
      public Object invoke( Object a_obj, String a_method, String [] a_argTypes, 
                            Object[] a_args )
          throws RepositoryException
      {
          Class [] l_argClasses = new Class[a_argTypes.length] ;
          
          /** Get all the argument classes */
          for ( int ii = 0; ii < a_argTypes.length; ii++ )
          {
              l_argClasses[ii] = loadClass( a_argTypes[ii] ) ;
          }
          
          Method l_method = null ;
          try
          {
              l_method = a_obj.getClass().getMethod( a_method, l_argClasses ) ;
              return l_method.invoke( a_obj, a_args ) ;
          }
          catch ( InvocationTargetException e )
          {
              throw new RepositoryException( "Failed to invoke target "
                      + toSignature( a_method, a_argTypes ) + " in class " 
                      + a_obj.getClass() ) ;
          }
          catch ( IllegalAccessException e )
          {
              throw new RepositoryException( "Cannot access method " 
                      + toSignature( a_method, a_argTypes ) + " in class "
                      + a_obj.getClass(), e ) ;
          }
          catch ( NoSuchMethodException e )
          {
              throw new RepositoryException( "Could not find method with matching"
                      + " signature " + toSignature( a_method, a_argTypes ) 
                      + " for object of class " + a_obj.getClass(), e ) ;
          }
      }
      
      
      /**
       * Loads a class using the ClassLoader created by the Repository.
       * 
       * @param a_fqcn the fully qualified class name 
       * @return the Class loaded using the Repository built ClassLoader
       * @throws RepositoryException if the class could not be found
       */
      public Class loadClass( String a_fqcn ) throws RepositoryException
      {
          try
          {
              return m_loader.loadClass( a_fqcn ) ;
          }
          catch ( ClassNotFoundException e )
          {
              throw new RepositoryException( "Could not find " + a_fqcn 
                      + " in repository jar artifact " + m_descriptor 
                      + " or in any one of its dependent Jars", e ) ;
          }
      }
      
      
      /**
       * Constructs a String representing the signature of an method.
       * 
       * @param a_method the name of the method
       * @param a_types the fully qualified class names of the method parameters
       * @return the signature String
       */
      public String toSignature( String a_method, String [] a_types )
      {
          StringBuffer l_buf = new StringBuffer( a_method ) ;
          
          l_buf.append( '(' ) ;
          for ( int ii = 0; ii < a_types.length; ii++ )
          {
              l_buf.append( a_types[ii] ) ;
              
              if ( ii < a_types.length )
              {
                  l_buf.append( ',' ) ;
              }
          }
          l_buf.append( ')' ) ;
          
          return l_buf.toString() ;
      }
  
  
      /**
       * Main wrapper.
       * 
       * @todo add more properties to allow full repo specification via 
       * system properties including a repository implementation replacement.
       * 
       * @param a_args
       */
      public static void main( String [] a_args )
      {
          String l_jarSpec = System.getProperty( "repository.application.jar" ) ;
          String l_fqcn = System.getProperty( "repository.application.class" ) ;
          
          if ( null == l_jarSpec )
          {
              System.err.println( "The repository application jar was not "
                      + "specified so we cannot continue ..." ) ;
              System.exit( -1 ) ;
          }
          
          if ( null == l_fqcn )
          {
              System.err.println( "The main application class was not "
                      + "specified so we cannot continue ..." ) ;
              System.exit( -1 ) ;
          }
          
          Repository l_repository ;
          JarDescriptor l_jar = null ;
          Bootstrapper l_bootstrapper ;
          try
          {
              l_jar = new JarDescriptor( l_jarSpec ) ;
          }
          catch ( ParseException e )
          {
              e.printStackTrace() ;
              System.exit( -1 ) ;
          }
          
          try
          {
              InitialRepositoryFactory l_factory = 
                  new InitialRepositoryFactory() ;
              RepositoryContext l_context = l_factory.getDefaultContext() ;
              l_repository = l_factory.create( l_context ) ;
              l_bootstrapper = new Bootstrapper( l_repository, l_jar ) ;
              l_bootstrapper.main( l_fqcn, a_args ) ;
          }
          catch ( RepositoryException e )
          {
              e.printStackTrace() ;
              System.exit( -1 ) ;
          }
      }
  }
  
  
  

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

Reply via email to