Neat,
that is a a brilliant solution!

Peter


On Thu, Feb 12, 2009 at 10:35 PM,  <jgl...@apache.org> wrote:
> Author: jglick
> Date: Thu Feb 12 22:35:18 2009
> New Revision: 743910
>
> URL: http://svn.apache.org/viewvc?rev=743910&view=rev
> Log:
> #43114: ensuring that package-info.class is created/touched when 
> package-info.java is compiled.
>
> Modified:
>    ant/core/trunk/WHATSNEW
>    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Javac.java
>
> Modified: ant/core/trunk/WHATSNEW
> URL: 
> http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=743910&r1=743909&r2=743910&view=diff
> ==============================================================================
> --- ant/core/trunk/WHATSNEW (original)
> +++ ant/core/trunk/WHATSNEW Thu Feb 12 22:35:18 2009
> @@ -137,6 +137,9 @@
>
>  Fixed bugs:
>  -----------
> +
> + * Better handling of package-info.class. Bugzilla Report 43114.
> +
>  * RPM task needed an inserted space between the define and the value.
>    bugzilla Report 46659.
>
>
> Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Javac.java
> URL: 
> http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Javac.java?rev=743910&r1=743909&r2=743910&view=diff
> ==============================================================================
> --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Javac.java 
> (original)
> +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Javac.java Thu Feb 
> 12 22:35:18 2009
> @@ -19,10 +19,12 @@
>  package org.apache.tools.ant.taskdefs;
>
>  import java.io.File;
> -
> -import java.util.ArrayList;
> +import java.io.FileOutputStream;
> +import java.io.IOException;
> +import java.io.OutputStream;
> +import java.util.HashMap;
>  import java.util.Iterator;
> -import java.util.List;
> +import java.util.Map;
>
>  import org.apache.tools.ant.BuildException;
>  import org.apache.tools.ant.DirectoryScanner;
> @@ -87,9 +89,6 @@
>     private static final String CLASSIC = "classic";
>     private static final String EXTJAVAC = "extJavac";
>
> -    private static final String PACKAGE_INFO_JAVA = "package-info.java";
> -    private static final String PACKAGE_INFO_CLASS = "package-info.class";
> -
>     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
>
>     private Path src;
> @@ -118,6 +117,7 @@
>     protected boolean failOnError = true;
>     protected boolean listFiles = false;
>     protected File[] compileList = new File[0];
> +    private Map/*<String,Long>*/ packageInfos = new HashMap();
>     // CheckStyle:VisibilityModifier ON
>
>     private String source;
> @@ -127,7 +127,6 @@
>     private String errorProperty;
>     private boolean taskSuccess = true; // assume the best
>     private boolean includeDestClasses = true;
> -    private List    updateDirList = new ArrayList();
>
>     /**
>      * Javac task for compilation of Java files.
> @@ -898,6 +897,7 @@
>      */
>     protected void resetFileLists() {
>         compileList = new File[0];
> +        packageInfos = new HashMap();
>     }
>
>     /**
> @@ -915,8 +915,8 @@
>         SourceFileScanner sfs = new SourceFileScanner(this);
>         File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
>
> -        newFiles = removePackageInfoFiles(newFiles, srcDir, destDir);
>         if (newFiles.length > 0) {
> +            lookForPackageInfos(srcDir, newFiles);
>             File[] newCompileList
>                 = new File[compileList.length + newFiles.length];
>             System.arraycopy(compileList, 0, newCompileList, 0,
> @@ -1069,10 +1069,12 @@
>
>             // finally, lets execute the compiler!!
>             if (adapter.execute()) {
> -                // Success - check
> -                for (Iterator i = updateDirList.iterator(); i.hasNext();) {
> -                    File file = (File) i.next();
> -                    file.setLastModified(System.currentTimeMillis());
> +                // Success
> +                try {
> +                    generateMissingPackageInfoClasses();
> +                } catch (IOException x) {
> +                    // Should this be made a nonfatal warning?
> +                    throw new BuildException(x, getLocation());
>                 }
>             } else {
>                 // Fail path
> @@ -1106,71 +1108,68 @@
>         }
>     }
>
> -    // ----------------------------------------------------------------
> -    //  Code to remove package-info.java files from compilation
> -    //  Since Ant 1.7.1.
> -    //
> -    //    package-info.java are files that contain package level
> -    //    annotations. They may or may not have corresponding .class
> -    //    files.
> -    //
> -    //    The following code uses the algorithm:
> -    //     * on entry we have the files that need to be compiled
> -    //     * if the filename is not package-info.java compile it
> -    //     * if a corresponding .class file exists compile it
> -    //     * if the corresponding class directory does not exist compile it
> -    //     * if the corresponding directory lastmodifed time is
> -    //       older than the java file, compile the java file and
> -    //       touch the corresponding class directory (on successful
> -    //       compilation).
> -    //
> -    // ----------------------------------------------------------------
> -    private File[] removePackageInfoFiles(
> -        File[] newFiles, File srcDir, File destDir) {
> -        if (!hasPackageInfo(newFiles)) {
> -            return newFiles;
> -        }
> -        List ret = new ArrayList();
> -        for (int i = 0; i < newFiles.length; ++i) {
> -            if (needsCompilePackageFile(newFiles[i], srcDir, destDir)) {
> -                ret.add(newFiles[i]);
> +    private void lookForPackageInfos(File srcDir, File[] newFiles) {
> +        for (int i = 0; i < newFiles.length; i++) {
> +            File f = newFiles[i];
> +            if (!f.getName().equals("package-info.java")) {
> +                continue;
>             }
> -        }
> -        return (File[]) ret.toArray(new File[0]);
> -    }
> -
> -    private boolean hasPackageInfo(File[] newFiles) {
> -        for (int i = 0; i < newFiles.length; ++i) {
> -            if (newFiles[i].getName().equals(PACKAGE_INFO_JAVA)) {
> -                return true;
> +            String path = FILE_UTILS.removeLeadingPath(srcDir, f).
> +                    replace(File.separatorChar, '/');
> +            String suffix = "/package-info.java";
> +            if (!path.endsWith(suffix)) {
> +                log("anomalous package-info.java path: " + path, 
> Project.MSG_WARN);
> +                continue;
>             }
> +            String pkg = path.substring(0, path.length() - suffix.length());
> +            packageInfos.put(pkg, Long.valueOf(f.lastModified()));
>         }
> -        return false;
>     }
>
> -    private boolean needsCompilePackageFile(
> -        File file, File srcDir, File destDir) {
> -        if (!file.getName().equals(PACKAGE_INFO_JAVA)) {
> -            return true;
> -        }
> -        // return true if destDir contains the file
> -        String rel = FILE_UTILS.removeLeadingPath(srcDir, file);
> -        File destFile = new File(destDir, rel);
> -        File parent = destFile.getParentFile();
> -        destFile = new File(parent, PACKAGE_INFO_CLASS);
> -        File sourceFile = new File(srcDir, rel);
> -        if (destFile.exists()) {
> -            return true;
> -        }
> -        // Dest file does not exist
> -        // Compile Source file if sourceFile is newer that destDir
> -        // TODO - use fs
> -        if (sourceFile.lastModified()
> -            > destFile.getParentFile().lastModified()) {
> -            updateDirList.add(destFile.getParentFile());
> -            return true;
> +    /**
> +     * Ensure that every {...@code package-info.java} produced a {...@code 
> package-info.class}.
> +     * Otherwise this task's up-to-date tracking mechanisms do not work.
> +     * @see <a 
> href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43114";>Bug #43114</a>
> +     */
> +    private void generateMissingPackageInfoClasses() throws IOException {
> +        for (Iterator i = packageInfos.entrySet().iterator(); i.hasNext(); ) 
> {
> +            Map.Entry entry = (Map.Entry) i.next();
> +            String pkg = (String) entry.getKey();
> +            Long sourceLastMod = (Long) entry.getValue();
> +            File pkgBinDir = new File(destDir, pkg.replace('/', 
> File.separatorChar));
> +            pkgBinDir.mkdirs();
> +            File pkgInfoClass = new File(pkgBinDir, "package-info.class");
> +            if (pkgInfoClass.isFile() && pkgInfoClass.lastModified() >= 
> sourceLastMod.longValue()) {
> +                continue;
> +            }
> +            log("Creating empty " + pkgInfoClass);
> +            OutputStream os = new FileOutputStream(pkgInfoClass);
> +            try {
> +                os.write(PACKAGE_INFO_CLASS_HEADER);
> +                byte[] name = pkg.getBytes("UTF-8");
> +                int length = name.length + /* "/package-info" */ 13;
> +                os.write((byte) length / 256);
> +                os.write((byte) length % 256);
> +                os.write(name);
> +                os.write(PACKAGE_INFO_CLASS_FOOTER);
> +            } finally {
> +                os.close();
> +            }
>         }
> -        return false;
>     }
> +    private static final byte[] PACKAGE_INFO_CLASS_HEADER = {
> +        (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, 0x00, 0x00, 0x00,
> +        0x31, 0x00, 0x07, 0x07, 0x00, 0x05, 0x07, 0x00, 0x06, 0x01, 0x00, 
> 0x0a,
> +        0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x01, 
> 0x00,
> +        0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 
> 0x66,
> +        0x6f, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x01
> +    };
> +    private static final byte[] PACKAGE_INFO_CLASS_FOOTER = {
> +        0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 
> 0x66,
> +        0x6f, 0x01, 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 
> 0x6e,
> +        0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x02, 0x00, 0x00, 
> 0x01,
> +        0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
> 0x03,
> +        0x00, 0x00, 0x00, 0x02, 0x00, 0x04
> +    };
>
>  }
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org
For additional commands, e-mail: dev-h...@ant.apache.org

Reply via email to