]> source.dussan.org Git - aspectj.git/commitdiff
2009,2010
authoraclement <aclement>
Wed, 4 Mar 2009 01:24:43 +0000 (01:24 +0000)
committeraclement <aclement>
Wed, 4 Mar 2009 01:24:43 +0000 (01:24 +0000)
build/src/org/aspectj/internal/tools/ant/taskdefs/Checklics.java

index 121059f6fdb85c8b79877620c3cf63b49b9a5f63..4b240b759535d89ee7bf24469bc2ca59060ff94e 100644 (file)
@@ -32,62 +32,54 @@ import org.apache.tools.ant.taskdefs.MatchingTask;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 
-/** 
- * Check that included .java files contain license and copyright strings
- * for MPL 1.0 (default), Apache, or CPL.
- * Use list="true" to get a list of known license variants {license}-{copyrightHolder}
- * todo reimplement with regexp and jdiff FileLine utilities 
+/**
+ * Check that included .java files contain license and copyright strings for MPL 1.0 (default), Apache, or CPL. Use list="true" to
+ * get a list of known license variants {license}-{copyrightHolder} todo reimplement with regexp and jdiff FileLine utilities
  */
 public class Checklics extends MatchingTask {
        /*
-         This does not enforce that copyrights are correct/current,
-         only that they exist.
-         E.g., the default behavior requires MPL but permits either 
-         Xerox or PARC copyright holders and any valid year.
+        * This does not enforce that copyrights are correct/current, only that they exist. E.g., the default behavior requires MPL but
+        * permits either Xerox or PARC copyright holders and any valid year.
         */
-    public static final String MPL_TAG = "mpl";
-    public static final String APACHE_TAG = "apache";
-    public static final String CPL_IBM_PARC_TAG = "cpl-ibm|parc";
-    public static final String CPL_IBM_TAG = "cpl-ibm";
-    public static final String MPL_XEROX_PARC_TAG = "mpl-parc|xerox";
-    public static final String MPL_ONLY_TAG = "mpl-only";
-    public static final String MPL_PARC_TAG = "mpl-parc";
-    public static final String PARC_COPYRIGHT_TAG = "parc-copy";
-    public static final String CPL_IBM_PARC_XEROX_TAG = "cpl-ibm|parc|xerox";
-    public static final String CPL_IBM_PARC_XEROX_OTHERS_TAG = "cpl-ibm|parc|xerox|others";
-    public static final String EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG = "epl-cpl-ibm|parc|xerox|others";
-    public static final String DEFAULT = EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG;
-    
-    static final Map LICENSES; // unmodifiable Map
-    
+       public static final String MPL_TAG = "mpl";
+       public static final String APACHE_TAG = "apache";
+       public static final String CPL_IBM_PARC_TAG = "cpl-ibm|parc";
+       public static final String CPL_IBM_TAG = "cpl-ibm";
+       public static final String MPL_XEROX_PARC_TAG = "mpl-parc|xerox";
+       public static final String MPL_ONLY_TAG = "mpl-only";
+       public static final String MPL_PARC_TAG = "mpl-parc";
+       public static final String PARC_COPYRIGHT_TAG = "parc-copy";
+       public static final String CPL_IBM_PARC_XEROX_TAG = "cpl-ibm|parc|xerox";
+       public static final String CPL_IBM_PARC_XEROX_OTHERS_TAG = "cpl-ibm|parc|xerox|others";
+       public static final String EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG = "epl-cpl-ibm|parc|xerox|others";
+       public static final String DEFAULT = EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG;
+
+       static final Map LICENSES; // unmodifiable Map
+
        static {
-        final String CONTRIBUTORS = "Contributors";
+               final String CONTRIBUTORS = "Contributors";
                final String XEROX = "Xerox";
                final String PARC = "Palo Alto Research Center";
                final String APACHE = "The Apache Software Foundation";
                final String IBM = "IBM";
                final String IBM_LONG = "International Business Machines";
-               final String LIC_APL =
-                       "Apache Software Foundation (http://www.apache.org/)";
+               final String LIC_APL = "Apache Software Foundation (http://www.apache.org/)";
                final String LIC_MPL = "http://aspectj.org/MPL/";
-        final String LIC_CPL = "Eclipse Public License";
-        final String LIC_ECPL = " Public License";
+               final String LIC_CPL = "Eclipse Public License";
+               final String LIC_ECPL = " Public License";
                License APL = new License(APACHE_TAG, LIC_APL, APACHE);
                License MPL = new License(MPL_TAG, LIC_MPL, XEROX);
                License MPL_XEROX_PARC = new License(DEFAULT, LIC_MPL, XEROX, PARC);
-               License CPL_IBM_PARC = new License(CPL_IBM_PARC_TAG,LIC_CPL,
-                                                   new String[] { IBM_LONG, IBM, PARC });
-        License CPL_IBM_PARC_XEROX = new License(CPL_IBM_PARC_XEROX_TAG,LIC_CPL,
-                                    new String[] { IBM_LONG, IBM, PARC, XEROX });
-
-        
-        License CPL_IBM_PARC_XEROX_OTHERS = new License(CPL_IBM_PARC_XEROX_OTHERS_TAG, LIC_CPL,
-                                    new String[] { IBM_LONG, IBM, PARC, XEROX, CONTRIBUTORS });
-        License EPL_CPL_IBM_PARC_XEROX_OTHERS = new License(EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG, LIC_ECPL,
-                new String[] { IBM_LONG, IBM, PARC, XEROX, CONTRIBUTORS });
-        License CPL_IBM = new License(CPL_IBM_TAG, LIC_CPL, IBM, IBM_LONG);
-        License MPL_ONLY = new License(MPL_ONLY_TAG, LIC_MPL);
-        License MPL_PARC = new License(MPL_PARC_TAG, LIC_MPL, PARC);
+               License CPL_IBM_PARC = new License(CPL_IBM_PARC_TAG, LIC_CPL, new String[] { IBM_LONG, IBM, PARC });
+               License CPL_IBM_PARC_XEROX = new License(CPL_IBM_PARC_XEROX_TAG, LIC_CPL, new String[] { IBM_LONG, IBM, PARC, XEROX });
+
+               License CPL_IBM_PARC_XEROX_OTHERS = new License(CPL_IBM_PARC_XEROX_OTHERS_TAG, LIC_CPL, new String[] { IBM_LONG, IBM, PARC,
+                               XEROX, CONTRIBUTORS });
+               License EPL_CPL_IBM_PARC_XEROX_OTHERS = new License(EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG, LIC_ECPL, new String[] { IBM_LONG,
+                               IBM, PARC, XEROX, CONTRIBUTORS });
+               License CPL_IBM = new License(CPL_IBM_TAG, LIC_CPL, IBM, IBM_LONG);
+               License MPL_ONLY = new License(MPL_ONLY_TAG, LIC_MPL);
+               License MPL_PARC = new License(MPL_PARC_TAG, LIC_MPL, PARC);
                License PARC_COPYRIGHT = new License(PARC_COPYRIGHT_TAG, null, PARC);
                LICENSES = new Hashtable();
                LICENSES.put(APL.tag, APL);
@@ -98,84 +90,88 @@ public class Checklics extends MatchingTask {
                LICENSES.put(MPL_ONLY.tag, MPL_ONLY);
                LICENSES.put(CPL_IBM.tag, CPL_IBM);
                LICENSES.put(PARC_COPYRIGHT.tag, PARC_COPYRIGHT);
-        LICENSES.put(CPL_IBM_PARC_XEROX.tag, CPL_IBM_PARC_XEROX);
-        LICENSES.put(CPL_IBM_PARC_XEROX_OTHERS.tag, CPL_IBM_PARC_XEROX_OTHERS);
-        LICENSES.put(EPL_CPL_IBM_PARC_XEROX_OTHERS.tag, EPL_CPL_IBM_PARC_XEROX_OTHERS);
+               LICENSES.put(CPL_IBM_PARC_XEROX.tag, CPL_IBM_PARC_XEROX);
+               LICENSES.put(CPL_IBM_PARC_XEROX_OTHERS.tag, CPL_IBM_PARC_XEROX_OTHERS);
+               LICENSES.put(EPL_CPL_IBM_PARC_XEROX_OTHERS.tag, EPL_CPL_IBM_PARC_XEROX_OTHERS);
+       }
+
+       /** @param args String[] { &lt; sourcepath &gt; {, &lt; licenseTag &gt; } } */
+       public static void main(String[] args) {
+               switch (args.length) {
+               case 1:
+                       runDirect(args[0], null, false);
+                       break;
+               case 2:
+                       runDirect(args[0], args[1], false);
+                       break;
+               default:
+                       String options = "{replace-headers|get-years|list|{licenseTag}}";
+                       System.err.println("java {me} sourcepath " + options);
+                       break;
+               }
        }
-    
-    /** @param args String[] { &lt; sourcepath &gt; {, &lt; licenseTag &gt; } } */
-    public static void main(String[] args) {
-        switch (args.length) {
-            case 1 :  runDirect(args[0], null, false);
-                break;
-            case 2 :  runDirect(args[0], args[1], false);
-                break;
-            default:
-                String options = "{replace-headers|get-years|list|{licenseTag}}";
-                System.err.println("java {me} sourcepath " + options);
-                break;
-        }
-    }
-
-    /**
-     * Run the license check directly
-     * @param sourcepaths String[] of paths to source directories
-     * @param license the String tag for the license, if any
-     * @param failonerror boolean flag to pass to Checklics
-     * @throws IllegalArgumentException if sourcepaths is empty
-     * @return total number of failed licenses
-     */
-    public static int runDirect(String sourcepath, String license, boolean failonerror) {
-        if ((null == sourcepath) || (1 > sourcepath.length())) {
-            throw new IllegalArgumentException("bad sourcepath: " + sourcepath);
-        }
-        Checklics me = new Checklics();
-        Project p = new Project();
-        p.setName("direct interface to Checklics");
-        p.setBasedir(".");
-        me.setProject(p);
-        me.setFailOnError(failonerror);
-        me.setSourcepath(new Path(p, sourcepath));
-        if (null != license) {
-            if ("replace-headers".equals(license)) {
-                me.setReplaceheaders(true);
-            } else if ("get-years".equals(license)) {
-                me.setGetYears(true);
-            } else if ("list".equals(license)) {
-                me.setList(true);
-            } else {
-                me.setLicense(license);        
-            }
-        }
-        me.execute();
-        return me.failed;
-    }
-       
-    private Path sourcepath;
-    private License license;
-    private boolean list;
-    private String streamTag;
-    private boolean failOnError;
-    private boolean getYears;
-    private boolean replaceHeaders;
-    private int failed;
-    private int passed;
+
+       /**
+        * Run the license check directly
+        * 
+        * @param sourcepaths String[] of paths to source directories
+        * @param license the String tag for the license, if any
+        * @param failonerror boolean flag to pass to Checklics
+        * @throws IllegalArgumentException if sourcepaths is empty
+        * @return total number of failed licenses
+        */
+       public static int runDirect(String sourcepath, String license, boolean failonerror) {
+               if ((null == sourcepath) || (1 > sourcepath.length())) {
+                       throw new IllegalArgumentException("bad sourcepath: " + sourcepath);
+               }
+               Checklics me = new Checklics();
+               Project p = new Project();
+               p.setName("direct interface to Checklics");
+               p.setBasedir(".");
+               me.setProject(p);
+               me.setFailOnError(failonerror);
+               me.setSourcepath(new Path(p, sourcepath));
+               if (null != license) {
+                       if ("replace-headers".equals(license)) {
+                               me.setReplaceheaders(true);
+                       } else if ("get-years".equals(license)) {
+                               me.setGetYears(true);
+                       } else if ("list".equals(license)) {
+                               me.setList(true);
+                       } else {
+                               me.setLicense(license);
+                       }
+               }
+               me.execute();
+               return me.failed;
+       }
+
+       private Path sourcepath;
+       private License license;
+       private boolean list;
+       private String streamTag;
+       private boolean failOnError;
+       private boolean getYears;
+       private boolean replaceHeaders;
+       private int failed;
+       private int passed;
 
        private boolean printDirectories;
 
-    /** @param list if true, don't run but list known license tags */
+       /** @param list if true, don't run but list known license tags */
        public void setList(boolean list) {
                this.list = list;
        }
-    
-    public void setPrintDirectories(boolean print) {
-        printDirectories = print;
-    }
-    
-       /** 
-        * When failOnError is true, if any file failed, throw BuildException 
-        * listing number of files that file failed to pass license check 
-        * @param fail if true, report errors by throwing BuildException  
+
+       public void setPrintDirectories(boolean print) {
+               printDirectories = print;
+       }
+
+       /**
+        * When failOnError is true, if any file failed, throw BuildException listing number of files that file failed to pass license
+        * check
+        * 
+        * @param fail if true, report errors by throwing BuildException
         */
        public void setFailOnError(boolean fail) {
                this.failOnError = fail;
@@ -199,9 +195,7 @@ public class Checklics extends MatchingTask {
        }
 
        public Path createSourcepath() {
-               return sourcepath == null
-                       ? (sourcepath = new Path(project))
-                       : sourcepath.createPath();
+               return sourcepath == null ? (sourcepath = new Path(project)) : sourcepath.createPath();
        }
 
        public void setSourcepathRef(Reference id) {
@@ -212,123 +206,117 @@ public class Checklics extends MatchingTask {
        public void setOutputStream(String out) {
                this.streamTag = out;
        }
-    
-    public void setReplaceheaders(boolean replaceHeaders) {
-        this.replaceHeaders = replaceHeaders;
-    }
-    
-    public void setGetYears(boolean getYears) {
-        this.getYears = getYears;
-    }
-
-    /** list known licenses or check source tree */
-    public void execute() throws BuildException {
-        if (list) {
-            list();
-        } else if (replaceHeaders) {
-            replaceHeaders();
-        } else if (getYears) {
-            getYears();
-        } else {
-            checkLicenses();
-        }
-    }
-    
-    private PrintStream getOut() {
-        return ("err".equals(streamTag) ? System.err : System.out);
-    }
-
-    interface FileVisitor {
-        void visit(File file);
-    }
-    
-    /** visit all .java files in all directories... */
-    private void visitAll(FileVisitor visitor) {
-//        List filelist = new ArrayList();
-        String[] dirs = sourcepath.list();
-        for (int i = 0; i < dirs.length; i++) {
-            File dir = project.resolveFile(dirs[i]);
-            String[] files = getDirectoryScanner(dir).getIncludedFiles();
-            for (int j = 0; j < files.length; j++) {
-                File file = new File(dir, files[j]);
-                String path = file.getPath();
-                if (path.endsWith(".java")) {
-                    visitor.visit(file);
-                }
-            }
-        }
-    }
-    
-    private void replaceHeaders() {
-        class YearVisitor implements FileVisitor {
-            public void visit(File file) {
-                HeaderInfo info = Header.checkFile(file);
-                if (!Header.replaceHeader(file, info)) {
-                    throw new BuildException("failed to replace header for " + file
-                        + " using " + info);
-                }
-            }
-        }
-        visitAll(new YearVisitor());
-    }
-
-    private void getYears() {
-        final PrintStream out = getOut();
-        class YearVisitor implements FileVisitor {
-            public void visit(File file) {
-                HeaderInfo info = Header.checkFile(file);
-                out.println(info.toString());                
-            }
-        }
-        visitAll(new YearVisitor());
-    }
-
-    private void checkLicenses() throws BuildException {
-        if (null == license) {
-            setLicense(DEFAULT);
-        }
-        final License license = this.license; // being paranoid...
-        if (null == license) {
-            throw new BuildException("no license");
-        }
-        final PrintStream out = getOut();
-
-        class Visitor implements FileVisitor {
-            int failed = 0;
-            int passed = 0;
+
+       public void setReplaceheaders(boolean replaceHeaders) {
+               this.replaceHeaders = replaceHeaders;
+       }
+
+       public void setGetYears(boolean getYears) {
+               this.getYears = getYears;
+       }
+
+       /** list known licenses or check source tree */
+       public void execute() throws BuildException {
+               if (list) {
+                       list();
+               } else if (replaceHeaders) {
+                       replaceHeaders();
+               } else if (getYears) {
+                       getYears();
+               } else {
+                       checkLicenses();
+               }
+       }
+
+       private PrintStream getOut() {
+               return ("err".equals(streamTag) ? System.err : System.out);
+       }
+
+       interface FileVisitor {
+               void visit(File file);
+       }
+
+       /** visit all .java files in all directories... */
+       private void visitAll(FileVisitor visitor) {
+               // List filelist = new ArrayList();
+               String[] dirs = sourcepath.list();
+               for (int i = 0; i < dirs.length; i++) {
+                       File dir = project.resolveFile(dirs[i]);
+                       String[] files = getDirectoryScanner(dir).getIncludedFiles();
+                       for (int j = 0; j < files.length; j++) {
+                               File file = new File(dir, files[j]);
+                               String path = file.getPath();
+                               if (path.endsWith(".java")) {
+                                       visitor.visit(file);
+                               }
+                       }
+               }
+       }
+
+       private void replaceHeaders() {
+               class YearVisitor implements FileVisitor {
+                       public void visit(File file) {
+                               HeaderInfo info = Header.checkFile(file);
+                               if (!Header.replaceHeader(file, info)) {
+                                       throw new BuildException("failed to replace header for " + file + " using " + info);
+                               }
+                       }
+               }
+               visitAll(new YearVisitor());
+       }
+
+       private void getYears() {
+               final PrintStream out = getOut();
+               class YearVisitor implements FileVisitor {
+                       public void visit(File file) {
+                               HeaderInfo info = Header.checkFile(file);
+                               out.println(info.toString());
+                       }
+               }
+               visitAll(new YearVisitor());
+       }
+
+       private void checkLicenses() throws BuildException {
+               if (null == license) {
+                       setLicense(DEFAULT);
+               }
+               final License license = this.license; // being paranoid...
+               if (null == license) {
+                       throw new BuildException("no license");
+               }
+               final PrintStream out = getOut();
+
+               class Visitor implements FileVisitor {
+                       int failed = 0;
+                       int passed = 0;
+
                        public void visit(File file) {
-                if (license.checkFile(file)) {
-                    passed++;
-                } else {
-                    failed++;
-                    String path = file.getPath();
-                    if (!license.foundLicense()) {
-                        out.println(
-                            license.tag + "   LICENSE FAIL: " + path);
-                    }
-                    if (!license.foundCopyright()) {
-                        out.println(
-                            license.tag + " COPYRIGHT FAIL: " + path);
-                    }
-                }
+                               if (license.checkFile(file)) {
+                                       passed++;
+                               } else {
+                                       failed++;
+                                       String path = file.getPath();
+                                       if (!license.foundLicense()) {
+                                               out.println(license.tag + "   LICENSE FAIL: " + path);
+                                       }
+                                       if (!license.foundCopyright()) {
+                                               out.println(license.tag + " COPYRIGHT FAIL: " + path);
+                                       }
+                               }
                        }
-        }
-        Visitor visitor = new Visitor();
-        visitAll(visitor);
-        this.failed = visitor.failed;
-        this.passed = visitor.passed;
-        if (0 < visitor.failed) {
-            getOut().println(
-                    "Total passed: "
-                        + visitor.passed
-                        + (visitor.failed == 0 ? "" : " failed: " + visitor.failed));
-            if (failOnError) {
-                throw new BuildException(
-                    failed + " files failed license check");
-            }
-        }
-    }
-    
+               }
+               Visitor visitor = new Visitor();
+               visitAll(visitor);
+               this.failed = visitor.failed;
+               this.passed = visitor.passed;
+               if (0 < visitor.failed) {
+                       getOut().println("Total passed: " + visitor.passed + (visitor.failed == 0 ? "" : " failed: " + visitor.failed));
+                       if (failOnError) {
+                               throw new BuildException(failed + " files failed license check");
+                       }
+               }
+       }
+
        private void list() {
                Iterator enu = LICENSES.keySet().iterator();
                StringBuffer sb = new StringBuffer();
@@ -343,15 +331,13 @@ public class Checklics extends MatchingTask {
                getOut().println(sb.toString());
        }
 
-
        /**
-        * Encapsulate license and copyright specifications 
-        * to check files use hokey string matching.
+        * Encapsulate license and copyright specifications to check files use hokey string matching.
         */
        public static class License {
                /** acceptable years for copyright prefix to company - append " " */
                static final String[] YEARS = // remove older after license xfer?
-                       new String[] { "2002 ", "2003 ", "2004 ", "2005", "2006", "2007", "2008", "2001 ", "2000 ", "1999 " }; 
+               new String[] { "2002 ", "2003 ", "2004 ", "2005", "2006", "2007", "2008", "2009", "2010", "2001 ", "2000 ", "1999 " };
                public final String tag;
                public final String license;
                private final String[] copyright;
@@ -366,11 +352,7 @@ public class Checklics extends MatchingTask {
                        this(tag, license, new String[] { copyright });
                }
 
-               License(
-                       String tag,
-                       String license,
-                       String copyright,
-                       String altCopyright) {
+               License(String tag, String license, String copyright, String altCopyright) {
                        this(tag, license, new String[] { copyright, altCopyright });
                }
 
@@ -399,20 +381,18 @@ public class Checklics extends MatchingTask {
 
                public boolean checkFile(final File file) {
                        clear();
-//                     boolean result = false;
+                       // boolean result = false;
                        BufferedReader input = null;
                        int lineNum = 0;
                        try {
                                input = new BufferedReader(new FileReader(file));
                                String line;
-                               while (!gotValidFile()
-                                       && (line = input.readLine()) != null) {
+                               while (!gotValidFile() && (line = input.readLine()) != null) {
                                        lineNum++;
                                        checkLine(line);
                                }
                        } catch (IOException e) {
-                               System.err.println(
-                                       "reading line " + lineNum + " of " + file);
+                               System.err.println("reading line " + lineNum + " of " + file);
                                e.printStackTrace(System.err);
                        } finally {
                                if (null != input) {
@@ -433,22 +413,16 @@ public class Checklics extends MatchingTask {
                        if ((null == line) || (0 == line.length())) {
                                return;
                        }
-                       if (!gotLicense
-                               && (null != license)
-                               && (-1 != line.indexOf(license))) {
+                       if (!gotLicense && (null != license) && (-1 != line.indexOf(license))) {
                                gotLicense = true;
                        }
                        if (!gotCopyright && (null != copyright)) {
                                int loc;
-                               for (int j = 0;
-                                       !gotCopyright && (j < YEARS.length);
-                                       j++) {
+                               for (int j = 0; !gotCopyright && (j < YEARS.length); j++) {
                                        if (-1 != (loc = line.indexOf(YEARS[j]))) {
                                                loc += YEARS[j].length();
                                                String afterLoc = line.substring(loc).trim();
-                        for (int i = 0;
-                                                       !gotCopyright && (i < copyright.length);
-                                                       i++) {
+                                               for (int i = 0; !gotCopyright && (i < copyright.length); i++) {
                                                        if (0 == afterLoc.indexOf(copyright[i])) {
                                                                gotCopyright = true;
                                                        }
@@ -470,240 +444,224 @@ public class Checklics extends MatchingTask {
 }
 
 class HeaderInfo {
-    /** File for which this is the info */
-    public final File file;
-    
-    /** unmodifiable List of String years */
-    public final List years;
-    
-    /** last line of license */
-    public final int lastLine;
-    
-    /** last line of license */
-    public final boolean hasLicense;
-
-    public HeaderInfo(File file, int lastLine, List years, boolean hasLicense) {
-        this.lastLine = lastLine;
-        this.file = file;
-        this.hasLicense = hasLicense;
-        List newYears = new ArrayList();
-        newYears.addAll(years);
-        Collections.sort(newYears);
-        this.years = Collections.unmodifiableList(newYears);
-        if ((null == file) || !file.canWrite()) {
-            throw new IllegalArgumentException("bad file: " + this);
-        }
-        if (!hasLicense) {
-            if ((0> lastLine) || (65 < lastLine)) {
-                throw new IllegalArgumentException("bad last line: " + this);
-            }
-        } else {            
-            if ((null == years) || (1 > years.size())) {
-                throw new IllegalArgumentException("no years: " + this);
-            }
-            if ((20 > lastLine) || (65 < lastLine)) {
-                throw new IllegalArgumentException("bad last line: " + this);
-            }
-        }
-    }
-
-    public String toString() {
-        return file.getPath() + ":" + lastLine  + " " + years;
-    }
-
-    public void writeHeader(PrintWriter writer) {
-        if (!hasLicense) {
-            writer.println(TOP);
-            writer.println(PARC_ONLY);
-            writeRest(writer);
-        } else {
-            final int size = years.size(); 
-            if (1 > size) {
-                throw new Error("no years found in " + toString());
-            }
-            String first = (String) years.get(0);
-            String last = (String) years.get(size-1);
-            boolean lastIs2002 = "2002".equals(last);
-            String xlast = last;
-            if (lastIs2002) {  // 2002 was PARC
-                xlast = (String) (size > 1 ? years.get(size-2) : null);
-                // 1999-2002 Xerox implies 1999-2001 Xerox
-                if (first.equals(xlast) && !"2001".equals(xlast)) {
-                    xlast = "2001";
-                }
-            }
-            String xyears = first + "-" + xlast;
-            if (first.equals(last)) {
-                xyears = first;
-            }
-    
-            writer.println(TOP);
-            if (!lastIs2002) {       // Xerox only
-                writer.println(XEROX_PREFIX + xyears + XEROX_SUFFIX + ". ");
-            } else if (size == 1) {    // PARC only
-                writer.println(PARC_ONLY);
-            } else {                   // XEROX plus PARC 
-                writer.println(XEROX_PREFIX + xyears + XEROX_SUFFIX + ", ");
-                writer.println(PARC);
-            }
-            writeRest(writer);
-        }
-    }
-    
-    void writeRest(PrintWriter writer) {
-        writer.println(" * All rights reserved. ");
-        writer.println(" * This program and the accompanying materials are made available ");
-        writer.println(" * under the terms of the Eclipse Public License v1.0 ");
-        writer.println(" * which accompanies this distribution and is available at ");
-        writer.println(" * http://www.eclipse.org/legal/epl-v10.html ");
-        writer.println(" *  ");
-        writer.println(" * Contributors: ");
-        writer.println(" *     Xerox/PARC     initial implementation ");
-        writer.println(" * ******************************************************************/");
-        writer.println("");
-    }
-    
-    public static final String TOP
-        = "/* *******************************************************************";
-    public static final String PARC
-        = " *               2002 Palo Alto Research Center, Incorporated (PARC).";
-    public static final String PARC_ONLY
-        = " * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).";
-    public static final String XEROX_PREFIX
-        = " * Copyright (c) ";
-    public static final String XEROX_SUFFIX
-        = " Xerox Corporation";
-    /*
-/* *******************************************************************
- * Copyright (c) 1998-2001 Xerox Corporation, 
- *               2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved. 
- * This program and the accompanying materials are made available 
- * under the terms of the Eclipse Public License v1.0 
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * 
- * Contributors:
- *     Xerox/PARC     initial implementation
- * ******************************************************************
-     
-     */
+       /** File for which this is the info */
+       public final File file;
+
+       /** unmodifiable List of String years */
+       public final List years;
+
+       /** last line of license */
+       public final int lastLine;
+
+       /** last line of license */
+       public final boolean hasLicense;
+
+       public HeaderInfo(File file, int lastLine, List years, boolean hasLicense) {
+               this.lastLine = lastLine;
+               this.file = file;
+               this.hasLicense = hasLicense;
+               List newYears = new ArrayList();
+               newYears.addAll(years);
+               Collections.sort(newYears);
+               this.years = Collections.unmodifiableList(newYears);
+               if ((null == file) || !file.canWrite()) {
+                       throw new IllegalArgumentException("bad file: " + this);
+               }
+               if (!hasLicense) {
+                       if ((0 > lastLine) || (65 < lastLine)) {
+                               throw new IllegalArgumentException("bad last line: " + this);
+                       }
+               } else {
+                       if ((null == years) || (1 > years.size())) {
+                               throw new IllegalArgumentException("no years: " + this);
+                       }
+                       if ((20 > lastLine) || (65 < lastLine)) {
+                               throw new IllegalArgumentException("bad last line: " + this);
+                       }
+               }
+       }
+
+       public String toString() {
+               return file.getPath() + ":" + lastLine + " " + years;
+       }
+
+       public void writeHeader(PrintWriter writer) {
+               if (!hasLicense) {
+                       writer.println(TOP);
+                       writer.println(PARC_ONLY);
+                       writeRest(writer);
+               } else {
+                       final int size = years.size();
+                       if (1 > size) {
+                               throw new Error("no years found in " + toString());
+                       }
+                       String first = (String) years.get(0);
+                       String last = (String) years.get(size - 1);
+                       boolean lastIs2002 = "2002".equals(last);
+                       String xlast = last;
+                       if (lastIs2002) { // 2002 was PARC
+                               xlast = (String) (size > 1 ? years.get(size - 2) : null);
+                               // 1999-2002 Xerox implies 1999-2001 Xerox
+                               if (first.equals(xlast) && !"2001".equals(xlast)) {
+                                       xlast = "2001";
+                               }
+                       }
+                       String xyears = first + "-" + xlast;
+                       if (first.equals(last)) {
+                               xyears = first;
+                       }
+
+                       writer.println(TOP);
+                       if (!lastIs2002) { // Xerox only
+                               writer.println(XEROX_PREFIX + xyears + XEROX_SUFFIX + ". ");
+                       } else if (size == 1) { // PARC only
+                               writer.println(PARC_ONLY);
+                       } else { // XEROX plus PARC
+                               writer.println(XEROX_PREFIX + xyears + XEROX_SUFFIX + ", ");
+                               writer.println(PARC);
+                       }
+                       writeRest(writer);
+               }
+       }
+
+       void writeRest(PrintWriter writer) {
+               writer.println(" * All rights reserved. ");
+               writer.println(" * This program and the accompanying materials are made available ");
+               writer.println(" * under the terms of the Eclipse Public License v1.0 ");
+               writer.println(" * which accompanies this distribution and is available at ");
+               writer.println(" * http://www.eclipse.org/legal/epl-v10.html ");
+               writer.println(" *  ");
+               writer.println(" * Contributors: ");
+               writer.println(" *     Xerox/PARC     initial implementation ");
+               writer.println(" * ******************************************************************/");
+               writer.println("");
+       }
+
+       public static final String TOP = "/* *******************************************************************";
+       public static final String PARC = " *               2002 Palo Alto Research Center, Incorporated (PARC).";
+       public static final String PARC_ONLY = " * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).";
+       public static final String XEROX_PREFIX = " * Copyright (c) ";
+       public static final String XEROX_SUFFIX = " Xerox Corporation";
+       /*
+        * /* ******************************************************************* Copyright (c) 1998-2001 Xerox Corporation, 2002 Palo
+        * Alto Research Center, Incorporated (PARC). All rights reserved. This program and the accompanying materials are made
+        * available under the terms of the Eclipse Public License v1.0 which accompanies this distribution and is available at
+        * http://www.eclipse.org/legal/epl-v10.html
+        * 
+        * Contributors: Xerox/PARC initial implementation ******************************************************************
+        */
 }
 
 /**
  * header search/replace using hokey string matching
  */
 class Header {
-    
-    /** replace the header in file */
-    public static boolean replaceHeader(File file, HeaderInfo info) {
-//        ArrayList years = new ArrayList();
-//        int endLine = 0;
-        BufferedReader input = null;
-        PrintWriter output = null;
-        FileWriter outWriter = null;
-        int lineNum = 0;
-        boolean result = false;
-        final File inFile = new File(file.getPath() + ".tmp");
-        try {
-            File outFile = new File(file.getPath());
-            if (!file.renameTo(inFile) || !inFile.canRead()) {
-                throw new Error("unable to rename " + file + " to " + inFile);
-            }
-            outWriter = new FileWriter(outFile);
-            input = new BufferedReader(new FileReader(inFile));
-            output = new PrintWriter(outWriter, true);
-            info.writeHeader(output);
-            String line;
-            while (null != (line = input.readLine())) {
-                lineNum++;
-                if (lineNum > info.lastLine) {
-                    output.println(line);
-                }
-            }
-        } catch (IOException e) {
-            System.err.println(
-                "writing line " + lineNum + " of " + file);
-            e.printStackTrace(System.err);
-            result = false;
-        } finally {
-            if (null != input) {
-                try {
-                    input.close();
-                } catch (IOException e) {
-                    result = false;
-                } 
-            }
-            if (null != outWriter) {
-                try {
-                    outWriter.close();
-                } catch (IOException e) {
-                    result = false;
-                } 
-            }
-            result = inFile.delete();
-        }
-        return result;
-    }
-    
-    public static HeaderInfo checkFile(final File file) {
-        ArrayList years = new ArrayList();
-        int endLine = 0;
-        BufferedReader input = null;
-        int lineNum = 0;
-        try {
-            input = new BufferedReader(new FileReader(file));
-            String line;
-            while (null != (line = input.readLine())) {
-                lineNum++;
-                String ll = line.trim();
-                if (ll.startsWith("package ")
-                    || ll.startsWith("import ")) {
-                    break;  // ignore default package w/o imports
-                }
-                if (checkLine(line, years)) {
-                    endLine = lineNum;
-                    break;
-                }                    
-            }
-        } catch (IOException e) {
-            System.err.println(
-                "reading line " + lineNum + " of " + file);
-            e.printStackTrace(System.err);
-        } finally {
-            if (null != input) {
-                try {
-                    input.close();
-                } catch (IOException e) {
-                } // ignore
-            }
-        }
-        return new HeaderInfo(file, endLine, years, endLine > 0);
-    }
-
-    /**
-     * Add any years found (as String) to years,
-     * and return true at the first end-of-comment
-     * @return true if this line has end-of-comment
-     */
-    private static boolean checkLine(String line, ArrayList years) {
-        if ((null == line) || (0 == line.length())) {
-            return false;
-        }
-        int loc;
-        int start = 0;
-        
-        while ((-1 != (loc = line.indexOf("199", start))
-                || (-1 != (loc = line.indexOf("200", start))))) {
-            char c = line.charAt(loc + 3);
-            if ((c <= '9') && (c >= '0')) {
-                years.add(line.substring(loc, loc+4));
-            }
-            start = loc + 4;
-        }
-        
-        return (-1 != line.indexOf("*/"));
-    }
+
+       /** replace the header in file */
+       public static boolean replaceHeader(File file, HeaderInfo info) {
+               // ArrayList years = new ArrayList();
+               // int endLine = 0;
+               BufferedReader input = null;
+               PrintWriter output = null;
+               FileWriter outWriter = null;
+               int lineNum = 0;
+               boolean result = false;
+               final File inFile = new File(file.getPath() + ".tmp");
+               try {
+                       File outFile = new File(file.getPath());
+                       if (!file.renameTo(inFile) || !inFile.canRead()) {
+                               throw new Error("unable to rename " + file + " to " + inFile);
+                       }
+                       outWriter = new FileWriter(outFile);
+                       input = new BufferedReader(new FileReader(inFile));
+                       output = new PrintWriter(outWriter, true);
+                       info.writeHeader(output);
+                       String line;
+                       while (null != (line = input.readLine())) {
+                               lineNum++;
+                               if (lineNum > info.lastLine) {
+                                       output.println(line);
+                               }
+                       }
+               } catch (IOException e) {
+                       System.err.println("writing line " + lineNum + " of " + file);
+                       e.printStackTrace(System.err);
+                       result = false;
+               } finally {
+                       if (null != input) {
+                               try {
+                                       input.close();
+                               } catch (IOException e) {
+                                       result = false;
+                               }
+                       }
+                       if (null != outWriter) {
+                               try {
+                                       outWriter.close();
+                               } catch (IOException e) {
+                                       result = false;
+                               }
+                       }
+                       result = inFile.delete();
+               }
+               return result;
+       }
+
+       public static HeaderInfo checkFile(final File file) {
+               ArrayList years = new ArrayList();
+               int endLine = 0;
+               BufferedReader input = null;
+               int lineNum = 0;
+               try {
+                       input = new BufferedReader(new FileReader(file));
+                       String line;
+                       while (null != (line = input.readLine())) {
+                               lineNum++;
+                               String ll = line.trim();
+                               if (ll.startsWith("package ") || ll.startsWith("import ")) {
+                                       break; // ignore default package w/o imports
+                               }
+                               if (checkLine(line, years)) {
+                                       endLine = lineNum;
+                                       break;
+                               }
+                       }
+               } catch (IOException e) {
+                       System.err.println("reading line " + lineNum + " of " + file);
+                       e.printStackTrace(System.err);
+               } finally {
+                       if (null != input) {
+                               try {
+                                       input.close();
+                               } catch (IOException e) {
+                               } // ignore
+                       }
+               }
+               return new HeaderInfo(file, endLine, years, endLine > 0);
+       }
+
+       /**
+        * Add any years found (as String) to years, and return true at the first end-of-comment
+        * 
+        * @return true if this line has end-of-comment
+        */
+       private static boolean checkLine(String line, ArrayList years) {
+               if ((null == line) || (0 == line.length())) {
+                       return false;
+               }
+               int loc;
+               int start = 0;
+
+               while ((-1 != (loc = line.indexOf("199", start)) || (-1 != (loc = line.indexOf("200", start))))) {
+                       char c = line.charAt(loc + 3);
+                       if ((c <= '9') && (c >= '0')) {
+                               years.add(line.substring(loc, loc + 4));
+                       }
+                       start = loc + 4;
+               }
+
+               return (-1 != line.indexOf("*/"));
+       }
 
 } // class Header