Initial revision

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@162523 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jason van Zyl 2004-01-03 05:33:25 +00:00
parent 4977a94400
commit f646e34f61
7 changed files with 1455 additions and 0 deletions

13
maven-mboot/README.txt Normal file
View File

@ -0,0 +1,13 @@
How to use mboot
----------------
o export MBOOT_HOME=<whatever>
o export PATH=$PATH:$MBOOT_HOME
o ./build
o cd target
o ./mboot-install.sh
o mboot
mboot will build Maven projects that are relatively simple. It will build
a JAR and package any resources into the JAR. Good enough for Maven itself
and the plugins but appears to be useful for other things.

28
maven-mboot/build Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
. src/bash/maven.functions
compile . target/classes src/main
isCommandSuccessful $? "Failed compiling Maven bootstrapper classes!"
DIST=target/mboot
rm -rf $DIST > /dev/null 2>&1
mkdir -p $DIST
cp -r target/classes $DIST
cp src/bash/* $DIST
(
cd target/mboot
tar cvzf ../mboot.tar.gz *
)
cat src/sea/sea-header target/mboot.tar.gz > target/mboot-install.sh
chmod +x target/mboot-install.sh

View File

@ -0,0 +1,271 @@
# -----------------------------------------------------------------------------
# Maven functions
#
# @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
# -----------------------------------------------------------------------------
isCommandSuccessful()
{
# $1 == $?
# $2 == Error message on failure
ret=$1
if [ $ret != 0 ]; then
echo $2
exit $ret
fi
}
runJava()
{
# $1 == classpath
# $2 == Main class
# $3 == Mail args
"${JAVACMD}" -classpath $1 $2 "$3"
}
compile()
{
# $1 == classpath
# $2 == destination for compiled classes
# $3 == source directory
# $4 == any extra sources
if [ -d $3 ]
then
if [ ! -d $2 ]
then
mkdir -p $2
fi
SOURCES=`find $3 -name '*.java'`
"${JAVAC}" -classpath $1 -d $2 ${SOURCES} $4
fi
}
buildJar()
{
# $1 == directory to JAR
# $2 == JAR path relative to the cwd
(
dir=`pwd`
cd $1
${JAVA_HOME}/bin/jar -cf ${dir}/$2 *
)
}
buildMavenProject()
{
# 1. Parse the model
# 2. Download any required dependencies
# 3. Compile the sources
# 4. Move required resources into location
# 5. Create JAR.
# I can use maven-model and I can detach maven-model-tools from
# Plexus so that I can use it for this tool. I can just use the
# command line compiler for now.
# $1 == directory where project lives
# $4 == jar name
# $5 == flag to leave mboot files
(
home=`pwd`
cd $1
# Look for source directory in project.xml
sourceDirectory=`grep sourceDirectory project.xml | sed -e 's/^*//;s/<sourceDirectory>//;s/<\/sourceDirectory>//'`
[ -z $sourceDirectory ] && sourceDirectory=src/main
buildDir=target
buildDest=target/classes
[ -d $buildDir ] && rm -rf $buildDir
echo "Building project in `pwd`"
echo "sourceDirectory = $sourceDirectory"
echo "buildDest = ${buildDest}"
runJava ${MBOOT_HOME}/classes Bootstrapper ${home}
isCommandSuccessful $? "Failed running project parser!"
projectDependencyClassPath=`cat bootstrap.classpath`:.
if [ ! -z $sourceDirectory ] && [ -d $sourceDirectory ]
then
compile $projectDependencyClassPath $buildDest $sourceDirectory
isCommandSuccessful $? "Failed compiling classes!"
fi
copyResources
if [ -z $2 ]
then
jarName=`getJarName project.xml`
else
jarName=$2
fi
buildJar $buildDest target/${jarName}
if [ -z $3 ]
then
rm -f bootstrap.classpath > /dev/null 2>&1
rm -f bootstrap.libs > /dev/null 2>&1
rm -f bootstrap.resources > /dev/null 2>&1
fi
)
}
getJarName()
{
# $1 == project.xml
version=`grep currentVersion $1 | sed -e 's/^ *//;s/<currentVersion>//;s/<\/currentVersion>//'`
artifactId=`grep artifactId $1 | sed -e 's/^ *//;s/<artifactId>//;s/<\/artifactId>//' | awk 'BEGIN { FS = "\n"; RS="" } { print $1 }'`
if [ -z $artifactId ]
then
artifactId=`grep id $1 | sed -e 's/^ *//;s/<id>//;s/<\/id>//' | awk 'BEGIN { FS = "\n"; RS="" } { print $1 }'`
fi
jarName="${artifactId}-${version}.jar"
echo $jarName
}
copyResources()
{
resources=`cat bootstrap.resources`
for i in $resources
do
directory=`echo $i | awk 'BEGIN { FS = "@" } { print $1 }' | awk 'BEGIN { FS = "," } { print $1 }'`
targetPath=`echo $i | awk 'BEGIN { FS = "@" } { print $1 }' | awk 'BEGIN { FS = "," } { print $2 }'`
includes=`echo $i | awk 'BEGIN { FS = "@" } { print $2 }' | awk 'BEGIN { FS = "," } { for ( j = 1; j <= NF; j++ ) { printf( "%s ", $j ) } }'`
for include in $includes
do
files=`eval "find $directory -name $include"`
for file in $files
do
# Replace the "/" with "@" to prevent shell expansion of *.properties
# to *.properties in the CWD.
tmpDirectory=`echo $directory | sed "s/\//@/g"`
tmpFile=`echo $file | sed "s/\//@/g"`
# Now grab the path excluding the original directory so we can translate that
# path into the target directory.
path=`echo $tmpFile | sed "s/$tmpDirectory//;s/\@/\//g;s/^\///"`
translatedPath=`dirname $path`
targetDirectory="target/classes"
if [ ! -z $targetPath ]
then
targetDirectory="${targetDirectory}/${targetPath}"
else
targetDirectory="${targetDirectory}/${translatedPath}"
fi
[ ! -d $targetDirectory ] && mkdir -p $targetDirectory
cp $file $targetDirectory
done
done
done
}
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
case "`uname`" in
CYGWIN*) cygwin=true ;;
Darwin*) darwin=true
if [ -z "$JAVA_HOME" ] ; then
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
fi
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# You will need to specify JAVA_HOME if compiling with 1.2 or later.
if [ -n "$JAVA_HOME" ] ; then
if [ -f "$JAVA_HOME/lib/tools.jar" ] ; then
CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/tools.jar
fi
if [ -f "$JAVA_HOME/lib/classes.zip" ] ; then
CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/classes.zip
fi
else
echo "Warning: JAVA_HOME environment variable not set."
echo " If build fails because sun.* classes could not be found"
echo " you will need to set the JAVA_HOME environment variable"
echo " to the installation directory of java."
fi
# IBM's JDK on AIX uses strange locations for the executables:
# JAVA_HOME/jre/sh for java and rmid
# JAVA_HOME/sh for javac and rmic
if [ -z "$JAVAC" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/sh/javac" ] ; then
JAVAC=${JAVA_HOME}/sh/javac;
else
JAVAC=${JAVA_HOME}/bin/javac;
fi
else
JAVAC=javac
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
else
JAVACMD=java
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly."
echo " We cannot execute $JAVACMD"
exit
fi
# For Cygwin, switch to Windows format before running java
if $cygwin; then
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
fi
export CLASSPATH

50
maven-mboot/src/bash/mboot Executable file
View File

@ -0,0 +1,50 @@
#!/bin/sh
[ -z $MBOOT_HOME ] && echo && echo "You must set MBOOT_HOME to use mboot!" && echo && exit
. ${MBOOT_HOME}/maven.functions
VERSION=1.0
dir="."
jar=""
leaveBootFiles=""
while [ $# -gt 0 ]; do
case $1 in
--version)
echo "mboot: version $VERSION"
exit 0
;;
-v)
verbose=-v
;;
--dir*)
if echo $1 | grep -q '=' ; then
dir=`echo $1 | sed 's/^--dir=//'`
else
dir=$2
shift
fi
;;
--jar*)
if echo $1 | grep -q '=' ; then
jar=`echo $1 | sed 's/^--jar=//'`
else
jar=$2
shift
fi
;;
--leave-boot-files)
leaveBootFiles=1;
;;
esac
shift
done
[ ! -d $dir ] && echo "Specified directory doesn't exist!" && exit
[ ! -f $dir/project.xml ] && echo "No project.xml in specified directory!" && exit
buildMavenProject $dir $jar $leaveBootFiles

View File

@ -0,0 +1,718 @@
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
public class Bootstrapper
{
private BootstrapPomParser bootstrapPomParser;
private List dependencies;
private List resources;
private File mavenRepoLocal;
private boolean useTimestamp = true;
private boolean ignoreErrors = true;
private String baseUrl;
private String proxyHost;
private String proxyPort;
private String proxyUserName;
private String proxyPassword;
public static void main( String[] args )
throws Exception
{
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.execute( args );
}
public void execute( String[] args )
throws Exception
{
String basedir = args[0];
Properties properties = loadProperties( new File( System.getProperty( "user.home" ), "build.properties" ) );
baseUrl = properties.getProperty( "maven.repo.remote" );
if ( baseUrl == null )
{
baseUrl = "http://www.ibiblio.org/maven/";
}
String mavenRepoLocalProperty = properties.getProperty( "maven.repo.local" );
if ( mavenRepoLocalProperty == null )
{
mavenRepoLocalProperty = System.getProperty( "user.home" ) + "/maven/repository";
}
mavenRepoLocal = new File( mavenRepoLocalProperty );
if ( !mavenRepoLocal.exists() )
{
if ( !mavenRepoLocal.mkdirs() )
{
System.err.println( "Cannot create the specified maven.repo.local: " + mavenRepoLocal );
System.exit( 1 );
}
}
if ( !mavenRepoLocal.canWrite() )
{
System.err.println( "Can't write to " + mavenRepoLocal.getAbsolutePath() );
System.exit( 1 );
}
System.out.println( "Using the following for your maven.repo.local: " + mavenRepoLocal );
bootstrapPomParser = new BootstrapPomParser();
bootstrapPomParser.parse( new File( "project.xml" ) );
dependencies = bootstrapPomParser.getDependencies();
List list = new ArrayList();
for ( Iterator i = dependencies.iterator(); i.hasNext(); )
{
Dependency d = (Dependency) i.next();
list.add( getArtifactPath( d, "/" ) );
}
downloadDependencies( list );
StringBuffer classPath = new StringBuffer();
StringBuffer libs = new StringBuffer();
for ( Iterator i = dependencies.iterator(); i.hasNext(); )
{
Dependency d = (Dependency) i.next();
classPath.append( mavenRepoLocal + "/" + getArtifactPath( d, "/" ) + ":" );
libs.append( mavenRepoLocal + "/" + getArtifactPath( d, "/" ) + "\n" );
}
FileWriter writer = new FileWriter( "bootstrap.classpath" );
writer.write( classPath.toString() );
writer.close();
writer = new FileWriter( "bootstrap.libs" );
writer.write( libs.toString() );
writer.close();
resources = bootstrapPomParser.getResources();
StringBuffer res = new StringBuffer();
for ( Iterator i = resources.iterator(); i.hasNext(); )
{
Resource r = (Resource) i.next();
// Not sure why r would be null. Happening in drools-core.
if ( r == null )
{
continue;
}
res.append( r.getDirectory() );
if ( r.getTargetPath() != null )
{
res.append( "," ).append( r.getTargetPath() );
}
res.append( "@" );
int size = r.getIncludes().size();
for ( int j = 0; j < size; j++ )
{
String include = (String) r.getIncludes().get( j );
if ( include.startsWith( "**/" ) )
{
include = include.substring( 3 );
}
res.append("'").append( include ).append("'");
if ( j != size - 1 )
{
res.append( "," );
}
}
res.append( "\n" );
}
writer = new FileWriter( "bootstrap.resources" );
writer.write( res.toString() );
writer.close();
}
private String getArtifactPath( Dependency d, String pathSeparator )
{
return d.getArtifactDirectory() + pathSeparator + "jars" + pathSeparator + d.getArtifact();
}
private void downloadDependencies( List files )
throws Exception
{
for ( Iterator j = files.iterator(); j.hasNext(); )
{
try
{
String file = (String) j.next();
File destinationFile = new File( mavenRepoLocal, file );
// The directory structure for this project may
// not exists so create it if missing.
File directory = destinationFile.getParentFile();
if ( directory.exists() == false )
{
directory.mkdirs();
}
if ( destinationFile.exists() )
{
continue;
}
log( "Downloading dependency: " + baseUrl + file );
int numRetries = 3;
while ( numRetries >= 0 )
{
try
{
HttpUtils.getFile( baseUrl + file,
destinationFile,
ignoreErrors,
useTimestamp,
proxyHost,
proxyPort,
proxyUserName,
proxyPassword );
break;
}
catch ( Exception e )
{
numRetries--;
continue;
}
}
if ( !destinationFile.exists() )
{
throw new Exception( "Failed to download " + baseUrl + file );
}
}
catch ( Exception e )
{
throw new Exception( e );
}
}
}
private void log( String message )
{
System.out.println( message );
}
private Properties loadProperties( File file )
{
try
{
return loadProperties( new FileInputStream( file ) );
}
catch ( Exception e )
{
// ignore
}
return null;
}
private static Properties loadProperties( InputStream is )
{
try
{
Properties properties = new Properties();
if ( is != null )
{
properties.load( is );
}
return properties;
}
catch ( IOException e )
{
// ignore
}
finally
{
try
{
if ( is != null )
{
is.close();
}
}
catch ( IOException e )
{
// ignore
}
}
return null;
}
static class BootstrapPomParser
extends DefaultHandler
{
private List dependencies = new ArrayList();
private List resources = new ArrayList();
private Dependency currentDependency;
private Resource currentResource;
private static SAXParserFactory saxFactory;
private boolean insideDependency = false;
private boolean insideUnitTest = false;
private boolean insideResource = false;
private StringBuffer bodyText = new StringBuffer();
private File file;
public List getDependencies()
{
return dependencies;
}
public List getResources()
{
return resources;
}
public void parse( File file )
{
this.file = file;
try
{
saxFactory = SAXParserFactory.newInstance();
SAXParser parser = saxFactory.newSAXParser();
InputSource is = new InputSource( new FileInputStream( file ) );
parser.parse( is, this );
}
catch ( Exception e )
{
e.printStackTrace();
}
}
public void startElement( String uri, String localName, String rawName, Attributes attributes )
{
if ( insideUnitTest )
{
return;
}
else if( rawName.equals( "unitTest" ) )
{
insideUnitTest = true;
}
else if ( rawName.equals( "dependency" ) )
{
currentDependency = new Dependency();
insideDependency = true;
}
else if ( rawName.equals( "resource" ) )
{
currentResource = new Resource();
insideResource = true;
}
}
public void characters( char buffer[], int start, int length )
{
bodyText.append( buffer, start, length );
}
private String getBodyText()
{
return bodyText.toString().trim();
}
public void endElement( String uri, String localName, String rawName )
{
if ( rawName.equals( "extend" ) )
{
String extend = getBodyText();
File f = new File( file.getParentFile(), extend );
BootstrapPomParser p = new BootstrapPomParser();
p.parse( f );
dependencies.addAll( p.getDependencies() );
resources.addAll( p.getResources() );
}
else if ( rawName.equals( "unitTest" ) )
{
insideUnitTest = false;
}
else if ( rawName.equals( "dependency" ) )
{
dependencies.add( currentDependency );
insideDependency = false;
}
else if ( rawName.equals( "resource" ) )
{
resources.add( currentResource );
insideResource = false;
}
else if ( insideDependency )
{
if ( rawName.equals( "id" ) )
{
currentDependency.setId( getBodyText() );
}
else if ( rawName.equals( "version" ) )
{
currentDependency.setVersion( getBodyText() );
}
else if ( rawName.equals( "jar" ) )
{
currentDependency.setJar( getBodyText() );
}
else if ( rawName.equals( "type" ) )
{
currentDependency.setType( getBodyText() );
}
else if ( rawName.equals( "groupId" ) )
{
currentDependency.setGroupId( getBodyText() );
}
else if ( rawName.equals( "artifactId" ) )
{
currentDependency.setArtifactId( getBodyText() );
}
}
else if ( insideResource )
{
if ( rawName.equals( "directory" ) )
{
currentResource.setDirectory( getBodyText() );
}
else if ( rawName.equals( "targetPath" ) )
{
currentResource.setTargetPath( getBodyText() );
}
else if ( rawName.equals( "include" ) )
{
currentResource.addInclude( getBodyText() );
}
else if ( rawName.equals( "exclude" ) )
{
currentResource.addExclude( getBodyText() );
}
}
bodyText = new StringBuffer();
}
public void warning( SAXParseException spe )
{
printParseError( "Warning", spe );
}
public void error( SAXParseException spe )
{
printParseError( "Error", spe );
}
public void fatalError( SAXParseException spe )
{
printParseError( "Fatal Error", spe );
}
private final void printParseError( String type, SAXParseException spe )
{
System.err.println( type + " [line " + spe.getLineNumber() +
", row " + spe.getColumnNumber() + "]: " +
spe.getMessage() );
}
}
public static class Dependency
{
private String id;
private String version;
private String url;
private String jar;
private String artifactId;
private String groupId;
private String type = "jar";
public Dependency()
{
}
public void setId( String id )
{
this.id = id;
}
public String getId()
{
if ( isValid( getGroupId() )
&& isValid( getArtifactId() ) )
{
// We have something like:
//
// <dependency>
// <groupId>commons-jelly</groupId>
// <artifactId>commons-jelly-tags-velocity</artifactId>
// <version>SNAPSHOT</version>
// </dependency>
return getGroupId() + ":" + getArtifactId();
}
return id;
}
public void setGroupId( String groupId )
{
this.groupId = groupId;
}
public String getGroupId()
{
return groupId;
}
public String getArtifactDirectory()
{
if ( isValid( getGroupId() ) )
{
return getGroupId();
}
return getId();
}
public String getArtifactId()
{
return artifactId;
}
public void setArtifactId( String artifactId )
{
this.artifactId = artifactId;
}
public String getArtifact()
{
// If the jar name has been explicty set then use that. This
// is when the <jar/> element is explicity used in the POM.
if ( jar != null)
{
return jar;
}
if ( isValid( getArtifactId() ) )
{
return getArtifactId() + "-" + getVersion() + "." + getType();
}
else
{
return getId() + "-" + getVersion() + "." + getType();
}
}
public void setVersion( String version )
{
this.version = version;
}
public String getVersion()
{
return version;
}
public void setJar( String jar )
{
// This is a check we need because of the jelly interpolation
// process. If we don't check an empty string will be set and
// screw up getArtifact() above.
if ( jar.trim().length() == 0 )
{
return;
}
this.jar = jar;
}
public String getJar()
{
return jar;
}
public void setUrl( String url )
{
this.url = url;
}
public String getUrl()
{
return url;
}
public String getType()
{
return type;
}
public void setType( String type )
{
this.type = type;
}
private boolean isValid( String value )
{
if ( value != null
&& value.trim().equals("") == false )
{
return true;
}
return false;
}
}
public static class Resource
implements Serializable
{
private String directory;
private String targetPath;
private List includes = new ArrayList();
private List excludes = new ArrayList();
private boolean filtering;
public void addInclude( String pattern )
{
this.includes.add( pattern );
}
public void addExclude( String pattern )
{
this.excludes.add( pattern );
}
public List getIncludes()
{
return this.includes;
}
public List getExcludes()
{
return this.excludes;
}
public void setDirectory( String directory )
{
this.directory = directory;
}
public String getDirectory()
{
return this.directory;
}
public void setTargetPath( String targetPath )
{
this.targetPath = targetPath;
}
public String getTargetPath()
{
return targetPath;
}
public boolean getFiltering()
{
return filtering;
}
public void setFiltering( boolean filtering )
{
this.filtering = filtering;
}
}
}

View File

@ -0,0 +1,336 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
/**
* Http utils for retrieving files.
*
* @author costin@dnt.ro
* @author gg@grtmail.com (Added Java 1.1 style HTTP basic auth)
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
*
* @todo Need to add a timeout so we can flip to a backup repository.
* @todo Download everything in a single session.
* @todo Throw meaningful exception when authentication fails.
*/
public class HttpUtils
{
/**
* Use a proxy to bypass the firewall with or without authentication
*
* @param proxyHost Proxy Host (if proxy is required), or null
* @param proxyPort Proxy Port (if proxy is required), or null
* @param proxyUserName Proxy Username (if authentification is required),
* or null
* @param proxyPassword Proxy Password (if authentification is required),
* or null
*/
public static void useProxyUser( final String proxyHost,
final String proxyPort,
final String proxyUserName,
final String proxyPassword )
{
if ( proxyHost != null && proxyPort != null )
{
System.getProperties().put( "proxySet", "true" );
System.getProperties().put( "proxyHost", proxyHost );
System.getProperties().put( "proxyPort", proxyPort );
if ( proxyUserName != null )
{
Authenticator.setDefault( new Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication( proxyUserName,
proxyPassword == null ? new char[0] : proxyPassword.toCharArray() );
}
} );
}
}
}
/**
* 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).
*
* @param url the of the file to retrieve
* @param destinationFile where to store it
* @param ignoreErrors whether to ignore errors during I/O or throw an
* exception when they happen
* @param useTimestamp whether to check the modified timestamp on the
* <code>destinationFile</code> against the remote <code>source</code>
* @param proxyHost Proxy Host (if proxy is required), or null
* @param proxyPort Proxy Port (if proxy is required), or null
* @param proxyUserName Proxy Username (if authentification is required),
* or null.
* @param proxyPassword Proxy Password (if authentification is required),
* or null.
* @param useChecksum Flag to indicate the use of the checksum for the retrieved
* artifact if it is available.
*/
public static void getFile( String url,
File destinationFile,
boolean ignoreErrors,
boolean useTimestamp,
String proxyHost,
String proxyPort,
String proxyUserName,
String proxyPassword,
boolean useChecksum )
throws Exception
{
// Get the requested file.
getFile( url,
destinationFile,
ignoreErrors,
useTimestamp,
proxyHost,
proxyPort,
proxyUserName,
proxyPassword );
// Get the checksum if requested.
if ( useChecksum )
{
File checksumFile = new File( destinationFile + ".md5" );
try
{
getFile( url + ".md5",
checksumFile,
ignoreErrors,
useTimestamp,
proxyHost,
proxyPort,
proxyUserName,
proxyPassword );
}
catch ( Exception e )
{
// do nothing we will check later in the process
// for the checksums.
}
}
}
/**
* 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).
*
* @param url the of the file to retrieve
* @param destinationFile where to store it
* @param ignoreErrors whether to ignore errors during I/O or throw an
* exception when they happen
* @param useTimestamp whether to check the modified timestamp on the
* <code>destinationFile</code> against the remote <code>source</code>
* @param proxyHost Proxy Host (if proxy is required), or null
* @param proxyPort Proxy Port (if proxy is required), or null
* @param proxyUserName Proxy Username (if authentification is required),
* or null
* @param proxyPassword Proxy Password (if authentification is required),
* or null
*/
public static void getFile( String url,
File destinationFile,
boolean ignoreErrors,
boolean useTimestamp,
String proxyHost,
String proxyPort,
String proxyUserName,
String proxyPassword )
throws Exception
{
String[] s = parseUrl( url );
String username = s[0];
String password = s[1];
String parsedUrl = s[2];
URL source = new URL( parsedUrl );
//set the timestamp to the file date.
long timestamp = 0;
boolean hasTimestamp = false;
if ( useTimestamp && destinationFile.exists() )
{
timestamp = destinationFile.lastModified();
hasTimestamp = true;
}
//set proxy connection
useProxyUser( proxyHost, proxyPort, proxyUserName, proxyPassword );
//set up the URL connection
URLConnection connection = source.openConnection();
//modify the headers
//NB: things like user authentication could go in here too.
if ( useTimestamp && hasTimestamp )
{
connection.setIfModifiedSince( timestamp );
}
// prepare Java 1.1 style credentials
if ( username != null || password != null )
{
String up = username + ":" + password;
String encoding = null;
// check to see if sun's Base64 encoder is available.
try
{
sun.misc.BASE64Encoder encoder =
(sun.misc.BASE64Encoder) Class.forName(
"sun.misc.BASE64Encoder" ).newInstance();
encoding = encoder.encode( up.getBytes() );
}
catch ( Exception ex )
{
// Do nothing, as for MavenSession we will never use
// auth and we will eventually move over httpclient
// in the commons.
}
connection.setRequestProperty( "Authorization", "Basic " + encoding );
}
//connect to the remote site (may take some time)
connection.connect();
//next test for a 304 result (HTTP only)
if ( connection instanceof HttpURLConnection )
{
HttpURLConnection httpConnection = (HttpURLConnection) connection;
if ( httpConnection.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED )
{
return;
}
// test for 401 result (HTTP only)
if ( 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 is = null;
for ( int i = 0; i < 3; i++ )
{
try
{
is = connection.getInputStream();
break;
}
catch ( IOException ex )
{
// do nothing
}
}
if ( is == null )
{
if ( ignoreErrors )
{
return;
}
// This will never happen with maven's use of this class.
throw new Exception( "Can't get " + destinationFile.getName() + " to " + destinationFile );
}
FileOutputStream fos = new FileOutputStream( destinationFile );
byte[] buffer = new byte[100 * 1024];
int length;
while ( ( length = is.read( buffer ) ) >= 0 )
{
fos.write( buffer, 0, length );
System.out.print( "." );
}
System.out.println();
fos.close();
is.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 ( useTimestamp )
{
long remoteTimestamp = connection.getLastModified();
if ( remoteTimestamp != 0 )
{
touchFile( destinationFile, remoteTimestamp );
}
}
}
/**
* Parse an url which might contain a username and password. If the
* given url doesn't contain a username and password then return the
* origin url unchanged.
*
* @param url The url to parse.
* @return The username, password and url.
*/
static String[] parseUrl( String url )
{
String[] parsedUrl = new String[3];
parsedUrl[0] = null;
parsedUrl[1] = null;
parsedUrl[2] = url;
// 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 i = url.indexOf( "@" );
if ( i > 0 )
{
String s = url.substring( 7, i );
int j = s.indexOf( ":" );
parsedUrl[0] = s.substring( 0, j );
parsedUrl[1] = s.substring( j + 1 );
parsedUrl[2] = "http://" + url.substring( i + 1 );
}
return parsedUrl;
}
/**
* set the timestamp of a named file to a specified time.
*
* @param file the file to touch
* @param timemillis in milliseconds since the start of the era
* @return true if it succeeded. False means that this is a java1.1 system
* and that file times can not be set
* @exception Exception Thrown in unrecoverable error. Likely this
* comes from file access failures.
*/
private static boolean touchFile( File file, long timemillis )
throws Exception
{
long modifiedTime;
if ( timemillis < 0 )
{
modifiedTime = System.currentTimeMillis();
}
else
{
modifiedTime = timemillis;
}
file.setLastModified( modifiedTime );
return true;
}
}

View File

@ -0,0 +1,39 @@
#!/bin/sh
echo ""
echo Maven MBoot
echo ""
echo
echo "Where would you like to install mboot? [ ~/mboot ] "
echo
read $DIR
[ -z $DIR ] && DIR=~/mboot
echo "Installing mboot in $DIR ..."
export DIR
[ -d $DIR ] && rm -rf $DIR
mkdir $DIR
SKIP=`awk '/^__ARCHIVE_FOLLOWS__/ { print NR + 1; exit 0; }' $0`
# Take the TGZ portion of this file and pipe it to tar.
tail +$SKIP $0 | tar xz -C $DIR
# execute the installation script
#PREV=`pwd`
#cd $WORK_DIR
#./install.sh
# delete the temp files
#cd $PREV
#rm -rf $WORK_DIR
exit 0
__ARCHIVE_FOLLOWS__