avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject cvs commit: avalon-sandbox/repository/api/src/java/org/apache/avalon/repository RepositoryUtils.java InitialRepositoryFactory.java JarBuildDescriptor.java ArtifactDescriptor.java
Date Sun, 09 Nov 2003 09:13:58 GMT
akarasulu    2003/11/09 01:13:58

  Modified:    repository/api/src/java/org/apache/avalon/repository
                        JarBuildDescriptor.java ArtifactDescriptor.java
  Added:       repository/api/src/java/org/apache/avalon/repository
                        RepositoryUtils.java InitialRepositoryFactory.java
  Log:
  Checkpointing
  
  Revision  Changes    Path
  1.2       +13 -10    avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/JarBuildDescriptor.java
  
  Index: JarBuildDescriptor.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/JarBuildDescriptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- JarBuildDescriptor.java	7 Nov 2003 12:50:54 -0000	1.1
  +++ JarBuildDescriptor.java	9 Nov 2003 09:13:58 -0000	1.2
  @@ -66,8 +66,8 @@
   {
       /** name of the file with the jar's build description */
       public static final String JAR_PROPS = "jar.properties" ;
  -    /** the key used to get the defualt repository url */
  -    public static final String REPO_KEY = "build.repo" ;
  +    /** the key used to get the defualt comma delimited repository urls */
  +    public static final String REPOS_KEY = "build.repos" ;
       /** the key used to get the artifact group */
       public static final String GROUP_KEY = "build.group" ;
       /** the key used to get the artifact name or id within the group */
  @@ -77,8 +77,8 @@
       
       /** the jar artifact descriptor */
       private final JarDescriptor m_jarDescriptor ;
  -    /** default repo that will contain this jar and project descriptors */
  -    private final String m_repo ;
  +    /** default repos that will contain this jar and project descriptors */
  +    private final String[] m_repos ;
   
       
       /**
  @@ -91,7 +91,10 @@
                                   Properties a_props )
       {
           m_jarDescriptor = a_jarDescriptor ;
  -        m_repo = a_props.getProperty( REPO_KEY ) ;
  +        
  +        // gets the comma separated repository list
  +        m_repos = RepositoryUtils.getDelimited( ',', a_props
  +                .getProperty( REPOS_KEY ) ) ;
       }
       
       
  @@ -141,12 +144,12 @@
   
       
       /**
  -     * Gets the default or bootstrap repository guaranteed to contain the jar.
  +     * Gets the default or bootstrap repositories guaranteed to contain the jar.
        * 
  -     * @return the repo url as a string
  +     * @return the repo urls as strings
        */
  -    public String getDefaultRepository()
  +    public String[] getDefaultRepositories()
       {
  -        return m_repo ;
  +        return m_repos ;
       }
   }
  
  
  
  1.2       +21 -1     avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/ArtifactDescriptor.java
  
  Index: ArtifactDescriptor.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/ArtifactDescriptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ArtifactDescriptor.java	7 Nov 2003 12:50:54 -0000	1.1
  +++ ArtifactDescriptor.java	9 Nov 2003 09:13:58 -0000	1.2
  @@ -209,6 +209,26 @@
           m_isDirty = true ;
           m_name = a_name ;
       }
  +    
  +    
  +    /**
  +     * Gets the file name of the artifact on the repository relative to 
  +     * the repository root. 
  +     *
  +     * @return the repository root relative file name of the artifact w/o 
  +     * a '/' at the front.
  +     */
  +    public String getRootRelativePath()
  +    {
  +        StringBuffer l_buf = new StringBuffer( m_group ) ;
  +        l_buf.append( '/' ) ;
  +        l_buf.append( m_name ) ;
  +        l_buf.append( '-' ) ;
  +        l_buf.append( m_version ) ;
  +        l_buf.append( '.' ) ;
  +        l_buf.append( m_type ) ;
  +        return l_buf.toString() ;
  +    }
   
       
       /**
  
  
  
  1.1                  avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/RepositoryUtils.java
  
  Index: RepositoryUtils.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 apache@apache.org.
  
   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.net.URL ;
  
  import java.io.IOException ;
  import java.io.InputStream ;
  
  import java.util.ArrayList;
  import java.util.Properties ;
  import java.util.Enumeration ;
  
  import javax.naming.directory.Attribute;
  import javax.naming.directory.Attributes ;
  import javax.naming.directory.BasicAttribute;
  import javax.naming.directory.BasicAttributes ;
  
  
  /**
   * Various static utility methods used throughout repository related programing 
   * interfaces.
   * 
   * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
   * @author $Author: akarasulu $
   * @version $Revision: 1.1 $
   */
  public class RepositoryUtils
  {
      /**
       * Transforms a Properties into a Attributes using a simple enumeration 
       * convention for property names which appends a numeric enumeration name
       * component to the dotted property key.  Note that changes to the 
       * Attributes object do not have any effect on the Properties object and 
       * vice versa.  All values are copied.
       * 
       * @param a_props the properties to be transformed
       * @return the Attributes representing the properties
       */
      public static Attributes getAsAttributes( Properties a_props )
      {
          Attributes l_attrs = new BasicAttributes( false ) ;
          Enumeration l_list = a_props.propertyNames() ;
          
          while ( l_list.hasMoreElements() )
          {
              String l_key = ( String ) l_list.nextElement() ;
              
              if ( isEnumerated( l_key ) )
              {
                  String l_keyBase = getEnumeratedBase( l_key ) ;
                  Attribute l_attr = l_attrs.get( l_keyBase ) ;
                  
                  if ( null == l_attr )
                  {
                      l_attr = new BasicAttribute( l_keyBase, false ) ;
                  }
                  
                  l_attr.add( a_props.getProperty( l_key ) ) ;
                  l_attrs.put( l_attr ) ;
              }
              else 
              {
                  l_attrs.put( l_key, a_props.getProperty( l_key ) ) ;
              }
          }
          
          return l_attrs ;
      }
      
      
      /**
       * Gets the Properties in a remote properties file.
       * 
       * @param a_url the url to the properties file
       * @return the loaded properties for the file
       * @throws IOException if there is any problem loading the properties
       */
      public static Properties getProperties( URL a_url ) throws IOException
      {
          InputStream l_in = null ;
          Properties l_props = new Properties() ;
          l_in = a_url.openStream() ;
          l_props.load( l_in ) ;
          
          if ( l_in != null )
          {    
              l_in.close() ;
          }
          
          return l_props ;
      }
      
  
      /**
       * Detects whether or not a property key is of the multivalued enumeration 
       * kind.  A multivalued key simply enumerates values by appending a '.' and
       * a number after the dot: i.e. artifact.dependency.2 and artifact.alias.23
       * et. cetera.
       * 
       * @param a_key the property name or key
       * @return true if the property conforms to the enumerated property 
       * convention, false otherwise
       */
      public static boolean isEnumerated( String a_key )
      {
          int l_lastDot = a_key.lastIndexOf( '.' ) ;
          String l_lastComponent = null ;
          
          if ( -1 == l_lastDot )
          {
              return false ;
          }
      
          l_lastComponent = a_key.substring( l_lastDot + 1 ) ;
          
          // names like .123 are not really considered enumerated without a base
          if ( a_key.equals( a_key.substring( l_lastDot ) ) )
          {
              return false ;
          }
          
          try 
          {
              Integer.parseInt( l_lastComponent ) ;
          }
          catch ( NumberFormatException e )
          {
              return false ;
          }
          
          return true ;
      }
  
      
      /**
       * Gets the key base of an enumerated property using the multivalued 
       * property key naming convention.
       * 
       * @param a_key the enumerated key whose last name component is a number
       * @return the base name of the enumerated property
       */
      public static String getEnumeratedBase( String a_key )
      {
          if ( null == a_key )
          {
              return null ;
          }
          
          if ( ! isEnumerated( a_key ) )
          {
              return a_key ;
          }
          
          int l_lastDot = a_key.lastIndexOf( '.' ) ;
          String l_base = null ;
          
          if ( -1 == l_lastDot )
          {
              return a_key ;
          }
      
          return a_key.substring( 0, l_lastDot ) ;
      }
  
      
      /**
       * 
       * @param a_delimiter
       * @param a_substrate
       * @return
       */
      public static String [] getDelimited( char a_delim, String a_substrate )
      {
          int l_start = 0, l_end = 0 ;
          ArrayList l_list = new ArrayList() ;
          
          if ( null == a_substrate || a_substrate.equals( "" ) )
          {
              return null ;
          }
  
          while( l_end < a_substrate.length() )
          {    
              l_end = a_substrate.indexOf( ',', l_start ) ;
              
              if ( -1 == l_end )
              {
                  l_end = a_substrate.length() ;
                  l_list.add( a_substrate.substring( l_start, l_end ) ) ;
                  break ;
              }
  
              l_list.add( a_substrate.substring( l_start, l_end ) ) ;
              l_start = l_end + 1 ;
          } 
          
          return ( String [] ) l_list.toArray( new String[0] ) ; 
      }
  }
  
  
  
  1.1                  avalon-sandbox/repository/api/src/java/org/apache/avalon/repository/InitialRepositoryFactory.java
  
  Index: InitialRepositoryFactory.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 apache@apache.org.
  
   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.io.File ;
  import java.io.IOException ;
  import java.io.InputStream ;
  import java.io.FileOutputStream ;
  
  import java.util.ArrayList ;
  import java.util.Properties ;
  import java.text.ParseException ;
  
  import java.net.URL ;
  import java.net.URLConnection ;
  import java.net.URLClassLoader ;
  import java.net.HttpURLConnection ;
  import java.net.MalformedURLException ;
  
  import javax.naming.NamingException ;
  import javax.naming.NamingEnumeration ;
  import javax.naming.directory.Attributes ;
  
  
  /**
   * Sets up the environment to create repositories by downloading the required 
   * jars, preparing a ClassLoader and delegating calls to repository factory 
   * methods using the newly configured ClassLoader.
   * 
   * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
   * @author $Author: akarasulu $
   * @version $Revision: 1.1 $
   */
  public class InitialRepositoryFactory implements RepositoryFactory
  {
      public static final String DEFAULT_FACTORY = 
          "org.apache.avalon.repository.DefaultRepositoryFactory" ;
      private static JarBuildDescriptor s_apiBuild ; 
      private static ArtifactDescriptor s_defaultImplementation ;
  
      static
      {
          /*
           * Creates the descriptor for the jar holding this class.
           */
          try
          {
              s_apiBuild = JarBuildDescriptor.getJarBuildDescriptor( 
                      InitialRepositoryFactory.class.getClassLoader() ) ;
          }
          catch ( RepositoryException e )
          {
              e.printStackTrace( System.err ) ;
          }
          
          /*
           * Use the version of the API for the default implementation artifact
           * version.  They should both be at the same version numbers always.
           */
          s_defaultImplementation = new ArtifactDescriptor(
              s_apiBuild.getJarDescriptor().getGroup(), 
              "avalon-repository-impl", "jar",
              s_apiBuild.getJarDescriptor().getVersion() ) ;
      }
      
      
      // ------------------------------------------------------------------------
      
      /** base property key for the urls of the required jars */
      public static final String URLS_BASE = "url" ;
      /** factory delegate implementation class name key */
      public static final String FACTORY_KEY = "factory" ;
      /** the properties file containing seed information */
      public static final String PROPS = "repository.properties" ;
  
      /** repository loader's bootstrap properties */
      private static Properties s_props = null ;
      
      /** the delegate repository factory instantiated */
      private RepositoryFactory m_delegate = null ;
  
      
      // ------------------------------------------------------------------------
      // C O N S T R U C T O R S
      // ------------------------------------------------------------------------
      
      
      /**
       * Creates a repository which in turn instantiates the default Repository 
       * factory implementation and delegates calls to it.
       * 
       * @throws RepositoryException
       */
      public InitialRepositoryFactory() 
          throws RepositoryException
      {
          this( DEFAULT_FACTORY, s_defaultImplementation ) ;
      }
      
      
      /**
       * Creates a repository which in turn instantiates a Repository 
       * factory implementation specified by an artifact descriptor and the 
       * implementation factory's class name.  This factory delegates 
       * calls to the implementation factory once it is created.
       * 
       * @throws RepositoryException
       */
      public InitialRepositoryFactory( String a_factory, 
                                       ArtifactDescriptor a_implementation ) 
          throws RepositoryException
      {
          /* 
           * Create the temporary directory to pull down files into
           */
          String l_userHome = System.getProperty( "user.home" ) ;
          File l_tmpDir = new File( l_userHome, ".bootstrap" ) ;
          if ( ! l_tmpDir.exists() )
          {
              l_tmpDir.mkdirs() ;
          }
          
          /*
           * Build the url to access the properties of the implementation artifact
           * which is default mechanism dependent.
           */
          StringBuffer l_buf = new StringBuffer( s_apiBuild
              .getDefaultRepositories()[0] ) ;
          
          if ( '/' == l_buf.charAt( l_buf.length() - 1 ) )
          {
              l_buf.append( '/' ) ;
          }
          
          l_buf.append( a_implementation.getGroup() ).append( '/' ) ;
          l_buf.append( "propertiess/" ) ;
          l_buf.append( a_implementation.getName() ).append( '-' ) ;
          l_buf.append( a_implementation.getVersion() ) ;
          l_buf.append( ".jar.properties" ) ;
          
          /*
           * Access the attributes associated with the implementation artifact
           * because we need to get the implementation dependencies and download
           * them.
           */
          Attributes l_attrs = null ;
          try 
          {
              URL l_url = new URL( l_buf.toString() ) ;
              Properties l_props = RepositoryUtils.getProperties( l_url ) ;
              l_attrs = RepositoryUtils.getAsAttributes( l_props ) ;
          }
          catch ( MalformedURLException e )
          {
              throw new RepositoryException( "Incorrect repository url: " 
                  + l_buf.toString(), e ) ;
          }
          catch ( IOException e )
          {
              throw new RepositoryException( "Failed to read attributes in "
                  + l_buf.toString() + " for artifact " 
                  + a_implementation.getSpecification(), e ) ;
          }
          
          /*
           * Download every dependency referenced by the implementation into the
           * temporary cache to build the repository classloader with.
           */
          ArrayList l_urlList = new ArrayList() ;
          try
          {
              NamingEnumeration l_list = l_attrs.get( "dependency" ).getAll() ;
              while ( l_list.hasMore() )
              {
                  String l_spec = ( String ) l_list.next() ;
                  JarDescriptor l_dep = new JarDescriptor( l_spec ) ;
                  URL l_url = new URL( l_dep.getUrl( s_apiBuild
                          .getDefaultRepositories()[0] ) ) ;
                  StringBuffer l_target = new StringBuffer( l_tmpDir
                          .toString() ) ;
                  
                  if ( '/' != l_target.charAt( l_target.length() - 1 ) )
                  {
                      l_target.append( '/' ) ;
                  }
                  
                  l_target.append( l_dep.getRootRelativePath() ) ;
                  File l_targetFile = new File( l_target.toString() ) ;
                  getTempFile( l_url.toExternalForm(), l_targetFile, true ) ;
                  l_urlList.add( l_targetFile.toURL() ) ;
              }
          }
          catch ( ParseException e )
          {
              throw new RepositoryException( "Failed to parse the spec", e ) ;
          }
          catch ( NamingException e )
          {
              throw new RepositoryException( "Error creating attributes", e ) ;
          }
          catch ( MalformedURLException e )
          {
              throw new RepositoryException( "Bad url", e ) ;
          }
          catch ( Exception e )
          {
              throw new RepositoryException( "Download failure", e ) ;
          }
          
          /*
           * Create the factory class loaders and instantiate the delegate factory
           */
          ClassLoader l_loader = new URLClassLoader( ( URL [] ) 
                  l_urlList.toArray( new URL [0] ), 
                  Thread.currentThread().getContextClassLoader() ) ;
          try
          {
              Class l_clazz = l_loader.loadClass( a_factory ) ;
              m_delegate = ( RepositoryFactory ) l_clazz.newInstance() ;
          }
          catch( IllegalAccessException e )
          {
              throw new RepositoryException( "Could not default constructor on: " 
                  + a_factory, e ) ;
          }
          catch( InstantiationException e )
          {
              throw new RepositoryException( 
                  "Could not instantiate the factory class: " + a_factory, e ) ;
          }
          catch( ClassNotFoundException e )
          {
              throw new RepositoryException( "Could not find the factory class: " 
                  + a_factory, e ) ;
          }
      }
  
  
      // ------------------------------------------------------------------------
      // RepositoryFactory Implementations
      // ------------------------------------------------------------------------
  
      
      /**
       * Factory method that creates a repository by calling the delegate factory.
       * 
       * @param context a repository creation context
       * @return the newly created repository
       * @throws RepositoryException if there is a failure while creating the repo
       * @see org.apache.avalon.repository.RepositoryFactory
       * create(org.apache.avalon.repository.RepositoryContext)
       */
      public Repository create( RepositoryContext context ) 
          throws RepositoryException 
      {
          return m_delegate.create( context ) ;
      }
  
      
      /**
       * Factory method that creates a default repository configuration bean 
       * by calling the delegate factory.
       * 
       * @see org.apache.avalon.repository.RepositoryFactory#getDefaultContext()
       */
      public RepositoryContext getDefaultContext() throws RepositoryException
      {
          return m_delegate.getDefaultContext() ;
      }
      
      
      // ------------------------------------------------------------------------
      // Utility Methods
      // ------------------------------------------------------------------------
  
      
      /**
       * Attempts to download and cache a remote artifact trying a set of remote
       * repositories.  The operation is not fail fast and so it keeps trying if
       * the first repository does not have the artifact in question.
       * 
       * @param a_artifact the artifact to retrieve and cache
       * @param a_destFile where to store it locally in the cache
       * @param a_useTimestamp whether to check the modified timestamp on the
       *      <code>destinationFile</code> against the remote <code>source</code>
       * @return TRUE if the file was updated else FALSE
       */
      public static boolean cacheArtifact( ArtifactDescriptor a_artifact, 
          File a_destFile, boolean a_useTimestamp ) 
          throws RepositoryException
      {
          String [] l_srcs = s_apiBuild.getDefaultRepositories() ;
          return cacheArtifact( a_artifact, l_srcs, a_destFile, a_useTimestamp ) ;
      }
      
      
      /**
       * Attempts to download and cache a remote artifact trying a set of remote
       * repositories.  The operation is not fail fast and so it keeps trying if
       * the first repository does not have the artifact in question.
       * 
       * @param a_artifact the artifact to retrieve and cache
       * @param a_repos the remote repositories to try to download from 
       * @param a_destFile where to store it locally in the cache
       * @param a_useTimestamp whether to check the modified timestamp on the
       *      <code>destinationFile</code> against the remote <code>source</code>
       * @return TRUE if the file was updated else FALSE
       */
      public static boolean cacheArtifact( ArtifactDescriptor a_artifact, 
          String [] a_repos, File a_destFile, boolean a_useTimestamp ) 
          throws RepositoryException
      {
          boolean l_updated = false ;
          Exception l_cause = null ;
          
          /*
           * Don't fail fast - keep trying until we get something.
           */
          for ( int ii = 0; ii < a_repos.length; ii++ )
          {
              try 
              {
                  String l_url = a_artifact.getUrl( a_repos[ii] ) ;
                  l_updated = getTempFile( l_url, a_destFile, a_useTimestamp ) ;
                  return l_updated ;
              }
              catch ( Exception e )
              {
                  l_cause = e ;
              }
          }
          
          if ( null == l_cause )
          {
              throw new RepositoryException( "Failed to download artifact to "
                  + "local cache file " + a_destFile.getAbsolutePath() ) ;
          }
  
          // Should not really execute but it shuts up the compiler
          throw new RepositoryException( "Failed to download artifact to "
              + "local cache file " + a_destFile.getAbsolutePath(), l_cause ) ;
      }
  
  
      /**
       * Retrieve a remote file.  Returns true if the file was successfully
       * retrieved or if it is up to date (when the useTimestamp flag is set).
       * 
       * Moved here from HttpController.
       *
       * @param a_url the of the file to retrieve
       * @param a_destFile where to store it
       * @param a_useTimestamp whether to check the modified timestamp on the
       *      <code>destinationFile</code> against the remote <code>source</code>
       * @return TRUE if the file was updated else FALSE
       */
      public static boolean getTempFile( String a_url, File a_destFile,
          boolean a_useTimestamp ) throws Exception
      {
          URL l_source = null ; 
          String l_username = null ;
          String l_password = null ;
  
          // We want to be able to deal with Basic Auth where the username
          // and password are part of the URL. An example of the URL string
          // we would like to be able to parse is like the following:
          //
          // http://username:password@repository.mycompany.com
  
          int l_atIdx = a_url.indexOf( "@" ) ;
          if ( l_atIdx > 0 )
          {
              String s = a_url.substring( 7, l_atIdx ) ;
              int l_colonIdx = s.indexOf( ":" ) ;
              l_username = s.substring( 0, l_colonIdx ) ;
              l_password = s.substring( l_colonIdx + 1 ) ;
              l_source = new URL( "http://" + a_url.substring( l_atIdx + 1 ) ) ;
          }
          else
          {
              l_source = new URL( a_url ) ;
          }
  
          //set the timestamp to the file date.
          long l_timestamp = 0 ;
          boolean l_hasTimestamp = false ;
          if ( a_useTimestamp && a_destFile.exists() )
          {
              l_timestamp = a_destFile.lastModified() ;
              l_hasTimestamp = true ;
          }
  
          //set up the URL connection
          URLConnection l_connection = l_source.openConnection() ;
  
          //modify the headers
          //NB: things like user authentication could go in here too.
          if ( a_useTimestamp && l_hasTimestamp )
          {
              l_connection.setIfModifiedSince( l_timestamp ) ;
          }
  
          //connect to the remote site (may take some time)
          l_connection.connect() ;
          //next test for a 304 result (HTTP only)
          if ( l_connection instanceof HttpURLConnection )
          {
              HttpURLConnection l_httpConnection = 
                  ( HttpURLConnection ) l_connection ;
              
              if ( l_httpConnection.getResponseCode() == 
                      HttpURLConnection.HTTP_NOT_MODIFIED )
              {
                  return false ;
              }
              
              // test for 401 result (HTTP only)
              if ( l_httpConnection.getResponseCode() == 
                      HttpURLConnection.HTTP_UNAUTHORIZED )
              {
                  throw new Exception( "Not authorized." ) ;
              }
          }
  
          // REVISIT: at this point even non HTTP connections may support the
          // if-modified-since behaviour - we just check the date of the
          // content and skip the write if it is not newer.
          // Some protocols (FTP) dont include dates, of course.
  
          InputStream l_in = null ;
          for ( int ii = 0; ii < 3; ii++ )
          {
              try
              {
                  l_in = l_connection.getInputStream() ;
                  break ;
              }
              catch ( IOException ex )
              {
                  // do nothing
              }
          }
          if ( l_in == null )
          {
              final String error = 
                "Connection returned a null input stream: " + a_url ;
              throw new IOException( error ) ;
          }
  
          File parent = a_destFile.getParentFile() ;
          parent.mkdirs() ;
  
          FileOutputStream l_out = new FileOutputStream( a_destFile ) ;
  
          byte[] buffer = new byte[100 * 1024] ;
          int length ;
  
          System.out.print( "Source: " + l_source + "\n") ;
          while ( ( length = l_in.read( buffer ) ) >= 0 )
          {
              l_out.write( buffer, 0, length ) ;
              System.out.print( "." ) ;
          }
  
          System.out.println( "" ) ;
          l_out.close() ;
          l_in.close() ;
  
          // if (and only if) the use file time option is set, then the
          // saved file now has its timestamp set to that of the downloaded
          // file
  
          if ( a_useTimestamp )
          {
              long l_remoteTimestamp = l_connection.getLastModified() ;
  
              if ( l_remoteTimestamp != 0 )
              {
                  long l_modifiedTime ;
  
                  if ( l_remoteTimestamp  < 0 )
                  {
                      l_modifiedTime = System.currentTimeMillis() ;
                  }
                  else
                  {
                      l_modifiedTime = l_remoteTimestamp  ;
                  }
  
                  a_destFile.setLastModified( l_modifiedTime ) ;
                  return true ;
              }
          }
          
          return true ;
      }
  }
  
  
  

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


Mime
View raw message