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 [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.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:[EMAIL PROTECTED]">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 [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.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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]
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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]