git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272460 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -1,197 +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.net.URL; | |||||
| import org.apache.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
| import org.apache.myrmidon.framework.nativelib.Argument; | |||||
| import org.apache.myrmidon.framework.file.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 final ExecuteJava m_exe = new ExecuteJava(); | |||||
| /** | |||||
| * where to output the result | |||||
| */ | |||||
| private File m_outputDirectory; | |||||
| /** | |||||
| * the file to process | |||||
| */ | |||||
| private File m_target; | |||||
| /** | |||||
| * The working directory of the process | |||||
| * | |||||
| * @param dir The new Dir value | |||||
| */ | |||||
| public void setDir( final File dir ) | |||||
| { | |||||
| m_exe.setWorkingDirectory( dir ); | |||||
| } | |||||
| public void setFork( final boolean fork ) | |||||
| { | |||||
| m_exe.setFork( fork ); | |||||
| } | |||||
| public void setOutputdirectory( final File outputDirectory ) | |||||
| { | |||||
| m_outputDirectory = outputDirectory; | |||||
| } | |||||
| public void setTarget( final File target ) | |||||
| { | |||||
| m_target = target; | |||||
| } | |||||
| /** | |||||
| * <code><classpath></code> allows classpath to be set because a | |||||
| * directory might be given for Antlr debug... | |||||
| */ | |||||
| public void addClasspath( final Path path ) | |||||
| { | |||||
| m_exe.getClassPath().add( path ); | |||||
| } | |||||
| /** | |||||
| * Create a new JVM argument. Ignored if no JVM is forked. | |||||
| * | |||||
| * @see #setFork(boolean) | |||||
| */ | |||||
| public void addJvmarg( final Argument argument ) | |||||
| { | |||||
| m_exe.getVmArguments().addArgument( 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( m_target.lastModified() <= getGeneratedFile().lastModified() ) | |||||
| { | |||||
| return; | |||||
| } | |||||
| m_exe.setClassName( "antlr.Tool" ); | |||||
| m_exe.getArguments().addArgument( "-o" ); | |||||
| m_exe.getArguments().addArgument( m_outputDirectory ); | |||||
| m_exe.getArguments().addArgument( m_target ); | |||||
| m_exe.execute( getContext() ); | |||||
| } | |||||
| /** | |||||
| * 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( final 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" ); | |||||
| m_exe.getClassPath().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" ); | |||||
| m_exe.getClassPath().addLocation( new File( dirName ) ); | |||||
| } | |||||
| 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( m_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( m_outputDirectory, generatedFileName + ".java" ); | |||||
| } | |||||
| private void validateAttributes() | |||||
| throws TaskException | |||||
| { | |||||
| if( m_target == null || !m_target.isFile() ) | |||||
| { | |||||
| throw new TaskException( "Invalid target: " + m_target ); | |||||
| } | |||||
| // if no output directory is specified, used the target's directory | |||||
| if( m_outputDirectory == null ) | |||||
| { | |||||
| m_outputDirectory = m_target.getParentFile(); | |||||
| } | |||||
| if( !m_outputDirectory.isDirectory() ) | |||||
| { | |||||
| throw new TaskException( "Invalid output directory: " + m_outputDirectory ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,291 +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.Os; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.nativelib.Execute; | |||||
| import org.apache.myrmidon.framework.FileSet; | |||||
| import org.apache.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| 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 ); | |||||
| Execute exe = new Execute(); | |||||
| exe.setWorkingDirectory( m_baseDir ); | |||||
| createCommand( exe, listFile ); | |||||
| exe.execute( getContext() ); | |||||
| 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 void createCommand( final Commandline cmd, final File listFile ) | |||||
| throws TaskException | |||||
| { | |||||
| 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() ); | |||||
| } | |||||
| /** | |||||
| * 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,303 +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.framework.FileSet; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| import org.apache.tools.todo.types.ScannerUtil; | |||||
| import org.apache.tools.todo.types.SimpleFileList; | |||||
| /** | |||||
| * 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( SimpleFileList 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( SimpleFileList 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() ) | |||||
| { | |||||
| SimpleFileList targetFL = (SimpleFileList)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() ) | |||||
| { | |||||
| SimpleFileList sourceFL = (SimpleFileList)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,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().verbose( "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().verbose( "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().verbose( "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,358 +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.framework.file.FileListUtil; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| import org.apache.tools.todo.util.FileUtils; | |||||
| /** | |||||
| * 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.add( 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.add( 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 ArgumentList cmd ) | |||||
| throws TaskException | |||||
| { | |||||
| final String[] args = cmd.getArguments(); | |||||
| getContext().debug( "Compilation args: " + FileUtils.formatCommandLine( args ) ); | |||||
| int n = 0; | |||||
| 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 ArgumentList setupJavahCommand() | |||||
| throws TaskException | |||||
| { | |||||
| final ArgumentList cmd = new ArgumentList(); | |||||
| 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.addArgument( FileListUtil.formatPath( m_classpath, getContext() ) ); | |||||
| } | |||||
| 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.addArgument( FileListUtil.formatPath( m_bootclasspath, getContext() ) ); | |||||
| } | |||||
| 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 | |||||
| { | |||||
| ArgumentList 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.myrmidon.framework.FileSet; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| 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,323 +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.framework.file.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.add( 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.listFiles( getContext() ); | |||||
| 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,141 +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.util.Iterator; | |||||
| import java.util.Properties; | |||||
| import org.apache.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| /** | |||||
| * 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 = new Path(); | |||||
| private String m_name; | |||||
| private String m_resource; | |||||
| private String m_value; | |||||
| public void addClasspath( final Path classpath ) | |||||
| throws TaskException | |||||
| { | |||||
| m_classpath.add( 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 | |||||
| { | |||||
| final ClassLoader classLoader = FileListUtil.createClassLoader( m_classpath, getContext() ); | |||||
| 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,128 +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.nativelib.Execute; | |||||
| import org.apache.myrmidon.framework.nativelib.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 Execute exe = createCommand(); | |||||
| exe.setWorkingDirectory( m_topDir ); | |||||
| final String message = "Building the RPM based on the " + m_specFile + " file"; | |||||
| getContext().info( message ); | |||||
| exe.execute( getContext() ); | |||||
| } | |||||
| private Execute createCommand() | |||||
| throws TaskException | |||||
| { | |||||
| final Execute cmd = new Execute(); | |||||
| 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,836 +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.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.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| import org.apache.myrmidon.framework.FileSet; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
| 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 = new Path(); | |||||
| /** | |||||
| * 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( final Path classpath ) | |||||
| throws TaskException | |||||
| { | |||||
| this.classpath.add( 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 | |||||
| { | |||||
| final ClassLoader classLoader = FileListUtil.createClassLoader( classpath, getContext() ); | |||||
| final Class dc = classLoader.loadClass( 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 MacNeill | |||||
| * @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,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,97 +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.excalibur.zip.ZipOutputStream; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| /** | |||||
| * 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,286 +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.framework.FileSet; | |||||
| 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.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,395 +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.myrmidon.api.TaskException; | |||||
| 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; | |||||
| import org.apache.excalibur.zip.ZipOutputStream; | |||||
| /** | |||||
| * 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,306 +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.avalon.excalibur.io.IOUtil; | |||||
| import org.apache.excalibur.tar.TarEntry; | |||||
| import org.apache.excalibur.tar.TarOutputStream; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| 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.myrmidon.framework.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,53 +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.avalon.excalibur.io.IOUtil; | |||||
| import org.apache.excalibur.tar.TarEntry; | |||||
| import org.apache.excalibur.tar.TarInputStream; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| /** | |||||
| * 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,109 +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.myrmidon.api.TaskException; | |||||
| import org.apache.excalibur.zip.ZipOutputStream; | |||||
| /** | |||||
| * 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,895 +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.avalon.excalibur.io.IOUtil; | |||||
| import org.apache.excalibur.zip.ZipEntry; | |||||
| import org.apache.excalibur.zip.ZipOutputStream; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.FileSet; | |||||
| import org.apache.tools.todo.taskdefs.MatchingTask; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| import org.apache.tools.todo.types.FileScanner; | |||||
| 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 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.myrmidon.framework.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 src 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,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,635 +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.framework.FileSet; | |||||
| import org.apache.tools.todo.taskdefs.MatchingTask; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| 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,468 +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.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.nativelib.Execute; | |||||
| import org.apache.myrmidon.framework.FileSet; | |||||
| import org.apache.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| import org.apache.tools.todo.util.FileUtils; | |||||
| import org.apache.aut.nativelib.PathUtil; | |||||
| /** | |||||
| * 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; | |||||
| /* | |||||
| * 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_memoryInitialSize = attributes.getMemoryInitialSize(); | |||||
| m_memoryMaximumSize = attributes.getMemoryMaximumSize(); | |||||
| } | |||||
| public Javac getJavac() | |||||
| { | |||||
| return m_attributes; | |||||
| } | |||||
| protected ArgumentList 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 ArgumentList setupJavacCommand( boolean debugLevelCheck ) | |||||
| throws TaskException | |||||
| { | |||||
| ArgumentList cmd = new ArgumentList(); | |||||
| setupJavacCommandlineSwitches( cmd, debugLevelCheck ); | |||||
| logFilesToCompile( cmd ); | |||||
| addFilesToCompile( 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 ArgumentList setupJavacCommandlineSwitches( ArgumentList cmd, | |||||
| boolean useDebugLevel ) | |||||
| throws TaskException | |||||
| { | |||||
| Path classpath = new Path(); | |||||
| addCompileClasspath( classpath ); | |||||
| 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.addArgument( FileListUtil.formatPath( classpath, getTaskContext() ) ); | |||||
| cmd.addArgument( "-sourcepath" ); | |||||
| cmd.addArgument( FileListUtil.formatPath( src, getTaskContext() ) ); | |||||
| if( target != null ) | |||||
| { | |||||
| cmd.addArgument( "-target" ); | |||||
| cmd.addArgument( target ); | |||||
| } | |||||
| final String[] bootclasspath = m_bootclasspath.listFiles( getTaskContext() ); | |||||
| if( bootclasspath.length > 0 ) | |||||
| { | |||||
| cmd.addArgument( "-bootclasspath" ); | |||||
| cmd.addArgument( PathUtil.formatPath( bootclasspath ) ); | |||||
| } | |||||
| if( m_extdirs != null ) | |||||
| { | |||||
| cmd.addArgument( "-extdirs" ); | |||||
| cmd.addArgument( FileListUtil.formatPath( m_extdirs, getTaskContext() ) ); | |||||
| } | |||||
| 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 ArgumentList setupModernJavacCommand() | |||||
| throws TaskException | |||||
| { | |||||
| ArgumentList cmd = new ArgumentList(); | |||||
| setupModernJavacCommandlineSwitches( cmd ); | |||||
| logFilesToCompile( cmd ); | |||||
| addFilesToCompile( 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 ArgumentList setupModernJavacCommandlineSwitches( ArgumentList cmd ) | |||||
| throws TaskException | |||||
| { | |||||
| setupJavacCommandlineSwitches( cmd, true ); | |||||
| if( m_attributes.getSource() != null ) | |||||
| { | |||||
| cmd.addArgument( "-source" ); | |||||
| cmd.addArgument( m_attributes.getSource() ); | |||||
| } | |||||
| return cmd; | |||||
| } | |||||
| /** | |||||
| * Adds the compilation classpath to a path. | |||||
| */ | |||||
| protected void addCompileClasspath( final Path classpath ) | |||||
| throws TaskException | |||||
| { | |||||
| // 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.add( m_compileClasspath ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Adds the command line arguments specifc to the current implementation. | |||||
| * | |||||
| * @param cmd The feature to be added to the CurrentCompilerArgs attribute | |||||
| */ | |||||
| protected void addCurrentCompilerArgs( ArgumentList cmd ) | |||||
| { | |||||
| cmd.addArguments( getJavac().getCurrentCompilerArgs() ); | |||||
| } | |||||
| /** | |||||
| * Do the compile with the specified arguments. | |||||
| * | |||||
| * @param cmd - the command line, to which the names of the files to | |||||
| * compile are added. | |||||
| */ | |||||
| protected boolean executeExternalCompile( final Commandline cmd ) | |||||
| throws TaskException | |||||
| { | |||||
| logFilesToCompile( cmd ); | |||||
| 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. | |||||
| */ | |||||
| try | |||||
| { | |||||
| tmpFile = File.createTempFile( "javac", "", new File( "." ) ); | |||||
| final FileWriter fout = new FileWriter( tmpFile ); | |||||
| try | |||||
| { | |||||
| final PrintWriter out = new PrintWriter( fout ); | |||||
| for( int i = 0; i < m_compileList.length; i++ ) | |||||
| { | |||||
| File file = m_compileList[i ]; | |||||
| out.println( file.getAbsolutePath() ); | |||||
| } | |||||
| out.close(); | |||||
| } | |||||
| finally | |||||
| { | |||||
| IOUtil.shutdownWriter( fout ); | |||||
| } | |||||
| } | |||||
| catch( final IOException ioe ) | |||||
| { | |||||
| throw new TaskException( "Error creating temporary file", ioe ); | |||||
| } | |||||
| cmd.addArgument( "@" + tmpFile.getAbsolutePath() ); | |||||
| final Execute exe = new Execute(); | |||||
| exe.setIgnoreReturnCode( true ); | |||||
| exe.setCommandline( cmd ); | |||||
| return exe.execute( getTaskContext() ) == 0; | |||||
| } | |||||
| 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 logFilesToCompile( final ArgumentList cmd ) | |||||
| throws TaskException | |||||
| { | |||||
| final String[] cmdline = cmd.getArguments(); | |||||
| getTaskContext().debug( "Compilation args: " + FileUtils.formatCommandLine( cmdline ) ); | |||||
| 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(); | |||||
| niceSourceList.append( " " + arg + StringUtil.LINE_SEPARATOR ); | |||||
| } | |||||
| getTaskContext().debug( niceSourceList.toString() ); | |||||
| } | |||||
| /** | |||||
| * Adds the files to compile to a command-line | |||||
| */ | |||||
| protected void addFilesToCompile( final ArgumentList cmd ) | |||||
| { | |||||
| for( int i = 0; i < m_compileList.length; i++ ) | |||||
| { | |||||
| File file = m_compileList[i ]; | |||||
| cmd.addArgument( file ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 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; | |||||
| } | |||||
| } | |||||
| addExtdirs( path, m_extdirs, getTaskContext() ); | |||||
| } | |||||
| /** | |||||
| * Adds the contents of a set of directories to a path. | |||||
| */ | |||||
| public static void addExtdirs( final Path toPath, | |||||
| final Path extDirs, | |||||
| final TaskContext context ) | |||||
| throws TaskException | |||||
| { | |||||
| final String[] dirs = extDirs.listFiles( context ); | |||||
| for( int i = 0; i < dirs.length; i++ ) | |||||
| { | |||||
| final File dir = new File( dirs[ i ] ); | |||||
| if( dir.exists() && dir.isDirectory() ) | |||||
| { | |||||
| final FileSet fileSet = new FileSet(); | |||||
| fileSet.setDir( dir ); | |||||
| fileSet.setIncludes( "*" ); | |||||
| toPath.addFileset( fileSet ); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,107 +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.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| /** | |||||
| * 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> | |||||
| * @author tora@debian.org | |||||
| */ | |||||
| 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 | |||||
| */ | |||||
| public boolean execute() | |||||
| throws TaskException | |||||
| { | |||||
| Commandline cmd; | |||||
| getTaskContext().debug( "Using gcj compiler" ); | |||||
| cmd = setupGCJCommand(); | |||||
| return executeExternalCompile( cmd ); | |||||
| } | |||||
| 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. | |||||
| final String[] bootclasspath = m_bootclasspath.listFiles( getTaskContext() ); | |||||
| classpath.add( bootclasspath ); | |||||
| // gcj doesn't support an extension dir (-extdir) | |||||
| // so we'll emulate it for compatibility and convenience. | |||||
| addExtdirs( classpath ); | |||||
| if( bootclasspath.length == 0 ) | |||||
| { | |||||
| // no bootclasspath, therefore, get one from the java runtime | |||||
| m_includeJavaRuntime = true; | |||||
| } | |||||
| addCompileClasspath( classpath ); | |||||
| // Gcj has no option for source-path so we | |||||
| // will add it to classpath. | |||||
| classpath.add( 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.addArgument( FileListUtil.formatPath( classpath, getTaskContext() ) ); | |||||
| 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.myrmidon.framework.nativelib.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,753 +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.framework.JavaVersion; | |||||
| import org.apache.tools.todo.taskdefs.MatchingTask; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| import org.apache.myrmidon.framework.file.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 = new Path(); | |||||
| 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( final Path bootclasspath ) | |||||
| { | |||||
| m_bootclasspath.add( 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.add( 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.add( 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.add( 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.listFiles( getContext() ); | |||||
| 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,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.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.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| 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" ); | |||||
| ArgumentList 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,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.javac; | |||||
| import java.lang.reflect.Method; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.api.TaskContext; | |||||
| import org.apache.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| 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" ); | |||||
| ArgumentList 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,42 +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.myrmidon.framework.nativelib.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 ); | |||||
| return executeExternalCompile( cmd ); | |||||
| } | |||||
| } | |||||
| @@ -1,134 +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.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| /** | |||||
| * 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> | |||||
| * @author skanthak@muehlheim.de | |||||
| */ | |||||
| 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 | |||||
| */ | |||||
| 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. | |||||
| final String[] bootclasspath = m_bootclasspath.listFiles( getTaskContext() ); | |||||
| classpath.add( bootclasspath ); | |||||
| // Jikes doesn't support an extension dir (-extdir) | |||||
| // so we'll emulate it for compatibility and convenience. | |||||
| addExtdirs( classpath ); | |||||
| if( bootclasspath.length == 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! | |||||
| addCompileClasspath( classpath ); | |||||
| // Jikes has no option for source-path so we | |||||
| // will add it to classpath. | |||||
| classpath.add( 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.add( 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.addArgument( FileListUtil.formatPath( classpath, getTaskContext() ) ); | |||||
| 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 ); | |||||
| return executeExternalCompile( cmd ); | |||||
| } | |||||
| } | |||||
| @@ -1,97 +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.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| /** | |||||
| * 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. | |||||
| final String[] bootclasspath = m_bootclasspath.listFiles( getTaskContext() ); | |||||
| classpath.add( bootclasspath ); | |||||
| // jvc doesn't support an extension dir (-extdir) | |||||
| // so we'll emulate it for compatibility and convenience. | |||||
| addExtdirs( classpath ); | |||||
| if( bootclasspath.length == 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! | |||||
| addCompileClasspath( classpath ); | |||||
| // jvc has no option for source-path so we | |||||
| // will add it to classpath. | |||||
| classpath.add( 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.addArgument( FileListUtil.formatPath( classpath, getTaskContext() ) ); | |||||
| // 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 ); | |||||
| return executeExternalCompile( cmd ); | |||||
| } | |||||
| } | |||||
| @@ -1,135 +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.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| /** | |||||
| * 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" ); | |||||
| ArgumentList 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 ArgumentList setupKjcCommand() | |||||
| throws TaskException | |||||
| { | |||||
| ArgumentList cmd = new Commandline(); | |||||
| // generate classpath, because kjc does't support sourcepath. | |||||
| Path classpath = new Path(); | |||||
| addCompileClasspath( classpath ); | |||||
| 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. | |||||
| cp.add( m_bootclasspath ); | |||||
| if( m_extdirs != null ) | |||||
| { | |||||
| addExtdirs( cp ); | |||||
| } | |||||
| cp.add( classpath ); | |||||
| cp.add( src ); | |||||
| cmd.addArgument( FileListUtil.formatPath( cp, getTaskContext() ) ); | |||||
| // 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 ); | |||||
| logFilesToCompile( cmd ); | |||||
| addFilesToCompile( cmd ); | |||||
| return cmd; | |||||
| } | |||||
| } | |||||
| @@ -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.myrmidon.framework.nativelib.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 = new Commandline(); | |||||
| setupJavacCommandlineSwitches( cmd, false ); | |||||
| cmd.setExecutable( "sj" ); | |||||
| return executeExternalCompile( cmd ); | |||||
| } | |||||
| } | |||||
| @@ -1,175 +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.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| /** | |||||
| * 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; | |||||
| 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 | |||||
| { | |||||
| final ExecuteJava exe = new ExecuteJava(); | |||||
| exe.setClassName( "COM.sun.labs.jjtree.Main" ); | |||||
| // load command line with optional attributes | |||||
| Enumeration iter = optionalAttrs.keys(); | |||||
| while( iter.hasMoreElements() ) | |||||
| { | |||||
| String name = (String)iter.nextElement(); | |||||
| Object value = optionalAttrs.get( name ); | |||||
| exe.getArguments().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 = target.getParentFile(); | |||||
| } | |||||
| 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 | |||||
| exe.getArguments().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().verbose( "Target is already built - skipping (" + target + ")" ); | |||||
| return; | |||||
| } | |||||
| exe.getArguments().addArgument( target ); | |||||
| if( javaccHome == null || !javaccHome.isDirectory() ) | |||||
| { | |||||
| throw new TaskException( "Javacchome not set." ); | |||||
| } | |||||
| final Path classpath = exe.getClassPath(); | |||||
| classpath.addLocation( new File( javaccHome, "JavaCC.zip" ) ); | |||||
| exe.setMaxMemory( "140M" ); | |||||
| exe.getSysProperties().addVariable( "install.root", javaccHome.getAbsolutePath() ); | |||||
| exe.executeForked( getContext() ); | |||||
| } | |||||
| } | |||||
| @@ -1,269 +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.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| /** | |||||
| * 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; | |||||
| 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 | |||||
| { | |||||
| // 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 = target.getParentFile(); | |||||
| } | |||||
| if( !outputDirectory.isDirectory() ) | |||||
| { | |||||
| throw new TaskException( "Outputdir not a directory." ); | |||||
| } | |||||
| if( javaccHome == null || !javaccHome.isDirectory() ) | |||||
| { | |||||
| throw new TaskException( "Javacchome not set." ); | |||||
| } | |||||
| // 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; | |||||
| } | |||||
| ExecuteJava exe = new ExecuteJava(); | |||||
| exe.setClassName( "COM.sun.labs.javacc.Main" ); | |||||
| // load command line with optional attributes | |||||
| Enumeration iter = optionalAttrs.keys(); | |||||
| while( iter.hasMoreElements() ) | |||||
| { | |||||
| String name = (String)iter.nextElement(); | |||||
| Object value = optionalAttrs.get( name ); | |||||
| exe.getArguments().addArgument( "-" + name + ":" + value.toString() ); | |||||
| } | |||||
| exe.getArguments().addArgument( "-OUTPUT_DIRECTORY:" + outputDirectory.getAbsolutePath() ); | |||||
| exe.getArguments().addArgument( target ); | |||||
| final Path classpath = exe.getClassPath(); | |||||
| classpath.addLocation( new File( javaccHome, "JavaCC.zip" ) ); | |||||
| exe.setMaxMemory( "140M" ); | |||||
| exe.getSysProperties().addVariable( "install.root", javaccHome.getAbsolutePath() ); | |||||
| exe.executeForked( getContext() ); | |||||
| } | |||||
| /** | |||||
| * 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.myrmidon.framework.file.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.add( 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.add( 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,261 +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.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| /** | |||||
| * 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 | |||||
| { | |||||
| private boolean m_fork; | |||||
| private String m_jvm; | |||||
| private String m_format = "text"; | |||||
| private Path m_compileClasspath = new Path(); | |||||
| 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 | |||||
| { | |||||
| addClasspath( 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 fork <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 jvm 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; | |||||
| } | |||||
| /** | |||||
| * Adds a nested classpath element. | |||||
| */ | |||||
| public void addClasspath( final Path path ) | |||||
| { | |||||
| m_compileClasspath.add( 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.add( path ); | |||||
| return path; | |||||
| } | |||||
| public void execute() | |||||
| throws TaskException | |||||
| { | |||||
| if( m_sourcesPath == null ) | |||||
| { | |||||
| throw new TaskException( "Missing Sourcepath required argument" ); | |||||
| } | |||||
| // execute the test and get the return code | |||||
| if( !m_fork ) | |||||
| { | |||||
| executeInVM(); | |||||
| } | |||||
| else | |||||
| { | |||||
| executeAsForked(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 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 void executeAsForked() | |||||
| throws TaskException | |||||
| { | |||||
| final ExecuteJava exe = new ExecuteJava(); | |||||
| exe.setWorkingDirectory( m_dir ); | |||||
| if( "text".equals( m_format ) ) | |||||
| { | |||||
| exe.setClassName( "jdepend.textui.JDepend" ); | |||||
| } | |||||
| else | |||||
| { | |||||
| exe.setClassName( "jdepend.xmlui.JDepend" ); | |||||
| } | |||||
| if( m_jvm != null ) | |||||
| { | |||||
| exe.setJvm( m_jvm ); | |||||
| } | |||||
| exe.getClassPath().add( m_compileClasspath ); | |||||
| 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 | |||||
| exe.getArguments().addArgument( "-file" ); | |||||
| exe.getArguments().addArgument( m_outputFile ); | |||||
| getContext().info( "Output to be stored in " + m_outputFile.getPath() ); | |||||
| } | |||||
| final String[] elements = m_sourcesPath.listFiles( getContext() ); | |||||
| 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." ); | |||||
| } | |||||
| exe.getArguments().addArgument( f ); | |||||
| } | |||||
| exe.executeForked( getContext() ); | |||||
| } | |||||
| // 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. | |||||
| */ | |||||
| private void executeInVM() | |||||
| 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(); | |||||
| throw new TaskException( msg ); | |||||
| } | |||||
| jdepend.setWriter( new PrintWriter( fw ) ); | |||||
| getContext().info( "Output to be stored in " + m_outputFile.getPath() ); | |||||
| } | |||||
| final String[] elements = m_sourcesPath.listFiles( getContext() ); | |||||
| 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."; | |||||
| throw new TaskException( msg ); | |||||
| } | |||||
| try | |||||
| { | |||||
| jdepend.addDirectory( f.getPath() ); | |||||
| } | |||||
| catch( IOException e ) | |||||
| { | |||||
| String msg = "JDepend Failed when adding a source directory: " + e.getMessage(); | |||||
| throw new TaskException( msg ); | |||||
| } | |||||
| } | |||||
| jdepend.analyze(); | |||||
| } | |||||
| } | |||||
| @@ -1,484 +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.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.myrmidon.framework.file.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.add( 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.add( 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.add( 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.listFiles( getContext() ); | |||||
| 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().verbose( "there were no files to compile" ); | |||||
| } | |||||
| else | |||||
| { | |||||
| getContext().verbose( "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,294 +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.myrmidon.framework.java.ExecuteJava; | |||||
| import org.apache.tools.todo.taskdefs.MatchingTask; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| /** | |||||
| * 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.add( 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) | |||||
| String[] args = new String[ 12 ]; | |||||
| File jspFile = null; | |||||
| String parents = ""; | |||||
| 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++ ] = FileListUtil.formatPath( compileClasspath, getContext() ); | |||||
| 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 ); | |||||
| ExecuteJava helperTask = new ExecuteJava(); | |||||
| helperTask.setClassName( "weblogic.jspc" ); | |||||
| helperTask.getArguments().addArguments( args ); | |||||
| helperTask.getClassPath().add( compileClasspath ); | |||||
| helperTask.executeForked( getContext() ); | |||||
| } | |||||
| } | |||||
| 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,91 +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.myrmidon.api.TaskException; | |||||
| import org.apache.tools.todo.taskdefs.jsp.JspC; | |||||
| import org.apache.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| import org.apache.tools.todo.util.FileUtils; | |||||
| /** | |||||
| * 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, | |||||
| ArgumentList cmd ) | |||||
| throws TaskException | |||||
| { | |||||
| final String[] args = cmd.getArguments(); | |||||
| getTaskContext().debug( "Compilation args: " + FileUtils.formatCommandLine( args ) ); | |||||
| 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,90 +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.framework.java.ExecuteJava; | |||||
| import org.apache.tools.todo.taskdefs.jsp.JspC; | |||||
| import org.apache.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| /** | |||||
| * 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" ); | |||||
| final ExecuteJava exe = new ExecuteJava(); | |||||
| exe.setClassName( "org.apache.jasper.JspC" ); | |||||
| if( getJspc().getClasspath() != null ) | |||||
| { | |||||
| exe.getClassPath().add( getJspc().getClasspath() ); | |||||
| } | |||||
| setupJasperCommand( exe.getArguments() ); | |||||
| // Create an instance of the compiler, redirecting output to | |||||
| // the project log | |||||
| exe.execute( getTaskContext() ); | |||||
| return true; | |||||
| } | |||||
| /* | |||||
| * ------------------------------------------------------------ | |||||
| */ | |||||
| private void setupJasperCommand( final ArgumentList cmd ) | |||||
| throws TaskException | |||||
| { | |||||
| 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 ); | |||||
| } | |||||
| } | |||||
| @@ -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.TaskContext; | |||||
| 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 TaskContext m_context; | |||||
| /** | |||||
| * the destination directory, this is the root from where html should be | |||||
| * generated | |||||
| */ | |||||
| private File m_toDir; | |||||
| public AggregateTransformer( TaskContext context ) | |||||
| { | |||||
| m_context = context; | |||||
| } | |||||
| 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_context.getBaseDirectory(), "." ); | |||||
| } | |||||
| else if( !m_toDir.isAbsolute() ) | |||||
| { | |||||
| m_toDir = FileUtil.resolveFile( m_context.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.myrmidon.framework.FileSet; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| 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,717 +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.util.ArrayList; | |||||
| import java.util.Iterator; | |||||
| import java.util.Properties; | |||||
| import java.util.Random; | |||||
| import org.apache.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskContext; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.framework.file.Path; | |||||
| import org.apache.myrmidon.framework.file.FileListUtil; | |||||
| import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
| import org.apache.myrmidon.framework.nativelib.Argument; | |||||
| import org.apache.myrmidon.framework.nativelib.Commandline; | |||||
| import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
| import org.apache.myrmidon.framework.nativelib.EnvironmentData; | |||||
| import org.apache.myrmidon.framework.nativelib.EnvironmentVariable; | |||||
| import org.apache.tools.todo.types.SysProperties; | |||||
| import org.apache.myrmidon.framework.nativelib.ArgumentList; | |||||
| /** | |||||
| * 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 ArrayList tests = new ArrayList(); | |||||
| private ArrayList batchTests = new ArrayList(); | |||||
| private ArrayList formatters = new ArrayList(); | |||||
| private Integer timeout = null; | |||||
| private boolean summary = false; | |||||
| private String summaryValue = ""; | |||||
| private JUnitTestRunner runner = null; | |||||
| private File dir; | |||||
| private String jvm; | |||||
| private String maxMem; | |||||
| private EnvironmentData sysProperties = new EnvironmentData(); | |||||
| private Path classPath = new Path(); | |||||
| private ArgumentList vmArgs = new Commandline(); | |||||
| /** | |||||
| * 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 ) | |||||
| { | |||||
| 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( final String value ) | |||||
| { | |||||
| jvm = 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( final String max ) | |||||
| { | |||||
| maxMem = 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 ) | |||||
| { | |||||
| sysProperties.addVariable( 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. | |||||
| */ | |||||
| public void addBatchTest( final BatchTest test ) | |||||
| { | |||||
| batchTests.add( test ); | |||||
| } | |||||
| /** | |||||
| * <code><classpath></code> allows classpath to be set for tests. | |||||
| */ | |||||
| public void addClasspath( final Path path ) | |||||
| { | |||||
| classPath.add( path ); | |||||
| } | |||||
| /** | |||||
| * Create a new JVM argument. Ignored if no JVM is forked. | |||||
| * | |||||
| * @see #setFork(boolean) | |||||
| */ | |||||
| public void addJvmarg( final Argument argument ) | |||||
| { | |||||
| vmArgs.addArgument( 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" ); | |||||
| classPath.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" ); | |||||
| classPath.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( final 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 | |||||
| { | |||||
| ExecuteJava cmd = new ExecuteJava(); | |||||
| cmd.setJvm( jvm ); | |||||
| cmd.setIgnoreReturnCode( true ); | |||||
| cmd.setWorkingDirectory( dir ); | |||||
| cmd.setMaxMemory( maxMem ); | |||||
| cmd.getClassPath().add( classPath ); | |||||
| cmd.getVmArguments().addArguments( vmArgs ); | |||||
| cmd.getSysProperties().addVariables( sysProperties ); | |||||
| cmd.setClassName( "org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" ); | |||||
| cmd.getArguments().addArgument( test.getName() ); | |||||
| cmd.getArguments().addArgument( "filtertrace=" + test.getFiltertrace() ); | |||||
| cmd.getArguments().addArgument( "haltOnError=" + test.getHaltonerror() ); | |||||
| cmd.getArguments().addArgument( "haltOnFailure=" + test.getHaltonfailure() ); | |||||
| if( summary ) | |||||
| { | |||||
| getContext().info( "Running " + test.getName() ); | |||||
| cmd.getArguments().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.getArguments().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.getArguments().addArgument( "propsfile=" + propsFile.getAbsolutePath() ); | |||||
| Properties props = new Properties(); | |||||
| props.putAll( getContext().getProperties() ); | |||||
| try | |||||
| { | |||||
| final FileOutputStream outstream = new FileOutputStream( propsFile ); | |||||
| props.store( outstream, "Ant JUnitTask generated properties file" ); | |||||
| outstream.close(); | |||||
| } | |||||
| catch( IOException ioe ) | |||||
| { | |||||
| throw new TaskException( "Error creating temporary properties file.", ioe ); | |||||
| } | |||||
| try | |||||
| { | |||||
| return cmd.executeForked( getContext() ); | |||||
| } | |||||
| 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() ); | |||||
| SysProperties.setSystem( sysProperties ); | |||||
| try | |||||
| { | |||||
| getContext().debug( "Using System properties " + System.getProperties() ); | |||||
| final ClassLoader classLoader = FileListUtil.createClassLoader( classPath, getContext() ); | |||||
| 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 | |||||
| { | |||||
| 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 ) | |||||
| { | |||||
| } | |||||
| } | |||||
| @@ -1,115 +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; | |||||
| /** | |||||
| * <p> | |||||
| * | |||||
| * Interface groups XML constants. Interface that groups all constants used | |||||
| * throughout the <tt>XML</tt> documents that are generated by the <tt> | |||||
| * XMLJUnitResultFormatter</tt> As of now the DTD is: <code><pre> | |||||
| * <----------------- | |||||
| * | |||||
| * @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
| * @see XMLJUnitResultFormatter | |||||
| * @see XMLResultAggregator | |||||
| * @todo describe DTDs ----------------------> </pre></code> | |||||
| */ | |||||
| public interface XMLConstants | |||||
| { | |||||
| /** | |||||
| * the testsuites element for the aggregate document | |||||
| */ | |||||
| String TESTSUITES = "testsuites"; | |||||
| /** | |||||
| * the testsuite element | |||||
| */ | |||||
| String TESTSUITE = "testsuite"; | |||||
| /** | |||||
| * the testcase element | |||||
| */ | |||||
| String TESTCASE = "testcase"; | |||||
| /** | |||||
| * the error element | |||||
| */ | |||||
| String ERROR = "error"; | |||||
| /** | |||||
| * the failure element | |||||
| */ | |||||
| String FAILURE = "failure"; | |||||
| /** | |||||
| * the system-err element | |||||
| */ | |||||
| String SYSTEM_ERR = "system-err"; | |||||
| /** | |||||
| * the system-out element | |||||
| */ | |||||
| String SYSTEM_OUT = "system-out"; | |||||
| /** | |||||
| * package attribute for the aggregate document | |||||
| */ | |||||
| String ATTR_PACKAGE = "package"; | |||||
| /** | |||||
| * name attribute for property, testcase and testsuite elements | |||||
| */ | |||||
| String ATTR_NAME = "name"; | |||||
| /** | |||||
| * time attribute for testcase and testsuite elements | |||||
| */ | |||||
| String ATTR_TIME = "time"; | |||||
| /** | |||||
| * errors attribute for testsuite elements | |||||
| */ | |||||
| String ATTR_ERRORS = "errors"; | |||||
| /** | |||||
| * failures attribute for testsuite elements | |||||
| */ | |||||
| String ATTR_FAILURES = "failures"; | |||||
| /** | |||||
| * tests attribute for testsuite elements | |||||
| */ | |||||
| String ATTR_TESTS = "tests"; | |||||
| /** | |||||
| * type attribute for failure and error elements | |||||
| */ | |||||
| String ATTR_TYPE = "type"; | |||||
| /** | |||||
| * message attribute for failure elements | |||||
| */ | |||||
| String ATTR_MESSAGE = "message"; | |||||
| /** | |||||
| * the properties element | |||||
| */ | |||||
| String PROPERTIES = "properties"; | |||||
| /** | |||||
| * the property element | |||||
| */ | |||||
| String PROPERTY = "property"; | |||||
| /** | |||||
| * value attribute for property elements | |||||
| */ | |||||
| String ATTR_VALUE = "value"; | |||||
| } | |||||
| @@ -1,278 +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.OutputStreamWriter; | |||||
| import java.io.Writer; | |||||
| import java.util.Hashtable; | |||||
| import java.util.Iterator; | |||||
| import java.util.Properties; | |||||
| import javax.xml.parsers.DocumentBuilder; | |||||
| import javax.xml.parsers.DocumentBuilderFactory; | |||||
| import junit.framework.AssertionFailedError; | |||||
| import junit.framework.Test; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.w3c.dom.Document; | |||||
| import org.w3c.dom.Element; | |||||
| import org.w3c.dom.Text; | |||||
| /** | |||||
| * Prints XML output of the test to a specified Writer. | |||||
| * | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> | |||||
| * @see FormatterElement | |||||
| */ | |||||
| public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants | |||||
| { | |||||
| /** | |||||
| * Element for the current test. | |||||
| */ | |||||
| private Hashtable testElements = new Hashtable(); | |||||
| /** | |||||
| * Timing helper. | |||||
| */ | |||||
| private Hashtable testStarts = new Hashtable(); | |||||
| /** | |||||
| * The XML document. | |||||
| */ | |||||
| private Document doc; | |||||
| /** | |||||
| * Where to write the log to. | |||||
| */ | |||||
| private OutputStream out; | |||||
| /** | |||||
| * The wrapper for the whole testsuite. | |||||
| */ | |||||
| private Element rootElement; | |||||
| public XMLJUnitResultFormatter() | |||||
| { | |||||
| } | |||||
| private static DocumentBuilder getDocumentBuilder() | |||||
| { | |||||
| try | |||||
| { | |||||
| return DocumentBuilderFactory.newInstance().newDocumentBuilder(); | |||||
| } | |||||
| catch( Exception exc ) | |||||
| { | |||||
| throw new ExceptionInInitializerError( exc ); | |||||
| } | |||||
| } | |||||
| public void setOutput( OutputStream out ) | |||||
| { | |||||
| this.out = out; | |||||
| } | |||||
| public void setSystemError( String out ) | |||||
| { | |||||
| formatOutput( SYSTEM_ERR, out ); | |||||
| } | |||||
| public void setSystemOutput( String out ) | |||||
| { | |||||
| formatOutput( SYSTEM_OUT, 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( 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( FAILURE, 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 ) | |||||
| { | |||||
| Element currentTest = (Element)testElements.get( test ); | |||||
| Long l = (Long)testStarts.get( test ); | |||||
| currentTest.setAttribute( ATTR_TIME, | |||||
| "" + ( ( System.currentTimeMillis() - l.longValue() ) | |||||
| / 1000.0 ) ); | |||||
| } | |||||
| /** | |||||
| * The whole testsuite ended. | |||||
| * | |||||
| * @param suite Description of Parameter | |||||
| * @exception TaskException Description of Exception | |||||
| */ | |||||
| public void endTestSuite( JUnitTest suite ) | |||||
| throws TaskException | |||||
| { | |||||
| rootElement.setAttribute( ATTR_TESTS, "" + suite.runCount() ); | |||||
| rootElement.setAttribute( ATTR_FAILURES, "" + suite.failureCount() ); | |||||
| rootElement.setAttribute( ATTR_ERRORS, "" + suite.errorCount() ); | |||||
| rootElement.setAttribute( ATTR_TIME, "" + ( suite.getRunTime() / 1000.0 ) ); | |||||
| if( out != null ) | |||||
| { | |||||
| Writer wri = null; | |||||
| try | |||||
| { | |||||
| wri = new OutputStreamWriter( out, "UTF8" ); | |||||
| wri.write( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" ); | |||||
| ( new DOMElementWriter() ).write( rootElement, wri, 0, " " ); | |||||
| wri.flush(); | |||||
| } | |||||
| catch( IOException exc ) | |||||
| { | |||||
| throw new TaskException( "Unable to write log file", exc ); | |||||
| } | |||||
| finally | |||||
| { | |||||
| if( out != System.out && out != System.err ) | |||||
| { | |||||
| if( wri != null ) | |||||
| { | |||||
| try | |||||
| { | |||||
| wri.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() ) ); | |||||
| Element currentTest = doc.createElement( TESTCASE ); | |||||
| currentTest.setAttribute( ATTR_NAME, | |||||
| JUnitVersionHelper.getTestCaseName( t ) ); | |||||
| rootElement.appendChild( currentTest ); | |||||
| testElements.put( t, currentTest ); | |||||
| } | |||||
| /** | |||||
| * The whole testsuite started. | |||||
| * | |||||
| * @param suite Description of Parameter | |||||
| */ | |||||
| public void startTestSuite( JUnitTest suite ) | |||||
| { | |||||
| doc = getDocumentBuilder().newDocument(); | |||||
| rootElement = doc.createElement( TESTSUITE ); | |||||
| rootElement.setAttribute( ATTR_NAME, suite.getName() ); | |||||
| // Output properties | |||||
| Element propsElement = doc.createElement( PROPERTIES ); | |||||
| rootElement.appendChild( propsElement ); | |||||
| Properties props = suite.getProperties(); | |||||
| if( props != null ) | |||||
| { | |||||
| final Iterator e = props.keySet().iterator(); | |||||
| while( e.hasNext() ) | |||||
| { | |||||
| final String name = (String)e.next(); | |||||
| final String value = props.getProperty( name ); | |||||
| final Element propElement = doc.createElement( PROPERTY ); | |||||
| propElement.setAttribute( ATTR_NAME, name ); | |||||
| propElement.setAttribute( ATTR_VALUE, value ); | |||||
| propsElement.appendChild( propElement ); | |||||
| } | |||||
| } | |||||
| } | |||||
| private void formatError( String type, Test test, Throwable t ) | |||||
| { | |||||
| if( test != null ) | |||||
| { | |||||
| endTest( test ); | |||||
| } | |||||
| Element nested = doc.createElement( type ); | |||||
| Element currentTest = null; | |||||
| if( test != null ) | |||||
| { | |||||
| currentTest = (Element)testElements.get( test ); | |||||
| } | |||||
| else | |||||
| { | |||||
| currentTest = rootElement; | |||||
| } | |||||
| currentTest.appendChild( nested ); | |||||
| String message = t.getMessage(); | |||||
| if( message != null && message.length() > 0 ) | |||||
| { | |||||
| nested.setAttribute( ATTR_MESSAGE, t.getMessage() ); | |||||
| } | |||||
| nested.setAttribute( ATTR_TYPE, t.getClass().getName() ); | |||||
| String strace = JUnitTestRunner.getFilteredTrace( t ); | |||||
| Text trace = doc.createTextNode( strace ); | |||||
| nested.appendChild( trace ); | |||||
| } | |||||
| private void formatOutput( String type, String output ) | |||||
| { | |||||
| Element nested = doc.createElement( type ); | |||||
| rootElement.appendChild( nested ); | |||||
| Text content = doc.createTextNode( output ); | |||||
| nested.appendChild( content ); | |||||
| } | |||||
| }// XMLJUnitResultFormatter | |||||
| @@ -1,336 +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.io.OutputStream; | |||||
| import java.io.OutputStreamWriter; | |||||
| import java.io.PrintWriter; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Iterator; | |||||
| import javax.xml.parsers.DocumentBuilder; | |||||
| import javax.xml.parsers.DocumentBuilderFactory; | |||||
| import org.apache.avalon.framework.ExceptionUtil; | |||||
| import org.apache.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.api.TaskContext; | |||||
| import org.apache.myrmidon.framework.FileSet; | |||||
| import org.apache.tools.todo.types.DirectoryScanner; | |||||
| import org.apache.tools.todo.types.ScannerUtil; | |||||
| import org.w3c.dom.Document; | |||||
| import org.w3c.dom.Element; | |||||
| import org.xml.sax.SAXException; | |||||
| /** | |||||
| * <p> | |||||
| * | |||||
| * This is an helper class that will aggregate all testsuites under a specific | |||||
| * directory and create a new single document. It is not particulary clean but | |||||
| * should be helpful while I am thinking about another technique. <p> | |||||
| * | |||||
| * The main problem is due to the fact that a JVM can be forked for a testcase | |||||
| * thus making it impossible to aggregate all testcases since the listener is | |||||
| * (obviously) in the forked JVM. A solution could be to write a TestListener | |||||
| * that will receive events from the TestRunner via sockets. This is IMHO the | |||||
| * simplest way to do it to avoid this file hacking thing. | |||||
| * | |||||
| * @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
| */ | |||||
| public class XMLResultAggregator | |||||
| extends AbstractTask | |||||
| implements XMLConstants | |||||
| { | |||||
| /** | |||||
| * the default directory: <tt>.</tt> . It is resolved from the project | |||||
| * directory | |||||
| */ | |||||
| public final static String DEFAULT_DIR = "."; | |||||
| /** | |||||
| * the default file name: <tt>TESTS-TestSuites.xml</tt> | |||||
| */ | |||||
| public final static String DEFAULT_FILENAME = "TESTS-TestSuites.xml"; | |||||
| /** | |||||
| * the list of all filesets, that should contains the xml to aggregate | |||||
| */ | |||||
| protected ArrayList filesets = new ArrayList(); | |||||
| protected ArrayList transformers = new ArrayList(); | |||||
| /** | |||||
| * the directory to write the file to | |||||
| */ | |||||
| protected File toDir; | |||||
| /** | |||||
| * the name of the result file | |||||
| */ | |||||
| protected String toFile; | |||||
| /** | |||||
| * Create a new document builder. Will issue an <tt> | |||||
| * ExceptionInitializerError</tt> if something is going wrong. It is fatal | |||||
| * anyway. | |||||
| * | |||||
| * @return a new document builder to create a DOM | |||||
| * @todo factorize this somewhere else. It is duplicated code. | |||||
| */ | |||||
| private static DocumentBuilder getDocumentBuilder() | |||||
| { | |||||
| try | |||||
| { | |||||
| return DocumentBuilderFactory.newInstance().newDocumentBuilder(); | |||||
| } | |||||
| catch( Exception exc ) | |||||
| { | |||||
| throw new ExceptionInInitializerError( exc ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Set the destination directory where the results should be written. If not | |||||
| * set if will use {@link #DEFAULT_DIR}. When given a relative directory it | |||||
| * will resolve it from the project directory. | |||||
| * | |||||
| * @param value the directory where to write the results, absolute or | |||||
| * relative. | |||||
| */ | |||||
| public void setTodir( File value ) | |||||
| { | |||||
| toDir = value; | |||||
| } | |||||
| /** | |||||
| * Set the name of the file aggregating the results. It must be relative | |||||
| * from the <tt>todir</tt> attribute. If not set it will use {@link | |||||
| * #DEFAULT_FILENAME} | |||||
| * | |||||
| * @param value the name of the file. | |||||
| * @see #setTodir(File) | |||||
| */ | |||||
| public void setTofile( String value ) | |||||
| { | |||||
| toFile = value; | |||||
| } | |||||
| /** | |||||
| * Add a new fileset containing the xml results to aggregate | |||||
| * | |||||
| * @param fs the new fileset of xml results. | |||||
| */ | |||||
| public void addFileSet( FileSet fs ) | |||||
| { | |||||
| filesets.add( fs ); | |||||
| } | |||||
| public AggregateTransformer createReport() | |||||
| { | |||||
| AggregateTransformer transformer = new AggregateTransformer( getContext() ); | |||||
| transformers.add( transformer ); | |||||
| return transformer; | |||||
| } | |||||
| /** | |||||
| * Aggregate all testsuites into a single document and write it to the | |||||
| * specified directory and file. | |||||
| * | |||||
| * @throws TaskException thrown if there is a serious error while writing | |||||
| * the document. | |||||
| */ | |||||
| public void execute() | |||||
| throws TaskException | |||||
| { | |||||
| final Element rootElement = createDocument(); | |||||
| File destFile = getDestinationFile(); | |||||
| // write the document | |||||
| try | |||||
| { | |||||
| writeDOMTree( rootElement.getOwnerDocument(), destFile ); | |||||
| } | |||||
| catch( IOException e ) | |||||
| { | |||||
| throw new TaskException( "Unable to write test aggregate to '" + destFile + "'", e ); | |||||
| } | |||||
| // apply transformation | |||||
| Iterator enum = transformers.iterator(); | |||||
| while( enum.hasNext() ) | |||||
| { | |||||
| AggregateTransformer transformer = | |||||
| (AggregateTransformer)enum.next(); | |||||
| transformer.setXmlDocument( rootElement.getOwnerDocument() ); | |||||
| transformer.transform(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Get the full destination file where to write the result. It is made of | |||||
| * the <tt>todir</tt> and <tt>tofile</tt> attributes. | |||||
| * | |||||
| * @return the destination file where should be written the result file. | |||||
| */ | |||||
| protected File getDestinationFile() | |||||
| throws TaskException | |||||
| { | |||||
| if( toFile == null ) | |||||
| { | |||||
| toFile = DEFAULT_FILENAME; | |||||
| } | |||||
| if( toDir == null ) | |||||
| { | |||||
| toDir = getContext().resolveFile( DEFAULT_DIR ); | |||||
| } | |||||
| return new File( toDir, toFile ); | |||||
| } | |||||
| /** | |||||
| * Get all <code>.xml</code> files in the fileset. | |||||
| * | |||||
| * @return all files in the fileset that end with a '.xml'. | |||||
| */ | |||||
| protected File[] getFiles() | |||||
| throws TaskException | |||||
| { | |||||
| final ArrayList v = new ArrayList(); | |||||
| final int size = filesets.size(); | |||||
| for( int i = 0; i < size; i++ ) | |||||
| { | |||||
| final FileSet fileSet = (FileSet)filesets.get( i ); | |||||
| final DirectoryScanner scanner = ScannerUtil.getDirectoryScanner( fileSet ); | |||||
| scanner.scan(); | |||||
| final String[] includes = scanner.getIncludedFiles(); | |||||
| for( int j = 0; j < includes.length; j++ ) | |||||
| { | |||||
| final String pathname = includes[ j ]; | |||||
| if( pathname.endsWith( ".xml" ) ) | |||||
| { | |||||
| File file = new File( scanner.getBasedir(), pathname ); | |||||
| file = getContext().resolveFile( file.getPath() ); | |||||
| v.add( file ); | |||||
| } | |||||
| } | |||||
| } | |||||
| return (File[])v.toArray( new File[ v.size() ] ); | |||||
| } | |||||
| /** | |||||
| * <p> | |||||
| * | |||||
| * Add a new testsuite node to the document. The main difference is that it | |||||
| * split the previous fully qualified name into a package and a name. <p> | |||||
| * | |||||
| * For example: <tt>org.apache.Whatever</tt> will be split into <tt> | |||||
| * org.apache</tt> and <tt>Whatever</tt> . | |||||
| * | |||||
| * @param root the root element to which the <tt>testsuite</tt> node should | |||||
| * be appended. | |||||
| * @param testsuite the element to append to the given root. It will | |||||
| * slightly modify the original node to change the name attribute and | |||||
| * add a package one. | |||||
| */ | |||||
| protected void addTestSuite( Element root, Element testsuite ) | |||||
| { | |||||
| String fullclassname = testsuite.getAttribute( ATTR_NAME ); | |||||
| int pos = fullclassname.lastIndexOf( '.' ); | |||||
| // a missing . might imply no package at all. Don't get fooled. | |||||
| String pkgName = ( pos == -1 ) ? "" : fullclassname.substring( 0, pos ); | |||||
| String classname = ( pos == -1 ) ? fullclassname : fullclassname.substring( pos + 1 ); | |||||
| Element copy = (Element)DOMUtil.importNode( root, testsuite ); | |||||
| // modify the name attribute and set the package | |||||
| copy.setAttribute( ATTR_NAME, classname ); | |||||
| copy.setAttribute( ATTR_PACKAGE, pkgName ); | |||||
| } | |||||
| /** | |||||
| * <p> | |||||
| * | |||||
| * Create a DOM tree. Has 'testsuites' as firstchild and aggregates all | |||||
| * testsuite results that exists in the base directory. | |||||
| * | |||||
| * @return the root element of DOM tree that aggregates all testsuites. | |||||
| */ | |||||
| protected Element createDocument() | |||||
| throws TaskException | |||||
| { | |||||
| // create the dom tree | |||||
| DocumentBuilder builder = getDocumentBuilder(); | |||||
| Document doc = builder.newDocument(); | |||||
| Element rootElement = doc.createElement( TESTSUITES ); | |||||
| doc.appendChild( rootElement ); | |||||
| // get all files and add them to the document | |||||
| final File[] files = getFiles(); | |||||
| for( int i = 0; i < files.length; i++ ) | |||||
| { | |||||
| try | |||||
| { | |||||
| getContext().debug( "Parsing file: '" + files[ i ] + "'" ); | |||||
| //XXX there seems to be a bug in xerces 1.3.0 that doesn't like file object | |||||
| // will investigate later. It does not use the given directory but | |||||
| // the vm dir instead ? Works fine with crimson. | |||||
| Document testsuiteDoc = builder.parse( "file:///" + files[ i ].getAbsolutePath() ); | |||||
| Element elem = testsuiteDoc.getDocumentElement(); | |||||
| // make sure that this is REALLY a testsuite. | |||||
| if( TESTSUITE.equals( elem.getNodeName() ) ) | |||||
| { | |||||
| addTestSuite( rootElement, elem ); | |||||
| } | |||||
| else | |||||
| { | |||||
| // issue a warning. | |||||
| getContext().warn( "the file " + files[ i ] + " is not a valid testsuite XML document" ); | |||||
| } | |||||
| } | |||||
| catch( SAXException e ) | |||||
| { | |||||
| // a testcase might have failed and write a zero-length document, | |||||
| // It has already failed, but hey.... mm. just put a warning | |||||
| getContext().warn( "The file " + files[ i ] + " is not a valid XML document. It is possibly corrupted." ); | |||||
| getContext().debug( ExceptionUtil.printStackTrace( e ) ); | |||||
| } | |||||
| catch( IOException e ) | |||||
| { | |||||
| getContext().error( "Error while accessing file " + files[ i ] + ": " + e.getMessage() ); | |||||
| } | |||||
| } | |||||
| return rootElement; | |||||
| } | |||||
| //----- from now, the methods are all related to DOM tree manipulation | |||||
| /** | |||||
| * Write the DOM tree to a file. | |||||
| * | |||||
| * @param doc the XML document to dump to disk. | |||||
| * @param file the filename to write the document to. Should obviouslly be a | |||||
| * .xml file. | |||||
| * @throws IOException thrown if there is an error while writing the | |||||
| * content. | |||||
| */ | |||||
| protected void writeDOMTree( Document doc, File file ) | |||||
| throws IOException | |||||
| { | |||||
| OutputStream out = new FileOutputStream( file ); | |||||
| PrintWriter wri = new PrintWriter( new OutputStreamWriter( out, "UTF8" ) ); | |||||
| wri.write( "<?xml version=\"1.0\"?>\n" ); | |||||
| ( new DOMElementWriter() ).write( doc.getDocumentElement(), wri, 0, " " ); | |||||
| wri.flush(); | |||||
| wri.close(); | |||||
| // writers do not throw exceptions, so check for them. | |||||
| if( wri.checkError() ) | |||||
| { | |||||
| throw new IOException( "Error while writing DOM content" ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,38 +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 org.apache.xalan.xslt.XSLTInputSource; | |||||
| import org.apache.xalan.xslt.XSLTProcessor; | |||||
| import org.apache.xalan.xslt.XSLTProcessorFactory; | |||||
| import org.apache.xalan.xslt.XSLTResultTarget; | |||||
| /** | |||||
| * Xalan 1 executor. It will need a lot of things in the classpath: xerces for | |||||
| * the serialization, xalan and bsf for the extension. | |||||
| * | |||||
| * @author RT | |||||
| * @todo do everything via reflection to avoid compile problems ? | |||||
| */ | |||||
| public class Xalan1Executor extends XalanExecutor | |||||
| { | |||||
| void execute() | |||||
| throws Exception | |||||
| { | |||||
| XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); | |||||
| // need to quote otherwise it breaks because of "extra illegal tokens" | |||||
| processor.setStylesheetParam( "output.dir", "'" + caller.getToDir().getAbsolutePath() + "'" ); | |||||
| XSLTInputSource xml_src = new XSLTInputSource( caller.getDocument() ); | |||||
| String system_id = caller.getStylesheetSystemId(); | |||||
| XSLTInputSource xsl_src = new XSLTInputSource( system_id ); | |||||
| OutputStream os = getOutputStream(); | |||||
| XSLTResultTarget target = new XSLTResultTarget( os ); | |||||
| processor.process( xml_src, xsl_src, target ); | |||||
| } | |||||
| } | |||||
| @@ -1,40 +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 javax.xml.transform.Result; | |||||
| import javax.xml.transform.Source; | |||||
| import javax.xml.transform.Transformer; | |||||
| import javax.xml.transform.TransformerFactory; | |||||
| import javax.xml.transform.dom.DOMSource; | |||||
| import javax.xml.transform.stream.StreamResult; | |||||
| import javax.xml.transform.stream.StreamSource; | |||||
| /** | |||||
| * Xalan executor via JAXP. Nothing special must exists in the classpath besides | |||||
| * of course, a parser, jaxp and xalan. | |||||
| * | |||||
| * @author RT | |||||
| */ | |||||
| public class Xalan2Executor extends XalanExecutor | |||||
| { | |||||
| void execute() | |||||
| throws Exception | |||||
| { | |||||
| TransformerFactory tfactory = TransformerFactory.newInstance(); | |||||
| String system_id = caller.getStylesheetSystemId(); | |||||
| Source xsl_src = new StreamSource( system_id ); | |||||
| Transformer tformer = tfactory.newTransformer( xsl_src ); | |||||
| Source xml_src = new DOMSource( caller.getDocument() ); | |||||
| OutputStream os = getOutputStream(); | |||||
| tformer.setParameter( "output.dir", caller.getToDir().getAbsolutePath() ); | |||||
| Result result = new StreamResult( os ); | |||||
| tformer.transform( xml_src, result ); | |||||
| } | |||||
| } | |||||
| @@ -1,127 +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.ByteArrayOutputStream; | |||||
| import java.io.File; | |||||
| import java.io.FileOutputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.OutputStream; | |||||
| import java.lang.reflect.Field; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| /** | |||||
| * Command class that encapsulate specific behavior for each Xalan version. The | |||||
| * right executor will be instantiated at runtime via class lookup. For | |||||
| * instance, it will check first for Xalan2, then for Xalan1. | |||||
| * | |||||
| * @author RT | |||||
| */ | |||||
| abstract class XalanExecutor | |||||
| { | |||||
| /** | |||||
| * the transformer caller | |||||
| */ | |||||
| protected AggregateTransformer caller; | |||||
| /** | |||||
| * Create a valid Xalan executor. It checks first if Xalan2 is present, if | |||||
| * not it checks for xalan1. If none is available, it fails. | |||||
| * | |||||
| * @param caller object containing the transformation information. | |||||
| * @return Description of the Returned Value | |||||
| * @throws TaskException thrown if it could not find a valid xalan | |||||
| * executor. | |||||
| */ | |||||
| static XalanExecutor newInstance( AggregateTransformer caller ) | |||||
| throws TaskException | |||||
| { | |||||
| Class procVersion = null; | |||||
| XalanExecutor executor = null; | |||||
| try | |||||
| { | |||||
| procVersion = Class.forName( "org.apache.xalan.processor.XSLProcessorVersion" ); | |||||
| executor = new Xalan2Executor(); | |||||
| } | |||||
| catch( Exception xalan2missing ) | |||||
| { | |||||
| try | |||||
| { | |||||
| procVersion = Class.forName( "org.apache.xalan.xslt.XSLProcessorVersion" ); | |||||
| executor = (XalanExecutor)Class.forName( | |||||
| "org.apache.tools.ant.taskdefs.optional.junit.Xalan1Executor" ).newInstance(); | |||||
| } | |||||
| catch( Exception xalan1missing ) | |||||
| { | |||||
| throw new TaskException( "Could not find xalan2 nor xalan1 in the classpath. Check http://xml.apache.org/xalan-j" ); | |||||
| } | |||||
| } | |||||
| String version = getXalanVersion( procVersion ); | |||||
| //caller.task.getLogger().info( "Using Xalan version: " + version ); | |||||
| executor.setCaller( caller ); | |||||
| return executor; | |||||
| } | |||||
| /** | |||||
| * pretty useful data (Xalan version information) to display. | |||||
| * | |||||
| * @param procVersion Description of Parameter | |||||
| * @return The XalanVersion value | |||||
| */ | |||||
| private static String getXalanVersion( Class procVersion ) | |||||
| { | |||||
| try | |||||
| { | |||||
| Field f = procVersion.getField( "S_VERSION" ); | |||||
| return f.get( null ).toString(); | |||||
| } | |||||
| catch( Exception e ) | |||||
| { | |||||
| return "?"; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * get the appropriate stream based on the format (frames/noframes) | |||||
| * | |||||
| * @return The OutputStream value | |||||
| * @exception IOException Description of Exception | |||||
| */ | |||||
| protected OutputStream getOutputStream() | |||||
| throws IOException | |||||
| { | |||||
| if( caller.FRAMES.equals( caller.getFormat() ) ) | |||||
| { | |||||
| // dummy output for the framed report | |||||
| // it's all done by extension... | |||||
| return new ByteArrayOutputStream(); | |||||
| } | |||||
| else | |||||
| { | |||||
| return new FileOutputStream( new File( caller.getToDir(), "junit-noframes.html" ) ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * override to perform transformation | |||||
| * | |||||
| * @exception Exception Description of Exception | |||||
| */ | |||||
| abstract void execute() | |||||
| throws Exception; | |||||
| /** | |||||
| * set the caller for this object. | |||||
| * | |||||
| * @param caller The new Caller value | |||||
| */ | |||||
| private final void setCaller( AggregateTransformer caller ) | |||||
| { | |||||
| this.caller = caller; | |||||
| } | |||||
| } | |||||
| @@ -1,117 +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.manifest; | |||||
| /** | |||||
| * Class to hold manifest attributes | |||||
| * | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @author Conor MacNeill | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class Attribute | |||||
| { | |||||
| /** | |||||
| * The attribute's name | |||||
| */ | |||||
| private String m_name; | |||||
| /** | |||||
| * The attribute's value | |||||
| */ | |||||
| private String m_value; | |||||
| /** | |||||
| * Construct an empty attribute | |||||
| */ | |||||
| public Attribute() | |||||
| { | |||||
| } | |||||
| /** | |||||
| * Construct a manifest by specifying its name and value | |||||
| * | |||||
| * @param name the attribute's name | |||||
| * @param value the Attribute's value | |||||
| */ | |||||
| public Attribute( final String name, final String value ) | |||||
| { | |||||
| m_name = name; | |||||
| m_value = value; | |||||
| } | |||||
| /** | |||||
| * Set the Attribute's name | |||||
| * | |||||
| * @param name the attribute's name | |||||
| */ | |||||
| public void setName( final String name ) | |||||
| { | |||||
| m_name = name; | |||||
| } | |||||
| /** | |||||
| * Set the Attribute's value | |||||
| * | |||||
| * @param value the attribute's value | |||||
| */ | |||||
| public void setValue( final String value ) | |||||
| { | |||||
| m_value = value; | |||||
| } | |||||
| /** | |||||
| * Get the Attribute's name | |||||
| * | |||||
| * @return the attribute's name. | |||||
| */ | |||||
| public String getName() | |||||
| { | |||||
| return m_name; | |||||
| } | |||||
| /** | |||||
| * Get the Attribute's value | |||||
| * | |||||
| * @return the attribute's value. | |||||
| */ | |||||
| public String getValue() | |||||
| { | |||||
| return m_value; | |||||
| } | |||||
| /** | |||||
| * Add a continuation line from the Manifest file When lines are too | |||||
| * long in a manifest, they are continued on the next line by starting | |||||
| * with a space. This method adds the continuation data to the attribute | |||||
| * value by skipping the first character. | |||||
| * | |||||
| * @param line The feature to be added to the Continuation attribute | |||||
| */ | |||||
| public void addContinuation( final String line ) | |||||
| { | |||||
| m_value += line.substring( 1 ); | |||||
| } | |||||
| public boolean equals( Object object ) | |||||
| { | |||||
| if( !( object instanceof Attribute ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| final Attribute other = (Attribute)object; | |||||
| final String name = other.m_name; | |||||
| return | |||||
| ( null != m_name && null != name && | |||||
| m_name.toLowerCase().equals( name.toLowerCase() ) && | |||||
| null != m_value && m_value.equals( other.m_value ) ); | |||||
| } | |||||
| } | |||||
| @@ -1,175 +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.manifest; | |||||
| import java.util.Collection; | |||||
| import java.util.Enumeration; | |||||
| import java.util.Hashtable; | |||||
| import java.util.Iterator; | |||||
| import java.util.Set; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| /** | |||||
| * Class to manage Manifest information | |||||
| * | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @author Conor MacNeill | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class Manifest | |||||
| { | |||||
| /** | |||||
| * The version of this manifest | |||||
| */ | |||||
| private String m_manifestVersion = ManifestUtil.DEFAULT_MANIFEST_VERSION; | |||||
| /** | |||||
| * The main section of this manifest | |||||
| */ | |||||
| private Section m_mainSection = new Section(); | |||||
| /** | |||||
| * The named sections of this manifest | |||||
| */ | |||||
| private Hashtable m_sections = new Hashtable(); | |||||
| public void setManifestVersion( final String manifestVersion ) | |||||
| { | |||||
| m_manifestVersion = manifestVersion; | |||||
| } | |||||
| public void setMainSection( final Section mainSection ) | |||||
| { | |||||
| m_mainSection = mainSection; | |||||
| } | |||||
| public void addAttribute( final Attribute attribute ) | |||||
| throws ManifestException | |||||
| { | |||||
| m_mainSection.addAttribute( attribute ); | |||||
| } | |||||
| public void addSection( final Section section ) | |||||
| throws ManifestException | |||||
| { | |||||
| if( section.getName() == null ) | |||||
| { | |||||
| final String message = "Sections must have a name"; | |||||
| throw new ManifestException( message ); | |||||
| } | |||||
| m_sections.put( section.getName().toLowerCase(), section ); | |||||
| } | |||||
| public String[] getSectionNames( final Manifest other ) | |||||
| { | |||||
| final Set keys = other.m_sections.keySet(); | |||||
| return (String[])keys.toArray( new String[ keys.size() ] ); | |||||
| } | |||||
| public String getManifestVersion() | |||||
| { | |||||
| return m_manifestVersion; | |||||
| } | |||||
| public Section getMainSection() | |||||
| { | |||||
| return m_mainSection; | |||||
| } | |||||
| public Section getSection( final String name ) | |||||
| { | |||||
| return (Section)m_sections.get( name ); | |||||
| } | |||||
| public Section[] getSections() | |||||
| { | |||||
| final Collection sections = m_sections.values(); | |||||
| return (Section[])sections.toArray( new Section[ sections.size() ] ); | |||||
| } | |||||
| /** | |||||
| * Merge the contents of the given manifest into this manifest | |||||
| * | |||||
| * @param other the Manifest to be merged with this one. | |||||
| * @throws org.apache.tools.todo.taskdefs.manifest.ManifestException if there is a problem merging the manfest | |||||
| * according to the Manifest spec. | |||||
| */ | |||||
| public void merge( final Manifest other ) | |||||
| throws ManifestException | |||||
| { | |||||
| if( other.m_manifestVersion != null ) | |||||
| { | |||||
| m_manifestVersion = other.m_manifestVersion; | |||||
| } | |||||
| m_mainSection.merge( other.m_mainSection ); | |||||
| mergeSections( other ); | |||||
| } | |||||
| public boolean equals( final Object object ) | |||||
| { | |||||
| if( !( object instanceof Manifest ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| final Manifest other = (Manifest)object; | |||||
| if( m_manifestVersion == null && other.m_manifestVersion != null ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| else if( !m_manifestVersion.equals( other.m_manifestVersion ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| if( m_sections.size() != other.m_sections.size() ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| if( !m_mainSection.equals( other.m_mainSection ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| final Iterator e = m_sections.values().iterator(); | |||||
| while( e.hasNext() ) | |||||
| { | |||||
| final Section section = (Section)e.next(); | |||||
| final String key = section.getName().toLowerCase(); | |||||
| final Section otherSection = (Section)other.m_sections.get( key ); | |||||
| if( !section.equals( otherSection ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| private void mergeSections( final Manifest other ) | |||||
| throws ManifestException | |||||
| { | |||||
| final String[] sections = getSectionNames( other ); | |||||
| for( int i = 0; i < sections.length; i++ ) | |||||
| { | |||||
| final String sectionName = sections[ i ]; | |||||
| final Section section = getSection( sectionName ); | |||||
| final Section otherSection = other.getSection( sectionName ); | |||||
| if( section == null ) | |||||
| { | |||||
| m_sections.put( sectionName.toLowerCase(), otherSection ); | |||||
| } | |||||
| else | |||||
| { | |||||
| section.merge( otherSection ); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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.manifest; | |||||
| /** | |||||
| * ManifestException is thrown when there is a problem parsing, generating or | |||||
| * handling a Manifest. | |||||
| * | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class ManifestException | |||||
| extends Exception | |||||
| { | |||||
| /** | |||||
| * The Throwable that caused this exception to be thrown. | |||||
| */ | |||||
| private final Throwable m_throwable; | |||||
| /** | |||||
| * Basic constructor for exception that does not specify a message | |||||
| */ | |||||
| public ManifestException() | |||||
| { | |||||
| this( "", null ); | |||||
| } | |||||
| /** | |||||
| * Basic constructor with a message | |||||
| * | |||||
| * @param message the message | |||||
| */ | |||||
| public ManifestException( final String message ) | |||||
| { | |||||
| this( message, null ); | |||||
| } | |||||
| /** | |||||
| * Constructor that builds cascade so that other exception information can be retained. | |||||
| * | |||||
| * @param message the message | |||||
| * @param throwable the throwable | |||||
| */ | |||||
| public ManifestException( final String message, final Throwable throwable ) | |||||
| { | |||||
| super( message ); | |||||
| m_throwable = throwable; | |||||
| } | |||||
| /** | |||||
| * Retrieve root cause of the exception. | |||||
| * | |||||
| * @return the root cause | |||||
| */ | |||||
| public final Throwable getCause() | |||||
| { | |||||
| return m_throwable; | |||||
| } | |||||
| } | |||||
| @@ -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.manifest; | |||||
| import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
| /** | |||||
| * Helper class for Manifest's mode attribute. | |||||
| * | |||||
| * @author Conor MacNeill | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class ManifestMode | |||||
| extends EnumeratedAttribute | |||||
| { | |||||
| public String[] getValues() | |||||
| { | |||||
| return new String[]{"update", "replace"}; | |||||
| } | |||||
| } | |||||
| @@ -1,198 +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.manifest; | |||||
| import java.io.File; | |||||
| import java.io.FileReader; | |||||
| import java.io.FileWriter; | |||||
| import java.io.IOException; | |||||
| import java.io.PrintWriter; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Iterator; | |||||
| import org.apache.avalon.excalibur.io.IOUtil; | |||||
| import org.apache.myrmidon.api.AbstractTask; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.tools.todo.taskdefs.manifest.Manifest; | |||||
| import org.apache.tools.todo.taskdefs.manifest.Section; | |||||
| /** | |||||
| * Class to manage Manifest information | |||||
| * | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @author Conor MacNeill | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class ManifestTask | |||||
| extends AbstractTask | |||||
| { | |||||
| private File m_destFile; | |||||
| private ManifestMode m_mode; | |||||
| private Manifest m_manifest = new Manifest(); | |||||
| /** | |||||
| * Construct an empty manifest | |||||
| */ | |||||
| public ManifestTask() | |||||
| throws TaskException | |||||
| { | |||||
| m_mode = new ManifestMode(); | |||||
| m_mode.setValue( "replace" ); | |||||
| } | |||||
| /** | |||||
| * The name of the manifest file to write. | |||||
| */ | |||||
| public void setDestFile( final File destFile ) | |||||
| { | |||||
| m_destFile = destFile; | |||||
| } | |||||
| /** | |||||
| * Shall we update or replace an existing manifest? | |||||
| */ | |||||
| public void setMode( final ManifestMode mode ) | |||||
| { | |||||
| m_mode = mode; | |||||
| } | |||||
| public void setManifestVersion( String manifestVersion ) | |||||
| { | |||||
| m_manifest.setManifestVersion( manifestVersion ); | |||||
| } | |||||
| public void addMainSection( Section mainSection ) | |||||
| throws Exception | |||||
| { | |||||
| m_manifest.setMainSection( mainSection ); | |||||
| } | |||||
| /** | |||||
| * Get the warnings for this manifest. | |||||
| * | |||||
| * @return an enumeration of warning strings | |||||
| */ | |||||
| public Iterator getWarnings() | |||||
| { | |||||
| ArrayList warnings = new ArrayList(); | |||||
| for( Iterator e2 = m_manifest.getMainSection().getWarnings(); e2.hasNext(); ) | |||||
| { | |||||
| warnings.add( e2.next() ); | |||||
| } | |||||
| final Section[] sections = m_manifest.getSections(); | |||||
| for( int i = 0; i < sections.length; i++ ) | |||||
| { | |||||
| final Section section = sections[ i ]; | |||||
| for( Iterator e2 = section.getWarnings(); e2.hasNext(); ) | |||||
| { | |||||
| warnings.add( e2.next() ); | |||||
| } | |||||
| } | |||||
| return warnings.iterator(); | |||||
| } | |||||
| public void addAttribute( final Attribute attribute ) | |||||
| throws ManifestException, TaskException | |||||
| { | |||||
| m_manifest.addAttribute( attribute ); | |||||
| } | |||||
| public void addSection( final Section section ) | |||||
| throws TaskException | |||||
| { | |||||
| try | |||||
| { | |||||
| m_manifest.addSection( section ); | |||||
| } | |||||
| catch( final ManifestException me ) | |||||
| { | |||||
| throw new TaskException( me.getMessage(), me ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Create or update the Manifest when used as a task. | |||||
| * | |||||
| * @exception org.apache.myrmidon.api.TaskException Description of Exception | |||||
| */ | |||||
| public void execute() | |||||
| throws TaskException | |||||
| { | |||||
| if( null == m_destFile ) | |||||
| { | |||||
| throw new TaskException( "the file attribute is required" ); | |||||
| } | |||||
| Manifest toWrite = getDefaultManifest(); | |||||
| if( m_mode.getValue().equals( "update" ) && m_destFile.exists() ) | |||||
| { | |||||
| FileReader f = null; | |||||
| try | |||||
| { | |||||
| f = new FileReader( m_destFile ); | |||||
| final Manifest other = ManifestUtil.buildManifest( f ); | |||||
| toWrite.merge( other ); | |||||
| } | |||||
| catch( ManifestException m ) | |||||
| { | |||||
| throw new TaskException( "Existing manifest " + m_destFile | |||||
| + " is invalid", m ); | |||||
| } | |||||
| catch( IOException e ) | |||||
| { | |||||
| throw new | |||||
| TaskException( "Failed to read " + m_destFile, e ); | |||||
| } | |||||
| finally | |||||
| { | |||||
| IOUtil.shutdownReader( f ); | |||||
| } | |||||
| } | |||||
| try | |||||
| { | |||||
| toWrite.merge( m_manifest ); | |||||
| } | |||||
| catch( ManifestException m ) | |||||
| { | |||||
| throw new TaskException( "Manifest is invalid", m ); | |||||
| } | |||||
| PrintWriter w = null; | |||||
| try | |||||
| { | |||||
| w = new PrintWriter( new FileWriter( m_destFile ) ); | |||||
| ManifestUtil.write( toWrite, w ); | |||||
| } | |||||
| catch( IOException e ) | |||||
| { | |||||
| throw new TaskException( "Failed to write " + m_destFile, e ); | |||||
| } | |||||
| finally | |||||
| { | |||||
| IOUtil.shutdownWriter( w ); | |||||
| } | |||||
| } | |||||
| private Manifest getDefaultManifest() | |||||
| throws TaskException | |||||
| { | |||||
| try | |||||
| { | |||||
| return ManifestUtil.getDefaultManifest(); | |||||
| } | |||||
| catch( final ManifestException me ) | |||||
| { | |||||
| throw new TaskException( me.getMessage(), me ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,242 +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.manifest; | |||||
| import java.io.BufferedReader; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.InputStreamReader; | |||||
| import java.io.PrintWriter; | |||||
| import java.io.Reader; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.util.jar.Attributes; | |||||
| import org.apache.tools.todo.taskdefs.manifest.Manifest; | |||||
| import org.apache.tools.todo.taskdefs.manifest.Section; | |||||
| import org.apache.tools.todo.taskdefs.manifest.Attribute; | |||||
| /** | |||||
| * Utility methods for manifest stuff. | |||||
| * | |||||
| * @author Conor MacNeill | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public final class ManifestUtil | |||||
| { | |||||
| /** | |||||
| * The Name Attribute is the first in a named section | |||||
| */ | |||||
| public final static String ATTRIBUTE_NAME = "Name"; | |||||
| /** | |||||
| * The From Header is disallowed in a Manifest | |||||
| */ | |||||
| public final static String ATTRIBUTE_FROM = "From"; | |||||
| /** | |||||
| * The Class-Path Header is special - it can be duplicated | |||||
| */ | |||||
| public final static String ATTRIBUTE_CLASSPATH = Attributes.Name.CLASS_PATH.toString(); | |||||
| /** | |||||
| * Default Manifest version if one is not specified | |||||
| */ | |||||
| public final static String DEFAULT_MANIFEST_VERSION = "1.0"; | |||||
| /** | |||||
| * The max length of a line in a Manifest | |||||
| */ | |||||
| public final static int MAX_LINE_LENGTH = 70; | |||||
| public static Attribute buildAttribute( final String line ) | |||||
| throws ManifestException | |||||
| { | |||||
| final Attribute attribute = new Attribute(); | |||||
| parse( attribute, line ); | |||||
| return attribute; | |||||
| } | |||||
| public static Manifest buildManifest( final Reader reader ) | |||||
| throws ManifestException, IOException | |||||
| { | |||||
| final Manifest manifest = new Manifest(); | |||||
| BufferedReader bufferedReader = new BufferedReader( reader ); | |||||
| // This should be the manifest version | |||||
| final Section mainSection = manifest.getMainSection(); | |||||
| String nextSectionName = mainSection.read( bufferedReader ); | |||||
| final String readManifestVersion = | |||||
| mainSection.getAttributeValue( Attributes.Name.MANIFEST_VERSION.toString() ); | |||||
| if( readManifestVersion != null ) | |||||
| { | |||||
| manifest.setManifestVersion( readManifestVersion ); | |||||
| mainSection.removeAttribute( Attributes.Name.MANIFEST_VERSION.toString() ); | |||||
| } | |||||
| String line = null; | |||||
| while( ( line = bufferedReader.readLine() ) != null ) | |||||
| { | |||||
| if( line.length() == 0 ) | |||||
| { | |||||
| continue; | |||||
| } | |||||
| Section section = new Section(); | |||||
| if( nextSectionName == null ) | |||||
| { | |||||
| Attribute sectionName = ManifestUtil.buildAttribute( line ); | |||||
| if( !sectionName.getName().equalsIgnoreCase( ManifestUtil.ATTRIBUTE_NAME ) ) | |||||
| { | |||||
| throw new ManifestException( "Manifest sections should start with a \"" + ManifestUtil.ATTRIBUTE_NAME + | |||||
| "\" attribute and not \"" + sectionName.getName() + "\"" ); | |||||
| } | |||||
| nextSectionName = sectionName.getValue(); | |||||
| } | |||||
| else | |||||
| { | |||||
| // we have already started reading this section | |||||
| // this line is the first attribute. set it and then let the normal | |||||
| // read handle the rest | |||||
| Attribute firstAttribute = ManifestUtil.buildAttribute( line ); | |||||
| section.addAttributeAndCheck( firstAttribute ); | |||||
| } | |||||
| section.setName( nextSectionName ); | |||||
| nextSectionName = section.read( bufferedReader ); | |||||
| manifest.addSection( section ); | |||||
| } | |||||
| return manifest; | |||||
| } | |||||
| /** | |||||
| * Construct a manifest from Ant's default manifest file. | |||||
| */ | |||||
| public static Manifest getDefaultManifest() | |||||
| throws ManifestException | |||||
| { | |||||
| try | |||||
| { | |||||
| final InputStream input = getInputStream(); | |||||
| final InputStreamReader reader = getReader( input ); | |||||
| return buildManifest( reader ); | |||||
| } | |||||
| catch( final IOException ioe ) | |||||
| { | |||||
| throw new ManifestException( "Unable to read default manifest", ioe ); | |||||
| } | |||||
| } | |||||
| private static InputStream getInputStream() | |||||
| throws ManifestException | |||||
| { | |||||
| final String location = "default.mf"; | |||||
| final InputStream input = ManifestUtil.class.getResourceAsStream( location ); | |||||
| if( null == input ) | |||||
| { | |||||
| throw new ManifestException( "Could not find default manifest: " + location ); | |||||
| } | |||||
| return input; | |||||
| } | |||||
| private static InputStreamReader getReader( final InputStream input ) | |||||
| { | |||||
| try | |||||
| { | |||||
| return new InputStreamReader( input, "ASCII" ); | |||||
| } | |||||
| catch( final UnsupportedEncodingException uee ) | |||||
| { | |||||
| return new InputStreamReader( input ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Parse a line into name and value pairs | |||||
| * | |||||
| * @param line the line to be parsed | |||||
| * @throws org.apache.tools.todo.taskdefs.manifest.ManifestException if the line does not contain a colon | |||||
| * separating the name and value | |||||
| */ | |||||
| public static void parse( final Attribute attribute, final String line ) | |||||
| throws ManifestException | |||||
| { | |||||
| final int index = line.indexOf( ": " ); | |||||
| if( index == -1 ) | |||||
| { | |||||
| throw new ManifestException( "Manifest line \"" + line + "\" is not valid as it does not " + | |||||
| "contain a name and a value separated by ': ' " ); | |||||
| } | |||||
| final String name = line.substring( 0, index ); | |||||
| final String value = line.substring( index + 2 ); | |||||
| attribute.setName( name ); | |||||
| attribute.setValue( value ); | |||||
| } | |||||
| public static void write( final Attribute attribute, final PrintWriter writer ) | |||||
| throws IOException | |||||
| { | |||||
| final String name = attribute.getName(); | |||||
| final String value = attribute.getValue(); | |||||
| String line = name + ": " + value; | |||||
| while( line.getBytes().length > MAX_LINE_LENGTH ) | |||||
| { | |||||
| // try to find a MAX_LINE_LENGTH byte section | |||||
| int breakIndex = MAX_LINE_LENGTH; | |||||
| String section = line.substring( 0, breakIndex ); | |||||
| while( section.getBytes().length > MAX_LINE_LENGTH && breakIndex > 0 ) | |||||
| { | |||||
| breakIndex--; | |||||
| section = line.substring( 0, breakIndex ); | |||||
| } | |||||
| if( breakIndex == 0 ) | |||||
| { | |||||
| throw new IOException( "Unable to write manifest line " + name + ": " + value ); | |||||
| } | |||||
| writer.println( section ); | |||||
| line = " " + line.substring( breakIndex ); | |||||
| } | |||||
| writer.println( line ); | |||||
| } | |||||
| /** | |||||
| * Write the manifest out to a print writer. | |||||
| * | |||||
| * @param writer the Writer to which the manifest is written | |||||
| * @throws java.io.IOException if the manifest cannot be written | |||||
| */ | |||||
| public static void write( Manifest manifest, PrintWriter writer ) | |||||
| throws IOException | |||||
| { | |||||
| final String sigVersionKey = Attributes.Name.SIGNATURE_VERSION.toString(); | |||||
| writer.println( Attributes.Name.MANIFEST_VERSION + ": " + manifest.getManifestVersion() ); | |||||
| final String signatureVersion = | |||||
| manifest.getMainSection().getAttributeValue( sigVersionKey ); | |||||
| if( signatureVersion != null ) | |||||
| { | |||||
| writer.println( Attributes.Name.SIGNATURE_VERSION + ": " + signatureVersion ); | |||||
| manifest.getMainSection().removeAttribute( sigVersionKey ); | |||||
| } | |||||
| manifest.getMainSection().write( writer ); | |||||
| if( signatureVersion != null ) | |||||
| { | |||||
| try | |||||
| { | |||||
| manifest.getMainSection().addAttribute( new Attribute( sigVersionKey, signatureVersion ) ); | |||||
| } | |||||
| catch( ManifestException e ) | |||||
| { | |||||
| // shouldn't happen - ignore | |||||
| } | |||||
| } | |||||
| final Section[] sections = manifest.getSections(); | |||||
| for( int i = 0; i < sections.length; i++ ) | |||||
| { | |||||
| sections[ i ].write( writer ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,334 +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.manifest; | |||||
| import java.io.BufferedReader; | |||||
| import java.io.IOException; | |||||
| import java.io.PrintWriter; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Enumeration; | |||||
| import java.util.Hashtable; | |||||
| import java.util.Iterator; | |||||
| /** | |||||
| * Class to represent an individual section in the Manifest. A section | |||||
| * consists of a set of attribute values, separated from other sections by a | |||||
| * blank line. | |||||
| * | |||||
| * @author Conor MacNeill | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class Section | |||||
| { | |||||
| private final ArrayList m_warnings = new ArrayList(); | |||||
| /** | |||||
| * The section's name if any. The main section in a manifest is unnamed. | |||||
| */ | |||||
| private String m_name; | |||||
| /** | |||||
| * The section's attributes. | |||||
| */ | |||||
| private final Hashtable m_attributes = new Hashtable(); | |||||
| /** | |||||
| * Set the Section's name | |||||
| * | |||||
| * @param name the section's name | |||||
| */ | |||||
| public void setName( final String name ) | |||||
| { | |||||
| m_name = name; | |||||
| } | |||||
| /** | |||||
| * Get the value of the attribute with the name given. | |||||
| * | |||||
| * @param attributeName the name of the attribute to be returned. | |||||
| * @return the attribute's value or null if the attribute does not exist | |||||
| * in the section | |||||
| */ | |||||
| public String getAttributeValue( final String attributeName ) | |||||
| { | |||||
| final Object attributeObject = m_attributes.get( attributeName.toLowerCase() ); | |||||
| if( null == attributeObject ) | |||||
| { | |||||
| return null; | |||||
| } | |||||
| else if( attributeObject instanceof Attribute ) | |||||
| { | |||||
| final Attribute attribute = (Attribute)attributeObject; | |||||
| return attribute.getValue(); | |||||
| } | |||||
| else | |||||
| { | |||||
| String value = ""; | |||||
| final ArrayList attributes = (ArrayList)attributeObject; | |||||
| Iterator e = attributes.iterator(); | |||||
| while( e.hasNext() ) | |||||
| { | |||||
| final Attribute classpathAttribute = (Attribute)e.next(); | |||||
| value += classpathAttribute.getValue() + " "; | |||||
| } | |||||
| return value.trim(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Get the Section's name | |||||
| * | |||||
| * @return the section's name. | |||||
| */ | |||||
| public String getName() | |||||
| { | |||||
| return m_name; | |||||
| } | |||||
| public Iterator getWarnings() | |||||
| { | |||||
| return m_warnings.iterator(); | |||||
| } | |||||
| /** | |||||
| * Add an attribute to the section | |||||
| * | |||||
| * @param attribute the attribute to be added. | |||||
| * @return the value of the attribute if it is a name attribute - null | |||||
| * other wise | |||||
| * @throws org.apache.tools.todo.taskdefs.manifest.ManifestException if the attribute already exists in this | |||||
| * section. | |||||
| */ | |||||
| public String addAttributeAndCheck( Attribute attribute ) | |||||
| throws ManifestException | |||||
| { | |||||
| if( attribute.getName() == null || attribute.getValue() == null ) | |||||
| { | |||||
| throw new ManifestException( "Attributes must have name and value" ); | |||||
| } | |||||
| if( attribute.getName().equalsIgnoreCase( ManifestUtil.ATTRIBUTE_NAME ) ) | |||||
| { | |||||
| m_warnings.add( "\"" + ManifestUtil.ATTRIBUTE_NAME + "\" attributes should not occur in the " + | |||||
| "main section and must be the first element in all " + | |||||
| "other sections: \"" + attribute.getName() + ": " + attribute.getValue() + "\"" ); | |||||
| return attribute.getValue(); | |||||
| } | |||||
| if( attribute.getName().toLowerCase().startsWith( ManifestUtil.ATTRIBUTE_FROM.toLowerCase() ) ) | |||||
| { | |||||
| m_warnings.add( "Manifest attributes should not start with \"" + | |||||
| ManifestUtil.ATTRIBUTE_FROM + "\" in \"" + attribute.getName() + ": " + attribute.getValue() + "\"" ); | |||||
| } | |||||
| else | |||||
| { | |||||
| // classpath attributes go into a vector | |||||
| String attributeName = attribute.getName().toLowerCase(); | |||||
| if( attributeName.equals( ManifestUtil.ATTRIBUTE_CLASSPATH ) ) | |||||
| { | |||||
| ArrayList classpathAttrs = (ArrayList)m_attributes.get( attributeName ); | |||||
| if( classpathAttrs == null ) | |||||
| { | |||||
| classpathAttrs = new ArrayList(); | |||||
| m_attributes.put( attributeName, classpathAttrs ); | |||||
| } | |||||
| classpathAttrs.add( attribute ); | |||||
| } | |||||
| else if( m_attributes.containsKey( attributeName ) ) | |||||
| { | |||||
| throw new ManifestException( "The attribute \"" + attribute.getName() + "\" may not " + | |||||
| "occur more than once in the same section" ); | |||||
| } | |||||
| else | |||||
| { | |||||
| m_attributes.put( attributeName, attribute ); | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public void addAttribute( final Attribute attribute ) | |||||
| throws ManifestException | |||||
| { | |||||
| String check = addAttributeAndCheck( attribute ); | |||||
| if( check != null ) | |||||
| { | |||||
| throw new ManifestException( "Specify the section name using the \"name\" attribute of the <section> element rather " + | |||||
| "than using a \"Name\" manifest attribute" ); | |||||
| } | |||||
| } | |||||
| public boolean equals( Object rhs ) | |||||
| { | |||||
| if( !( rhs instanceof Section ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| Section rhsSection = (Section)rhs; | |||||
| if( m_attributes.size() != rhsSection.m_attributes.size() ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| for( Enumeration e = m_attributes.elements(); e.hasMoreElements(); ) | |||||
| { | |||||
| Attribute attribute = (Attribute)e.nextElement(); | |||||
| Attribute rshAttribute = (Attribute)rhsSection.m_attributes.get( attribute.getName().toLowerCase() ); | |||||
| if( !attribute.equals( rshAttribute ) ) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Merge in another section | |||||
| * | |||||
| * @param section the section to be merged with this one. | |||||
| * @throws org.apache.tools.todo.taskdefs.manifest.ManifestException if the sections cannot be merged. | |||||
| */ | |||||
| public void merge( Section section ) | |||||
| throws ManifestException | |||||
| { | |||||
| if( m_name == null && section.getName() != null || | |||||
| m_name != null && !( m_name.equalsIgnoreCase( section.getName() ) ) ) | |||||
| { | |||||
| throw new ManifestException( "Unable to merge sections with different names" ); | |||||
| } | |||||
| for( Enumeration e = section.m_attributes.keys(); e.hasMoreElements(); ) | |||||
| { | |||||
| String attributeName = (String)e.nextElement(); | |||||
| if( attributeName.equals( ManifestUtil.ATTRIBUTE_CLASSPATH ) && | |||||
| m_attributes.containsKey( attributeName ) ) | |||||
| { | |||||
| // classpath entries are vetors which are merged | |||||
| ArrayList classpathAttrs = (ArrayList)section.m_attributes.get( attributeName ); | |||||
| ArrayList ourClasspathAttrs = (ArrayList)m_attributes.get( attributeName ); | |||||
| for( Iterator e2 = classpathAttrs.iterator(); e2.hasNext(); ) | |||||
| { | |||||
| ourClasspathAttrs.add( e2.next() ); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| // the merge file always wins | |||||
| m_attributes.put( attributeName, section.m_attributes.get( attributeName ) ); | |||||
| } | |||||
| } | |||||
| // add in the warnings | |||||
| for( Iterator e = section.m_warnings.iterator(); e.hasNext(); ) | |||||
| { | |||||
| m_warnings.add( e.next() ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Read a section through a reader | |||||
| * | |||||
| * @param reader the reader from which the section is read | |||||
| * @return the name of the next section if it has been read as part of | |||||
| * this section - This only happens if the Manifest is malformed. | |||||
| * @throws org.apache.tools.todo.taskdefs.manifest.ManifestException if the section is not valid according to | |||||
| * the JAR spec | |||||
| * @throws java.io.IOException if the section cannot be read from the reader. | |||||
| */ | |||||
| public String read( BufferedReader reader ) | |||||
| throws ManifestException, IOException | |||||
| { | |||||
| Attribute attribute = null; | |||||
| while( true ) | |||||
| { | |||||
| String line = reader.readLine(); | |||||
| if( line == null || line.length() == 0 ) | |||||
| { | |||||
| return null; | |||||
| } | |||||
| if( line.charAt( 0 ) == ' ' ) | |||||
| { | |||||
| // continuation line | |||||
| if( attribute == null ) | |||||
| { | |||||
| if( m_name != null ) | |||||
| { | |||||
| // a continuation on the first line is a continuation of the name - concatenate | |||||
| // this line and the name | |||||
| m_name += line.substring( 1 ); | |||||
| } | |||||
| else | |||||
| { | |||||
| throw new ManifestException( "Can't start an attribute with a continuation line " + line ); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| attribute.addContinuation( line ); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| attribute = ManifestUtil.buildAttribute( line ); | |||||
| String nameReadAhead = addAttributeAndCheck( attribute ); | |||||
| if( nameReadAhead != null ) | |||||
| { | |||||
| return nameReadAhead; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Remove tge given attribute from the section | |||||
| * | |||||
| * @param attributeName the name of the attribute to be removed. | |||||
| */ | |||||
| public void removeAttribute( String attributeName ) | |||||
| { | |||||
| m_attributes.remove( attributeName.toLowerCase() ); | |||||
| } | |||||
| /** | |||||
| * Write the section out to a print writer. | |||||
| * | |||||
| * @param writer the Writer to which the section is written | |||||
| * @throws java.io.IOException if the section cannot be written | |||||
| */ | |||||
| public void write( PrintWriter writer ) | |||||
| throws IOException | |||||
| { | |||||
| if( m_name != null ) | |||||
| { | |||||
| Attribute nameAttr = new Attribute( ManifestUtil.ATTRIBUTE_NAME, m_name ); | |||||
| ManifestUtil.write( nameAttr, writer ); | |||||
| } | |||||
| for( Enumeration e = m_attributes.elements(); e.hasMoreElements(); ) | |||||
| { | |||||
| Object object = e.nextElement(); | |||||
| if( object instanceof Attribute ) | |||||
| { | |||||
| Attribute attribute = (Attribute)object; | |||||
| ManifestUtil.write( attribute, writer ); | |||||
| } | |||||
| else | |||||
| { | |||||
| ArrayList attrList = (ArrayList)object; | |||||
| for( Iterator e2 = attrList.iterator(); e2.hasNext(); ) | |||||
| { | |||||
| Attribute attribute = (Attribute)e2.next(); | |||||
| ManifestUtil.write( attribute, writer ); | |||||
| } | |||||
| } | |||||
| } | |||||
| writer.println(); | |||||
| } | |||||
| } | |||||
| @@ -1,3 +0,0 @@ | |||||
| Manifest-Version: 1.0 | |||||
| Created-By: Apache Ant @VERSION@ | |||||
| @@ -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.net; | |||||
| import java.util.Locale; | |||||
| import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
| public class Action | |||||
| extends EnumeratedAttribute | |||||
| { | |||||
| private final static String[] validActions = new String[] | |||||
| { | |||||
| "send", "put", "recv", "get", "del", "delete", "list", "mkdir" | |||||
| }; | |||||
| public int getAction() | |||||
| { | |||||
| String actionL = getValue().toLowerCase( Locale.US ); | |||||
| if( actionL.equals( "send" ) || | |||||
| actionL.equals( "put" ) ) | |||||
| { | |||||
| return FTP.SEND_FILES; | |||||
| } | |||||
| else if( actionL.equals( "recv" ) || | |||||
| actionL.equals( "get" ) ) | |||||
| { | |||||
| return FTP.GET_FILES; | |||||
| } | |||||
| else if( actionL.equals( "del" ) || | |||||
| actionL.equals( "delete" ) ) | |||||
| { | |||||
| return FTP.DEL_FILES; | |||||
| } | |||||
| else if( actionL.equals( "list" ) ) | |||||
| { | |||||
| return FTP.LIST_FILES; | |||||
| } | |||||
| else if( actionL.equals( "mkdir" ) ) | |||||
| { | |||||
| return FTP.MK_DIR; | |||||
| } | |||||
| return FTP.SEND_FILES; | |||||
| } | |||||
| public String[] getValues() | |||||
| { | |||||
| return validActions; | |||||
| } | |||||
| } | |||||
| @@ -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.net; | |||||
| import com.oroinc.net.telnet.TelnetClient; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| /** | |||||
| * This class handles the abstraction of the telnet protocol. Currently it | |||||
| * is a wrapper around <a href="www.oroinc.com">ORO</a> 's NetComponents | |||||
| */ | |||||
| public class AntTelnetClient | |||||
| extends TelnetClient | |||||
| { | |||||
| private TelnetTask m_task; | |||||
| public AntTelnetClient( final TelnetTask task ) | |||||
| { | |||||
| m_task = task; | |||||
| } | |||||
| /** | |||||
| * Write this string to the telnet session. | |||||
| */ | |||||
| public void sendString( final String string, final boolean echoString ) | |||||
| throws TaskException | |||||
| { | |||||
| final OutputStream output = this.getOutputStream(); | |||||
| m_task.doSendString( output, string, echoString ); | |||||
| } | |||||
| /** | |||||
| * Read from the telnet session until the string we are waiting for is | |||||
| * found | |||||
| */ | |||||
| public void waitForString( final String string ) | |||||
| throws TaskException | |||||
| { | |||||
| waitForString( string, null ); | |||||
| } | |||||
| /** | |||||
| * Read from the telnet session until the string we are waiting for is | |||||
| * found or the timeout has been reached | |||||
| * | |||||
| * @parm s The string to wait on | |||||
| * @parm timeout The maximum number of seconds to wait | |||||
| */ | |||||
| public void waitForString( final String string, | |||||
| final Integer timeout ) | |||||
| throws TaskException | |||||
| { | |||||
| final InputStream input = this.getInputStream(); | |||||
| m_task.doWaitForString( input, string, timeout ); | |||||
| } | |||||
| } | |||||