git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271882 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,266 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
import java.net.URL; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.taskdefs.ExecuteJava; | |||
import org.apache.tools.ant.types.Argument; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.CommandlineJava; | |||
import org.apache.tools.todo.types.Path; | |||
/** | |||
* ANTLR task. | |||
* | |||
* @author <a href="mailto:emeade@geekfarm.org">Erik Meade</a> | |||
* @author <a href="mailto:sbailliez@apache.org>Stephane Bailliez</a> | |||
*/ | |||
public class ANTLR extends AbstractTask | |||
{ | |||
private CommandlineJava commandline = new CommandlineJava(); | |||
/** | |||
* should fork ? | |||
*/ | |||
private boolean fork = false; | |||
/** | |||
* working directory | |||
*/ | |||
private File workingdir = null; | |||
/** | |||
* where to output the result | |||
*/ | |||
private File outputDirectory; | |||
/** | |||
* the file to process | |||
*/ | |||
private File target; | |||
public ANTLR() | |||
{ | |||
commandline.setVm( "java" ); | |||
commandline.setClassname( "antlr.Tool" ); | |||
} | |||
/** | |||
* The working directory of the process | |||
* | |||
* @param d The new Dir value | |||
*/ | |||
public void setDir( File d ) | |||
{ | |||
this.workingdir = d; | |||
} | |||
public void setFork( boolean s ) | |||
{ | |||
this.fork = s; | |||
} | |||
public void setOutputdirectory( File outputDirectory ) | |||
{ | |||
getContext().debug( "Setting output directory to: " + outputDirectory.toString() ); | |||
this.outputDirectory = outputDirectory; | |||
} | |||
public void setTarget( File target ) | |||
{ | |||
getContext().debug( "Setting target to: " + target.toString() ); | |||
this.target = target; | |||
} | |||
/** | |||
* <code><classpath></code> allows classpath to be set because a | |||
* directory might be given for Antlr debug... | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public Path createClasspath() | |||
{ | |||
Path path1 = commandline.createClasspath(); | |||
final Path path = new Path(); | |||
path1.addPath( path ); | |||
return path; | |||
} | |||
/** | |||
* Create a new JVM argument. Ignored if no JVM is forked. | |||
* | |||
* @return create a new JVM argument so that any argument can be passed to | |||
* the JVM. | |||
* @see #setFork(boolean) | |||
*/ | |||
public void addJvmarg( final Argument argument ) | |||
{ | |||
commandline.addVmArgument( argument ); | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
//Adds the jars or directories containing Antlr this should make the forked | |||
//JVM work without having to specify it directly. | |||
addClasspathEntry( "/antlr/Tool.class" ); | |||
validateAttributes(); | |||
//TODO: use ANTLR to parse the grammer file to do this. | |||
if( target.lastModified() > getGeneratedFile().lastModified() ) | |||
{ | |||
commandline.addArgument( "-o" ); | |||
commandline.addArgument( outputDirectory.toString() ); | |||
commandline.addArgument( target.toString() ); | |||
if( fork ) | |||
{ | |||
getContext().debug( "Forking " + commandline.toString() ); | |||
int err = run( commandline ); | |||
if( err == 1 ) | |||
{ | |||
throw new TaskException( "ANTLR returned: " + err ); | |||
} | |||
} | |||
else | |||
{ | |||
ExecuteJava exe = new ExecuteJava(); | |||
exe.setJavaCommand( commandline.getJavaCommand() ); | |||
exe.setClasspath( commandline.getClasspath() ); | |||
exe.execute(); | |||
} | |||
} | |||
} | |||
/** | |||
* Search for the given resource and add the directory or archive that | |||
* contains it to the classpath. <p> | |||
* | |||
* Doesn't work for archives in JDK 1.1 as the URL returned by getResource | |||
* doesn't contain the name of the archive.</p> | |||
* | |||
* @param resource The feature to be added to the ClasspathEntry attribute | |||
*/ | |||
protected void addClasspathEntry( String resource ) | |||
{ | |||
URL url = getClass().getResource( resource ); | |||
if( url != null ) | |||
{ | |||
String u = url.toString(); | |||
if( u.startsWith( "jar:file:" ) ) | |||
{ | |||
int pling = u.indexOf( "!" ); | |||
String jarName = u.substring( 9, pling ); | |||
getContext().debug( "Implicitly adding " + jarName + " to classpath" ); | |||
createClasspath().setLocation( new File( ( new File( jarName ) ).getAbsolutePath() ) ); | |||
} | |||
else if( u.startsWith( "file:" ) ) | |||
{ | |||
int tail = u.indexOf( resource ); | |||
String dirName = u.substring( 5, tail ); | |||
getContext().debug( "Implicitly adding " + dirName + " to classpath" ); | |||
createClasspath().setLocation( new File( ( new File( dirName ) ).getAbsolutePath() ) ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "Don\'t know how to handle resource URL " + u ); | |||
} | |||
} | |||
else | |||
{ | |||
getContext().debug( "Couldn\'t find " + resource ); | |||
} | |||
} | |||
private File getGeneratedFile() | |||
throws TaskException | |||
{ | |||
String generatedFileName = null; | |||
try | |||
{ | |||
BufferedReader in = new BufferedReader( new FileReader( target ) ); | |||
String line; | |||
while( ( line = in.readLine() ) != null ) | |||
{ | |||
int extendsIndex = line.indexOf( " extends " ); | |||
if( line.startsWith( "class " ) && extendsIndex > -1 ) | |||
{ | |||
generatedFileName = line.substring( 6, extendsIndex ).trim(); | |||
break; | |||
} | |||
} | |||
in.close(); | |||
} | |||
catch( Exception e ) | |||
{ | |||
throw new TaskException( "Unable to determine generated class", e ); | |||
} | |||
if( generatedFileName == null ) | |||
{ | |||
throw new TaskException( "Unable to determine generated class" ); | |||
} | |||
return new File( outputDirectory, generatedFileName + ".java" ); | |||
} | |||
/** | |||
* execute in a forked VM | |||
* | |||
* @param command Description of Parameter | |||
* @return Description of the Returned Value | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private int run( final Commandline command ) | |||
throws TaskException | |||
{ | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
if( workingdir != null ) | |||
{ | |||
exe.setWorkingDirectory( workingdir ); | |||
} | |||
exe.setCommandline( command ); | |||
try | |||
{ | |||
return exe.execute(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
} | |||
private void validateAttributes() | |||
throws TaskException | |||
{ | |||
if( target == null || !target.isFile() ) | |||
{ | |||
throw new TaskException( "Invalid target: " + target ); | |||
} | |||
// if no output directory is specified, used the target's directory | |||
if( outputDirectory == null ) | |||
{ | |||
setOutputdirectory( new File( target.getParent() ) ); | |||
} | |||
if( !outputDirectory.isDirectory() ) | |||
{ | |||
throw new TaskException( "Invalid output directory: " + outputDirectory ); | |||
} | |||
} | |||
} |
@@ -1,300 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.PrintWriter; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.aut.nativelib.Os; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* Create a CAB archive. | |||
* | |||
* @author <a href="mailto:rvaughn@seaconinc.com">Roger Vaughn</a> | |||
*/ | |||
public class Cab | |||
extends MatchingTask | |||
{ | |||
private ArrayList m_filesets = new ArrayList(); | |||
private boolean m_compress = true; | |||
private File m_baseDir; | |||
private File m_cabFile; | |||
private String m_options; | |||
/** | |||
* This is the base directory to look in for things to cab. | |||
* | |||
* @param baseDir The new Basedir value | |||
*/ | |||
public void setBasedir( final File baseDir ) | |||
{ | |||
m_baseDir = baseDir; | |||
} | |||
/** | |||
* This is the name/location of where to create the .cab file. | |||
* | |||
* @param cabFile The new Cabfile value | |||
*/ | |||
public void setCabfile( final File cabFile ) | |||
{ | |||
m_cabFile = cabFile; | |||
} | |||
/** | |||
* Sets whether we want to compress the files or only store them. | |||
* | |||
* @param compress The new Compress value | |||
*/ | |||
public void setCompress( final boolean compress ) | |||
{ | |||
m_compress = compress; | |||
} | |||
/** | |||
* Sets additional cabarc options that aren't supported directly. | |||
* | |||
* @param options The new Options value | |||
*/ | |||
public void setOptions( final String options ) | |||
{ | |||
m_options = options; | |||
} | |||
/** | |||
* Adds a set of files (nested fileset attribute). | |||
* | |||
* @param set The feature to be added to the Fileset attribute | |||
*/ | |||
public void addFileset( final FileSet set ) | |||
{ | |||
m_filesets.add( set ); | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
checkConfiguration(); | |||
final ArrayList files = getFileList(); | |||
// quick exit if the target is up to date | |||
if( isUpToDate( files ) ) | |||
{ | |||
return; | |||
} | |||
getContext().info( "Building cab: " + m_cabFile.getAbsolutePath() ); | |||
if( !Os.isFamily( Os.OS_FAMILY_WINDOWS ) ) | |||
{ | |||
getContext().debug( "Using listcab/libcabinet" ); | |||
final StringBuffer sb = new StringBuffer(); | |||
final Iterator e = files.iterator(); | |||
while( e.hasNext() ) | |||
{ | |||
sb.append( e.next() ).append( "\n" ); | |||
} | |||
sb.append( "\n" ).append( m_cabFile.getAbsolutePath() ).append( "\n" ); | |||
try | |||
{ | |||
Process p = Runtime.getRuntime().exec( "listcab" ); | |||
OutputStream out = p.getOutputStream(); | |||
out.write( sb.toString().getBytes() ); | |||
out.flush(); | |||
out.close(); | |||
} | |||
catch( IOException ex ) | |||
{ | |||
String msg = "Problem creating " + m_cabFile + " " + ex.getMessage(); | |||
throw new TaskException( msg ); | |||
} | |||
} | |||
else | |||
{ | |||
try | |||
{ | |||
File listFile = createListFile( files ); | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
Execute exe = new Execute( execManager ); | |||
exe.setWorkingDirectory( m_baseDir ); | |||
final Commandline cmd = createCommand( listFile ); | |||
exe.setCommandline( cmd ); | |||
exe.execute(); | |||
listFile.delete(); | |||
} | |||
catch( final IOException ioe ) | |||
{ | |||
final String message = | |||
"Problem creating " + m_cabFile + " " + ioe.getMessage(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
} | |||
/** | |||
* Get the complete list of files to be included in the cab. Filenames are | |||
* gathered from filesets if any have been added, otherwise from the | |||
* traditional include parameters. | |||
*/ | |||
protected ArrayList getFileList() | |||
throws TaskException | |||
{ | |||
ArrayList files = new ArrayList(); | |||
if( m_filesets.size() == 0 ) | |||
{ | |||
// get files from old methods - includes and nested include | |||
appendFiles( files, super.getDirectoryScanner( m_baseDir ) ); | |||
} | |||
else | |||
{ | |||
// get files from filesets | |||
for( int i = 0; i < m_filesets.size(); i++ ) | |||
{ | |||
FileSet fs = (FileSet)m_filesets.get( i ); | |||
if( fs != null ) | |||
{ | |||
appendFiles( files, ScannerUtil.getDirectoryScanner( fs ) ); | |||
} | |||
} | |||
} | |||
return files; | |||
} | |||
/** | |||
* Check to see if the target is up to date with respect to input files. | |||
* | |||
* @param files Description of Parameter | |||
* @return true if the cab file is newer than its dependents. | |||
*/ | |||
protected boolean isUpToDate( ArrayList files ) | |||
{ | |||
boolean upToDate = true; | |||
for( int i = 0; i < files.size() && upToDate; i++ ) | |||
{ | |||
String file = files.get( i ).toString(); | |||
if( new File( m_baseDir, file ).lastModified() > | |||
m_cabFile.lastModified() ) | |||
{ | |||
upToDate = false; | |||
} | |||
} | |||
return upToDate; | |||
} | |||
/** | |||
* Append all files found by a directory scanner to a vector. | |||
* | |||
* @param files Description of Parameter | |||
* @param ds Description of Parameter | |||
*/ | |||
protected void appendFiles( ArrayList files, DirectoryScanner ds ) | |||
{ | |||
String[] dsfiles = ds.getIncludedFiles(); | |||
for( int i = 0; i < dsfiles.length; i++ ) | |||
{ | |||
files.add( dsfiles[ i ] ); | |||
} | |||
} | |||
/* | |||
* I'm not fond of this pattern: "sub-method expected to throw | |||
* task-cancelling exceptions". It feels too much like programming | |||
* for side-effects to me... | |||
*/ | |||
protected void checkConfiguration() | |||
throws TaskException | |||
{ | |||
if( m_baseDir == null ) | |||
{ | |||
throw new TaskException( "basedir attribute must be set!" ); | |||
} | |||
if( !m_baseDir.exists() ) | |||
{ | |||
throw new TaskException( "basedir does not exist!" ); | |||
} | |||
if( m_cabFile == null ) | |||
{ | |||
throw new TaskException( "cabfile attribute must be set!" ); | |||
} | |||
} | |||
/** | |||
* Create the cabarc command line to use. | |||
*/ | |||
protected Commandline createCommand( final File listFile ) | |||
throws TaskException | |||
{ | |||
final Commandline cmd = new Commandline(); | |||
cmd.setExecutable( "cabarc" ); | |||
cmd.addArgument( "-r" ); | |||
cmd.addArgument( "-p" ); | |||
if( !m_compress ) | |||
{ | |||
cmd.addArgument( "-m" ); | |||
cmd.addArgument( "none" ); | |||
} | |||
if( m_options != null ) | |||
{ | |||
cmd.addLine( m_options ); | |||
} | |||
cmd.addArgument( "n" ); | |||
cmd.addArgument( m_cabFile ); | |||
cmd.addArgument( "@" + listFile.getAbsolutePath() ); | |||
return cmd; | |||
} | |||
/** | |||
* Creates a list file. This temporary file contains a list of all files to | |||
* be included in the cab, one file per line. | |||
* | |||
* @param files Description of Parameter | |||
* @return Description of the Returned Value | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
protected File createListFile( ArrayList files ) | |||
throws IOException | |||
{ | |||
File listFile = File.createTempFile( "ant", "", getBaseDirectory() ); | |||
PrintWriter writer = new PrintWriter( new FileOutputStream( listFile ) ); | |||
for( int i = 0; i < files.size(); i++ ) | |||
{ | |||
writer.println( files.get( i ).toString() ); | |||
} | |||
writer.close(); | |||
return listFile; | |||
} | |||
} |
@@ -1,23 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
public class ClassArgument | |||
{ | |||
private String m_name; | |||
public void setName( String name ) | |||
{ | |||
m_name = name; | |||
} | |||
public String getName() | |||
{ | |||
return m_name; | |||
} | |||
} |
@@ -1,305 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.Iterator; | |||
import org.apache.aut.nativelib.Os; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileList; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* A Task to record explicit dependencies. If any of the target files are out of | |||
* date with respect to any of the source files, all target files are removed. | |||
* This is useful where dependencies cannot be computed (for example, | |||
* dynamically interpreted parameters or files that need to stay in synch but | |||
* are not directly linked) or where the ant task in question could compute them | |||
* but does not (for example, the linked DTD for an XML file using the style | |||
* task). nested arguments: | |||
* <ul> | |||
* <li> srcfileset (fileset describing the source files to examine) | |||
* <li> srcfilelist (filelist describing the source files to examine) | |||
* <li> targetfileset (fileset describing the target files to examine) | |||
* <li> targetfilelist (filelist describing the target files to examine) | |||
* </ul> | |||
* At least one instance of either a fileset or filelist for both source and | |||
* target are required. <p> | |||
* | |||
* This task will examine each of the source files against each of the target | |||
* files. If any target files are out of date with respect to any of the source | |||
* files, all targets are removed. If any files named in a (src or target) | |||
* filelist do not exist, all targets are removed. Hint: If missing files should | |||
* be ignored, specify them as include patterns in filesets, rather than using | |||
* filelists. </p> <p> | |||
* | |||
* This task attempts to optimize speed of dependency checking. It will stop | |||
* after the first out of date file is found and remove all targets, rather than | |||
* exhaustively checking every source vs target combination unnecessarily. </p> | |||
* <p> | |||
* | |||
* Example uses: | |||
* <ul> | |||
* <li> Record the fact that an XML file must be up to date with respect to | |||
* its XSD (Schema file), even though the XML file itself includes no | |||
* reference to its XSD. </li> | |||
* <li> Record the fact that an XSL stylesheet includes other sub-stylesheets | |||
* </li> | |||
* <li> Record the fact that java files must be recompiled if the ant build | |||
* file changes </li> | |||
* </ul> | |||
* | |||
* | |||
* @author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class DependSet extends MatchingTask | |||
{ | |||
private ArrayList sourceFileSets = new ArrayList(); | |||
private ArrayList sourceFileLists = new ArrayList(); | |||
private ArrayList targetFileSets = new ArrayList(); | |||
private ArrayList targetFileLists = new ArrayList(); | |||
/** | |||
* Creates a new DependSet Task. | |||
*/ | |||
public DependSet() | |||
{ | |||
} | |||
/** | |||
* Nested <srcfilelist> element. | |||
* | |||
* @param fl The feature to be added to the Srcfilelist attribute | |||
*/ | |||
public void addSrcfilelist( FileList fl ) | |||
{ | |||
sourceFileLists.add( fl ); | |||
}//-- DependSet | |||
/** | |||
* Nested <srcfileset> element. | |||
* | |||
* @param fs The feature to be added to the Srcfileset attribute | |||
*/ | |||
public void addSrcfileset( FileSet fs ) | |||
{ | |||
sourceFileSets.add( fs ); | |||
} | |||
/** | |||
* Nested <targetfilelist> element. | |||
* | |||
* @param fl The feature to be added to the Targetfilelist attribute | |||
*/ | |||
public void addTargetfilelist( FileList fl ) | |||
{ | |||
targetFileLists.add( fl ); | |||
} | |||
/** | |||
* Nested <targetfileset> element. | |||
* | |||
* @param fs The feature to be added to the Targetfileset attribute | |||
*/ | |||
public void addTargetfileset( FileSet fs ) | |||
{ | |||
targetFileSets.add( fs ); | |||
} | |||
/** | |||
* Executes the task. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( ( sourceFileSets.size() == 0 ) && ( sourceFileLists.size() == 0 ) ) | |||
{ | |||
throw new TaskException( "At least one <srcfileset> or <srcfilelist> element must be set" ); | |||
} | |||
if( ( targetFileSets.size() == 0 ) && ( targetFileLists.size() == 0 ) ) | |||
{ | |||
throw new TaskException( "At least one <targetfileset> or <targetfilelist> element must be set" ); | |||
} | |||
long now = ( new Date() ).getTime(); | |||
/* | |||
* If we're on Windows, we have to munge the time up to 2 secs to | |||
* be able to check file modification times. | |||
* (Windows has a max resolution of two secs for modification times) | |||
*/ | |||
if( Os.isFamily( Os.OS_FAMILY_WINDOWS ) ) | |||
{ | |||
now += 2000; | |||
} | |||
// | |||
// Grab all the target files specified via filesets | |||
// | |||
ArrayList allTargets = new ArrayList(); | |||
Iterator enumTargetSets = targetFileSets.iterator(); | |||
while( enumTargetSets.hasNext() ) | |||
{ | |||
FileSet targetFS = (FileSet)enumTargetSets.next(); | |||
DirectoryScanner targetDS = ScannerUtil.getDirectoryScanner( targetFS ); | |||
String[] targetFiles = targetDS.getIncludedFiles(); | |||
for( int i = 0; i < targetFiles.length; i++ ) | |||
{ | |||
File dest = new File( targetFS.getDir(), targetFiles[ i ] ); | |||
allTargets.add( dest ); | |||
if( dest.lastModified() > now ) | |||
{ | |||
getContext().warn( "Warning: " + targetFiles[ i ] + " modified in the future." ); | |||
} | |||
} | |||
} | |||
// | |||
// Grab all the target files specified via filelists | |||
// | |||
boolean upToDate = true; | |||
Iterator enumTargetLists = targetFileLists.iterator(); | |||
while( enumTargetLists.hasNext() ) | |||
{ | |||
FileList targetFL = (FileList)enumTargetLists.next(); | |||
String[] targetFiles = targetFL.getFiles(); | |||
for( int i = 0; i < targetFiles.length; i++ ) | |||
{ | |||
File dest = new File( targetFL.getDir(), targetFiles[ i ] ); | |||
if( !dest.exists() ) | |||
{ | |||
getContext().debug( targetFiles[ i ] + " does not exist." ); | |||
upToDate = false; | |||
continue; | |||
} | |||
else | |||
{ | |||
allTargets.add( dest ); | |||
} | |||
if( dest.lastModified() > now ) | |||
{ | |||
getContext().warn( "Warning: " + targetFiles[ i ] + " modified in the future." ); | |||
} | |||
} | |||
} | |||
// | |||
// Check targets vs source files specified via filesets | |||
// | |||
if( upToDate ) | |||
{ | |||
Iterator enumSourceSets = sourceFileSets.iterator(); | |||
while( upToDate && enumSourceSets.hasNext() ) | |||
{ | |||
FileSet sourceFS = (FileSet)enumSourceSets.next(); | |||
DirectoryScanner sourceDS = ScannerUtil.getDirectoryScanner( sourceFS ); | |||
String[] sourceFiles = sourceDS.getIncludedFiles(); | |||
for( int i = 0; upToDate && i < sourceFiles.length; i++ ) | |||
{ | |||
File src = new File( sourceFS.getDir(), sourceFiles[ i ] ); | |||
if( src.lastModified() > now ) | |||
{ | |||
getContext().warn( "Warning: " + sourceFiles[ i ] + " modified in the future." ); | |||
} | |||
Iterator enumTargets = allTargets.iterator(); | |||
while( upToDate && enumTargets.hasNext() ) | |||
{ | |||
File dest = (File)enumTargets.next(); | |||
if( src.lastModified() > dest.lastModified() ) | |||
{ | |||
getContext().debug( dest.getPath() + " is out of date with respect to " + sourceFiles[ i ] ); | |||
upToDate = false; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// | |||
// Check targets vs source files specified via filelists | |||
// | |||
if( upToDate ) | |||
{ | |||
Iterator enumSourceLists = sourceFileLists.iterator(); | |||
while( upToDate && enumSourceLists.hasNext() ) | |||
{ | |||
FileList sourceFL = (FileList)enumSourceLists.next(); | |||
String[] sourceFiles = sourceFL.getFiles(); | |||
int i = 0; | |||
do | |||
{ | |||
File src = new File( sourceFL.getDir(), sourceFiles[ i ] ); | |||
if( src.lastModified() > now ) | |||
{ | |||
getContext().warn( "Warning: " + sourceFiles[ i ] + " modified in the future." ); | |||
} | |||
if( !src.exists() ) | |||
{ | |||
getContext().debug( sourceFiles[ i ] + " does not exist." ); | |||
upToDate = false; | |||
break; | |||
} | |||
Iterator enumTargets = allTargets.iterator(); | |||
while( upToDate && enumTargets.hasNext() ) | |||
{ | |||
File dest = (File)enumTargets.next(); | |||
if( src.lastModified() > dest.lastModified() ) | |||
{ | |||
getContext().debug( dest.getPath() + " is out of date with respect to " + sourceFiles[ i ] ); | |||
upToDate = false; | |||
} | |||
} | |||
} while( upToDate && ( ++i < sourceFiles.length ) ); | |||
} | |||
} | |||
if( !upToDate ) | |||
{ | |||
getContext().debug( "Deleting all target files. " ); | |||
for( Iterator e = allTargets.iterator(); e.hasNext(); ) | |||
{ | |||
File fileToRemove = (File)e.next(); | |||
getContext().debug( "Deleting file " + fileToRemove.getAbsolutePath() ); | |||
fileToRemove.delete(); | |||
} | |||
} | |||
}//-- execute | |||
}//-- DependSet.java |
@@ -1,108 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.io.FileWriter; | |||
import java.io.IOException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Log | |||
* | |||
* @author costin@dnt.ro | |||
*/ | |||
public class Echo | |||
extends AbstractTask | |||
{ | |||
private String m_message = "";// required | |||
private File m_file; | |||
private boolean m_append; | |||
/** | |||
* Shall we append to an existing file? | |||
* | |||
* @param append The new Append value | |||
*/ | |||
public void setAppend( final boolean append ) | |||
{ | |||
m_append = append; | |||
} | |||
/** | |||
* Sets the file attribute. | |||
* | |||
* @param file The new File value | |||
*/ | |||
public void setFile( final File file ) | |||
{ | |||
m_file = file; | |||
} | |||
/** | |||
* Sets the message variable. | |||
* | |||
* @param msg Sets the value for the message variable. | |||
*/ | |||
public void setMessage( final String message ) | |||
{ | |||
m_message = message; | |||
} | |||
/** | |||
* Set a multiline message. | |||
* | |||
* @param msg The feature to be added to the Text attribute | |||
*/ | |||
public void addContent( final String message ) | |||
throws TaskException | |||
{ | |||
m_message = message; | |||
} | |||
/** | |||
* Does the work. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException if someting goes wrong with the build | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( m_file == null ) | |||
{ | |||
throw new TaskException( "Echo only used to write to files now !" ); | |||
} | |||
else | |||
{ | |||
FileWriter out = null; | |||
try | |||
{ | |||
out = new FileWriter( m_file.getAbsolutePath(), m_append ); | |||
out.write( m_message, 0, m_message.length() ); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
throw new TaskException( "Error", ioe ); | |||
} | |||
finally | |||
{ | |||
if( out != null ) | |||
{ | |||
try | |||
{ | |||
out.close(); | |||
} | |||
catch( IOException ioex ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,488 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.text.DateFormat; | |||
import java.text.DecimalFormat; | |||
import java.text.ParseException; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Calendar; | |||
import java.util.Date; | |||
import java.util.GregorianCalendar; | |||
import java.util.Properties; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
/** | |||
* Instance of this class represents nested elements of a task propertyfile. | |||
*/ | |||
public class Entry | |||
{ | |||
final static String NOW_VALUE_ = "now"; | |||
final static String NULL_VALUE_ = "never"; | |||
private final static int DEFAULT_INT_VALUE = 1; | |||
private final static GregorianCalendar | |||
DEFAULT_DATE_VALUE = new GregorianCalendar(); | |||
private String m_key; | |||
private int m_type = Type.STRING_TYPE; | |||
private int m_operation = Operation.EQUALS_OPER; | |||
private String m_value = ""; | |||
private String m_default; | |||
private String m_pattern; | |||
public void setDefault( String value ) | |||
{ | |||
this.m_default = value; | |||
} | |||
public void setKey( String value ) | |||
{ | |||
this.m_key = value; | |||
} | |||
public void setOperation( Operation value ) | |||
{ | |||
int newOperation = Operation.toOperation( value.getValue() ); | |||
if( newOperation == Operation.NOW_VALUE ) | |||
{ | |||
this.m_operation = Operation.EQUALS_OPER; | |||
this.setValue( this.NOW_VALUE_ ); | |||
} | |||
else if( newOperation == Operation.NULL_VALUE ) | |||
{ | |||
this.m_operation = Operation.EQUALS_OPER; | |||
this.setValue( this.NULL_VALUE_ ); | |||
} | |||
else | |||
{ | |||
this.m_operation = newOperation; | |||
} | |||
} | |||
public void setPattern( String value ) | |||
{ | |||
this.m_pattern = value; | |||
} | |||
public void setType( Type value ) | |||
{ | |||
this.m_type = Type.toType( value.getValue() ); | |||
} | |||
public void setValue( String value ) | |||
{ | |||
this.m_value = value; | |||
} | |||
protected void executeOn( Properties props ) | |||
throws TaskException | |||
{ | |||
checkParameters(); | |||
// m_type may be null because it wasn't set | |||
try | |||
{ | |||
if( m_type == Type.INTEGER_TYPE ) | |||
{ | |||
executeInteger( (String)props.get( m_key ) ); | |||
} | |||
else if( m_type == Type.DATE_TYPE ) | |||
{ | |||
executeDate( (String)props.get( m_key ) ); | |||
} | |||
else if( m_type == Type.STRING_TYPE ) | |||
{ | |||
executeString( (String)props.get( m_key ) ); | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Unknown operation type: " + m_type + "" ); | |||
} | |||
} | |||
catch( NullPointerException npe ) | |||
{ | |||
// Default to string type | |||
// which means do nothing | |||
npe.printStackTrace(); | |||
} | |||
// Insert as a string by default | |||
props.put( m_key, m_value ); | |||
} | |||
/** | |||
* Check if parameter combinations can be supported | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private void checkParameters() | |||
throws TaskException | |||
{ | |||
if( m_type == Type.STRING_TYPE && | |||
m_operation == Operation.DECREMENT_OPER ) | |||
{ | |||
throw new TaskException( "- is not suported for string properties (key:" + m_key + ")" ); | |||
} | |||
if( m_value == null && m_default == null ) | |||
{ | |||
throw new TaskException( "value and/or default must be specified (key:" + m_key + ")" ); | |||
} | |||
if( m_key == null ) | |||
{ | |||
throw new TaskException( "key is mandatory" ); | |||
} | |||
if( m_type == Type.STRING_TYPE && | |||
m_pattern != null ) | |||
{ | |||
throw new TaskException( "pattern is not suported for string properties (key:" + m_key + ")" ); | |||
} | |||
} | |||
/** | |||
* Handle operations for type <code>date</code>. | |||
* | |||
* @param oldValue the current value read from the property file or | |||
* <code>null</code> if the <code>key</code> was not contained in | |||
* the property file. | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private void executeDate( String oldValue ) | |||
throws TaskException | |||
{ | |||
GregorianCalendar value = new GregorianCalendar(); | |||
GregorianCalendar newValue = new GregorianCalendar(); | |||
if( m_pattern == null ) | |||
{ | |||
m_pattern = "yyyy/MM/dd HH:mm"; | |||
} | |||
DateFormat fmt = new SimpleDateFormat( m_pattern ); | |||
// special case | |||
if( m_default != null && | |||
NOW_VALUE_.equals( m_default.toLowerCase() ) && | |||
( m_operation == Operation.INCREMENT_OPER || | |||
m_operation == Operation.DECREMENT_OPER ) ) | |||
{ | |||
oldValue = null; | |||
} | |||
if( oldValue != null ) | |||
{ | |||
try | |||
{ | |||
value.setTime( fmt.parse( oldValue ) ); | |||
} | |||
catch( ParseException pe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
} | |||
if( m_value != null ) | |||
{ | |||
if( NOW_VALUE_.equals( m_value.toLowerCase() ) ) | |||
{ | |||
value.setTime( new Date() ); | |||
} | |||
else if( NULL_VALUE_.equals( m_value.toLowerCase() ) ) | |||
{ | |||
value = null; | |||
} | |||
else | |||
{ | |||
try | |||
{ | |||
value.setTime( fmt.parse( m_value ) ); | |||
} | |||
catch( Exception ex ) | |||
{ | |||
// obviously not a date, try a simple int | |||
try | |||
{ | |||
int offset = Integer.parseInt( m_value ); | |||
value.clear(); | |||
value.set( Calendar.DAY_OF_YEAR, offset ); | |||
} | |||
catch( Exception ex_ ) | |||
{ | |||
value.clear(); | |||
value.set( Calendar.DAY_OF_YEAR, 1 ); | |||
} | |||
} | |||
} | |||
} | |||
if( m_default != null && oldValue == null ) | |||
{ | |||
if( NOW_VALUE_.equals( m_default.toLowerCase() ) ) | |||
{ | |||
value.setTime( new Date() ); | |||
} | |||
else if( NULL_VALUE_.equals( m_default.toLowerCase() ) ) | |||
{ | |||
value = null; | |||
} | |||
else | |||
{ | |||
try | |||
{ | |||
value.setTime( fmt.parse( m_default ) ); | |||
} | |||
catch( ParseException pe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
} | |||
} | |||
if( m_operation == Operation.EQUALS_OPER ) | |||
{ | |||
newValue = value; | |||
} | |||
else if( m_operation == Operation.INCREMENT_OPER ) | |||
{ | |||
newValue.add( Calendar.SECOND, value.get( Calendar.SECOND ) ); | |||
newValue.add( Calendar.MINUTE, value.get( Calendar.MINUTE ) ); | |||
newValue.add( Calendar.HOUR_OF_DAY, value.get( Calendar.HOUR_OF_DAY ) ); | |||
newValue.add( Calendar.DAY_OF_YEAR, value.get( Calendar.DAY_OF_YEAR ) ); | |||
} | |||
else if( m_operation == Operation.DECREMENT_OPER ) | |||
{ | |||
newValue.add( Calendar.SECOND, -1 * value.get( Calendar.SECOND ) ); | |||
newValue.add( Calendar.MINUTE, -1 * value.get( Calendar.MINUTE ) ); | |||
newValue.add( Calendar.HOUR_OF_DAY, -1 * value.get( Calendar.HOUR_OF_DAY ) ); | |||
newValue.add( Calendar.DAY_OF_YEAR, -1 * value.get( Calendar.DAY_OF_YEAR ) ); | |||
} | |||
if( newValue != null ) | |||
{ | |||
m_value = fmt.format( newValue.getTime() ); | |||
} | |||
else | |||
{ | |||
m_value = ""; | |||
} | |||
} | |||
/** | |||
* Handle operations for type <code>int</code>. | |||
* | |||
* @param oldValue the current value read from the property file or | |||
* <code>null</code> if the <code>key</code> was not contained in | |||
* the property file. | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private void executeInteger( String oldValue ) | |||
throws TaskException | |||
{ | |||
int value = 0; | |||
int newValue = 0; | |||
DecimalFormat fmt = ( m_pattern != null ) ? new DecimalFormat( m_pattern ) | |||
: new DecimalFormat(); | |||
if( oldValue != null ) | |||
{ | |||
try | |||
{ | |||
value = fmt.parse( oldValue ).intValue(); | |||
} | |||
catch( NumberFormatException nfe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
catch( ParseException pe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
} | |||
if( m_value != null ) | |||
{ | |||
try | |||
{ | |||
value = fmt.parse( m_value ).intValue(); | |||
} | |||
catch( NumberFormatException nfe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
catch( ParseException pe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
} | |||
if( m_default != null && oldValue == null ) | |||
{ | |||
try | |||
{ | |||
value = fmt.parse( m_default ).intValue(); | |||
} | |||
catch( NumberFormatException nfe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
catch( ParseException pe ) | |||
{ | |||
/* | |||
* swollow | |||
*/ | |||
} | |||
} | |||
if( m_operation == Operation.EQUALS_OPER ) | |||
{ | |||
newValue = value; | |||
} | |||
else if( m_operation == Operation.INCREMENT_OPER ) | |||
{ | |||
newValue = ++value; | |||
} | |||
else if( m_operation == Operation.DECREMENT_OPER ) | |||
{ | |||
newValue = --value; | |||
} | |||
m_value = fmt.format( newValue ); | |||
} | |||
/** | |||
* Handle operations for type <code>string</code>. | |||
* | |||
* @param oldValue the current value read from the property file or | |||
* <code>null</code> if the <code>key</code> was not contained in | |||
* the property file. | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private void executeString( String oldValue ) | |||
throws TaskException | |||
{ | |||
String value = ""; | |||
String newValue = ""; | |||
// the order of events is, of course, very important here | |||
// default initially to the old value | |||
if( oldValue != null ) | |||
{ | |||
value = oldValue; | |||
} | |||
// but if a value is specified, use it | |||
if( m_value != null ) | |||
{ | |||
value = m_value; | |||
} | |||
// even if value is specified, ignore it and set to the default | |||
// value if it is specified and there is no previous value | |||
if( m_default != null && oldValue == null ) | |||
{ | |||
value = m_default; | |||
} | |||
if( m_operation == Operation.EQUALS_OPER ) | |||
{ | |||
newValue = value; | |||
} | |||
else if( m_operation == Operation.INCREMENT_OPER ) | |||
{ | |||
newValue += value; | |||
} | |||
m_value = newValue; | |||
} | |||
/** | |||
* Enumerated attribute with the values "+", "-", "=", "now" and | |||
* "never". | |||
* | |||
* @author RT | |||
*/ | |||
public static class Operation extends EnumeratedAttribute | |||
{ | |||
// Property type operations | |||
public final static int INCREMENT_OPER = 0; | |||
public final static int DECREMENT_OPER = 1; | |||
public final static int EQUALS_OPER = 2; | |||
// Special values | |||
public final static int NOW_VALUE = 3; | |||
public final static int NULL_VALUE = 4; | |||
public static int toOperation( String oper ) | |||
{ | |||
if( "+".equals( oper ) ) | |||
{ | |||
return INCREMENT_OPER; | |||
} | |||
else if( "-".equals( oper ) ) | |||
{ | |||
return DECREMENT_OPER; | |||
} | |||
else if( NOW_VALUE_.equals( oper ) ) | |||
{ | |||
return NOW_VALUE; | |||
} | |||
else if( NULL_VALUE_.equals( oper ) ) | |||
{ | |||
return NULL_VALUE; | |||
} | |||
return EQUALS_OPER; | |||
} | |||
public String[] getValues() | |||
{ | |||
return new String[]{"+", "-", "=", NOW_VALUE_, NULL_VALUE_}; | |||
} | |||
} | |||
/** | |||
* Enumerated attribute with the values "int", "date" and "string". | |||
* | |||
* @author RT | |||
*/ | |||
public static class Type extends EnumeratedAttribute | |||
{ | |||
// Property types | |||
public final static int INTEGER_TYPE = 0; | |||
public final static int DATE_TYPE = 1; | |||
public final static int STRING_TYPE = 2; | |||
public static int toType( String type ) | |||
{ | |||
if( "int".equals( type ) ) | |||
{ | |||
return INTEGER_TYPE; | |||
} | |||
else if( "date".equals( type ) ) | |||
{ | |||
return DATE_TYPE; | |||
} | |||
return STRING_TYPE; | |||
} | |||
public String[] getValues() | |||
{ | |||
return new String[]{"int", "date", "string"}; | |||
} | |||
} | |||
} |
@@ -1,105 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.lang.reflect.Method; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
import org.apache.tools.todo.types.SysProperties; | |||
/* | |||
* @author thomas.haas@softwired-inc.com | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class ExecuteJava | |||
{ | |||
private Commandline m_javaCommand; | |||
private Path m_classpath; | |||
private SysProperties m_sysProperties; | |||
public void setClasspath( final Path classpath ) | |||
{ | |||
m_classpath = classpath; | |||
} | |||
public void setJavaCommand( final Commandline javaCommand ) | |||
{ | |||
m_javaCommand = javaCommand; | |||
} | |||
public void setSystemProperties( final SysProperties sysProperties ) | |||
{ | |||
m_sysProperties = sysProperties; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
final String classname = m_javaCommand.getExecutable(); | |||
final Object[] argument = new Object[]{m_javaCommand.getArguments()}; | |||
try | |||
{ | |||
if( m_sysProperties != null ) | |||
{ | |||
m_sysProperties.setSystem(); | |||
} | |||
final Class[] param = {Class.forName( "[Ljava.lang.String;" )}; | |||
Class target = null; | |||
if( m_classpath == null ) | |||
{ | |||
target = Class.forName( classname ); | |||
} | |||
else | |||
{ | |||
final URL[] urls = PathUtil.toURLs( m_classpath ); | |||
final URLClassLoader classLoader = new URLClassLoader( urls ); | |||
target = classLoader.loadClass( classname ); | |||
} | |||
final Method main = target.getMethod( "main", param ); | |||
main.invoke( null, argument ); | |||
} | |||
catch( NullPointerException e ) | |||
{ | |||
throw new TaskException( "Could not find main() method in " + classname ); | |||
} | |||
catch( ClassNotFoundException e ) | |||
{ | |||
throw new TaskException( "Could not find " + classname + ". Make sure you have it in your classpath" ); | |||
} | |||
catch( InvocationTargetException e ) | |||
{ | |||
Throwable t = e.getTargetException(); | |||
if( !( t instanceof SecurityException ) ) | |||
{ | |||
throw new TaskException( "Error", t ); | |||
} | |||
else | |||
{ | |||
throw (SecurityException)t; | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
finally | |||
{ | |||
if( m_sysProperties != null ) | |||
{ | |||
m_sysProperties.restoreSystem(); | |||
} | |||
} | |||
} | |||
} |
@@ -1,36 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
public class FileDir | |||
extends EnumeratedAttribute | |||
{ | |||
private final static String[] values = {"file", "dir"}; | |||
public String[] getValues() | |||
{ | |||
return values; | |||
} | |||
public boolean isDir() | |||
{ | |||
return "dir".equalsIgnoreCase( getValue() ); | |||
} | |||
public boolean isFile() | |||
{ | |||
return "file".equalsIgnoreCase( getValue() ); | |||
} | |||
public String toString() | |||
{ | |||
return getValue(); | |||
} | |||
} |
@@ -1,381 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.HttpURLConnection; | |||
import java.net.URL; | |||
import java.net.URLConnection; | |||
import java.util.Date; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
/** | |||
* Get a particular file from a URL source. Options include verbose reporting, | |||
* timestamp based fetches and controlling actions on failures. NB: access | |||
* through a firewall only works if the whole Java runtime is correctly | |||
* configured. | |||
* | |||
* @author costin@dnt.ro | |||
* @author gg@grtmail.com (Added Java 1.1 style HTTP basic auth) | |||
*/ | |||
public class Get extends AbstractTask | |||
{// required | |||
private boolean verbose = false; | |||
private boolean useTimestamp = false;//off by default | |||
private boolean ignoreErrors = false; | |||
private String uname = null; | |||
private String pword = null;// required | |||
private File dest; | |||
private URL source; | |||
/** | |||
* Where to copy the source file. | |||
* | |||
* @param dest Path to file. | |||
*/ | |||
public void setDest( File dest ) | |||
{ | |||
this.dest = dest; | |||
} | |||
/** | |||
* Don't stop if get fails if set to "<CODE>true</CODE>". | |||
* | |||
* @param v if "true" then don't report download errors up to ant | |||
*/ | |||
public void setIgnoreErrors( boolean v ) | |||
{ | |||
ignoreErrors = v; | |||
} | |||
/** | |||
* password for the basic auth. | |||
* | |||
* @param p password for authentication | |||
*/ | |||
public void setPassword( String p ) | |||
{ | |||
this.pword = p; | |||
} | |||
/** | |||
* Set the URL. | |||
* | |||
* @param u URL for the file. | |||
*/ | |||
public void setSrc( URL u ) | |||
{ | |||
this.source = u; | |||
} | |||
/** | |||
* Use timestamps, if set to "<CODE>true</CODE>". <p> | |||
* | |||
* In this situation, the if-modified-since header is set so that the file | |||
* is only fetched if it is newer than the local file (or there is no local | |||
* file) This flag is only valid on HTTP connections, it is ignored in other | |||
* cases. When the flag is set, the local copy of the downloaded file will | |||
* also have its timestamp set to the remote file time. <br> | |||
* Note that remote files of date 1/1/1970 (GMT) are treated as 'no | |||
* timestamp', and web servers often serve files with a timestamp in the | |||
* future by replacing their timestamp with that of the current time. Also, | |||
* inter-computer clock differences can cause no end of grief. | |||
* | |||
* @param v "true" to enable file time fetching | |||
*/ | |||
public void setUseTimestamp( boolean v ) | |||
{ | |||
useTimestamp = v; | |||
} | |||
/** | |||
* Username for basic auth. | |||
* | |||
* @param u username for authentication | |||
*/ | |||
public void setUsername( String u ) | |||
{ | |||
this.uname = u; | |||
} | |||
/** | |||
* Be verbose, if set to "<CODE>true</CODE>". | |||
* | |||
* @param v if "true" then be verbose | |||
*/ | |||
public void setVerbose( boolean v ) | |||
{ | |||
verbose = v; | |||
} | |||
/** | |||
* Does the work. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Thrown in unrecoverable error. | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( source == null ) | |||
{ | |||
throw new TaskException( "src attribute is required" ); | |||
} | |||
if( dest == null ) | |||
{ | |||
throw new TaskException( "dest attribute is required" ); | |||
} | |||
if( dest.exists() && dest.isDirectory() ) | |||
{ | |||
throw new TaskException( "The specified destination is a directory" ); | |||
} | |||
if( dest.exists() && !dest.canWrite() ) | |||
{ | |||
throw new TaskException( "Can't write to " + dest.getAbsolutePath() ); | |||
} | |||
try | |||
{ | |||
getContext().info( "Getting: " + source ); | |||
//set the timestamp to the file date. | |||
long timestamp = 0; | |||
boolean hasTimestamp = false; | |||
if( useTimestamp && dest.exists() ) | |||
{ | |||
timestamp = dest.lastModified(); | |||
if( verbose ) | |||
{ | |||
Date t = new Date( timestamp ); | |||
getContext().info( "local file date : " + t.toString() ); | |||
} | |||
hasTimestamp = true; | |||
} | |||
//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( uname != null || pword != null ) | |||
{ | |||
String up = uname + ":" + pword; | |||
String encoding; | |||
// 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 ) | |||
{// sun's base64 encoder isn't available | |||
Base64Converter encoder = new Base64Converter(); | |||
encoding = encoder.encode( up.getBytes() ); | |||
} | |||
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 ) | |||
{ | |||
//not modified so no file download. just return instead | |||
//and trace out something so the user doesn't think that the | |||
//download happened when it didnt | |||
getContext().info( "Not modified - so not downloaded" ); | |||
return; | |||
} | |||
// test for 401 result (HTTP only) | |||
if( httpConnection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED ) | |||
{ | |||
getContext().info( "Not authorized - check " + dest + " for details" ); | |||
return; | |||
} | |||
} | |||
//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. | |||
FileOutputStream fos = new FileOutputStream( dest ); | |||
InputStream is = null; | |||
for( int i = 0; i < 3; i++ ) | |||
{ | |||
try | |||
{ | |||
is = connection.getInputStream(); | |||
break; | |||
} | |||
catch( IOException ex ) | |||
{ | |||
getContext().info( "Error opening connection " + ex ); | |||
} | |||
} | |||
if( is == null ) | |||
{ | |||
getContext().info( "Can't get " + source + " to " + dest ); | |||
if( ignoreErrors ) | |||
{ | |||
return; | |||
} | |||
throw new TaskException( "Can't get " + source + " to " + dest ); | |||
} | |||
byte[] buffer = new byte[ 100 * 1024 ]; | |||
int length; | |||
while( ( length = is.read( buffer ) ) >= 0 ) | |||
{ | |||
fos.write( buffer, 0, length ); | |||
if( verbose ) | |||
{ | |||
System.out.print( "." ); | |||
} | |||
} | |||
if( verbose ) | |||
{ | |||
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( verbose ) | |||
{ | |||
Date t = new Date( remoteTimestamp ); | |||
getContext().info( "last modified = " + t.toString() | |||
+ ( ( remoteTimestamp == 0 ) ? " - using current time instead" : "" ) ); | |||
} | |||
if( remoteTimestamp != 0 ) | |||
{ | |||
dest.setLastModified( remoteTimestamp ); | |||
} | |||
} | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
getContext().info( "Error getting " + source + " to " + dest ); | |||
if( ignoreErrors ) | |||
{ | |||
return; | |||
} | |||
throw new TaskException( "Error", ioe ); | |||
} | |||
} | |||
/** | |||
* BASE 64 encoding of a String or an array of bytes. Based on RFC 1421. | |||
* | |||
* @author Unknown | |||
* @author <a HREF="gg@grtmail.com">Gautam Guliani</a> | |||
*/ | |||
class Base64Converter | |||
{ | |||
public final char[] alphabet = { | |||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7 | |||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15 | |||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23 | |||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31 | |||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39 | |||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47 | |||
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55 | |||
'4', '5', '6', '7', '8', '9', '+', '/'};// 56 to 63 | |||
public String encode( String s ) | |||
{ | |||
return encode( s.getBytes() ); | |||
} | |||
public String encode( byte[] octetString ) | |||
{ | |||
int bits24; | |||
int bits6; | |||
char[] out | |||
= new char[ ( ( octetString.length - 1 ) / 3 + 1 ) * 4 ]; | |||
int outIndex = 0; | |||
int i = 0; | |||
while( ( i + 3 ) <= octetString.length ) | |||
{ | |||
// store the octets | |||
bits24 = ( octetString[ i++ ] & 0xFF ) << 16; | |||
bits24 |= ( octetString[ i++ ] & 0xFF ) << 8; | |||
bits6 = ( bits24 & 0x00FC0000 ) >> 18; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
bits6 = ( bits24 & 0x0003F000 ) >> 12; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
bits6 = ( bits24 & 0x00000FC0 ) >> 6; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
bits6 = ( bits24 & 0x0000003F ); | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
} | |||
if( octetString.length - i == 2 ) | |||
{ | |||
// store the octets | |||
bits24 = ( octetString[ i ] & 0xFF ) << 16; | |||
bits24 |= ( octetString[ i + 1 ] & 0xFF ) << 8; | |||
bits6 = ( bits24 & 0x00FC0000 ) >> 18; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
bits6 = ( bits24 & 0x0003F000 ) >> 12; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
bits6 = ( bits24 & 0x00000FC0 ) >> 6; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
// padding | |||
out[ outIndex++ ] = '='; | |||
} | |||
else if( octetString.length - i == 1 ) | |||
{ | |||
// store the octets | |||
bits24 = ( octetString[ i ] & 0xFF ) << 16; | |||
bits6 = ( bits24 & 0x00FC0000 ) >> 18; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
bits6 = ( bits24 & 0x0003F000 ) >> 12; | |||
out[ outIndex++ ] = alphabet[ bits6 ]; | |||
// padding | |||
out[ outIndex++ ] = '='; | |||
out[ outIndex++ ] = '='; | |||
} | |||
return new String( out ); | |||
} | |||
} | |||
} |
@@ -1,235 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Argument; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.CommandlineJava; | |||
import org.apache.tools.todo.types.EnvironmentVariable; | |||
import org.apache.tools.todo.types.Path; | |||
/** | |||
* This task acts as a loader for java applications but allows to use the same | |||
* JVM for the called application thus resulting in much faster operation. | |||
* | |||
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org"> | |||
* stefano@apache.org</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class Java | |||
extends AbstractTask | |||
{ | |||
private CommandlineJava m_cmdl = new CommandlineJava(); | |||
private boolean m_fork; | |||
private File m_dir; | |||
/** | |||
* Set the class name. | |||
*/ | |||
public void setClassname( String s ) | |||
{ | |||
m_cmdl.setClassname( s ); | |||
} | |||
/** | |||
* Add a classpath element. | |||
*/ | |||
public void addClasspath( final Path classpath ) | |||
throws TaskException | |||
{ | |||
m_cmdl.createClasspath().addPath( classpath ); | |||
} | |||
/** | |||
* The working directory of the process | |||
* | |||
* @param dir The new Dir value | |||
*/ | |||
public void setDir( final File dir ) | |||
{ | |||
m_dir = dir; | |||
} | |||
/** | |||
* Set the forking flag. | |||
*/ | |||
public void setFork( final boolean fork ) | |||
{ | |||
m_fork = fork; | |||
} | |||
/** | |||
* set the jar name... | |||
*/ | |||
public void setJar( final File jar ) | |||
{ | |||
m_cmdl.setJar( jar.getAbsolutePath() ); | |||
} | |||
/** | |||
* Set the command used to start the VM (only if fork==false). | |||
*/ | |||
public void setJvm( final String jvm ) | |||
{ | |||
m_cmdl.setVm( jvm ); | |||
} | |||
/** | |||
* -mx or -Xmx depending on VM version | |||
*/ | |||
public void setMaxmemory( final String max ) | |||
{ | |||
m_cmdl.setMaxmemory( max ); | |||
} | |||
/** | |||
* Add a nested sysproperty element. | |||
*/ | |||
public void addSysproperty( final EnvironmentVariable sysp ) | |||
{ | |||
m_cmdl.addSysproperty( sysp ); | |||
} | |||
/** | |||
* Creates a nested arg element. | |||
*/ | |||
public void addArg( final Argument argument ) | |||
{ | |||
m_cmdl.addArgument( argument ); | |||
} | |||
/** | |||
* Creates a nested jvmarg element. | |||
*/ | |||
public void addJvmarg( final Argument argument ) | |||
{ | |||
m_cmdl.addVmArgument( argument ); | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
final int err = executeJava(); | |||
if( 0 != err ) | |||
{ | |||
throw new TaskException( "Java returned: " + err ); | |||
} | |||
} | |||
/** | |||
* Do the execution and return a return code. | |||
* | |||
* @return the return code from the execute java class if it was executed in | |||
* a separate VM (fork = "yes"). | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public int executeJava() | |||
throws TaskException | |||
{ | |||
final String classname = m_cmdl.getClassname(); | |||
final String jar = m_cmdl.getJar(); | |||
if( classname != null && jar != null ) | |||
{ | |||
throw new TaskException( "Only one of Classname and Jar can be set." ); | |||
} | |||
else if( classname == null && jar == null ) | |||
{ | |||
throw new TaskException( "Classname must not be null." ); | |||
} | |||
if( !m_fork && jar != null ) | |||
{ | |||
throw new TaskException( "Cannot execute a jar in non-forked mode. Please set fork='true'. " ); | |||
} | |||
if( m_fork ) | |||
{ | |||
getContext().debug( "Forking " + m_cmdl.toString() ); | |||
return run( new Commandline( m_cmdl.getCommandline() ) ); | |||
} | |||
else | |||
{ | |||
if( m_cmdl.getVmCommand().size() > 1 ) | |||
{ | |||
getContext().warn( "JVM args ignored when same JVM is used." ); | |||
} | |||
if( m_dir != null ) | |||
{ | |||
getContext().warn( "Working directory ignored when same JVM is used." ); | |||
} | |||
getContext().debug( "Running in same VM " + m_cmdl.getJavaCommand().toString() ); | |||
run( m_cmdl ); | |||
return 0; | |||
} | |||
} | |||
/** | |||
* Executes the given classname with the given arguments as it was a command | |||
* line application. | |||
*/ | |||
protected void run( final String classname, final ArrayList args ) | |||
throws TaskException | |||
{ | |||
final CommandlineJava java = new CommandlineJava(); | |||
java.setClassname( classname ); | |||
final int size = args.size(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final String arg = (String)args.get( i ); | |||
java.addArgument( arg ); | |||
} | |||
run( java ); | |||
} | |||
/** | |||
* Executes the given classname with the given arguments as it was a command | |||
* line application. | |||
*/ | |||
private void run( final CommandlineJava command ) | |||
throws TaskException | |||
{ | |||
final ExecuteJava exe = new ExecuteJava(); | |||
exe.setJavaCommand( command.getJavaCommand() ); | |||
exe.setClasspath( command.getClasspath() ); | |||
exe.setSystemProperties( command.getSystemProperties() ); | |||
exe.execute(); | |||
} | |||
/** | |||
* Executes the given classname with the given arguments in a separate VM. | |||
*/ | |||
private int run( final Commandline command ) | |||
throws TaskException | |||
{ | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
if( m_dir == null ) | |||
{ | |||
m_dir = getBaseDirectory(); | |||
} | |||
else if( !m_dir.exists() || !m_dir.isDirectory() ) | |||
{ | |||
final String message = m_dir.getAbsolutePath() + " is not a valid directory"; | |||
throw new TaskException( message ); | |||
} | |||
exe.setWorkingDirectory( m_dir ); | |||
exe.setCommandline( command ); | |||
return exe.execute(); | |||
} | |||
} |
@@ -1,357 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.StringTokenizer; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.util.FileUtils; | |||
import org.apache.tools.todo.taskdefs.ClassArgument; | |||
/** | |||
* Task to generate JNI header files using javah. This task can take the | |||
* following arguments: | |||
* <ul> | |||
* <li> classname - the fully-qualified name of a class</li> | |||
* <li> outputFile - Concatenates the resulting header or source files for all | |||
* the classes listed into this file</li> | |||
* <li> destdir - Sets the directory where javah saves the header files or the | |||
* stub files</li> | |||
* <li> classpath</li> | |||
* <li> bootclasspath</li> | |||
* <li> force - Specifies that output files should always be written (JDK1.2 | |||
* only)</li> | |||
* <li> old - Specifies that old JDK1.0-style header files should be generated | |||
* (otherwise output file contain JNI-style native method function prototypes) | |||
* (JDK1.2 only)</li> | |||
* <li> stubs - generate C declarations from the Java object file (used with | |||
* old)</li> | |||
* <li> verbose - causes javah to print a message to stdout concerning the | |||
* status of the generated files</li> | |||
* <li> extdirs - Override location of installed extensions</li> | |||
* </ul> | |||
* Of these arguments, either <b>outputFile</b> or <b>destdir</b> is required, | |||
* but not both. More than one classname may be specified, using a | |||
* comma-separated list or by using <code><class name="xxx"></code> | |||
* elements within the task. <p> | |||
* | |||
* When this task executes, it will generate C header and source files that are | |||
* needed to implement native methods. | |||
* | |||
* @author Rick Beton <a href="mailto:richard.beton@physics.org"> | |||
* richard.beton@physics.org</a> | |||
*/ | |||
public class Javah | |||
extends AbstractTask | |||
{ | |||
private final static String FAIL_MSG = "Compile failed, messages should have been provided."; | |||
private ArrayList m_classes = new ArrayList( 2 ); | |||
private Path m_classpath; | |||
private File m_outputFile; | |||
private boolean m_verbose; | |||
private boolean m_force; | |||
private boolean m_old; | |||
private boolean m_stubs; | |||
private Path m_bootclasspath; | |||
private String m_cls; | |||
private File m_destDir; | |||
/** | |||
* Adds an element to the bootclasspath. | |||
*/ | |||
public void addBootclasspath( final Path bootclasspath ) | |||
{ | |||
if( m_bootclasspath == null ) | |||
{ | |||
m_bootclasspath = bootclasspath; | |||
} | |||
else | |||
{ | |||
m_bootclasspath.addPath( bootclasspath ); | |||
} | |||
} | |||
public void setClass( final String cls ) | |||
{ | |||
m_cls = cls; | |||
} | |||
/** | |||
* Adds an element to the classpath. | |||
*/ | |||
public void addClasspath( final Path classpath ) | |||
throws TaskException | |||
{ | |||
if( m_classpath == null ) | |||
{ | |||
m_classpath = classpath; | |||
} | |||
else | |||
{ | |||
m_classpath.addPath( classpath ); | |||
} | |||
} | |||
/** | |||
* Set the destination directory into which the Java source files should be | |||
* compiled. | |||
* | |||
* @param destDir The new Destdir value | |||
*/ | |||
public void setDestdir( final File destDir ) | |||
{ | |||
m_destDir = destDir; | |||
} | |||
/** | |||
* Set the force-write flag. | |||
*/ | |||
public void setForce( final boolean force ) | |||
{ | |||
m_force = force; | |||
} | |||
/** | |||
* Set the old flag. | |||
*/ | |||
public void setOld( final boolean old ) | |||
{ | |||
m_old = old; | |||
} | |||
/** | |||
* Set the output file name. | |||
*/ | |||
public void setOutputFile( final File outputFile ) | |||
{ | |||
m_outputFile = outputFile; | |||
} | |||
/** | |||
* Set the stubs flag. | |||
*/ | |||
public void setStubs( final boolean stubs ) | |||
{ | |||
m_stubs = stubs; | |||
} | |||
/** | |||
* Set the verbose flag. | |||
*/ | |||
public void setVerbose( final boolean verbose ) | |||
{ | |||
m_verbose = verbose; | |||
} | |||
public ClassArgument createClass() | |||
{ | |||
final ClassArgument ga = new ClassArgument(); | |||
m_classes.add( ga ); | |||
return ga; | |||
} | |||
/** | |||
* Executes the task. | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
validate(); | |||
doClassicCompile(); | |||
} | |||
private void validate() throws TaskException | |||
{ | |||
if( ( m_cls == null ) && ( m_classes.size() == 0 ) ) | |||
{ | |||
final String message = "class attribute must be set!"; | |||
throw new TaskException( message ); | |||
} | |||
if( ( m_cls != null ) && ( m_classes.size() > 0 ) ) | |||
{ | |||
final String message = "set class attribute or class element, not both."; | |||
throw new TaskException( message ); | |||
} | |||
if( m_destDir != null ) | |||
{ | |||
if( !m_destDir.isDirectory() ) | |||
{ | |||
final String message = "destination directory \"" + m_destDir + | |||
"\" does not exist or is not a directory"; | |||
throw new TaskException( message ); | |||
} | |||
if( m_outputFile != null ) | |||
{ | |||
final String message = "destdir and outputFile are mutually exclusive"; | |||
throw new TaskException( message ); | |||
} | |||
} | |||
} | |||
/** | |||
* Logs the compilation parameters, adds the files to compile and logs the | |||
* &qout;niceSourceList" | |||
*/ | |||
private void logAndAddFilesToCompile( final Commandline cmd ) | |||
{ | |||
int n = 0; | |||
getContext().debug( "Compilation args: " + cmd.toString() ); | |||
StringBuffer niceClassList = new StringBuffer(); | |||
if( m_cls != null ) | |||
{ | |||
final StringTokenizer tok = new StringTokenizer( m_cls, ",", false ); | |||
while( tok.hasMoreTokens() ) | |||
{ | |||
final String aClass = tok.nextToken().trim(); | |||
cmd.addArgument( aClass ); | |||
niceClassList.append( " " + aClass + StringUtil.LINE_SEPARATOR ); | |||
n++; | |||
} | |||
} | |||
final Iterator enum = m_classes.iterator(); | |||
while( enum.hasNext() ) | |||
{ | |||
final ClassArgument arg = (ClassArgument)enum.next(); | |||
final String aClass = arg.getName(); | |||
cmd.addArgument( aClass ); | |||
niceClassList.append( " " + aClass + StringUtil.LINE_SEPARATOR ); | |||
n++; | |||
} | |||
final StringBuffer prefix = new StringBuffer( "Class" ); | |||
if( n > 1 ) | |||
{ | |||
prefix.append( "es" ); | |||
} | |||
prefix.append( " to be compiled:" ); | |||
prefix.append( StringUtil.LINE_SEPARATOR ); | |||
getContext().debug( prefix.toString() + niceClassList.toString() ); | |||
} | |||
/** | |||
* Does the command line argument processing common to classic and modern. | |||
*/ | |||
private Commandline setupJavahCommand() | |||
throws TaskException | |||
{ | |||
final Commandline cmd = new Commandline(); | |||
if( m_destDir != null ) | |||
{ | |||
cmd.addArgument( "-d" ); | |||
cmd.addArgument( m_destDir ); | |||
} | |||
if( m_outputFile != null ) | |||
{ | |||
cmd.addArgument( "-o" ); | |||
cmd.addArgument( m_outputFile ); | |||
} | |||
if( m_classpath != null ) | |||
{ | |||
cmd.addArgument( "-classpath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( m_classpath ) ); | |||
} | |||
if( m_verbose ) | |||
{ | |||
cmd.addArgument( "-verbose" ); | |||
} | |||
if( m_old ) | |||
{ | |||
cmd.addArgument( "-old" ); | |||
} | |||
if( m_force ) | |||
{ | |||
cmd.addArgument( "-force" ); | |||
} | |||
if( m_stubs ) | |||
{ | |||
if( !m_old ) | |||
{ | |||
final String message = "stubs only available in old mode."; | |||
throw new TaskException( message ); | |||
} | |||
cmd.addArgument( "-stubs" ); | |||
} | |||
if( m_bootclasspath != null ) | |||
{ | |||
cmd.addArgument( "-bootclasspath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( m_bootclasspath ) ); | |||
} | |||
logAndAddFilesToCompile( cmd ); | |||
return cmd; | |||
} | |||
/** | |||
* Peforms a compile using the classic compiler that shipped with JDK 1.1 | |||
* and 1.2. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private void doClassicCompile() | |||
throws TaskException | |||
{ | |||
Commandline cmd = setupJavahCommand(); | |||
// Use reflection to be able to build on all JDKs | |||
/* | |||
* / provide the compiler a different message sink - namely our own | |||
* sun.tools.javac.Main compiler = | |||
* new sun.tools.javac.Main(new LogOutputStream(this, Project.MSG_WARN), "javac"); | |||
* if (!compiler.compile(cmd.getArguments())) { | |||
* throw new TaskException("Compile failed"); | |||
* } | |||
*/ | |||
try | |||
{ | |||
// Javac uses logstr to change the output stream and calls | |||
// the constructor's invoke method to create a compiler instance | |||
// dynamically. However, javah has a different interface and this | |||
// makes it harder, so here's a simple alternative. | |||
//------------------------------------------------------------------ | |||
com.sun.tools.javah.Main main = new com.sun.tools.javah.Main( cmd.getArguments() ); | |||
main.run(); | |||
} | |||
//catch (ClassNotFoundException ex) { | |||
// throw new TaskException("Cannot use javah because it is not available"+ | |||
// " A common solution is to set the environment variable"+ | |||
// " JAVA_HOME to your jdk directory.", location); | |||
//} | |||
catch( Exception ex ) | |||
{ | |||
if( ex instanceof TaskException ) | |||
{ | |||
throw (TaskException)ex; | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Error starting javah: ", ex ); | |||
} | |||
} | |||
} | |||
} | |||
@@ -1,101 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.Pattern; | |||
import org.apache.myrmidon.framework.PatternSet; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* This is an abstract task that should be used by all those tasks that require | |||
* to include or exclude files based on pattern matching. | |||
* | |||
* @author <a href="mailto:ajkuiper@wxs.nl">Arnout J. Kuiper</a> | |||
* @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> | |||
* @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a> | |||
* @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public abstract class MatchingTask | |||
extends AbstractTask | |||
{ | |||
private FileSet m_fileset = new FileSet(); | |||
/** | |||
* Sets whether default exclusions should be used or not. | |||
*/ | |||
public void setDefaultexcludes( final boolean useDefaultExcludes ) | |||
{ | |||
m_fileset.setDefaultExcludes( useDefaultExcludes ); | |||
} | |||
/** | |||
* Sets the set of exclude patterns. Patterns may be separated by a comma or | |||
* a space. | |||
* | |||
* @param excludes the string containing the exclude patterns | |||
*/ | |||
public void setExcludes( final String excludes ) | |||
{ | |||
m_fileset.setExcludes( excludes ); | |||
} | |||
/** | |||
* Sets the set of include patterns. Patterns may be separated by a comma or | |||
* a space. | |||
* | |||
* @param includes the string containing the include patterns | |||
*/ | |||
public void setIncludes( final String includes ) | |||
{ | |||
m_fileset.setIncludes( includes ); | |||
} | |||
/** | |||
* add a name entry on the exclude list | |||
*/ | |||
public void addExclude( final Pattern pattern ) | |||
{ | |||
m_fileset.addExclude( pattern ); | |||
} | |||
/** | |||
* add a name entry on the include list | |||
*/ | |||
public void addInclude( final Pattern pattern ) | |||
throws TaskException | |||
{ | |||
m_fileset.addInclude( pattern ); | |||
} | |||
/** | |||
* add a set of patterns | |||
*/ | |||
public void addPatternSet( final PatternSet set ) | |||
{ | |||
m_fileset.addPatternSet( set ); | |||
} | |||
/** | |||
* Returns the directory scanner needed to access the files to process. | |||
* | |||
* @param baseDir Description of Parameter | |||
* @return The DirectoryScanner value | |||
*/ | |||
protected DirectoryScanner getDirectoryScanner( final File baseDir ) | |||
throws TaskException | |||
{ | |||
m_fileset.setDir( baseDir ); | |||
return ScannerUtil.getDirectoryScanner( m_fileset ); | |||
} | |||
} |
@@ -1,770 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.PrintWriter; | |||
import java.io.StringWriter; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import java.util.Properties; | |||
import java.util.StringTokenizer; | |||
import netrexx.lang.Rexx; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
/** | |||
* Task to compile NetRexx source files. This task can take the following | |||
* arguments: | |||
* <ul> | |||
* <li> binary</li> | |||
* <li> classpath</li> | |||
* <li> comments</li> | |||
* <li> compile</li> | |||
* <li> console</li> | |||
* <li> crossref</li> | |||
* <li> decimal</li> | |||
* <li> destdir</li> | |||
* <li> diag</li> | |||
* <li> explicit</li> | |||
* <li> format</li> | |||
* <li> keep</li> | |||
* <li> logo</li> | |||
* <li> replace</li> | |||
* <li> savelog</li> | |||
* <li> srcdir</li> | |||
* <li> sourcedir</li> | |||
* <li> strictargs</li> | |||
* <li> strictassign</li> | |||
* <li> strictcase</li> | |||
* <li> strictimport</li> | |||
* <li> symbols</li> | |||
* <li> time</li> | |||
* <li> trace</li> | |||
* <li> utf8</li> | |||
* <li> verbose</li> | |||
* </ul> | |||
* Of these arguments, the <b>srcdir</b> argument is required. <p> | |||
* | |||
* When this task executes, it will recursively scan the srcdir looking for | |||
* NetRexx source files to compile. This task makes its compile decision based | |||
* on timestamp. <p> | |||
* | |||
* Before files are compiled they and any other file in the srcdir will be | |||
* copied to the destdir allowing support files to be located properly in the | |||
* classpath. The reason for copying the source files before the compile is that | |||
* NetRexxC has only two destinations for classfiles: | |||
* <ol> | |||
* <li> The current directory, and,</li> | |||
* <li> The directory the source is in (see sourcedir option) | |||
* </ol> | |||
* | |||
* | |||
* @author dIon Gillard <a href="mailto:dion@multitask.com.au"> | |||
* dion@multitask.com.au</a> | |||
*/ | |||
public class NetRexxC extends MatchingTask | |||
{ | |||
private boolean compile = true; | |||
private boolean decimal = true; | |||
private boolean logo = true; | |||
private boolean sourcedir = true; | |||
private String trace = "trace2"; | |||
private String verbose = "verbose3"; | |||
// other implementation variables | |||
private ArrayList compileList = new ArrayList(); | |||
private Hashtable filecopyList = new Hashtable(); | |||
private String oldClasspath = System.getProperty( "java.class.path" ); | |||
// variables to hold arguments | |||
private boolean binary; | |||
private String classpath; | |||
private boolean comments; | |||
private boolean compact; | |||
private boolean console; | |||
private boolean crossref; | |||
private File destDir; | |||
private boolean diag; | |||
private boolean explicit; | |||
private boolean format; | |||
private boolean java; | |||
private boolean keep; | |||
private boolean replace; | |||
private boolean savelog; | |||
private File srcDir;// ?? Should this be the default for ant? | |||
private boolean strictargs; | |||
private boolean strictassign; | |||
private boolean strictcase; | |||
private boolean strictimport; | |||
private boolean strictprops; | |||
private boolean strictsignal; | |||
private boolean symbols; | |||
private boolean time; | |||
private boolean utf8; | |||
/** | |||
* Set whether literals are treated as binary, rather than NetRexx types | |||
* | |||
* @param binary The new Binary value | |||
*/ | |||
public void setBinary( boolean binary ) | |||
{ | |||
this.binary = binary; | |||
} | |||
/** | |||
* Set the classpath used for NetRexx compilation | |||
* | |||
* @param classpath The new Classpath value | |||
*/ | |||
public void setClasspath( String classpath ) | |||
{ | |||
this.classpath = classpath; | |||
} | |||
/** | |||
* Set whether comments are passed through to the generated java source. | |||
* Valid true values are "on" or "true". Anything else sets the flag to | |||
* false. The default value is false | |||
* | |||
* @param comments The new Comments value | |||
*/ | |||
public void setComments( boolean comments ) | |||
{ | |||
this.comments = comments; | |||
} | |||
/** | |||
* Set whether error messages come out in compact or verbose format. Valid | |||
* true values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is false | |||
* | |||
* @param compact The new Compact value | |||
*/ | |||
public void setCompact( boolean compact ) | |||
{ | |||
this.compact = compact; | |||
} | |||
/** | |||
* Set whether the NetRexx compiler should compile the generated java code | |||
* Valid true values are "on" or "true". Anything else sets the flag to | |||
* false. The default value is true. Setting this flag to false, will | |||
* automatically set the keep flag to true. | |||
* | |||
* @param compile The new Compile value | |||
*/ | |||
public void setCompile( boolean compile ) | |||
{ | |||
this.compile = compile; | |||
if( !this.compile && !this.keep ) | |||
{ | |||
this.keep = true; | |||
} | |||
} | |||
/** | |||
* Set whether or not messages should be displayed on the 'console' Valid | |||
* true values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is true. | |||
* | |||
* @param console The new Console value | |||
*/ | |||
public void setConsole( boolean console ) | |||
{ | |||
this.console = console; | |||
} | |||
/** | |||
* Whether variable cross references are generated | |||
* | |||
* @param crossref The new Crossref value | |||
*/ | |||
public void setCrossref( boolean crossref ) | |||
{ | |||
this.crossref = crossref; | |||
} | |||
/** | |||
* Set whether decimal arithmetic should be used for the netrexx code. | |||
* Binary arithmetic is used when this flag is turned off. Valid true values | |||
* are "on" or "true". Anything else sets the flag to false. The default | |||
* value is true. | |||
* | |||
* @param decimal The new Decimal value | |||
*/ | |||
public void setDecimal( boolean decimal ) | |||
{ | |||
this.decimal = decimal; | |||
} | |||
/** | |||
* Set the destination directory into which the NetRexx source files should | |||
* be copied and then compiled. | |||
* | |||
* @param destDirName The new DestDir value | |||
*/ | |||
public void setDestDir( File destDirName ) | |||
{ | |||
destDir = destDirName; | |||
} | |||
/** | |||
* Whether diagnostic information about the compile is generated | |||
* | |||
* @param diag The new Diag value | |||
*/ | |||
public void setDiag( boolean diag ) | |||
{ | |||
this.diag = diag; | |||
} | |||
/** | |||
* Sets whether variables must be declared explicitly before use. Valid true | |||
* values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is false. | |||
* | |||
* @param explicit The new Explicit value | |||
*/ | |||
public void setExplicit( boolean explicit ) | |||
{ | |||
this.explicit = explicit; | |||
} | |||
/** | |||
* Whether the generated java code is formatted nicely or left to match | |||
* NetRexx line numbers for call stack debugging | |||
* | |||
* @param format The new Format value | |||
*/ | |||
public void setFormat( boolean format ) | |||
{ | |||
this.format = format; | |||
} | |||
/** | |||
* Whether the generated java code is produced Valid true values are "on" or | |||
* "true". Anything else sets the flag to false. The default value is false. | |||
* | |||
* @param java The new Java value | |||
*/ | |||
public void setJava( boolean java ) | |||
{ | |||
this.java = java; | |||
} | |||
/** | |||
* Sets whether the generated java source file should be kept after | |||
* compilation. The generated files will have an extension of .java.keep, | |||
* <b>not</b> .java Valid true values are "on" or "true". Anything else sets | |||
* the flag to false. The default value is false. | |||
* | |||
* @param keep The new Keep value | |||
*/ | |||
public void setKeep( boolean keep ) | |||
{ | |||
this.keep = keep; | |||
} | |||
/** | |||
* Whether the compiler text logo is displayed when compiling | |||
* | |||
* @param logo The new Logo value | |||
*/ | |||
public void setLogo( boolean logo ) | |||
{ | |||
this.logo = logo; | |||
} | |||
/** | |||
* Whether the generated .java file should be replaced when compiling Valid | |||
* true values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is false. | |||
* | |||
* @param replace The new Replace value | |||
*/ | |||
public void setReplace( boolean replace ) | |||
{ | |||
this.replace = replace; | |||
} | |||
/** | |||
* Sets whether the compiler messages will be written to NetRexxC.log as | |||
* well as to the console Valid true values are "on" or "true". Anything | |||
* else sets the flag to false. The default value is false. | |||
* | |||
* @param savelog The new Savelog value | |||
*/ | |||
public void setSavelog( boolean savelog ) | |||
{ | |||
this.savelog = savelog; | |||
} | |||
/** | |||
* Tells the NetRexx compiler to store the class files in the same directory | |||
* as the source files. The alternative is the working directory Valid true | |||
* values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is true. | |||
* | |||
* @param sourcedir The new Sourcedir value | |||
*/ | |||
public void setSourcedir( boolean sourcedir ) | |||
{ | |||
this.sourcedir = sourcedir; | |||
} | |||
/** | |||
* Set the source dir to find the source Java files. | |||
* | |||
* @param srcDirName The new SrcDir value | |||
*/ | |||
public void setSrcDir( File srcDirName ) | |||
{ | |||
srcDir = srcDirName; | |||
} | |||
/** | |||
* Tells the NetRexx compiler that method calls always need parentheses, | |||
* even if no arguments are needed, e.g. <code>aStringVar.getBytes</code> | |||
* vs. <code>aStringVar.getBytes()</code> Valid true values are "on" or | |||
* "true". Anything else sets the flag to false. The default value is false. | |||
* | |||
* @param strictargs The new Strictargs value | |||
*/ | |||
public void setStrictargs( boolean strictargs ) | |||
{ | |||
this.strictargs = strictargs; | |||
} | |||
/** | |||
* Tells the NetRexx compile that assignments must match exactly on type | |||
* | |||
* @param strictassign The new Strictassign value | |||
*/ | |||
public void setStrictassign( boolean strictassign ) | |||
{ | |||
this.strictassign = strictassign; | |||
} | |||
/** | |||
* Specifies whether the NetRexx compiler should be case sensitive or not | |||
* | |||
* @param strictcase The new Strictcase value | |||
*/ | |||
public void setStrictcase( boolean strictcase ) | |||
{ | |||
this.strictcase = strictcase; | |||
} | |||
/** | |||
* Sets whether classes need to be imported explicitly using an <code>import</code> | |||
* statement. By default the NetRexx compiler will import certain packages | |||
* automatically Valid true values are "on" or "true". Anything else sets | |||
* the flag to false. The default value is false. | |||
* | |||
* @param strictimport The new Strictimport value | |||
*/ | |||
public void setStrictimport( boolean strictimport ) | |||
{ | |||
this.strictimport = strictimport; | |||
} | |||
/** | |||
* Sets whether local properties need to be qualified explicitly using | |||
* <code>this</code> Valid true values are "on" or "true". Anything else | |||
* sets the flag to false. The default value is false. | |||
* | |||
* @param strictprops The new Strictprops value | |||
*/ | |||
public void setStrictprops( boolean strictprops ) | |||
{ | |||
this.strictprops = strictprops; | |||
} | |||
/** | |||
* Whether the compiler should force catching of exceptions by explicitly | |||
* named types | |||
* | |||
* @param strictsignal The new Strictsignal value | |||
*/ | |||
public void setStrictsignal( boolean strictsignal ) | |||
{ | |||
this.strictsignal = strictsignal; | |||
} | |||
/** | |||
* Sets whether debug symbols should be generated into the class file Valid | |||
* true values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is false. | |||
* | |||
* @param symbols The new Symbols value | |||
*/ | |||
public void setSymbols( boolean symbols ) | |||
{ | |||
this.symbols = symbols; | |||
} | |||
/** | |||
* Asks the NetRexx compiler to print compilation times to the console Valid | |||
* true values are "on" or "true". Anything else sets the flag to false. The | |||
* default value is false. | |||
* | |||
* @param time The new Time value | |||
*/ | |||
public void setTime( boolean time ) | |||
{ | |||
this.time = time; | |||
} | |||
/** | |||
* Turns on or off tracing and directs the resultant trace output Valid | |||
* values are: "trace", "trace1", "trace2" and "notrace". "trace" and | |||
* "trace2" | |||
* | |||
* @param trace The new Trace value | |||
*/ | |||
public void setTrace( String trace ) | |||
{ | |||
if( trace.equalsIgnoreCase( "trace" ) | |||
|| trace.equalsIgnoreCase( "trace1" ) | |||
|| trace.equalsIgnoreCase( "trace2" ) | |||
|| trace.equalsIgnoreCase( "notrace" ) ) | |||
{ | |||
this.trace = trace; | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Unknown trace value specified: '" + trace + "'" ); | |||
} | |||
} | |||
/** | |||
* Tells the NetRexx compiler that the source is in UTF8 Valid true values | |||
* are "on" or "true". Anything else sets the flag to false. The default | |||
* value is false. | |||
* | |||
* @param utf8 The new Utf8 value | |||
*/ | |||
public void setUtf8( boolean utf8 ) | |||
{ | |||
this.utf8 = utf8; | |||
} | |||
/** | |||
* Whether lots of warnings and error messages should be generated | |||
* | |||
* @param verbose The new Verbose value | |||
*/ | |||
public void setVerbose( String verbose ) | |||
{ | |||
this.verbose = verbose; | |||
} | |||
/** | |||
* Executes the task, i.e. does the actual compiler call | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
// first off, make sure that we've got a srcdir and destdir | |||
if( srcDir == null || destDir == null ) | |||
{ | |||
throw new TaskException( "srcDir and destDir attributes must be set!" ); | |||
} | |||
// scan source and dest dirs to build up both copy lists and | |||
// compile lists | |||
// scanDir(srcDir, destDir); | |||
DirectoryScanner ds = getDirectoryScanner( srcDir ); | |||
String[] files = ds.getIncludedFiles(); | |||
scanDir( srcDir, destDir, files ); | |||
// copy the source and support files | |||
copyFilesToDestination(); | |||
// compile the source files | |||
if( compileList.size() > 0 ) | |||
{ | |||
getContext().info( "Compiling " + compileList.size() + " source file" | |||
+ ( compileList.size() == 1 ? "" : "s" ) | |||
+ " to " + destDir ); | |||
doNetRexxCompile(); | |||
} | |||
} | |||
/** | |||
* Builds the compilation classpath. | |||
* | |||
* @return The CompileClasspath value | |||
*/ | |||
private String getCompileClasspath() | |||
throws TaskException | |||
{ | |||
StringBuffer classpath = new StringBuffer(); | |||
// add dest dir to classpath so that previously compiled and | |||
// untouched classes are on classpath | |||
classpath.append( destDir.getAbsolutePath() ); | |||
// add our classpath to the mix | |||
if( this.classpath != null ) | |||
{ | |||
addExistingToClasspath( classpath, this.classpath ); | |||
} | |||
// add the system classpath | |||
// addExistingToClasspath(classpath,System.getProperty("java.class.path")); | |||
return classpath.toString(); | |||
} | |||
/** | |||
* This | |||
* | |||
* @return The CompileOptionsAsArray value | |||
*/ | |||
private String[] getCompileOptionsAsArray() | |||
{ | |||
ArrayList options = new ArrayList(); | |||
options.add( binary ? "-binary" : "-nobinary" ); | |||
options.add( comments ? "-comments" : "-nocomments" ); | |||
options.add( compile ? "-compile" : "-nocompile" ); | |||
options.add( compact ? "-compact" : "-nocompact" ); | |||
options.add( console ? "-console" : "-noconsole" ); | |||
options.add( crossref ? "-crossref" : "-nocrossref" ); | |||
options.add( decimal ? "-decimal" : "-nodecimal" ); | |||
options.add( diag ? "-diag" : "-nodiag" ); | |||
options.add( explicit ? "-explicit" : "-noexplicit" ); | |||
options.add( format ? "-format" : "-noformat" ); | |||
options.add( keep ? "-keep" : "-nokeep" ); | |||
options.add( logo ? "-logo" : "-nologo" ); | |||
options.add( replace ? "-replace" : "-noreplace" ); | |||
options.add( savelog ? "-savelog" : "-nosavelog" ); | |||
options.add( sourcedir ? "-sourcedir" : "-nosourcedir" ); | |||
options.add( strictargs ? "-strictargs" : "-nostrictargs" ); | |||
options.add( strictassign ? "-strictassign" : "-nostrictassign" ); | |||
options.add( strictcase ? "-strictcase" : "-nostrictcase" ); | |||
options.add( strictimport ? "-strictimport" : "-nostrictimport" ); | |||
options.add( strictprops ? "-strictprops" : "-nostrictprops" ); | |||
options.add( strictsignal ? "-strictsignal" : "-nostrictsignal" ); | |||
options.add( symbols ? "-symbols" : "-nosymbols" ); | |||
options.add( time ? "-time" : "-notime" ); | |||
options.add( "-" + trace ); | |||
options.add( utf8 ? "-utf8" : "-noutf8" ); | |||
options.add( "-" + verbose ); | |||
String[] results = new String[ options.size() ]; | |||
options.copyInto( results ); | |||
return results; | |||
} | |||
/** | |||
* Takes a classpath-like string, and adds each element of this string to a | |||
* new classpath, if the components exist. Components that don't exist, | |||
* aren't added. We do this, because jikes issues warnings for non-existant | |||
* files/dirs in his classpath, and these warnings are pretty annoying. | |||
* | |||
* @param target - target classpath | |||
* @param source - source classpath to get file objects. | |||
*/ | |||
private void addExistingToClasspath( StringBuffer target, String source ) | |||
throws TaskException | |||
{ | |||
final StringTokenizer tok = new StringTokenizer( source, | |||
System.getProperty( "path.separator" ), false ); | |||
while( tok.hasMoreTokens() ) | |||
{ | |||
File f = getContext().resolveFile( tok.nextToken() ); | |||
if( f.exists() ) | |||
{ | |||
target.append( File.pathSeparator ); | |||
target.append( f.getAbsolutePath() ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "Dropping from classpath: " + f.getAbsolutePath() ); | |||
} | |||
} | |||
} | |||
/** | |||
* Copy eligible files from the srcDir to destDir | |||
*/ | |||
private void copyFilesToDestination() | |||
{ | |||
//FIXME: This should be zapped no ? | |||
if( filecopyList.size() > 0 ) | |||
{ | |||
getContext().info( "Copying " + filecopyList.size() + " file" | |||
+ ( filecopyList.size() == 1 ? "" : "s" ) | |||
+ " to " + destDir.getAbsolutePath() ); | |||
Iterator enum = filecopyList.keySet().iterator(); | |||
while( enum.hasNext() ) | |||
{ | |||
String fromFile = (String)enum.next(); | |||
String toFile = (String)filecopyList.get( fromFile ); | |||
try | |||
{ | |||
FileUtil.copyFile( new File( fromFile ), new File( toFile ) ); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
String msg = "Failed to copy " + fromFile + " to " + toFile | |||
+ " due to " + ioe.getMessage(); | |||
throw new TaskException( msg, ioe ); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Peforms a copmile using the NetRexx 1.1.x compiler | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
private void doNetRexxCompile() | |||
throws TaskException | |||
{ | |||
getContext().debug( "Using NetRexx compiler" ); | |||
String classpath = getCompileClasspath(); | |||
StringBuffer compileOptions = new StringBuffer(); | |||
StringBuffer fileList = new StringBuffer(); | |||
// create an array of strings for input to the compiler: one array | |||
// comes from the compile options, the other from the compileList | |||
String[] compileOptionsArray = getCompileOptionsAsArray(); | |||
String[] fileListArray = new String[ compileList.size() ]; | |||
Iterator e = compileList.iterator(); | |||
int j = 0; | |||
while( e.hasNext() ) | |||
{ | |||
fileListArray[ j ] = (String)e.next(); | |||
j++; | |||
} | |||
// create a single array of arguments for the compiler | |||
String compileArgs[] = new String[ compileOptionsArray.length + fileListArray.length ]; | |||
for( int i = 0; i < compileOptionsArray.length; i++ ) | |||
{ | |||
compileArgs[ i ] = compileOptionsArray[ i ]; | |||
} | |||
for( int i = 0; i < fileListArray.length; i++ ) | |||
{ | |||
compileArgs[ i + compileOptionsArray.length ] = fileListArray[ i ]; | |||
} | |||
// print nice output about what we are doing for the log | |||
compileOptions.append( "Compilation args: " ); | |||
for( int i = 0; i < compileOptionsArray.length; i++ ) | |||
{ | |||
compileOptions.append( compileOptionsArray[ i ] ); | |||
compileOptions.append( " " ); | |||
} | |||
getContext().debug( compileOptions.toString() ); | |||
StringBuffer niceSourceList = new StringBuffer( "Files to be compiled:" + StringUtil.LINE_SEPARATOR ); | |||
for( int i = 0; i < compileList.size(); i++ ) | |||
{ | |||
niceSourceList.append( " " ); | |||
niceSourceList.append( compileList.get( i ).toString() ); | |||
niceSourceList.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
getContext().debug( niceSourceList.toString() ); | |||
// need to set java.class.path property and restore it later | |||
// since the NetRexx compiler has no option for the classpath | |||
String currentClassPath = System.getProperty( "java.class.path" ); | |||
Properties currentProperties = System.getProperties(); | |||
currentProperties.put( "java.class.path", classpath ); | |||
try | |||
{ | |||
StringWriter out = new StringWriter(); | |||
int rc = | |||
COM.ibm.netrexx.process.NetRexxC.main( new Rexx( compileArgs ), new PrintWriter( out ) ); | |||
if( rc > 1 ) | |||
{// 1 is warnings from real NetRexxC | |||
getContext().error( out.toString() ); | |||
String msg = "Compile failed, messages should have been provided."; | |||
throw new TaskException( msg ); | |||
} | |||
else if( rc == 1 ) | |||
{ | |||
getContext().warn( out.toString() ); | |||
} | |||
else | |||
{ | |||
getContext().info( out.toString() ); | |||
} | |||
} | |||
finally | |||
{ | |||
// need to reset java.class.path property | |||
// since the NetRexx compiler has no option for the classpath | |||
currentProperties = System.getProperties(); | |||
currentProperties.put( "java.class.path", currentClassPath ); | |||
} | |||
} | |||
/** | |||
* Scans the directory looking for source files to be compiled and support | |||
* files to be copied. | |||
* | |||
* @param srcDir Description of Parameter | |||
* @param destDir Description of Parameter | |||
* @param files Description of Parameter | |||
*/ | |||
private void scanDir( File srcDir, File destDir, String[] files ) | |||
{ | |||
for( int i = 0; i < files.length; i++ ) | |||
{ | |||
File srcFile = new File( srcDir, files[ i ] ); | |||
File destFile = new File( destDir, files[ i ] ); | |||
String filename = files[ i ]; | |||
// if it's a non source file, copy it if a later date than the | |||
// dest | |||
// if it's a source file, see if the destination class file | |||
// needs to be recreated via compilation | |||
if( filename.toLowerCase().endsWith( ".nrx" ) ) | |||
{ | |||
File classFile = | |||
new File( destDir, | |||
filename.substring( 0, filename.lastIndexOf( '.' ) ) + ".class" ); | |||
if( !compile || srcFile.lastModified() > classFile.lastModified() ) | |||
{ | |||
filecopyList.put( srcFile.getAbsolutePath(), destFile.getAbsolutePath() ); | |||
compileList.add( destFile.getAbsolutePath() ); | |||
} | |||
} | |||
else | |||
{ | |||
if( srcFile.lastModified() > destFile.lastModified() ) | |||
{ | |||
filecopyList.put( srcFile.getAbsolutePath(), destFile.getAbsolutePath() ); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,324 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import org.apache.aut.nativelib.Os; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Path; | |||
/** | |||
* This task converts path and classpath information to a specific target OS | |||
* format. The resulting formatted path is placed into a specified property. <p> | |||
* | |||
* LIMITATION: Currently this implementation groups all machines into one of two | |||
* types: Unix or Windows. Unix is defined as NOT windows. | |||
* | |||
* @author Larry Streepy <a href="mailto:streepy@healthlanguage.com"> | |||
* streepy@healthlanguage.com</a> | |||
*/ | |||
public class PathConvert extends AbstractTask | |||
{ | |||
private Path m_path;// Path to be converted | |||
private String m_targetOS;// The target OS type | |||
private boolean m_targetWindows;// Set when targetOS is set | |||
private boolean m_onWindows;// Set if we're running on windows | |||
private String m_property;// The property to receive the results | |||
private ArrayList m_prefixMap = new ArrayList();// Path prefix map | |||
private String m_pathSep;// User override on path sep char | |||
private String m_dirSep; | |||
/** | |||
* Override the default directory separator string for the target os | |||
*/ | |||
public void setDirSep( final String dirSep ) | |||
{ | |||
m_dirSep = dirSep; | |||
} | |||
/** | |||
* Override the default path separator string for the target os | |||
* | |||
* @param pathSep The new PathSep value | |||
*/ | |||
public void setPathSep( final String pathSep ) | |||
{ | |||
m_pathSep = pathSep; | |||
} | |||
/** | |||
* Set the value of the proprty attribute - this is the property into which | |||
* our converted path will be placed. | |||
*/ | |||
public void setProperty( final String property ) | |||
{ | |||
m_property = property; | |||
} | |||
/** | |||
* Set the value of the targetos attribute | |||
* | |||
* @param targetOS The new Targetos value | |||
*/ | |||
public void setTargetos( String targetOS ) | |||
throws TaskException | |||
{ | |||
m_targetOS = targetOS.toLowerCase(); | |||
if( !m_targetOS.equals( "windows" ) && !targetOS.equals( "unix" ) && | |||
!m_targetOS.equals( "netware" ) ) | |||
{ | |||
throw new TaskException( "targetos must be one of 'unix', 'netware', or 'windows'" ); | |||
} | |||
// Currently, we deal with only two path formats: Unix and Windows | |||
// And Unix is everything that is not Windows | |||
// for NetWare, piggy-back on Windows, since in the validateSetup code, | |||
// the same assumptions can be made as with windows - | |||
// that ; is the path separator | |||
m_targetWindows = ( m_targetOS.equals( "windows" ) || m_targetOS.equals( "netware" ) ); | |||
} | |||
/** | |||
* Create a nested MAP element | |||
*/ | |||
public void addMap( final MapEntry entry ) | |||
{ | |||
m_prefixMap.add( entry ); | |||
} | |||
/** | |||
* Adds a PATH element | |||
*/ | |||
public void addPath( Path path ) | |||
throws TaskException | |||
{ | |||
if( m_path == null ) | |||
{ | |||
m_path = path; | |||
} | |||
else | |||
{ | |||
m_path.addPath( path ); | |||
} | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
// If we are a reference, the create a Path from the reference | |||
validate();// validate our setup | |||
// Currently, we deal with only two path formats: Unix and Windows | |||
// And Unix is everything that is not Windows | |||
// (with the exception for NetWare below) | |||
// for NetWare, piggy-back on Windows, since here and in the | |||
// apply code, the same assumptions can be made as with windows - | |||
// that \\ is an OK separator, and do comparisons case-insensitive. | |||
m_onWindows = ( Os.isFamily( Os.OS_FAMILY_WINDOWS ) || Os.isFamily( Os.OS_FAMILY_NETWARE ) ); | |||
// Determine the from/to char mappings for dir sep | |||
char fromDirSep = m_onWindows ? '\\' : '/'; | |||
char toDirSep = m_dirSep.charAt( 0 ); | |||
StringBuffer rslt = new StringBuffer( 100 ); | |||
// Get the list of path components in canonical form | |||
String[] elems = m_path.list(); | |||
for( int i = 0; i < elems.length; i++ ) | |||
{ | |||
String elem = elems[ i ]; | |||
elem = mapElement( elem );// Apply the path prefix map | |||
// Now convert the path and file separator characters from the | |||
// current os to the target os. | |||
elem = elem.replace( fromDirSep, toDirSep ); | |||
if( i != 0 ) | |||
{ | |||
rslt.append( m_pathSep ); | |||
} | |||
rslt.append( elem ); | |||
} | |||
// Place the result into the specified property | |||
final String value = rslt.toString(); | |||
getContext().debug( "Set property " + m_property + " = " + value ); | |||
final String name = m_property; | |||
getContext().setProperty( name, value ); | |||
} | |||
/** | |||
* Apply the configured map to a path element. The map is used to convert | |||
* between Windows drive letters and Unix paths. If no map is configured, | |||
* then the input string is returned unchanged. | |||
* | |||
* @param elem The path element to apply the map to | |||
* @return String Updated element | |||
*/ | |||
private String mapElement( String elem ) | |||
throws TaskException | |||
{ | |||
int size = m_prefixMap.size(); | |||
if( size != 0 ) | |||
{ | |||
// Iterate over the map entries and apply each one. Stop when one of the | |||
// entries actually changes the element | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
MapEntry entry = (MapEntry)m_prefixMap.get( i ); | |||
String newElem = entry.apply( elem ); | |||
// Note I'm using "!=" to see if we got a new object back from | |||
// the apply method. | |||
if( newElem != elem ) | |||
{ | |||
elem = newElem; | |||
break;// We applied one, so we're done | |||
} | |||
} | |||
} | |||
return elem; | |||
} | |||
/** | |||
* Validate that all our parameters have been properly initialized. | |||
* | |||
* @throws org.apache.myrmidon.api.TaskException if something is not setup properly | |||
*/ | |||
private void validate() | |||
throws TaskException | |||
{ | |||
if( m_path == null ) | |||
{ | |||
throw new TaskException( "You must specify a path to convert" ); | |||
} | |||
if( m_property == null ) | |||
{ | |||
throw new TaskException( "You must specify a property" ); | |||
} | |||
// Must either have a target OS or both a dirSep and pathSep | |||
if( m_targetOS == null && m_pathSep == null && m_dirSep == null ) | |||
{ | |||
throw new TaskException( "You must specify at least one of targetOS, dirSep, or pathSep" ); | |||
} | |||
// Determine the separator strings. The dirsep and pathsep attributes | |||
// override the targetOS settings. | |||
String dsep = File.separator; | |||
String psep = File.pathSeparator; | |||
if( m_targetOS != null ) | |||
{ | |||
psep = m_targetWindows ? ";" : ":"; | |||
dsep = m_targetWindows ? "\\" : "/"; | |||
} | |||
if( m_pathSep != null ) | |||
{// override with pathsep= | |||
psep = m_pathSep; | |||
} | |||
if( m_dirSep != null ) | |||
{// override with dirsep= | |||
dsep = m_dirSep; | |||
} | |||
m_pathSep = psep; | |||
m_dirSep = dsep; | |||
} | |||
/** | |||
* Helper class, holds the nested <map> values. Elements will look like | |||
* this: <map from="d:" to="/foo"/> <p> | |||
* | |||
* When running on windows, the prefix comparison will be case insensitive. | |||
*/ | |||
public class MapEntry | |||
{ | |||
private String m_from; | |||
private String m_to; | |||
/** | |||
* Set the "from" attribute of the map entry | |||
* | |||
* @param from The new From value | |||
*/ | |||
public void setFrom( final String from ) | |||
{ | |||
m_from = from; | |||
} | |||
/** | |||
* Set the "to" attribute of the map entry | |||
* | |||
* @param to The new To value | |||
*/ | |||
public void setTo( final String to ) | |||
{ | |||
m_to = to; | |||
} | |||
/** | |||
* Apply this map entry to a given path element | |||
* | |||
* @param elem Path element to process | |||
* @return String Updated path element after mapping | |||
*/ | |||
public String apply( String elem ) | |||
throws TaskException | |||
{ | |||
if( m_from == null || m_to == null ) | |||
{ | |||
throw new TaskException( "Both 'from' and 'to' must be set in a map entry" ); | |||
} | |||
// If we're on windows, then do the comparison ignoring case | |||
final String cmpElem = m_onWindows ? elem.toLowerCase() : elem; | |||
final String cmpFrom = m_onWindows ? m_from.toLowerCase() : m_from; | |||
// If the element starts with the configured prefix, then convert the prefix | |||
// to the configured 'to' value. | |||
if( cmpElem.startsWith( cmpFrom ) ) | |||
{ | |||
final int len = m_from.length(); | |||
if( len >= elem.length() ) | |||
{ | |||
elem = m_to; | |||
} | |||
else | |||
{ | |||
elem = m_to + elem.substring( len ); | |||
} | |||
} | |||
return elem; | |||
} | |||
} | |||
} |
@@ -1,161 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.util.Iterator; | |||
import java.util.Properties; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
/** | |||
* Will set a Project property. Used to be a hack in ProjectHelper Will not | |||
* override values set by the command line or parent projects. | |||
* | |||
* @author costin@dnt.ro | |||
* @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a> | |||
* @author <a href="mailto:glennm@ca.ibm.com">Glenn McAllister</a> | |||
*/ | |||
public class Property | |||
extends AbstractTask | |||
{ | |||
private Path m_classpath; | |||
private String m_name; | |||
private String m_resource; | |||
private String m_value; | |||
public void addClasspath( Path classpath ) | |||
throws TaskException | |||
{ | |||
if( m_classpath == null ) | |||
{ | |||
m_classpath = classpath; | |||
} | |||
else | |||
{ | |||
m_classpath.addPath( classpath ); | |||
} | |||
} | |||
public void setLocation( File location ) | |||
{ | |||
setValue( location.getAbsolutePath() ); | |||
} | |||
public void setName( String name ) | |||
{ | |||
m_name = name; | |||
} | |||
public void setResource( String resource ) | |||
{ | |||
m_resource = resource; | |||
} | |||
public void setValue( String value ) | |||
{ | |||
m_value = value; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
validate(); | |||
if( ( m_name != null ) && ( m_value != null ) ) | |||
{ | |||
final String name = m_name; | |||
final Object value = m_value; | |||
getContext().setProperty( name, value ); | |||
} | |||
if( m_resource != null ) | |||
{ | |||
loadResource( m_resource ); | |||
} | |||
} | |||
private void validate() throws TaskException | |||
{ | |||
if( m_name != null ) | |||
{ | |||
if( m_value == null ) | |||
{ | |||
throw new TaskException( "You must specify value, location or refid with the name attribute" ); | |||
} | |||
} | |||
else | |||
{ | |||
if( m_resource == null ) | |||
{ | |||
throw new TaskException( "You must specify resource when not using the name attribute" ); | |||
} | |||
} | |||
} | |||
public String toString() | |||
{ | |||
return m_value == null ? "" : m_value; | |||
} | |||
protected void addProperties( Properties props ) | |||
throws TaskException | |||
{ | |||
final Iterator e = props.keySet().iterator(); | |||
while( e.hasNext() ) | |||
{ | |||
final String name = (String)e.next(); | |||
final String value = (String)props.getProperty( name ); | |||
getContext().setProperty( name, value ); | |||
} | |||
} | |||
protected void loadResource( String name ) | |||
throws TaskException | |||
{ | |||
Properties props = new Properties(); | |||
getContext().debug( "Resource Loading " + name ); | |||
try | |||
{ | |||
ClassLoader classLoader = null; | |||
if( m_classpath != null ) | |||
{ | |||
final URL[] urls = PathUtil.toURLs( m_classpath ); | |||
classLoader = new URLClassLoader( urls ); | |||
} | |||
else | |||
{ | |||
classLoader = ClassLoader.getSystemClassLoader(); | |||
} | |||
final InputStream is = classLoader.getResourceAsStream( name ); | |||
if( is != null ) | |||
{ | |||
props.load( is ); | |||
addProperties( props ); | |||
} | |||
else | |||
{ | |||
getContext().warn( "Unable to find resource " + name ); | |||
} | |||
} | |||
catch( IOException ex ) | |||
{ | |||
throw new TaskException( "Error", ex ); | |||
} | |||
} | |||
} |
@@ -1,138 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* @author lucas@collab.net | |||
*/ | |||
public class Rpm | |||
extends AbstractTask | |||
{ | |||
/** | |||
* the rpm command to use | |||
*/ | |||
private String m_command = "-bb"; | |||
/** | |||
* clean BUILD directory | |||
*/ | |||
private boolean m_cleanBuildDir; | |||
/** | |||
* remove spec file | |||
*/ | |||
private boolean m_removeSpec; | |||
/** | |||
* remove sources | |||
*/ | |||
private boolean m_removeSource; | |||
/** | |||
* the spec file | |||
*/ | |||
private String m_specFile; | |||
/** | |||
* the rpm top dir | |||
*/ | |||
private File m_topDir; | |||
public void setCleanBuildDir( boolean cleanBuildDir ) | |||
{ | |||
m_cleanBuildDir = cleanBuildDir; | |||
} | |||
public void setCommand( final String command ) | |||
{ | |||
m_command = command; | |||
} | |||
public void setRemoveSource( final boolean removeSource ) | |||
{ | |||
m_removeSource = removeSource; | |||
} | |||
public void setRemoveSpec( final boolean removeSpec ) | |||
{ | |||
m_removeSpec = removeSpec; | |||
} | |||
public void setSpecFile( final String specFile ) | |||
throws TaskException | |||
{ | |||
if( ( specFile == null ) || ( specFile.trim().equals( "" ) ) ) | |||
{ | |||
throw new TaskException( "You must specify a spec file" ); | |||
} | |||
m_specFile = specFile; | |||
} | |||
public void setTopDir( final File topDir ) | |||
{ | |||
m_topDir = topDir; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
final Commandline cmd = createCommand(); | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
if( m_topDir == null ) | |||
{ | |||
m_topDir = getBaseDirectory(); | |||
} | |||
exe.setWorkingDirectory( m_topDir ); | |||
exe.setCommandline( cmd ); | |||
exe.setReturnCode( 0 ); | |||
final String message = "Building the RPM based on the " + m_specFile + " file"; | |||
getContext().info( message ); | |||
exe.execute(); | |||
} | |||
private Commandline createCommand() | |||
throws TaskException | |||
{ | |||
final Commandline cmd = new Commandline(); | |||
cmd.setExecutable( "rpm" ); | |||
if( m_topDir != null ) | |||
{ | |||
cmd.addArgument( "--define" ); | |||
cmd.addArgument( "_topdir" + m_topDir ); | |||
} | |||
cmd.addLine( m_command ); | |||
if( m_cleanBuildDir ) | |||
{ | |||
cmd.addArgument( "--clean" ); | |||
} | |||
if( m_removeSpec ) | |||
{ | |||
cmd.addArgument( "--rmspec" ); | |||
} | |||
if( m_removeSource ) | |||
{ | |||
cmd.addArgument( "--rmsource" ); | |||
} | |||
cmd.addArgument( "SPECS/" + m_specFile ); | |||
return cmd; | |||
} | |||
} |
@@ -1,858 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.BufferedOutputStream; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.io.PrintStream; | |||
import java.io.Reader; | |||
import java.io.StringReader; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.sql.Connection; | |||
import java.sql.DatabaseMetaData; | |||
import java.sql.Driver; | |||
import java.sql.ResultSet; | |||
import java.sql.ResultSetMetaData; | |||
import java.sql.SQLException; | |||
import java.sql.SQLWarning; | |||
import java.sql.Statement; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.Properties; | |||
import java.util.StringTokenizer; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* Reads in a text file containing SQL statements seperated with semicolons and | |||
* executes it in a given db. Comments may be created with REM -- or //. | |||
* | |||
* @author <a href="mailto:jeff@custommonkey.org">Jeff Martin</a> | |||
* @author <A href="mailto:gholam@xtra.co.nz">Michael McCallum</A> | |||
* @author <A href="mailto:tim.stephenson@sybase.com">Tim Stephenson</A> | |||
*/ | |||
public class SQLExec | |||
extends AbstractTask | |||
{ | |||
private int goodSql = 0, totalSql = 0; | |||
private ArrayList filesets = new ArrayList(); | |||
/** | |||
* Database connection | |||
*/ | |||
private Connection conn; | |||
/** | |||
* Autocommit flag. Default value is false | |||
*/ | |||
private boolean autocommit; | |||
/** | |||
* SQL statement | |||
*/ | |||
private Statement statement; | |||
/** | |||
* DB driver. | |||
*/ | |||
private String driver; | |||
/** | |||
* DB url. | |||
*/ | |||
private String url; | |||
/** | |||
* User name. | |||
*/ | |||
private String userId; | |||
/** | |||
* Password | |||
*/ | |||
private String password; | |||
/** | |||
* SQL input file | |||
*/ | |||
private File srcFile; | |||
/** | |||
* SQL input command | |||
*/ | |||
private String sqlCommand = ""; | |||
/** | |||
* SQL transactions to perform | |||
*/ | |||
private ArrayList transactions = new ArrayList(); | |||
/** | |||
* SQL Statement delimiter | |||
*/ | |||
private String delimiter = ";"; | |||
/** | |||
* The delimiter type indicating whether the delimiter will only be | |||
* recognized on a line by itself | |||
*/ | |||
private String delimiterType = DelimiterType.NORMAL; | |||
/** | |||
* Print SQL results. | |||
*/ | |||
private boolean print; | |||
/** | |||
* Print header columns. | |||
*/ | |||
private boolean showheaders = true; | |||
/** | |||
* Results Output file. | |||
*/ | |||
private File output; | |||
/** | |||
* RDBMS Product needed for this SQL. | |||
*/ | |||
private String rdbms; | |||
/** | |||
* RDBMS Version needed for this SQL. | |||
*/ | |||
private String version; | |||
/** | |||
* Action to perform if an error is found | |||
*/ | |||
private String onError = "abort"; | |||
/** | |||
* Encoding to use when reading SQL statements from a file | |||
*/ | |||
private String encoding; | |||
private Path classpath; | |||
/** | |||
* Set the autocommit flag for the DB connection. | |||
* | |||
* @param autocommit The new Autocommit value | |||
*/ | |||
public void setAutocommit( boolean autocommit ) | |||
{ | |||
this.autocommit = autocommit; | |||
} | |||
/** | |||
* Adds an element to the classpath for loading the driver. | |||
* | |||
* @param classpath The new Classpath value | |||
*/ | |||
public void addClasspath( Path classpath ) | |||
throws TaskException | |||
{ | |||
if( this.classpath == null ) | |||
{ | |||
this.classpath = classpath; | |||
} | |||
else | |||
{ | |||
this.classpath.addPath( classpath ); | |||
} | |||
} | |||
/** | |||
* Set the statement delimiter. <p> | |||
* | |||
* For example, set this to "go" and delimitertype to "ROW" for Sybase ASE | |||
* or MS SQL Server.</p> | |||
* | |||
* @param delimiter The new Delimiter value | |||
*/ | |||
public void setDelimiter( String delimiter ) | |||
{ | |||
this.delimiter = delimiter; | |||
} | |||
/** | |||
* Set the Delimiter type for this sql task. The delimiter type takes two | |||
* values - normal and row. Normal means that any occurence of the delimiter | |||
* terminate the SQL command whereas with row, only a line containing just | |||
* the delimiter is recognized as the end of the command. | |||
* | |||
* @param delimiterType The new DelimiterType value | |||
*/ | |||
public void setDelimiterType( DelimiterType delimiterType ) | |||
{ | |||
this.delimiterType = delimiterType.getValue(); | |||
} | |||
/** | |||
* Set the JDBC driver to be used. | |||
* | |||
* @param driver The new Driver value | |||
*/ | |||
public void setDriver( String driver ) | |||
{ | |||
this.driver = driver; | |||
} | |||
/** | |||
* Set the file encoding to use on the sql files read in | |||
* | |||
* @param encoding the encoding to use on the files | |||
*/ | |||
public void setEncoding( String encoding ) | |||
{ | |||
this.encoding = encoding; | |||
} | |||
/** | |||
* Set the action to perform onerror | |||
* | |||
* @param action The new Onerror value | |||
*/ | |||
public void setOnerror( OnError action ) | |||
{ | |||
this.onError = action.getValue(); | |||
} | |||
/** | |||
* Set the output file. | |||
* | |||
* @param output The new Output value | |||
*/ | |||
public void setOutput( File output ) | |||
{ | |||
this.output = output; | |||
} | |||
/** | |||
* Set the password for the DB connection. | |||
* | |||
* @param password The new Password value | |||
*/ | |||
public void setPassword( String password ) | |||
{ | |||
this.password = password; | |||
} | |||
/** | |||
* Set the print flag. | |||
* | |||
* @param print The new Print value | |||
*/ | |||
public void setPrint( boolean print ) | |||
{ | |||
this.print = print; | |||
} | |||
/** | |||
* Set the rdbms required | |||
* | |||
* @param vendor The new Rdbms value | |||
*/ | |||
public void setRdbms( String vendor ) | |||
{ | |||
this.rdbms = vendor.toLowerCase(); | |||
} | |||
/** | |||
* Set the showheaders flag. | |||
* | |||
* @param showheaders The new Showheaders value | |||
*/ | |||
public void setShowheaders( boolean showheaders ) | |||
{ | |||
this.showheaders = showheaders; | |||
} | |||
/** | |||
* Set the name of the sql file to be run. | |||
* | |||
* @param srcFile The new Src value | |||
*/ | |||
public void setSrc( File srcFile ) | |||
{ | |||
this.srcFile = srcFile; | |||
} | |||
/** | |||
* Set the DB connection url. | |||
* | |||
* @param url The new Url value | |||
*/ | |||
public void setUrl( String url ) | |||
{ | |||
this.url = url; | |||
} | |||
/** | |||
* Set the user name for the DB connection. | |||
* | |||
* @param userId The new Userid value | |||
*/ | |||
public void setUserid( String userId ) | |||
{ | |||
this.userId = userId; | |||
} | |||
/** | |||
* Set the version required | |||
* | |||
* @param version The new Version value | |||
*/ | |||
public void setVersion( String version ) | |||
{ | |||
this.version = version.toLowerCase(); | |||
} | |||
/** | |||
* Adds a set of files (nested fileset attribute). | |||
* | |||
* @param set The feature to be added to the Fileset attribute | |||
*/ | |||
public void addFileset( FileSet set ) | |||
{ | |||
filesets.add( set ); | |||
} | |||
/** | |||
* Set the sql command to execute | |||
* | |||
* @param sql The feature to be added to the Text attribute | |||
*/ | |||
public void addContent( String sql ) | |||
{ | |||
this.sqlCommand += sql; | |||
} | |||
/** | |||
* Set the sql command to execute | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public Transaction createTransaction() | |||
{ | |||
Transaction t = new Transaction(); | |||
transactions.add( t ); | |||
return t; | |||
} | |||
/** | |||
* Load the sql file and then execute it | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
sqlCommand = sqlCommand.trim(); | |||
if( srcFile == null && sqlCommand.length() == 0 && filesets.isEmpty() ) | |||
{ | |||
if( transactions.size() == 0 ) | |||
{ | |||
throw new TaskException( "Source file or fileset, transactions or sql statement must be set!" ); | |||
} | |||
} | |||
else | |||
{ | |||
// deal with the filesets | |||
for( int i = 0; i < filesets.size(); i++ ) | |||
{ | |||
FileSet fs = (FileSet)filesets.get( i ); | |||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||
File srcDir = fs.getDir(); | |||
String[] srcFiles = ds.getIncludedFiles(); | |||
// Make a transaction for each file | |||
for( int j = 0; j < srcFiles.length; j++ ) | |||
{ | |||
Transaction t = createTransaction(); | |||
t.setSrc( new File( srcDir, srcFiles[ j ] ) ); | |||
} | |||
} | |||
// Make a transaction group for the outer command | |||
Transaction t = createTransaction(); | |||
t.setSrc( srcFile ); | |||
t.addContent( sqlCommand ); | |||
} | |||
if( driver == null ) | |||
{ | |||
throw new TaskException( "Driver attribute must be set!" ); | |||
} | |||
if( userId == null ) | |||
{ | |||
throw new TaskException( "User Id attribute must be set!" ); | |||
} | |||
if( password == null ) | |||
{ | |||
throw new TaskException( "Password attribute must be set!" ); | |||
} | |||
if( url == null ) | |||
{ | |||
throw new TaskException( "Url attribute must be set!" ); | |||
} | |||
if( srcFile != null && !srcFile.exists() ) | |||
{ | |||
throw new TaskException( "Source file does not exist!" ); | |||
} | |||
Driver driverInstance = null; | |||
// Load the driver using the | |||
try | |||
{ | |||
Class dc; | |||
if( classpath != null ) | |||
{ | |||
getContext().debug( "Loading " + driver + " using AntClassLoader with classpath " + classpath ); | |||
final URL[] urls = PathUtil.toURLs( classpath ); | |||
final ClassLoader classLoader = new URLClassLoader( urls ); | |||
dc = classLoader.loadClass( driver ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "Loading " + driver + " using system loader." ); | |||
dc = Class.forName( driver ); | |||
} | |||
driverInstance = (Driver)dc.newInstance(); | |||
} | |||
catch( ClassNotFoundException e ) | |||
{ | |||
throw new TaskException( "Class Not Found: JDBC driver " + driver + " could not be loaded" ); | |||
} | |||
catch( IllegalAccessException e ) | |||
{ | |||
throw new TaskException( "Illegal Access: JDBC driver " + driver + " could not be loaded" ); | |||
} | |||
catch( InstantiationException e ) | |||
{ | |||
throw new TaskException( "Instantiation Exception: JDBC driver " + driver + " could not be loaded" ); | |||
} | |||
try | |||
{ | |||
getContext().debug( "connecting to " + url ); | |||
Properties info = new Properties(); | |||
info.put( "user", userId ); | |||
info.put( "password", password ); | |||
conn = driverInstance.connect( url, info ); | |||
if( conn == null ) | |||
{ | |||
// Driver doesn't understand the URL | |||
throw new SQLException( "No suitable Driver for " + url ); | |||
} | |||
if( !isValidRdbms( conn ) ) | |||
{ | |||
return; | |||
} | |||
conn.setAutoCommit( autocommit ); | |||
statement = conn.createStatement(); | |||
PrintStream out = System.out; | |||
try | |||
{ | |||
if( output != null ) | |||
{ | |||
getContext().debug( "Opening PrintStream to output file " + output ); | |||
out = new PrintStream( new BufferedOutputStream( new FileOutputStream( output ) ) ); | |||
} | |||
// Process all transactions | |||
for( Iterator e = transactions.iterator(); | |||
e.hasNext(); ) | |||
{ | |||
( (Transaction)e.next() ).runTransaction( out ); | |||
if( !autocommit ) | |||
{ | |||
getContext().debug( "Commiting transaction" ); | |||
conn.commit(); | |||
} | |||
} | |||
} | |||
finally | |||
{ | |||
if( out != null && out != System.out ) | |||
{ | |||
out.close(); | |||
} | |||
} | |||
} | |||
catch( IOException e ) | |||
{ | |||
if( !autocommit && conn != null && onError.equals( "abort" ) ) | |||
{ | |||
try | |||
{ | |||
conn.rollback(); | |||
} | |||
catch( SQLException ex ) | |||
{ | |||
} | |||
} | |||
throw new TaskException( "Error", e ); | |||
} | |||
catch( SQLException e ) | |||
{ | |||
if( !autocommit && conn != null && onError.equals( "abort" ) ) | |||
{ | |||
try | |||
{ | |||
conn.rollback(); | |||
} | |||
catch( SQLException ex ) | |||
{ | |||
} | |||
} | |||
throw new TaskException( "Error", e ); | |||
} | |||
finally | |||
{ | |||
try | |||
{ | |||
if( statement != null ) | |||
{ | |||
statement.close(); | |||
} | |||
if( conn != null ) | |||
{ | |||
conn.close(); | |||
} | |||
} | |||
catch( SQLException e ) | |||
{ | |||
} | |||
} | |||
getContext().info( goodSql + " of " + totalSql + | |||
" SQL statements executed successfully" ); | |||
} | |||
/** | |||
* Verify if connected to the correct RDBMS | |||
* | |||
* @param conn Description of Parameter | |||
* @return The ValidRdbms value | |||
*/ | |||
protected boolean isValidRdbms( Connection conn ) | |||
{ | |||
if( rdbms == null && version == null ) | |||
{ | |||
return true; | |||
} | |||
try | |||
{ | |||
DatabaseMetaData dmd = conn.getMetaData(); | |||
if( rdbms != null ) | |||
{ | |||
String theVendor = dmd.getDatabaseProductName().toLowerCase(); | |||
getContext().debug( "RDBMS = " + theVendor ); | |||
if( theVendor == null || theVendor.indexOf( rdbms ) < 0 ) | |||
{ | |||
getContext().debug( "Not the required RDBMS: " + rdbms ); | |||
return false; | |||
} | |||
} | |||
if( version != null ) | |||
{ | |||
String theVersion = dmd.getDatabaseProductVersion().toLowerCase(); | |||
getContext().debug( "Version = " + theVersion ); | |||
if( theVersion == null || | |||
!( theVersion.startsWith( version ) || | |||
theVersion.indexOf( " " + version ) >= 0 ) ) | |||
{ | |||
getContext().debug( "Not the required version: \"" + version + "\"" ); | |||
return false; | |||
} | |||
} | |||
} | |||
catch( SQLException e ) | |||
{ | |||
// Could not get the required information | |||
getContext().error( "Failed to obtain required RDBMS information" ); | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Exec the sql statement. | |||
* | |||
* @param sql Description of Parameter | |||
* @param out Description of Parameter | |||
* @exception java.sql.SQLException Description of Exception | |||
*/ | |||
protected void execSQL( String sql, PrintStream out ) | |||
throws SQLException | |||
{ | |||
// Check and ignore empty statements | |||
if( "".equals( sql.trim() ) ) | |||
{ | |||
return; | |||
} | |||
try | |||
{ | |||
totalSql++; | |||
if( !statement.execute( sql ) ) | |||
{ | |||
getContext().debug( statement.getUpdateCount() + " rows affected" ); | |||
} | |||
else | |||
{ | |||
if( print ) | |||
{ | |||
printResults( out ); | |||
} | |||
} | |||
SQLWarning warning = conn.getWarnings(); | |||
while( warning != null ) | |||
{ | |||
getContext().debug( warning + " sql warning" ); | |||
warning = warning.getNextWarning(); | |||
} | |||
conn.clearWarnings(); | |||
goodSql++; | |||
} | |||
catch( SQLException e ) | |||
{ | |||
getContext().error( "Failed to execute: " + sql ); | |||
if( !onError.equals( "continue" ) ) | |||
{ | |||
throw e; | |||
} | |||
getContext().error( e.toString() ); | |||
} | |||
} | |||
/** | |||
* print any results in the statement. | |||
* | |||
* @param out Description of Parameter | |||
* @exception java.sql.SQLException Description of Exception | |||
*/ | |||
protected void printResults( PrintStream out ) | |||
throws java.sql.SQLException | |||
{ | |||
ResultSet rs = null; | |||
do | |||
{ | |||
rs = statement.getResultSet(); | |||
if( rs != null ) | |||
{ | |||
getContext().debug( "Processing new result set." ); | |||
ResultSetMetaData md = rs.getMetaData(); | |||
int columnCount = md.getColumnCount(); | |||
StringBuffer line = new StringBuffer(); | |||
if( showheaders ) | |||
{ | |||
for( int col = 1; col < columnCount; col++ ) | |||
{ | |||
line.append( md.getColumnName( col ) ); | |||
line.append( "," ); | |||
} | |||
line.append( md.getColumnName( columnCount ) ); | |||
out.println( line ); | |||
line.setLength( 0 ); | |||
} | |||
while( rs.next() ) | |||
{ | |||
boolean first = true; | |||
for( int col = 1; col <= columnCount; col++ ) | |||
{ | |||
String columnValue = rs.getString( col ); | |||
if( columnValue != null ) | |||
{ | |||
columnValue = columnValue.trim(); | |||
} | |||
if( first ) | |||
{ | |||
first = false; | |||
} | |||
else | |||
{ | |||
line.append( "," ); | |||
} | |||
line.append( columnValue ); | |||
} | |||
out.println( line ); | |||
line.setLength( 0 ); | |||
} | |||
} | |||
} while( statement.getMoreResults() ); | |||
out.println(); | |||
} | |||
protected void runStatements( Reader reader, PrintStream out ) | |||
throws SQLException, IOException, TaskException | |||
{ | |||
String sql = ""; | |||
String line = ""; | |||
BufferedReader in = new BufferedReader( reader ); | |||
try | |||
{ | |||
while( ( line = in.readLine() ) != null ) | |||
{ | |||
line = line.trim(); | |||
final String value = line; | |||
line = "" + getContext().resolveValue( value ); | |||
if( line.startsWith( "//" ) ) | |||
{ | |||
continue; | |||
} | |||
if( line.startsWith( "--" ) ) | |||
{ | |||
continue; | |||
} | |||
StringTokenizer st = new StringTokenizer( line ); | |||
if( st.hasMoreTokens() ) | |||
{ | |||
String token = st.nextToken(); | |||
if( "REM".equalsIgnoreCase( token ) ) | |||
{ | |||
continue; | |||
} | |||
} | |||
sql += " " + line; | |||
sql = sql.trim(); | |||
// SQL defines "--" as a comment to EOL | |||
// and in Oracle it may contain a hint | |||
// so we cannot just remove it, instead we must end it | |||
if( line.indexOf( "--" ) >= 0 ) | |||
{ | |||
sql += "\n"; | |||
} | |||
if( delimiterType.equals( DelimiterType.NORMAL ) && sql.endsWith( delimiter ) || | |||
delimiterType.equals( DelimiterType.ROW ) && line.equals( delimiter ) ) | |||
{ | |||
getContext().debug( "SQL: " + sql ); | |||
execSQL( sql.substring( 0, sql.length() - delimiter.length() ), out ); | |||
sql = ""; | |||
} | |||
} | |||
// Catch any statements not followed by ; | |||
if( !sql.equals( "" ) ) | |||
{ | |||
execSQL( sql, out ); | |||
} | |||
} | |||
catch( SQLException e ) | |||
{ | |||
throw e; | |||
} | |||
} | |||
public static class DelimiterType extends EnumeratedAttribute | |||
{ | |||
public final static String NORMAL = "normal"; | |||
public final static String ROW = "row"; | |||
public String[] getValues() | |||
{ | |||
return new String[]{NORMAL, ROW}; | |||
} | |||
} | |||
/** | |||
* Enumerated attribute with the values "continue", "stop" and "abort" for | |||
* the onerror attribute. | |||
* | |||
* @author RT | |||
*/ | |||
public static class OnError extends EnumeratedAttribute | |||
{ | |||
public String[] getValues() | |||
{ | |||
return new String[]{"continue", "stop", "abort"}; | |||
} | |||
} | |||
/** | |||
* Contains the definition of a new transaction element. Transactions allow | |||
* several files or blocks of statements to be executed using the same JDBC | |||
* connection and commit operation in between. | |||
* | |||
* @author RT | |||
*/ | |||
public class Transaction | |||
{ | |||
private File tSrcFile = null; | |||
private String tSqlCommand = ""; | |||
public void setSrc( File src ) | |||
{ | |||
this.tSrcFile = src; | |||
} | |||
public void addContent( String sql ) | |||
{ | |||
this.tSqlCommand += sql; | |||
} | |||
private void runTransaction( PrintStream out ) | |||
throws IOException, SQLException, TaskException | |||
{ | |||
if( tSqlCommand.length() != 0 ) | |||
{ | |||
getContext().info( "Executing commands" ); | |||
runStatements( new StringReader( tSqlCommand ), out ); | |||
} | |||
if( tSrcFile != null ) | |||
{ | |||
getContext().info( "Executing file: " + tSrcFile.getAbsolutePath() ); | |||
Reader reader = ( encoding == null ) ? new FileReader( tSrcFile ) | |||
: new InputStreamReader( new FileInputStream( tSrcFile ), encoding ); | |||
runStatements( reader, out ); | |||
reader.close(); | |||
} | |||
} | |||
} | |||
} |
@@ -1,155 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import com.ibm.bsf.BSFException; | |||
import com.ibm.bsf.BSFManager; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Execute a script | |||
* | |||
* @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a> | |||
*/ | |||
public class Script extends AbstractTask | |||
{ | |||
private String script = ""; | |||
private Hashtable beans = new Hashtable(); | |||
private String language; | |||
/** | |||
* Defines the language (required). | |||
* | |||
* @param language The new Language value | |||
*/ | |||
public void setLanguage( String language ) | |||
{ | |||
this.language = language; | |||
} | |||
/** | |||
* Load the script from an external file | |||
* | |||
* @param fileName The new Src value | |||
*/ | |||
public void setSrc( String fileName ) | |||
{ | |||
File file = new File( fileName ); | |||
if( !file.exists() ) | |||
{ | |||
throw new TaskException( "file " + fileName + " not found." ); | |||
} | |||
int count = (int)file.length(); | |||
byte data[] = new byte[ count ]; | |||
try | |||
{ | |||
FileInputStream inStream = new FileInputStream( file ); | |||
inStream.read( data ); | |||
inStream.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
script += new String( data ); | |||
} | |||
/** | |||
* Defines the script. | |||
* | |||
* @param text The feature to be added to the Text attribute | |||
*/ | |||
public void addContent( String text ) | |||
{ | |||
this.script += text; | |||
} | |||
/** | |||
* Do the work. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException if someting goes wrong with the build | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
addBeans( getContext().getProperties() ); | |||
//In Ant2 there is no difference between properties and references | |||
//addBeans( getProject().getReferences() ); | |||
beans.put( "context", getContext() ); | |||
beans.put( "self", this ); | |||
BSFManager manager = new BSFManager(); | |||
for( Iterator e = beans.keys(); e.hasNext(); ) | |||
{ | |||
String key = (String)e.next(); | |||
Object value = beans.get( key ); | |||
manager.declareBean( key, value, value.getClass() ); | |||
} | |||
// execute the script | |||
manager.exec( language, "<ANT>", 0, 0, script ); | |||
} | |||
catch( BSFException be ) | |||
{ | |||
Throwable t = be; | |||
Throwable te = be.getTargetException(); | |||
if( te != null ) | |||
{ | |||
if( te instanceof TaskException ) | |||
{ | |||
throw (TaskException)te; | |||
} | |||
else | |||
{ | |||
t = te; | |||
} | |||
} | |||
throw new TaskException( "Error", t ); | |||
} | |||
} | |||
/** | |||
* Add a list of named objects to the list to be exported to the script | |||
* | |||
* @param dictionary The feature to be added to the Beans attribute | |||
*/ | |||
private void addBeans( Hashtable dictionary ) | |||
{ | |||
for( Iterator e = dictionary.keys(); e.hasNext(); ) | |||
{ | |||
String key = (String)e.next(); | |||
boolean isValid = key.length() > 0 && | |||
Character.isJavaIdentifierStart( key.charAt( 0 ) ); | |||
for( int i = 1; isValid && i < key.length(); i++ ) | |||
{ | |||
isValid = Character.isJavaIdentifierPart( key.charAt( i ) ); | |||
} | |||
if( isValid ) | |||
{ | |||
beans.put( key, dictionary.get( key ) ); | |||
} | |||
} | |||
} | |||
} |
@@ -1,256 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.text.SimpleDateFormat; | |||
import java.util.ArrayList; | |||
import java.util.Calendar; | |||
import java.util.Date; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import java.util.Locale; | |||
import java.util.NoSuchElementException; | |||
import java.util.StringTokenizer; | |||
import java.util.TimeZone; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
/** | |||
* Sets TSTAMP, DSTAMP and TODAY | |||
* | |||
* @author costin@dnt.ro | |||
* @author stefano@apache.org | |||
* @author roxspring@yahoo.com | |||
* @author conor@cognet.com.au | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
*/ | |||
public class Tstamp | |||
extends AbstractTask | |||
{ | |||
private ArrayList customFormats = new ArrayList(); | |||
private String m_prefix = ""; | |||
public void setPrefix( String prefix ) | |||
{ | |||
this.m_prefix = prefix; | |||
if( !this.m_prefix.endsWith( "." ) ) | |||
{ | |||
this.m_prefix += "."; | |||
} | |||
} | |||
public CustomFormat createFormat() | |||
{ | |||
CustomFormat cts = new CustomFormat( m_prefix ); | |||
customFormats.add( cts ); | |||
return cts; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
Date d = new Date(); | |||
SimpleDateFormat dstamp = new SimpleDateFormat( "yyyyMMdd" ); | |||
final String name = m_prefix + "DSTAMP"; | |||
final Object value = dstamp.format( d ); | |||
getContext().setProperty( name, value ); | |||
SimpleDateFormat tstamp = new SimpleDateFormat( "HHmm" ); | |||
final String name1 = m_prefix + "TSTAMP"; | |||
final Object value1 = tstamp.format( d ); | |||
getContext().setProperty( name1, value1 ); | |||
SimpleDateFormat today = new SimpleDateFormat( "MMMM d yyyy", Locale.US ); | |||
final String name2 = m_prefix + "TODAY"; | |||
final Object value2 = today.format( d ); | |||
getContext().setProperty( name2, value2 ); | |||
Iterator i = customFormats.iterator(); | |||
while( i.hasNext() ) | |||
{ | |||
CustomFormat cts = (CustomFormat)i.next(); | |||
cts.execute( d ); | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
} | |||
public static class Unit extends EnumeratedAttribute | |||
{ | |||
private final static String MILLISECOND = "millisecond"; | |||
private final static String SECOND = "second"; | |||
private final static String MINUTE = "minute"; | |||
private final static String HOUR = "hour"; | |||
private final static String DAY = "day"; | |||
private final static String WEEK = "week"; | |||
private final static String MONTH = "month"; | |||
private final static String YEAR = "year"; | |||
private final static String[] units = { | |||
MILLISECOND, | |||
SECOND, | |||
MINUTE, | |||
HOUR, | |||
DAY, | |||
WEEK, | |||
MONTH, | |||
YEAR | |||
}; | |||
private Hashtable calendarFields = new Hashtable(); | |||
public Unit() | |||
{ | |||
calendarFields.put( MILLISECOND, | |||
new Integer( Calendar.MILLISECOND ) ); | |||
calendarFields.put( SECOND, new Integer( Calendar.SECOND ) ); | |||
calendarFields.put( MINUTE, new Integer( Calendar.MINUTE ) ); | |||
calendarFields.put( HOUR, new Integer( Calendar.HOUR_OF_DAY ) ); | |||
calendarFields.put( DAY, new Integer( Calendar.DATE ) ); | |||
calendarFields.put( WEEK, new Integer( Calendar.WEEK_OF_YEAR ) ); | |||
calendarFields.put( MONTH, new Integer( Calendar.MONTH ) ); | |||
calendarFields.put( YEAR, new Integer( Calendar.YEAR ) ); | |||
} | |||
public int getCalendarField() | |||
{ | |||
String key = getValue().toLowerCase(); | |||
Integer i = (Integer)calendarFields.get( key ); | |||
return i.intValue(); | |||
} | |||
public String[] getValues() | |||
{ | |||
return units; | |||
} | |||
} | |||
public class CustomFormat | |||
{ | |||
private int offset = 0; | |||
private int field = Calendar.DATE; | |||
private String prefix = ""; | |||
private String country; | |||
private String language; | |||
private String pattern; | |||
private String propertyName; | |||
private TimeZone timeZone; | |||
private String variant; | |||
public CustomFormat( String prefix ) | |||
{ | |||
this.prefix = prefix; | |||
} | |||
public void setLocale( String locale ) | |||
throws TaskException | |||
{ | |||
StringTokenizer st = new StringTokenizer( locale, " \t\n\r\f," ); | |||
try | |||
{ | |||
language = st.nextToken(); | |||
if( st.hasMoreElements() ) | |||
{ | |||
country = st.nextToken(); | |||
if( st.hasMoreElements() ) | |||
{ | |||
country = st.nextToken(); | |||
if( st.hasMoreElements() ) | |||
{ | |||
throw new TaskException( "bad locale format" ); | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
country = ""; | |||
} | |||
} | |||
catch( NoSuchElementException e ) | |||
{ | |||
throw new TaskException( "bad locale format", e ); | |||
} | |||
} | |||
public void setOffset( int offset ) | |||
{ | |||
this.offset = offset; | |||
} | |||
public void setPattern( String pattern ) | |||
{ | |||
this.pattern = pattern; | |||
} | |||
public void setProperty( String propertyName ) | |||
{ | |||
this.propertyName = prefix + propertyName; | |||
} | |||
public void setTimezone( String id ) | |||
{ | |||
timeZone = TimeZone.getTimeZone( id ); | |||
} | |||
public void setUnit( Unit unit ) | |||
{ | |||
field = unit.getCalendarField(); | |||
} | |||
public void execute( final Date date ) | |||
throws TaskException | |||
{ | |||
if( propertyName == null ) | |||
{ | |||
throw new TaskException( "property attribute must be provided" ); | |||
} | |||
if( pattern == null ) | |||
{ | |||
throw new TaskException( "pattern attribute must be provided" ); | |||
} | |||
SimpleDateFormat sdf; | |||
if( language == null ) | |||
{ | |||
sdf = new SimpleDateFormat( pattern ); | |||
} | |||
else if( variant == null ) | |||
{ | |||
sdf = new SimpleDateFormat( pattern, new Locale( language, country ) ); | |||
} | |||
else | |||
{ | |||
sdf = new SimpleDateFormat( pattern, new Locale( language, country, variant ) ); | |||
} | |||
Date time = date; | |||
if( offset != 0 ) | |||
{ | |||
final Calendar calendar = Calendar.getInstance(); | |||
calendar.setTime( time ); | |||
calendar.add( field, offset ); | |||
time = calendar.getTime(); | |||
} | |||
if( timeZone != null ) | |||
{ | |||
sdf.setTimeZone( timeZone ); | |||
} | |||
getContext().setProperty( propertyName, sdf.format( time ) ); | |||
} | |||
} | |||
} |
@@ -1,190 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.FileNameMapper; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
import org.apache.tools.todo.types.SourceFileScanner; | |||
import org.apache.tools.todo.util.mappers.MergingMapper; | |||
/** | |||
* Will set the given property if the specified target has a timestamp greater | |||
* than all of the source files. | |||
* | |||
* @author William Ferguson <a href="mailto:williamf@mincom.com"> | |||
* williamf@mincom.com</a> | |||
* @author Hiroaki Nakamura <a href="mailto:hnakamur@mc.neweb.ne.jp"> | |||
* hnakamur@mc.neweb.ne.jp</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class UpToDate | |||
extends AbstractTask | |||
{ | |||
private final ArrayList m_fileSets = new ArrayList(); | |||
private FileNameMapper m_mapper; | |||
private String m_property; | |||
private File m_targetFile; | |||
private String m_value; | |||
/** | |||
* The property to set if the target file is more up to date than each of | |||
* the source files. | |||
* | |||
* @param property the name of the property to set if Target is up to date. | |||
*/ | |||
public void setProperty( final String property ) | |||
{ | |||
m_property = property; | |||
} | |||
/** | |||
* The file which must be more up to date than each of the source files if | |||
* the property is to be set. | |||
* | |||
* @param file the file which we are checking against. | |||
*/ | |||
public void setTargetFile( final File file ) | |||
{ | |||
m_targetFile = file; | |||
} | |||
/** | |||
* The value to set the named property to if the target file is more up to | |||
* date than each of the source files. Defaults to 'true'. | |||
* | |||
* @param value the value to set the property to if Target is up to date | |||
*/ | |||
public void setValue( final String value ) | |||
{ | |||
m_value = value; | |||
} | |||
/** | |||
* Nested <srcfiles> element. | |||
* | |||
* @param fs The feature to be added to the Srcfiles attribute | |||
*/ | |||
public void addSrcfiles( final FileSet fs ) | |||
{ | |||
m_fileSets.add( fs ); | |||
} | |||
/** | |||
* Defines the FileNameMapper to use (nested mapper element). | |||
*/ | |||
public void addMapper( final FileNameMapper mapper ) | |||
throws TaskException | |||
{ | |||
if( m_mapper != null ) | |||
{ | |||
throw new TaskException( "Cannot define more than one mapper" ); | |||
} | |||
m_mapper = mapper; | |||
} | |||
/** | |||
* Evaluate all target and source files, see if the targets are up-to-date. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public boolean eval() | |||
throws TaskException | |||
{ | |||
if( m_fileSets.size() == 0 ) | |||
{ | |||
throw new TaskException( "At least one <srcfiles> element must be set" ); | |||
} | |||
if( m_targetFile == null && m_mapper == null ) | |||
{ | |||
throw new TaskException( "The targetfile attribute or a nested mapper element must be set" ); | |||
} | |||
// if not there then it can't be up to date | |||
if( m_targetFile != null && !m_targetFile.exists() ) | |||
{ | |||
return false; | |||
} | |||
Iterator enum = m_fileSets.iterator(); | |||
boolean upToDate = true; | |||
while( upToDate && enum.hasNext() ) | |||
{ | |||
FileSet fs = (FileSet)enum.next(); | |||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||
upToDate = upToDate && scanDir( fs.getDir(), | |||
ds.getIncludedFiles() ); | |||
} | |||
return upToDate; | |||
} | |||
/** | |||
* Sets property to true if target files have a more recent timestamp than | |||
* each of the corresponding source files. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
boolean upToDate = eval(); | |||
if( upToDate ) | |||
{ | |||
final String name = m_property; | |||
final Object value = this.getValue(); | |||
getContext().setProperty( name, value ); | |||
if( m_mapper == null ) | |||
{ | |||
getContext().debug( "File \"" + m_targetFile.getAbsolutePath() + "\" is up to date." ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "All target files have been up to date." ); | |||
} | |||
} | |||
} | |||
protected boolean scanDir( File srcDir, String files[] ) | |||
throws TaskException | |||
{ | |||
SourceFileScanner scanner = new SourceFileScanner(); | |||
FileNameMapper mapper = null; | |||
File dir = srcDir; | |||
if( m_mapper == null ) | |||
{ | |||
MergingMapper mm = new MergingMapper(); | |||
mm.setTo( m_targetFile.getAbsolutePath() ); | |||
mapper = mm; | |||
dir = null; | |||
} | |||
else | |||
{ | |||
mapper = m_mapper; | |||
} | |||
return scanner.restrict( files, srcDir, dir, mapper, getContext() ).length == 0; | |||
} | |||
/** | |||
* Returns the value, or "true" if a specific value wasn't provided. | |||
* | |||
* @return The Value value | |||
*/ | |||
private String getValue() | |||
{ | |||
return ( m_value != null ) ? m_value : "true"; | |||
} | |||
} |
@@ -1,181 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs; | |||
import java.util.Hashtable; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.framework.conditions.AndCondition; | |||
import org.apache.myrmidon.framework.conditions.Condition; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
/** | |||
* Wait for an external event to occur. Wait for an external process to start or | |||
* to complete some task. This is useful with the <code>parallel</code> task to | |||
* syncronize the execution of tests with server startup. The following | |||
* attributes can be specified on a waitfor task: | |||
* <ul> | |||
* <li> maxwait - maximum length of time to wait before giving up</li> | |||
* <li> maxwaitunit - The unit to be used to interpret maxwait attribute</li> | |||
* | |||
* <li> checkevery - amount of time to sleep between each check</li> | |||
* <li> checkeveryunit - The unit to be used to interpret checkevery attribute | |||
* </li> | |||
* <li> timeoutproperty - name of a property to set if maxwait has been | |||
* exceeded.</li> | |||
* </ul> | |||
* The maxwaitunit and checkeveryunit are allowed to have the following values: | |||
* millesond, second, minute, hour, day and week. The default is millisecond. | |||
* | |||
* @author <a href="mailto:denis@network365.com">Denis Hennessy</a> | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
*/ | |||
public class WaitFor | |||
extends AbstractTask | |||
{ | |||
private long maxWaitMillis = 1000l * 60l * 3l;// default max wait time | |||
private long maxWaitMultiplier = 1l; | |||
private long checkEveryMillis = 500l; | |||
private long checkEveryMultiplier = 1l; | |||
private String timeoutProperty; | |||
private AndCondition m_condition = new AndCondition(); | |||
/** | |||
* Adds a condition. | |||
*/ | |||
public void add( final Condition condition ) | |||
{ | |||
m_condition.add( condition ); | |||
} | |||
/** | |||
* Set the time between each check | |||
* | |||
* @param time The new CheckEvery value | |||
*/ | |||
public void setCheckEvery( long time ) | |||
{ | |||
checkEveryMillis = time; | |||
} | |||
/** | |||
* Set the check every time unit | |||
* | |||
* @param unit The new CheckEveryUnit value | |||
*/ | |||
public void setCheckEveryUnit( Unit unit ) | |||
{ | |||
checkEveryMultiplier = unit.getMultiplier(); | |||
} | |||
/** | |||
* Set the maximum length of time to wait | |||
* | |||
* @param time The new MaxWait value | |||
*/ | |||
public void setMaxWait( long time ) | |||
{ | |||
maxWaitMillis = time; | |||
} | |||
/** | |||
* Set the max wait time unit | |||
* | |||
* @param unit The new MaxWaitUnit value | |||
*/ | |||
public void setMaxWaitUnit( Unit unit ) | |||
{ | |||
maxWaitMultiplier = unit.getMultiplier(); | |||
} | |||
/** | |||
* Set the timeout property. | |||
* | |||
* @param p The new TimeoutProperty value | |||
*/ | |||
public void setTimeoutProperty( String p ) | |||
{ | |||
timeoutProperty = p; | |||
} | |||
/** | |||
* Check repeatedly for the specified conditions until they become true or | |||
* the timeout expires. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
maxWaitMillis *= maxWaitMultiplier; | |||
checkEveryMillis *= checkEveryMultiplier; | |||
long start = System.currentTimeMillis(); | |||
long end = start + maxWaitMillis; | |||
while( System.currentTimeMillis() < end ) | |||
{ | |||
if( m_condition.evaluate( getContext() ) ) | |||
{ | |||
return; | |||
} | |||
try | |||
{ | |||
Thread.sleep( checkEveryMillis ); | |||
} | |||
catch( InterruptedException e ) | |||
{ | |||
} | |||
} | |||
if( timeoutProperty != null ) | |||
{ | |||
final String name = timeoutProperty; | |||
getContext().setProperty( name, "true" ); | |||
} | |||
} | |||
public static class Unit extends EnumeratedAttribute | |||
{ | |||
private final static String MILLISECOND = "millisecond"; | |||
private final static String SECOND = "second"; | |||
private final static String MINUTE = "minute"; | |||
private final static String HOUR = "hour"; | |||
private final static String DAY = "day"; | |||
private final static String WEEK = "week"; | |||
private final static String[] units = { | |||
MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK | |||
}; | |||
private Hashtable timeTable = new Hashtable(); | |||
public Unit() | |||
{ | |||
timeTable.put( MILLISECOND, new Long( 1l ) ); | |||
timeTable.put( SECOND, new Long( 1000l ) ); | |||
timeTable.put( MINUTE, new Long( 1000l * 60l ) ); | |||
timeTable.put( HOUR, new Long( 1000l * 60l * 60l ) ); | |||
timeTable.put( DAY, new Long( 1000l * 60l * 60l * 24l ) ); | |||
timeTable.put( WEEK, new Long( 1000l * 60l * 60l * 24l * 7l ) ); | |||
} | |||
public long getMultiplier() | |||
{ | |||
String key = getValue().toLowerCase(); | |||
Long l = (Long)timeTable.get( key ); | |||
return l.longValue(); | |||
} | |||
public String[] getValues() | |||
{ | |||
return units; | |||
} | |||
} | |||
} |
@@ -1,99 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.aut.zip.ZipOutputStream; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
/** | |||
* Creates a EAR archive. Based on WAR task | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:leslie.hughes@rubus.com">Les Hughes</a> | |||
*/ | |||
public class Ear | |||
extends Jar | |||
{ | |||
private File m_appxml; | |||
private boolean m_descriptorAdded; | |||
public Ear() | |||
{ | |||
m_archiveType = "ear"; | |||
m_emptyBehavior = "create"; | |||
} | |||
public void setAppxml( final File appxml ) | |||
throws TaskException | |||
{ | |||
m_appxml = appxml; | |||
if( !m_appxml.exists() ) | |||
{ | |||
final String message = "Deployment descriptor: " + | |||
m_appxml + " does not exist."; | |||
throw new TaskException( message ); | |||
} | |||
addFileAs( m_appxml, "META-INF/application.xml" ); | |||
} | |||
public void addArchives( ZipFileSet fs ) | |||
{ | |||
// We just set the prefix for this fileset, and pass it up. | |||
// Do we need to do this? LH | |||
getContext().debug( "addArchives called" ); | |||
fs.setPrefix( "/" ); | |||
super.addFileset( fs ); | |||
} | |||
protected void initZipOutputStream( final ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
if( m_appxml == null && !isInUpdateMode() ) | |||
{ | |||
final String message = "appxml attribute is required"; | |||
throw new TaskException( message ); | |||
} | |||
super.initZipOutputStream( zOut ); | |||
} | |||
protected void zipFile( File file, ZipOutputStream zOut, String vPath ) | |||
throws IOException, TaskException | |||
{ | |||
// If the file being added is WEB-INF/web.xml, we warn if it's not the | |||
// one specified in the "webxml" attribute - or if it's being added twice, | |||
// meaning the same file is specified by the "webxml" attribute and in | |||
// a <fileset> element. | |||
if( vPath.equalsIgnoreCase( "META-INF/aplication.xml" ) ) | |||
{ | |||
if( m_appxml == null || | |||
!m_appxml.equals( file ) || | |||
m_descriptorAdded ) | |||
{ | |||
final String message = "Warning: selected " + m_archiveType + | |||
" files include a META-INF/application.xml which will be ignored " + | |||
"(please use appxml attribute to " + m_archiveType + " task)"; | |||
getContext().warn( message ); | |||
} | |||
else | |||
{ | |||
super.zipFile( file, zOut, vPath ); | |||
m_descriptorAdded = true; | |||
} | |||
} | |||
else | |||
{ | |||
super.zipFile( file, zOut, vPath ); | |||
} | |||
} | |||
} |
@@ -1,287 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import java.io.FileNotFoundException; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.avalon.excalibur.io.IOUtil; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.framework.PatternSet; | |||
import org.apache.myrmidon.framework.PatternUtil; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* Unzip a file. | |||
* | |||
* @author costin@dnt.ro | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public abstract class Expand | |||
extends MatchingTask | |||
{ | |||
private boolean m_overwrite = true; | |||
private ArrayList m_patternsets = new ArrayList(); | |||
private ArrayList m_filesets = new ArrayList(); | |||
private File m_dest;//req | |||
private File m_src; | |||
/** | |||
* Set the destination directory. File will be unzipped into the destination | |||
* directory. | |||
* | |||
* @param dest Path to the directory. | |||
*/ | |||
public void setDest( final File dest ) | |||
{ | |||
m_dest = dest; | |||
} | |||
/** | |||
* Should we overwrite files in dest, even if they are newer than the | |||
* corresponding entries in the archive? | |||
* | |||
* @param overwrite The new Overwrite value | |||
*/ | |||
public void setOverwrite( final boolean overwrite ) | |||
{ | |||
m_overwrite = overwrite; | |||
} | |||
/** | |||
* Set the path to zip-file. | |||
* | |||
* @param src Path to zip-file. | |||
*/ | |||
public void setSrc( final File src ) | |||
{ | |||
m_src = src; | |||
} | |||
/** | |||
* Add a fileset | |||
* | |||
* @param set The feature to be added to the Fileset attribute | |||
*/ | |||
public void addFileset( final FileSet set ) | |||
{ | |||
m_filesets.add( set ); | |||
} | |||
/** | |||
* Add a patternset | |||
* | |||
* @param set The feature to be added to the Patternset attribute | |||
*/ | |||
public void addPatternset( final PatternSet set ) | |||
{ | |||
m_patternsets.add( set ); | |||
} | |||
/** | |||
* Do the work. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Thrown in unrecoverable error. | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
validate(); | |||
if( m_src != null ) | |||
{ | |||
expandFile( m_src, m_dest ); | |||
} | |||
final int size = m_filesets.size(); | |||
if( size > 0 ) | |||
{ | |||
for( int j = 0; j < size; j++ ) | |||
{ | |||
final FileSet fileSet = (FileSet)m_filesets.get( j ); | |||
final DirectoryScanner scanner = ScannerUtil.getDirectoryScanner( fileSet ); | |||
final File fromDir = fileSet.getDir(); | |||
final String[] files = scanner.getIncludedFiles(); | |||
for( int i = 0; i < files.length; ++i ) | |||
{ | |||
final File file = new File( fromDir, files[ i ] ); | |||
expandFile( file, m_dest ); | |||
} | |||
} | |||
} | |||
} | |||
private void validate() | |||
throws TaskException | |||
{ | |||
if( m_src == null && m_filesets.size() == 0 ) | |||
{ | |||
final String message = "src attribute and/or filesets must be specified"; | |||
throw new TaskException( message ); | |||
} | |||
if( m_dest == null ) | |||
{ | |||
final String message = "Dest attribute must be specified"; | |||
throw new TaskException( message ); | |||
} | |||
if( m_dest.exists() && !m_dest.isDirectory() ) | |||
{ | |||
final String message = "Dest must be a directory."; | |||
throw new TaskException( message ); | |||
} | |||
if( m_src != null && m_src.isDirectory() ) | |||
{ | |||
final String message = "Src must not be a directory." + | |||
" Use nested filesets instead."; | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/* | |||
* This method is to be overridden by extending unarchival tasks. | |||
*/ | |||
protected void expandFile( final File src, final File dir ) | |||
throws TaskException | |||
{ | |||
if( getContext().isInfoEnabled() ) | |||
{ | |||
final String message = "Expanding: " + src + " into " + dir; | |||
getContext().info( message ); | |||
} | |||
try | |||
{ | |||
expandArchive( src, dir ); | |||
} | |||
catch( final IOException ioe ) | |||
{ | |||
final String message = "Error while expanding " + src.getPath(); | |||
throw new TaskException( message, ioe ); | |||
} | |||
if( getContext().isDebugEnabled() ) | |||
{ | |||
final String message = "expand complete"; | |||
getContext().debug( message ); | |||
} | |||
} | |||
protected abstract void expandArchive( final File src, final File dir ) | |||
throws IOException, TaskException; | |||
protected void extractFile( final File dir, | |||
final InputStream input, | |||
final String entryName, | |||
final Date date, | |||
final boolean isDirectory ) | |||
throws IOException, TaskException | |||
{ | |||
final int size = m_patternsets.size(); | |||
if( m_patternsets != null && size > 0 ) | |||
{ | |||
boolean included = false; | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
PatternSet p = (PatternSet)m_patternsets.get( i ); | |||
final TaskContext context = getContext(); | |||
String[] incls = PatternUtil.getIncludePatterns( p, context ); | |||
if( incls != null ) | |||
{ | |||
for( int j = 0; j < incls.length; j++ ) | |||
{ | |||
boolean isIncl = ScannerUtil.match( incls[ j ], entryName ); | |||
if( isIncl ) | |||
{ | |||
included = true; | |||
break; | |||
} | |||
} | |||
} | |||
final TaskContext context1 = getContext(); | |||
String[] excls = PatternUtil.getExcludePatterns( p, context1 ); | |||
if( excls != null ) | |||
{ | |||
for( int j = 0; j < excls.length; j++ ) | |||
{ | |||
boolean isExcl = ScannerUtil.match( excls[ j ], entryName ); | |||
if( isExcl ) | |||
{ | |||
included = false; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
if( !included ) | |||
{ | |||
//Do not process this file | |||
return; | |||
} | |||
} | |||
final File file = FileUtil.resolveFile( dir, entryName ); | |||
try | |||
{ | |||
if( !m_overwrite && file.exists() && | |||
file.lastModified() >= date.getTime() ) | |||
{ | |||
final String message = "Skipping " + file + " as it is up-to-date"; | |||
getContext().debug( message ); | |||
return; | |||
} | |||
getContext().debug( "expanding " + entryName + " to " + file ); | |||
// create intermediary directories - sometimes zip don't add them | |||
final File parent = file.getParentFile(); | |||
parent.mkdirs(); | |||
if( isDirectory ) | |||
{ | |||
file.mkdirs(); | |||
} | |||
else | |||
{ | |||
FileOutputStream fos = null; | |||
try | |||
{ | |||
fos = new FileOutputStream( file ); | |||
IOUtil.copy( input, fos ); | |||
} | |||
finally | |||
{ | |||
IOUtil.shutdownStream( fos ); | |||
} | |||
} | |||
file.setLastModified( date.getTime() ); | |||
} | |||
catch( final FileNotFoundException fnfe ) | |||
{ | |||
final String message = "Unable to expand to file " + file.getPath(); | |||
getContext().warn( message ); | |||
} | |||
} | |||
} |
@@ -1,397 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.InputStreamReader; | |||
import java.io.OutputStreamWriter; | |||
import java.io.PrintWriter; | |||
import java.io.Reader; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipFile; | |||
import org.apache.aut.zip.ZipOutputStream; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.manifest.Manifest; | |||
import org.apache.tools.todo.taskdefs.manifest.ManifestException; | |||
import org.apache.tools.todo.taskdefs.manifest.ManifestUtil; | |||
import org.apache.tools.todo.types.FileScanner; | |||
/** | |||
* Creates a JAR archive. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
*/ | |||
public class Jar | |||
extends Zip | |||
{ | |||
/** | |||
* The index file name. | |||
*/ | |||
private final static String INDEX_NAME = "META-INF/INDEX.LIST"; | |||
/** | |||
* true if a manifest has been specified in the task | |||
*/ | |||
private boolean buildFileManifest; | |||
/** | |||
* jar index is JDK 1.3+ only | |||
*/ | |||
private boolean m_index; | |||
private Manifest m_execManifest; | |||
private Manifest m_manifest; | |||
private File m_manifestFile; | |||
/** | |||
* constructor | |||
*/ | |||
public Jar() | |||
{ | |||
super(); | |||
m_archiveType = "jar"; | |||
m_emptyBehavior = "create"; | |||
setEncoding( "UTF8" ); | |||
} | |||
/** | |||
* Set whether or not to create an index list for classes to speed up | |||
* classloading. | |||
* | |||
* @param flag The new Index value | |||
*/ | |||
public void setIndex( boolean flag ) | |||
{ | |||
m_index = flag; | |||
} | |||
public void setManifest( File manifestFile ) | |||
throws TaskException | |||
{ | |||
if( !manifestFile.exists() ) | |||
{ | |||
final String message = "Manifest file: " + manifestFile + " does not exist."; | |||
throw new TaskException( message ); | |||
} | |||
this.m_manifestFile = manifestFile; | |||
Reader r = null; | |||
try | |||
{ | |||
r = new FileReader( manifestFile ); | |||
Manifest newManifest = ManifestUtil.buildManifest( r ); | |||
if( m_manifest == null ) | |||
{ | |||
m_manifest = ManifestUtil.getDefaultManifest(); | |||
} | |||
m_manifest.merge( newManifest ); | |||
} | |||
catch( ManifestException e ) | |||
{ | |||
final String message = "Manifest " + manifestFile + " is invalid: " + e.getMessage(); | |||
getContext().error( message ); | |||
throw new TaskException( message, e ); | |||
} | |||
catch( IOException e ) | |||
{ | |||
final String message = "Unable to read manifest file: " + manifestFile; | |||
throw new TaskException( message, e ); | |||
} | |||
finally | |||
{ | |||
if( r != null ) | |||
{ | |||
try | |||
{ | |||
r.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
// do nothing | |||
} | |||
} | |||
} | |||
} | |||
public void setWhenempty( WhenEmpty we ) | |||
{ | |||
final String message = "JARs are never empty, they contain at least a manifest file"; | |||
getContext().warn( message ); | |||
} | |||
public void addManifest( Manifest newManifest ) | |||
throws ManifestException, TaskException | |||
{ | |||
if( m_manifest == null ) | |||
{ | |||
m_manifest = ManifestUtil.getDefaultManifest(); | |||
} | |||
m_manifest.merge( newManifest ); | |||
buildFileManifest = true; | |||
} | |||
public void addMetainf( ZipFileSet fs ) | |||
{ | |||
// We just set the prefix for this fileset, and pass it up. | |||
fs.setPrefix( "META-INF/" ); | |||
super.addFileset( fs ); | |||
} | |||
/** | |||
* Check whether the archive is up-to-date; | |||
* | |||
* @param scanners list of prepared scanners containing files to archive | |||
* @param zipFile intended archive file (may or may not exist) | |||
* @return true if nothing need be done (may have done something already); | |||
* false if archive creation should proceed | |||
* @exception org.apache.myrmidon.api.TaskException if it likes | |||
*/ | |||
protected boolean isUpToDate( FileScanner[] scanners, File zipFile ) | |||
throws TaskException | |||
{ | |||
// need to handle manifest as a special check | |||
if( buildFileManifest || m_manifestFile == null ) | |||
{ | |||
java.util.zip.ZipFile theZipFile = null; | |||
try | |||
{ | |||
theZipFile = new ZipFile( zipFile ); | |||
java.util.zip.ZipEntry entry = theZipFile.getEntry( "META-INF/MANIFEST.MF" ); | |||
if( entry == null ) | |||
{ | |||
getContext().debug( "Updating jar since the current jar has no manifest" ); | |||
return false; | |||
} | |||
Manifest currentManifest = ManifestUtil.buildManifest( new InputStreamReader( theZipFile.getInputStream( entry ) ) ); | |||
if( m_manifest == null ) | |||
{ | |||
m_manifest = ManifestUtil.getDefaultManifest(); | |||
} | |||
if( !currentManifest.equals( m_manifest ) ) | |||
{ | |||
getContext().debug( "Updating jar since jar manifest has changed" ); | |||
return false; | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
// any problems and we will rebuild | |||
getContext().debug( "Updating jar since cannot read current jar manifest: " + e.getClass().getName() + e.getMessage() ); | |||
return false; | |||
} | |||
finally | |||
{ | |||
if( theZipFile != null ) | |||
{ | |||
try | |||
{ | |||
theZipFile.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
//ignore | |||
} | |||
} | |||
} | |||
} | |||
else if( m_manifestFile.lastModified() > zipFile.lastModified() ) | |||
{ | |||
return false; | |||
} | |||
return super.isUpToDate( scanners, zipFile ); | |||
} | |||
protected boolean createEmptyZip( File zipFile ) | |||
{ | |||
// Jar files always contain a manifest and can never be empty | |||
return false; | |||
} | |||
protected void finalizeZipOutputStream( ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
if( m_index ) | |||
{ | |||
createIndexList( zOut ); | |||
} | |||
} | |||
protected void initZipOutputStream( ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
try | |||
{ | |||
m_execManifest = ManifestUtil.getDefaultManifest(); | |||
if( m_manifest != null ) | |||
{ | |||
m_execManifest.merge( m_manifest ); | |||
} | |||
/* | |||
for( Iterator e = m_execManifest.getWarnings(); e.hasNext(); ) | |||
{ | |||
getLogger().warn( "Manifest warning: " + (String)e.next() ); | |||
} | |||
*/ | |||
zipDir( null, zOut, "META-INF/" ); | |||
// time to write the manifest | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
PrintWriter writer = new PrintWriter( baos ); | |||
Manifest manifest = m_execManifest; | |||
ManifestUtil.write( manifest, writer ); | |||
writer.flush(); | |||
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() ); | |||
super.zipFile( bais, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis() ); | |||
super.initZipOutputStream( zOut ); | |||
} | |||
catch( ManifestException e ) | |||
{ | |||
getContext().error( "Manifest is invalid: " + e.getMessage() ); | |||
throw new TaskException( "Invalid Manifest", e ); | |||
} | |||
} | |||
protected void zipFile( File file, ZipOutputStream zOut, String vPath ) | |||
throws IOException, TaskException | |||
{ | |||
// If the file being added is META-INF/MANIFEST.MF, we warn if it's not the | |||
// one specified in the "manifest" attribute - or if it's being added twice, | |||
// meaning the same file is specified by the "manifeset" attribute and in | |||
// a <fileset> element. | |||
if( vPath.equalsIgnoreCase( "META-INF/MANIFEST.MF" ) ) | |||
{ | |||
final String message = "Warning: selected " + m_archiveType + | |||
" files include a META-INF/MANIFEST.MF which will be ignored " + | |||
"(please use manifest attribute to " + m_archiveType + " task)"; | |||
getContext().warn( message ); | |||
} | |||
else | |||
{ | |||
super.zipFile( file, zOut, vPath ); | |||
} | |||
} | |||
protected void zipFile( InputStream is, ZipOutputStream zOut, String vPath, long lastModified ) | |||
throws IOException, TaskException | |||
{ | |||
// If the file being added is META-INF/MANIFEST.MF, we merge it with the | |||
// current manifest | |||
if( vPath.equalsIgnoreCase( "META-INF/MANIFEST.MF" ) ) | |||
{ | |||
try | |||
{ | |||
zipManifestEntry( is ); | |||
} | |||
catch( IOException e ) | |||
{ | |||
throw new TaskException( "Unable to read manifest file: ", e ); | |||
} | |||
} | |||
else | |||
{ | |||
super.zipFile( is, zOut, vPath, lastModified ); | |||
} | |||
} | |||
/** | |||
* Create the index list to speed up classloading. This is a JDK 1.3+ | |||
* specific feature and is enabled by default. {@link | |||
* http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index} | |||
* | |||
* @param zOut the zip stream representing the jar being built. | |||
* @throws java.io.IOException thrown if there is an error while creating the index | |||
* and adding it to the zip stream. | |||
*/ | |||
private void createIndexList( ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
// encoding must be UTF8 as specified in the specs. | |||
PrintWriter writer = new PrintWriter( new OutputStreamWriter( baos, "UTF8" ) ); | |||
// version-info blankline | |||
writer.println( "JarIndex-Version: 1.0" ); | |||
writer.println(); | |||
// header newline | |||
writer.println( m_file.getName() ); | |||
// JarIndex is sorting the directories by ascending order. | |||
// it's painful to do in JDK 1.1 and it has no value but cosmetic | |||
// since it will be read into a hashtable by the classloader. | |||
Enumeration enum = m_addedDirs.keys(); | |||
while( enum.hasMoreElements() ) | |||
{ | |||
String dir = (String)enum.nextElement(); | |||
// try to be smart, not to be fooled by a weird directory name | |||
// @fixme do we need to check for directories starting by ./ ? | |||
dir = dir.replace( '\\', '/' ); | |||
int pos = dir.lastIndexOf( '/' ); | |||
if( pos != -1 ) | |||
{ | |||
dir = dir.substring( 0, pos ); | |||
} | |||
// looks like nothing from META-INF should be added | |||
// and the check is not case insensitive. | |||
// see sun.misc.JarIndex | |||
if( dir.startsWith( "META-INF" ) ) | |||
{ | |||
continue; | |||
} | |||
// name newline | |||
writer.println( dir ); | |||
} | |||
writer.flush(); | |||
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() ); | |||
super.zipFile( bais, zOut, INDEX_NAME, System.currentTimeMillis() ); | |||
} | |||
/** | |||
* Handle situation when we encounter a manifest file If we haven't been | |||
* given one, we use this one. If we have, we merge the manifest in, | |||
* provided it is a new file and not the old one from the JAR we are | |||
* updating | |||
* | |||
* @param is Description of Parameter | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
private void zipManifestEntry( InputStream is ) | |||
throws IOException, TaskException | |||
{ | |||
try | |||
{ | |||
if( m_execManifest == null ) | |||
{ | |||
m_execManifest = ManifestUtil.buildManifest( new InputStreamReader( is ) ); | |||
} | |||
else if( isAddingNewFiles() ) | |||
{ | |||
final Manifest other = ManifestUtil.buildManifest( new InputStreamReader( is ) ); | |||
m_execManifest.merge( other ); | |||
} | |||
} | |||
catch( ManifestException e ) | |||
{ | |||
getContext().error( "Manifest is invalid: " + e.getMessage() ); | |||
throw new TaskException( "Invalid Manifest", e ); | |||
} | |||
} | |||
} |
@@ -1,308 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import org.apache.aut.tar.TarEntry; | |||
import org.apache.aut.tar.TarOutputStream; | |||
import org.apache.avalon.excalibur.io.IOUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
import org.apache.tools.todo.types.SourceFileScanner; | |||
import org.apache.tools.todo.util.mappers.MergingMapper; | |||
/** | |||
* Creates a TAR archive. | |||
* | |||
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org"> | |||
* stefano@apache.org</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
*/ | |||
public class Tar | |||
extends MatchingTask | |||
{ | |||
private TarLongFileMode longFileMode = createMode(); | |||
private TarLongFileMode createMode() | |||
{ | |||
try | |||
{ | |||
return new TarLongFileMode(); | |||
} | |||
catch( TaskException e ) | |||
{ | |||
throw new IllegalStateException( e.getMessage() ); | |||
} | |||
} | |||
ArrayList filesets = new ArrayList(); | |||
ArrayList fileSetFiles = new ArrayList(); | |||
/** | |||
* Indicates whether the user has been warned about long files already. | |||
*/ | |||
private boolean longWarningGiven = false; | |||
File baseDir; | |||
File tarFile; | |||
/** | |||
* This is the base directory to look in for things to tar. | |||
* | |||
* @param baseDir The new Basedir value | |||
*/ | |||
public void setBasedir( File baseDir ) | |||
{ | |||
this.baseDir = baseDir; | |||
} | |||
/** | |||
* Set how to handle long files. Allowable values are truncate - paths are | |||
* truncated to the maximum length fail - paths greater than the maximim | |||
* cause a build exception warn - paths greater than the maximum cause a | |||
* warning and GNU is used gnu - GNU extensions are used for any paths | |||
* greater than the maximum. omit - paths greater than the maximum are | |||
* omitted from the archive | |||
* | |||
* @param mode The new Longfile value | |||
*/ | |||
public void setLongfile( TarLongFileMode mode ) | |||
{ | |||
this.longFileMode = mode; | |||
} | |||
/** | |||
* This is the name/location of where to create the tar file. | |||
* | |||
* @param tarFile The new Tarfile value | |||
*/ | |||
public void setTarfile( File tarFile ) | |||
{ | |||
this.tarFile = tarFile; | |||
} | |||
public TarFileSet createTarFileSet() | |||
{ | |||
TarFileSet fileset = new TarFileSet(); | |||
filesets.add( fileset ); | |||
return fileset; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( tarFile == null ) | |||
{ | |||
throw new TaskException( "tarfile attribute must be set!" ); | |||
} | |||
if( tarFile.exists() && tarFile.isDirectory() ) | |||
{ | |||
throw new TaskException( "tarfile is a directory!" ); | |||
} | |||
if( tarFile.exists() && !tarFile.canWrite() ) | |||
{ | |||
throw new TaskException( "Can not write to the specified tarfile!" ); | |||
} | |||
if( baseDir != null ) | |||
{ | |||
if( !baseDir.exists() ) | |||
{ | |||
throw new TaskException( "basedir does not exist!" ); | |||
} | |||
// add the main fileset to the list of filesets to process. | |||
final TarFileSet mainFileSet = new TarFileSet( /*fileset*/ ); | |||
mainFileSet.setDir( baseDir ); | |||
filesets.add( mainFileSet ); | |||
} | |||
if( filesets.size() == 0 ) | |||
{ | |||
throw new TaskException( "You must supply either a basdir attribute or some nested filesets." ); | |||
} | |||
// check if tr is out of date with respect to each | |||
// fileset | |||
boolean upToDate = true; | |||
for( Iterator e = filesets.iterator(); e.hasNext(); ) | |||
{ | |||
TarFileSet fs = (TarFileSet)e.next(); | |||
String[] files = ScannerUtil.getFiles( fs ); | |||
if( !archiveIsUpToDate( files ) ) | |||
{ | |||
upToDate = false; | |||
} | |||
for( int i = 0; i < files.length; ++i ) | |||
{ | |||
if( tarFile.equals( new File( fs.getDir(), files[ i ] ) ) ) | |||
{ | |||
throw new TaskException( "A tar file cannot include itself" ); | |||
} | |||
} | |||
} | |||
if( upToDate ) | |||
{ | |||
getContext().info( "Nothing to do: " + tarFile.getAbsolutePath() + " is up to date." ); | |||
return; | |||
} | |||
getContext().info( "Building tar: " + tarFile.getAbsolutePath() ); | |||
TarOutputStream tOut = null; | |||
try | |||
{ | |||
tOut = new TarOutputStream( new FileOutputStream( tarFile ) ); | |||
if( longFileMode.isTruncateMode() ) | |||
{ | |||
tOut.setLongFileMode( TarOutputStream.LONGFILE_TRUNCATE ); | |||
} | |||
else if( longFileMode.isFailMode() || | |||
longFileMode.isOmitMode() ) | |||
{ | |||
tOut.setLongFileMode( TarOutputStream.LONGFILE_ERROR ); | |||
} | |||
else | |||
{ | |||
// warn or GNU | |||
tOut.setLongFileMode( TarOutputStream.LONGFILE_GNU ); | |||
} | |||
longWarningGiven = false; | |||
for( Iterator e = filesets.iterator(); e.hasNext(); ) | |||
{ | |||
TarFileSet fs = (TarFileSet)e.next(); | |||
String[] files = ScannerUtil.getFiles( fs ); | |||
for( int i = 0; i < files.length; i++ ) | |||
{ | |||
File f = new File( fs.getDir(), files[ i ] ); | |||
String name = files[ i ].replace( File.separatorChar, '/' ); | |||
tarFile( f, tOut, name, fs ); | |||
} | |||
} | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
String msg = "Problem creating TAR: " + ioe.getMessage(); | |||
throw new TaskException( msg, ioe ); | |||
} | |||
finally | |||
{ | |||
if( tOut != null ) | |||
{ | |||
try | |||
{ | |||
// close up | |||
tOut.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
private boolean archiveIsUpToDate( final String[] files ) | |||
throws TaskException | |||
{ | |||
final SourceFileScanner scanner = new SourceFileScanner(); | |||
final MergingMapper mapper = new MergingMapper(); | |||
mapper.setTo( tarFile.getAbsolutePath() ); | |||
return scanner.restrict( files, baseDir, null, mapper, getContext() ).length == 0; | |||
} | |||
private void tarFile( final File file, | |||
final TarOutputStream output, | |||
final String path, | |||
final TarFileSet tarFileSet ) | |||
throws IOException, TaskException | |||
{ | |||
String storedPath = path; | |||
// don't add "" to the archive | |||
if( storedPath.length() <= 0 ) | |||
{ | |||
return; | |||
} | |||
if( file.isDirectory() && !storedPath.endsWith( "/" ) ) | |||
{ | |||
storedPath += "/"; | |||
} | |||
if( storedPath.length() >= TarEntry.NAMELEN ) | |||
{ | |||
if( longFileMode.isOmitMode() ) | |||
{ | |||
final String message = "Omitting: " + storedPath; | |||
getContext().info( message ); | |||
return; | |||
} | |||
else if( longFileMode.isWarnMode() ) | |||
{ | |||
final String message = "Entry: " + storedPath + " longer than " + | |||
TarEntry.NAMELEN + " characters."; | |||
getContext().warn( message ); | |||
if( !longWarningGiven ) | |||
{ | |||
final String message2 = "Resulting tar file can only be processed successfully" | |||
+ " by GNU compatible tar commands"; | |||
getContext().warn( message2 ); | |||
longWarningGiven = true; | |||
} | |||
} | |||
else if( longFileMode.isFailMode() ) | |||
{ | |||
final String message = "Entry: " + storedPath + " longer than " + | |||
TarEntry.NAMELEN + "characters."; | |||
throw new TaskException( message ); | |||
} | |||
} | |||
FileInputStream input = null; | |||
try | |||
{ | |||
final TarEntry entry = new TarEntry( storedPath ); | |||
entry.setModTime( file.lastModified() ); | |||
if( !file.isDirectory() ) | |||
{ | |||
entry.setSize( file.length() ); | |||
entry.setMode( tarFileSet.getMode() ); | |||
} | |||
entry.setUserName( tarFileSet.getUserName() ); | |||
entry.setGroupName( tarFileSet.getGroup() ); | |||
output.putNextEntry( entry ); | |||
if( !file.isDirectory() ) | |||
{ | |||
input = new FileInputStream( file ); | |||
IOUtil.copy( input, output ); | |||
} | |||
output.closeEntry(); | |||
} | |||
finally | |||
{ | |||
IOUtil.shutdownStream( input ); | |||
} | |||
} | |||
} |
@@ -1,48 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import org.apache.tools.todo.types.FileSet; | |||
public class TarFileSet | |||
extends FileSet | |||
{ | |||
private int m_mode = 0100644; | |||
private String m_userName = ""; | |||
private String m_groupName = ""; | |||
public void setGroup( final String groupName ) | |||
{ | |||
m_groupName = groupName; | |||
} | |||
public void setMode( final String octalString ) | |||
{ | |||
m_mode = 0100000 | Integer.parseInt( octalString, 8 ); | |||
} | |||
public void setUserName( final String userName ) | |||
{ | |||
m_userName = userName; | |||
} | |||
protected String getGroup() | |||
{ | |||
return m_groupName; | |||
} | |||
protected int getMode() | |||
{ | |||
return m_mode; | |||
} | |||
protected String getUserName() | |||
{ | |||
return m_userName; | |||
} | |||
} |
@@ -1,66 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
/** | |||
* Valid Modes for LongFile attribute to Tar Task | |||
* | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
*/ | |||
public class TarLongFileMode | |||
extends EnumeratedAttribute | |||
{ | |||
// permissable values for longfile attribute | |||
public final static String WARN = "warn"; | |||
public final static String FAIL = "fail"; | |||
public final static String TRUNCATE = "truncate"; | |||
public final static String GNU = "gnu"; | |||
public final static String OMIT = "omit"; | |||
private final String[] validModes = {WARN, FAIL, TRUNCATE, GNU, OMIT}; | |||
public TarLongFileMode() | |||
throws TaskException | |||
{ | |||
super(); | |||
setValue( WARN ); | |||
} | |||
public String[] getValues() | |||
{ | |||
return validModes; | |||
} | |||
public boolean isFailMode() | |||
{ | |||
return FAIL.equalsIgnoreCase( getValue() ); | |||
} | |||
public boolean isGnuMode() | |||
{ | |||
return GNU.equalsIgnoreCase( getValue() ); | |||
} | |||
public boolean isOmitMode() | |||
{ | |||
return OMIT.equalsIgnoreCase( getValue() ); | |||
} | |||
public boolean isTruncateMode() | |||
{ | |||
return TRUNCATE.equalsIgnoreCase( getValue() ); | |||
} | |||
public boolean isWarnMode() | |||
{ | |||
return WARN.equalsIgnoreCase( getValue() ); | |||
} | |||
} |
@@ -1,54 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import org.apache.aut.tar.TarEntry; | |||
import org.apache.aut.tar.TarInputStream; | |||
import org.apache.avalon.excalibur.io.IOUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.taskdefs.archive.Expand; | |||
/** | |||
* Untar a file. Heavily based on the Expand task. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public class Untar | |||
extends Expand | |||
{ | |||
protected void expandArchive( final File src, final File dir ) | |||
throws IOException, TaskException | |||
{ | |||
TarInputStream input = null; | |||
FileInputStream fileInput = null; | |||
try | |||
{ | |||
fileInput = new FileInputStream( src ); | |||
input = new TarInputStream( fileInput ); | |||
TarEntry entry = null; | |||
while( ( entry = input.getNextEntry() ) != null ) | |||
{ | |||
extractFile( dir, | |||
input, | |||
entry.getName(), | |||
entry.getModTime(), | |||
entry.isDirectory() ); | |||
} | |||
} | |||
finally | |||
{ | |||
IOUtil.shutdownStream( fileInput ); | |||
IOUtil.shutdownStream( input ); | |||
} | |||
} | |||
} |
@@ -1,54 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.Date; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipInputStream; | |||
import org.apache.avalon.excalibur.io.IOUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.taskdefs.archive.Expand; | |||
/** | |||
* Untar a file. Heavily based on the Expand task. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public class Unzip | |||
extends Expand | |||
{ | |||
protected void expandArchive( final File src, final File dir ) | |||
throws IOException, TaskException | |||
{ | |||
ZipInputStream zis = null; | |||
try | |||
{ | |||
// code from WarExpand | |||
zis = new ZipInputStream( new FileInputStream( src ) ); | |||
ZipEntry ze = null; | |||
while( ( ze = zis.getNextEntry() ) != null ) | |||
{ | |||
final Date date = new Date( ze.getTime() ); | |||
extractFile( dir, | |||
zis, | |||
ze.getName(), | |||
date, | |||
ze.isDirectory() ); | |||
} | |||
} | |||
finally | |||
{ | |||
IOUtil.shutdownStream( zis ); | |||
} | |||
} | |||
} |
@@ -1,112 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.aut.zip.ZipOutputStream; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.archive.Jar; | |||
/** | |||
* Creates a WAR archive. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class War | |||
extends Jar | |||
{ | |||
private File m_webxml; | |||
private boolean m_descriptorAdded; | |||
public War() | |||
{ | |||
super(); | |||
m_archiveType = "war"; | |||
m_emptyBehavior = "create"; | |||
} | |||
public void setWebxml( final File descr ) | |||
throws TaskException | |||
{ | |||
m_webxml = descr; | |||
if( !m_webxml.exists() ) | |||
{ | |||
final String message = "Deployment descriptor: " + | |||
m_webxml + " does not exist."; | |||
throw new TaskException( message ); | |||
} | |||
addFileAs( descr, "WEB-INF/web.xml" ); | |||
} | |||
public void addClasses( final ZipFileSet fs ) | |||
{ | |||
// We just set the prefix for this fileset, and pass it up. | |||
fs.setPrefix( "WEB-INF/classes/" ); | |||
super.addFileset( fs ); | |||
} | |||
public void addLib( final ZipFileSet fs ) | |||
{ | |||
// We just set the prefix for this fileset, and pass it up. | |||
fs.setPrefix( "WEB-INF/lib/" ); | |||
super.addFileset( fs ); | |||
} | |||
public void addWebinf( final ZipFileSet fs ) | |||
{ | |||
// We just set the prefix for this fileset, and pass it up. | |||
fs.setPrefix( "WEB-INF/" ); | |||
super.addFileset( fs ); | |||
} | |||
protected void initZipOutputStream( final ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
// If no webxml file is specified, it's an error. | |||
if( m_webxml == null && !isInUpdateMode() ) | |||
{ | |||
throw new TaskException( "webxml attribute is required" ); | |||
} | |||
super.initZipOutputStream( zOut ); | |||
} | |||
protected void zipFile( final File file, | |||
final ZipOutputStream zOut, | |||
final String vPath ) | |||
throws IOException, TaskException | |||
{ | |||
// If the file being added is WEB-INF/web.xml, we warn if it's not the | |||
// one specified in the "webxml" attribute - or if it's being added twice, | |||
// meaning the same file is specified by the "webxml" attribute and in | |||
// a <fileset> element. | |||
if( vPath.equalsIgnoreCase( "WEB-INF/web.xml" ) ) | |||
{ | |||
if( m_webxml == null || !m_webxml.equals( file ) || m_descriptorAdded ) | |||
{ | |||
final String message = "Warning: selected " + m_archiveType + | |||
" files include a WEB-INF/web.xml which will be ignored " + | |||
"(please use webxml attribute to " + m_archiveType + " task)"; | |||
getContext().warn( message ); | |||
} | |||
else | |||
{ | |||
super.zipFile( file, zOut, vPath ); | |||
m_descriptorAdded = true; | |||
} | |||
} | |||
else | |||
{ | |||
super.zipFile( file, zOut, vPath ); | |||
} | |||
} | |||
} |
@@ -1,22 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
/** | |||
* Possible behaviors when there are no matching files for the task. | |||
*/ | |||
public class WhenEmpty | |||
extends EnumeratedAttribute | |||
{ | |||
public String[] getValues() | |||
{ | |||
return new String[]{"fail", "skip", "create"}; | |||
} | |||
} |
@@ -1,898 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Stack; | |||
import java.util.zip.CRC32; | |||
import java.util.zip.ZipInputStream; | |||
import org.apache.aut.zip.ZipEntry; | |||
import org.apache.aut.zip.ZipOutputStream; | |||
import org.apache.avalon.excalibur.io.IOUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.taskdefs.archive.WhenEmpty; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
import org.apache.tools.todo.types.SourceFileScanner; | |||
import org.apache.tools.todo.util.mappers.MergingMapper; | |||
/** | |||
* Create a ZIP archive. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class Zip | |||
extends MatchingTask | |||
{ | |||
// For directories: | |||
private final static long EMPTY_CRC = new CRC32().getValue(); | |||
private boolean m_compress = true; | |||
private boolean m_update; | |||
private boolean m_filesonly; | |||
protected String m_archiveType = "zip"; | |||
protected String m_emptyBehavior = "skip"; | |||
private ArrayList m_filesets = new ArrayList(); | |||
protected Hashtable m_addedDirs = new Hashtable(); | |||
private ArrayList m_addedFiles = new ArrayList(); | |||
protected File m_file; | |||
/** | |||
* true when we are adding new files into the Zip file, as opposed to adding | |||
* back the unchanged files | |||
*/ | |||
private boolean m_addingNewFiles; | |||
private File m_baseDir; | |||
/** | |||
* Encoding to use for filenames, defaults to the platform's default | |||
* encoding. | |||
*/ | |||
private String m_encoding; | |||
private static String[][] grabFileNames( final FileScanner[] scanners ) | |||
throws TaskException | |||
{ | |||
String[][] result = new String[ scanners.length ][]; | |||
for( int i = 0; i < scanners.length; i++ ) | |||
{ | |||
String[] files = scanners[ i ].getIncludedFiles(); | |||
String[] dirs = scanners[ i ].getIncludedDirectories(); | |||
result[ i ] = new String[ files.length + dirs.length ]; | |||
System.arraycopy( files, 0, result[ i ], 0, files.length ); | |||
System.arraycopy( dirs, 0, result[ i ], files.length, dirs.length ); | |||
} | |||
return result; | |||
} | |||
private static File[] grabFiles( final FileScanner[] scanners, | |||
final String[][] filenames ) | |||
{ | |||
final ArrayList files = new ArrayList(); | |||
for( int i = 0; i < filenames.length; i++ ) | |||
{ | |||
final File baseDir = scanners[ i ].getBasedir(); | |||
for( int j = 0; j < filenames[ i ].length; j++ ) | |||
{ | |||
files.add( new File( baseDir, filenames[ i ][ j ] ) ); | |||
} | |||
} | |||
final File[] toret = new File[ files.size() ]; | |||
return (File[])files.toArray( toret ); | |||
} | |||
/** | |||
* This is the base directory to look in for things to zip. | |||
* | |||
* @param baseDir The new Basedir value | |||
*/ | |||
public void setBasedir( final File baseDir ) | |||
{ | |||
m_baseDir = baseDir; | |||
} | |||
/** | |||
* Sets whether we want to compress the files or only store them. | |||
* | |||
* @param compress The new Compress value | |||
*/ | |||
public void setCompress( final boolean compress ) | |||
{ | |||
m_compress = compress; | |||
} | |||
/** | |||
* Encoding to use for filenames, defaults to the platform's default | |||
* encoding. <p> | |||
* | |||
* For a list of possible values see <a | |||
* href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html"> | |||
* http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html | |||
* </a>.</p> | |||
* | |||
* @param encoding The new Encoding value | |||
*/ | |||
public void setEncoding( final String encoding ) | |||
{ | |||
m_encoding = encoding; | |||
} | |||
/** | |||
* This is the name/location of where to create the .zip file. | |||
* | |||
* @param file The new File value | |||
*/ | |||
public void setFile( final File file ) | |||
{ | |||
m_file = file; | |||
} | |||
/** | |||
* Emulate Sun's jar utility by not adding parent dirs | |||
*/ | |||
public void setFilesonly( final boolean filesonly ) | |||
{ | |||
m_filesonly = filesonly; | |||
} | |||
/** | |||
* Sets whether we want to update the file (if it exists) or create a new | |||
* one. | |||
*/ | |||
public void setUpdate( final boolean update ) | |||
{ | |||
m_update = update; | |||
} | |||
/** | |||
* Sets behavior of the task when no files match. Possible values are: | |||
* <code>fail</code> (throw an exception and halt the build); <code>skip</code> | |||
* (do not create any archive, but issue a warning); <code>create</code> | |||
* (make an archive with no entries). Default for zip tasks is <code>skip</code> | |||
* ; for jar tasks, <code>create</code>. | |||
* | |||
* @param we The new Whenempty value | |||
*/ | |||
public void setWhenempty( final WhenEmpty we ) | |||
{ | |||
m_emptyBehavior = we.getValue(); | |||
} | |||
/** | |||
* Are we updating an existing archive? | |||
* | |||
* @return The InUpdateMode value | |||
*/ | |||
protected final boolean isInUpdateMode() | |||
{ | |||
return m_update; | |||
} | |||
/** | |||
* Adds a set of files (nested fileset attribute). | |||
*/ | |||
public void addFileset( final FileSet set ) | |||
{ | |||
m_filesets.add( set ); | |||
} | |||
/** | |||
* Adds a set of files (nested zipfileset attribute) that can be read from | |||
* an archive and be given a prefix/fullpath. | |||
* | |||
* @param set The feature to be added to the Zipfileset attribute | |||
*/ | |||
public void addZipfileset( final ZipFileSet set ) | |||
{ | |||
m_filesets.add( set ); | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( m_baseDir == null && m_filesets.size() == 0 && | |||
"zip".equals( m_archiveType ) ) | |||
{ | |||
final String message = "basedir attribute must be set, or at least " + | |||
"one fileset must be given!"; | |||
throw new TaskException( message ); | |||
} | |||
if( m_file == null ) | |||
{ | |||
final String message = "You must specify the " + | |||
m_archiveType + " file to create!"; | |||
throw new TaskException( message ); | |||
} | |||
// Renamed version of original file, if it exists | |||
File renamedFile = null; | |||
// Whether or not an actual update is required - | |||
// we don't need to update if the original file doesn't exist | |||
m_addingNewFiles = true; | |||
m_update = m_update && m_file.exists(); | |||
if( m_update ) | |||
{ | |||
try | |||
{ | |||
renamedFile = File.createTempFile( "zip", ".tmp", | |||
m_file.getParentFile() ); | |||
} | |||
catch( final IOException ioe ) | |||
{ | |||
throw new TaskException( ioe.toString(), ioe ); | |||
} | |||
try | |||
{ | |||
if( !m_file.renameTo( renamedFile ) ) | |||
{ | |||
throw new TaskException( "Unable to rename old file to temporary file" ); | |||
} | |||
} | |||
catch( SecurityException e ) | |||
{ | |||
throw new TaskException( "Not allowed to rename old file to temporary file" ); | |||
} | |||
} | |||
// Create the scanners to pass to isUpToDate(). | |||
ArrayList dss = new ArrayList(); | |||
if( m_baseDir != null ) | |||
{ | |||
dss.add( getDirectoryScanner( m_baseDir ) ); | |||
} | |||
final int size = m_filesets.size(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final FileSet fileSet = (FileSet)m_filesets.get( i ); | |||
final DirectoryScanner scanner = getScanner( fileSet ); | |||
dss.add( scanner ); | |||
} | |||
int dssSize = dss.size(); | |||
FileScanner[] scanners = new FileScanner[ dssSize ]; | |||
scanners = (FileScanner[])dss.toArray( scanners ); | |||
// quick exit if the target is up to date | |||
// can also handle empty archives | |||
if( isUpToDate( scanners, m_file ) ) | |||
{ | |||
return; | |||
} | |||
String action = m_update ? "Updating " : "Building "; | |||
getContext().info( action + m_archiveType + ": " + m_file.getAbsolutePath() ); | |||
boolean success = false; | |||
try | |||
{ | |||
ZipOutputStream zOut = | |||
new ZipOutputStream( new FileOutputStream( m_file ) ); | |||
zOut.setEncoding( m_encoding ); | |||
try | |||
{ | |||
if( m_compress ) | |||
{ | |||
zOut.setMethod( ZipOutputStream.DEFLATED ); | |||
} | |||
else | |||
{ | |||
zOut.setMethod( ZipOutputStream.STORED ); | |||
} | |||
initZipOutputStream( zOut ); | |||
// Add the implicit fileset to the archive. | |||
if( m_baseDir != null ) | |||
{ | |||
addFiles( getDirectoryScanner( m_baseDir ), zOut, "", "" ); | |||
} | |||
// Add the explicit filesets to the archive. | |||
addFiles( m_filesets, zOut ); | |||
if( m_update ) | |||
{ | |||
m_addingNewFiles = false; | |||
ZipFileSet oldFiles = new ZipFileSet(); | |||
oldFiles.setSrc( renamedFile ); | |||
StringBuffer exclusionPattern = new StringBuffer(); | |||
final int addedFilesCount = m_addedFiles.size(); | |||
for( int i = 0; i < addedFilesCount; i++ ) | |||
{ | |||
if( i != 0 ) | |||
{ | |||
exclusionPattern.append( "," ); | |||
} | |||
exclusionPattern.append( (String)m_addedFiles.get( i ) ); | |||
} | |||
oldFiles.setExcludes( exclusionPattern.toString() ); | |||
ArrayList tmp = new ArrayList(); | |||
tmp.add( oldFiles ); | |||
addFiles( tmp, zOut ); | |||
} | |||
finalizeZipOutputStream( zOut ); | |||
success = true; | |||
} | |||
finally | |||
{ | |||
// Close the output stream. | |||
try | |||
{ | |||
if( zOut != null ) | |||
{ | |||
zOut.close(); | |||
} | |||
} | |||
catch( IOException ex ) | |||
{ | |||
// If we're in this finally clause because of an exception, we don't | |||
// really care if there's an exception when closing the stream. E.g. if it | |||
// throws "ZIP file must have at least one entry", because an exception happened | |||
// before we added any files, then we must swallow this exception. Otherwise, | |||
// the error that's reported will be the close() error, which is not the real | |||
// cause of the problem. | |||
if( success ) | |||
{ | |||
throw ex; | |||
} | |||
} | |||
} | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
String msg = "Problem creating " + m_archiveType + ": " + ioe.getMessage(); | |||
// delete a bogus ZIP file | |||
if( !m_file.delete() ) | |||
{ | |||
msg += " (and the archive is probably corrupt but I could not delete it)"; | |||
} | |||
if( m_update ) | |||
{ | |||
if( !renamedFile.renameTo( m_file ) ) | |||
{ | |||
msg += " (and I couldn't rename the temporary file " + | |||
renamedFile.getName() + " back)"; | |||
} | |||
} | |||
throw new TaskException( msg, ioe ); | |||
} | |||
// If we've been successful on an update, delete the temporary file | |||
if( success && m_update ) | |||
{ | |||
if( !renamedFile.delete() ) | |||
{ | |||
final String message = "Warning: unable to delete temporary file " + | |||
renamedFile.getName(); | |||
getContext().warn( message ); | |||
} | |||
} | |||
} | |||
private DirectoryScanner getScanner( final FileSet fileSet ) | |||
throws TaskException | |||
{ | |||
if( fileSet instanceof ZipFileSet ) | |||
{ | |||
final ZipFileSet zipFileSet = (ZipFileSet)fileSet; | |||
return ScannerUtil.getZipScanner( zipFileSet ); | |||
} | |||
else | |||
{ | |||
return ScannerUtil.getDirectoryScanner( fileSet ); | |||
} | |||
} | |||
protected void addFileAs( final File file, final String name ) | |||
throws TaskException | |||
{ | |||
// Create a ZipFileSet for this file, and pass it up. | |||
final ZipFileSet fs = new ZipFileSet(); | |||
fs.setDir( file.getParentFile() ); | |||
fs.setIncludes( file.getName() ); | |||
fs.setFullpath( name ); | |||
addFileset( fs ); | |||
} | |||
/** | |||
* Indicates if the task is adding new files into the archive as opposed to | |||
* copying back unchanged files from the backup copy | |||
* | |||
* @return The AddingNewFiles value | |||
*/ | |||
protected final boolean isAddingNewFiles() | |||
{ | |||
return m_addingNewFiles; | |||
} | |||
/** | |||
* Check whether the archive is up-to-date; and handle behavior for empty | |||
* archives. | |||
* | |||
* @param scanners list of prepared scanners containing files to archive | |||
* @param zipFile intended archive file (may or may not exist) | |||
* @return true if nothing need be done (may have done something already); | |||
* false if archive creation should proceed | |||
* @exception org.apache.myrmidon.api.TaskException if it likes | |||
*/ | |||
protected boolean isUpToDate( FileScanner[] scanners, File zipFile ) | |||
throws TaskException | |||
{ | |||
String[][] fileNames = grabFileNames( scanners ); | |||
File[] files = grabFiles( scanners, fileNames ); | |||
if( files.length == 0 ) | |||
{ | |||
if( m_emptyBehavior.equals( "skip" ) ) | |||
{ | |||
final String message = "Warning: skipping " + m_archiveType + " archive " + zipFile + | |||
" because no files were included."; | |||
getContext().warn( message ); | |||
return true; | |||
} | |||
else if( m_emptyBehavior.equals( "fail" ) ) | |||
{ | |||
throw new TaskException( "Cannot create " + m_archiveType + " archive " + zipFile + | |||
": no files were included." ); | |||
} | |||
else | |||
{ | |||
// Create. | |||
return createEmptyZip( zipFile ); | |||
} | |||
} | |||
else | |||
{ | |||
for( int i = 0; i < files.length; ++i ) | |||
{ | |||
if( files[ i ].equals( zipFile ) ) | |||
{ | |||
throw new TaskException( "A zip file cannot include itself" ); | |||
} | |||
} | |||
if( !zipFile.exists() ) | |||
{ | |||
return false; | |||
} | |||
final SourceFileScanner scanner = new SourceFileScanner(); | |||
MergingMapper mm = new MergingMapper(); | |||
mm.setTo( zipFile.getAbsolutePath() ); | |||
for( int i = 0; i < scanners.length; i++ ) | |||
{ | |||
if( scanner.restrict( fileNames[ i ], scanners[ i ].getBasedir(), null, | |||
mm, getContext() ).length > 0 ) | |||
{ | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
} | |||
/** | |||
* Add all files of the given FileScanner to the ZipOutputStream prependig | |||
* the given prefix to each filename. <p> | |||
* | |||
* Ensure parent directories have been added as well. | |||
* | |||
* @param scanner The feature to be added to the Files attribute | |||
* @param zOut The feature to be added to the Files attribute | |||
* @param prefix The feature to be added to the Files attribute | |||
* @param fullpath The feature to be added to the Files attribute | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
protected void addFiles( FileScanner scanner, ZipOutputStream zOut, | |||
String prefix, String fullpath ) | |||
throws IOException, TaskException | |||
{ | |||
if( prefix.length() > 0 && fullpath.length() > 0 ) | |||
{ | |||
throw new TaskException( "Both prefix and fullpath attributes may not be set on the same fileset." ); | |||
} | |||
File thisBaseDir = scanner.getBasedir(); | |||
// directories that matched include patterns | |||
String[] dirs = scanner.getIncludedDirectories(); | |||
if( dirs.length > 0 && fullpath.length() > 0 ) | |||
{ | |||
throw new TaskException( "fullpath attribute may only be specified for filesets that specify a single file." ); | |||
} | |||
for( int i = 0; i < dirs.length; i++ ) | |||
{ | |||
final String dir = dirs[ i ]; | |||
if( "".equals( dir ) ) | |||
{ | |||
continue; | |||
} | |||
final String name = getName( dir ); | |||
addParentDirs( thisBaseDir, name, zOut, prefix ); | |||
} | |||
// files that matched include patterns | |||
String[] files = scanner.getIncludedFiles(); | |||
if( files.length > 1 && fullpath.length() > 0 ) | |||
{ | |||
throw new TaskException( "fullpath attribute may only be specified for filesets that specify a single file." ); | |||
} | |||
for( int i = 0; i < files.length; i++ ) | |||
{ | |||
File f = new File( thisBaseDir, files[ i ] ); | |||
if( fullpath.length() > 0 ) | |||
{ | |||
// Add this file at the specified location. | |||
addParentDirs( null, fullpath, zOut, "" ); | |||
zipFile( f, zOut, fullpath ); | |||
} | |||
else | |||
{ | |||
// Add this file with the specified prefix. | |||
String name = files[ i ].replace( File.separatorChar, '/' ); | |||
addParentDirs( thisBaseDir, name, zOut, prefix ); | |||
zipFile( f, zOut, prefix + name ); | |||
} | |||
} | |||
} | |||
private String getName( final String dir ) | |||
{ | |||
String name = dir.replace( File.separatorChar, '/' ); | |||
if( !name.endsWith( "/" ) ) | |||
{ | |||
name += "/"; | |||
} | |||
return name; | |||
} | |||
/** | |||
* Iterate over the given ArrayList of (zip)filesets and add all files to the | |||
* ZipOutputStream using the given prefix or fullpath. | |||
* | |||
* @param filesets The feature to be added to the Files attribute | |||
* @param zOut The feature to be added to the Files attribute | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
protected void addFiles( ArrayList filesets, ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
// Add each fileset in the ArrayList. | |||
final int size = filesets.size(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
FileSet fs = (FileSet)filesets.get( i ); | |||
DirectoryScanner ds = getScanner( fs ); | |||
String prefix = ""; | |||
String fullpath = ""; | |||
if( fs instanceof ZipFileSet ) | |||
{ | |||
ZipFileSet zfs = (ZipFileSet)fs; | |||
prefix = getPrefix( zfs.getPrefix() ); | |||
fullpath = zfs.getFullpath(); | |||
} | |||
// Need to manually add either fullpath's parent directory, or | |||
// the prefix directory, to the archive. | |||
if( prefix.length() > 0 ) | |||
{ | |||
addParentDirs( null, prefix, zOut, "" ); | |||
zipDir( null, zOut, prefix ); | |||
} | |||
else if( fullpath.length() > 0 ) | |||
{ | |||
addParentDirs( null, fullpath, zOut, "" ); | |||
} | |||
if( fs instanceof ZipFileSet | |||
&& ( (ZipFileSet)fs ).getSrc() != null ) | |||
{ | |||
addZipEntries( (ZipFileSet)fs, ds, zOut, prefix, fullpath ); | |||
} | |||
else | |||
{ | |||
// Add the fileset. | |||
addFiles( ds, zOut, prefix, fullpath ); | |||
} | |||
} | |||
} | |||
private String getPrefix( final String prefix ) | |||
{ | |||
String result = prefix; | |||
if( result.length() > 0 | |||
&& !result.endsWith( "/" ) | |||
&& !result.endsWith( "\\" ) ) | |||
{ | |||
result += "/"; | |||
} | |||
return result; | |||
} | |||
/** | |||
* Ensure all parent dirs of a given entry have been added. | |||
* | |||
* @param baseDir The feature to be added to the ParentDirs attribute | |||
* @param entry The feature to be added to the ParentDirs attribute | |||
* @param zOut The feature to be added to the ParentDirs attribute | |||
* @param prefix The feature to be added to the ParentDirs attribute | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
protected void addParentDirs( File baseDir, String entry, | |||
ZipOutputStream zOut, String prefix ) | |||
throws IOException | |||
{ | |||
if( !m_filesonly ) | |||
{ | |||
Stack directories = new Stack(); | |||
int slashPos = entry.length(); | |||
while( ( slashPos = entry.lastIndexOf( '/', slashPos - 1 ) ) != -1 ) | |||
{ | |||
String dir = entry.substring( 0, slashPos + 1 ); | |||
if( m_addedDirs.get( prefix + dir ) != null ) | |||
{ | |||
break; | |||
} | |||
directories.push( dir ); | |||
} | |||
while( !directories.isEmpty() ) | |||
{ | |||
String dir = (String)directories.pop(); | |||
File f = null; | |||
if( baseDir != null ) | |||
{ | |||
f = new File( baseDir, dir ); | |||
} | |||
else | |||
{ | |||
f = new File( dir ); | |||
} | |||
zipDir( f, zOut, prefix + dir ); | |||
} | |||
} | |||
} | |||
protected void addZipEntries( ZipFileSet fs, DirectoryScanner ds, | |||
ZipOutputStream zOut, String prefix, String fullpath ) | |||
throws IOException, TaskException | |||
{ | |||
if( prefix.length() > 0 && fullpath.length() > 0 ) | |||
{ | |||
throw new TaskException( "Both prefix and fullpath attributes may not be set on the same fileset." ); | |||
} | |||
ZipScanner zipScanner = (ZipScanner)ds; | |||
File zipSrc = fs.getSrc(); | |||
ZipEntry entry; | |||
java.util.zip.ZipEntry origEntry; | |||
ZipInputStream in = null; | |||
try | |||
{ | |||
in = new ZipInputStream( new FileInputStream( zipSrc ) ); | |||
while( ( origEntry = in.getNextEntry() ) != null ) | |||
{ | |||
entry = new ZipEntry( origEntry ); | |||
String vPath = entry.getName(); | |||
if( zipScanner.match( vPath ) ) | |||
{ | |||
if( fullpath.length() > 0 ) | |||
{ | |||
addParentDirs( null, fullpath, zOut, "" ); | |||
zipFile( in, zOut, fullpath, entry.getTime() ); | |||
} | |||
else | |||
{ | |||
addParentDirs( null, vPath, zOut, prefix ); | |||
if( !entry.isDirectory() ) | |||
{ | |||
zipFile( in, zOut, prefix + vPath, entry.getTime() ); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
finally | |||
{ | |||
if( in != null ) | |||
{ | |||
in.close(); | |||
} | |||
} | |||
} | |||
/** | |||
* Create an empty zip file | |||
* | |||
* @param zipFile Description of Parameter | |||
* @return true if the file is then considered up to date. | |||
*/ | |||
protected boolean createEmptyZip( File zipFile ) | |||
throws TaskException | |||
{ | |||
// In this case using java.util.zip will not work | |||
// because it does not permit a zero-entry archive. | |||
// Must create it manually. | |||
getContext().info( "Note: creating empty " + m_archiveType + " archive " + zipFile ); | |||
try | |||
{ | |||
OutputStream os = new FileOutputStream( zipFile ); | |||
try | |||
{ | |||
// Cf. PKZIP specification. | |||
byte[] empty = new byte[ 22 ]; | |||
empty[ 0 ] = 80;// P | |||
empty[ 1 ] = 75;// K | |||
empty[ 2 ] = 5; | |||
empty[ 3 ] = 6; | |||
// remainder zeros | |||
os.write( empty ); | |||
} | |||
finally | |||
{ | |||
os.close(); | |||
} | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
throw new TaskException( "Could not create empty ZIP archive", ioe ); | |||
} | |||
return true; | |||
} | |||
protected void finalizeZipOutputStream( ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
} | |||
protected void initZipOutputStream( ZipOutputStream zOut ) | |||
throws IOException, TaskException | |||
{ | |||
} | |||
protected void zipDir( File dir, ZipOutputStream zOut, String vPath ) | |||
throws IOException | |||
{ | |||
if( m_addedDirs.get( vPath ) != null ) | |||
{ | |||
// don't add directories we've already added. | |||
// no warning if we try, it is harmless in and of itself | |||
return; | |||
} | |||
m_addedDirs.put( vPath, vPath ); | |||
ZipEntry ze = new ZipEntry( vPath ); | |||
if( dir != null && dir.exists() ) | |||
{ | |||
ze.setTime( dir.lastModified() ); | |||
} | |||
else | |||
{ | |||
ze.setTime( System.currentTimeMillis() ); | |||
} | |||
ze.setSize( 0 ); | |||
ze.setMethod( ZipEntry.STORED ); | |||
// This is faintly ridiculous: | |||
ze.setCrc( EMPTY_CRC ); | |||
// this is 040775 | MS-DOS directory flag in reverse byte order | |||
ze.setExternalAttributes( 0x41FD0010L ); | |||
zOut.putNextEntry( ze ); | |||
} | |||
protected void zipFile( final InputStream input, | |||
final ZipOutputStream output, | |||
final String path, | |||
final long lastModified ) | |||
throws IOException, TaskException | |||
{ | |||
final ZipEntry entry = new ZipEntry( path ); | |||
entry.setTime( lastModified ); | |||
/* | |||
* XXX ZipOutputStream.putEntry expects the ZipEntry to know its | |||
* size and the CRC sum before you start writing the data when using | |||
* STORED mode. | |||
* | |||
* This forces us to process the data twice. | |||
* | |||
* I couldn't find any documentation on this, just found out by try | |||
* and error. | |||
*/ | |||
InputStream inputToStore = input; | |||
if( !m_compress ) | |||
{ | |||
final CRC32 crc = new CRC32(); | |||
long size = 0; | |||
if( !inputToStore.markSupported() ) | |||
{ | |||
// Store data into a byte[] | |||
ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |||
byte[] buffer = new byte[ 8 * 1024 ]; | |||
int count = 0; | |||
do | |||
{ | |||
size += count; | |||
crc.update( buffer, 0, count ); | |||
bos.write( buffer, 0, count ); | |||
count = inputToStore.read( buffer, 0, buffer.length ); | |||
} while( count != -1 ); | |||
inputToStore = new ByteArrayInputStream( bos.toByteArray() ); | |||
} | |||
else | |||
{ | |||
inputToStore.mark( Integer.MAX_VALUE ); | |||
byte[] buffer = new byte[ 8 * 1024 ]; | |||
int count = 0; | |||
do | |||
{ | |||
size += count; | |||
crc.update( buffer, 0, count ); | |||
count = inputToStore.read( buffer, 0, buffer.length ); | |||
} while( count != -1 ); | |||
inputToStore.reset(); | |||
} | |||
entry.setSize( size ); | |||
entry.setCrc( crc.getValue() ); | |||
} | |||
output.putNextEntry( entry ); | |||
IOUtil.copy( inputToStore, output ); | |||
m_addedFiles.add( path ); | |||
} | |||
protected void zipFile( final File file, | |||
final ZipOutputStream zOut, | |||
final String vPath ) | |||
throws IOException, TaskException | |||
{ | |||
if( file.equals( m_file ) ) | |||
{ | |||
final String message = "A zip file cannot include itself"; | |||
throw new TaskException( message ); | |||
} | |||
final FileInputStream fIn = new FileInputStream( file ); | |||
try | |||
{ | |||
zipFile( fIn, zOut, vPath, file.lastModified() ); | |||
} | |||
finally | |||
{ | |||
IOUtil.shutdownStream( fIn ); | |||
} | |||
} | |||
} |
@@ -1,98 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import org.apache.tools.todo.types.FileSet; | |||
/** | |||
* A ZipFileSet is a FileSet with extra attributes useful in the context of | |||
* Zip/Jar tasks. A ZipFileSet extends FileSets with the ability to extract a | |||
* subset of the entries of a Zip file for inclusion in another Zip file. It | |||
* also includes a prefix attribute which is prepended to each entry in the | |||
* output Zip file. At present, ZipFileSets are not surfaced in the public API. | |||
* FileSets nested in a Zip task are instantiated as ZipFileSets, and their | |||
* attributes are only recognized in the context of the the Zip task. It is not | |||
* possible to define a ZipFileSet outside of the Zip task and refer to it via a | |||
* refid. However a standard FileSet may be included by reference in the Zip | |||
* task, and attributes in the refering ZipFileSet can augment FileSet | |||
* definition. | |||
* | |||
* @author <a href="mailto:don@bea.com">Don Ferguson</a> | |||
*/ | |||
public class ZipFileSet | |||
extends FileSet | |||
{ | |||
private File m_src; | |||
private String m_prefix = ""; | |||
private String m_fullpath = ""; | |||
/** | |||
* Set the full pathname of the single entry in this fileset. | |||
* | |||
* @param fullpath The new Fullpath value | |||
*/ | |||
public void setFullpath( final String fullpath ) | |||
{ | |||
m_fullpath = fullpath; | |||
} | |||
/** | |||
* Prepend this prefix to the path for each zip entry. Does not perform | |||
* reference test; the referenced file set can be augmented with a prefix. | |||
* | |||
* @param prefix The prefix to prepend to entries in the zip file. | |||
*/ | |||
public void setPrefix( final String prefix ) | |||
{ | |||
m_prefix = prefix; | |||
} | |||
/** | |||
* Set the source Zip file for the zipfileset. Prevents both "dir" and "src" | |||
* from being specified. | |||
* | |||
* @param srcFile The zip file from which to extract entries. | |||
*/ | |||
public void setSrc( final File src ) | |||
{ | |||
m_src = src; | |||
} | |||
/** | |||
* Return the full pathname of the single entry in this fileset. | |||
* | |||
* @return The Fullpath value | |||
*/ | |||
public String getFullpath() | |||
{ | |||
return m_fullpath; | |||
} | |||
/** | |||
* Return the prefix prepended to entries in the zip file. | |||
* | |||
* @return The Prefix value | |||
*/ | |||
public String getPrefix() | |||
{ | |||
return m_prefix; | |||
} | |||
/** | |||
* Get the zip file from which entries will be extracted. References are not | |||
* followed, since it is not possible to have a reference to a ZipFileSet, | |||
* only to a FileSet. | |||
* | |||
* @return The Src value | |||
*/ | |||
public File getSrc() | |||
{ | |||
return m_src; | |||
} | |||
} |
@@ -1,98 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.archive; | |||
import java.io.File; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
/** | |||
* ZipScanner accesses the pattern matching algorithm in DirectoryScanner, which | |||
* are protected methods that can only be accessed by subclassing. This | |||
* implementation of FileScanner defines getIncludedFiles to return only the Zip | |||
* File which is being scanned, not the matching Zip entries. Arguably, it | |||
* should return the matching entries, however this would complicate existing | |||
* code which assumes that FileScanners return a set of file system files that | |||
* can be accessed directly. | |||
* | |||
* @author Don Ferguson <a href="mailto:don@bea.com">don@bea.com</a> | |||
*/ | |||
public class ZipScanner | |||
extends DirectoryScanner | |||
{ | |||
/** | |||
* The zip file which should be scanned. | |||
*/ | |||
private File m_src; | |||
/** | |||
* Sets the srcFile for scanning. This is the jar or zip file that is | |||
* scanned for matching entries. | |||
* | |||
* @param srcFile the (non-null) zip file name for scanning | |||
*/ | |||
public void setSrc( final File srcFile ) | |||
{ | |||
m_src = srcFile; | |||
} | |||
/** | |||
* Returns an empty list of directories to create. | |||
* | |||
* @return The IncludedDirectories value | |||
*/ | |||
public String[] getIncludedDirectories() | |||
{ | |||
return new String[ 0 ]; | |||
} | |||
/** | |||
* Returns the zip file itself, not the matching entries within the zip | |||
* file. This keeps the uptodate test in the Zip task simple; otherwise we'd | |||
* need to treat zip filesets specially. | |||
* | |||
* @return the source file from which entries will be extracted. | |||
*/ | |||
public String[] getIncludedFiles() | |||
{ | |||
final String[] result = new String[ 1 ]; | |||
result[ 0 ] = m_src.getAbsolutePath(); | |||
return result; | |||
} | |||
/** | |||
* Initialize DirectoryScanner data structures. | |||
*/ | |||
public void init() | |||
{ | |||
if( getIncludes() == null ) | |||
{ | |||
// No includes supplied, so set it to 'matches all' | |||
setIncludes( new String[ 1 ] ); | |||
getIncludes()[ 0 ] = "**"; | |||
} | |||
if( getExcludes() == null ) | |||
{ | |||
setExcludes( new String[ 0 ] ); | |||
} | |||
} | |||
/** | |||
* Matches a jar entry against the includes/excludes list, normalizing the | |||
* path separator. | |||
* | |||
* @param path the (non-null) path name to test for inclusion | |||
* @return <code>true</code> if the path should be included <code>false</code> | |||
* otherwise. | |||
*/ | |||
public boolean match( String path ) | |||
{ | |||
final String vpath = | |||
path.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); | |||
return isIncluded( vpath ) && !isExcluded( vpath ); | |||
} | |||
} |
@@ -1,155 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
import java.io.File; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Class common to all check commands (checkout, checkin,checkin default task); | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public class CCMCheck extends Continuus | |||
{ | |||
/** | |||
* -comment flag -- comment to attach to the file | |||
*/ | |||
public final static String FLAG_COMMENT = "/comment"; | |||
/** | |||
* -task flag -- associate checckout task with task | |||
*/ | |||
public final static String FLAG_TASK = "/task"; | |||
private File _file = null; | |||
private String _comment = null; | |||
private String _task = null; | |||
public CCMCheck() | |||
{ | |||
super(); | |||
} | |||
/** | |||
* Set the value of comment. | |||
* | |||
* @param v Value to assign to comment. | |||
*/ | |||
public void setComment( String v ) | |||
{ | |||
this._comment = v; | |||
} | |||
/** | |||
* Set the value of file. | |||
* | |||
* @param v Value to assign to file. | |||
*/ | |||
public void setFile( File v ) | |||
{ | |||
this._file = v; | |||
} | |||
/** | |||
* Set the value of task. | |||
* | |||
* @param v Value to assign to task. | |||
*/ | |||
public void setTask( String v ) | |||
{ | |||
this._task = v; | |||
} | |||
/** | |||
* Get the value of comment. | |||
* | |||
* @return value of comment. | |||
*/ | |||
public String getComment() | |||
{ | |||
return _comment; | |||
} | |||
/** | |||
* Get the value of file. | |||
* | |||
* @return value of file. | |||
*/ | |||
public File getFile() | |||
{ | |||
return _file; | |||
} | |||
/** | |||
* Get the value of task. | |||
* | |||
* @return value of task. | |||
*/ | |||
public String getTask() | |||
{ | |||
return _task; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute ccm and then calls Exec's run method to | |||
* execute the command line. </p> | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
Commandline commandLine = new Commandline(); | |||
// build the command line from what we got the format is | |||
// ccm co /t .. files | |||
// as specified in the CLEARTOOL.EXE help | |||
commandLine.setExecutable( getCcmCommand() ); | |||
commandLine.addArgument( getCcmAction() ); | |||
checkOptions( commandLine ); | |||
final int result = run( commandLine, null ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + commandLine.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/** | |||
* Check the command line options. | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void checkOptions( Commandline cmd ) | |||
{ | |||
if( getComment() != null ) | |||
{ | |||
cmd.addArgument( FLAG_COMMENT ); | |||
cmd.addArgument( getComment() ); | |||
} | |||
if( getTask() != null ) | |||
{ | |||
cmd.addArgument( FLAG_TASK ); | |||
cmd.addArgument( getTask() ); | |||
}// end of if () | |||
if( getFile() != null ) | |||
{ | |||
cmd.addArgument( _file.getAbsolutePath() ); | |||
}// end of if () | |||
} | |||
} | |||
@@ -1,28 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
import java.util.Date; | |||
/** | |||
* Task to perform Checkin command to Continuus | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public class CCMCheckin extends CCMCheck | |||
{ | |||
public CCMCheckin() | |||
{ | |||
super(); | |||
setCcmAction( COMMAND_CHECKIN ); | |||
setComment( "Checkin " + new Date() ); | |||
} | |||
} | |||
@@ -1,27 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
/** | |||
* Task to perform Checkin Default task command to Continuus | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public class CCMCheckinDefault extends CCMCheck | |||
{ | |||
public final static String DEFAULT_TASK = "default"; | |||
public CCMCheckinDefault() | |||
{ | |||
super(); | |||
setCcmAction( COMMAND_CHECKIN ); | |||
setTask( DEFAULT_TASK ); | |||
} | |||
} | |||
@@ -1,24 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
/** | |||
* Task to perform Checkout command to Continuus | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public class CCMCheckout extends CCMCheck | |||
{ | |||
public CCMCheckout() | |||
{ | |||
super(); | |||
setCcmAction( COMMAND_CHECKOUT ); | |||
} | |||
} | |||
@@ -1,256 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
import org.apache.aut.nativelib.ExecOutputHandler; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Task allows to create new ccm task and set it as the default | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public class CCMCreateTask | |||
extends Continuus | |||
implements ExecOutputHandler | |||
{ | |||
/** | |||
* /comment -- comments associated to the task | |||
*/ | |||
private final static String FLAG_COMMENT = "/synopsis"; | |||
/** | |||
* /platform flag -- target platform | |||
*/ | |||
private final static String FLAG_PLATFORM = "/plat"; | |||
/** | |||
* /resolver flag | |||
*/ | |||
private final static String FLAG_RESOLVER = "/resolver"; | |||
/** | |||
* /release flag | |||
*/ | |||
private final static String FLAG_RELEASE = "/release"; | |||
/** | |||
* /release flag | |||
*/ | |||
private final static String FLAG_SUBSYSTEM = "/subsystem"; | |||
/** | |||
* -task flag -- associate checckout task with task | |||
*/ | |||
private final static String FLAG_TASK = "/task"; | |||
private String m_comment; | |||
private String m_platform; | |||
private String m_resolver; | |||
private String m_release; | |||
private String m_subSystem; | |||
private String m_task; | |||
public CCMCreateTask() | |||
{ | |||
setCcmAction( COMMAND_CREATE_TASK ); | |||
} | |||
/** | |||
* Set the value of comment. | |||
* | |||
* @param v Value to assign to comment. | |||
*/ | |||
public void setComment( final String comment ) | |||
{ | |||
m_comment = comment; | |||
} | |||
/** | |||
* Set the value of platform. | |||
* | |||
* @param v Value to assign to platform. | |||
*/ | |||
public void setPlatform( final String platform ) | |||
{ | |||
m_platform = platform; | |||
} | |||
/** | |||
* Set the value of release. | |||
* | |||
* @param v Value to assign to release. | |||
*/ | |||
public void setRelease( final String release ) | |||
{ | |||
m_release = release; | |||
} | |||
/** | |||
* Set the value of resolver. | |||
* | |||
* @param v Value to assign to resolver. | |||
*/ | |||
public void setResolver( final String resolver ) | |||
{ | |||
m_resolver = resolver; | |||
} | |||
/** | |||
* Set the value of subSystem. | |||
* | |||
* @param v Value to assign to subSystem. | |||
*/ | |||
public void setSubSystem( final String subSystem ) | |||
{ | |||
m_subSystem = subSystem; | |||
} | |||
/** | |||
* Set the value of task. | |||
* | |||
* @param v Value to assign to task. | |||
*/ | |||
public void setTask( final String task ) | |||
{ | |||
m_task = task; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute ccm and then calls Exec's run method to | |||
* execute the command line. </p> | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
final Commandline commandLine = determineTask(); | |||
if( null == m_task ) | |||
{ | |||
final String message = "Error determining task"; | |||
throw new TaskException( message ); | |||
} | |||
//create task ok, set this task as the default one | |||
final Commandline cmd = new Commandline(); | |||
cmd.setExecutable( getCcmCommand() ); | |||
cmd.addArgument( COMMAND_DEFAULT_TASK ); | |||
cmd.addArgument( m_task ); | |||
getContext().debug( commandLine.toString() ); | |||
final int result2 = run( cmd, null ); | |||
if( result2 != 0 ) | |||
{ | |||
final String message = "Failed executing: " + cmd.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
private Commandline determineTask() | |||
throws TaskException | |||
{ | |||
final Commandline commandLine = new Commandline(); | |||
// build the command line from what we got the format | |||
// as specified in the CCM.EXE help | |||
commandLine.setExecutable( getCcmCommand() ); | |||
commandLine.addArgument( getCcmAction() ); | |||
checkOptions( commandLine ); | |||
final int result = run( commandLine, this ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + commandLine.toString(); | |||
throw new TaskException( message ); | |||
} | |||
return commandLine; | |||
} | |||
/** | |||
* Check the command line options. | |||
*/ | |||
private void checkOptions( final Commandline cmd ) | |||
{ | |||
if( m_comment != null ) | |||
{ | |||
cmd.addArgument( FLAG_COMMENT ); | |||
cmd.addArgument( "\"" + m_comment + "\"" ); | |||
} | |||
if( m_platform != null ) | |||
{ | |||
cmd.addArgument( FLAG_PLATFORM ); | |||
cmd.addArgument( m_platform ); | |||
} | |||
if( m_resolver != null ) | |||
{ | |||
cmd.addArgument( FLAG_RESOLVER ); | |||
cmd.addArgument( m_resolver ); | |||
} | |||
if( m_subSystem != null ) | |||
{ | |||
cmd.addArgument( FLAG_SUBSYSTEM ); | |||
cmd.addArgument( "\"" + m_subSystem + "\"" ); | |||
} | |||
if( m_release != null ) | |||
{ | |||
cmd.addArgument( FLAG_RELEASE ); | |||
cmd.addArgument( m_release ); | |||
} | |||
} | |||
/** | |||
* Receive notification about the process writing | |||
* to standard output. | |||
*/ | |||
public void stdout( final String line ) | |||
{ | |||
getContext().debug( "buffer:" + line ); | |||
final String task = getTask( line ); | |||
setTask( task ); | |||
getContext().debug( "task is " + m_task ); | |||
} | |||
private String getTask( final String line ) | |||
{ | |||
try | |||
{ | |||
final String task = line.substring( line.indexOf( ' ' ) ).trim(); | |||
return task.substring( 0, task.lastIndexOf( ' ' ) ).trim(); | |||
} | |||
catch( final Exception e ) | |||
{ | |||
final String message = "error procession stream " + e.getMessage(); | |||
getContext().error( message, e ); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Receive notification about the process writing | |||
* to standard error. | |||
*/ | |||
public void stderr( final String line ) | |||
{ | |||
getContext().debug( "err " + line ); | |||
} | |||
} | |||
@@ -1,118 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Task allows to reconfigure a project, recurcively or not | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public class CCMReconfigure | |||
extends Continuus | |||
{ | |||
/** | |||
* /recurse -- | |||
*/ | |||
public final static String FLAG_RECURSE = "/recurse"; | |||
/** | |||
* /recurse -- | |||
*/ | |||
public final static String FLAG_VERBOSE = "/verbose"; | |||
/** | |||
* /project flag -- target project | |||
*/ | |||
public final static String FLAG_PROJECT = "/project"; | |||
private String m_ccmProject; | |||
private boolean m_recurse; | |||
private boolean m_verbose; | |||
public CCMReconfigure() | |||
{ | |||
super(); | |||
setCcmAction( COMMAND_RECONFIGURE ); | |||
} | |||
/** | |||
* Set the value of project. | |||
*/ | |||
public void setCcmProject( final String ccmProject ) | |||
{ | |||
m_ccmProject = ccmProject; | |||
} | |||
/** | |||
* Set the value of recurse. | |||
*/ | |||
public void setRecurse( final boolean recurse ) | |||
{ | |||
m_recurse = recurse; | |||
} | |||
/** | |||
* Set the value of verbose. | |||
*/ | |||
public void setVerbose( final boolean verbose ) | |||
{ | |||
m_verbose = verbose; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute ccm and then calls Exec's run method to | |||
* execute the command line. </p> | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
final Commandline cmd = new Commandline(); | |||
// build the command line from what we got the format | |||
// as specified in the CCM.EXE help | |||
cmd.setExecutable( getCcmCommand() ); | |||
cmd.addArgument( getCcmAction() ); | |||
checkOptions( cmd ); | |||
final int result = run( cmd, null ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + cmd.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/** | |||
* Build the command line options. | |||
*/ | |||
private void checkOptions( final Commandline cmd ) | |||
{ | |||
if( m_recurse == true ) | |||
{ | |||
cmd.addArgument( FLAG_RECURSE ); | |||
} | |||
if( m_verbose == true ) | |||
{ | |||
cmd.addArgument( FLAG_VERBOSE ); | |||
} | |||
if( m_ccmProject != null ) | |||
{ | |||
cmd.addArgument( FLAG_PROJECT ); | |||
cmd.addArgument( m_ccmProject ); | |||
} | |||
} | |||
} | |||
@@ -1,122 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.ccm; | |||
import java.io.File; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.aut.nativelib.ExecOutputHandler; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* A base class for creating tasks for executing commands on Continuus 5.1 <p> | |||
* | |||
* The class extends the task as it operates by executing the ccm.exe program | |||
* supplied with Continuus/Synergy. By default the task expects the ccm | |||
* executable to be in the path, you can override this be specifying the ccmdir | |||
* attribute. </p> | |||
* | |||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||
*/ | |||
public abstract class Continuus | |||
extends AbstractTask | |||
{ | |||
/** | |||
* Constant for the thing to execute | |||
*/ | |||
private final static String CCM_EXE = "ccm"; | |||
/** | |||
* The 'CreateTask' command | |||
*/ | |||
public final static String COMMAND_CREATE_TASK = "create_task"; | |||
/** | |||
* The 'Checkout' command | |||
*/ | |||
public final static String COMMAND_CHECKOUT = "co"; | |||
/** | |||
* The 'Checkin' command | |||
*/ | |||
public final static String COMMAND_CHECKIN = "ci"; | |||
/** | |||
* The 'Reconfigure' command | |||
*/ | |||
public final static String COMMAND_RECONFIGURE = "reconfigure"; | |||
/** | |||
* The 'Reconfigure' command | |||
*/ | |||
public final static String COMMAND_DEFAULT_TASK = "default_task"; | |||
private String m_ccmDir = ""; | |||
private String m_ccmAction = ""; | |||
/** | |||
* Set the directory where the ccm executable is located | |||
* | |||
* @param dir the directory containing the ccm executable | |||
*/ | |||
public final void setCcmDir( final File dir ) | |||
{ | |||
m_ccmDir = dir.toString(); | |||
} | |||
/** | |||
* Set the value of ccmAction. | |||
* | |||
* @param ccmAction Value to assign to ccmAction. | |||
*/ | |||
public void setCcmAction( final String ccmAction ) | |||
{ | |||
m_ccmAction = ccmAction; | |||
} | |||
/** | |||
* Get the value of ccmAction. | |||
* | |||
* @return value of ccmAction. | |||
*/ | |||
public String getCcmAction() | |||
{ | |||
return m_ccmAction; | |||
} | |||
/** | |||
* Builds and returns the command string to execute ccm | |||
* | |||
* @return String containing path to the executable | |||
*/ | |||
protected final String getCcmCommand() | |||
{ | |||
String toReturn = m_ccmDir; | |||
if( !toReturn.equals( "" ) && !toReturn.endsWith( "/" ) ) | |||
{ | |||
toReturn += "/"; | |||
} | |||
toReturn += CCM_EXE; | |||
return toReturn; | |||
} | |||
protected int run( final Commandline cmd, final ExecOutputHandler handler ) | |||
throws TaskException | |||
{ | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
if( null != handler ) | |||
{ | |||
exe.setExecOutputHandler( handler ); | |||
} | |||
exe.setWorkingDirectory( getBaseDirectory() ); | |||
exe.setCommandline( cmd ); | |||
return exe.execute(); | |||
} | |||
} |
@@ -1,444 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.clearcase; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Task to perform Checkin command to ClearCase. <p> | |||
* | |||
* The following attributes are interpreted: | |||
* <tableborder="1"> | |||
* | |||
* <tr> | |||
* | |||
* <th> | |||
* Attribute | |||
* </th> | |||
* | |||
* <th> | |||
* Values | |||
* </th> | |||
* | |||
* <th> | |||
* Required | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* viewpath | |||
* </td> | |||
* | |||
* <td> | |||
* Path to the ClearCase view file or directory that the command will | |||
* operate on | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* comment | |||
* </td> | |||
* | |||
* <td> | |||
* Specify a comment. Only one of comment or cfile may be used. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* commentfile | |||
* </td> | |||
* | |||
* <td> | |||
* Specify a file containing a comment. Only one of comment or | |||
* cfile may be used. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* nowarn | |||
* </td> | |||
* | |||
* <td> | |||
* Suppress warning messages | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* preservetime | |||
* </td> | |||
* | |||
* <td> | |||
* Preserve the modification time | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* keepcopy | |||
* </td> | |||
* | |||
* <td> | |||
* Keeps a copy of the file with a .keep extension | |||
* | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* identical | |||
* </td> | |||
* | |||
* <td> | |||
* Allows the file to be checked in even if it is | |||
* identical to the original | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* </table> | |||
* | |||
* | |||
* @author Curtis White | |||
*/ | |||
public class CCCheckin extends ClearCase | |||
{ | |||
/** | |||
* -c flag -- comment to attach to the file | |||
*/ | |||
public final static String FLAG_COMMENT = "-c"; | |||
/** | |||
* -cfile flag -- file containing a comment to attach to the file | |||
*/ | |||
public final static String FLAG_COMMENTFILE = "-cfile"; | |||
/** | |||
* -nc flag -- no comment is specified | |||
*/ | |||
public final static String FLAG_NOCOMMENT = "-nc"; | |||
/** | |||
* -nwarn flag -- suppresses warning messages | |||
*/ | |||
public final static String FLAG_NOWARN = "-nwarn"; | |||
/** | |||
* -ptime flag -- preserves the modification time | |||
*/ | |||
public final static String FLAG_PRESERVETIME = "-ptime"; | |||
/** | |||
* -keep flag -- keeps a copy of the file with a .keep extension | |||
*/ | |||
public final static String FLAG_KEEPCOPY = "-keep"; | |||
/** | |||
* -identical flag -- allows the file to be checked in even if it is | |||
* identical to the original | |||
*/ | |||
public final static String FLAG_IDENTICAL = "-identical"; | |||
private String m_Comment = null; | |||
private String m_Cfile = null; | |||
private boolean m_Nwarn = false; | |||
private boolean m_Ptime = false; | |||
private boolean m_Keep = false; | |||
private boolean m_Identical = true; | |||
/** | |||
* Set comment string | |||
* | |||
* @param comment the comment string | |||
*/ | |||
public void setComment( String comment ) | |||
{ | |||
m_Comment = comment; | |||
} | |||
/** | |||
* Set comment file | |||
* | |||
* @param cfile the path to the comment file | |||
*/ | |||
public void setCommentFile( String cfile ) | |||
{ | |||
m_Cfile = cfile; | |||
} | |||
/** | |||
* Set the identical flag | |||
* | |||
* @param identical the status to set the flag to | |||
*/ | |||
public void setIdentical( boolean identical ) | |||
{ | |||
m_Identical = identical; | |||
} | |||
/** | |||
* Set the keepcopy flag | |||
* | |||
* @param keep the status to set the flag to | |||
*/ | |||
public void setKeepCopy( boolean keep ) | |||
{ | |||
m_Keep = keep; | |||
} | |||
/** | |||
* Set the nowarn flag | |||
* | |||
* @param nwarn the status to set the flag to | |||
*/ | |||
public void setNoWarn( boolean nwarn ) | |||
{ | |||
m_Nwarn = nwarn; | |||
} | |||
/** | |||
* Set preservetime flag | |||
* | |||
* @param ptime the status to set the flag to | |||
*/ | |||
public void setPreserveTime( boolean ptime ) | |||
{ | |||
m_Ptime = ptime; | |||
} | |||
/** | |||
* Get comment string | |||
* | |||
* @return String containing the comment | |||
*/ | |||
public String getComment() | |||
{ | |||
return m_Comment; | |||
} | |||
/** | |||
* Get comment file | |||
* | |||
* @return String containing the path to the comment file | |||
*/ | |||
public String getCommentFile() | |||
{ | |||
return m_Cfile; | |||
} | |||
/** | |||
* Get identical flag status | |||
* | |||
* @return boolean containing status of identical flag | |||
*/ | |||
public boolean getIdentical() | |||
{ | |||
return m_Identical; | |||
} | |||
/** | |||
* Get keepcopy flag status | |||
* | |||
* @return boolean containing status of keepcopy flag | |||
*/ | |||
public boolean getKeepCopy() | |||
{ | |||
return m_Keep; | |||
} | |||
/** | |||
* Get nowarn flag status | |||
* | |||
* @return boolean containing status of nwarn flag | |||
*/ | |||
public boolean getNoWarn() | |||
{ | |||
return m_Nwarn; | |||
} | |||
/** | |||
* Get preservetime flag status | |||
* | |||
* @return boolean containing status of preservetime flag | |||
*/ | |||
public boolean getPreserveTime() | |||
{ | |||
return m_Ptime; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute cleartool and then calls Exec's run | |||
* method to execute the command line. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
Commandline commandLine = new Commandline(); | |||
// Default the viewpath to basedir if it is not specified | |||
if( getViewPath() == null ) | |||
{ | |||
setViewPath( getBaseDirectory().getPath() ); | |||
} | |||
// build the command line from what we got. the format is | |||
// cleartool checkin [options...] [viewpath ...] | |||
// as specified in the CLEARTOOL.EXE help | |||
commandLine.setExecutable( getClearToolCommand() ); | |||
commandLine.addArgument( COMMAND_CHECKIN ); | |||
checkOptions( commandLine ); | |||
final int result = run( commandLine ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + commandLine.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/** | |||
* Get the 'comment' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getCommentCommand( Commandline cmd ) | |||
{ | |||
if( getComment() != null ) | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_COMMENT ); | |||
cmd.addArgument( getComment() ); | |||
} | |||
} | |||
/** | |||
* Get the 'commentfile' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getCommentFileCommand( Commandline cmd ) | |||
{ | |||
if( getCommentFile() != null ) | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_COMMENTFILE ); | |||
cmd.addArgument( getCommentFile() ); | |||
} | |||
} | |||
/** | |||
* Check the command line options. | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void checkOptions( Commandline cmd ) | |||
{ | |||
if( getComment() != null ) | |||
{ | |||
// -c | |||
getCommentCommand( cmd ); | |||
} | |||
else | |||
{ | |||
if( getCommentFile() != null ) | |||
{ | |||
// -cfile | |||
getCommentFileCommand( cmd ); | |||
} | |||
else | |||
{ | |||
cmd.addArgument( FLAG_NOCOMMENT ); | |||
} | |||
} | |||
if( getNoWarn() ) | |||
{ | |||
// -nwarn | |||
cmd.addArgument( FLAG_NOWARN ); | |||
} | |||
if( getPreserveTime() ) | |||
{ | |||
// -ptime | |||
cmd.addArgument( FLAG_PRESERVETIME ); | |||
} | |||
if( getKeepCopy() ) | |||
{ | |||
// -keep | |||
cmd.addArgument( FLAG_KEEPCOPY ); | |||
} | |||
if( getIdentical() ) | |||
{ | |||
// -identical | |||
cmd.addArgument( FLAG_IDENTICAL ); | |||
} | |||
// viewpath | |||
cmd.addArgument( getViewPath() ); | |||
} | |||
} | |||
@@ -1,596 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.clearcase; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Task to perform Checkout command to ClearCase. <p> | |||
* | |||
* The following attributes are interpretted: | |||
* <tableborder="1"> | |||
* | |||
* <tr> | |||
* | |||
* <th> | |||
* Attribute | |||
* </th> | |||
* | |||
* <th> | |||
* Values | |||
* </th> | |||
* | |||
* <th> | |||
* Required | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* viewpath | |||
* </td> | |||
* | |||
* <td> | |||
* Path to the ClearCase view file or directory that the command will | |||
* operate on | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* reserved | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies whether to check out the file as reserved or not | |||
* </td> | |||
* | |||
* <td> | |||
* Yes | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* out | |||
* </td> | |||
* | |||
* <td> | |||
* Creates a writable file under a different filename | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* nodata | |||
* </td> | |||
* | |||
* <td> | |||
* Checks out the file but does not create an editable file | |||
* containing its data | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* branch | |||
* </td> | |||
* | |||
* <td> | |||
* Specify a branch to check out the file to | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* version | |||
* </td> | |||
* | |||
* <td> | |||
* Allows checkout of a version other than main latest | |||
* | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* nowarn | |||
* </td> | |||
* | |||
* <td> | |||
* Suppress warning messages | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* comment | |||
* </td> | |||
* | |||
* <td> | |||
* Specify a comment. Only one of comment or | |||
* cfile may be used. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* commentfile | |||
* </td> | |||
* | |||
* <td> | |||
* Specify a file containing a comment. | |||
* Only one of comment or cfile may be | |||
* used. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* </table> | |||
* | |||
* | |||
* @author Curtis White | |||
*/ | |||
public class CCCheckout extends ClearCase | |||
{ | |||
/** | |||
* -reserved flag -- check out the file as reserved | |||
*/ | |||
public final static String FLAG_RESERVED = "-reserved"; | |||
/** | |||
* -reserved flag -- check out the file as unreserved | |||
*/ | |||
public final static String FLAG_UNRESERVED = "-unreserved"; | |||
/** | |||
* -out flag -- create a writable file under a different filename | |||
*/ | |||
public final static String FLAG_OUT = "-out"; | |||
/** | |||
* -ndata flag -- checks out the file but does not create an editable file | |||
* containing its data | |||
*/ | |||
public final static String FLAG_NODATA = "-ndata"; | |||
/** | |||
* -branch flag -- checks out the file on a specified branch | |||
*/ | |||
public final static String FLAG_BRANCH = "-branch"; | |||
/** | |||
* -version flag -- allows checkout of a version that is not main latest | |||
*/ | |||
public final static String FLAG_VERSION = "-version"; | |||
/** | |||
* -nwarn flag -- suppresses warning messages | |||
*/ | |||
public final static String FLAG_NOWARN = "-nwarn"; | |||
/** | |||
* -c flag -- comment to attach to the file | |||
*/ | |||
public final static String FLAG_COMMENT = "-c"; | |||
/** | |||
* -cfile flag -- file containing a comment to attach to the file | |||
*/ | |||
public final static String FLAG_COMMENTFILE = "-cfile"; | |||
/** | |||
* -nc flag -- no comment is specified | |||
*/ | |||
public final static String FLAG_NOCOMMENT = "-nc"; | |||
private boolean m_Reserved = true; | |||
private String m_Out = null; | |||
private boolean m_Ndata = false; | |||
private String m_Branch = null; | |||
private boolean m_Version = false; | |||
private boolean m_Nwarn = false; | |||
private String m_Comment = null; | |||
private String m_Cfile = null; | |||
/** | |||
* Set branch name | |||
* | |||
* @param branch the name of the branch | |||
*/ | |||
public void setBranch( String branch ) | |||
{ | |||
m_Branch = branch; | |||
} | |||
/** | |||
* Set comment string | |||
* | |||
* @param comment the comment string | |||
*/ | |||
public void setComment( String comment ) | |||
{ | |||
m_Comment = comment; | |||
} | |||
/** | |||
* Set comment file | |||
* | |||
* @param cfile the path to the comment file | |||
*/ | |||
public void setCommentFile( String cfile ) | |||
{ | |||
m_Cfile = cfile; | |||
} | |||
/** | |||
* Set the nodata flag | |||
* | |||
* @param ndata the status to set the flag to | |||
*/ | |||
public void setNoData( boolean ndata ) | |||
{ | |||
m_Ndata = ndata; | |||
} | |||
/** | |||
* Set the nowarn flag | |||
* | |||
* @param nwarn the status to set the flag to | |||
*/ | |||
public void setNoWarn( boolean nwarn ) | |||
{ | |||
m_Nwarn = nwarn; | |||
} | |||
/** | |||
* Set out file | |||
* | |||
* @param outf the path to the out file | |||
*/ | |||
public void setOut( String outf ) | |||
{ | |||
m_Out = outf; | |||
} | |||
/** | |||
* Set reserved flag status | |||
* | |||
* @param reserved the status to set the flag to | |||
*/ | |||
public void setReserved( boolean reserved ) | |||
{ | |||
m_Reserved = reserved; | |||
} | |||
/** | |||
* Set the version flag | |||
* | |||
* @param version the status to set the flag to | |||
*/ | |||
public void setVersion( boolean version ) | |||
{ | |||
m_Version = version; | |||
} | |||
/** | |||
* Get branch name | |||
* | |||
* @return String containing the name of the branch | |||
*/ | |||
public String getBranch() | |||
{ | |||
return m_Branch; | |||
} | |||
/** | |||
* Get comment string | |||
* | |||
* @return String containing the comment | |||
*/ | |||
public String getComment() | |||
{ | |||
return m_Comment; | |||
} | |||
/** | |||
* Get comment file | |||
* | |||
* @return String containing the path to the comment file | |||
*/ | |||
public String getCommentFile() | |||
{ | |||
return m_Cfile; | |||
} | |||
/** | |||
* Get nodata flag status | |||
* | |||
* @return boolean containing status of ndata flag | |||
*/ | |||
public boolean getNoData() | |||
{ | |||
return m_Ndata; | |||
} | |||
/** | |||
* Get nowarn flag status | |||
* | |||
* @return boolean containing status of nwarn flag | |||
*/ | |||
public boolean getNoWarn() | |||
{ | |||
return m_Nwarn; | |||
} | |||
/** | |||
* Get out file | |||
* | |||
* @return String containing the path to the out file | |||
*/ | |||
public String getOut() | |||
{ | |||
return m_Out; | |||
} | |||
/** | |||
* Get reserved flag status | |||
* | |||
* @return boolean containing status of reserved flag | |||
*/ | |||
public boolean getReserved() | |||
{ | |||
return m_Reserved; | |||
} | |||
/** | |||
* Get version flag status | |||
* | |||
* @return boolean containing status of version flag | |||
*/ | |||
public boolean getVersion() | |||
{ | |||
return m_Version; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute cleartool and then calls Exec's run | |||
* method to execute the command line. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
Commandline commandLine = new Commandline(); | |||
// Default the viewpath to basedir if it is not specified | |||
if( getViewPath() == null ) | |||
{ | |||
setViewPath( getBaseDirectory().getPath() ); | |||
} | |||
// build the command line from what we got the format is | |||
// cleartool checkout [options...] [viewpath ...] | |||
// as specified in the CLEARTOOL.EXE help | |||
commandLine.setExecutable( getClearToolCommand() ); | |||
commandLine.addArgument( COMMAND_CHECKOUT ); | |||
checkOptions( commandLine ); | |||
final int result = run( commandLine ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + commandLine.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/** | |||
* Get the 'branch' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getBranchCommand( Commandline cmd ) | |||
{ | |||
if( getBranch() != null ) | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_BRANCH ); | |||
cmd.addArgument( getBranch() ); | |||
} | |||
} | |||
/** | |||
* Get the 'comment' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getCommentCommand( Commandline cmd ) | |||
{ | |||
if( getComment() != null ) | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_COMMENT ); | |||
cmd.addArgument( getComment() ); | |||
} | |||
} | |||
/** | |||
* Get the 'cfile' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getCommentFileCommand( Commandline cmd ) | |||
{ | |||
if( getCommentFile() != null ) | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_COMMENTFILE ); | |||
cmd.addArgument( getCommentFile() ); | |||
} | |||
} | |||
/** | |||
* Get the 'out' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getOutCommand( Commandline cmd ) | |||
{ | |||
if( getOut() != null ) | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_OUT ); | |||
cmd.addArgument( getOut() ); | |||
} | |||
} | |||
/** | |||
* Check the command line options. | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void checkOptions( Commandline cmd ) | |||
{ | |||
// ClearCase items | |||
if( getReserved() ) | |||
{ | |||
// -reserved | |||
cmd.addArgument( FLAG_RESERVED ); | |||
} | |||
else | |||
{ | |||
// -unreserved | |||
cmd.addArgument( FLAG_UNRESERVED ); | |||
} | |||
if( getOut() != null ) | |||
{ | |||
// -out | |||
getOutCommand( cmd ); | |||
} | |||
else | |||
{ | |||
if( getNoData() ) | |||
{ | |||
// -ndata | |||
cmd.addArgument( FLAG_NODATA ); | |||
} | |||
} | |||
if( getBranch() != null ) | |||
{ | |||
// -branch | |||
getBranchCommand( cmd ); | |||
} | |||
else | |||
{ | |||
if( getVersion() ) | |||
{ | |||
// -version | |||
cmd.addArgument( FLAG_VERSION ); | |||
} | |||
} | |||
if( getNoWarn() ) | |||
{ | |||
// -nwarn | |||
cmd.addArgument( FLAG_NOWARN ); | |||
} | |||
if( getComment() != null ) | |||
{ | |||
// -c | |||
getCommentCommand( cmd ); | |||
} | |||
else | |||
{ | |||
if( getCommentFile() != null ) | |||
{ | |||
// -cfile | |||
getCommentFileCommand( cmd ); | |||
} | |||
else | |||
{ | |||
cmd.addArgument( FLAG_NOCOMMENT ); | |||
} | |||
} | |||
// viewpath | |||
cmd.addArgument( getViewPath() ); | |||
} | |||
} | |||
@@ -1,166 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.clearcase; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Task to perform UnCheckout command to ClearCase. <p> | |||
* | |||
* The following attributes are interpretted: | |||
* <tableborder="1"> | |||
* | |||
* <tr> | |||
* | |||
* <th> | |||
* Attribute | |||
* </th> | |||
* | |||
* <th> | |||
* Values | |||
* </th> | |||
* | |||
* <th> | |||
* Required | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* viewpath | |||
* </td> | |||
* | |||
* <td> | |||
* Path to the ClearCase view file or directory that the command will | |||
* operate on | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* keepcopy | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies whether to keep a copy of the file with a .keep extension | |||
* or not | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* </table> | |||
* | |||
* | |||
* @author Curtis White | |||
*/ | |||
public class CCUnCheckout extends ClearCase | |||
{ | |||
/** | |||
* -keep flag -- keep a copy of the file with .keep extension | |||
*/ | |||
public final static String FLAG_KEEPCOPY = "-keep"; | |||
/** | |||
* -rm flag -- remove the copy of the file | |||
*/ | |||
public final static String FLAG_RM = "-rm"; | |||
private boolean m_Keep = false; | |||
/** | |||
* Set keepcopy flag status | |||
* | |||
* @param keep the status to set the flag to | |||
*/ | |||
public void setKeepCopy( boolean keep ) | |||
{ | |||
m_Keep = keep; | |||
} | |||
/** | |||
* Get keepcopy flag status | |||
* | |||
* @return boolean containing status of keep flag | |||
*/ | |||
public boolean getKeepCopy() | |||
{ | |||
return m_Keep; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute cleartool and then calls Exec's run | |||
* method to execute the command line. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
Commandline commandLine = new Commandline(); | |||
// Default the viewpath to basedir if it is not specified | |||
if( getViewPath() == null ) | |||
{ | |||
setViewPath( getBaseDirectory().getPath() ); | |||
} | |||
// build the command line from what we got the format is | |||
// cleartool uncheckout [options...] [viewpath ...] | |||
// as specified in the CLEARTOOL.EXE help | |||
commandLine.setExecutable( getClearToolCommand() ); | |||
commandLine.addArgument( COMMAND_UNCHECKOUT ); | |||
checkOptions( commandLine ); | |||
final int result = run( commandLine ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + commandLine.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/** | |||
* Check the command line options. | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void checkOptions( Commandline cmd ) | |||
{ | |||
// ClearCase items | |||
if( getKeepCopy() ) | |||
{ | |||
// -keep | |||
cmd.addArgument( FLAG_KEEPCOPY ); | |||
} | |||
else | |||
{ | |||
// -rm | |||
cmd.addArgument( FLAG_RM ); | |||
} | |||
// viewpath | |||
cmd.addArgument( getViewPath() ); | |||
} | |||
} | |||
@@ -1,436 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.clearcase; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* Task to perform an Update command to ClearCase. <p> | |||
* | |||
* The following attributes are interpretted: | |||
* <tableborder="1"> | |||
* | |||
* <tr> | |||
* | |||
* <th> | |||
* Attribute | |||
* </th> | |||
* | |||
* <th> | |||
* Values | |||
* </th> | |||
* | |||
* <th> | |||
* Required | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* viewpath | |||
* </td> | |||
* | |||
* <td> | |||
* Path to the ClearCase view file or directory that the command will | |||
* operate on | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* graphical | |||
* </td> | |||
* | |||
* <td> | |||
* Displays a graphical dialog during the update | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* log | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies a log file for ClearCase to write to | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* overwrite | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies whether to overwrite hijacked files or not | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* rename | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies that hijacked files should be renamed with a | |||
* .keep extension | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* currenttime | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies that modification time should be written | |||
* as the current time. Either currenttime or | |||
* preservetime can be specified. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* preservetime | |||
* </td> | |||
* | |||
* <td> | |||
* Specifies that modification time should | |||
* preserved from the VOB time. Either currenttime | |||
* or preservetime can be specified. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* <tr> | |||
* | |||
* </table> | |||
* | |||
* | |||
* @author Curtis White | |||
*/ | |||
public class CCUpdate extends ClearCase | |||
{ | |||
/** | |||
* -graphical flag -- display graphical dialog during update operation | |||
*/ | |||
public final static String FLAG_GRAPHICAL = "-graphical"; | |||
/** | |||
* -log flag -- file to log status to | |||
*/ | |||
public final static String FLAG_LOG = "-log"; | |||
/** | |||
* -overwrite flag -- overwrite hijacked files | |||
*/ | |||
public final static String FLAG_OVERWRITE = "-overwrite"; | |||
/** | |||
* -noverwrite flag -- do not overwrite hijacked files | |||
*/ | |||
public final static String FLAG_NOVERWRITE = "-noverwrite"; | |||
/** | |||
* -rename flag -- rename hijacked files with .keep extension | |||
*/ | |||
public final static String FLAG_RENAME = "-rename"; | |||
/** | |||
* -ctime flag -- modified time is written as the current time | |||
*/ | |||
public final static String FLAG_CURRENTTIME = "-ctime"; | |||
/** | |||
* -ptime flag -- modified time is written as the VOB time | |||
*/ | |||
public final static String FLAG_PRESERVETIME = "-ptime"; | |||
private boolean m_Graphical = false; | |||
private boolean m_Overwrite = false; | |||
private boolean m_Rename = false; | |||
private boolean m_Ctime = false; | |||
private boolean m_Ptime = false; | |||
private String m_Log = null; | |||
/** | |||
* Set modified time based on current time | |||
* | |||
* @param ct the status to set the flag to | |||
*/ | |||
public void setCurrentTime( boolean ct ) | |||
{ | |||
m_Ctime = ct; | |||
} | |||
/** | |||
* Set graphical flag status | |||
* | |||
* @param graphical the status to set the flag to | |||
*/ | |||
public void setGraphical( boolean graphical ) | |||
{ | |||
m_Graphical = graphical; | |||
} | |||
/** | |||
* Set log file where cleartool can record the status of the command | |||
* | |||
* @param log the path to the log file | |||
*/ | |||
public void setLog( String log ) | |||
{ | |||
m_Log = log; | |||
} | |||
/** | |||
* Set overwrite hijacked files status | |||
* | |||
* @param ow the status to set the flag to | |||
*/ | |||
public void setOverwrite( boolean ow ) | |||
{ | |||
m_Overwrite = ow; | |||
} | |||
/** | |||
* Preserve modified time from the VOB time | |||
* | |||
* @param pt the status to set the flag to | |||
*/ | |||
public void setPreserveTime( boolean pt ) | |||
{ | |||
m_Ptime = pt; | |||
} | |||
/** | |||
* Set rename hijacked files status | |||
* | |||
* @param ren the status to set the flag to | |||
*/ | |||
public void setRename( boolean ren ) | |||
{ | |||
m_Rename = ren; | |||
} | |||
/** | |||
* Get current time status | |||
* | |||
* @return boolean containing status of current time flag | |||
*/ | |||
public boolean getCurrentTime() | |||
{ | |||
return m_Ctime; | |||
} | |||
/** | |||
* Get graphical flag status | |||
* | |||
* @return boolean containing status of graphical flag | |||
*/ | |||
public boolean getGraphical() | |||
{ | |||
return m_Graphical; | |||
} | |||
/** | |||
* Get log file | |||
* | |||
* @return String containing the path to the log file | |||
*/ | |||
public String getLog() | |||
{ | |||
return m_Log; | |||
} | |||
/** | |||
* Get overwrite hijacked files status | |||
* | |||
* @return boolean containing status of overwrite flag | |||
*/ | |||
public boolean getOverwrite() | |||
{ | |||
return m_Overwrite; | |||
} | |||
/** | |||
* Get preserve time status | |||
* | |||
* @return boolean containing status of preserve time flag | |||
*/ | |||
public boolean getPreserveTime() | |||
{ | |||
return m_Ptime; | |||
} | |||
/** | |||
* Get rename hijacked files status | |||
* | |||
* @return boolean containing status of rename flag | |||
*/ | |||
public boolean getRename() | |||
{ | |||
return m_Rename; | |||
} | |||
/** | |||
* Executes the task. <p> | |||
* | |||
* Builds a command line to execute cleartool and then calls Exec's run | |||
* method to execute the command line. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
Commandline commandLine = new Commandline(); | |||
// Default the viewpath to basedir if it is not specified | |||
if( getViewPath() == null ) | |||
{ | |||
setViewPath( getBaseDirectory().getPath() ); | |||
} | |||
// build the command line from what we got the format is | |||
// cleartool update [options...] [viewpath ...] | |||
// as specified in the CLEARTOOL.EXE help | |||
commandLine.setExecutable( getClearToolCommand() ); | |||
commandLine.addArgument( COMMAND_UPDATE ); | |||
// Check the command line options | |||
checkOptions( commandLine ); | |||
// For debugging | |||
System.out.println( commandLine.toString() ); | |||
final int result = run( commandLine ); | |||
if( result != 0 ) | |||
{ | |||
final String message = "Failed executing: " + commandLine.toString(); | |||
throw new TaskException( message ); | |||
} | |||
} | |||
/** | |||
* Get the 'log' command | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void getLogCommand( Commandline cmd ) | |||
{ | |||
if( getLog() == null ) | |||
{ | |||
return; | |||
} | |||
else | |||
{ | |||
/* | |||
* Had to make two separate commands here because if a space is | |||
* inserted between the flag and the value, it is treated as a | |||
* Windows filename with a space and it is enclosed in double | |||
* quotes ("). This breaks clearcase. | |||
*/ | |||
cmd.addArgument( FLAG_LOG ); | |||
cmd.addArgument( getLog() ); | |||
} | |||
} | |||
/** | |||
* Check the command line options. | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
private void checkOptions( Commandline cmd ) | |||
{ | |||
// ClearCase items | |||
if( getGraphical() ) | |||
{ | |||
// -graphical | |||
cmd.addArgument( FLAG_GRAPHICAL ); | |||
} | |||
else | |||
{ | |||
if( getOverwrite() ) | |||
{ | |||
// -overwrite | |||
cmd.addArgument( FLAG_OVERWRITE ); | |||
} | |||
else | |||
{ | |||
if( getRename() ) | |||
{ | |||
// -rename | |||
cmd.addArgument( FLAG_RENAME ); | |||
} | |||
else | |||
{ | |||
// -noverwrite | |||
cmd.addArgument( FLAG_NOVERWRITE ); | |||
} | |||
} | |||
if( getCurrentTime() ) | |||
{ | |||
// -ctime | |||
cmd.addArgument( FLAG_CURRENTTIME ); | |||
} | |||
else | |||
{ | |||
if( getPreserveTime() ) | |||
{ | |||
// -ptime | |||
cmd.addArgument( FLAG_PRESERVETIME ); | |||
} | |||
} | |||
// -log logname | |||
getLogCommand( cmd ); | |||
} | |||
// viewpath | |||
cmd.addArgument( getViewPath() ); | |||
} | |||
} | |||
@@ -1,116 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.clearcase; | |||
import java.io.File; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* A base class for creating tasks for executing commands on ClearCase. <p> | |||
* | |||
* The class extends the 'exec' task as it operates by executing the cleartool | |||
* program supplied with ClearCase. By default the task expects the cleartool | |||
* executable to be in the path, * you can override this be specifying the | |||
* cleartooldir attribute. </p> <p> | |||
* | |||
* This class provides set and get methods for the 'viewpath' attribute. It also | |||
* contains constants for the flags that can be passed to cleartool. </p> | |||
* | |||
* @author Curtis White | |||
*/ | |||
public abstract class ClearCase extends AbstractTask | |||
{ | |||
/** | |||
* Constant for the thing to execute | |||
*/ | |||
private final static String CLEARTOOL_EXE = "cleartool"; | |||
/** | |||
* The 'Update' command | |||
*/ | |||
public final static String COMMAND_UPDATE = "update"; | |||
/** | |||
* The 'Checkout' command | |||
*/ | |||
public final static String COMMAND_CHECKOUT = "checkout"; | |||
/** | |||
* The 'Checkin' command | |||
*/ | |||
public final static String COMMAND_CHECKIN = "checkin"; | |||
/** | |||
* The 'UndoCheckout' command | |||
*/ | |||
public final static String COMMAND_UNCHECKOUT = "uncheckout"; | |||
private String m_ClearToolDir = ""; | |||
private String m_viewPath = null; | |||
/** | |||
* Set the directory where the cleartool executable is located | |||
* | |||
* @param dir the directory containing the cleartool executable | |||
*/ | |||
public final void setClearToolDir( final File dir ) | |||
{ | |||
m_ClearToolDir = dir.toString(); | |||
} | |||
/** | |||
* Set the path to the item in a clearcase view to operate on | |||
* | |||
* @param viewPath Path to the view directory or file | |||
*/ | |||
public final void setViewPath( String viewPath ) | |||
{ | |||
m_viewPath = viewPath; | |||
} | |||
/** | |||
* Get the path to the item in a clearcase view | |||
* | |||
* @return m_viewPath | |||
*/ | |||
public String getViewPath() | |||
{ | |||
return m_viewPath; | |||
} | |||
/** | |||
* Builds and returns the command string to execute cleartool | |||
* | |||
* @return String containing path to the executable | |||
*/ | |||
protected final String getClearToolCommand() | |||
{ | |||
String toReturn = m_ClearToolDir; | |||
if( !toReturn.equals( "" ) && !toReturn.endsWith( "/" ) ) | |||
{ | |||
toReturn += "/"; | |||
} | |||
toReturn += CLEARTOOL_EXE; | |||
return toReturn; | |||
} | |||
protected int run( Commandline cmd ) | |||
throws TaskException | |||
{ | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
exe.setWorkingDirectory( getBaseDirectory() ); | |||
exe.setCommandline( cmd ); | |||
return exe.execute(); | |||
} | |||
} | |||
@@ -1,53 +0,0 @@ | |||
package org.apache.tools.todo.taskdefs.conditions; | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.conditions.Condition; | |||
/** | |||
* Simple String comparison condition. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @version $Revision$ | |||
* | |||
* @ant:type type="condition" nam="equals" | |||
*/ | |||
public class Equals implements Condition | |||
{ | |||
private String arg1, arg2; | |||
public void setArg1( String a1 ) | |||
{ | |||
arg1 = a1; | |||
} | |||
public void setArg2( String a2 ) | |||
{ | |||
arg2 = a2; | |||
} | |||
/** | |||
* Evaluates this condition. | |||
* | |||
* @param context | |||
* The context to evaluate the condition in. | |||
*/ | |||
public boolean evaluate( final TaskContext context ) | |||
throws TaskException | |||
{ | |||
if( arg1 == null || arg2 == null ) | |||
{ | |||
throw new TaskException( "both arg1 and arg2 are required in equals" ); | |||
} | |||
return arg1.equals( arg2 ); | |||
} | |||
} |
@@ -1,79 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.conditions; | |||
import java.net.HttpURLConnection; | |||
import java.net.MalformedURLException; | |||
import java.net.URL; | |||
import java.net.URLConnection; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.conditions.Condition; | |||
/** | |||
* Condition to wait for a HTTP request to succeed. Its attribute(s) are: url - | |||
* the URL of the request. | |||
* | |||
* @author <a href="mailto:denis@network365.com">Denis Hennessy</a> | |||
* | |||
* @ant:type type="condition" name="http" | |||
*/ | |||
public class Http | |||
implements Condition | |||
{ | |||
String spec = null; | |||
public void setUrl( String url ) | |||
{ | |||
spec = url; | |||
} | |||
/** | |||
* Evaluates this condition. | |||
*/ | |||
public boolean evaluate( final TaskContext context ) | |||
throws TaskException | |||
{ | |||
if( spec == null ) | |||
{ | |||
throw new TaskException( "No url specified in HTTP task" ); | |||
} | |||
context.debug( "Checking for " + spec ); | |||
try | |||
{ | |||
URL url = new URL( spec ); | |||
try | |||
{ | |||
URLConnection conn = url.openConnection(); | |||
if( conn instanceof HttpURLConnection ) | |||
{ | |||
HttpURLConnection http = (HttpURLConnection)conn; | |||
int code = http.getResponseCode(); | |||
context.debug( "Result code for " + spec + " was " + code ); | |||
if( code > 0 && code < 500 ) | |||
{ | |||
return true; | |||
} | |||
else | |||
{ | |||
return false; | |||
} | |||
} | |||
} | |||
catch( java.io.IOException e ) | |||
{ | |||
return false; | |||
} | |||
} | |||
catch( MalformedURLException e ) | |||
{ | |||
throw new TaskException( "Badly formed URL: " + spec, e ); | |||
} | |||
return true; | |||
} | |||
} |
@@ -1,66 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.conditions; | |||
import java.io.IOException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.conditions.Condition; | |||
/** | |||
* Condition to wait for a TCP/IP socket to have a listener. Its attribute(s) | |||
* are: server - the name of the server. port - the port number of the socket. | |||
* | |||
* @author <a href="mailto:denis@network365.com">Denis Hennessy</a> | |||
* | |||
* @ant:type type="condition" name="socket" | |||
*/ | |||
public class Socket | |||
implements Condition | |||
{ | |||
String server = null; | |||
int port = 0; | |||
public void setPort( int port ) | |||
{ | |||
this.port = port; | |||
} | |||
public void setServer( String server ) | |||
{ | |||
this.server = server; | |||
} | |||
/** | |||
* Evaluates this condition. | |||
*/ | |||
public boolean evaluate( TaskContext context ) | |||
throws TaskException | |||
{ | |||
if( server == null ) | |||
{ | |||
throw new TaskException( "No server specified in Socket task" ); | |||
} | |||
if( port == 0 ) | |||
{ | |||
throw new TaskException( "No port specified in Socket task" ); | |||
} | |||
context.debug( "Checking for listener at " + server + ":" + port ); | |||
try | |||
{ | |||
java.net.Socket socket = new java.net.Socket( server, port ); | |||
socket.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@@ -1,64 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.exec; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Used by <code>Execute</code> to handle input and output stream of | |||
* subprocesses. | |||
* | |||
* @author thomas.haas@softwired-inc.com | |||
*/ | |||
public interface ExecuteStreamHandler | |||
{ | |||
/** | |||
* Install a handler for the input stream of the subprocess. | |||
* | |||
* @param os output stream to write to the standard input stream of the | |||
* subprocess | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
void setProcessInputStream( OutputStream os ) | |||
throws IOException; | |||
/** | |||
* Install a handler for the error stream of the subprocess. | |||
* | |||
* @param is input stream to read from the error stream from the subprocess | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
void setProcessErrorStream( InputStream is ) | |||
throws IOException; | |||
/** | |||
* Install a handler for the output stream of the subprocess. | |||
* | |||
* @param is input stream to read from the error stream from the subprocess | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
void setProcessOutputStream( InputStream is ) | |||
throws TaskException, IOException; | |||
/** | |||
* Start handling of the streams. | |||
* | |||
* @exception java.io.IOException Description of Exception | |||
*/ | |||
void start() | |||
throws IOException; | |||
/** | |||
* Stop handling of the streams - will not be restarted. | |||
*/ | |||
void stop() | |||
throws TaskException; | |||
} |
@@ -1,637 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.i18n; | |||
import java.io.BufferedReader; | |||
import java.io.BufferedWriter; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.io.OutputStreamWriter; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Locale; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* Translates text embedded in files using Resource Bundle files. | |||
* | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public class Translate | |||
extends MatchingTask | |||
{ | |||
/** | |||
* ArrayList to hold source file sets. | |||
*/ | |||
private ArrayList filesets = new ArrayList(); | |||
/** | |||
* Holds key value pairs loaded from resource bundle file | |||
*/ | |||
private Hashtable resourceMap = new Hashtable(); | |||
/** | |||
* Last Modified Timestamp of resource bundle file being used. | |||
*/ | |||
private long[] bundleLastModified = new long[ 7 ]; | |||
/** | |||
* Has at least one file from the bundle been loaded? | |||
*/ | |||
private boolean loaded = false; | |||
/** | |||
* Family name of resource bundle | |||
*/ | |||
private String bundle; | |||
/** | |||
* Locale specific country of the resource bundle | |||
*/ | |||
private String bundleCountry; | |||
/** | |||
* Resource Bundle file encoding scheme, defaults to srcEncoding | |||
*/ | |||
private String bundleEncoding; | |||
/** | |||
* Locale specific language of the resource bundle | |||
*/ | |||
private String bundleLanguage; | |||
/** | |||
* Locale specific variant of the resource bundle | |||
*/ | |||
private String bundleVariant; | |||
/** | |||
* Destination file encoding scheme | |||
*/ | |||
private String destEncoding; | |||
/** | |||
* Last Modified Timestamp of destination file being used. | |||
*/ | |||
private long destLastModified; | |||
/** | |||
* Ending token to identify keys | |||
*/ | |||
private String endToken; | |||
/** | |||
* Create new destination file? Defaults to false. | |||
*/ | |||
private boolean forceOverwrite; | |||
/** | |||
* Source file encoding scheme | |||
*/ | |||
private String srcEncoding; | |||
/** | |||
* Last Modified Timestamp of source file being used. | |||
*/ | |||
private long srcLastModified; | |||
/** | |||
* Starting token to identify keys | |||
*/ | |||
private String startToken; | |||
/** | |||
* Destination directory | |||
*/ | |||
private File toDir; | |||
/** | |||
* Sets Family name of resource bundle | |||
* | |||
* @param bundle The new Bundle value | |||
*/ | |||
public void setBundle( String bundle ) | |||
{ | |||
this.bundle = bundle; | |||
} | |||
/** | |||
* Sets locale specific country of resource bundle | |||
* | |||
* @param bundleCountry The new BundleCountry value | |||
*/ | |||
public void setBundleCountry( String bundleCountry ) | |||
{ | |||
this.bundleCountry = bundleCountry; | |||
} | |||
/** | |||
* Sets Resource Bundle file encoding scheme | |||
* | |||
* @param bundleEncoding The new BundleEncoding value | |||
*/ | |||
public void setBundleEncoding( String bundleEncoding ) | |||
{ | |||
this.bundleEncoding = bundleEncoding; | |||
} | |||
/** | |||
* Sets locale specific language of resource bundle | |||
* | |||
* @param bundleLanguage The new BundleLanguage value | |||
*/ | |||
public void setBundleLanguage( String bundleLanguage ) | |||
{ | |||
this.bundleLanguage = bundleLanguage; | |||
} | |||
/** | |||
* Sets locale specific variant of resource bundle | |||
* | |||
* @param bundleVariant The new BundleVariant value | |||
*/ | |||
public void setBundleVariant( String bundleVariant ) | |||
{ | |||
this.bundleVariant = bundleVariant; | |||
} | |||
/** | |||
* Sets destination file encoding scheme. Defaults to source file encoding | |||
* | |||
* @param destEncoding The new DestEncoding value | |||
*/ | |||
public void setDestEncoding( String destEncoding ) | |||
{ | |||
this.destEncoding = destEncoding; | |||
} | |||
/** | |||
* Sets ending token to identify keys | |||
* | |||
* @param endToken The new EndToken value | |||
*/ | |||
public void setEndToken( String endToken ) | |||
{ | |||
this.endToken = endToken; | |||
} | |||
/** | |||
* Overwrite existing file irrespective of whether it is newer than the | |||
* source file as well as the resource bundle file? Defaults to false. | |||
* | |||
* @param forceOverwrite The new ForceOverwrite value | |||
*/ | |||
public void setForceOverwrite( boolean forceOverwrite ) | |||
{ | |||
this.forceOverwrite = forceOverwrite; | |||
} | |||
/** | |||
* Sets source file encoding scheme | |||
* | |||
* @param srcEncoding The new SrcEncoding value | |||
*/ | |||
public void setSrcEncoding( String srcEncoding ) | |||
{ | |||
this.srcEncoding = srcEncoding; | |||
} | |||
/** | |||
* Sets starting token to identify keys | |||
* | |||
* @param startToken The new StartToken value | |||
*/ | |||
public void setStartToken( String startToken ) | |||
{ | |||
this.startToken = startToken; | |||
} | |||
/** | |||
* Sets Destination directory | |||
* | |||
* @param toDir The new ToDir value | |||
*/ | |||
public void setToDir( File toDir ) | |||
{ | |||
this.toDir = toDir; | |||
} | |||
/** | |||
* Adds a set of files (nested fileset attribute). | |||
* | |||
* @param set The feature to be added to the Fileset attribute | |||
*/ | |||
public void addFileset( FileSet set ) | |||
{ | |||
filesets.add( set ); | |||
} | |||
/** | |||
* Check attributes values, load resource map and translate | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( bundle == null ) | |||
{ | |||
throw new TaskException( "The bundle attribute must be set." ); | |||
} | |||
if( startToken == null ) | |||
{ | |||
throw new TaskException( "The starttoken attribute must be set." ); | |||
} | |||
if( startToken.length() != 1 ) | |||
{ | |||
throw new TaskException( | |||
"The starttoken attribute must be a single character." ); | |||
} | |||
if( endToken == null ) | |||
{ | |||
throw new TaskException( "The endtoken attribute must be set." ); | |||
} | |||
if( endToken.length() != 1 ) | |||
{ | |||
throw new TaskException( | |||
"The endtoken attribute must be a single character." ); | |||
} | |||
if( bundleLanguage == null ) | |||
{ | |||
Locale l = Locale.getDefault(); | |||
bundleLanguage = l.getLanguage(); | |||
} | |||
if( bundleCountry == null ) | |||
{ | |||
bundleCountry = Locale.getDefault().getCountry(); | |||
} | |||
if( bundleVariant == null ) | |||
{ | |||
Locale l = new Locale( bundleLanguage, bundleCountry ); | |||
bundleVariant = l.getVariant(); | |||
} | |||
if( toDir == null ) | |||
{ | |||
throw new TaskException( "The todir attribute must be set." ); | |||
} | |||
if( !toDir.exists() ) | |||
{ | |||
toDir.mkdirs(); | |||
} | |||
else | |||
{ | |||
if( toDir.isFile() ) | |||
{ | |||
throw new TaskException( toDir + " is not a directory" ); | |||
} | |||
} | |||
if( srcEncoding == null ) | |||
{ | |||
srcEncoding = System.getProperty( "file.encoding" ); | |||
} | |||
if( destEncoding == null ) | |||
{ | |||
destEncoding = srcEncoding; | |||
} | |||
if( bundleEncoding == null ) | |||
{ | |||
bundleEncoding = srcEncoding; | |||
} | |||
loadResourceMaps(); | |||
translate(); | |||
} | |||
/** | |||
* Load resourceMap with key value pairs. Values of existing keys are not | |||
* overwritten. Bundle's encoding scheme is used. | |||
* | |||
* @param ins Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
private void loadResourceMap( FileInputStream ins ) | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
BufferedReader in = null; | |||
InputStreamReader isr = new InputStreamReader( ins, bundleEncoding ); | |||
in = new BufferedReader( isr ); | |||
String line = null; | |||
while( ( line = in.readLine() ) != null ) | |||
{ | |||
//So long as the line isn't empty and isn't a comment... | |||
if( line.trim().length() > 1 && | |||
( '#' != line.charAt( 0 ) || '!' != line.charAt( 0 ) ) ) | |||
{ | |||
//Legal Key-Value separators are :, = and white space. | |||
int sepIndex = line.indexOf( '=' ); | |||
if( -1 == sepIndex ) | |||
{ | |||
sepIndex = line.indexOf( ':' ); | |||
} | |||
if( -1 == sepIndex ) | |||
{ | |||
for( int k = 0; k < line.length(); k++ ) | |||
{ | |||
if( Character.isSpaceChar( line.charAt( k ) ) ) | |||
{ | |||
sepIndex = k; | |||
break; | |||
} | |||
} | |||
} | |||
//Only if we do have a key is there going to be a value | |||
if( -1 != sepIndex ) | |||
{ | |||
String key = line.substring( 0, sepIndex ).trim(); | |||
String value = line.substring( sepIndex + 1 ).trim(); | |||
//Handle line continuations, if any | |||
while( value.endsWith( "\\" ) ) | |||
{ | |||
value = value.substring( 0, value.length() - 1 ); | |||
if( ( line = in.readLine() ) != null ) | |||
{ | |||
value = value + line.trim(); | |||
} | |||
else | |||
{ | |||
break; | |||
} | |||
} | |||
if( key.length() > 0 ) | |||
{ | |||
//Has key already been loaded into resourceMap? | |||
if( resourceMap.get( key ) == null ) | |||
{ | |||
resourceMap.put( key, value ); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
if( in != null ) | |||
{ | |||
in.close(); | |||
} | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
throw new TaskException( ioe.getMessage() ); | |||
} | |||
} | |||
/** | |||
* Load resource maps based on resource bundle encoding scheme. The resource | |||
* bundle lookup searches for resource files with various suffixes on the | |||
* basis of (1) the desired locale and (2) the default locale | |||
* (basebundlename), in the following order from lower-level (more specific) | |||
* to parent-level (less specific): basebundlename + "_" + language1 + "_" + | |||
* country1 + "_" + variant1 basebundlename + "_" + language1 + "_" + | |||
* country1 basebundlename + "_" + language1 basebundlename basebundlename + | |||
* "_" + language2 + "_" + country2 + "_" + variant2 basebundlename + "_" + | |||
* language2 + "_" + country2 basebundlename + "_" + language2 To the | |||
* generated name, a ".properties" string is appeneded and once this file is | |||
* located, it is treated just like a properties file but with bundle | |||
* encoding also considered while loading. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
private void loadResourceMaps() | |||
throws TaskException | |||
{ | |||
Locale locale = new Locale( bundleLanguage, | |||
bundleCountry, | |||
bundleVariant ); | |||
String language = locale.getLanguage().length() > 0 ? | |||
"_" + locale.getLanguage() : | |||
""; | |||
String country = locale.getCountry().length() > 0 ? | |||
"_" + locale.getCountry() : | |||
""; | |||
String variant = locale.getVariant().length() > 0 ? | |||
"_" + locale.getVariant() : | |||
""; | |||
String bundleFile = bundle + language + country + variant; | |||
processBundle( bundleFile, 0, false ); | |||
bundleFile = bundle + language + country; | |||
processBundle( bundleFile, 1, false ); | |||
bundleFile = bundle + language; | |||
processBundle( bundleFile, 2, false ); | |||
bundleFile = bundle; | |||
processBundle( bundleFile, 3, false ); | |||
//Load default locale bundle files | |||
//using default file encoding scheme. | |||
locale = Locale.getDefault(); | |||
language = locale.getLanguage().length() > 0 ? | |||
"_" + locale.getLanguage() : | |||
""; | |||
country = locale.getCountry().length() > 0 ? | |||
"_" + locale.getCountry() : | |||
""; | |||
variant = locale.getVariant().length() > 0 ? | |||
"_" + locale.getVariant() : | |||
""; | |||
bundleEncoding = System.getProperty( "file.encoding" ); | |||
bundleFile = bundle + language + country + variant; | |||
processBundle( bundleFile, 4, false ); | |||
bundleFile = bundle + language + country; | |||
processBundle( bundleFile, 5, false ); | |||
bundleFile = bundle + language; | |||
processBundle( bundleFile, 6, true ); | |||
} | |||
/** | |||
* Process each file that makes up this bundle. | |||
* | |||
* @param bundleFile Description of Parameter | |||
* @param i Description of Parameter | |||
* @param checkLoaded Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
private void processBundle( String bundleFile, int i, | |||
boolean checkLoaded ) | |||
throws TaskException | |||
{ | |||
bundleFile += ".properties"; | |||
FileInputStream ins = null; | |||
try | |||
{ | |||
ins = new FileInputStream( bundleFile ); | |||
loaded = true; | |||
bundleLastModified[ i ] = new File( bundleFile ).lastModified(); | |||
getContext().debug( "Using " + bundleFile ); | |||
loadResourceMap( ins ); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
getContext().debug( bundleFile + " not found." ); | |||
//if all resource files associated with this bundle | |||
//have been scanned for and still not able to | |||
//find a single resrouce file, throw exception | |||
if( !loaded && checkLoaded ) | |||
{ | |||
throw new TaskException( ioe.getMessage() ); | |||
} | |||
} | |||
} | |||
/** | |||
* Reads source file line by line using the source encoding and searches for | |||
* keys that are sandwiched between the startToken and endToken. The values | |||
* for these keys are looked up from the hashtable and substituted. If the | |||
* hashtable doesn't contain the key, they key itself is used as the value. | |||
* Detination files and directories are created as needed. The destination | |||
* file is overwritten only if the forceoverwritten attribute is set to true | |||
* if the source file or any associated bundle resource file is newer than | |||
* the destination file. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
private void translate() | |||
throws TaskException | |||
{ | |||
for( int i = 0; i < filesets.size(); i++ ) | |||
{ | |||
FileSet fs = (FileSet)filesets.get( i ); | |||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||
String[] srcFiles = ds.getIncludedFiles(); | |||
for( int j = 0; j < srcFiles.length; j++ ) | |||
{ | |||
try | |||
{ | |||
File dest = FileUtil.resolveFile( toDir, srcFiles[ j ] ); | |||
//Make sure parent dirs exist, else, create them. | |||
try | |||
{ | |||
File destDir = new File( dest.getParent() ); | |||
if( !destDir.exists() ) | |||
{ | |||
destDir.mkdirs(); | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
getContext().debug( "Exception occured while trying to check/create " + " parent directory. " + e.getMessage() ); | |||
} | |||
destLastModified = dest.lastModified(); | |||
srcLastModified = new File( srcFiles[ i ] ).lastModified(); | |||
//Check to see if dest file has to be recreated | |||
if( forceOverwrite | |||
|| destLastModified < srcLastModified | |||
|| destLastModified < bundleLastModified[ 0 ] | |||
|| destLastModified < bundleLastModified[ 1 ] | |||
|| destLastModified < bundleLastModified[ 2 ] | |||
|| destLastModified < bundleLastModified[ 3 ] | |||
|| destLastModified < bundleLastModified[ 4 ] | |||
|| destLastModified < bundleLastModified[ 5 ] | |||
|| destLastModified < bundleLastModified[ 6 ] ) | |||
{ | |||
getContext().debug( "Processing " + srcFiles[ j ] ); | |||
FileOutputStream fos = new FileOutputStream( dest ); | |||
BufferedWriter out = new BufferedWriter( | |||
new OutputStreamWriter( fos, | |||
destEncoding ) ); | |||
FileInputStream fis = new FileInputStream( srcFiles[ j ] ); | |||
BufferedReader in = new BufferedReader( | |||
new InputStreamReader( fis, | |||
srcEncoding ) ); | |||
String line; | |||
while( ( line = in.readLine() ) != null ) | |||
{ | |||
int startIndex = -1; | |||
int endIndex = -1; | |||
outer : | |||
while( true ) | |||
{ | |||
startIndex = line.indexOf( startToken, endIndex + 1 ); | |||
if( startIndex < 0 || | |||
startIndex + 1 >= line.length() ) | |||
{ | |||
break; | |||
} | |||
endIndex = line.indexOf( endToken, startIndex + 1 ); | |||
if( endIndex < 0 ) | |||
{ | |||
break; | |||
} | |||
String matches = line.substring( startIndex + 1, | |||
endIndex ); | |||
//If there is a white space or = or :, then | |||
//it isn't to be treated as a valid key. | |||
for( int k = 0; k < matches.length(); k++ ) | |||
{ | |||
char c = matches.charAt( k ); | |||
if( c == ':' || | |||
c == '=' || | |||
Character.isSpaceChar( c ) ) | |||
{ | |||
endIndex = endIndex - 1; | |||
continue outer; | |||
} | |||
} | |||
String replace = null; | |||
replace = (String)resourceMap.get( matches ); | |||
//If the key hasn't been loaded into resourceMap, | |||
//use the key itself as the value also. | |||
if( replace == null ) | |||
{ | |||
getContext().debug( "Warning: The key: " + matches + " hasn't been defined." ); | |||
replace = matches; | |||
} | |||
line = line.substring( 0, startIndex ) | |||
+ replace | |||
+ line.substring( endIndex + 1 ); | |||
endIndex = startIndex + replace.length() + 1; | |||
if( endIndex + 1 >= line.length() ) | |||
{ | |||
break; | |||
} | |||
} | |||
out.write( line ); | |||
out.newLine(); | |||
} | |||
if( in != null ) | |||
{ | |||
in.close(); | |||
} | |||
if( out != null ) | |||
{ | |||
out.close(); | |||
} | |||
} | |||
else | |||
{ | |||
getContext().debug( "Skipping " + srcFiles[ j ] + " as destination file is up to date" ); | |||
} | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
throw new TaskException( ioe.getMessage() ); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,45 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
/** | |||
* The interface that all compiler adapters must adher to. <p> | |||
* | |||
* A compiler adapter is an adapter that interprets the javac's parameters in | |||
* preperation to be passed off to the compier this adapter represents. As all | |||
* the necessary values are stored in the Javac task itself, the only thing all | |||
* adapters need is the javac task, the execute command and a parameterless | |||
* constructor (for reflection).</p> | |||
* | |||
* @author Jay Dickon Glanville <a href="mailto:jayglanville@home.com"> | |||
* jayglanville@home.com</a> | |||
*/ | |||
public interface CompilerAdapter | |||
{ | |||
void setTaskContext( TaskContext context ); | |||
/** | |||
* Sets the compiler attributes, which are stored in the Javac task. | |||
* | |||
* @param attributes The new Javac value | |||
*/ | |||
void setJavac( Javac attributes ); | |||
/** | |||
* Executes the task. | |||
* | |||
* @return has the compilation been successful | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
boolean execute() | |||
throws TaskException; | |||
} |
@@ -1,155 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.taskdefs.javac.CompilerAdapter; | |||
/** | |||
* Creates the necessary compiler adapter, given basic criteria. | |||
* | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public class CompilerAdapterFactory | |||
{ | |||
/** | |||
* This is a singlton -- can't create instances!! | |||
*/ | |||
private CompilerAdapterFactory() | |||
{ | |||
} | |||
/** | |||
* Based on the parameter passed in, this method creates the necessary | |||
* factory desired. The current mapping for compiler names are as follows: | |||
* | |||
* <ul> | |||
* <li> jikes = jikes compiler | |||
* <li> classic, javac1.1, javac1.2 = the standard compiler from JDK | |||
* 1.1/1.2 | |||
* <li> modern, javac1.3 = the new compiler of JDK 1.3 | |||
* <li> jvc, microsoft = the command line compiler from Microsoft's SDK | |||
* for Java / Visual J++ | |||
* <li> kjc = the kopi compiler</li> | |||
* <li> gcj = the gcj compiler from gcc</li> | |||
* <li> <i>a fully quallified classname</i> = the name of a compiler | |||
* adapter | |||
* </ul> | |||
* | |||
* | |||
* @param compilerType either the name of the desired compiler, or the full | |||
* classname of the compiler's adapter. | |||
* @return The Compiler value | |||
* @throws org.apache.myrmidon.api.TaskException if the compiler type could not be resolved into a | |||
* compiler adapter. | |||
*/ | |||
public static CompilerAdapter getCompiler( String compilerType, | |||
TaskContext context ) | |||
throws TaskException | |||
{ | |||
final CompilerAdapter adaptor = createAdaptor( compilerType, context ); | |||
adaptor.setTaskContext( context ); | |||
return adaptor; | |||
} | |||
private static CompilerAdapter createAdaptor( String compilerType, TaskContext context ) throws TaskException | |||
{ | |||
/* | |||
* If I've done things right, this should be the extent of the | |||
* conditional statements required. | |||
*/ | |||
if( compilerType.equalsIgnoreCase( "jikes" ) ) | |||
{ | |||
return new Jikes(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "extJavac" ) ) | |||
{ | |||
return new JavacExternal(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "classic" ) || | |||
compilerType.equalsIgnoreCase( "javac1.1" ) || | |||
compilerType.equalsIgnoreCase( "javac1.2" ) ) | |||
{ | |||
return new Javac12(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "modern" ) || | |||
compilerType.equalsIgnoreCase( "javac1.3" ) || | |||
compilerType.equalsIgnoreCase( "javac1.4" ) ) | |||
{ | |||
// does the modern compiler exist? | |||
try | |||
{ | |||
Class.forName( "com.sun.tools.javac.Main" ); | |||
} | |||
catch( ClassNotFoundException cnfe ) | |||
{ | |||
final String message = "Modern compiler is not available - using " | |||
+ "classic compiler"; | |||
context.warn( message ); | |||
return new Javac12(); | |||
} | |||
return new Javac13(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "jvc" ) || | |||
compilerType.equalsIgnoreCase( "microsoft" ) ) | |||
{ | |||
return new Jvc(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "kjc" ) ) | |||
{ | |||
return new Kjc(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "gcj" ) ) | |||
{ | |||
return new Gcj(); | |||
} | |||
if( compilerType.equalsIgnoreCase( "sj" ) || | |||
compilerType.equalsIgnoreCase( "symantec" ) ) | |||
{ | |||
return new Sj(); | |||
} | |||
return resolveClassName( compilerType ); | |||
} | |||
/** | |||
* Tries to resolve the given classname into a compiler adapter. Throws a | |||
* fit if it can't. | |||
* | |||
* @param className The fully qualified classname to be created. | |||
* @return Description of the Returned Value | |||
* @throws org.apache.myrmidon.api.TaskException This is the fit that is thrown if className isn't | |||
* an instance of CompilerAdapter. | |||
*/ | |||
private static CompilerAdapter resolveClassName( String className ) | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
Class c = Class.forName( className ); | |||
Object o = c.newInstance(); | |||
return (CompilerAdapter)o; | |||
} | |||
catch( ClassNotFoundException cnfe ) | |||
{ | |||
throw new TaskException( className + " can\'t be found.", cnfe ); | |||
} | |||
catch( ClassCastException cce ) | |||
{ | |||
throw new TaskException( className + " isn\'t the classname of " | |||
+ "a compiler adapter.", cce ); | |||
} | |||
catch( Throwable t ) | |||
{ | |||
// for all other possibilities | |||
throw new TaskException( className + " caused an interesting " | |||
+ "exception.", t ); | |||
} | |||
} | |||
} |
@@ -1,442 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import java.io.File; | |||
import java.io.FileWriter; | |||
import java.io.IOException; | |||
import java.io.PrintWriter; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.avalon.excalibur.io.IOUtil; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
import org.apache.tools.todo.util.FileUtils; | |||
import org.apache.tools.todo.taskdefs.javac.CompilerAdapter; | |||
/** | |||
* This is the default implementation for the CompilerAdapter interface. | |||
* Currently, this is a cut-and-paste of the original javac task. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public abstract class DefaultCompilerAdapter | |||
implements CompilerAdapter | |||
{ | |||
protected boolean m_debug; | |||
protected boolean m_optimize; | |||
protected boolean m_deprecation; | |||
protected boolean m_depend; | |||
protected boolean m_verbose; | |||
protected Javac m_attributes; | |||
protected Path m_bootclasspath; | |||
protected Path m_compileClasspath; | |||
protected File[] m_compileList; | |||
protected File m_destDir; | |||
protected String m_encoding; | |||
protected Path m_extdirs; | |||
protected boolean m_includeAntRuntime; | |||
protected boolean m_includeJavaRuntime; | |||
protected String m_memoryInitialSize; | |||
protected String m_memoryMaximumSize; | |||
protected File m_baseDir; | |||
/* | |||
* jdg - TODO - all these attributes are currently protected, but they | |||
* should probably be private in the near future. | |||
*/ | |||
protected Path src; | |||
protected String target; | |||
private TaskContext m_taskContext; | |||
public void setTaskContext( final TaskContext context ) | |||
{ | |||
m_taskContext = context; | |||
} | |||
protected final TaskContext getTaskContext() | |||
{ | |||
return m_taskContext; | |||
} | |||
public void setJavac( Javac attributes ) | |||
{ | |||
m_attributes = attributes; | |||
src = attributes.getSrcdir(); | |||
m_destDir = attributes.getDestdir(); | |||
m_encoding = attributes.getEncoding(); | |||
m_debug = attributes.getDebug(); | |||
m_optimize = attributes.isOptimize(); | |||
m_deprecation = attributes.getDeprecation(); | |||
m_depend = attributes.getDepend(); | |||
m_verbose = attributes.getVerbose(); | |||
target = attributes.getTarget(); | |||
m_bootclasspath = attributes.getBootclasspath(); | |||
m_extdirs = attributes.getExtdirs(); | |||
m_compileList = attributes.getFileList(); | |||
m_compileClasspath = attributes.getClasspath(); | |||
m_baseDir = attributes.getBaseDirectory(); | |||
m_memoryInitialSize = attributes.getMemoryInitialSize(); | |||
m_memoryMaximumSize = attributes.getMemoryMaximumSize(); | |||
} | |||
public Javac getJavac() | |||
{ | |||
return m_attributes; | |||
} | |||
protected Commandline setupJavacCommand() | |||
throws TaskException | |||
{ | |||
return setupJavacCommand( false ); | |||
} | |||
/** | |||
* Does the command line argument processing for classic and adds the files | |||
* to compile as well. | |||
* | |||
* @param debugLevelCheck Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
protected Commandline setupJavacCommand( boolean debugLevelCheck ) | |||
throws TaskException | |||
{ | |||
Commandline cmd = new Commandline(); | |||
setupJavacCommandlineSwitches( cmd, debugLevelCheck ); | |||
logAndAddFilesToCompile( cmd ); | |||
return cmd; | |||
} | |||
/** | |||
* Does the command line argument processing common to classic and modern. | |||
* Doesn't add the files to compile. | |||
* | |||
* @param cmd Description of Parameter | |||
* @param useDebugLevel Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
protected Commandline setupJavacCommandlineSwitches( Commandline cmd, | |||
boolean useDebugLevel ) | |||
throws TaskException | |||
{ | |||
Path classpath = getCompileClasspath(); | |||
String memoryParameterPrefix = "-J-X"; | |||
if( m_memoryInitialSize != null ) | |||
{ | |||
if( !m_attributes.isForkedJavac() ) | |||
{ | |||
final String message = "Since fork is false, ignoring memoryInitialSize setting."; | |||
getTaskContext().warn( message ); | |||
} | |||
else | |||
{ | |||
cmd.addArgument( memoryParameterPrefix + "ms" + m_memoryInitialSize ); | |||
} | |||
} | |||
if( m_memoryMaximumSize != null ) | |||
{ | |||
if( !m_attributes.isForkedJavac() ) | |||
{ | |||
final String message = "Since fork is false, ignoring memoryMaximumSize setting."; | |||
getTaskContext().warn( message ); | |||
} | |||
else | |||
{ | |||
cmd.addArgument( memoryParameterPrefix + "mx" + m_memoryMaximumSize ); | |||
} | |||
} | |||
if( m_attributes.getNowarn() ) | |||
{ | |||
cmd.addArgument( "-nowarn" ); | |||
} | |||
if( m_deprecation == true ) | |||
{ | |||
cmd.addArgument( "-deprecation" ); | |||
} | |||
if( m_destDir != null ) | |||
{ | |||
cmd.addArgument( "-d" ); | |||
cmd.addArgument( m_destDir ); | |||
} | |||
cmd.addArgument( "-classpath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( classpath ) ); | |||
cmd.addArgument( "-sourcepath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( src ) ); | |||
if( target != null ) | |||
{ | |||
cmd.addArgument( "-target" ); | |||
cmd.addArgument( target ); | |||
} | |||
if( m_bootclasspath != null ) | |||
{ | |||
cmd.addArgument( "-bootclasspath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( m_bootclasspath ) ); | |||
} | |||
if( m_extdirs != null ) | |||
{ | |||
cmd.addArgument( "-extdirs" ); | |||
cmd.addArguments( FileUtils.translateCommandline( m_extdirs ) ); | |||
} | |||
if( m_encoding != null ) | |||
{ | |||
cmd.addArgument( "-encoding" ); | |||
cmd.addArgument( m_encoding ); | |||
} | |||
if( m_debug ) | |||
{ | |||
if( useDebugLevel ) | |||
{ | |||
String debugLevel = m_attributes.getDebugLevel(); | |||
if( debugLevel != null ) | |||
{ | |||
cmd.addArgument( "-g:" + debugLevel ); | |||
} | |||
else | |||
{ | |||
cmd.addArgument( "-g" ); | |||
} | |||
} | |||
else | |||
{ | |||
cmd.addArgument( "-g" ); | |||
} | |||
} | |||
else | |||
{ | |||
cmd.addArgument( "-g:none" ); | |||
} | |||
if( m_optimize ) | |||
{ | |||
cmd.addArgument( "-O" ); | |||
} | |||
if( m_verbose ) | |||
{ | |||
cmd.addArgument( "-verbose" ); | |||
} | |||
addCurrentCompilerArgs( cmd ); | |||
return cmd; | |||
} | |||
/** | |||
* Does the command line argument processing for modern and adds the files | |||
* to compile as well. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
protected Commandline setupModernJavacCommand() | |||
throws TaskException | |||
{ | |||
Commandline cmd = new Commandline(); | |||
setupModernJavacCommandlineSwitches( cmd ); | |||
logAndAddFilesToCompile( cmd ); | |||
return cmd; | |||
} | |||
/** | |||
* Does the command line argument processing for modern. Doesn't add the | |||
* files to compile. | |||
* | |||
* @param cmd Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
protected Commandline setupModernJavacCommandlineSwitches( Commandline cmd ) | |||
throws TaskException | |||
{ | |||
setupJavacCommandlineSwitches( cmd, true ); | |||
if( m_attributes.getSource() != null ) | |||
{ | |||
cmd.addArgument( "-source" ); | |||
cmd.addArgument( m_attributes.getSource() ); | |||
} | |||
return cmd; | |||
} | |||
/** | |||
* Builds the compilation classpath. | |||
* | |||
* @return The CompileClasspath value | |||
*/ | |||
protected Path getCompileClasspath() | |||
throws TaskException | |||
{ | |||
Path classpath = new Path(); | |||
// add dest dir to classpath so that previously compiled and | |||
// untouched classes are on classpath | |||
if( m_destDir != null ) | |||
{ | |||
classpath.addLocation( m_destDir ); | |||
} | |||
// add the classpath | |||
if( m_compileClasspath != null ) | |||
{ | |||
classpath.addExisting( m_compileClasspath ); | |||
} | |||
return classpath; | |||
} | |||
/** | |||
* Adds the command line arguments specifc to the current implementation. | |||
* | |||
* @param cmd The feature to be added to the CurrentCompilerArgs attribute | |||
*/ | |||
protected void addCurrentCompilerArgs( Commandline cmd ) | |||
{ | |||
cmd.addArguments( getJavac().getCurrentCompilerArgs() ); | |||
} | |||
/** | |||
* Do the compile with the specified arguments. | |||
* | |||
* @param args - arguments to pass to process on command line | |||
* @param firstFileName - index of the first source file in args | |||
* @return Description of the Returned Value | |||
*/ | |||
protected int executeExternalCompile( String[] args, int firstFileName ) | |||
throws TaskException | |||
{ | |||
String[] commandArray = null; | |||
File tmpFile = null; | |||
try | |||
{ | |||
/* | |||
* Many system have been reported to get into trouble with | |||
* long command lines - no, not only Windows ;-). | |||
* | |||
* POSIX seems to define a lower limit of 4k, so use a temporary | |||
* file if the total length of the command line exceeds this limit. | |||
*/ | |||
if( StringUtil.join( args, " " ).length() > 4096 ) | |||
{ | |||
PrintWriter out = null; | |||
try | |||
{ | |||
tmpFile = File.createTempFile( "jikes", "", new File( "." ) ); | |||
out = new PrintWriter( new FileWriter( tmpFile ) ); | |||
for( int i = firstFileName; i < args.length; i++ ) | |||
{ | |||
out.println( args[ i ] ); | |||
} | |||
out.flush(); | |||
commandArray = new String[ firstFileName + 1 ]; | |||
System.arraycopy( args, 0, commandArray, 0, firstFileName ); | |||
commandArray[ firstFileName ] = "@" + tmpFile.getAbsolutePath(); | |||
} | |||
catch( final IOException ioe ) | |||
{ | |||
throw new TaskException( "Error creating temporary file", ioe ); | |||
} | |||
finally | |||
{ | |||
IOUtil.shutdownWriter( out ); | |||
} | |||
} | |||
else | |||
{ | |||
commandArray = args; | |||
} | |||
final ExecManager execManager = (ExecManager)m_attributes.getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
exe.setWorkingDirectory( m_baseDir ); | |||
final String[] commandline = commandArray; | |||
exe.setCommandline( new Commandline( commandline ) ); | |||
return exe.execute(); | |||
} | |||
finally | |||
{ | |||
if( tmpFile != null ) | |||
{ | |||
tmpFile.delete(); | |||
} | |||
} | |||
} | |||
/** | |||
* Logs the compilation parameters, adds the files to compile and logs the | |||
* &qout;niceSourceList" | |||
* | |||
* @param cmd Description of Parameter | |||
*/ | |||
protected void logAndAddFilesToCompile( Commandline cmd ) | |||
{ | |||
getTaskContext().debug( "Compilation args: " + cmd.toString() ); | |||
StringBuffer niceSourceList = new StringBuffer( "File" ); | |||
if( m_compileList.length != 1 ) | |||
{ | |||
niceSourceList.append( "s" ); | |||
} | |||
niceSourceList.append( " to be compiled:" ); | |||
niceSourceList.append( StringUtil.LINE_SEPARATOR ); | |||
for( int i = 0; i < m_compileList.length; i++ ) | |||
{ | |||
String arg = m_compileList[ i ].getAbsolutePath(); | |||
cmd.addArgument( arg ); | |||
niceSourceList.append( " " + arg + StringUtil.LINE_SEPARATOR ); | |||
} | |||
getTaskContext().debug( niceSourceList.toString() ); | |||
} | |||
/** | |||
* Emulation of extdirs feature in java >= 1.2. This method adds all files | |||
* in the given directories (but not in sub-directories!) to the classpath, | |||
* so that you don't have to specify them all one by one. | |||
*/ | |||
protected void addExtdirs( Path path ) | |||
throws TaskException | |||
{ | |||
if( m_extdirs == null ) | |||
{ | |||
String extProp = System.getProperty( "java.ext.dirs" ); | |||
if( extProp != null ) | |||
{ | |||
m_extdirs = new Path( extProp ); | |||
} | |||
else | |||
{ | |||
return; | |||
} | |||
} | |||
PathUtil.addExtdirs( path, m_extdirs ); | |||
} | |||
} | |||
@@ -1,113 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.util.FileUtils; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the gcj compiler. This is primarily a cut-and-paste | |||
* from the jikes. | |||
* | |||
* @author <a href="mailto:tora@debian.org">Takashi Okamoto</a> | |||
*/ | |||
public class Gcj extends DefaultCompilerAdapter | |||
{ | |||
/** | |||
* Performs a compile using the gcj compiler. | |||
* | |||
* @return Description of the Returned Value | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
* @author tora@debian.org | |||
*/ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
Commandline cmd; | |||
getTaskContext().debug( "Using gcj compiler" ); | |||
cmd = setupGCJCommand(); | |||
int firstFileName = cmd.size(); | |||
logAndAddFilesToCompile( cmd ); | |||
return executeExternalCompile( cmd.getCommandline(), firstFileName ) == 0; | |||
} | |||
protected Commandline setupGCJCommand() | |||
throws TaskException | |||
{ | |||
Commandline cmd = new Commandline(); | |||
Path classpath = new Path(); | |||
// gcj doesn't support bootclasspath dir (-bootclasspath) | |||
// so we'll emulate it for compatibility and convenience. | |||
if( m_bootclasspath != null ) | |||
{ | |||
classpath.append( m_bootclasspath ); | |||
} | |||
// gcj doesn't support an extension dir (-extdir) | |||
// so we'll emulate it for compatibility and convenience. | |||
addExtdirs( classpath ); | |||
if( ( m_bootclasspath == null ) || ( m_bootclasspath.size() == 0 ) ) | |||
{ | |||
// no bootclasspath, therefore, get one from the java runtime | |||
m_includeJavaRuntime = true; | |||
} | |||
classpath.append( getCompileClasspath() ); | |||
// Gcj has no option for source-path so we | |||
// will add it to classpath. | |||
classpath.append( src ); | |||
cmd.setExecutable( "gcj" ); | |||
if( m_destDir != null ) | |||
{ | |||
cmd.addArgument( "-d" ); | |||
cmd.addArgument( m_destDir ); | |||
if( m_destDir.mkdirs() ) | |||
{ | |||
throw new TaskException( "Can't make output directories. Maybe permission is wrong. " ); | |||
} | |||
; | |||
} | |||
cmd.addArgument( "-classpath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( classpath ) ); | |||
if( m_encoding != null ) | |||
{ | |||
cmd.addArgument( "--encoding=" + m_encoding ); | |||
} | |||
if( m_debug ) | |||
{ | |||
cmd.addArgument( "-g1" ); | |||
} | |||
if( m_optimize ) | |||
{ | |||
cmd.addArgument( "-O" ); | |||
} | |||
/** | |||
* gcj should be set for generate class. | |||
*/ | |||
cmd.addArgument( "-C" ); | |||
addCurrentCompilerArgs( cmd ); | |||
return cmd; | |||
} | |||
} |
@@ -1,43 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.tools.todo.types.Argument; | |||
/** | |||
* Adds an "implementation" attribute to Commandline$Attribute used to | |||
* filter command line attributes based on the current implementation. | |||
*/ | |||
public class ImplementationSpecificArgument | |||
extends Argument | |||
{ | |||
private String m_impl; | |||
private Javac m_javac; | |||
public ImplementationSpecificArgument( Javac javac ) | |||
{ | |||
m_javac = javac; | |||
} | |||
public void setImplementation( String impl ) | |||
{ | |||
this.m_impl = impl; | |||
} | |||
public String[] getParts() | |||
{ | |||
if( m_impl == null || m_impl.equals( m_javac.determineCompiler() ) ) | |||
{ | |||
return super.getParts(); | |||
} | |||
else | |||
{ | |||
return new String[ 0 ]; | |||
} | |||
} | |||
} |
@@ -1,765 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import org.apache.aut.nativelib.Os; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.JavaVersion; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.taskdefs.javac.CompilerAdapter; | |||
import org.apache.tools.todo.taskdefs.javac.CompilerAdapterFactory; | |||
import org.apache.tools.todo.taskdefs.javac.ImplementationSpecificArgument; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.SourceFileScanner; | |||
import org.apache.tools.todo.util.mappers.GlobPatternMapper; | |||
/** | |||
* Task to compile Java source files. This task can take the following | |||
* arguments: | |||
* <ul> | |||
* <li> sourcedir | |||
* <li> destdir | |||
* <li> deprecation | |||
* <li> classpath | |||
* <li> bootclasspath | |||
* <li> extdirs | |||
* <li> optimize | |||
* <li> debug | |||
* <li> encoding | |||
* <li> target | |||
* <li> depend | |||
* <li> vebose | |||
* <li> failonerror | |||
* <li> includeantruntime | |||
* <li> includejavaruntime | |||
* <li> source | |||
* </ul> | |||
* Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required. <p> | |||
* | |||
* When this task executes, it will recursively scan the sourcedir and destdir | |||
* looking for Java source files to compile. This task makes its compile | |||
* decision based on timestamp. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public class Javac | |||
extends MatchingTask | |||
{ | |||
private final static String FAIL_MSG | |||
= "Compile failed, messages should have been provided."; | |||
private boolean m_debug; | |||
private boolean m_optimize; | |||
private boolean m_deprecation; | |||
private boolean m_depend; | |||
private boolean m_verbose; | |||
private boolean m_includeAntRuntime = true; | |||
private boolean m_includeJavaRuntime; | |||
private boolean m_fork; | |||
private String m_forkedExecutable; | |||
private boolean m_nowarn; | |||
private ArrayList m_implementationSpecificArgs = new ArrayList(); | |||
protected File[] m_compileList = new File[ 0 ]; | |||
private Path m_bootclasspath; | |||
private Path m_compileClasspath; | |||
private String m_debugLevel; | |||
private File m_destDir; | |||
private String m_encoding; | |||
private Path m_extdirs; | |||
private String m_memoryInitialSize; | |||
private String m_memoryMaximumSize; | |||
private String m_source; | |||
private Path m_src; | |||
private String m_target; | |||
/** | |||
* Adds an element to the bootclasspath that will be used to compile the | |||
* classes against. | |||
*/ | |||
public void addBootclasspath( Path bootclasspath ) | |||
{ | |||
if( m_bootclasspath == null ) | |||
{ | |||
m_bootclasspath = bootclasspath; | |||
} | |||
else | |||
{ | |||
m_bootclasspath.addPath( bootclasspath ); | |||
} | |||
} | |||
/** | |||
* Adds an element to the classpath to be used for this compilation. | |||
*/ | |||
public void addClasspath( Path classpath ) | |||
{ | |||
if( m_compileClasspath == null ) | |||
{ | |||
m_compileClasspath = classpath; | |||
} | |||
else | |||
{ | |||
m_compileClasspath.addPath( classpath ); | |||
} | |||
} | |||
/** | |||
* Set the debug flag. | |||
*/ | |||
public void setDebug( final boolean debug ) | |||
{ | |||
m_debug = debug; | |||
} | |||
/** | |||
* Set the value of debugLevel. | |||
* | |||
* @param v Value to assign to debugLevel. | |||
*/ | |||
public void setDebugLevel( String v ) | |||
{ | |||
m_debugLevel = v; | |||
} | |||
/** | |||
* Set the depend flag. | |||
* | |||
* @param depend The new Depend value | |||
*/ | |||
public void setDepend( boolean depend ) | |||
{ | |||
m_depend = depend; | |||
} | |||
/** | |||
* Set the deprecation flag. | |||
* | |||
* @param deprecation The new Deprecation value | |||
*/ | |||
public void setDeprecation( boolean deprecation ) | |||
{ | |||
m_deprecation = deprecation; | |||
} | |||
/** | |||
* Set the destination directory into which the Java source files should be | |||
* compiled. | |||
* | |||
* @param destDir The new Destdir value | |||
*/ | |||
public void setDestdir( File destDir ) | |||
{ | |||
m_destDir = destDir; | |||
} | |||
/** | |||
* Set the Java source file encoding name. | |||
* | |||
* @param encoding The new Encoding value | |||
*/ | |||
public void setEncoding( String encoding ) | |||
{ | |||
m_encoding = encoding; | |||
} | |||
/** | |||
* Adds an element to the extension directories that will be used during | |||
* the compilation. | |||
* | |||
* @param extdirs The new Extdirs value | |||
*/ | |||
public void addExtdirs( Path extdirs ) | |||
throws TaskException | |||
{ | |||
if( m_extdirs == null ) | |||
{ | |||
m_extdirs = extdirs; | |||
} | |||
else | |||
{ | |||
m_extdirs.addPath( extdirs ); | |||
} | |||
} | |||
/** | |||
* Sets whether to fork the javac compiler. | |||
*/ | |||
public void setFork( final boolean fork ) | |||
{ | |||
m_fork = fork; | |||
if( fork ) | |||
{ | |||
m_forkedExecutable = getSystemJavac(); | |||
} | |||
} | |||
/** | |||
* Include ant's own classpath in this task's classpath? | |||
* | |||
* @param include The new Includeantruntime value | |||
*/ | |||
public void setIncludeantruntime( boolean include ) | |||
{ | |||
m_includeAntRuntime = include; | |||
} | |||
/** | |||
* Sets whether or not to include the java runtime libraries to this task's | |||
* classpath. | |||
* | |||
* @param include The new Includejavaruntime value | |||
*/ | |||
public void setIncludejavaruntime( boolean include ) | |||
{ | |||
m_includeJavaRuntime = include; | |||
} | |||
/** | |||
* Set the memoryInitialSize flag. | |||
* | |||
* @param memoryInitialSize The new MemoryInitialSize value | |||
*/ | |||
public void setMemoryInitialSize( String memoryInitialSize ) | |||
{ | |||
m_memoryInitialSize = memoryInitialSize; | |||
} | |||
/** | |||
* Set the memoryMaximumSize flag. | |||
* | |||
* @param memoryMaximumSize The new MemoryMaximumSize value | |||
*/ | |||
public void setMemoryMaximumSize( String memoryMaximumSize ) | |||
{ | |||
m_memoryMaximumSize = memoryMaximumSize; | |||
} | |||
/** | |||
* Sets whether the -nowarn option should be used. | |||
* | |||
* @param flag The new Nowarn value | |||
*/ | |||
public void setNowarn( boolean flag ) | |||
{ | |||
m_nowarn = flag; | |||
} | |||
/** | |||
* Set the optimize flag. | |||
* | |||
* @param optimize The new Optimize value | |||
*/ | |||
public void setOptimize( boolean optimize ) | |||
{ | |||
m_optimize = optimize; | |||
} | |||
/** | |||
* Set the value of source. | |||
* | |||
* @param v Value to assign to source. | |||
*/ | |||
public void setSource( String v ) | |||
{ | |||
m_source = v; | |||
} | |||
/** | |||
* Adds an element to the source dirs to find the source Java files. | |||
* | |||
* @param srcDir The new Srcdir value | |||
*/ | |||
public void addSrcdir( Path srcDir ) | |||
throws TaskException | |||
{ | |||
if( m_src == null ) | |||
{ | |||
m_src = srcDir; | |||
} | |||
else | |||
{ | |||
m_src.addPath( srcDir ); | |||
} | |||
} | |||
/** | |||
* Sets the target VM that the classes will be compiled for. Valid strings | |||
* are "1.1", "1.2", and "1.3". | |||
* | |||
* @param target The new Target value | |||
*/ | |||
public void setTarget( String target ) | |||
{ | |||
m_target = target; | |||
} | |||
/** | |||
* Set the verbose flag. | |||
* | |||
* @param verbose The new Verbose value | |||
*/ | |||
public void setVerbose( boolean verbose ) | |||
{ | |||
m_verbose = verbose; | |||
} | |||
/** | |||
* Gets the bootclasspath that will be used to compile the classes against. | |||
* | |||
* @return The Bootclasspath value | |||
*/ | |||
public Path getBootclasspath() | |||
{ | |||
return m_bootclasspath; | |||
} | |||
/** | |||
* Gets the classpath to be used for this compilation. | |||
* | |||
* @return The Classpath value | |||
*/ | |||
public Path getClasspath() | |||
{ | |||
return m_compileClasspath; | |||
} | |||
protected File getBaseDir() | |||
{ | |||
return getBaseDirectory(); | |||
} | |||
/** | |||
* Get the additional implementation specific command line arguments. | |||
* | |||
* @return array of command line arguments, guaranteed to be non-null. | |||
*/ | |||
public String[] getCurrentCompilerArgs() | |||
{ | |||
ArrayList args = new ArrayList(); | |||
for( Iterator enum = m_implementationSpecificArgs.iterator(); | |||
enum.hasNext(); | |||
) | |||
{ | |||
String[] curr = | |||
( (ImplementationSpecificArgument)enum.next() ).getParts(); | |||
for( int i = 0; i < curr.length; i++ ) | |||
{ | |||
args.add( curr[ i ] ); | |||
} | |||
} | |||
final String[] res = new String[ args.size() ]; | |||
return (String[])args.toArray( res ); | |||
} | |||
/** | |||
* Gets the debug flag. | |||
* | |||
* @return The Debug value | |||
*/ | |||
public boolean getDebug() | |||
{ | |||
return m_debug; | |||
} | |||
/** | |||
* Get the value of debugLevel. | |||
* | |||
* @return value of debugLevel. | |||
*/ | |||
public String getDebugLevel() | |||
{ | |||
return m_debugLevel; | |||
} | |||
/** | |||
* Gets the depend flag. | |||
* | |||
* @return The Depend value | |||
*/ | |||
public boolean getDepend() | |||
{ | |||
return m_depend; | |||
} | |||
/** | |||
* Gets the deprecation flag. | |||
* | |||
* @return The Deprecation value | |||
*/ | |||
public boolean getDeprecation() | |||
{ | |||
return m_deprecation; | |||
} | |||
/** | |||
* Gets the destination directory into which the java source files should be | |||
* compiled. | |||
* | |||
* @return The Destdir value | |||
*/ | |||
public File getDestdir() | |||
{ | |||
return m_destDir; | |||
} | |||
/** | |||
* Gets the java source file encoding name. | |||
* | |||
* @return The Encoding value | |||
*/ | |||
public String getEncoding() | |||
{ | |||
return m_encoding; | |||
} | |||
/** | |||
* Gets the extension directories that will be used during the compilation. | |||
* | |||
* @return The Extdirs value | |||
*/ | |||
public Path getExtdirs() | |||
{ | |||
return m_extdirs; | |||
} | |||
/** | |||
* Gets the list of files to be compiled. | |||
* | |||
* @return The FileList value | |||
*/ | |||
public File[] getFileList() | |||
{ | |||
return m_compileList; | |||
} | |||
/** | |||
* Gets whether or not the ant classpath is to be included in the task's | |||
* classpath. | |||
* | |||
* @return The Includeantruntime value | |||
*/ | |||
public boolean getIncludeantruntime() | |||
{ | |||
return m_includeAntRuntime; | |||
} | |||
/** | |||
* Gets whether or not the java runtime should be included in this task's | |||
* classpath. | |||
* | |||
* @return The Includejavaruntime value | |||
*/ | |||
public boolean getIncludejavaruntime() | |||
{ | |||
return m_includeJavaRuntime; | |||
} | |||
/** | |||
* The name of the javac executable to use in fork-mode. | |||
* | |||
* @return The JavacExecutable value | |||
*/ | |||
public String getJavacExecutable() | |||
{ | |||
if( m_forkedExecutable == null && isForkedJavac() ) | |||
{ | |||
m_forkedExecutable = getSystemJavac(); | |||
} | |||
else if( m_forkedExecutable != null && !isForkedJavac() ) | |||
{ | |||
m_forkedExecutable = null; | |||
} | |||
return m_forkedExecutable; | |||
} | |||
/** | |||
* Gets the memoryInitialSize flag. | |||
* | |||
* @return The MemoryInitialSize value | |||
*/ | |||
public String getMemoryInitialSize() | |||
{ | |||
return m_memoryInitialSize; | |||
} | |||
/** | |||
* Gets the memoryMaximumSize flag. | |||
* | |||
* @return The MemoryMaximumSize value | |||
*/ | |||
public String getMemoryMaximumSize() | |||
{ | |||
return m_memoryMaximumSize; | |||
} | |||
/** | |||
* Should the -nowarn option be used. | |||
* | |||
* @return The Nowarn value | |||
*/ | |||
public boolean getNowarn() | |||
{ | |||
return m_nowarn; | |||
} | |||
/** | |||
* Gets the optimize flag. | |||
* | |||
* @return The Optimize value | |||
*/ | |||
public boolean isOptimize() | |||
{ | |||
return m_optimize; | |||
} | |||
/** | |||
* Get the value of source. | |||
* | |||
* @return value of source. | |||
*/ | |||
public String getSource() | |||
{ | |||
return m_source; | |||
} | |||
/** | |||
* Gets the source dirs to find the source java files. | |||
* | |||
* @return The Srcdir value | |||
*/ | |||
public Path getSrcdir() | |||
{ | |||
return m_src; | |||
} | |||
/** | |||
* Gets the target VM that the classes will be compiled for. | |||
* | |||
* @return The Target value | |||
*/ | |||
public String getTarget() | |||
{ | |||
return m_target; | |||
} | |||
/** | |||
* Gets the verbose flag. | |||
* | |||
* @return The Verbose value | |||
*/ | |||
public boolean getVerbose() | |||
{ | |||
return m_verbose; | |||
} | |||
/** | |||
* Is this a forked invocation of JDK's javac? | |||
* | |||
* @return The ForkedJavac value | |||
*/ | |||
public boolean isForkedJavac() | |||
{ | |||
return m_fork; | |||
} | |||
/** | |||
* Adds an implementation specific command line argument. | |||
*/ | |||
public ImplementationSpecificArgument createCompilerArg() | |||
{ | |||
final ImplementationSpecificArgument arg = new ImplementationSpecificArgument( this ); | |||
m_implementationSpecificArgs.add( arg ); | |||
return arg; | |||
} | |||
/** | |||
* Executes the task. | |||
* | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
// first off, make sure that we've got a srcdir | |||
if( m_src == null ) | |||
{ | |||
throw new TaskException( "srcdir attribute must be set!" ); | |||
} | |||
String[] list = m_src.list(); | |||
if( list.length == 0 ) | |||
{ | |||
throw new TaskException( "srcdir attribute must be set!" ); | |||
} | |||
if( m_destDir != null && !m_destDir.isDirectory() ) | |||
{ | |||
throw new TaskException( "destination directory \"" + m_destDir + "\" does not exist or is not a directory" ); | |||
} | |||
// scan source directories and dest directory to build up | |||
// compile lists | |||
resetFileLists(); | |||
for( int i = 0; i < list.length; i++ ) | |||
{ | |||
final String filename = list[ i ]; | |||
File srcDir = (File)getContext().resolveFile( filename ); | |||
if( !srcDir.exists() ) | |||
{ | |||
throw new TaskException( "srcdir \"" + srcDir.getPath() + "\" does not exist!" ); | |||
} | |||
DirectoryScanner ds = getDirectoryScanner( srcDir ); | |||
String[] files = ds.getIncludedFiles(); | |||
scanDir( srcDir, m_destDir != null ? m_destDir : srcDir, files ); | |||
} | |||
// compile the source files | |||
String compiler = determineCompiler(); | |||
if( m_compileList.length > 0 ) | |||
{ | |||
CompilerAdapter adapter = | |||
CompilerAdapterFactory.getCompiler( compiler, getContext() ); | |||
final String message = "Compiling " + m_compileList.length + " source file" + | |||
( m_compileList.length == 1 ? "" : "s" ) + | |||
( m_destDir != null ? " to " + m_destDir : "" ); | |||
getContext().info( message ); | |||
// now we need to populate the compiler adapter | |||
adapter.setJavac( this ); | |||
// finally, lets execute the compiler!! | |||
if( !adapter.execute() ) | |||
{ | |||
throw new TaskException( FAIL_MSG ); | |||
} | |||
} | |||
} | |||
protected String getSystemJavac() | |||
{ | |||
// This is the most common extension case - exe for windows and OS/2, | |||
// nothing for *nix. | |||
String extension = Os.isFamily( Os.OS_FAMILY_DOS ) ? ".exe" : ""; | |||
// Look for java in the java.home/../bin directory. Unfortunately | |||
// on Windows java.home doesn't always refer to the correct location, | |||
// so we need to fall back to assuming java is somewhere on the | |||
// PATH. | |||
File jExecutable = | |||
new File( System.getProperty( "java.home" ) + | |||
"/../bin/javac" + extension ); | |||
if( jExecutable.exists() && !Os.isFamily( Os.OS_FAMILY_NETWARE ) ) | |||
{ | |||
return jExecutable.getAbsolutePath(); | |||
} | |||
else | |||
{ | |||
return "javac"; | |||
} | |||
} | |||
protected boolean isJdkCompiler( String compiler ) | |||
{ | |||
return "modern".equals( compiler ) || | |||
"classic".equals( compiler ) || | |||
"javac1.1".equals( compiler ) || | |||
"javac1.2".equals( compiler ) || | |||
"javac1.3".equals( compiler ) || | |||
"javac1.4".equals( compiler ); | |||
} | |||
/** | |||
* Clear the list of files to be compiled and copied.. | |||
*/ | |||
protected void resetFileLists() | |||
{ | |||
m_compileList = new File[ 0 ]; | |||
} | |||
/** | |||
* Scans the directory looking for source files to be compiled. The results | |||
* are returned in the class variable compileList | |||
* | |||
* @param srcDir Description of Parameter | |||
* @param destDir Description of Parameter | |||
* @param files Description of Parameter | |||
*/ | |||
protected void scanDir( File srcDir, File destDir, String files[] ) | |||
throws TaskException | |||
{ | |||
GlobPatternMapper m = new GlobPatternMapper(); | |||
m.setFrom( "*.java" ); | |||
m.setTo( "*.class" ); | |||
SourceFileScanner sfs = new SourceFileScanner(); | |||
File[] newFiles = sfs.restrictAsFiles( files, srcDir, destDir, m, getContext() ); | |||
if( newFiles.length > 0 ) | |||
{ | |||
File[] newCompileList = new File[ m_compileList.length + | |||
newFiles.length ]; | |||
System.arraycopy( m_compileList, 0, newCompileList, 0, | |||
m_compileList.length ); | |||
System.arraycopy( newFiles, 0, newCompileList, | |||
m_compileList.length, newFiles.length ); | |||
m_compileList = newCompileList; | |||
} | |||
} | |||
protected String determineCompiler() | |||
{ | |||
Object compiler = getContext().getProperty( "build.compiler" ); | |||
if( compiler != null ) | |||
{ | |||
if( isJdkCompiler( compiler.toString() ) ) | |||
{ | |||
final String message = "Since fork is true, ignoring build.compiler setting."; | |||
getContext().warn( message ); | |||
compiler = "extJavac"; | |||
} | |||
else | |||
{ | |||
getContext().warn( "Since build.compiler setting isn't classic or modern, ignoring fork setting." ); | |||
} | |||
} | |||
else | |||
{ | |||
compiler = "extJavac"; | |||
} | |||
if( compiler == null ) | |||
{ | |||
if( JavaVersion.JAVA1_2 != JavaVersion.getCurrentJavaVersion() ) | |||
{ | |||
compiler = "modern"; | |||
} | |||
else | |||
{ | |||
compiler = "classic"; | |||
} | |||
} | |||
return compiler.toString(); | |||
} | |||
} |
@@ -1,68 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import java.io.OutputStream; | |||
import java.lang.reflect.Constructor; | |||
import java.lang.reflect.Method; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the javac compiler for JDK 1.2 This is primarily a | |||
* cut-and-paste from the original javac task before it was refactored. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public class Javac12 extends DefaultCompilerAdapter | |||
{ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using classic compiler" ); | |||
Commandline cmd = setupJavacCommand( true ); | |||
try | |||
{ | |||
// Create an instance of the compiler, redirecting output to | |||
// the project log | |||
Class c = Class.forName( "sun.tools.javac.Main" ); | |||
Constructor cons = c.getConstructor( new Class[]{OutputStream.class, String.class} ); | |||
Object compiler = cons.newInstance( new Object[]{System.out, "javac"} ); | |||
// Call the compile() method | |||
Method compile = c.getMethod( "compile", new Class[]{String[].class} ); | |||
Boolean ok = (Boolean)compile.invoke( compiler, new Object[]{cmd.getArguments()} ); | |||
return ok.booleanValue(); | |||
} | |||
catch( ClassNotFoundException ex ) | |||
{ | |||
throw new TaskException( "Cannot use classic compiler, as it is not available" + | |||
" A common solution is to set the environment variable" + | |||
" JAVA_HOME to your jdk directory." ); | |||
} | |||
catch( Exception ex ) | |||
{ | |||
if( ex instanceof TaskException ) | |||
{ | |||
throw (TaskException)ex; | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Error starting classic compiler: ", ex ); | |||
} | |||
} | |||
} | |||
} |
@@ -1,63 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import java.lang.reflect.Method; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the javac compiler for JDK 1.3 This is primarily a | |||
* cut-and-paste from the original javac task before it was refactored. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public class Javac13 extends DefaultCompilerAdapter | |||
{ | |||
/** | |||
* Integer returned by the "Modern" jdk1.3 compiler to indicate success. | |||
*/ | |||
private final static int MODERN_COMPILER_SUCCESS = 0; | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using modern compiler" ); | |||
Commandline cmd = setupModernJavacCommand(); | |||
// Use reflection to be able to build on all JDKs >= 1.1: | |||
try | |||
{ | |||
Class c = Class.forName( "com.sun.tools.javac.Main" ); | |||
Object compiler = c.newInstance(); | |||
Method compile = c.getMethod( "compile", | |||
new Class[]{( new String[]{} ).getClass()} ); | |||
int result = ( (Integer)compile.invoke | |||
( compiler, new Object[]{cmd.getArguments()} ) ).intValue(); | |||
return ( result == MODERN_COMPILER_SUCCESS ); | |||
} | |||
catch( Exception ex ) | |||
{ | |||
if( ex instanceof TaskException ) | |||
{ | |||
throw (TaskException)ex; | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Error starting modern compiler", ex ); | |||
} | |||
} | |||
} | |||
} |
@@ -1,44 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* Performs a compile using javac externally. | |||
* | |||
* @author Brian Deitte | |||
*/ | |||
public class JavacExternal extends DefaultCompilerAdapter | |||
{ | |||
/** | |||
* Performs a compile using the Javac externally. | |||
* | |||
* @return Description of the Returned Value | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
*/ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using external javac compiler" ); | |||
Commandline cmd = new Commandline(); | |||
cmd.setExecutable( getJavac().getJavacExecutable() ); | |||
setupModernJavacCommandlineSwitches( cmd ); | |||
int firstFileName = cmd.size(); | |||
logAndAddFilesToCompile( cmd ); | |||
return executeExternalCompile( cmd.getCommandline(), firstFileName ) == 0; | |||
} | |||
} | |||
@@ -1,143 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.util.FileUtils; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the jikes compiler. This is primarily a cut-and-paste | |||
* from the original javac task before it was refactored. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public class Jikes | |||
extends DefaultCompilerAdapter | |||
{ | |||
/** | |||
* Performs a compile using the Jikes compiler from IBM.. Mostly of this | |||
* code is identical to doClassicCompile() However, it does not support all | |||
* options like bootclasspath, extdirs, deprecation and so on, because there | |||
* is no option in jikes and I don't understand what they should do. It has | |||
* been successfully tested with jikes >1.10 | |||
* | |||
* @return Description of the Returned Value | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
* @author skanthak@muehlheim.de | |||
*/ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using jikes compiler" ); | |||
Path classpath = new Path(); | |||
// Jikes doesn't support bootclasspath dir (-bootclasspath) | |||
// so we'll emulate it for compatibility and convenience. | |||
if( m_bootclasspath != null ) | |||
{ | |||
classpath.append( m_bootclasspath ); | |||
} | |||
// Jikes doesn't support an extension dir (-extdir) | |||
// so we'll emulate it for compatibility and convenience. | |||
addExtdirs( classpath ); | |||
if( ( m_bootclasspath == null ) || ( m_bootclasspath.size() == 0 ) ) | |||
{ | |||
// no bootclasspath, therefore, get one from the java runtime | |||
m_includeJavaRuntime = true; | |||
} | |||
else | |||
{ | |||
// there is a bootclasspath stated. By default, the | |||
// includeJavaRuntime is false. If the user has stated a | |||
// bootclasspath and said to include the java runtime, it's on | |||
// their head! | |||
} | |||
classpath.append( getCompileClasspath() ); | |||
// Jikes has no option for source-path so we | |||
// will add it to classpath. | |||
classpath.append( src ); | |||
// if the user has set JIKESPATH we should add the contents as well | |||
String jikesPath = System.getProperty( "jikes.class.path" ); | |||
if( jikesPath != null ) | |||
{ | |||
classpath.append( new Path( jikesPath ) ); | |||
} | |||
Commandline cmd = new Commandline(); | |||
cmd.setExecutable( "jikes" ); | |||
if( m_deprecation == true ) | |||
{ | |||
cmd.addArgument( "-deprecation" ); | |||
} | |||
if( m_destDir != null ) | |||
{ | |||
cmd.addArgument( "-d" ); | |||
cmd.addArgument( m_destDir ); | |||
} | |||
cmd.addArgument( "-classpath" ); | |||
cmd.addArguments( FileUtils.translateCommandline( classpath ) ); | |||
if( m_encoding != null ) | |||
{ | |||
cmd.addArgument( "-encoding" ); | |||
cmd.addArgument( m_encoding ); | |||
} | |||
if( m_debug ) | |||
{ | |||
cmd.addArgument( "-g" ); | |||
} | |||
if( m_optimize ) | |||
{ | |||
cmd.addArgument( "-O" ); | |||
} | |||
if( m_verbose ) | |||
{ | |||
cmd.addArgument( "-verbose" ); | |||
} | |||
if( m_depend ) | |||
{ | |||
cmd.addArgument( "-depend" ); | |||
} | |||
if( m_attributes.getNowarn() ) | |||
{ | |||
/* | |||
* FIXME later | |||
* | |||
* let the magic property win over the attribute for backwards | |||
* compatibility | |||
*/ | |||
cmd.addArgument( "-nowarn" ); | |||
} | |||
addCurrentCompilerArgs( cmd ); | |||
int firstFileName = cmd.size(); | |||
logAndAddFilesToCompile( cmd ); | |||
return executeExternalCompile( cmd.getCommandline(), firstFileName ) == 0; | |||
} | |||
} |
@@ -1,106 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.util.FileUtils; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the jvc compiler from microsoft. This is primarily a | |||
* cut-and-paste from the original javac task before it was refactored. | |||
* | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
*/ | |||
public class Jvc extends DefaultCompilerAdapter | |||
{ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using jvc compiler" ); | |||
Path classpath = new Path(); | |||
// jvc doesn't support bootclasspath dir (-bootclasspath) | |||
// so we'll emulate it for compatibility and convenience. | |||
if( m_bootclasspath != null ) | |||
{ | |||
classpath.append( m_bootclasspath ); | |||
} | |||
// jvc doesn't support an extension dir (-extdir) | |||
// so we'll emulate it for compatibility and convenience. | |||
addExtdirs( classpath ); | |||
if( ( m_bootclasspath == null ) || ( m_bootclasspath.size() == 0 ) ) | |||
{ | |||
// no bootclasspath, therefore, get one from the java runtime | |||
m_includeJavaRuntime = true; | |||
} | |||
else | |||
{ | |||
// there is a bootclasspath stated. By default, the | |||
// includeJavaRuntime is false. If the user has stated a | |||
// bootclasspath and said to include the java runtime, it's on | |||
// their head! | |||
} | |||
classpath.append( getCompileClasspath() ); | |||
// jvc has no option for source-path so we | |||
// will add it to classpath. | |||
classpath.append( src ); | |||
Commandline cmd = new Commandline(); | |||
cmd.setExecutable( "jvc" ); | |||
if( m_destDir != null ) | |||
{ | |||
cmd.addArgument( "/d" ); | |||
cmd.addArgument( m_destDir ); | |||
} | |||
// Add the Classpath before the "internal" one. | |||
cmd.addArgument( "/cp:p" ); | |||
cmd.addArguments( FileUtils.translateCommandline( classpath ) ); | |||
// Enable MS-Extensions and ... | |||
cmd.addArgument( "/x-" ); | |||
// ... do not display a Message about this. | |||
cmd.addArgument( "/nomessage" ); | |||
// Do not display Logo | |||
cmd.addArgument( "/nologo" ); | |||
if( m_debug ) | |||
{ | |||
cmd.addArgument( "/g" ); | |||
} | |||
if( m_optimize ) | |||
{ | |||
cmd.addArgument( "/O" ); | |||
} | |||
if( m_verbose ) | |||
{ | |||
cmd.addArgument( "/verbose" ); | |||
} | |||
addCurrentCompilerArgs( cmd ); | |||
int firstFileName = cmd.size(); | |||
logAndAddFilesToCompile( cmd ); | |||
return executeExternalCompile( cmd.getCommandline(), firstFileName ) == 0; | |||
} | |||
} |
@@ -1,137 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import java.lang.reflect.Method; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.util.FileUtils; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the Java compiler for KJC. This is primarily a | |||
* cut-and-paste from Jikes.java and DefaultCompilerAdapter. | |||
* | |||
* @author <a href="mailto:tora@debian.org">Takashi Okamoto</a> + | |||
*/ | |||
public class Kjc extends DefaultCompilerAdapter | |||
{ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using kjc compiler" ); | |||
Commandline cmd = setupKjcCommand(); | |||
try | |||
{ | |||
Class c = Class.forName( "at.dms.kjc.Main" ); | |||
// Call the compile() method | |||
Method compile = c.getMethod( "compile", | |||
new Class[]{String[].class} ); | |||
Boolean ok = (Boolean)compile.invoke( null, | |||
new Object[]{cmd.getArguments()} ); | |||
return ok.booleanValue(); | |||
} | |||
catch( ClassNotFoundException ex ) | |||
{ | |||
throw new TaskException( "Cannot use kjc compiler, as it is not available" + | |||
" A common solution is to set the environment variable" + | |||
" CLASSPATH to your kjc archive (kjc.jar)." ); | |||
} | |||
catch( Exception ex ) | |||
{ | |||
if( ex instanceof TaskException ) | |||
{ | |||
throw (TaskException)ex; | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Error starting kjc compiler: ", ex ); | |||
} | |||
} | |||
} | |||
/** | |||
* setup kjc command arguments. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
protected Commandline setupKjcCommand() | |||
throws TaskException | |||
{ | |||
Commandline cmd = new Commandline(); | |||
// generate classpath, because kjc does't support sourcepath. | |||
Path classpath = getCompileClasspath(); | |||
if( m_deprecation == true ) | |||
{ | |||
cmd.addArgument( "-deprecation" ); | |||
} | |||
if( m_destDir != null ) | |||
{ | |||
cmd.addArgument( "-d" ); | |||
cmd.addArgument( m_destDir ); | |||
} | |||
// generate the clsspath | |||
cmd.addArgument( "-classpath" ); | |||
Path cp = new Path(); | |||
// kjc don't have bootclasspath option. | |||
if( m_bootclasspath != null ) | |||
{ | |||
cp.append( m_bootclasspath ); | |||
} | |||
if( m_extdirs != null ) | |||
{ | |||
addExtdirs( cp ); | |||
} | |||
cp.append( classpath ); | |||
cp.append( src ); | |||
cmd.addArguments( FileUtils.translateCommandline( cp ) ); | |||
// kjc-1.5A doesn't support -encoding option now. | |||
// but it will be supported near the feature. | |||
if( m_encoding != null ) | |||
{ | |||
cmd.addArgument( "-encoding" ); | |||
cmd.addArgument( m_encoding ); | |||
} | |||
if( m_debug ) | |||
{ | |||
cmd.addArgument( "-g" ); | |||
} | |||
if( m_optimize ) | |||
{ | |||
cmd.addArgument( "-O2" ); | |||
} | |||
if( m_verbose ) | |||
{ | |||
cmd.addArgument( "-verbose" ); | |||
} | |||
addCurrentCompilerArgs( cmd ); | |||
logAndAddFilesToCompile( cmd ); | |||
return cmd; | |||
} | |||
} | |||
@@ -1,45 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javac; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.taskdefs.javac.DefaultCompilerAdapter; | |||
/** | |||
* The implementation of the sj compiler. Uses the defaults for | |||
* DefaultCompilerAdapter | |||
* | |||
* @author <a href="mailto:don@bea.com">Don Ferguson</a> | |||
*/ | |||
public class Sj extends DefaultCompilerAdapter | |||
{ | |||
/** | |||
* Performs a compile using the sj compiler from Symantec. | |||
* | |||
* @return Description of the Returned Value | |||
* @exception org.apache.myrmidon.api.TaskException Description of Exception | |||
* @author don@bea.com | |||
*/ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using symantec java compiler" ); | |||
Commandline cmd = setupJavacCommand(); | |||
cmd.setExecutable( "sj" ); | |||
int firstFileName = cmd.size() - m_compileList.length; | |||
return executeExternalCompile( cmd.getCommandline(), firstFileName ) == 0; | |||
} | |||
} | |||
@@ -1,191 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javacc; | |||
import java.io.File; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.CommandlineJava; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
/** | |||
* Taskdef for the JJTree compiler compiler. | |||
* | |||
* @author thomas.haas@softwired-inc.com | |||
* @author Michael Saunders <a href="mailto:michael@amtec.com">michael@amtec.com | |||
* </a> | |||
*/ | |||
public class JJTree | |||
extends AbstractTask | |||
{ | |||
// keys to optional attributes | |||
private final static String BUILD_NODE_FILES = "BUILD_NODE_FILES"; | |||
private final static String MULTI = "MULTI"; | |||
private final static String NODE_DEFAULT_VOID = "NODE_DEFAULT_VOID"; | |||
private final static String NODE_FACTORY = "NODE_FACTORY"; | |||
private final static String NODE_SCOPE_HOOK = "NODE_SCOPE_HOOK"; | |||
private final static String NODE_USES_PARSER = "NODE_USES_PARSER"; | |||
private final static String STATIC = "STATIC"; | |||
private final static String VISITOR = "VISITOR"; | |||
private final static String NODE_PACKAGE = "NODE_PACKAGE"; | |||
private final static String VISITOR_EXCEPTION = "VISITOR_EXCEPTION"; | |||
private final static String NODE_PREFIX = "NODE_PREFIX"; | |||
private final Hashtable optionalAttrs = new Hashtable(); | |||
// required attributes | |||
private File outputDirectory = null; | |||
private File target = null; | |||
private File javaccHome = null; | |||
private CommandlineJava cmdl = new CommandlineJava(); | |||
public JJTree() | |||
{ | |||
cmdl.setVm( "java" ); | |||
cmdl.setClassname( "COM.sun.labs.jjtree.Main" ); | |||
} | |||
public void setBuildnodefiles( boolean buildNodeFiles ) | |||
{ | |||
optionalAttrs.put( BUILD_NODE_FILES, new Boolean( buildNodeFiles ) ); | |||
} | |||
public void setJavacchome( File javaccHome ) | |||
{ | |||
this.javaccHome = javaccHome; | |||
} | |||
public void setMulti( boolean multi ) | |||
{ | |||
optionalAttrs.put( MULTI, new Boolean( multi ) ); | |||
} | |||
public void setNodedefaultvoid( boolean nodeDefaultVoid ) | |||
{ | |||
optionalAttrs.put( NODE_DEFAULT_VOID, new Boolean( nodeDefaultVoid ) ); | |||
} | |||
public void setNodefactory( boolean nodeFactory ) | |||
{ | |||
optionalAttrs.put( NODE_FACTORY, new Boolean( nodeFactory ) ); | |||
} | |||
public void setNodepackage( String nodePackage ) | |||
{ | |||
optionalAttrs.put( NODE_PACKAGE, new String( nodePackage ) ); | |||
} | |||
public void setNodeprefix( String nodePrefix ) | |||
{ | |||
optionalAttrs.put( NODE_PREFIX, new String( nodePrefix ) ); | |||
} | |||
public void setNodescopehook( boolean nodeScopeHook ) | |||
{ | |||
optionalAttrs.put( NODE_SCOPE_HOOK, new Boolean( nodeScopeHook ) ); | |||
} | |||
public void setNodeusesparser( boolean nodeUsesParser ) | |||
{ | |||
optionalAttrs.put( NODE_USES_PARSER, new Boolean( nodeUsesParser ) ); | |||
} | |||
public void setOutputdirectory( File outputDirectory ) | |||
{ | |||
this.outputDirectory = outputDirectory; | |||
} | |||
public void setStatic( boolean staticParser ) | |||
{ | |||
optionalAttrs.put( STATIC, new Boolean( staticParser ) ); | |||
} | |||
public void setTarget( File target ) | |||
{ | |||
this.target = target; | |||
} | |||
public void setVisitor( boolean visitor ) | |||
{ | |||
optionalAttrs.put( VISITOR, new Boolean( visitor ) ); | |||
} | |||
public void setVisitorException( String visitorException ) | |||
{ | |||
optionalAttrs.put( VISITOR_EXCEPTION, new String( visitorException ) ); | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
// load command line with optional attributes | |||
Enumeration iter = optionalAttrs.keys(); | |||
while( iter.hasMoreElements() ) | |||
{ | |||
String name = (String)iter.nextElement(); | |||
Object value = optionalAttrs.get( name ); | |||
cmdl.addArgument( "-" + name + ":" + value.toString() ); | |||
} | |||
if( target == null || !target.isFile() ) | |||
{ | |||
throw new TaskException( "Invalid target: " + target ); | |||
} | |||
// use the directory containing the target as the output directory | |||
if( outputDirectory == null ) | |||
{ | |||
outputDirectory = new File( target.getParent() ); | |||
} | |||
if( !outputDirectory.isDirectory() ) | |||
{ | |||
throw new TaskException( "'outputdirectory' " + outputDirectory + " is not a directory." ); | |||
} | |||
// convert backslashes to slashes, otherwise jjtree will put this as | |||
// comments and this seems to confuse javacc | |||
cmdl.addArgument( "-OUTPUT_DIRECTORY:" + outputDirectory.getAbsolutePath().replace( '\\', '/' ) ); | |||
String targetName = target.getName(); | |||
final File javaFile = new File( outputDirectory, | |||
targetName.substring( 0, targetName.indexOf( ".jjt" ) ) + ".jj" ); | |||
if( javaFile.exists() && target.lastModified() < javaFile.lastModified() ) | |||
{ | |||
getContext().info( "Target is already built - skipping (" + target + ")" ); | |||
return; | |||
} | |||
cmdl.addArgument( target.getAbsolutePath() ); | |||
if( javaccHome == null || !javaccHome.isDirectory() ) | |||
{ | |||
throw new TaskException( "Javacchome not set." ); | |||
} | |||
final Path classpath = cmdl.createClasspath(); | |||
classpath.addLocation( new File( javaccHome, "JavaCC.zip" ) ); | |||
PathUtil.addJavaRuntime( classpath ); | |||
cmdl.addVmArgument( "-mx140M" ); | |||
cmdl.addVmArgument( "-Dinstall.root=" + javaccHome.getAbsolutePath() ); | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
getContext().debug( cmdl.toString() ); | |||
exe.setCommandline( new Commandline( cmdl.getCommandline() ) ); | |||
exe.setReturnCode( 0 ); | |||
exe.execute(); | |||
} | |||
} |
@@ -1,290 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javacc; | |||
import java.io.File; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.CommandlineJava; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
/** | |||
* Taskdef for the JavaCC compiler compiler. | |||
* | |||
* @author thomas.haas@softwired-inc.com | |||
* @author Michael Saunders <a href="mailto:michael@amtec.com">michael@amtec.com | |||
* </a> | |||
*/ | |||
public class JavaCC | |||
extends AbstractTask | |||
{ | |||
// keys to optional attributes | |||
private final static String LOOKAHEAD = "LOOKAHEAD"; | |||
private final static String CHOICE_AMBIGUITY_CHECK = "CHOICE_AMBIGUITY_CHECK"; | |||
private final static String OTHER_AMBIGUITY_CHECK = "OTHER_AMBIGUITY_CHECK"; | |||
private final static String STATIC = "STATIC"; | |||
private final static String DEBUG_PARSER = "DEBUG_PARSER"; | |||
private final static String DEBUG_LOOKAHEAD = "DEBUG_LOOKAHEAD"; | |||
private final static String DEBUG_TOKEN_MANAGER = "DEBUG_TOKEN_MANAGER"; | |||
private final static String OPTIMIZE_TOKEN_MANAGER = "OPTIMIZE_TOKEN_MANAGER"; | |||
private final static String ERROR_REPORTING = "ERROR_REPORTING"; | |||
private final static String JAVA_UNICODE_ESCAPE = "JAVA_UNICODE_ESCAPE"; | |||
private final static String UNICODE_INPUT = "UNICODE_INPUT"; | |||
private final static String IGNORE_CASE = "IGNORE_CASE"; | |||
private final static String COMMON_TOKEN_ACTION = "COMMON_TOKEN_ACTION"; | |||
private final static String USER_TOKEN_MANAGER = "USER_TOKEN_MANAGER"; | |||
private final static String USER_CHAR_STREAM = "USER_CHAR_STREAM"; | |||
private final static String BUILD_PARSER = "BUILD_PARSER"; | |||
private final static String BUILD_TOKEN_MANAGER = "BUILD_TOKEN_MANAGER"; | |||
private final static String SANITY_CHECK = "SANITY_CHECK"; | |||
private final static String FORCE_LA_CHECK = "FORCE_LA_CHECK"; | |||
private final static String CACHE_TOKENS = "CACHE_TOKENS"; | |||
private final Hashtable optionalAttrs = new Hashtable(); | |||
// required attributes | |||
private File outputDirectory = null; | |||
private File target = null; | |||
private File javaccHome = null; | |||
private CommandlineJava cmdl = new CommandlineJava(); | |||
public JavaCC() | |||
{ | |||
cmdl.setVm( "java" ); | |||
cmdl.setClassname( "COM.sun.labs.javacc.Main" ); | |||
} | |||
public void setBuildparser( boolean buildParser ) | |||
{ | |||
optionalAttrs.put( BUILD_PARSER, new Boolean( buildParser ) ); | |||
} | |||
public void setBuildtokenmanager( boolean buildTokenManager ) | |||
{ | |||
optionalAttrs.put( BUILD_TOKEN_MANAGER, new Boolean( buildTokenManager ) ); | |||
} | |||
public void setCachetokens( boolean cacheTokens ) | |||
{ | |||
optionalAttrs.put( CACHE_TOKENS, new Boolean( cacheTokens ) ); | |||
} | |||
public void setChoiceambiguitycheck( int choiceAmbiguityCheck ) | |||
{ | |||
optionalAttrs.put( CHOICE_AMBIGUITY_CHECK, new Integer( choiceAmbiguityCheck ) ); | |||
} | |||
public void setCommontokenaction( boolean commonTokenAction ) | |||
{ | |||
optionalAttrs.put( COMMON_TOKEN_ACTION, new Boolean( commonTokenAction ) ); | |||
} | |||
public void setDebuglookahead( boolean debugLookahead ) | |||
{ | |||
optionalAttrs.put( DEBUG_LOOKAHEAD, new Boolean( debugLookahead ) ); | |||
} | |||
public void setDebugparser( boolean debugParser ) | |||
{ | |||
optionalAttrs.put( DEBUG_PARSER, new Boolean( debugParser ) ); | |||
} | |||
public void setDebugtokenmanager( boolean debugTokenManager ) | |||
{ | |||
optionalAttrs.put( DEBUG_TOKEN_MANAGER, new Boolean( debugTokenManager ) ); | |||
} | |||
public void setErrorreporting( boolean errorReporting ) | |||
{ | |||
optionalAttrs.put( ERROR_REPORTING, new Boolean( errorReporting ) ); | |||
} | |||
public void setForcelacheck( boolean forceLACheck ) | |||
{ | |||
optionalAttrs.put( FORCE_LA_CHECK, new Boolean( forceLACheck ) ); | |||
} | |||
public void setIgnorecase( boolean ignoreCase ) | |||
{ | |||
optionalAttrs.put( IGNORE_CASE, new Boolean( ignoreCase ) ); | |||
} | |||
public void setJavacchome( File javaccHome ) | |||
{ | |||
this.javaccHome = javaccHome; | |||
} | |||
public void setJavaunicodeescape( boolean javaUnicodeEscape ) | |||
{ | |||
optionalAttrs.put( JAVA_UNICODE_ESCAPE, new Boolean( javaUnicodeEscape ) ); | |||
} | |||
public void setLookahead( int lookahead ) | |||
{ | |||
optionalAttrs.put( LOOKAHEAD, new Integer( lookahead ) ); | |||
} | |||
public void setOptimizetokenmanager( boolean optimizeTokenManager ) | |||
{ | |||
optionalAttrs.put( OPTIMIZE_TOKEN_MANAGER, new Boolean( optimizeTokenManager ) ); | |||
} | |||
public void setOtherambiguityCheck( int otherAmbiguityCheck ) | |||
{ | |||
optionalAttrs.put( OTHER_AMBIGUITY_CHECK, new Integer( otherAmbiguityCheck ) ); | |||
} | |||
public void setOutputdirectory( File outputDirectory ) | |||
{ | |||
this.outputDirectory = outputDirectory; | |||
} | |||
public void setSanitycheck( boolean sanityCheck ) | |||
{ | |||
optionalAttrs.put( SANITY_CHECK, new Boolean( sanityCheck ) ); | |||
} | |||
public void setStatic( boolean staticParser ) | |||
{ | |||
optionalAttrs.put( STATIC, new Boolean( staticParser ) ); | |||
} | |||
public void setTarget( File target ) | |||
{ | |||
this.target = target; | |||
} | |||
public void setUnicodeinput( boolean unicodeInput ) | |||
{ | |||
optionalAttrs.put( UNICODE_INPUT, new Boolean( unicodeInput ) ); | |||
} | |||
public void setUsercharstream( boolean userCharStream ) | |||
{ | |||
optionalAttrs.put( USER_CHAR_STREAM, new Boolean( userCharStream ) ); | |||
} | |||
public void setUsertokenmanager( boolean userTokenManager ) | |||
{ | |||
optionalAttrs.put( USER_TOKEN_MANAGER, new Boolean( userTokenManager ) ); | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
// load command line with optional attributes | |||
Enumeration iter = optionalAttrs.keys(); | |||
while( iter.hasMoreElements() ) | |||
{ | |||
String name = (String)iter.nextElement(); | |||
Object value = optionalAttrs.get( name ); | |||
cmdl.addArgument( "-" + name + ":" + value.toString() ); | |||
} | |||
// check the target is a file | |||
if( target == null || !target.isFile() ) | |||
{ | |||
throw new TaskException( "Invalid target: " + target ); | |||
} | |||
// use the directory containing the target as the output directory | |||
if( outputDirectory == null ) | |||
{ | |||
outputDirectory = new File( target.getParent() ); | |||
} | |||
else if( !outputDirectory.isDirectory() ) | |||
{ | |||
throw new TaskException( "Outputdir not a directory." ); | |||
} | |||
cmdl.addArgument( "-OUTPUT_DIRECTORY:" + outputDirectory.getAbsolutePath() ); | |||
// determine if the generated java file is up-to-date | |||
final File javaFile = getOutputJavaFile( outputDirectory, target ); | |||
if( javaFile.exists() && target.lastModified() < javaFile.lastModified() ) | |||
{ | |||
getContext().debug( "Target is already built - skipping (" + target + ")" ); | |||
return; | |||
} | |||
cmdl.addArgument( target.getAbsolutePath() ); | |||
if( javaccHome == null || !javaccHome.isDirectory() ) | |||
{ | |||
throw new TaskException( "Javacchome not set." ); | |||
} | |||
final Path classpath = cmdl.createClasspath(); | |||
classpath.addLocation( new File( javaccHome, "JavaCC.zip" ) ); | |||
PathUtil.addJavaRuntime( classpath ); | |||
cmdl.addVmArgument( "-mx140M" ); | |||
cmdl.addVmArgument( "-Dinstall.root=" + javaccHome.getAbsolutePath() ); | |||
runCommand( cmdl ); | |||
} | |||
private void runCommand( final CommandlineJava cmdline ) | |||
throws TaskException | |||
{ | |||
getContext().debug( cmdline.toString() ); | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
final String[] commandline = cmdline.getCommandline(); | |||
exe.setCommandline( new Commandline( commandline ) ); | |||
exe.setReturnCode( 0 ); | |||
exe.execute(); | |||
} | |||
/** | |||
* Determines the output Java file to be generated by the given grammar | |||
* file. | |||
* | |||
* @param outputdir Description of Parameter | |||
* @param srcfile Description of Parameter | |||
* @return The OutputJavaFile value | |||
*/ | |||
private File getOutputJavaFile( File outputdir, File srcfile ) | |||
{ | |||
String path = srcfile.getPath(); | |||
// Extract file's base-name | |||
int startBasename = path.lastIndexOf( File.separator ); | |||
if( startBasename != -1 ) | |||
{ | |||
path = path.substring( startBasename + 1 ); | |||
} | |||
// Replace the file's extension with '.java' | |||
int startExtn = path.lastIndexOf( '.' ); | |||
if( startExtn != -1 ) | |||
{ | |||
path = path.substring( 0, startExtn ) + ".java"; | |||
} | |||
else | |||
{ | |||
path += ".java"; | |||
} | |||
// Change the directory | |||
if( outputdir != null ) | |||
{ | |||
path = outputdir + File.separator + path; | |||
} | |||
return new File( path ); | |||
} | |||
} |
@@ -1,21 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
public class AccessType | |||
extends EnumeratedAttribute | |||
{ | |||
public String[] getValues() | |||
{ | |||
// Protected first so if any GUI tool offers a default | |||
// based on enum #0, it will be right. | |||
return new String[]{"protected", "public", "package", "private"}; | |||
} | |||
} |
@@ -1,73 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.Path; | |||
public class DocletInfo | |||
{ | |||
private ArrayList m_params = new ArrayList(); | |||
private String m_name; | |||
private Path m_path; | |||
public void setName( final String name ) | |||
{ | |||
m_name = name; | |||
} | |||
public void setPath( final Path path ) | |||
throws TaskException | |||
{ | |||
if( m_path == null ) | |||
{ | |||
m_path = path; | |||
} | |||
else | |||
{ | |||
m_path.append( path ); | |||
} | |||
} | |||
public String getName() | |||
{ | |||
return m_name; | |||
} | |||
public Iterator getParams() | |||
{ | |||
return m_params.iterator(); | |||
} | |||
public Path getPath() | |||
{ | |||
return m_path; | |||
} | |||
public DocletParam createParam() | |||
{ | |||
final DocletParam param = new DocletParam(); | |||
m_params.add( param ); | |||
return param; | |||
} | |||
public Path createPath() | |||
throws TaskException | |||
{ | |||
if( m_path == null ) | |||
{ | |||
m_path = new Path(); | |||
} | |||
Path path1 = m_path; | |||
final Path path = new Path(); | |||
path1.addPath( path ); | |||
return path; | |||
} | |||
} |
@@ -1,34 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
public class DocletParam | |||
{ | |||
private String m_name; | |||
private String m_value; | |||
public void setName( final String name ) | |||
{ | |||
this.m_name = name; | |||
} | |||
public void setValue( final String value ) | |||
{ | |||
this.m_value = value; | |||
} | |||
public String getName() | |||
{ | |||
return m_name; | |||
} | |||
public String getValue() | |||
{ | |||
return m_value; | |||
} | |||
} |
@@ -1,65 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
import java.util.ArrayList; | |||
import java.util.StringTokenizer; | |||
public class GroupArgument | |||
{ | |||
private ArrayList m_packages = new ArrayList( 3 ); | |||
private Html m_title; | |||
public void setPackages( final String src ) | |||
{ | |||
final StringTokenizer tok = new StringTokenizer( src, "," ); | |||
while( tok.hasMoreTokens() ) | |||
{ | |||
final String p = tok.nextToken(); | |||
final PackageName pn = new PackageName(); | |||
pn.setName( p ); | |||
addPackage( pn ); | |||
} | |||
} | |||
public void setTitle( final String src ) | |||
{ | |||
final Html h = new Html(); | |||
h.addContent( src ); | |||
addTitle( h ); | |||
} | |||
public String getPackages() | |||
{ | |||
final StringBuffer p = new StringBuffer(); | |||
for( int i = 0; i < m_packages.size(); i++ ) | |||
{ | |||
if( i > 0 ) | |||
{ | |||
p.append( ":" ); | |||
} | |||
p.append( m_packages.get( i ).toString() ); | |||
} | |||
return p.toString(); | |||
} | |||
public String getTitle() | |||
{ | |||
return m_title != null ? m_title.getText() : null; | |||
} | |||
public void addPackage( final PackageName pn ) | |||
{ | |||
m_packages.add( pn ); | |||
} | |||
public void addTitle( final Html text ) | |||
{ | |||
m_title = text; | |||
} | |||
} |
@@ -1,23 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
public class Html | |||
{ | |||
private StringBuffer m_text = new StringBuffer(); | |||
public String getText() | |||
{ | |||
return m_text.toString(); | |||
} | |||
public void addContent( final String text ) | |||
{ | |||
m_text.append( text ); | |||
} | |||
} |
@@ -1,47 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
import java.io.File; | |||
public class LinkArgument | |||
{ | |||
private boolean m_offline; | |||
private String m_href; | |||
private File m_packagelistLoc; | |||
public void setHref( String hr ) | |||
{ | |||
m_href = hr; | |||
} | |||
public void setOffline( boolean offline ) | |||
{ | |||
this.m_offline = offline; | |||
} | |||
public void setPackagelistLoc( File src ) | |||
{ | |||
m_packagelistLoc = src; | |||
} | |||
public String getHref() | |||
{ | |||
return m_href; | |||
} | |||
public File getPackagelistLoc() | |||
{ | |||
return m_packagelistLoc; | |||
} | |||
public boolean isLinkOffline() | |||
{ | |||
return m_offline; | |||
} | |||
} |
@@ -1,28 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
public class PackageName | |||
{ | |||
private String m_name; | |||
public void setName( final String name ) | |||
{ | |||
m_name = name; | |||
} | |||
public String getName() | |||
{ | |||
return m_name; | |||
} | |||
public String toString() | |||
{ | |||
return getName(); | |||
} | |||
} |
@@ -1,25 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.javadoc; | |||
import java.io.File; | |||
public class SourceFile | |||
{ | |||
private File m_file; | |||
public void setFile( File file ) | |||
{ | |||
this.m_file = file; | |||
} | |||
public File getFile() | |||
{ | |||
return m_file; | |||
} | |||
} |
@@ -1,21 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jdepend; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
public class FormatAttribute | |||
extends EnumeratedAttribute | |||
{ | |||
private String[] m_formats = new String[]{"xml", "text"}; | |||
public String[] getValues() | |||
{ | |||
return m_formats; | |||
} | |||
} |
@@ -1,332 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jdepend; | |||
import java.io.File; | |||
import java.io.FileWriter; | |||
import java.io.IOException; | |||
import java.io.PrintWriter; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.CommandlineJava; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.util.FileUtils; | |||
/** | |||
* Ant task to run JDepend tests. <p> | |||
* | |||
* JDepend is a tool to generate design quality metrics for each Java package. | |||
* It has been initially created by Mike Clark. JDepend can be found at <a | |||
* href="http://www.clarkware.com/software/JDepend.html"> | |||
* http://www.clarkware.com/software/JDepend.html</a> . The current | |||
* implementation spawn a new Java VM. | |||
* | |||
* @author <a href="mailto:Jerome@jeromelacoste.com">Jerome Lacoste</a> | |||
* @author <a href="mailto:roxspring@yahoo.com">Rob Oxspring</a> | |||
*/ | |||
public class JDependTask | |||
extends AbstractTask | |||
{ | |||
/** | |||
* No problems with this test. | |||
*/ | |||
private final static int SUCCESS = 0; | |||
/** | |||
* An error occured. | |||
*/ | |||
private final static int ERRORS = 1; | |||
private boolean m_fork; | |||
private String m_jvm; | |||
private String m_format = "text"; | |||
private Path m_compileClasspath; | |||
private File m_dir; | |||
private File m_outputFile; | |||
private Path m_sourcesPath; | |||
/** | |||
* Set the classpath to be used for this compilation. | |||
*/ | |||
public void setClasspath( final Path classpath ) | |||
throws TaskException | |||
{ | |||
if( m_compileClasspath == null ) | |||
{ | |||
m_compileClasspath = classpath; | |||
} | |||
else | |||
{ | |||
m_compileClasspath.append( classpath ); | |||
} | |||
} | |||
/** | |||
* The directory to invoke the VM in. Ignored if no JVM is forked. | |||
* | |||
* @param dir the directory to invoke the JVM from. | |||
* @see #setFork(boolean) | |||
*/ | |||
public void setDir( final File dir ) | |||
{ | |||
m_dir = dir; | |||
} | |||
/** | |||
* Tells whether a JVM should be forked for the task. Default: false. | |||
* | |||
* @param value <tt>true</tt> if a JVM should be forked, otherwise <tt>false | |||
* <tt> | |||
*/ | |||
public void setFork( final boolean fork ) | |||
{ | |||
m_fork = fork; | |||
} | |||
public void setFormat( final FormatAttribute format ) | |||
{ | |||
m_format = format.getValue(); | |||
} | |||
/** | |||
* Set a new VM to execute the task. Default is <tt>java</tt> . Ignored if | |||
* no JVM is forked. | |||
* | |||
* @param value the new VM to use instead of <tt>java</tt> | |||
* @see #setFork(boolean) | |||
*/ | |||
public void setJvm( final String jvm ) | |||
{ | |||
m_jvm = jvm; | |||
} | |||
/* | |||
* public void setTimeout(Integer value) { | |||
* _timeout = value; | |||
* } | |||
* public Integer getTimeout() { | |||
* return _timeout; | |||
* } | |||
*/ | |||
public void setOutputFile( final File outputFile ) | |||
{ | |||
m_outputFile = outputFile; | |||
} | |||
/** | |||
* Maybe creates a nested classpath element. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public Path createClasspath() | |||
{ | |||
if( m_compileClasspath == null ) | |||
{ | |||
m_compileClasspath = new Path(); | |||
} | |||
Path path1 = m_compileClasspath; | |||
final Path path = new Path(); | |||
path1.addPath( path ); | |||
return path; | |||
} | |||
/** | |||
* Maybe creates a nested classpath element. | |||
*/ | |||
public Path createSourcespath() | |||
{ | |||
if( m_sourcesPath == null ) | |||
{ | |||
m_sourcesPath = new Path(); | |||
} | |||
Path path1 = m_sourcesPath; | |||
final Path path = new Path(); | |||
path1.addPath( path ); | |||
return path; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
final CommandlineJava commandline = new CommandlineJava(); | |||
if( "text".equals( m_format ) ) | |||
{ | |||
commandline.setClassname( "jdepend.textui.JDepend" ); | |||
} | |||
else if( "xml".equals( m_format ) ) | |||
{ | |||
commandline.setClassname( "jdepend.xmlui.JDepend" ); | |||
} | |||
if( m_jvm != null ) | |||
{ | |||
commandline.setVm( m_jvm ); | |||
} | |||
if( m_sourcesPath == null ) | |||
{ | |||
throw new TaskException( "Missing Sourcepath required argument" ); | |||
} | |||
// execute the test and get the return code | |||
int exitValue = JDependTask.ERRORS; | |||
if( !m_fork ) | |||
{ | |||
exitValue = executeInVM( commandline ); | |||
} | |||
else | |||
{ | |||
exitValue = executeAsForked( commandline ); | |||
} | |||
// if there is an error/failure and that it should halt, stop everything otherwise | |||
// just log a statement | |||
final boolean errorOccurred = exitValue == JDependTask.ERRORS; | |||
if( errorOccurred ) | |||
{ | |||
throw new TaskException( "JDepend failed" ); | |||
} | |||
} | |||
/** | |||
* Execute the task by forking a new JVM. The command will block until it | |||
* finishes. To know if the process was destroyed or not, use the <tt> | |||
* killedProcess()</tt> method of the watchdog class. | |||
*/ | |||
// JL: comment extracted from JUnitTask (and slightly modified) | |||
private int executeAsForked( final CommandlineJava commandline ) | |||
throws TaskException | |||
{ | |||
// if not set, auto-create the ClassPath from the project | |||
createClasspath(); | |||
// not sure whether this test is needed but cost nothing to put. | |||
// hope it will be reviewed by anybody competent | |||
if( m_compileClasspath.toString().length() > 0 ) | |||
{ | |||
commandline.addVmArgument( "-classpath" ); | |||
commandline.addVmArgument( m_compileClasspath.toString() ); | |||
} | |||
if( m_outputFile != null ) | |||
{ | |||
// having a space between the file and its path causes commandline to add quotes " | |||
// around the argument thus making JDepend not taking it into account. Thus we split it in two | |||
commandline.addArgument( "-file" ); | |||
commandline.addArgument( m_outputFile.getPath() ); | |||
// we have to find a cleaner way to put this output | |||
} | |||
final String[] elements = FileUtils.parsePath( m_sourcesPath.toString() ); | |||
for( int i = 0; i < elements.length; i++ ) | |||
{ | |||
File f = new File( elements[ i ] ); | |||
// not necessary as JDepend would fail, but why loose some time? | |||
if( !f.exists() || !f.isDirectory() ) | |||
{ | |||
throw new TaskException( "\"" + f.getPath() + "\" does not represent a valid directory. JDepend would fail." ); | |||
} | |||
commandline.addArgument( f.getPath() ); | |||
} | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
final String[] commandline1 = commandline.getCommandline(); | |||
exe.setCommandline( new Commandline( commandline1 ) ); | |||
if( m_dir != null ) | |||
{ | |||
exe.setWorkingDirectory( m_dir ); | |||
} | |||
if( m_outputFile != null ) | |||
{ | |||
getContext().info( "Output to be stored in " + m_outputFile.getPath() ); | |||
} | |||
getContext().debug( "Executing: " + commandline.toString() ); | |||
return exe.execute(); | |||
} | |||
// this comment extract from JUnit Task may also apply here | |||
// "in VM is not very nice since it could probably hang the | |||
// whole build. IMHO this method should be avoided and it would be best | |||
// to remove it in future versions. TBD. (SBa)" | |||
/** | |||
* Execute inside VM. | |||
* | |||
* @param commandline Description of Parameter | |||
* @return Description of the Returned Value | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public int executeInVM( final CommandlineJava commandline ) | |||
throws TaskException | |||
{ | |||
jdepend.textui.JDepend jdepend; | |||
if( "xml".equals( m_format ) ) | |||
{ | |||
jdepend = new jdepend.xmlui.JDepend(); | |||
} | |||
else | |||
{ | |||
jdepend = new jdepend.textui.JDepend(); | |||
} | |||
if( m_outputFile != null ) | |||
{ | |||
FileWriter fw; | |||
try | |||
{ | |||
fw = new FileWriter( m_outputFile.getPath() ); | |||
} | |||
catch( IOException e ) | |||
{ | |||
String msg = "JDepend Failed when creating the output file: " + e.getMessage(); | |||
getContext().info( msg ); | |||
throw new TaskException( msg ); | |||
} | |||
jdepend.setWriter( new PrintWriter( fw ) ); | |||
getContext().info( "Output to be stored in " + m_outputFile.getPath() ); | |||
} | |||
final String[] elements = FileUtils.parsePath( m_sourcesPath.toString() ); | |||
for( int i = 0; i < elements.length; i++ ) | |||
{ | |||
File f = new File( elements[ i ] ); | |||
// not necessary as JDepend would fail, but why loose some time? | |||
if( !f.exists() || !f.isDirectory() ) | |||
{ | |||
String msg = "\"" + f.getPath() + "\" does not represent a valid directory. JDepend would fail."; | |||
getContext().info( msg ); | |||
throw new TaskException( msg ); | |||
} | |||
try | |||
{ | |||
jdepend.addDirectory( f.getPath() ); | |||
} | |||
catch( IOException e ) | |||
{ | |||
String msg = "JDepend Failed when adding a source directory: " + e.getMessage(); | |||
getContext().info( msg ); | |||
throw new TaskException( msg ); | |||
} | |||
} | |||
jdepend.analyze(); | |||
return SUCCESS; | |||
} | |||
} |
@@ -1,486 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jsp; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.taskdefs.jsp.compilers.CompilerAdapter; | |||
import org.apache.tools.todo.taskdefs.jsp.compilers.CompilerAdapterFactory; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.Path; | |||
/** | |||
* Ant task to run the jsp compiler. <p> | |||
* | |||
* This task takes the given jsp files and compiles them into java files. It is | |||
* then up to the user to compile the java files into classes. <p> | |||
* | |||
* The task requires the srcdir and destdir attributes to be set. This Task is a | |||
* MatchingTask, so the files to be compiled can be specified using | |||
* includes/excludes attributes or nested include/exclude elements. Optional | |||
* attributes are verbose (set the verbosity level passed to jasper), package | |||
* (name of the destination package for generated java classes and classpath | |||
* (the classpath to use when running the jsp compiler). <p> | |||
* | |||
* This task supports the nested elements classpath (A Path) and classpathref (A | |||
* Reference) which can be used in preference to the attribute classpath, if the | |||
* jsp compiler is not already in the ant classpath. <p> | |||
* | |||
* <h4>Notes</h4> <p> | |||
* | |||
* At present, this task only supports the jasper compiler. In future, other | |||
* compilers will be supported by setting the jsp.compiler property. <p> | |||
* | |||
* <h4>Usage</h4> <pre> | |||
* <jspc srcdir="${basedir}/src/war" | |||
* destdir="${basedir}/gensrc" | |||
* package="com.i3sp.jsp" | |||
* verbose="9"> | |||
* <include name="**\/*.jsp" /> | |||
* </jspc> | |||
* </pre> | |||
* | |||
* @author <a href="mailto:mattw@i3sp.com">Matthew Watson</a> <p> | |||
* | |||
* Large Amount of cutting and pasting from the Javac task... | |||
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a> | |||
* @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com | |||
* </a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class JspC extends MatchingTask | |||
{ | |||
private final static String FAIL_MSG | |||
= "Compile failed, messages should have been provided."; | |||
private int verbose = 0; | |||
protected ArrayList compileList = new ArrayList(); | |||
protected boolean failOnError = true; | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
private Path classpath; | |||
private File destDir; | |||
private String iepluginid; | |||
private boolean mapped; | |||
private String packageName; | |||
private Path src; | |||
/** | |||
* -uribase <dir>The uri directory compilations should be relative to | |||
* (Default is "/") | |||
*/ | |||
private File uribase; | |||
/** | |||
* -uriroot <dir>The root directory that uri files should be resolved | |||
* against, | |||
*/ | |||
private File uriroot; | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Set the classpath to be used for this compilation | |||
* | |||
* @param cp The new Classpath value | |||
*/ | |||
public void setClasspath( Path cp ) | |||
throws TaskException | |||
{ | |||
if( classpath == null ) | |||
{ | |||
classpath = cp; | |||
} | |||
else | |||
{ | |||
classpath.append( cp ); | |||
} | |||
} | |||
/** | |||
* Set the destination directory into which the JSP source files should be | |||
* compiled. | |||
* | |||
* @param destDir The new Destdir value | |||
*/ | |||
public void setDestdir( File destDir ) | |||
{ | |||
this.destDir = destDir; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Throw a TaskException if compilation fails | |||
* | |||
* @param fail The new Failonerror value | |||
*/ | |||
public void setFailonerror( boolean fail ) | |||
{ | |||
failOnError = fail; | |||
} | |||
/** | |||
* Set the ieplugin id | |||
* | |||
* @param iepluginid_ The new Ieplugin value | |||
*/ | |||
public void setIeplugin( String iepluginid_ ) | |||
{ | |||
iepluginid = iepluginid_; | |||
} | |||
/** | |||
* set the mapped flag | |||
* | |||
* @param mapped_ The new Mapped value | |||
*/ | |||
public void setMapped( boolean mapped_ ) | |||
{ | |||
mapped = mapped_; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Set the name of the package the compiled jsp files should be in | |||
* | |||
* @param pkg The new Package value | |||
*/ | |||
public void setPackage( String pkg ) | |||
{ | |||
this.packageName = pkg; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Set the source dirs to find the source JSP files. | |||
* | |||
* @param srcDir The new Srcdir value | |||
*/ | |||
public void setSrcdir( Path srcDir ) | |||
throws TaskException | |||
{ | |||
if( src == null ) | |||
{ | |||
src = srcDir; | |||
} | |||
else | |||
{ | |||
src.append( srcDir ); | |||
} | |||
} | |||
/** | |||
* -uribase. the uri context of relative URI references in the JSP pages. If | |||
* it does not exist then it is derived from the location of the file | |||
* relative to the declared or derived value of -uriroot. | |||
* | |||
* @param uribase The new Uribase value | |||
*/ | |||
public void setUribase( File uribase ) | |||
{ | |||
this.uribase = uribase; | |||
} | |||
/** | |||
* -uriroot <dir>The root directory that uri files should be resolved | |||
* against, (Default is the directory jspc is invoked from) | |||
* | |||
* @param uriroot The new Uribase value | |||
*/ | |||
public void setUriroot( File uriroot ) | |||
{ | |||
this.uriroot = uriroot; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Set the verbose level of the compiler | |||
* | |||
* @param i The new Verbose value | |||
*/ | |||
public void setVerbose( int i ) | |||
{ | |||
verbose = i; | |||
} | |||
public Path getClasspath() | |||
{ | |||
return classpath; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
public ArrayList getCompileList() | |||
{ | |||
return compileList; | |||
} | |||
public File getDestdir() | |||
{ | |||
return destDir; | |||
} | |||
/** | |||
* Gets the failonerror flag. | |||
* | |||
* @return The Failonerror value | |||
*/ | |||
public boolean getFailonerror() | |||
{ | |||
return failOnError; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
public String getIeplugin() | |||
{ | |||
return iepluginid; | |||
} | |||
public String getPackage() | |||
{ | |||
return packageName; | |||
} | |||
public Path getSrcDir() | |||
{ | |||
return src; | |||
} | |||
public File getUribase() | |||
{ | |||
return uriroot; | |||
} | |||
public File getUriroot() | |||
{ | |||
return uriroot; | |||
} | |||
public int getVerbose() | |||
{ | |||
return verbose; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
public boolean isMapped() | |||
{ | |||
return mapped; | |||
} | |||
/** | |||
* Maybe creates a nested classpath element. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public Path createClasspath() | |||
throws TaskException | |||
{ | |||
if( classpath == null ) | |||
{ | |||
classpath = new Path(); | |||
} | |||
Path path1 = classpath; | |||
final Path path = new Path(); | |||
path1.addPath( path ); | |||
return path; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
// first off, make sure that we've got a srcdir | |||
if( src == null ) | |||
{ | |||
throw new TaskException( "srcdir attribute must be set!" ); | |||
} | |||
String[] list = src.list(); | |||
if( list.length == 0 ) | |||
{ | |||
throw new TaskException( "srcdir attribute must be set!" ); | |||
} | |||
if( destDir != null && !destDir.isDirectory() ) | |||
{ | |||
throw new | |||
TaskException( "destination directory \"" + destDir + | |||
"\" does not exist or is not a directory" ); | |||
} | |||
// calculate where the files will end up: | |||
File dest = null; | |||
if( packageName == null ) | |||
{ | |||
dest = destDir; | |||
} | |||
else | |||
{ | |||
String path = destDir.getPath() + File.separatorChar + | |||
packageName.replace( '.', File.separatorChar ); | |||
dest = new File( path ); | |||
} | |||
// scan source directories and dest directory to build up both copy | |||
// lists and compile lists | |||
resetFileLists(); | |||
int filecount = 0; | |||
for( int i = 0; i < list.length; i++ ) | |||
{ | |||
final String filename = list[ i ]; | |||
File srcDir = (File)getContext().resolveFile( filename ); | |||
if( !srcDir.exists() ) | |||
{ | |||
throw new TaskException( "srcdir \"" + srcDir.getPath() + | |||
"\" does not exist!" ); | |||
} | |||
DirectoryScanner ds = this.getDirectoryScanner( srcDir ); | |||
String[] files = ds.getIncludedFiles(); | |||
filecount = files.length; | |||
scanDir( srcDir, dest, files ); | |||
} | |||
// compile the source files | |||
Object compiler = getContext().getProperty( "jsp.compiler" ); | |||
if( compiler == null ) | |||
{ | |||
compiler = "jasper"; | |||
} | |||
getContext().debug( "compiling " + compileList.size() + " files" ); | |||
if( compileList.size() > 0 ) | |||
{ | |||
CompilerAdapter adapter = | |||
CompilerAdapterFactory.getCompiler( compiler.toString(), getContext() ); | |||
getContext().info( "Compiling " + compileList.size() + | |||
" source file" | |||
+ ( compileList.size() == 1 ? "" : "s" ) | |||
+ ( destDir != null ? " to " + destDir : "" ) ); | |||
// now we need to populate the compiler adapter | |||
adapter.setJspc( this ); | |||
// finally, lets execute the compiler!! | |||
if( !adapter.execute() ) | |||
{ | |||
if( failOnError ) | |||
{ | |||
throw new TaskException( FAIL_MSG ); | |||
} | |||
else | |||
{ | |||
getContext().error( FAIL_MSG ); | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
if( filecount == 0 ) | |||
{ | |||
getContext().info( "there were no files to compile" ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "all files are up to date" ); | |||
} | |||
} | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Clear the list of files to be compiled and copied.. | |||
*/ | |||
protected void resetFileLists() | |||
{ | |||
compileList.clear(); | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Scans the directory looking for source files to be compiled. The results | |||
* are returned in the class variable compileList | |||
* | |||
* @param srcDir Description of Parameter | |||
* @param destDir Description of Parameter | |||
* @param files Description of Parameter | |||
*/ | |||
protected void scanDir( File srcDir, File destDir, String files[] ) | |||
{ | |||
long now = ( new Date() ).getTime(); | |||
for( int i = 0; i < files.length; i++ ) | |||
{ | |||
File srcFile = new File( srcDir, files[ i ] ); | |||
if( files[ i ].endsWith( ".jsp" ) ) | |||
{ | |||
// drop leading path (if any) | |||
int fileStart = | |||
files[ i ].lastIndexOf( File.separatorChar ) + 1; | |||
File javaFile = new File( destDir, files[ i ].substring( fileStart, | |||
files[ i ].indexOf( ".jsp" ) ) + ".java" ); | |||
if( srcFile.lastModified() > now ) | |||
{ | |||
final String message = | |||
"Warning: file modified in the future: " + files[ i ]; | |||
getContext().warn( message ); | |||
} | |||
if( !javaFile.exists() || | |||
srcFile.lastModified() > javaFile.lastModified() ) | |||
{ | |||
if( !javaFile.exists() ) | |||
{ | |||
getContext().debug( "Compiling " + srcFile.getPath() + " because java file " + javaFile.getPath() + " does not exist" ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "Compiling " + srcFile.getPath() + " because it is out of date with respect to " + javaFile.getPath() ); | |||
} | |||
compileList.add( srcFile.getAbsolutePath() ); | |||
} | |||
} | |||
} | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
} |
@@ -1,308 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jsp;//java imports | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.StringTokenizer; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.taskdefs.Java; | |||
import org.apache.tools.todo.taskdefs.MatchingTask; | |||
import org.apache.tools.todo.types.Argument; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.Path; | |||
/** | |||
* Class to precompile JSP's using weblogic's jsp compiler (weblogic.jspc) | |||
* | |||
* @author <a href="mailto:avik@aviksengupta.com">Avik Sengupta</a> | |||
* http://www.webteksoftware.com Tested only on Weblogic 4.5.1 - NT4.0 and | |||
* Solaris 5.7 required attributes src : root of source tree for JSP, ie, | |||
* the document root for your weblogic server dest : root of destination | |||
* directory, what you have set as WorkingDir in the weblogic properties | |||
* package : start package name under which your JSP's would be compiled | |||
* other attributes classpath A classpath should be set which contains the | |||
* weblogic classes as well as all application classes referenced by the | |||
* JSP. The system classpath is also appended when the jspc is called, so | |||
* you may choose to put everything in the classpath while calling Ant. | |||
* However, since presumably the JSP's will reference classes being build | |||
* by Ant, it would be better to explicitly add the classpath in the task | |||
* The task checks timestamps on the JSP's and the generated classes, and | |||
* compiles only those files that have changed. It follows the weblogic | |||
* naming convention of putting classes in <b> _dirName/_fileName.class for | |||
* dirname/fileName.jsp </b> Limitation: It compiles the files thru the | |||
* Classic compiler only. Limitation: Since it is my experience that | |||
* weblogic jspc throws out of memory error on being given too many files | |||
* at one go, it is called multiple times with one jsp file each. <pre> | |||
* example | |||
* <target name="jspcompile" depends="compile"> | |||
* <wljspc src="c:\\weblogic\\myserver\\public_html" dest="c:\\weblogic\\myserver\\serverclasses" package="myapp.jsp"> | |||
* <classpath> | |||
* <pathelement location="${weblogic.classpath}" /> | |||
* <pathelement path="${compile.dest}" /> | |||
* </classpath> | |||
* | |||
* </wljspc> | |||
* </target> | |||
* </pre> | |||
*/ | |||
public class WLJspc extends MatchingTask | |||
{//classpath used to compile the jsp files. | |||
//private String compilerPath; //fully qualified name for the compiler executable | |||
private String pathToPackage = ""; | |||
private ArrayList filesToDo = new ArrayList();//package under which resultant classes will reside | |||
private Path compileClasspath; | |||
//TODO Test on other versions of weblogic | |||
//TODO add more attributes to the task, to take care of all jspc options | |||
//TODO Test on Unix | |||
private File destinationDirectory;// root of source files tree | |||
private String destinationPackage;//root of compiled files tree | |||
private File sourceDirectory; | |||
/** | |||
* Set the classpath to be used for this compilation. | |||
* | |||
* @param classpath The new Classpath value | |||
*/ | |||
public void setClasspath( Path classpath ) | |||
throws TaskException | |||
{ | |||
if( compileClasspath == null ) | |||
{ | |||
compileClasspath = classpath; | |||
} | |||
else | |||
{ | |||
compileClasspath.append( classpath ); | |||
} | |||
} | |||
/** | |||
* Set the directory containing the source jsp's | |||
* | |||
* @param dirName the directory containg the source jsp's | |||
*/ | |||
public void setDest( File dirName ) | |||
{ | |||
destinationDirectory = dirName; | |||
} | |||
/** | |||
* Set the package under which the compiled classes go | |||
* | |||
* @param packageName the package name for the clases | |||
*/ | |||
public void setPackage( String packageName ) | |||
{ | |||
destinationPackage = packageName; | |||
} | |||
/** | |||
* Set the directory containing the source jsp's | |||
* | |||
* @param dirName the directory containg the source jsp's | |||
*/ | |||
public void setSrc( File dirName ) | |||
{ | |||
sourceDirectory = dirName; | |||
} | |||
/** | |||
* Maybe creates a nested classpath element. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public Path createClasspath() | |||
{ | |||
if( compileClasspath == null ) | |||
{ | |||
compileClasspath = new Path(); | |||
} | |||
return compileClasspath; | |||
} | |||
public void execute() | |||
throws TaskException | |||
{ | |||
if( !destinationDirectory.isDirectory() ) | |||
{ | |||
throw new TaskException( "destination directory " + destinationDirectory.getPath() + | |||
" is not valid" ); | |||
} | |||
if( !sourceDirectory.isDirectory() ) | |||
{ | |||
throw new TaskException( "src directory " + sourceDirectory.getPath() + | |||
" is not valid" ); | |||
} | |||
if( destinationPackage == null ) | |||
{ | |||
throw new TaskException( "package attribute must be present." ); | |||
} | |||
pathToPackage = this.destinationPackage.replace( '.', File.separatorChar ); | |||
// get all the files in the sourceDirectory | |||
DirectoryScanner ds = super.getDirectoryScanner( sourceDirectory ); | |||
//use the systemclasspath as well, to include the ant jar | |||
if( compileClasspath == null ) | |||
{ | |||
compileClasspath = new Path(); | |||
} | |||
// TODO - make sure tools.jar ends up in the classpath | |||
//compileClasspath.append( Path.systemClasspath ); | |||
String[] files = ds.getIncludedFiles(); | |||
//Weblogic.jspc calls System.exit() ... have to fork | |||
// Therefore, takes loads of time | |||
// Can pass directories at a time (*.jsp) but easily runs out of memory on hefty dirs | |||
// (even on a Sun) | |||
Java helperTask = null;//(Java)getProject().createTask( "java" ); | |||
helperTask.setFork( true ); | |||
helperTask.setClassname( "weblogic.jspc" ); | |||
String[] args = new String[ 12 ]; | |||
File jspFile = null; | |||
String parents = ""; | |||
String arg = ""; | |||
int j = 0; | |||
//XXX this array stuff is a remnant of prev trials.. gotta remove. | |||
args[ j++ ] = "-d"; | |||
args[ j++ ] = destinationDirectory.getAbsolutePath().trim(); | |||
args[ j++ ] = "-docroot"; | |||
args[ j++ ] = sourceDirectory.getAbsolutePath().trim(); | |||
args[ j++ ] = "-keepgenerated";//TODO: Parameterise ?? | |||
//Call compiler as class... dont want to fork again | |||
//Use classic compiler -- can be parameterised? | |||
args[ j++ ] = "-compilerclass"; | |||
args[ j++ ] = "sun.tools.javac.Main"; | |||
//Weblogic jspc does not seem to work unless u explicitly set this... | |||
// Does not take the classpath from the env.... | |||
// Am i missing something about the Java task?? | |||
args[ j++ ] = "-classpath"; | |||
args[ j++ ] = compileClasspath.toString(); | |||
this.scanDir( files ); | |||
getContext().info( "Compiling " + filesToDo.size() + " JSP files" ); | |||
for( int i = 0; i < filesToDo.size(); i++ ) | |||
{ | |||
//XXX | |||
// All this to get package according to weblogic standards | |||
// Can be written better... this is too hacky! | |||
// Careful.. similar code in scanDir , but slightly different!! | |||
jspFile = new File( (String)filesToDo.get( i ) ); | |||
args[ j ] = "-package"; | |||
parents = jspFile.getParent(); | |||
if( ( parents != null ) && ( !( "" ).equals( parents ) ) ) | |||
{ | |||
parents = this.replaceString( parents, File.separator, "_." ); | |||
args[ j + 1 ] = destinationPackage + "." + "_" + parents; | |||
} | |||
else | |||
{ | |||
args[ j + 1 ] = destinationPackage; | |||
} | |||
args[ j + 2 ] = sourceDirectory + File.separator + (String)filesToDo.get( i ); | |||
arg = ""; | |||
for( int x = 0; x < 12; x++ ) | |||
{ | |||
arg += " " + args[ x ]; | |||
} | |||
System.out.println( "arg = " + arg ); | |||
//helperTask.clearArgs(); | |||
helperTask.addArg( new Argument( arg ) ); | |||
helperTask.addClasspath( compileClasspath ); | |||
if( helperTask.executeJava() != 0 ) | |||
{ | |||
getContext().warn( files[ i ] + " failed to compile" ); | |||
} | |||
} | |||
} | |||
protected String replaceString( String inpString, String escapeChars, String replaceChars ) | |||
{ | |||
String localString = ""; | |||
int numTokens = 0; | |||
StringTokenizer st = new StringTokenizer( inpString, escapeChars, true ); | |||
numTokens = st.countTokens(); | |||
for( int i = 0; i < numTokens; i++ ) | |||
{ | |||
String test = st.nextToken(); | |||
test = ( test.equals( escapeChars ) ? replaceChars : test ); | |||
localString += test; | |||
} | |||
return localString; | |||
} | |||
protected void scanDir( String files[] ) | |||
{ | |||
long now = ( new Date() ).getTime(); | |||
File jspFile = null; | |||
String parents = null; | |||
String pack = ""; | |||
for( int i = 0; i < files.length; i++ ) | |||
{ | |||
File srcFile = new File( this.sourceDirectory, files[ i ] ); | |||
//XXX | |||
// All this to convert source to destination directory according to weblogic standards | |||
// Can be written better... this is too hacky! | |||
jspFile = new File( files[ i ] ); | |||
parents = jspFile.getParent(); | |||
if( ( parents != null ) && ( !( "" ).equals( parents ) ) ) | |||
{ | |||
parents = this.replaceString( parents, File.separator, "_/" ); | |||
pack = pathToPackage + File.separator + "_" + parents; | |||
} | |||
else | |||
{ | |||
pack = pathToPackage; | |||
} | |||
String filePath = pack + File.separator + "_"; | |||
int startingIndex | |||
= files[ i ].lastIndexOf( File.separator ) != -1 ? files[ i ].lastIndexOf( File.separator ) + 1 : 0; | |||
int endingIndex = files[ i ].indexOf( ".jsp" ); | |||
if( endingIndex == -1 ) | |||
{ | |||
break; | |||
} | |||
filePath += files[ i ].substring( startingIndex, endingIndex ); | |||
filePath += ".class"; | |||
File classFile = new File( this.destinationDirectory, filePath ); | |||
if( srcFile.lastModified() > now ) | |||
{ | |||
final String message = "Warning: file modified in the future: " + files[ i ]; | |||
getContext().warn( message ); | |||
} | |||
if( srcFile.lastModified() > classFile.lastModified() ) | |||
{ | |||
//log("Files are" + srcFile.getAbsolutePath()+" " +classFile.getAbsolutePath()); | |||
filesToDo.add( files[ i ] ); | |||
getContext().debug( "Recompiling File " + files[ i ] ); | |||
} | |||
} | |||
} | |||
} |
@@ -1,46 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jsp.compilers; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.jsp.JspC; | |||
/** | |||
* The interface that all jsp compiler adapters must adher to. <p> | |||
* | |||
* A compiler adapter is an adapter that interprets the jspc's parameters in | |||
* preperation to be passed off to the compier this adapter represents. As all | |||
* the necessary values are stored in the Jspc task itself, the only thing all | |||
* adapters need is the jsp task, the execute command and a parameterless | |||
* constructor (for reflection).</p> | |||
* | |||
* @author Jay Dickon Glanville <a href="mailto:jayglanville@home.com"> | |||
* jayglanville@home.com</a> | |||
* @author Matthew Watson <a href="mailto:mattw@i3sp.com">mattw@i3sp.com</a> | |||
*/ | |||
public interface CompilerAdapter | |||
{ | |||
void setTaskContext( TaskContext context ); | |||
/** | |||
* Sets the compiler attributes, which are stored in the Jspc task. | |||
* | |||
* @param attributes The new Jspc value | |||
*/ | |||
void setJspc( JspC attributes ); | |||
/** | |||
* Executes the task. | |||
* | |||
* @return has the compilation been successful | |||
* @exception TaskException Description of Exception | |||
*/ | |||
boolean execute() | |||
throws TaskException; | |||
} |
@@ -1,103 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jsp.compilers; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
/** | |||
* Creates the necessary compiler adapter, given basic criteria. | |||
* | |||
* @author <a href="mailto:jayglanville@home.com">J D Glanville</a> | |||
* @author Matthew Watson <a href="mailto:mattw@i3sp.com">mattw@i3sp.com</a> | |||
*/ | |||
public class CompilerAdapterFactory | |||
{ | |||
/** | |||
* This is a singlton -- can't create instances!! | |||
*/ | |||
private CompilerAdapterFactory() | |||
{ | |||
} | |||
/** | |||
* Based on the parameter passed in, this method creates the necessary | |||
* factory desired. The current mapping for compiler names are as follows: | |||
* | |||
* <ul> | |||
* <li> jasper = jasper compiler (the default) | |||
* <li> <i>a fully quallified classname</i> = the name of a jsp compiler | |||
* adapter | |||
* </ul> | |||
* | |||
* | |||
* @param compilerType either the name of the desired compiler, or the full | |||
* classname of the compiler's adapter. | |||
* @return The Compiler value | |||
* @throws TaskException if the compiler type could not be resolved into a | |||
* compiler adapter. | |||
*/ | |||
public static CompilerAdapter getCompiler( String compilerType, TaskContext context ) | |||
throws TaskException | |||
{ | |||
final CompilerAdapter adapter = createAdapter( compilerType ); | |||
adapter.setTaskContext( context ); | |||
return adapter; | |||
} | |||
private static CompilerAdapter createAdapter( String compilerType ) | |||
throws TaskException | |||
{ | |||
/* | |||
* If I've done things right, this should be the extent of the | |||
* conditional statements required. | |||
*/ | |||
if( compilerType.equalsIgnoreCase( "jasper" ) ) | |||
{ | |||
return new JasperC(); | |||
} | |||
return resolveClassName( compilerType ); | |||
} | |||
/** | |||
* Tries to resolve the given classname into a compiler adapter. Throws a | |||
* fit if it can't. | |||
* | |||
* @param className The fully qualified classname to be created. | |||
* @return Description of the Returned Value | |||
* @throws TaskException This is the fit that is thrown if className isn't | |||
* an instance of CompilerAdapter. | |||
*/ | |||
private static CompilerAdapter resolveClassName( String className ) | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
Class c = Class.forName( className ); | |||
Object o = c.newInstance(); | |||
return (CompilerAdapter)o; | |||
} | |||
catch( ClassNotFoundException cnfe ) | |||
{ | |||
throw new TaskException( className + " can\'t be found.", cnfe ); | |||
} | |||
catch( ClassCastException cce ) | |||
{ | |||
throw new TaskException( className + " isn\'t the classname of " | |||
+ "a compiler adapter.", cce ); | |||
} | |||
catch( Throwable t ) | |||
{ | |||
// for all other possibilities | |||
throw new TaskException( className + " caused an interesting " | |||
+ "exception.", t ); | |||
} | |||
} | |||
} |
@@ -1,86 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jsp.compilers; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.jsp.JspC; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* This is the default implementation for the CompilerAdapter interface. This is | |||
* currently very light on the ground since only one compiler type is supported. | |||
* | |||
* @author Matthew Watson <a href="mailto:mattw@i3sp.com">mattw@i3sp.com</a> | |||
*/ | |||
public abstract class DefaultCompilerAdapter | |||
implements CompilerAdapter | |||
{ | |||
private JspC m_attributes; | |||
private TaskContext m_taskContext; | |||
public void setTaskContext( final TaskContext context ) | |||
{ | |||
m_taskContext = context; | |||
} | |||
protected final TaskContext getTaskContext() | |||
{ | |||
return m_taskContext; | |||
} | |||
public void setJspc( final JspC attributes ) | |||
{ | |||
this.m_attributes = attributes; | |||
} | |||
public JspC getJspc() | |||
{ | |||
return m_attributes; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
/** | |||
* Logs the compilation parameters, adds the files to compile and logs the | |||
* &qout;niceSourceList" | |||
* | |||
* @param jspc Description of Parameter | |||
* @param compileList Description of Parameter | |||
* @param cmd Description of Parameter | |||
*/ | |||
protected void logAndAddFilesToCompile( JspC jspc, | |||
ArrayList compileList, | |||
Commandline cmd ) | |||
{ | |||
getTaskContext().debug( "Compilation args: " + cmd.toString() ); | |||
StringBuffer niceSourceList = new StringBuffer( "File" ); | |||
if( compileList.size() != 1 ) | |||
{ | |||
niceSourceList.append( "s" ); | |||
} | |||
niceSourceList.append( " to be compiled:" ); | |||
niceSourceList.append( StringUtil.LINE_SEPARATOR ); | |||
Iterator enum = compileList.iterator(); | |||
while( enum.hasNext() ) | |||
{ | |||
String arg = (String)enum.next(); | |||
cmd.addArgument( arg ); | |||
niceSourceList.append( " " + arg + StringUtil.LINE_SEPARATOR ); | |||
} | |||
getTaskContext().debug( niceSourceList.toString() ); | |||
} | |||
} | |||
@@ -1,114 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.jsp.compilers; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.tools.todo.taskdefs.Java; | |||
import org.apache.tools.todo.taskdefs.jsp.JspC; | |||
import org.apache.tools.todo.types.Argument; | |||
import org.apache.tools.todo.types.Commandline; | |||
/** | |||
* The implementation of the jasper compiler. This is a cut-and-paste of the | |||
* original Jspc task. | |||
* | |||
* @author Matthew Watson <a href="mailto:mattw@i3sp.com">mattw@i3sp.com</a> | |||
*/ | |||
public class JasperC | |||
extends DefaultCompilerAdapter | |||
{ | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
public boolean execute() | |||
throws TaskException | |||
{ | |||
getTaskContext().debug( "Using jasper compiler" ); | |||
Commandline cmd = setupJasperCommand(); | |||
try | |||
{ | |||
// Create an instance of the compiler, redirecting output to | |||
// the project log | |||
//FIXME | |||
Java java = null;//(Java)( getJspc().getProject() ).createTask( "java" ); | |||
if( getJspc().getClasspath() != null ) | |||
{ | |||
java.addClasspath( getJspc().getClasspath() ); | |||
} | |||
java.setClassname( "org.apache.jasper.JspC" ); | |||
String args[] = cmd.getArguments(); | |||
for( int i = 0; i < args.length; i++ ) | |||
{ | |||
java.addArg( new Argument( args[ i ] ) ); | |||
} | |||
java.execute(); | |||
return true; | |||
} | |||
catch( Exception ex ) | |||
{ | |||
if( ex instanceof TaskException ) | |||
{ | |||
throw (TaskException)ex; | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Error running jsp compiler: ", | |||
ex ); | |||
} | |||
} | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
private Commandline setupJasperCommand() | |||
{ | |||
Commandline cmd = new Commandline(); | |||
JspC jspc = getJspc(); | |||
if( jspc.getDestdir() != null ) | |||
{ | |||
cmd.addArgument( "-d" ); | |||
cmd.addArgument( jspc.getDestdir() ); | |||
} | |||
if( jspc.getPackage() != null ) | |||
{ | |||
cmd.addArgument( "-p" ); | |||
cmd.addArgument( jspc.getPackage() ); | |||
} | |||
if( jspc.getVerbose() != 0 ) | |||
{ | |||
cmd.addArgument( "-v" + jspc.getVerbose() ); | |||
} | |||
if( jspc.isMapped() ) | |||
{ | |||
cmd.addArgument( "-mapped" ); | |||
} | |||
if( jspc.getIeplugin() != null ) | |||
{ | |||
cmd.addArgument( "-ieplugin" ); | |||
cmd.addArgument( jspc.getIeplugin() ); | |||
} | |||
if( jspc.getUriroot() != null ) | |||
{ | |||
cmd.addArgument( "-uriroot" ); | |||
cmd.addArgument( jspc.getUriroot().toString() ); | |||
} | |||
if( jspc.getUribase() != null ) | |||
{ | |||
cmd.addArgument( "-uribase" ); | |||
cmd.addArgument( jspc.getUribase().toString() ); | |||
} | |||
logAndAddFilesToCompile( getJspc(), getJspc().getCompileList(), cmd ); | |||
return cmd; | |||
} | |||
/* | |||
* ------------------------------------------------------------ | |||
*/ | |||
} |
@@ -1,230 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileNotFoundException; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.URL; | |||
import javax.xml.parsers.DocumentBuilder; | |||
import javax.xml.parsers.DocumentBuilderFactory; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
import org.w3c.dom.Document; | |||
/** | |||
* Transform a JUnit xml report. The default transformation generates an html | |||
* report in either framed or non-framed style. The non-framed style is | |||
* convenient to have a concise report via mail, the framed report is much more | |||
* convenient if you want to browse into different packages or testcases since | |||
* it is a Javadoc like report. | |||
* | |||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||
*/ | |||
public class AggregateTransformer | |||
{ | |||
public final static String FRAMES = "frames"; | |||
public final static String NOFRAMES = "noframes"; | |||
/** | |||
* XML Parser factory | |||
*/ | |||
private final static DocumentBuilderFactory c_dbfactory = DocumentBuilderFactory.newInstance(); | |||
/** | |||
* the xml document to process | |||
*/ | |||
private Document m_document; | |||
/** | |||
* the format to use for the report. Must be <tt>FRAMES</tt> or <tt>NOFRAMES | |||
* </tt> | |||
*/ | |||
private String m_format; | |||
/** | |||
* the style directory. XSLs should be read from here if necessary | |||
*/ | |||
private File m_styleDir; | |||
private AbstractTask m_task; | |||
/** | |||
* the destination directory, this is the root from where html should be | |||
* generated | |||
*/ | |||
private File m_toDir; | |||
public AggregateTransformer( AbstractTask task ) | |||
{ | |||
m_task = task; | |||
} | |||
public void setFormat( Format format ) | |||
{ | |||
m_format = format.getValue(); | |||
} | |||
/** | |||
* set the style directory. It is optional and will override the default xsl | |||
* used. | |||
* | |||
* @param styledir the directory containing the xsl files if the user would | |||
* like to override with its own style. | |||
*/ | |||
public void setStyledir( File styledir ) | |||
{ | |||
m_styleDir = styledir; | |||
} | |||
/** | |||
* set the destination directory | |||
* | |||
* @param todir The new Todir value | |||
*/ | |||
public void setTodir( File todir ) | |||
{ | |||
m_toDir = todir; | |||
} | |||
public void setXmlDocument( Document doc ) | |||
{ | |||
m_document = doc; | |||
} | |||
public void transform() | |||
throws TaskException | |||
{ | |||
checkOptions(); | |||
try | |||
{ | |||
XalanExecutor executor = XalanExecutor.newInstance( this ); | |||
executor.execute(); | |||
} | |||
catch( Exception e ) | |||
{ | |||
throw new TaskException( "Errors while applying transformations", e ); | |||
} | |||
//task.getLogger().info( "Transform time: " + dt + "ms" ); | |||
} | |||
/** | |||
* Set the xml file to be processed. This is a helper if you want to set the | |||
* file directly. Much more for testing purposes. | |||
* | |||
* @param xmlfile xml file to be processed | |||
* @exception TaskException Description of Exception | |||
*/ | |||
protected void setXmlfile( File xmlfile ) | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
DocumentBuilder builder = c_dbfactory.newDocumentBuilder(); | |||
InputStream in = new FileInputStream( xmlfile ); | |||
try | |||
{ | |||
Document doc = builder.parse( in ); | |||
setXmlDocument( doc ); | |||
} | |||
finally | |||
{ | |||
in.close(); | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
throw new TaskException( "Error while parsing document: " + xmlfile, e ); | |||
} | |||
} | |||
/** | |||
* Get the systemid of the appropriate stylesheet based on its name and | |||
* styledir. If no styledir is defined it will load it as a java resource in | |||
* the xsl child package, otherwise it will get it from the given directory. | |||
* | |||
* @return The StylesheetSystemId value | |||
* @throws IOException thrown if the requested stylesheet does not exist. | |||
*/ | |||
protected String getStylesheetSystemId() | |||
throws IOException | |||
{ | |||
String xslname = "junit-frames.xsl"; | |||
if( NOFRAMES.equals( m_format ) ) | |||
{ | |||
xslname = "junit-noframes.xsl"; | |||
} | |||
URL url = null; | |||
if( m_styleDir == null ) | |||
{ | |||
url = getClass().getResource( "xsl/" + xslname ); | |||
if( url == null ) | |||
{ | |||
throw new FileNotFoundException( "Could not find jar resource " + xslname ); | |||
} | |||
} | |||
else | |||
{ | |||
File file = new File( m_styleDir, xslname ); | |||
if( !file.exists() ) | |||
{ | |||
throw new FileNotFoundException( "Could not find file '" + file + "'" ); | |||
} | |||
url = new URL( "file", "", file.getAbsolutePath() ); | |||
} | |||
return url.toExternalForm(); | |||
} | |||
/** | |||
* check for invalid options | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
protected void checkOptions() | |||
throws TaskException | |||
{ | |||
// set the destination directory relative from the project if needed. | |||
if( m_toDir == null ) | |||
{ | |||
m_toDir = FileUtil.resolveFile( m_task.getBaseDirectory(), "." ); | |||
} | |||
else if( !m_toDir.isAbsolute() ) | |||
{ | |||
m_toDir = FileUtil.resolveFile( m_task.getBaseDirectory(), m_toDir.getPath() ); | |||
} | |||
} | |||
protected Document getDocument() | |||
{ | |||
return m_document; | |||
} | |||
protected String getFormat() | |||
{ | |||
return m_format; | |||
} | |||
protected File getToDir() | |||
{ | |||
return m_toDir; | |||
} | |||
public static class Format extends EnumeratedAttribute | |||
{ | |||
public String[] getValues() | |||
{ | |||
return new String[]{FRAMES, NOFRAMES}; | |||
} | |||
} | |||
} |
@@ -1,133 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
/** | |||
* Baseclass for BatchTest and JUnitTest. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||
*/ | |||
public abstract class BaseTest | |||
{ | |||
protected boolean m_haltOnError = false; | |||
protected boolean m_haltOnFail = false; | |||
protected boolean m_filtertrace = true; | |||
protected boolean fork = false; | |||
protected String ifProperty = null; | |||
protected String unlessProperty = null; | |||
protected ArrayList formatters = new ArrayList(); | |||
/** | |||
* destination directory | |||
*/ | |||
protected File destDir = null; | |||
protected String errorProperty; | |||
protected String failureProperty; | |||
public void setErrorProperty( String errorProperty ) | |||
{ | |||
this.errorProperty = errorProperty; | |||
} | |||
public void setFailureProperty( String failureProperty ) | |||
{ | |||
this.failureProperty = failureProperty; | |||
} | |||
public void setFiltertrace( boolean value ) | |||
{ | |||
m_filtertrace = value; | |||
} | |||
public void setFork( boolean value ) | |||
{ | |||
fork = value; | |||
} | |||
public void setHaltonerror( boolean value ) | |||
{ | |||
m_haltOnError = value; | |||
} | |||
public void setHaltonfailure( boolean value ) | |||
{ | |||
m_haltOnFail = value; | |||
} | |||
public void setIf( String propertyName ) | |||
{ | |||
ifProperty = propertyName; | |||
} | |||
/** | |||
* Sets the destination directory. | |||
* | |||
* @param destDir The new Todir value | |||
*/ | |||
public void setTodir( File destDir ) | |||
{ | |||
this.destDir = destDir; | |||
} | |||
public void setUnless( String propertyName ) | |||
{ | |||
unlessProperty = propertyName; | |||
} | |||
public java.lang.String getErrorProperty() | |||
{ | |||
return errorProperty; | |||
} | |||
public java.lang.String getFailureProperty() | |||
{ | |||
return failureProperty; | |||
} | |||
public boolean getFiltertrace() | |||
{ | |||
return m_filtertrace; | |||
} | |||
public boolean getFork() | |||
{ | |||
return fork; | |||
} | |||
public boolean getHaltonerror() | |||
{ | |||
return m_haltOnError; | |||
} | |||
public boolean getHaltonfailure() | |||
{ | |||
return m_haltOnFail; | |||
} | |||
/** | |||
* @return the destination directory as an absolute path if it exists | |||
* otherwise return <tt>null</tt> | |||
*/ | |||
public String getTodir() | |||
{ | |||
if( destDir != null ) | |||
{ | |||
return destDir.getAbsolutePath(); | |||
} | |||
return null; | |||
} | |||
public void addFormatter( FormatterElement elem ) | |||
{ | |||
formatters.add( elem ); | |||
} | |||
} |
@@ -1,187 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Iterator; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.DirectoryScanner; | |||
import org.apache.tools.todo.types.FileSet; | |||
import org.apache.tools.todo.types.ScannerUtil; | |||
/** | |||
* <p> | |||
* | |||
* Create then run <code>JUnitTest</code>'s based on the list of files given by | |||
* the fileset attribute. <p> | |||
* | |||
* Every <code>.java</code> or <code>.class</code> file in the fileset is | |||
* assumed to be a testcase. A <code>JUnitTest</code> is created for each of | |||
* these named classes with basic setup inherited from the parent <code>BatchTest</code> | |||
* . | |||
* | |||
* @author <a href="mailto:jeff.martin@synamic.co.uk">Jeff Martin</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||
* @see JUnitTest | |||
*/ | |||
public final class BatchTest extends BaseTest | |||
{ | |||
/** | |||
* the list of filesets containing the testcase filename rules | |||
*/ | |||
private ArrayList filesets = new ArrayList(); | |||
/** | |||
* Convenient method to convert a pathname without extension to a fully | |||
* qualified classname. For example <tt>org/apache/Whatever</tt> will be | |||
* converted to <tt>org.apache.Whatever</tt> | |||
* | |||
* @param filename the filename to "convert" to a classname. | |||
* @return the classname matching the filename. | |||
*/ | |||
public static final String javaToClass( String filename ) | |||
{ | |||
return filename.replace( File.separatorChar, '.' ); | |||
} | |||
/** | |||
* Return all <tt>JUnitTest</tt> instances obtain by applying the fileset | |||
* rules. | |||
* | |||
* @return an enumeration of all elements of this batchtest that are a <tt> | |||
* JUnitTest</tt> instance. | |||
*/ | |||
public final Iterator iterator() | |||
throws TaskException | |||
{ | |||
final JUnitTest[] tests = createAllJUnitTest(); | |||
return Arrays.asList( tests ).iterator(); | |||
} | |||
/** | |||
* Add a new fileset instance to this batchtest. Whatever the fileset is, | |||
* only filename that are <tt>.java</tt> or <tt>.class</tt> will be | |||
* considered as 'candidates'. | |||
* | |||
* @param fs the new fileset containing the rules to get the testcases. | |||
*/ | |||
public void addFileSet( FileSet fs ) | |||
{ | |||
filesets.add( fs ); | |||
} | |||
/** | |||
* Convenient method to merge the <tt>JUnitTest</tt> s of this batchtest to | |||
* a <tt>ArrayList</tt> . | |||
* | |||
* @param v the vector to which should be added all individual tests of this | |||
* batch test. | |||
*/ | |||
final void addTestsTo( ArrayList v ) | |||
throws TaskException | |||
{ | |||
final JUnitTest[] tests = createAllJUnitTest(); | |||
v.ensureCapacity( v.size() + tests.length ); | |||
for( int i = 0; i < tests.length; i++ ) | |||
{ | |||
v.add( tests[ i ] ); | |||
} | |||
} | |||
/** | |||
* Iterate over all filesets and return the filename of all files that end | |||
* with <tt>.java</tt> or <tt>.class</tt> . This is to avoid wrapping a <tt> | |||
* JUnitTest</tt> over an xml file for example. A Testcase is obviously a | |||
* java file (compiled or not). | |||
* | |||
* @return an array of filenames without their extension. As they should | |||
* normally be taken from their root, filenames should match their | |||
* fully qualified class name (If it is not the case it will fail when | |||
* running the test). For the class <tt>org/apache/Whatever.class</tt> | |||
* it will return <tt>org/apache/Whatever</tt> . | |||
*/ | |||
private String[] getFilenames() | |||
throws TaskException | |||
{ | |||
ArrayList v = new ArrayList(); | |||
final int size = this.filesets.size(); | |||
for( int j = 0; j < size; j++ ) | |||
{ | |||
FileSet fs = (FileSet)filesets.get( j ); | |||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||
ds.scan(); | |||
String[] f = ds.getIncludedFiles(); | |||
for( int k = 0; k < f.length; k++ ) | |||
{ | |||
String pathname = f[ k ]; | |||
if( pathname.endsWith( ".java" ) ) | |||
{ | |||
v.add( pathname.substring( 0, pathname.length() - ".java".length() ) ); | |||
} | |||
else if( pathname.endsWith( ".class" ) ) | |||
{ | |||
v.add( pathname.substring( 0, pathname.length() - ".class".length() ) ); | |||
} | |||
} | |||
} | |||
return (String[])v.toArray( new String[ v.size() ] ); | |||
} | |||
/** | |||
* Create all <tt>JUnitTest</tt> s based on the filesets. Each instance is | |||
* configured to match this instance properties. | |||
* | |||
* @return the array of all <tt>JUnitTest</tt> s that belongs to this batch. | |||
*/ | |||
private JUnitTest[] createAllJUnitTest() | |||
throws TaskException | |||
{ | |||
String[] filenames = getFilenames(); | |||
JUnitTest[] tests = new JUnitTest[ filenames.length ]; | |||
for( int i = 0; i < tests.length; i++ ) | |||
{ | |||
String classname = javaToClass( filenames[ i ] ); | |||
tests[ i ] = createJUnitTest( classname ); | |||
} | |||
return tests; | |||
} | |||
/** | |||
* Create a <tt>JUnitTest</tt> that has the same property as this <tt> | |||
* BatchTest</tt> instance. | |||
* | |||
* @param classname the name of the class that should be run as a <tt> | |||
* JUnitTest</tt> . It must be a fully qualified name. | |||
* @return the <tt>JUnitTest</tt> over the given classname. | |||
*/ | |||
private JUnitTest createJUnitTest( String classname ) | |||
{ | |||
JUnitTest test = new JUnitTest(); | |||
test.setName( classname ); | |||
test.setHaltonerror( this.m_haltOnError ); | |||
test.setHaltonfailure( this.m_haltOnFail ); | |||
test.setFiltertrace( this.m_filtertrace ); | |||
test.setFork( this.fork ); | |||
test.setIf( this.ifProperty ); | |||
test.setUnless( this.unlessProperty ); | |||
test.setTodir( this.destDir ); | |||
test.setFailureProperty( failureProperty ); | |||
test.setErrorProperty( errorProperty ); | |||
Iterator list = this.formatters.iterator(); | |||
while( list.hasNext() ) | |||
{ | |||
test.addFormatter( (FormatterElement)list.next() ); | |||
} | |||
return test; | |||
} | |||
} |
@@ -1,272 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import junit.framework.AssertionFailedError; | |||
import junit.framework.Test; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Prints plain text output of the test to a specified Writer. Inspired by the | |||
* PlainJUnitResultFormatter. | |||
* | |||
* @author <a href="mailto:robertdw@bigpond.net.au">Robert Watkins</a> | |||
* @see FormatterElement | |||
* @see PlainJUnitResultFormatter | |||
*/ | |||
public class BriefJUnitResultFormatter implements JUnitResultFormatter | |||
{ | |||
/** | |||
* Formatter for timings. | |||
*/ | |||
private java.text.NumberFormat m_numberFormat = java.text.NumberFormat.getInstance(); | |||
/** | |||
* Output suite has written to System.out | |||
*/ | |||
private String systemOutput = null; | |||
/** | |||
* Output suite has written to System.err | |||
*/ | |||
private String systemError = null; | |||
/** | |||
* Where to write the log to. | |||
*/ | |||
private java.io.OutputStream m_out; | |||
/** | |||
* Used for writing the results. | |||
*/ | |||
private java.io.PrintWriter m_output; | |||
/** | |||
* Used for writing formatted results to. | |||
*/ | |||
private java.io.PrintWriter m_resultWriter; | |||
/** | |||
* Used as part of formatting the results. | |||
*/ | |||
private java.io.StringWriter m_results; | |||
public BriefJUnitResultFormatter() | |||
{ | |||
m_results = new java.io.StringWriter(); | |||
m_resultWriter = new java.io.PrintWriter( m_results ); | |||
} | |||
/** | |||
* Sets the stream the formatter is supposed to write its results to. | |||
* | |||
* @param out The new Output value | |||
*/ | |||
public void setOutput( java.io.OutputStream out ) | |||
{ | |||
m_out = out; | |||
m_output = new java.io.PrintWriter( out ); | |||
} | |||
public void setSystemError( String err ) | |||
{ | |||
systemError = err; | |||
} | |||
public void setSystemOutput( String out ) | |||
{ | |||
systemOutput = out; | |||
} | |||
/** | |||
* A test caused an error. | |||
* | |||
* @param test The feature to be added to the Error attribute | |||
* @param error The feature to be added to the Error attribute | |||
*/ | |||
public void addError( Test test, Throwable error ) | |||
{ | |||
formatError( "\tCaused an ERROR", test, error ); | |||
} | |||
/** | |||
* Interface TestListener for JUnit <= 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, Throwable t ) | |||
{ | |||
formatError( "\tFAILED", test, t ); | |||
} | |||
/** | |||
* Interface TestListener for JUnit > 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, AssertionFailedError t ) | |||
{ | |||
addFailure( test, (Throwable)t ); | |||
} | |||
/** | |||
* A test ended. | |||
* | |||
* @param test Description of Parameter | |||
*/ | |||
public void endTest( Test test ) | |||
{ | |||
} | |||
/** | |||
* The whole testsuite ended. | |||
* | |||
* @param suite Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void endTestSuite( JUnitTest suite ) | |||
throws TaskException | |||
{ | |||
final StringBuffer sb = new StringBuffer( "Testsuite: " ); | |||
sb.append( suite.getName() ); | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
sb.append( "Tests run: " ); | |||
sb.append( suite.runCount() ); | |||
sb.append( ", Failures: " ); | |||
sb.append( suite.failureCount() ); | |||
sb.append( ", Errors: " ); | |||
sb.append( suite.errorCount() ); | |||
sb.append( ", Time elapsed: " ); | |||
sb.append( m_numberFormat.format( suite.getRunTime() / 1000.0 ) ); | |||
sb.append( " sec" ); | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
// append the err and output streams to the log | |||
if( systemOutput != null && systemOutput.length() > 0 ) | |||
{ | |||
sb.append( "------------- Standard Output ---------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ) | |||
.append( systemOutput ) | |||
.append( "------------- ---------------- ---------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
if( systemError != null && systemError.length() > 0 ) | |||
{ | |||
sb.append( "------------- Standard Error -----------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ) | |||
.append( systemError ) | |||
.append( "------------- ---------------- ---------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
if( output() != null ) | |||
{ | |||
try | |||
{ | |||
output().write( sb.toString() ); | |||
resultWriter().close(); | |||
output().write( m_results.toString() ); | |||
output().flush(); | |||
} | |||
finally | |||
{ | |||
if( m_out != (Object)System.out && | |||
m_out != (Object)System.err ) | |||
{ | |||
try | |||
{ | |||
m_out.close(); | |||
} | |||
catch( java.io.IOException e ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* A test started. | |||
* | |||
* @param test Description of Parameter | |||
*/ | |||
public void startTest( Test test ) | |||
{ | |||
} | |||
/** | |||
* The whole testsuite started. | |||
* | |||
* @param suite Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void startTestSuite( JUnitTest suite ) | |||
throws TaskException | |||
{ | |||
} | |||
/** | |||
* Format an error and print it. | |||
* | |||
* @param type Description of Parameter | |||
* @param test Description of Parameter | |||
* @param error Description of Parameter | |||
*/ | |||
protected synchronized void formatError( String type, Test test, | |||
Throwable error ) | |||
{ | |||
if( test != null ) | |||
{ | |||
endTest( test ); | |||
} | |||
resultWriter().println( formatTest( test ) + type ); | |||
resultWriter().println( error.getMessage() ); | |||
String strace = JUnitTestRunner.getFilteredTrace( error ); | |||
resultWriter().println( strace ); | |||
resultWriter().println( "" ); | |||
} | |||
/** | |||
* Format the test for printing.. | |||
* | |||
* @param test Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
protected String formatTest( Test test ) | |||
{ | |||
if( test == null ) | |||
{ | |||
return "Null Test: "; | |||
} | |||
else | |||
{ | |||
return "Testcase: " + test.toString() + ":"; | |||
} | |||
} | |||
protected java.io.PrintWriter output() | |||
{ | |||
return m_output; | |||
} | |||
protected java.io.PrintWriter resultWriter() | |||
{ | |||
return m_resultWriter; | |||
} | |||
} |
@@ -1,100 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.util.Iterator; | |||
import java.util.NoSuchElementException; | |||
/** | |||
* Convenient enumeration over an array of enumeration. For example: <pre> | |||
* Iterator e1 = v1.iterator(); | |||
* while (e1.hasNext()){ | |||
* // do something | |||
* } | |||
* Iterator e2 = v2.iterator(); | |||
* while (e2.hasNext()){ | |||
* // do the same thing | |||
* } | |||
* </pre> can be written as: <pre> | |||
* Iterator[] enums = { v1.iterator(), v2.iterator() }; | |||
* Iterator e = Iterators.fromCompound(enums); | |||
* while (e.hasNext()){ | |||
* // do something | |||
* } | |||
* </pre> Note that the enumeration will skip null elements in the array. The | |||
* following is thus possible: <pre> | |||
* Iterator[] enums = { v1.iterator(), null, v2.iterator() }; // a null enumeration in the array | |||
* Iterator e = Iterators.fromCompound(enums); | |||
* while (e.hasNext()){ | |||
* // do something | |||
* } | |||
* </pre> | |||
* | |||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||
*/ | |||
class CompoundIterator | |||
implements Iterator | |||
{ | |||
/** | |||
* index in the enums array | |||
*/ | |||
private int index = 0; | |||
/** | |||
* enumeration array | |||
*/ | |||
private Iterator[] enumArray; | |||
public CompoundIterator( Iterator[] enumarray ) | |||
{ | |||
this.enumArray = enumarray; | |||
} | |||
/** | |||
* Tests if this enumeration contains more elements. | |||
* | |||
* @return <code>true</code> if and only if this enumeration object contains | |||
* at least one more element to provide; <code>false</code> otherwise. | |||
*/ | |||
public boolean hasNext() | |||
{ | |||
while( index < enumArray.length ) | |||
{ | |||
if( enumArray[ index ] != null && enumArray[ index ].hasNext() ) | |||
{ | |||
return true; | |||
} | |||
index++; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Returns the next element of this enumeration if this enumeration object | |||
* has at least one more element to provide. | |||
* | |||
* @return the next element of this enumeration. | |||
* @throws NoSuchElementException if no more elements exist. | |||
*/ | |||
public Object next() | |||
throws NoSuchElementException | |||
{ | |||
if( hasNext() ) | |||
{ | |||
return enumArray[ index ].next(); | |||
} | |||
throw new NoSuchElementException(); | |||
} | |||
public void remove() | |||
throws UnsupportedOperationException | |||
{ | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
@@ -1,239 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.IOException; | |||
import java.io.Writer; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.w3c.dom.Attr; | |||
import org.w3c.dom.Element; | |||
import org.w3c.dom.NamedNodeMap; | |||
import org.w3c.dom.Node; | |||
import org.w3c.dom.NodeList; | |||
import org.w3c.dom.Text; | |||
/** | |||
* Writes a DOM tree to a given Writer. <p> | |||
* | |||
* Utility class used by {@link org.apache.tools.ant.XmlLogger XmlLogger} and | |||
* org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter | |||
* XMLJUnitResultFormatter}.</p> | |||
* | |||
* @author The original author of XmlLogger | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</tt> | |||
*/ | |||
public class DOMElementWriter | |||
{ | |||
private StringBuffer sb = new StringBuffer(); | |||
/** | |||
* Don't try to be too smart but at least recognize the predefined entities. | |||
*/ | |||
protected String[] knownEntities = {"gt", "amp", "lt", "apos", "quot"}; | |||
/** | |||
* Is the given argument a character or entity reference? | |||
* | |||
* @param ent Description of Parameter | |||
* @return The Reference value | |||
*/ | |||
public boolean isReference( String ent ) | |||
{ | |||
if( !( ent.charAt( 0 ) == '&' ) || !ent.endsWith( ";" ) ) | |||
{ | |||
return false; | |||
} | |||
if( ent.charAt( 1 ) == '#' ) | |||
{ | |||
if( ent.charAt( 2 ) == 'x' ) | |||
{ | |||
try | |||
{ | |||
Integer.parseInt( ent.substring( 3, ent.length() - 1 ), 16 ); | |||
return true; | |||
} | |||
catch( NumberFormatException nfe ) | |||
{ | |||
return false; | |||
} | |||
} | |||
else | |||
{ | |||
try | |||
{ | |||
Integer.parseInt( ent.substring( 2, ent.length() - 1 ) ); | |||
return true; | |||
} | |||
catch( NumberFormatException nfe ) | |||
{ | |||
return false; | |||
} | |||
} | |||
} | |||
String name = ent.substring( 1, ent.length() - 1 ); | |||
for( int i = 0; i < knownEntities.length; i++ ) | |||
{ | |||
if( name.equals( knownEntities[ i ] ) ) | |||
{ | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* Escape <, > & ' and " as their entities. | |||
* | |||
* @param value Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
public String encode( String value ) | |||
{ | |||
sb.setLength( 0 ); | |||
for( int i = 0; i < value.length(); i++ ) | |||
{ | |||
char c = value.charAt( i ); | |||
switch( c ) | |||
{ | |||
case '<': | |||
sb.append( "<" ); | |||
break; | |||
case '>': | |||
sb.append( ">" ); | |||
break; | |||
case '\'': | |||
sb.append( "'" ); | |||
break; | |||
case '\"': | |||
sb.append( """ ); | |||
break; | |||
case '&': | |||
int nextSemi = value.indexOf( ";", i ); | |||
if( nextSemi < 0 | |||
|| !isReference( value.substring( i, nextSemi + 1 ) ) ) | |||
{ | |||
sb.append( "&" ); | |||
} | |||
else | |||
{ | |||
sb.append( '&' ); | |||
} | |||
break; | |||
default: | |||
sb.append( c ); | |||
break; | |||
} | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* Writes a DOM tree to a stream. | |||
* | |||
* @param element the Root DOM element of the tree | |||
* @param out where to send the output | |||
* @param indent number of | |||
* @param indentWith strings, that should be used to indent the | |||
* corresponding tag. | |||
* @exception IOException Description of Exception | |||
*/ | |||
public void write( Element element, Writer out, int indent, | |||
String indentWith ) | |||
throws IOException | |||
{ | |||
// Write indent characters | |||
for( int i = 0; i < indent; i++ ) | |||
{ | |||
out.write( indentWith ); | |||
} | |||
// Write element | |||
out.write( "<" ); | |||
out.write( element.getTagName() ); | |||
// Write attributes | |||
NamedNodeMap attrs = element.getAttributes(); | |||
for( int i = 0; i < attrs.getLength(); i++ ) | |||
{ | |||
Attr attr = (Attr)attrs.item( i ); | |||
out.write( " " ); | |||
out.write( attr.getName() ); | |||
out.write( "=\"" ); | |||
out.write( encode( attr.getValue() ) ); | |||
out.write( "\"" ); | |||
} | |||
out.write( ">" ); | |||
// Write child elements and text | |||
boolean hasChildren = false; | |||
NodeList children = element.getChildNodes(); | |||
for( int i = 0; i < children.getLength(); i++ ) | |||
{ | |||
Node child = children.item( i ); | |||
switch( child.getNodeType() ) | |||
{ | |||
case Node.ELEMENT_NODE: | |||
if( !hasChildren ) | |||
{ | |||
out.write( StringUtil.LINE_SEPARATOR ); | |||
hasChildren = true; | |||
} | |||
write( (Element)child, out, indent + 1, indentWith ); | |||
break; | |||
case Node.TEXT_NODE: | |||
out.write( encode( child.getNodeValue() ) ); | |||
break; | |||
case Node.CDATA_SECTION_NODE: | |||
out.write( "<![CDATA[" ); | |||
out.write( ( (Text)child ).getData() ); | |||
out.write( "]]>" ); | |||
break; | |||
case Node.ENTITY_REFERENCE_NODE: | |||
out.write( '&' ); | |||
out.write( child.getNodeName() ); | |||
out.write( ';' ); | |||
break; | |||
case Node.PROCESSING_INSTRUCTION_NODE: | |||
out.write( "<?" ); | |||
out.write( child.getNodeName() ); | |||
String data = child.getNodeValue(); | |||
if( data != null && data.length() > 0 ) | |||
{ | |||
out.write( ' ' ); | |||
out.write( data ); | |||
} | |||
out.write( "?>" ); | |||
break; | |||
} | |||
} | |||
// If we had child elements, we need to indent before we close | |||
// the element, otherwise we're on the same line and don't need | |||
// to indent | |||
if( hasChildren ) | |||
{ | |||
for( int i = 0; i < indent; i++ ) | |||
{ | |||
out.write( indentWith ); | |||
} | |||
} | |||
// Write element close | |||
out.write( "</" ); | |||
out.write( element.getTagName() ); | |||
out.write( ">" ); | |||
out.write( StringUtil.LINE_SEPARATOR ); | |||
out.flush(); | |||
} | |||
} |
@@ -1,226 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import org.w3c.dom.Attr; | |||
import org.w3c.dom.CDATASection; | |||
import org.w3c.dom.Comment; | |||
import org.w3c.dom.DOMException; | |||
import org.w3c.dom.Document; | |||
import org.w3c.dom.Element; | |||
import org.w3c.dom.NamedNodeMap; | |||
import org.w3c.dom.Node; | |||
import org.w3c.dom.NodeList; | |||
import org.w3c.dom.ProcessingInstruction; | |||
import org.w3c.dom.Text; | |||
/** | |||
* Some utilities that might be useful when manipulating DOM trees. | |||
* | |||
* @author <a href="bailliez@noos.fr">Stephane Bailliez</a> | |||
*/ | |||
public final class DOMUtil | |||
{ | |||
/** | |||
* unused constructor | |||
*/ | |||
private DOMUtil() | |||
{ | |||
} | |||
/** | |||
* Iterate over the children of a given node and return the first node that | |||
* has a specific name. | |||
* | |||
* @param parent the node to search child from. Can be <tt>null</tt> . | |||
* @param tagname the child name we are looking for. Cannot be <tt>null</tt> | |||
* . | |||
* @return the first child that matches the given name or <tt>null</tt> if | |||
* the parent is <tt>null</tt> or if a child does not match the given | |||
* name. | |||
*/ | |||
public static Element getChildByTagName( Node parent, String tagname ) | |||
{ | |||
if( parent == null ) | |||
{ | |||
return null; | |||
} | |||
NodeList childList = parent.getChildNodes(); | |||
final int len = childList.getLength(); | |||
for( int i = 0; i < len; i++ ) | |||
{ | |||
Node child = childList.item( i ); | |||
if( child != null && child.getNodeType() == Node.ELEMENT_NODE && | |||
child.getNodeName().equals( tagname ) ) | |||
{ | |||
return (Element)child; | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* return the attribute value of an element. | |||
* | |||
* @param node the node to get the attribute from. | |||
* @param name the name of the attribute we are looking for the value. | |||
* @return the value of the requested attribute or <tt>null</tt> if the | |||
* attribute was not found or if <tt>node</tt> is not an <tt>Element | |||
* </tt>. | |||
*/ | |||
public static String getNodeAttribute( Node node, String name ) | |||
{ | |||
if( node instanceof Element ) | |||
{ | |||
Element element = (Element)node; | |||
return element.getAttribute( name ); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Simple tree walker that will clone recursively a node. This is to avoid | |||
* using parser-specific API such as Sun's <tt>changeNodeOwner</tt> when we | |||
* are dealing with DOM L1 implementations since <tt>cloneNode(boolean)</tt> | |||
* will not change the owner document. <tt>changeNodeOwner</tt> is much | |||
* faster and avoid the costly cloning process. <tt>importNode</tt> is in | |||
* the DOM L2 interface. | |||
* | |||
* @param parent the node parent to which we should do the import to. | |||
* @param child the node to clone recursively. Its clone will be appended to | |||
* <tt>parent</tt> . | |||
* @return the cloned node that is appended to <tt>parent</tt> | |||
*/ | |||
public static final Node importNode( Node parent, Node child ) | |||
{ | |||
Node copy = null; | |||
final Document doc = parent.getOwnerDocument(); | |||
switch( child.getNodeType() ) | |||
{ | |||
case Node.CDATA_SECTION_NODE: | |||
copy = doc.createCDATASection( ( (CDATASection)child ).getData() ); | |||
break; | |||
case Node.COMMENT_NODE: | |||
copy = doc.createComment( ( (Comment)child ).getData() ); | |||
break; | |||
case Node.DOCUMENT_FRAGMENT_NODE: | |||
copy = doc.createDocumentFragment(); | |||
break; | |||
case Node.ELEMENT_NODE: | |||
final Element elem = doc.createElement( ( (Element)child ).getTagName() ); | |||
copy = elem; | |||
final NamedNodeMap attributes = child.getAttributes(); | |||
if( attributes != null ) | |||
{ | |||
final int size = attributes.getLength(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final Attr attr = (Attr)attributes.item( i ); | |||
elem.setAttribute( attr.getName(), attr.getValue() ); | |||
} | |||
} | |||
break; | |||
case Node.ENTITY_REFERENCE_NODE: | |||
copy = doc.createEntityReference( child.getNodeName() ); | |||
break; | |||
case Node.PROCESSING_INSTRUCTION_NODE: | |||
final ProcessingInstruction pi = (ProcessingInstruction)child; | |||
copy = doc.createProcessingInstruction( pi.getTarget(), pi.getData() ); | |||
break; | |||
case Node.TEXT_NODE: | |||
copy = doc.createTextNode( ( (Text)child ).getData() ); | |||
break; | |||
default: | |||
// this should never happen | |||
throw new IllegalStateException( "Invalid node type: " + child.getNodeType() ); | |||
} | |||
// okay we have a copy of the child, now the child becomes the parent | |||
// and we are iterating recursively over its children. | |||
try | |||
{ | |||
final NodeList children = child.getChildNodes(); | |||
if( children != null ) | |||
{ | |||
final int size = children.getLength(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final Node newChild = children.item( i ); | |||
if( newChild != null ) | |||
{ | |||
importNode( copy, newChild ); | |||
} | |||
} | |||
} | |||
} | |||
catch( DOMException ignored ) | |||
{ | |||
} | |||
// bingo append it. (this should normally not be done here) | |||
parent.appendChild( copy ); | |||
return copy; | |||
} | |||
/** | |||
* list a set of node that match a specific filter. The list can be made | |||
* recursively or not. | |||
* | |||
* @param parent the parent node to search from | |||
* @param filter the filter that children should match. | |||
* @param recurse <tt>true</tt> if you want the list to be made recursively | |||
* otherwise <tt>false</tt> . | |||
* @return Description of the Returned Value | |||
*/ | |||
public static NodeList listChildNodes( Node parent, NodeFilter filter, boolean recurse ) | |||
{ | |||
NodeListImpl matches = new NodeListImpl(); | |||
NodeList children = parent.getChildNodes(); | |||
if( children != null ) | |||
{ | |||
final int len = children.getLength(); | |||
for( int i = 0; i < len; i++ ) | |||
{ | |||
Node child = children.item( i ); | |||
if( filter.accept( child ) ) | |||
{ | |||
matches.add( child ); | |||
} | |||
if( recurse ) | |||
{ | |||
NodeList recmatches = listChildNodes( child, filter, recurse ); | |||
final int reclength = matches.getLength(); | |||
for( int j = 0; j < reclength; j++ ) | |||
{ | |||
matches.add( recmatches.item( i ) ); | |||
} | |||
} | |||
} | |||
} | |||
return matches; | |||
} | |||
/** | |||
* Filter interface to be applied when iterating over a DOM tree. Just think | |||
* of it like a <tt>FileFilter</tt> clone. | |||
* | |||
* @author RT | |||
*/ | |||
public interface NodeFilter | |||
{ | |||
/** | |||
* @param node the node to check for acceptance. | |||
* @return <tt>true</tt> if the node is accepted by this filter, | |||
* otherwise <tt>false</tt> | |||
*/ | |||
boolean accept( Node node ); | |||
} | |||
} |
@@ -1,244 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.OutputStream; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
/** | |||
* <p> | |||
* | |||
* A wrapper for the implementations of <code>JUnitResultFormatter</code>. In | |||
* particular, used as a nested <code><formatter></code> element in a | |||
* <code><junit></code> task. <p> | |||
* | |||
* For example, <code><pre> | |||
* <junit printsummary="no" haltonfailure="yes" fork="false"> | |||
* <formatter type="plain" usefile="false" /> | |||
* <test name="org.apache.ecs.InternationalCharTest" /> | |||
* </junit></pre></code> adds a <code>plain</code> type | |||
* implementation (<code>PlainJUnitResultFormatter</code>) to display the | |||
* results of the test. <p> | |||
* | |||
* Either the <code>type</code> or the <code>classname</code> attribute must be | |||
* set. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @see JUnitTask | |||
* @see XMLJUnitResultFormatter | |||
* @see BriefJUnitResultFormatter | |||
* @see PlainJUnitResultFormatter | |||
* @see JUnitResultFormatter | |||
*/ | |||
public class FormatterElement | |||
{ | |||
private OutputStream out = System.out; | |||
private boolean useFile = true; | |||
private String classname; | |||
private String extension; | |||
private File outFile; | |||
/** | |||
* <p> | |||
* | |||
* Set name of class to be used as the formatter. <p> | |||
* | |||
* This class must implement <code>JUnitResultFormatter</code> | |||
* | |||
* @param classname The new Classname value | |||
*/ | |||
public void setClassname( String classname ) | |||
{ | |||
this.classname = classname; | |||
} | |||
public void setExtension( String ext ) | |||
{ | |||
this.extension = ext; | |||
} | |||
/** | |||
* <p> | |||
* | |||
* Set output stream for formatter to use. <p> | |||
* | |||
* Defaults to standard out. | |||
* | |||
* @param out The new Output value | |||
*/ | |||
public void setOutput( OutputStream out ) | |||
{ | |||
this.out = out; | |||
} | |||
/** | |||
* <p> | |||
* | |||
* Quick way to use a standard formatter. <p> | |||
* | |||
* At the moment, there are three supported standard formatters. | |||
* <ul> | |||
* <li> The <code>xml</code> type uses a <code>XMLJUnitResultFormatter</code> | |||
* . | |||
* <li> The <code>brief</code> type uses a <code>BriefJUnitResultFormatter</code> | |||
* . | |||
* <li> The <code>plain</code> type (the default) uses a <code>PlainJUnitResultFormatter</code> | |||
* . | |||
* </ul> | |||
* <p> | |||
* | |||
* Sets <code>classname</code> attribute - so you can't use that attribute | |||
* if you use this one. | |||
* | |||
* @param type The new Type value | |||
*/ | |||
public void setType( TypeAttribute type ) | |||
{ | |||
if( "xml".equals( type.getValue() ) ) | |||
{ | |||
setClassname( "org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter" ); | |||
setExtension( ".xml" ); | |||
} | |||
else | |||
{ | |||
if( "brief".equals( type.getValue() ) ) | |||
{ | |||
setClassname( "org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter" ); | |||
} | |||
else | |||
{// must be plain, ensured by TypeAttribute | |||
setClassname( "org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter" ); | |||
} | |||
setExtension( ".txt" ); | |||
} | |||
} | |||
/** | |||
* Set whether the formatter should log to file. | |||
* | |||
* @param useFile The new UseFile value | |||
*/ | |||
public void setUseFile( boolean useFile ) | |||
{ | |||
this.useFile = useFile; | |||
} | |||
/** | |||
* Get name of class to be used as the formatter. | |||
* | |||
* @return The Classname value | |||
*/ | |||
public String getClassname() | |||
{ | |||
return classname; | |||
} | |||
public String getExtension() | |||
{ | |||
return extension; | |||
} | |||
/** | |||
* <p> | |||
* | |||
* Set the file which the formatte should log to. <p> | |||
* | |||
* Note that logging to file must be enabled . | |||
* | |||
* @param out The new Outfile value | |||
*/ | |||
void setOutfile( File out ) | |||
{ | |||
this.outFile = out; | |||
} | |||
/** | |||
* Get whether the formatter should log to file. | |||
* | |||
* @return The UseFile value | |||
*/ | |||
boolean getUseFile() | |||
{ | |||
return useFile; | |||
} | |||
JUnitResultFormatter createFormatter() | |||
throws TaskException | |||
{ | |||
if( classname == null ) | |||
{ | |||
throw new TaskException( "you must specify type or classname" ); | |||
} | |||
Class f = null; | |||
try | |||
{ | |||
f = Class.forName( classname ); | |||
} | |||
catch( ClassNotFoundException e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
Object o = null; | |||
try | |||
{ | |||
o = f.newInstance(); | |||
} | |||
catch( InstantiationException e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
catch( IllegalAccessException e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
if( !( o instanceof JUnitResultFormatter ) ) | |||
{ | |||
throw new TaskException( classname + " is not a JUnitResultFormatter" ); | |||
} | |||
JUnitResultFormatter r = (JUnitResultFormatter)o; | |||
if( useFile && outFile != null ) | |||
{ | |||
try | |||
{ | |||
out = new FileOutputStream( outFile ); | |||
} | |||
catch( java.io.IOException e ) | |||
{ | |||
throw new TaskException( "Error", e ); | |||
} | |||
} | |||
r.setOutput( out ); | |||
return r; | |||
} | |||
/** | |||
* <p> | |||
* | |||
* Enumerated attribute with the values "plain", "xml" and "brief". <p> | |||
* | |||
* Use to enumerate options for <code>type</code> attribute. | |||
* | |||
* @author RT | |||
*/ | |||
public static class TypeAttribute extends EnumeratedAttribute | |||
{ | |||
public String[] getValues() | |||
{ | |||
return new String[]{"plain", "xml", "brief"}; | |||
} | |||
} | |||
} |
@@ -1,59 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.OutputStream; | |||
import junit.framework.TestListener; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* This Interface describes classes that format the results of a JUnit testrun. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public interface JUnitResultFormatter extends TestListener | |||
{ | |||
/** | |||
* The whole testsuite started. | |||
* | |||
* @param suite Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
void startTestSuite( JUnitTest suite ) | |||
throws TaskException; | |||
/** | |||
* The whole testsuite ended. | |||
* | |||
* @param suite Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
void endTestSuite( JUnitTest suite ) | |||
throws TaskException; | |||
/** | |||
* Sets the stream the formatter is supposed to write its results to. | |||
* | |||
* @param out The new Output value | |||
*/ | |||
void setOutput( OutputStream out ); | |||
/** | |||
* This is what the test has written to System.out | |||
* | |||
* @param out The new SystemOutput value | |||
*/ | |||
void setSystemOutput( String out ); | |||
/** | |||
* This is what the test has written to System.err | |||
* | |||
* @param err The new SystemError value | |||
*/ | |||
void setSystemError( String err ); | |||
} |
@@ -1,759 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import java.util.Properties; | |||
import java.util.Random; | |||
import org.apache.aut.nativelib.ExecManager; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.framework.Execute; | |||
import org.apache.tools.todo.types.Argument; | |||
import org.apache.tools.todo.types.Commandline; | |||
import org.apache.tools.todo.types.CommandlineJava; | |||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||
import org.apache.tools.todo.types.EnvironmentVariable; | |||
import org.apache.tools.todo.types.Path; | |||
import org.apache.tools.todo.types.PathUtil; | |||
import org.apache.tools.todo.types.SysProperties; | |||
/** | |||
* Ant task to run JUnit tests. <p> | |||
* | |||
* JUnit is a framework to create unit test. It has been initially created by | |||
* Erich Gamma and Kent Beck. JUnit can be found at <a | |||
* href="http://www.junit.org">http://www.junit.org</a> . <p> | |||
* | |||
* <code>JUnitTask</code> can run a single specific <code>JUnitTest</code> using | |||
* the <code>test</code> element. For example, the following target <code><pre> | |||
* <target name="test-int-chars" depends="jar-test"> | |||
* <echo message="testing international characters"/> | |||
* <junit printsummary="no" haltonfailure="yes" fork="false"> | |||
* <classpath refid="classpath"/> | |||
* <formatter type="plain" usefile="false" /> | |||
* <test name="org.apache.ecs.InternationalCharTest" /> | |||
* </junit> | |||
* </target> | |||
* </pre></code> runs a single junit test (<code>org.apache.ecs.InternationalCharTest</code> | |||
* ) in the current VM using the path with id <code>classpath</code> as | |||
* classpath and presents the results formatted using the standard <code>plain</code> | |||
* formatter on the command line. <p> | |||
* | |||
* This task can also run batches of tests. The <code>batchtest</code> element | |||
* creates a <code>BatchTest</code> based on a fileset. This allows, for | |||
* example, all classes found in directory to be run as testcases. For example, | |||
* <code><pre> | |||
* <target name="run-tests" depends="dump-info,compile-tests" if="junit.present"> | |||
* <junit printsummary="no" haltonfailure="yes" fork="${junit.fork}"> | |||
* <jvmarg value="-classic"/> | |||
* <classpath refid="tests-classpath"/> | |||
* <sysproperty key="build.tests" value="${build.tests}"/> | |||
* <formatter type="brief" usefile="false" /> | |||
* <batchtest> | |||
* <fileset dir="${tests.dir}"> | |||
* <include name="**/*Test*" /> | |||
* </fileset> | |||
* </batchtest> | |||
* </junit> | |||
* </target> | |||
* </pre></code> this target finds any classes with a <code>test</code> | |||
* directory anywhere in their path (under the top <code>${tests.dir}</code>, of | |||
* course) and creates <code>JUnitTest</code>'s for each one. <p> | |||
* | |||
* Of course, <code><junit></code> and <code><batch></code> elements | |||
* can be combined for more complex tests. For an example, see the ant <code>build.xml</code> | |||
* target <code>run-tests</code> (the second example is an edited version). <p> | |||
* | |||
* To spawn a new Java VM to prevent interferences between different testcases, | |||
* you need to enable <code>fork</code>. A number of attributes and elements | |||
* allow you to set up how this JVM runs. | |||
* <ul> | |||
* <li> {@link #setTimeout} property sets the maximum time allowed before a | |||
* test is 'timed out' | |||
* <li> {@link #setMaxmemory} property sets memory assignment for the forked | |||
* jvm | |||
* <li> {@link #setJvm} property allows the jvm to be specified | |||
* <li> The <code><jvmarg></code> element sets arguements to be passed | |||
* to the forked jvm | |||
* </ul> | |||
* | |||
* | |||
* @author Thomas Haas | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||
* @author <a href="mailto:Gerrit.Riessen@web.de">Gerrit Riessen</a> | |||
* @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> | |||
* @see JUnitTest | |||
* @see BatchTest | |||
*/ | |||
public class JUnitTask extends AbstractTask | |||
{ | |||
private CommandlineJava commandline = new CommandlineJava(); | |||
private ArrayList tests = new ArrayList(); | |||
private ArrayList batchTests = new ArrayList(); | |||
private ArrayList formatters = new ArrayList(); | |||
private File dir = null; | |||
private Integer timeout = null; | |||
private boolean summary = false; | |||
private String summaryValue = ""; | |||
private JUnitTestRunner runner = null; | |||
/** | |||
* Creates a new JUnitRunner and enables fork of a new Java VM. | |||
* | |||
* @exception Exception Description of Exception | |||
*/ | |||
public JUnitTask() | |||
throws Exception | |||
{ | |||
commandline.setClassname( "org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" ); | |||
} | |||
/** | |||
* The directory to invoke the VM in. Ignored if no JVM is forked. | |||
* | |||
* @param dir the directory to invoke the JVM from. | |||
* @see #setFork(boolean) | |||
*/ | |||
public void setDir( File dir ) | |||
{ | |||
this.dir = dir; | |||
} | |||
/** | |||
* Tells this task to set the named property to "true" when there is a error | |||
* in a test. This property is applied on all BatchTest (batchtest) and | |||
* JUnitTest (test), however, it can possibly be overriden by their own | |||
* properties. | |||
* | |||
* @param propertyName The new ErrorProperty value | |||
*/ | |||
public void setErrorProperty( String propertyName ) | |||
{ | |||
Iterator enum = allTests(); | |||
while( enum.hasNext() ) | |||
{ | |||
BaseTest test = (BaseTest)enum.next(); | |||
test.setErrorProperty( propertyName ); | |||
} | |||
} | |||
/** | |||
* Tells this task to set the named property to "true" when there is a | |||
* failure in a test. This property is applied on all BatchTest (batchtest) | |||
* and JUnitTest (test), however, it can possibly be overriden by their own | |||
* properties. | |||
* | |||
* @param propertyName The new FailureProperty value | |||
*/ | |||
public void setFailureProperty( String propertyName ) | |||
{ | |||
Iterator enum = allTests(); | |||
while( enum.hasNext() ) | |||
{ | |||
BaseTest test = (BaseTest)enum.next(); | |||
test.setFailureProperty( propertyName ); | |||
} | |||
} | |||
/** | |||
* Tells this task whether to smartly filter the stack frames of JUnit | |||
* testcase errors and failures before reporting them. This property is | |||
* applied on all BatchTest (batchtest) and JUnitTest (test) however it can | |||
* possibly be overridden by their own properties. | |||
* | |||
* @param value <tt>false</tt> if it should not filter, otherwise <tt>true | |||
* <tt> | |||
*/ | |||
public void setFiltertrace( boolean value ) | |||
{ | |||
Iterator enum = allTests(); | |||
while( enum.hasNext() ) | |||
{ | |||
BaseTest test = (BaseTest)enum.next(); | |||
test.setFiltertrace( value ); | |||
} | |||
} | |||
/** | |||
* Tells whether a JVM should be forked for each testcase. It avoids | |||
* interference between testcases and possibly avoids hanging the build. | |||
* this property is applied on all BatchTest (batchtest) and JUnitTest | |||
* (test) however it can possibly be overridden by their own properties. | |||
* | |||
* @param value <tt>true</tt> if a JVM should be forked, otherwise <tt>false | |||
* </tt> | |||
* @see #setTimeout | |||
*/ | |||
public void setFork( boolean value ) | |||
{ | |||
Iterator enum = allTests(); | |||
while( enum.hasNext() ) | |||
{ | |||
BaseTest test = (BaseTest)enum.next(); | |||
test.setFork( value ); | |||
} | |||
} | |||
/** | |||
* Tells this task to halt when there is an error in a test. this property | |||
* is applied on all BatchTest (batchtest) and JUnitTest (test) however it | |||
* can possibly be overridden by their own properties. | |||
* | |||
* @param value <tt>true</tt> if it should halt, otherwise <tt>false</tt> | |||
*/ | |||
public void setHaltonerror( boolean value ) | |||
{ | |||
Iterator enum = allTests(); | |||
while( enum.hasNext() ) | |||
{ | |||
BaseTest test = (BaseTest)enum.next(); | |||
test.setHaltonerror( value ); | |||
} | |||
} | |||
/** | |||
* Tells this task to halt when there is a failure in a test. this property | |||
* is applied on all BatchTest (batchtest) and JUnitTest (test) however it | |||
* can possibly be overridden by their own properties. | |||
* | |||
* @param value <tt>true</tt> if it should halt, otherwise <tt>false</tt> | |||
*/ | |||
public void setHaltonfailure( boolean value ) | |||
{ | |||
Iterator enum = allTests(); | |||
while( enum.hasNext() ) | |||
{ | |||
BaseTest test = (BaseTest)enum.next(); | |||
test.setHaltonfailure( value ); | |||
} | |||
} | |||
/** | |||
* Set a new VM to execute the testcase. Default is <tt>java</tt> . Ignored | |||
* if no JVM is forked. | |||
* | |||
* @param value the new VM to use instead of <tt>java</tt> | |||
* @see #setFork(boolean) | |||
*/ | |||
public void setJvm( String value ) | |||
{ | |||
commandline.setVm( value ); | |||
} | |||
/** | |||
* Set the maximum memory to be used by all forked JVMs. | |||
* | |||
* @param max the value as defined by <tt>-mx</tt> or <tt>-Xmx</tt> in the | |||
* java command line options. | |||
*/ | |||
public void setMaxmemory( String max ) | |||
{ | |||
commandline.addVmArgument( "-Xmx" + max ); | |||
} | |||
/** | |||
* Tells whether the task should print a short summary of the task. | |||
* | |||
* @param value <tt>true</tt> to print a summary, <tt>withOutAndErr</tt> to | |||
* include the test's output as well, <tt>false</tt> otherwise. | |||
* @see SummaryJUnitResultFormatter | |||
*/ | |||
public void setPrintsummary( SummaryAttribute value ) | |||
{ | |||
summaryValue = value.getValue(); | |||
summary = value.asBoolean(); | |||
} | |||
/** | |||
* Set the timeout value (in milliseconds). If the test is running for more | |||
* than this value, the test will be canceled. (works only when in 'fork' | |||
* mode). | |||
* | |||
* @param value the maximum time (in milliseconds) allowed before declaring | |||
* the test as 'timed-out' | |||
* @see #setFork(boolean) | |||
*/ | |||
public void setTimeout( Integer value ) | |||
{ | |||
timeout = value; | |||
} | |||
/** | |||
* Add a new formatter to all tests of this task. | |||
* | |||
* @param fe The feature to be added to the Formatter attribute | |||
*/ | |||
public void addFormatter( FormatterElement fe ) | |||
{ | |||
formatters.add( fe ); | |||
} | |||
/** | |||
* Add a nested sysproperty element. This might be useful to tranfer Ant | |||
* properties to the testcases when JVM forking is not enabled. | |||
* | |||
* @param sysp The feature to be added to the Sysproperty attribute | |||
*/ | |||
public void addSysproperty( EnvironmentVariable sysp ) | |||
{ | |||
commandline.addSysproperty( sysp ); | |||
} | |||
/** | |||
* Add a new single testcase. | |||
* | |||
* @param test a new single testcase | |||
* @see JUnitTest | |||
*/ | |||
public void addTest( JUnitTest test ) | |||
{ | |||
tests.add( test ); | |||
} | |||
/** | |||
* Create a new set of testcases (also called ..batchtest) and add it to the | |||
* list. | |||
* | |||
* @return a new instance of a batch test. | |||
* @see BatchTest | |||
*/ | |||
public BatchTest createBatchTest() | |||
{ | |||
BatchTest test = new BatchTest(); | |||
batchTests.add( test ); | |||
return test; | |||
} | |||
/** | |||
* <code><classpath></code> allows classpath to be set for tests. | |||
* | |||
* @return Description of the Returned Value | |||
*/ | |||
public Path createClasspath() | |||
{ | |||
Path path1 = commandline.createClasspath(); | |||
final Path path = new Path(); | |||
path1.addPath( path ); | |||
return path; | |||
} | |||
/** | |||
* Create a new JVM argument. Ignored if no JVM is forked. | |||
* | |||
* @see #setFork(boolean) | |||
*/ | |||
public void addJvmarg( final Argument argument ) | |||
{ | |||
commandline.addVmArgument( argument ); | |||
} | |||
/** | |||
* Runs the testcase. | |||
* | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
/* | |||
* Adds the jars or directories containing Ant, this task and JUnit to the | |||
* classpath - this should make the forked JVM work without having to | |||
* specify them directly. | |||
*/ | |||
addClasspathEntry( "/junit/framework/TestCase.class" ); | |||
addClasspathEntry( "/org/apache/tools/ant/Task.class" ); | |||
addClasspathEntry( "/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class" ); | |||
Iterator list = getIndividualTests(); | |||
while( list.hasNext() ) | |||
{ | |||
JUnitTest test = (JUnitTest)list.next(); | |||
final TaskContext context = getContext(); | |||
if( test.shouldRun( context ) ) | |||
{ | |||
execute( test ); | |||
} | |||
} | |||
} | |||
/** | |||
* Merge all individual tests from the batchtest with all individual tests | |||
* and return an enumeration over all <tt>JUnitTest</tt> . | |||
* | |||
* @return The IndividualTests value | |||
*/ | |||
protected Iterator getIndividualTests() | |||
throws TaskException | |||
{ | |||
Iterator[] enums = new Iterator[ batchTests.size() + 1 ]; | |||
for( int i = 0; i < batchTests.size(); i++ ) | |||
{ | |||
BatchTest batchtest = (BatchTest)batchTests.get( i ); | |||
enums[ i ] = batchtest.iterator(); | |||
} | |||
enums[ enums.length - 1 ] = tests.iterator(); | |||
return new CompoundIterator( enums ); | |||
} | |||
/** | |||
* return the file or null if does not use a file | |||
* | |||
* @param fe Description of Parameter | |||
* @param test Description of Parameter | |||
* @return The Output value | |||
*/ | |||
protected File getOutput( FormatterElement fe, JUnitTest test ) | |||
throws TaskException | |||
{ | |||
if( fe.getUseFile() ) | |||
{ | |||
String filename = test.getOutfile() + fe.getExtension(); | |||
File destFile = new File( test.getTodir(), filename ); | |||
final String absFilename = destFile.getAbsolutePath(); | |||
return getContext().resolveFile( absFilename ); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Search for the given resource and add the directory or archive that | |||
* contains it to the classpath. <p> | |||
* | |||
* Doesn't work for archives in JDK 1.1 as the URL returned by getResource | |||
* doesn't contain the name of the archive.</p> | |||
* | |||
* @param resource The feature to be added to the ClasspathEntry attribute | |||
*/ | |||
protected void addClasspathEntry( String resource ) | |||
{ | |||
URL url = getClass().getResource( resource ); | |||
if( url != null ) | |||
{ | |||
String u = url.toString(); | |||
if( u.startsWith( "jar:file:" ) ) | |||
{ | |||
int pling = u.indexOf( "!" ); | |||
String jarName = u.substring( 9, pling ); | |||
getContext().debug( "Implicitly adding " + jarName + " to classpath" ); | |||
createClasspath().addLocation( new File( jarName ) ); | |||
} | |||
else if( u.startsWith( "file:" ) ) | |||
{ | |||
int tail = u.indexOf( resource ); | |||
String dirName = u.substring( 5, tail ); | |||
getContext().debug( "Implicitly adding " + dirName + " to classpath" ); | |||
createClasspath().addLocation( new File( dirName ) ); | |||
} | |||
else | |||
{ | |||
getContext().debug( "Don\'t know how to handle resource URL " + u ); | |||
} | |||
} | |||
else | |||
{ | |||
getContext().debug( "Couldn\'t find " + resource ); | |||
} | |||
} | |||
protected Iterator allTests() | |||
{ | |||
Iterator[] enums = {tests.iterator(), batchTests.iterator()}; | |||
return new CompoundIterator( enums ); | |||
} | |||
/** | |||
* Run the tests. | |||
* | |||
* @param test Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
protected void execute( JUnitTest test ) | |||
throws TaskException | |||
{ | |||
// set the default values if not specified | |||
//@todo should be moved to the test class instead. | |||
if( test.getTodir() == null ) | |||
{ | |||
test.setTodir( getBaseDirectory() ); | |||
} | |||
if( test.getOutfile() == null ) | |||
{ | |||
test.setOutfile( "TEST-" + test.getName() ); | |||
} | |||
// execute the test and get the return code | |||
int exitValue = JUnitTestRunner.ERRORS; | |||
boolean wasKilled = false; | |||
if( !test.getFork() ) | |||
{ | |||
exitValue = executeInVM( test ); | |||
} | |||
else | |||
{ | |||
exitValue = executeAsForked( test ); | |||
} | |||
// if there is an error/failure and that it should halt, stop everything otherwise | |||
// just log a statement | |||
boolean errorOccurredHere = exitValue == JUnitTestRunner.ERRORS; | |||
boolean failureOccurredHere = exitValue != JUnitTestRunner.SUCCESS; | |||
if( errorOccurredHere || failureOccurredHere ) | |||
{ | |||
if( errorOccurredHere && test.getHaltonerror() | |||
|| failureOccurredHere && test.getHaltonfailure() ) | |||
{ | |||
throw new TaskException( "Test " + test.getName() + " failed" | |||
+ ( wasKilled ? " (timeout)" : "" ) ); | |||
} | |||
else | |||
{ | |||
final String message = "TEST " + test.getName() + " FAILED" + | |||
( wasKilled ? " (timeout)" : "" ); | |||
getContext().error( message ); | |||
if( errorOccurredHere && test.getErrorProperty() != null ) | |||
{ | |||
final String name = test.getErrorProperty(); | |||
getContext().setProperty( name, "true" ); | |||
} | |||
if( failureOccurredHere && test.getFailureProperty() != null ) | |||
{ | |||
final String name = test.getFailureProperty(); | |||
getContext().setProperty( name, "true" ); | |||
} | |||
} | |||
} | |||
} | |||
protected void handleErrorOutput( String line ) | |||
{ | |||
if( runner != null ) | |||
{ | |||
runner.handleErrorOutput( line ); | |||
} | |||
else | |||
{ | |||
//super.handleErrorOutput( line ); | |||
} | |||
} | |||
// in VM is not very nice since it could probably hang the | |||
// whole build. IMHO this method should be avoided and it would be best | |||
// to remove it in future versions. TBD. (SBa) | |||
protected void handleOutput( String line ) | |||
{ | |||
if( runner != null ) | |||
{ | |||
runner.handleOutput( line ); | |||
} | |||
else | |||
{ | |||
//super.handleOutput( line ); | |||
} | |||
} | |||
/** | |||
* Execute a testcase by forking a new JVM. The command will block until it | |||
* finishes. To know if the process was destroyed or not, use the <tt> | |||
* killedProcess()</tt> method of the watchdog class. | |||
* | |||
* @param test the testcase to execute. | |||
*/ | |||
private int executeAsForked( JUnitTest test ) | |||
throws TaskException | |||
{ | |||
CommandlineJava cmd = commandline;//(CommandlineJava)commandline.clone(); | |||
cmd.setClassname( "org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" ); | |||
cmd.addArgument( test.getName() ); | |||
cmd.addArgument( "filtertrace=" + test.getFiltertrace() ); | |||
cmd.addArgument( "haltOnError=" + test.getHaltonerror() ); | |||
cmd.addArgument( "haltOnFailure=" + test.getHaltonfailure() ); | |||
if( summary ) | |||
{ | |||
getContext().info( "Running " + test.getName() ); | |||
cmd.addArgument( "formatter=org.apache.tools.ant.taskdefs.optional.junit.SummaryJUnitResultFormatter" ); | |||
} | |||
StringBuffer formatterArg = new StringBuffer( 128 ); | |||
final FormatterElement[] feArray = mergeFormatters( test ); | |||
for( int i = 0; i < feArray.length; i++ ) | |||
{ | |||
FormatterElement fe = feArray[ i ]; | |||
formatterArg.append( "formatter=" ); | |||
formatterArg.append( fe.getClassname() ); | |||
File outFile = getOutput( fe, test ); | |||
if( outFile != null ) | |||
{ | |||
formatterArg.append( "," ); | |||
formatterArg.append( outFile ); | |||
} | |||
cmd.addArgument( formatterArg.toString() ); | |||
formatterArg.setLength( 0 ); | |||
} | |||
// Create a temporary file to pass the Ant properties to the forked test | |||
File propsFile = new File( "junit" + ( new Random( System.currentTimeMillis() ) ).nextLong() + ".properties" ); | |||
cmd.addArgument( "propsfile=" + propsFile.getAbsolutePath() ); | |||
Map p = getContext().getProperties(); | |||
Properties props = new Properties(); | |||
for( Iterator enum = p.keySet().iterator(); enum.hasNext(); ) | |||
{ | |||
final Object key = enum.next(); | |||
props.put( key, p.get( key ) ); | |||
} | |||
try | |||
{ | |||
final FileOutputStream outstream = new FileOutputStream( propsFile ); | |||
props.save( outstream, "Ant JUnitTask generated properties file" ); | |||
outstream.close(); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
throw new TaskException( "Error creating temporary properties file.", ioe ); | |||
} | |||
final ExecManager execManager = (ExecManager)getService( ExecManager.class ); | |||
final Execute exe = new Execute( execManager ); | |||
exe.setCommandline( new Commandline( cmd.getCommandline() ) ); | |||
if( dir != null ) | |||
{ | |||
exe.setWorkingDirectory( dir ); | |||
} | |||
getContext().debug( "Executing: " + cmd.toString() ); | |||
try | |||
{ | |||
return exe.execute(); | |||
} | |||
finally | |||
{ | |||
if( !propsFile.delete() ) | |||
{ | |||
throw new TaskException( "Could not delete temporary properties file." ); | |||
} | |||
} | |||
} | |||
/** | |||
* Execute inside VM. | |||
*/ | |||
private int executeInVM( JUnitTest test ) | |||
throws TaskException | |||
{ | |||
test.setProperties( getContext().getProperties() ); | |||
if( dir != null ) | |||
{ | |||
getContext().warn( "dir attribute ignored if running in the same VM" ); | |||
} | |||
SysProperties sysProperties = commandline.getSystemProperties(); | |||
if( sysProperties != null ) | |||
{ | |||
sysProperties.setSystem(); | |||
} | |||
try | |||
{ | |||
getContext().debug( "Using System properties " + System.getProperties() ); | |||
ClassLoader classLoader = null; | |||
Path classpath = commandline.getClasspath(); | |||
if( classpath != null ) | |||
{ | |||
getContext().debug( "Using CLASSPATH " + classpath ); | |||
final URL[] urls = PathUtil.toURLs( classpath ); | |||
classLoader = new URLClassLoader( urls ); | |||
} | |||
runner = new JUnitTestRunner( test, | |||
test.getHaltonerror(), | |||
test.getFiltertrace(), | |||
test.getHaltonfailure(), | |||
classLoader ); | |||
if( summary ) | |||
{ | |||
getContext().info( "Running " + test.getName() ); | |||
SummaryJUnitResultFormatter f = | |||
new SummaryJUnitResultFormatter(); | |||
f.setWithOutAndErr( "withoutanderr".equalsIgnoreCase( summaryValue ) ); | |||
f.setOutput( System.out ); | |||
runner.addFormatter( f ); | |||
} | |||
final FormatterElement[] feArray = mergeFormatters( test ); | |||
for( int i = 0; i < feArray.length; i++ ) | |||
{ | |||
FormatterElement fe = feArray[ i ]; | |||
File outFile = getOutput( fe, test ); | |||
if( outFile != null ) | |||
{ | |||
fe.setOutfile( outFile ); | |||
} | |||
else | |||
{ | |||
fe.setOutput( System.out ); | |||
} | |||
runner.addFormatter( fe.createFormatter() ); | |||
} | |||
runner.run(); | |||
return runner.getRetCode(); | |||
} | |||
finally | |||
{ | |||
if( sysProperties != null ) | |||
{ | |||
sysProperties.restoreSystem(); | |||
} | |||
} | |||
} | |||
private FormatterElement[] mergeFormatters( JUnitTest test ) | |||
{ | |||
final ArrayList feArrayList = (ArrayList)formatters.clone(); | |||
test.addFormattersTo( feArrayList ); | |||
return (FormatterElement[])feArrayList.toArray( new FormatterElement[ feArrayList.size() ] ); | |||
} | |||
/** | |||
* Print summary enumeration values. | |||
* | |||
* @author RT | |||
*/ | |||
public static class SummaryAttribute extends EnumeratedAttribute | |||
{ | |||
public String[] getValues() | |||
{ | |||
return new String[]{"true", "yes", "false", "no", | |||
"on", "off", "withOutAndErr"}; | |||
} | |||
public boolean asBoolean() | |||
{ | |||
final String value = getValue(); | |||
return "true".equals( value ) || | |||
"on".equals( value ) || | |||
"yes".equals( value ) || | |||
"withOutAndErr".equals( value ); | |||
} | |||
} | |||
} |
@@ -1,186 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import java.util.Properties; | |||
import org.apache.myrmidon.api.TaskContext; | |||
/** | |||
* <p> | |||
* | |||
* Run a single JUnit test. <p> | |||
* | |||
* The JUnit test is actually run by {@link JUnitTestRunner}. So read the doc | |||
* comments for that class :) | |||
* | |||
* @author Thomas Haas | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> , | |||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||
* @see JUnitTask | |||
* @see JUnitTestRunner | |||
*/ | |||
public class JUnitTest extends BaseTest | |||
{ | |||
/** | |||
* the name of the test case | |||
*/ | |||
private String m_name; | |||
/** | |||
* the name of the result file | |||
*/ | |||
private String m_outfile; | |||
// Snapshot of the system properties | |||
private Properties m_props; | |||
private long m_runTime; | |||
// @todo this is duplicating TestResult information. Only the time is not | |||
// part of the result. So we'd better derive a new class from TestResult | |||
// and deal with it. (SB) | |||
private long m_runs; | |||
private long m_failures; | |||
private long m_errors; | |||
public JUnitTest() | |||
{ | |||
} | |||
public JUnitTest( String name ) | |||
{ | |||
m_name = name; | |||
} | |||
public JUnitTest( final String name, | |||
final boolean haltOnError, | |||
final boolean haltOnFailure, | |||
final boolean filtertrace ) | |||
{ | |||
m_name = name; | |||
m_haltOnError = haltOnError; | |||
m_haltOnFail = haltOnFailure; | |||
m_filtertrace = filtertrace; | |||
} | |||
public void setCounts( long runs, long failures, long errors ) | |||
{ | |||
m_runs = runs; | |||
m_failures = failures; | |||
m_errors = errors; | |||
} | |||
/** | |||
* Set the name of the test class. | |||
*/ | |||
public void setName( final String value ) | |||
{ | |||
m_name = value; | |||
} | |||
/** | |||
* Set the name of the output file. | |||
*/ | |||
public void setOutfile( final String value ) | |||
{ | |||
m_outfile = value; | |||
} | |||
public void setProperties( final Map properties ) | |||
{ | |||
m_props = new Properties(); | |||
final Iterator enum = properties.keySet().iterator(); | |||
while( enum.hasNext() ) | |||
{ | |||
final Object key = enum.next(); | |||
final Object value = properties.get( key ); | |||
m_props.put( key, value ); | |||
} | |||
} | |||
public void setRunTime( final long runTime ) | |||
{ | |||
m_runTime = runTime; | |||
} | |||
public FormatterElement[] getFormatters() | |||
{ | |||
return (FormatterElement[])formatters.toArray( new FormatterElement[ formatters.size() ] ); | |||
} | |||
/** | |||
* Get the name of the test class. | |||
* | |||
* @return The Name value | |||
*/ | |||
public String getName() | |||
{ | |||
return m_name; | |||
} | |||
/** | |||
* Get the name of the output file | |||
* | |||
* @return the name of the output file. | |||
*/ | |||
public String getOutfile() | |||
{ | |||
return m_outfile; | |||
} | |||
public Properties getProperties() | |||
{ | |||
return m_props; | |||
} | |||
public long getRunTime() | |||
{ | |||
return m_runTime; | |||
} | |||
public long errorCount() | |||
{ | |||
return m_errors; | |||
} | |||
public long failureCount() | |||
{ | |||
return m_failures; | |||
} | |||
public long runCount() | |||
{ | |||
return m_runs; | |||
} | |||
public boolean shouldRun( final TaskContext context ) | |||
{ | |||
if( ifProperty != null && context.getProperty( ifProperty ) == null ) | |||
{ | |||
return false; | |||
} | |||
else if( unlessProperty != null && | |||
context.getProperty( unlessProperty ) != null ) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Convenient method to add formatters to a vector | |||
*/ | |||
void addFormattersTo( ArrayList v ) | |||
{ | |||
v.addAll( formatters ); | |||
} | |||
} |
@@ -1,643 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.BufferedReader; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.PrintStream; | |||
import java.io.PrintWriter; | |||
import java.io.StringReader; | |||
import java.io.StringWriter; | |||
import java.lang.reflect.Method; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Properties; | |||
import junit.framework.AssertionFailedError; | |||
import junit.framework.Test; | |||
import junit.framework.TestListener; | |||
import junit.framework.TestResult; | |||
import junit.framework.TestSuite; | |||
import org.apache.avalon.framework.ExceptionUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Simple Testrunner for JUnit that runs all tests of a testsuite. <p> | |||
* | |||
* This TestRunner expects a name of a TestCase class as its argument. If this | |||
* class provides a static suite() method it will be called and the resulting | |||
* Test will be run. So, the signature should be <pre><code> | |||
* public static junit.framework.Test suite() | |||
* </code></pre> <p> | |||
* | |||
* If no such method exists, all public methods starting with "test" and taking | |||
* no argument will be run. <p> | |||
* | |||
* Summary output is generated at the end. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> | |||
*/ | |||
public class JUnitTestRunner | |||
implements TestListener | |||
{ | |||
/** | |||
* No problems with this test. | |||
*/ | |||
public final static int SUCCESS = 0; | |||
/** | |||
* Some tests failed. | |||
*/ | |||
public final static int FAILURES = 1; | |||
/** | |||
* An error occured. | |||
*/ | |||
public final static int ERRORS = 2; | |||
/** | |||
* Do we filter junit.*.* stack frames out of failure and error exceptions. | |||
*/ | |||
private static boolean filtertrace = true; | |||
private final static String[] DEFAULT_TRACE_FILTERS = new String[] | |||
{ | |||
"junit.framework.TestCase", | |||
"junit.framework.TestResult", | |||
"junit.framework.TestSuite", | |||
"junit.framework.Assert.", // don't filter AssertionFailure | |||
"junit.swingui.TestRunner", | |||
"junit.awtui.TestRunner", | |||
"junit.textui.TestRunner", | |||
"java.lang.reflect.Method.invoke(", | |||
"org.apache.tools.ant." | |||
}; | |||
private static ArrayList m_fromCmdLine = new ArrayList(); | |||
/** | |||
* Holds the registered formatters. | |||
*/ | |||
private ArrayList m_formatters = new ArrayList(); | |||
/** | |||
* Do we stop on errors. | |||
*/ | |||
private boolean m_haltOnError; | |||
/** | |||
* Do we stop on test failures. | |||
*/ | |||
private boolean m_haltOnFailure; | |||
/** | |||
* The corresponding testsuite. | |||
*/ | |||
private Test m_suite; | |||
/** | |||
* Returncode | |||
*/ | |||
private int m_retCode = SUCCESS; | |||
/** | |||
* Exception caught in constructor. | |||
*/ | |||
private Exception m_exception; | |||
/** | |||
* The TestSuite we are currently running. | |||
*/ | |||
private JUnitTest m_junitTest; | |||
/** | |||
* Collects TestResults. | |||
*/ | |||
private TestResult m_res; | |||
/** | |||
* output written during the test | |||
*/ | |||
private PrintStream m_systemError; | |||
/** | |||
* Error output during the test | |||
*/ | |||
private PrintStream m_systemOut; | |||
/** | |||
* Constructor for fork=true or when the user hasn't specified a classpath. | |||
* | |||
* @param test Description of Parameter | |||
* @param haltOnError Description of Parameter | |||
* @param filtertrace Description of Parameter | |||
* @param haltOnFailure Description of Parameter | |||
*/ | |||
public JUnitTestRunner( final JUnitTest test, | |||
final boolean haltOnError, | |||
final boolean filtertrace, | |||
final boolean haltOnFailure ) | |||
{ | |||
this( test, haltOnError, filtertrace, haltOnFailure, null ); | |||
} | |||
/** | |||
* Constructor to use when the user has specified a classpath. | |||
* | |||
* @param test Description of Parameter | |||
* @param haltOnError Description of Parameter | |||
* @param filtertrace Description of Parameter | |||
* @param haltOnFailure Description of Parameter | |||
* @param loader Description of Parameter | |||
*/ | |||
public JUnitTestRunner( JUnitTest test, boolean haltOnError, boolean filtertrace, | |||
boolean haltOnFailure, ClassLoader loader ) | |||
{ | |||
//JUnitTestRunner.filtertrace = filtertrace; | |||
this.filtertrace = filtertrace; | |||
this.m_junitTest = test; | |||
this.m_haltOnError = haltOnError; | |||
this.m_haltOnFailure = haltOnFailure; | |||
try | |||
{ | |||
Class testClass = null; | |||
if( loader == null ) | |||
{ | |||
testClass = Class.forName( test.getName() ); | |||
} | |||
else | |||
{ | |||
testClass = loader.loadClass( test.getName() ); | |||
} | |||
Method suiteMethod = null; | |||
try | |||
{ | |||
// check if there is a suite method | |||
suiteMethod = testClass.getMethod( "suite", new Class[ 0 ] ); | |||
} | |||
catch( Exception e ) | |||
{ | |||
// no appropriate suite method found. We don't report any | |||
// error here since it might be perfectly normal. We don't | |||
// know exactly what is the cause, but we're doing exactly | |||
// the same as JUnit TestRunner do. We swallow the exceptions. | |||
} | |||
if( suiteMethod != null ) | |||
{ | |||
// if there is a suite method available, then try | |||
// to extract the suite from it. If there is an error | |||
// here it will be caught below and reported. | |||
m_suite = (Test)suiteMethod.invoke( null, new Class[ 0 ] ); | |||
} | |||
else | |||
{ | |||
// try to extract a test suite automatically | |||
// this will generate warnings if the class is no suitable Test | |||
m_suite = new TestSuite( testClass ); | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
m_retCode = ERRORS; | |||
m_exception = e; | |||
} | |||
} | |||
/** | |||
* Returns a filtered stack trace. This is ripped out of | |||
* junit.runner.BaseTestRunner. Scott M. Stirling. | |||
* | |||
* @param t Description of Parameter | |||
* @return The FilteredTrace value | |||
*/ | |||
public static String getFilteredTrace( Throwable t ) | |||
{ | |||
final String trace = ExceptionUtil.printStackTrace( t ); | |||
return JUnitTestRunner.filterStack( trace ); | |||
} | |||
/** | |||
* Filters stack frames from internal JUnit and Ant classes | |||
* | |||
* @param stack Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
public static String filterStack( String stack ) | |||
{ | |||
if( !filtertrace ) | |||
{ | |||
return stack; | |||
} | |||
StringWriter sw = new StringWriter(); | |||
PrintWriter pw = new PrintWriter( sw ); | |||
StringReader sr = new StringReader( stack ); | |||
BufferedReader br = new BufferedReader( sr ); | |||
String line; | |||
try | |||
{ | |||
while( ( line = br.readLine() ) != null ) | |||
{ | |||
if( !filterLine( line ) ) | |||
{ | |||
pw.println( line ); | |||
} | |||
} | |||
} | |||
catch( Exception IOException ) | |||
{ | |||
return stack;// return the stack unfiltered | |||
} | |||
return sw.toString(); | |||
} | |||
/** | |||
* Entry point for standalone (forked) mode. Parameters: testcaseclassname | |||
* plus parameters in the format key=value, none of which is required. | |||
* | |||
* <tablecols="4" border="1"> | |||
* | |||
* <tr> | |||
* | |||
* <th> | |||
* key | |||
* </th> | |||
* | |||
* <th> | |||
* description | |||
* </th> | |||
* | |||
* <th> | |||
* default value | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* haltOnError | |||
* </td> | |||
* | |||
* <td> | |||
* halt test on errors? | |||
* </td> | |||
* | |||
* <td> | |||
* false | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* haltOnFailure | |||
* </td> | |||
* | |||
* <td> | |||
* halt test on failures? | |||
* </td> | |||
* | |||
* <td> | |||
* false | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* formatter | |||
* </td> | |||
* | |||
* <td> | |||
* A JUnitResultFormatter given as classname,filename. If filename is | |||
* ommitted, System.out is assumed. | |||
* </td> | |||
* | |||
* <td> | |||
* none | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* </table> | |||
* | |||
* | |||
* @param args The command line arguments | |||
* @exception IOException Description of Exception | |||
*/ | |||
public static void main( String[] args ) | |||
throws IOException, TaskException | |||
{ | |||
boolean exitAtEnd = true; | |||
boolean haltError = false; | |||
boolean haltFail = false; | |||
boolean stackfilter = true; | |||
Properties props = new Properties(); | |||
if( args.length == 0 ) | |||
{ | |||
System.err.println( "required argument TestClassName missing" ); | |||
System.exit( ERRORS ); | |||
} | |||
for( int i = 1; i < args.length; i++ ) | |||
{ | |||
if( args[ i ].startsWith( "haltOnError=" ) ) | |||
{ | |||
haltError = "true".equals( args[ i ].substring( 12 ) ); | |||
} | |||
else if( args[ i ].startsWith( "haltOnFailure=" ) ) | |||
{ | |||
haltFail = "true".equals( args[ i ].substring( 14 ) ); | |||
} | |||
else if( args[ i ].startsWith( "filtertrace=" ) ) | |||
{ | |||
stackfilter = "true".equals( args[ i ].substring( 12 ) ); | |||
} | |||
else if( args[ i ].startsWith( "formatter=" ) ) | |||
{ | |||
try | |||
{ | |||
createAndStoreFormatter( args[ i ].substring( 10 ) ); | |||
} | |||
catch( TaskException be ) | |||
{ | |||
System.err.println( be.getMessage() ); | |||
System.exit( ERRORS ); | |||
} | |||
} | |||
else if( args[ i ].startsWith( "propsfile=" ) ) | |||
{ | |||
FileInputStream in = new FileInputStream( args[ i ].substring( 10 ) ); | |||
props.load( in ); | |||
in.close(); | |||
} | |||
} | |||
JUnitTest t = new JUnitTest( args[ 0 ] ); | |||
// Add/overlay system properties on the properties from the Ant project | |||
Hashtable p = System.getProperties(); | |||
props.putAll( p ); | |||
t.setProperties( props ); | |||
JUnitTestRunner runner = new JUnitTestRunner( t, haltError, stackfilter, haltFail ); | |||
transferFormatters( runner ); | |||
runner.run(); | |||
System.exit( runner.getRetCode() ); | |||
} | |||
/** | |||
* Line format is: formatter=<classname>(,<pathname> | |||
* | |||
* )? | |||
* | |||
* @param line Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
private static void createAndStoreFormatter( String line ) | |||
throws TaskException | |||
{ | |||
FormatterElement fe = new FormatterElement(); | |||
int pos = line.indexOf( ',' ); | |||
if( pos == -1 ) | |||
{ | |||
fe.setClassname( line ); | |||
} | |||
else | |||
{ | |||
fe.setClassname( line.substring( 0, pos ) ); | |||
fe.setOutfile( new File( line.substring( pos + 1 ) ) ); | |||
} | |||
m_fromCmdLine.add( fe.createFormatter() ); | |||
} | |||
private static boolean filterLine( String line ) | |||
{ | |||
for( int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++ ) | |||
{ | |||
if( line.indexOf( DEFAULT_TRACE_FILTERS[ i ] ) > 0 ) | |||
{ | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
private static void transferFormatters( JUnitTestRunner runner ) | |||
{ | |||
for( int i = 0; i < m_fromCmdLine.size(); i++ ) | |||
{ | |||
runner.addFormatter( (JUnitResultFormatter)m_fromCmdLine.get( i ) ); | |||
} | |||
} | |||
/** | |||
* Returns what System.exit() would return in the standalone version. | |||
* | |||
* @return 2 if errors occurred, 1 if tests failed else 0. | |||
*/ | |||
public int getRetCode() | |||
{ | |||
return m_retCode; | |||
} | |||
/** | |||
* Interface TestListener. <p> | |||
* | |||
* An error occured while running the test. | |||
* | |||
* @param test The feature to be added to the Error attribute | |||
* @param t The feature to be added to the Error attribute | |||
*/ | |||
public void addError( Test test, Throwable t ) | |||
{ | |||
if( m_haltOnError ) | |||
{ | |||
m_res.stop(); | |||
} | |||
} | |||
/** | |||
* Interface TestListener for JUnit <= 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, Throwable t ) | |||
{ | |||
if( m_haltOnFailure ) | |||
{ | |||
m_res.stop(); | |||
} | |||
} | |||
/** | |||
* Interface TestListener for JUnit > 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, AssertionFailedError t ) | |||
{ | |||
addFailure( test, (Throwable)t ); | |||
} | |||
public void addFormatter( JUnitResultFormatter f ) | |||
{ | |||
m_formatters.add( f ); | |||
} | |||
/** | |||
* Interface TestListener. <p> | |||
* | |||
* A Test is finished. | |||
* | |||
* @param test Description of Parameter | |||
*/ | |||
public void endTest( Test test ) | |||
{ | |||
} | |||
public void run() | |||
throws TaskException | |||
{ | |||
m_res = new TestResult(); | |||
m_res.addListener( this ); | |||
for( int i = 0; i < m_formatters.size(); i++ ) | |||
{ | |||
final TestListener listener = (TestListener)m_formatters.get( i ); | |||
m_res.addListener( listener ); | |||
} | |||
long start = System.currentTimeMillis(); | |||
fireStartTestSuite(); | |||
if( m_exception != null ) | |||
{// had an exception in the constructor | |||
for( int i = 0; i < m_formatters.size(); i++ ) | |||
{ | |||
( (TestListener)m_formatters.get( i ) ).addError( null, | |||
m_exception ); | |||
} | |||
m_junitTest.setCounts( 1, 0, 1 ); | |||
m_junitTest.setRunTime( 0 ); | |||
} | |||
else | |||
{ | |||
ByteArrayOutputStream errStrm = new ByteArrayOutputStream(); | |||
m_systemError = new PrintStream( errStrm ); | |||
ByteArrayOutputStream outStrm = new ByteArrayOutputStream(); | |||
m_systemOut = new PrintStream( outStrm ); | |||
try | |||
{ | |||
m_suite.run( m_res ); | |||
} | |||
finally | |||
{ | |||
m_systemError.close(); | |||
m_systemError = null; | |||
m_systemOut.close(); | |||
m_systemOut = null; | |||
sendOutAndErr( new String( outStrm.toByteArray() ), | |||
new String( errStrm.toByteArray() ) ); | |||
m_junitTest.setCounts( m_res.runCount(), m_res.failureCount(), | |||
m_res.errorCount() ); | |||
m_junitTest.setRunTime( System.currentTimeMillis() - start ); | |||
} | |||
} | |||
fireEndTestSuite(); | |||
if( m_retCode != SUCCESS || m_res.errorCount() != 0 ) | |||
{ | |||
m_retCode = ERRORS; | |||
} | |||
else if( m_res.failureCount() != 0 ) | |||
{ | |||
m_retCode = FAILURES; | |||
} | |||
} | |||
/** | |||
* Interface TestListener. <p> | |||
* | |||
* A new Test is started. | |||
*/ | |||
public void startTest( Test t ) | |||
{ | |||
} | |||
protected void handleErrorOutput( String line ) | |||
{ | |||
if( m_systemError != null ) | |||
{ | |||
m_systemError.println( line ); | |||
} | |||
} | |||
protected void handleOutput( String line ) | |||
{ | |||
if( m_systemOut != null ) | |||
{ | |||
m_systemOut.println( line ); | |||
} | |||
} | |||
private void fireEndTestSuite() | |||
throws TaskException | |||
{ | |||
final int size = m_formatters.size(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final JUnitResultFormatter formatter = | |||
(JUnitResultFormatter)m_formatters.get( i ); | |||
formatter.endTestSuite( m_junitTest ); | |||
} | |||
} | |||
private void fireStartTestSuite() | |||
throws TaskException | |||
{ | |||
final int size = m_formatters.size(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final JUnitResultFormatter formatter = (JUnitResultFormatter)m_formatters.get( i ); | |||
formatter.startTestSuite( m_junitTest ); | |||
} | |||
} | |||
private void sendOutAndErr( String out, String err ) | |||
{ | |||
final int size = m_formatters.size(); | |||
for( int i = 0; i < size; i++ ) | |||
{ | |||
final JUnitResultFormatter formatter = | |||
(JUnitResultFormatter)m_formatters.get( i ); | |||
formatter.setSystemOutput( out ); | |||
formatter.setSystemError( err ); | |||
} | |||
} | |||
} |
@@ -1,69 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.lang.reflect.Method; | |||
import junit.framework.Test; | |||
import junit.framework.TestCase; | |||
/** | |||
* Work around for some changes to the public JUnit API between different JUnit | |||
* releases. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @version $Revision$ | |||
*/ | |||
public class JUnitVersionHelper | |||
{ | |||
private static Method testCaseName = null; | |||
static | |||
{ | |||
try | |||
{ | |||
testCaseName = TestCase.class.getMethod( "getName", new Class[ 0 ] ); | |||
} | |||
catch( NoSuchMethodException e ) | |||
{ | |||
// pre JUnit 3.7 | |||
try | |||
{ | |||
testCaseName = TestCase.class.getMethod( "name", new Class[ 0 ] ); | |||
} | |||
catch( NoSuchMethodException e2 ) | |||
{ | |||
} | |||
} | |||
} | |||
/** | |||
* JUnit 3.7 introduces TestCase.getName() and subsequent versions of JUnit | |||
* remove the old name() method. This method provides access to the name of | |||
* a TestCase via reflection that is supposed to work with version before | |||
* and after JUnit 3.7. | |||
* | |||
* @param t Description of Parameter | |||
* @return The TestCaseName value | |||
*/ | |||
public static String getTestCaseName( Test t ) | |||
{ | |||
if( t instanceof TestCase && testCaseName != null ) | |||
{ | |||
try | |||
{ | |||
return (String)testCaseName.invoke( t, new Object[ 0 ] ); | |||
} | |||
catch( Throwable e ) | |||
{ | |||
} | |||
} | |||
return "unknown"; | |||
} | |||
} |
@@ -1,37 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.util.ArrayList; | |||
import org.w3c.dom.Node; | |||
import org.w3c.dom.NodeList; | |||
/** | |||
* custom implementation of a nodelist | |||
*/ | |||
public class NodeListImpl | |||
extends ArrayList | |||
implements NodeList | |||
{ | |||
public int getLength() | |||
{ | |||
return size(); | |||
} | |||
public Node item( final int i ) | |||
{ | |||
try | |||
{ | |||
return (Node)get( i ); | |||
} | |||
catch( final ArrayIndexOutOfBoundsException aioobe ) | |||
{ | |||
return null;// conforming to NodeList interface | |||
} | |||
} | |||
} |
@@ -1,253 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.PrintWriter; | |||
import java.io.StringWriter; | |||
import java.text.NumberFormat; | |||
import java.util.Hashtable; | |||
import junit.framework.AssertionFailedError; | |||
import junit.framework.Test; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Prints plain text output of the test to a specified Writer. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class PlainJUnitResultFormatter implements JUnitResultFormatter | |||
{ | |||
/** | |||
* Formatter for timings. | |||
*/ | |||
private NumberFormat nf = NumberFormat.getInstance(); | |||
/** | |||
* Timing helper. | |||
*/ | |||
private Hashtable testStarts = new Hashtable(); | |||
/** | |||
* Suppress endTest if testcase failed. | |||
*/ | |||
private Hashtable failed = new Hashtable(); | |||
private String systemOutput = null; | |||
private String systemError = null; | |||
/** | |||
* Helper to store intermediate output. | |||
*/ | |||
private StringWriter inner; | |||
/** | |||
* Where to write the log to. | |||
*/ | |||
private OutputStream out; | |||
/** | |||
* Convenience layer on top of {@link #inner inner}. | |||
*/ | |||
private PrintWriter wri; | |||
public PlainJUnitResultFormatter() | |||
{ | |||
inner = new StringWriter(); | |||
wri = new PrintWriter( inner ); | |||
} | |||
public void setOutput( OutputStream out ) | |||
{ | |||
this.out = out; | |||
} | |||
public void setSystemError( String err ) | |||
{ | |||
systemError = err; | |||
} | |||
public void setSystemOutput( String out ) | |||
{ | |||
systemOutput = out; | |||
} | |||
/** | |||
* Interface TestListener. <p> | |||
* | |||
* An error occured while running the test. | |||
* | |||
* @param test The feature to be added to the Error attribute | |||
* @param t The feature to be added to the Error attribute | |||
*/ | |||
public void addError( Test test, Throwable t ) | |||
{ | |||
formatError( "\tCaused an ERROR", test, t ); | |||
} | |||
/** | |||
* Interface TestListener for JUnit <= 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, Throwable t ) | |||
{ | |||
formatError( "\tFAILED", test, t ); | |||
} | |||
/** | |||
* Interface TestListener for JUnit > 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, AssertionFailedError t ) | |||
{ | |||
addFailure( test, (Throwable)t ); | |||
} | |||
/** | |||
* Interface TestListener. <p> | |||
* | |||
* A Test is finished. | |||
* | |||
* @param test Description of Parameter | |||
*/ | |||
public void endTest( Test test ) | |||
{ | |||
synchronized( wri ) | |||
{ | |||
wri.print( "Testcase: " | |||
+ JUnitVersionHelper.getTestCaseName( test ) ); | |||
if( Boolean.TRUE.equals( failed.get( test ) ) ) | |||
{ | |||
return; | |||
} | |||
Long l = (Long)testStarts.get( test ); | |||
wri.println( " took " | |||
+ nf.format( ( System.currentTimeMillis() - l.longValue() ) | |||
/ 1000.0 ) | |||
+ " sec" ); | |||
} | |||
} | |||
/** | |||
* The whole testsuite ended. | |||
*/ | |||
public void endTestSuite( JUnitTest suite ) | |||
throws TaskException | |||
{ | |||
StringBuffer sb = new StringBuffer( "Testsuite: " ); | |||
sb.append( suite.getName() ); | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
sb.append( "Tests run: " ); | |||
sb.append( suite.runCount() ); | |||
sb.append( ", Failures: " ); | |||
sb.append( suite.failureCount() ); | |||
sb.append( ", Errors: " ); | |||
sb.append( suite.errorCount() ); | |||
sb.append( ", Time elapsed: " ); | |||
sb.append( nf.format( suite.getRunTime() / 1000.0 ) ); | |||
sb.append( " sec" ); | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
// append the err and output streams to the log | |||
if( systemOutput != null && systemOutput.length() > 0 ) | |||
{ | |||
sb.append( "------------- Standard Output ---------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ) | |||
.append( systemOutput ) | |||
.append( "------------- ---------------- ---------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
if( systemError != null && systemError.length() > 0 ) | |||
{ | |||
sb.append( "------------- Standard Error -----------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ) | |||
.append( systemError ) | |||
.append( "------------- ---------------- ---------------" ) | |||
.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
if( out != null ) | |||
{ | |||
try | |||
{ | |||
out.write( sb.toString().getBytes() ); | |||
wri.close(); | |||
out.write( inner.toString().getBytes() ); | |||
out.flush(); | |||
} | |||
catch( IOException ioex ) | |||
{ | |||
throw new TaskException( "Unable to write output", ioex ); | |||
} | |||
finally | |||
{ | |||
if( out != System.out && out != System.err ) | |||
{ | |||
try | |||
{ | |||
out.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Interface TestListener. <p> | |||
* | |||
* A new Test is started. | |||
* | |||
* @param t Description of Parameter | |||
*/ | |||
public void startTest( Test t ) | |||
{ | |||
testStarts.put( t, new Long( System.currentTimeMillis() ) ); | |||
failed.put( t, Boolean.FALSE ); | |||
} | |||
/** | |||
* Empty. | |||
* | |||
* @param suite Description of Parameter | |||
*/ | |||
public void startTestSuite( JUnitTest suite ) | |||
{ | |||
} | |||
private void formatError( String type, Test test, Throwable t ) | |||
{ | |||
synchronized( wri ) | |||
{ | |||
if( test != null ) | |||
{ | |||
endTest( test ); | |||
failed.put( test, Boolean.TRUE ); | |||
} | |||
wri.println( type ); | |||
wri.println( t.getMessage() ); | |||
String strace = JUnitTestRunner.getFilteredTrace( t ); | |||
wri.print( strace ); | |||
wri.println( "" ); | |||
} | |||
} | |||
}// PlainJUnitResultFormatter |
@@ -1,190 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.todo.taskdefs.junit; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.text.NumberFormat; | |||
import junit.framework.AssertionFailedError; | |||
import junit.framework.Test; | |||
import org.apache.avalon.excalibur.util.StringUtil; | |||
import org.apache.myrmidon.api.TaskException; | |||
/** | |||
* Prints short summary output of the test to Ant's logging system. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class SummaryJUnitResultFormatter implements JUnitResultFormatter | |||
{ | |||
/** | |||
* Formatter for timings. | |||
*/ | |||
private NumberFormat nf = NumberFormat.getInstance(); | |||
private boolean withOutAndErr = false; | |||
private String systemOutput = null; | |||
private String systemError = null; | |||
/** | |||
* OutputStream to write to. | |||
*/ | |||
private OutputStream out; | |||
/** | |||
* Empty | |||
*/ | |||
public SummaryJUnitResultFormatter() | |||
{ | |||
} | |||
public void setOutput( OutputStream out ) | |||
{ | |||
this.out = out; | |||
} | |||
public void setSystemError( String err ) | |||
{ | |||
systemError = err; | |||
} | |||
public void setSystemOutput( String out ) | |||
{ | |||
systemOutput = out; | |||
} | |||
/** | |||
* Should the output to System.out and System.err be written to the summary. | |||
* | |||
* @param value The new WithOutAndErr value | |||
*/ | |||
public void setWithOutAndErr( boolean value ) | |||
{ | |||
withOutAndErr = value; | |||
} | |||
/** | |||
* Empty | |||
* | |||
* @param test The feature to be added to the Error attribute | |||
* @param t The feature to be added to the Error attribute | |||
*/ | |||
public void addError( Test test, Throwable t ) | |||
{ | |||
} | |||
/** | |||
* Empty | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, Throwable t ) | |||
{ | |||
} | |||
/** | |||
* Interface TestListener for JUnit > 3.4. <p> | |||
* | |||
* A Test failed. | |||
* | |||
* @param test The feature to be added to the Failure attribute | |||
* @param t The feature to be added to the Failure attribute | |||
*/ | |||
public void addFailure( Test test, AssertionFailedError t ) | |||
{ | |||
addFailure( test, (Throwable)t ); | |||
} | |||
/** | |||
* Empty | |||
* | |||
* @param test Description of Parameter | |||
*/ | |||
public void endTest( Test test ) | |||
{ | |||
} | |||
/** | |||
* The whole testsuite ended. | |||
* | |||
* @param suite Description of Parameter | |||
* @exception TaskException Description of Exception | |||
*/ | |||
public void endTestSuite( JUnitTest suite ) | |||
throws TaskException | |||
{ | |||
StringBuffer sb = new StringBuffer( "Tests run: " ); | |||
sb.append( suite.runCount() ); | |||
sb.append( ", Failures: " ); | |||
sb.append( suite.failureCount() ); | |||
sb.append( ", Errors: " ); | |||
sb.append( suite.errorCount() ); | |||
sb.append( ", Time elapsed: " ); | |||
sb.append( nf.format( suite.getRunTime() / 1000.0 ) ); | |||
sb.append( " sec" ); | |||
sb.append( StringUtil.LINE_SEPARATOR ); | |||
if( withOutAndErr ) | |||
{ | |||
if( systemOutput != null && systemOutput.length() > 0 ) | |||
{ | |||
sb.append( "Output:" ).append( StringUtil.LINE_SEPARATOR ).append( systemOutput ) | |||
.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
if( systemError != null && systemError.length() > 0 ) | |||
{ | |||
sb.append( "Error: " ).append( StringUtil.LINE_SEPARATOR ).append( systemError ) | |||
.append( StringUtil.LINE_SEPARATOR ); | |||
} | |||
} | |||
try | |||
{ | |||
out.write( sb.toString().getBytes() ); | |||
out.flush(); | |||
} | |||
catch( IOException ioex ) | |||
{ | |||
throw new TaskException( "Unable to write summary output", ioex ); | |||
} | |||
finally | |||
{ | |||
if( out != System.out && out != System.err ) | |||
{ | |||
try | |||
{ | |||
out.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Empty | |||
* | |||
* @param t Description of Parameter | |||
*/ | |||
public void startTest( Test t ) | |||
{ | |||
} | |||
/** | |||
* Empty | |||
* | |||
* @param suite Description of Parameter | |||
*/ | |||
public void startTestSuite( JUnitTest suite ) | |||
{ | |||
} | |||
} |