Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

package com.erggroup.mass.ant.taskdefs;

import java.io.*;
import java.util.*;
import java.util.zip.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.*;


/**
 * Custom ANT task - given a code JAR and a source base, build a JAR
 * containing the corresponding source code.
 *
 * @ant.examples Here are examples
 *
 */
public class JarSrc extends Task
{
        /**
         * The binary source file; the src jar will be constructed with a
         * corresponding name (-src) and will contain the code counterparts.
         */
        private String binary;

        /**
         * The location that the source file will be created in.
         */
        private String toDir;

        /**
         * The FileSet indicating which corresponding source files should be
         * obtained (if they exist) from the source path.
         */
        private FileSet correspondingFileSet = null;

        /**
         * The set of directories under which the source code is located in
         * its' expected location.
         */
        private ArrayList dirsets = new ArrayList();

        /**
         * Set the filename of the source file. This file is used as a basis
         * for emulation, by constructing a src package to match.
         *
         * @param value the filename.
         */
        public void setBinary( String value )
        {
                binary = value;
        }

        /**
         * Set the 'todir', being the directory location in which the source
         * file will be constructed.
         *
         * @param value the directory.
         */
        public void setToDir( String value )
        {
                toDir = value;
        }

        /**
         * Nested element - this tag supports nested 'DirSet' elements.
         */
        public DirSet createDirSet()
        {
                DirSet dirset = new DirSet();
                dirsets.add( dirset );
                return dirset;
        }

        /**
         *
         */
        public void execute() throws BuildException
        {
                if ( dirsets.size() == 0 )
                {
                        throw new BuildException("At least one DirSet must be provided");
                }

                for ( Iterator i=dirsets.iterator(); i.hasNext(); )
                {
                        DirSet dirset = (DirSet)i.next();
                        FileScanner scanner = dirset.getDirectoryScanner( getProject() );
                        String[] directories = scanner.getIncludedDirectories();
                        File basedir = scanner.getBasedir();
                        for ( int j=0; j<directories.length; j++ )
                        {
                                File srcDirectory = new File( basedir, directories[j] );
                                packageSource( srcDirectory );
                        }
                }
        }

        /**
         *
         */
        private void packageSource( File srcDir ) throws BuildException
        {
                log("Packaging source from '" + srcDir + "'", Project.MSG_VERBOSE );
                FileSet corresponding = null;

                try
                {
                        corresponding = getCorrespondingNames();
                        corresponding.setDir( srcDir );
                }
                catch (IOException x)
                {
                        throw new BuildException( "Could not read binary '" + binary + "'", x);
                }

                File binarySource = new File( srcDir, binary );
                String binaryName = binarySource.getName();
                String destName = binaryName.substring(0, binaryName.lastIndexOf("."));
                destName += "-src.jar";
                File destDir = new File( toDir );
                File destFile = new File( toDir, destName );

                // Check that the corresponding src JAR exists; if not, create one.
                Jar jarTask = new Jar();
                jarTask.setTaskName(this.getTaskName());
                jarTask.setProject( getProject() );
                jarTask.setDestFile( destFile );
                jarTask.setUpdate(true);

                jarTask.addFileset( corresponding );
                jarTask.execute();
        }

        /**
         * Get the corresponding java source names (as a FileSet), by
         * using the configured 'binary'.
         *
         * @return a FileSet containing a list of the expected source
         *         files.
         *
         * @throws IOException if the binary could not be read.
         */
        private FileSet getCorrespondingNames() throws IOException
        {
                if ( correspondingFileSet == null )
                {
                        FileSet corresponding = new FileSet();
                        corresponding.setProject( getProject() );

                        ZipFile zf = null;
                        try
                        {
                                log("Loading from source binary '" + binary + "'", Project.MSG_VERBOSE );
                                zf = new ZipFile(binary);
                                Enumeration l_enum = zf.entries();
                                while (l_enum.hasMoreElements())
                                {
                                        ZipEntry ze = (ZipEntry)l_enum.nextElement();
                                        String entryName = ze.getName();
                                        if ( entryName.endsWith( ".class" ) )
                                        {
                                                String correspondingName = entryName.substring(0, entryName.indexOf(".class") );
                                                correspondingName += ".java";
                                                log("Adding '" + correspondingName + "' to FileSet", Project.MSG_VERBOSE );
                                                corresponding.setIncludes( correspondingName );
                                        }
                                }
                        }
                        finally
                        {
                                if (zf != null)
                                {
                                        try
                                        {
                                                zf.close();
                                        }
                                        catch (IOException e)
                                        {
                                        }
                                }
                        }
                        correspondingFileSet = corresponding;
                }
                return correspondingFileSet;
        }
}