Little utility that will yank the author comments from java files.

If the resulting comment block is effectively empty, it will be yanked too.


git-svn-id: https://svn.apache.org/repos/asf/incubator/rat/tentacles/trunk@1214594 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index ff7ae5a..d9216bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,7 +67,7 @@
     <dependency>
       <groupId>org.codehaus.swizzle</groupId>
       <artifactId>swizzle-stream</artifactId>
-      <version>1.6.1</version>
+      <version>1.6.2-SNAPSHOT</version>
     </dependency>
 
     <dependency>
diff --git a/src/main/java/org/apache/rat/tentacles/Deauthorize.java b/src/main/java/org/apache/rat/tentacles/Deauthorize.java
new file mode 100644
index 0000000..6e096f4
--- /dev/null
+++ b/src/main/java/org/apache/rat/tentacles/Deauthorize.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.rat.tentacles;
+
+import org.codehaus.swizzle.stream.DelimitedTokenReplacementInputStream;
+import org.codehaus.swizzle.stream.ExcludeFilterInputStream;
+import org.codehaus.swizzle.stream.StringTokenHandler;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Little utility that will yank the author comments from java files.
+ *
+ * If the resulting comment block is effectively empty, it will be yanked too.
+ */
+public class Deauthorize {
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length == 0) throw new IllegalArgumentException("At least one directory must be specified");
+
+        final List<File> dirs = new ArrayList<File>();
+
+        // Check the input args upfront
+        for (String arg : args) {
+            final File dir = new File(arg);
+
+            if (not(dir.exists(), "Does not exist: %s", arg)) continue;
+            if (not(dir.isDirectory(), "Not a directory: %s", arg)) continue;
+
+            dirs.add(dir);
+        }
+
+        // Exit if we got bad input
+        if (dirs.size() != args.length) System.exit(1);
+
+        // Go!
+        for (File dir : dirs) {
+            deauthorize(dir);
+        }
+    }
+
+    private static void deauthorize(File dir) throws IOException {
+        for (File file : Files.collect(dir, ".*\\.java")) {
+
+            if (not(file.canRead(), "File not readable: %s", file.getAbsolutePath())) continue;
+
+            final String text = IO.slurp(file);
+
+            // You really can't trust text to be in the native line ending
+            final String eol = (text.contains("\r\n")) ? "\r\n" : "\n";
+
+            InputStream in = new ByteArrayInputStream(text.getBytes());
+
+            // Yank author tags
+            in = new ExcludeFilterInputStream(in, " * @author", eol);
+
+            // Clean "empty" comments
+            final String begin = eol + "/*";
+            final String end = "*/" + eol;
+            in = new DelimitedTokenReplacementInputStream(in, begin, end, new StringTokenHandler() {
+                @Override
+                public String handleToken(String s) throws IOException {
+
+                    if (s.replaceAll("[\\s*]", "").length() == 0) return eol;
+
+                    return begin + s + end;
+                }
+            });
+
+            byte[] content = IO.read(in);
+
+            if (content.length != file.length()) {
+
+                if (not(file.canWrite(), "File not writable: %s", file.getAbsolutePath())) continue;
+
+                IO.copy(content, file);
+            }
+        }
+    }
+
+    private static boolean not(boolean b, String message, Object... details) {
+        System.err.printf(message, details);
+        System.err.println();
+        return b;
+    }
+}
diff --git a/src/main/java/org/apache/rat/tentacles/Files.java b/src/main/java/org/apache/rat/tentacles/Files.java
new file mode 100644
index 0000000..d3a664c
--- /dev/null
+++ b/src/main/java/org/apache/rat/tentacles/Files.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.rat.tentacles;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class Files {
+
+    public static List<File> collect(final File dir, final String regex) {
+        return collect(dir, Pattern.compile(regex));
+    }
+
+    public static List<File> collect(final File dir, final Pattern pattern) {
+        return collect(dir, new FileFilter() {
+            @Override
+            public boolean accept(File file) {
+                return pattern.matcher(file.getAbsolutePath()).matches();
+            }
+        });
+    }
+
+
+    public static List<File> collect(File dir, FileFilter filter) {
+        final List<File> accepted = new ArrayList<File>();
+        if (filter.accept(dir)) accepted.add(dir);
+
+        final File[] files = dir.listFiles();
+        if (files != null) for (File file : files) {
+            accepted.addAll(collect(file, filter));
+        }
+
+        return accepted;
+    }
+
+    public static void exists(File file, String s) {
+        if (!file.exists()) throw new RuntimeException(s + " does not exist: " + file.getAbsolutePath());
+    }
+
+    public static void dir(File file) {
+        if (!file.isDirectory()) throw new RuntimeException("Not a directory: " + file.getAbsolutePath());
+    }
+
+    public static void file(File file) {
+        if (!file.isFile()) throw new RuntimeException("Not a file: " + file.getAbsolutePath());
+    }
+
+    public static void writable(File file) {
+        if (!file.canWrite()) throw new RuntimeException("Not writable: " + file.getAbsolutePath());
+    }
+
+    public static void readable(File file) {
+        if (!file.canRead()) throw new RuntimeException("Not readable: " + file.getAbsolutePath());
+    }
+
+    public static void mkdir(File file) {
+        if (file.exists()) return;
+        if (!file.mkdirs()) throw new RuntimeException("Cannot mkdir: " + file.getAbsolutePath());
+    }
+}
diff --git a/src/main/java/org/apache/rat/tentacles/IOUtil.java b/src/main/java/org/apache/rat/tentacles/IO.java
similarity index 90%
rename from src/main/java/org/apache/rat/tentacles/IOUtil.java
rename to src/main/java/org/apache/rat/tentacles/IO.java
index 0e31e2e..c8a641b 100644
--- a/src/main/java/org/apache/rat/tentacles/IOUtil.java
+++ b/src/main/java/org/apache/rat/tentacles/IO.java
@@ -20,6 +20,7 @@
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.File;
@@ -40,9 +41,9 @@
 /**
  * @version $Rev$ $Date$
  */
-public class IOUtil {
+public class IO {
 
-    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(IOUtil.class);
+    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(IO.class);
 
     public static String readString(URL url) throws IOException {
         final InputStream in = url.openStream();
@@ -127,6 +128,14 @@
         to.flush();
     }
 
+    public static void copy(byte[] from, File to) throws IOException {
+        copy(new ByteArrayInputStream(from), to);
+    }
+
+    public static void copy(byte[] from, OutputStream to) throws IOException {
+        copy(new ByteArrayInputStream(from), to);
+    }
+
     public static ZipOutputStream zip(File file) throws IOException {
         final OutputStream write = write(file);
         return new ZipOutputStream(write);
@@ -175,4 +184,11 @@
         final InputStream in = new FileInputStream(source);
         return new BufferedInputStream(in, 32768);
     }
+
+    public static byte[] read(InputStream in) throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        copy(in, out);
+        out.close();
+        return out.toByteArray();
+    }
 }
diff --git a/src/main/java/org/apache/rat/tentacles/Main.java b/src/main/java/org/apache/rat/tentacles/Main.java
index 7621677..9ff7ae1 100644
--- a/src/main/java/org/apache/rat/tentacles/Main.java
+++ b/src/main/java/org/apache/rat/tentacles/Main.java
@@ -99,7 +99,7 @@
 
         this.filter = System.getProperty("filter", "org/apache/openejb");
         final URL style = this.getClass().getClassLoader().getResource("legal/style.css");
-        IOUtil.copy(style.openStream(), new File(local, "style.css"));
+        IO.copy(style.openStream(), new File(local, "style.css"));
 
         licenses("asl-2.0");
         licenses("cpl-1.0");
@@ -118,7 +118,7 @@
 
     private void licenses(String s) throws IOException {
         URL aslURL = this.getClass().getClassLoader().getResource("licenses/" + s + ".txt");
-        licenses.put(s, IOUtil.slurp(aslURL).trim());
+        licenses.put(s, IO.slurp(aslURL).trim());
     }
 
     public static void main(String[] args) throws Exception {
@@ -129,7 +129,7 @@
 
         prepare();
 
-        final List<File> jars = collect(repository, new FileFilter() {
+        final List<File> jars = Files.collect(repository, new FileFilter() {
             @Override
             public boolean accept(File pathname) {
                 return pathname.isFile();
@@ -166,9 +166,9 @@
         Map<License, License> licenses = new HashMap<License, License>();
 
         for (Archive archive : archives) {
-            List<File> files = collect(contents(archive.getFile()), new LicenseFilter());
+            List<File> files = Files.collect(contents(archive.getFile()), new LicenseFilter());
             for (File file : files) {
-                final License license = new License(IOUtil.slurp(file));
+                final License license = new License(IO.slurp(file));
 
                 License existing = licenses.get(license);
                 if (existing == null) {
@@ -211,11 +211,11 @@
         final Set<License> undeclared = new HashSet<License>(archive.getLicenses());
 
         final File contents = contents(archive.getFile());
-        final List<File> files = collect(contents, new Filters(new DeclaredFilter(contents), new LicenseFilter()));
+        final List<File> files = Files.collect(contents, new Filters(new DeclaredFilter(contents), new LicenseFilter()));
 
         for (File file : files) {
 
-            final License license = new License(IOUtil.slurp(file));
+            final License license = new License(IO.slurp(file));
 
             undeclared.remove(license);
 
@@ -245,11 +245,11 @@
             final Set<Notice> undeclared = new HashSet<Notice>(archive.getNotices());
 
             final File contents = contents(archive.getFile());
-            final List<File> files = collect(contents, new Filters(new DeclaredFilter(contents), new NoticeFilter()));
+            final List<File> files = Files.collect(contents, new Filters(new DeclaredFilter(contents), new NoticeFilter()));
 
             for (File file : files) {
 
-                final Notice notice = new Notice(IOUtil.slurp(file));
+                final Notice notice = new Notice(IO.slurp(file));
 
                 undeclared.remove(notice);
             }
@@ -281,9 +281,9 @@
         Map<Notice, Notice> notices = new HashMap<Notice, Notice>();
 
         for (Archive archive : archives) {
-            List<File> files = collect(contents(archive.getFile()), new NoticeFilter());
+            List<File> files = Files.collect(contents(archive.getFile()), new NoticeFilter());
             for (File file : files) {
-                final Notice notice = new Notice(IOUtil.slurp(file));
+                final Notice notice = new Notice(IO.slurp(file));
 
                 Notice existing = notices.get(notice);
                 if (existing == null) {
@@ -316,7 +316,7 @@
 
 
     private List<URI> allNoticeFiles() {
-        List<File> legal = collect(content, new LegalFilter());
+        List<File> legal = Files.collect(content, new LegalFilter());
         for (File file : legal) {
             log.info("Legal " + file);
         }
@@ -342,7 +342,7 @@
             }
         } else if (staging.toString().startsWith("file:")) {
             File file = new File(staging);
-            List<File> collect = collect(file, new FileFilter() {
+            List<File> collect = Files.collect(file, new FileFilter() {
                 @Override
                 public boolean accept(File pathname) {
                     String path = pathname.getAbsolutePath();
@@ -364,7 +364,7 @@
         log.info("Unpack " + archive);
 
         try {
-            final ZipInputStream zip = IOUtil.unzip(archive);
+            final ZipInputStream zip = IO.unzip(archive);
 
             final File contents = contents(archive);
 
@@ -383,14 +383,14 @@
 
                     // Open the output file
 
-                    IOUtil.copy(zip, fileEntry);
+                    IO.copy(zip, fileEntry);
 
                     if (fileEntry.getName().endsWith(".jar")) {
                         unpack(fileEntry);
                     }
                 }
             } finally {
-                IOUtil.close(zip);
+                IO.close(zip);
             }
         } catch (IOException e) {
             log.error("Not a zip " + archive);
@@ -520,18 +520,6 @@
 
     }
 
-    public List<File> collect(File dir, FileFilter filter) {
-        final List<File> accepted = new ArrayList<File>();
-        if (filter.accept(dir)) accepted.add(dir);
-
-        final File[] files = dir.listFiles();
-        if (files != null) for (File file : files) {
-            accepted.addAll(collect(file, filter));
-        }
-
-        return accepted;
-    }
-
     private File contents(File archive) {
         String path = archive.getAbsolutePath().substring(local.getAbsolutePath().length() + 1);
 
@@ -567,7 +555,7 @@
 
         mkparent(file);
 
-        IOUtil.copy(content, file);
+        IO.copy(content, file);
 
         return file;
     }
@@ -581,7 +569,7 @@
 
         mkparent(file);
 
-        IOUtil.copy(IOUtil.read(src), file);
+        IO.copy(IO.read(src), file);
 
         return file;
     }
@@ -741,7 +729,7 @@
 
         private Map<URI, URI> mapOther() {
             final File jarContents = contents(file);
-            final List<File> legal = collect(jarContents, new Filters(new N(new DeclaredFilter(jarContents)), new LegalFilter()));
+            final List<File> legal = Files.collect(jarContents, new Filters(new N(new DeclaredFilter(jarContents)), new LegalFilter()));
 
             Map<URI, URI> map = new LinkedHashMap<URI, URI>();
             for (File file : legal) {
@@ -755,7 +743,7 @@
 
         private Map<URI, URI> map() {
             final File jarContents = contents(file);
-            final List<File> legal = collect(jarContents, new Filters(new DeclaredFilter(jarContents), new LegalFilter()));
+            final List<File> legal = Files.collect(jarContents, new Filters(new DeclaredFilter(jarContents), new LegalFilter()));
 
             Map<URI, URI> map = new LinkedHashMap<URI, URI>();
             for (File file : legal) {
diff --git a/src/main/java/org/apache/rat/tentacles/Templates.java b/src/main/java/org/apache/rat/tentacles/Templates.java
index 187df54..f8ff968 100644
--- a/src/main/java/org/apache/rat/tentacles/Templates.java
+++ b/src/main/java/org/apache/rat/tentacles/Templates.java
@@ -165,7 +165,7 @@
         }
 
         public File write(File file) throws IOException {
-            IOUtil.writeString(file, apply());
+            IO.writeString(file, apply());
             return file;
         }
     }