Inject IO object, hopefully more testable

git-svn-id: https://svn.apache.org/repos/asf/creadur/tentacles/trunk@1462791 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/creadur/tentacles/Deauthorize.java b/src/main/java/org/apache/creadur/tentacles/Deauthorize.java
index 224d3a2..66cd5b5 100644
--- a/src/main/java/org/apache/creadur/tentacles/Deauthorize.java
+++ b/src/main/java/org/apache/creadur/tentacles/Deauthorize.java
@@ -97,6 +97,11 @@
      * @throws IOException
      */
     private static void deauthorize(final File dir) throws IOException {
+        deauthorize(dir, new IOSystem());
+    }
+
+    private static void deauthorize(final File dir, final IOSystem io)
+            throws IOException {
         for (final File file : new FileSystem().collect(dir, ".*\\.java")) {
 
             if (not(file.canRead(), "File not readable: %s",
@@ -104,7 +109,7 @@
                 continue;
             }
 
-            final String text = IO.slurp(file);
+            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";
@@ -137,7 +142,7 @@
                                 }
                             });
 
-            final byte[] content = IO.read(in);
+            final byte[] content = io.read(in);
 
             if (content.length != file.length()) {
 
@@ -146,7 +151,7 @@
                     continue;
                 }
 
-                IO.copy(content, file);
+                io.copy(content, file);
             }
         }
     }
diff --git a/src/main/java/org/apache/creadur/tentacles/IO.java b/src/main/java/org/apache/creadur/tentacles/IOSystem.java
similarity index 79%
rename from src/main/java/org/apache/creadur/tentacles/IO.java
rename to src/main/java/org/apache/creadur/tentacles/IOSystem.java
index 0a2bf31..6752b2b 100644
--- a/src/main/java/org/apache/creadur/tentacles/IO.java
+++ b/src/main/java/org/apache/creadur/tentacles/IOSystem.java
@@ -37,21 +37,21 @@
 /**
  * @version $Rev$ $Date$
  */
-public class IO {
+public class IOSystem {
 
-    public static String slurp(final File file) throws IOException {
+    public String slurp(final File file) throws IOException {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
         copy(file, out);
         return new String(out.toByteArray());
     }
 
-    public static String slurp(final URL url) throws IOException {
+    public String slurp(final URL url) throws IOException {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
         copy(url.openStream(), out);
         return new String(out.toByteArray());
     }
 
-    public static void writeString(final File file, final String string)
+    public void writeString(final File file, final String string)
             throws IOException {
         final FileWriter out = new FileWriter(file);
         try {
@@ -67,7 +67,7 @@
         }
     }
 
-    private static void copy(final File from, final OutputStream to)
+    private void copy(final File from, final OutputStream to)
             throws IOException {
         final InputStream read = read(from);
         try {
@@ -77,8 +77,7 @@
         }
     }
 
-    public static void copy(final InputStream from, final File to)
-            throws IOException {
+    public void copy(final InputStream from, final File to) throws IOException {
         final OutputStream write = write(to);
         try {
             copy(from, write);
@@ -87,7 +86,7 @@
         }
     }
 
-    private static void copy(final InputStream from, final OutputStream to)
+    private void copy(final InputStream from, final OutputStream to)
             throws IOException {
         final byte[] buffer = new byte[1024];
         int length = 0;
@@ -97,17 +96,16 @@
         to.flush();
     }
 
-    public static void copy(final byte[] from, final File to)
-            throws IOException {
+    public void copy(final byte[] from, final File to) throws IOException {
         copy(new ByteArrayInputStream(from), to);
     }
 
-    public static ZipInputStream unzip(final File file) throws IOException {
+    public ZipInputStream unzip(final File file) throws IOException {
         final InputStream read = read(file);
         return new ZipInputStream(read);
     }
 
-    public static void close(final Closeable closeable) throws IOException {
+    public void close(final Closeable closeable) throws IOException {
         if (closeable == null) {
             return;
         }
@@ -123,19 +121,18 @@
         }
     }
 
-    public static OutputStream write(final File destination)
+    public OutputStream write(final File destination)
             throws FileNotFoundException {
         final OutputStream out = new FileOutputStream(destination);
         return new BufferedOutputStream(out, 32768);
     }
 
-    public static InputStream read(final File source)
-            throws FileNotFoundException {
+    public InputStream read(final File source) throws FileNotFoundException {
         final InputStream in = new FileInputStream(source);
         return new BufferedInputStream(in, 32768);
     }
 
-    public static byte[] read(final InputStream in) throws IOException {
+    public byte[] read(final InputStream in) throws IOException {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
         copy(in, out);
         out.close();
diff --git a/src/main/java/org/apache/creadur/tentacles/Main.java b/src/main/java/org/apache/creadur/tentacles/Main.java
index 72ae690..d3b2e93 100644
--- a/src/main/java/org/apache/creadur/tentacles/Main.java
+++ b/src/main/java/org/apache/creadur/tentacles/Main.java
@@ -64,21 +64,24 @@
 
     private final Configuration configuration;
     private final FileSystem fileSystem;
+    private final IOSystem ioSystem;
 
     public Main(final String... args) throws Exception {
-        this(new Configuration(args), new FileSystem());
-    }
-
-    public Main(final Configuration configuration, final FileSystem fileSystem)
-            throws Exception {
-        this(configuration, fileSystem, new NexusClient(fileSystem));
+        this(new Configuration(args), new FileSystem(), new IOSystem());
     }
 
     public Main(final Configuration configuration, final FileSystem fileSystem,
-            final NexusClient client) throws Exception {
+            final IOSystem ioSystem) throws Exception {
+        this(configuration, fileSystem, new NexusClient(fileSystem, ioSystem),
+                ioSystem);
+    }
+
+    public Main(final Configuration configuration, final FileSystem fileSystem,
+            final NexusClient client, final IOSystem ioSystem) throws Exception {
         this.client = client;
         this.configuration = configuration;
         this.fileSystem = fileSystem;
+        this.ioSystem = ioSystem;
 
         this.local =
                 new File(this.configuration.getRootDirectoryForLocalOutput());
@@ -99,7 +102,7 @@
 
         final URL style =
                 this.getClass().getClassLoader().getResource("legal/style.css");
-        IO.copy(style.openStream(), new File(this.local, "style.css"));
+        ioSystem.copy(style.openStream(), new File(this.local, "style.css"));
 
         licenses("asl-2.0");
         licenses("cpl-1.0");
@@ -110,7 +113,7 @@
         final URL aslURL =
                 this.getClass().getClassLoader()
                         .getResource("licenses/" + s + ".txt");
-        this.licenses.put(s, IO.slurp(aslURL).trim());
+        this.licenses.put(s, this.ioSystem.slurp(aslURL).trim());
     }
 
     public static void main(final String[] args) throws Exception {
@@ -135,8 +138,8 @@
             archives.add(archive);
         }
 
-        Templates.template("legal/archives.vm").add("archives", archives)
-                .add("reports", this.reports)
+        Templates.template("legal/archives.vm", this.ioSystem)
+                .add("archives", archives).add("reports", this.reports)
                 .write(new File(this.local, "archives.html"));
 
         reportLicenses(archives);
@@ -149,7 +152,7 @@
             throws IOException {
         initLicenses(archives);
 
-        Templates.template("legal/licenses.vm")
+        Templates.template("legal/licenses.vm", this.ioSystem)
                 .add("licenses", getLicenses(archives))
                 .add("reports", this.reports)
                 .write(new File(this.local, "licenses.html"));
@@ -163,7 +166,7 @@
                     this.fileSystem.collect(contents(archive.getFile()),
                             new LicenseFilter());
             for (final File file : files) {
-                final License license = new License(IO.slurp(file));
+                final License license = new License(this.ioSystem.slurp(file));
 
                 License existing = licenses.get(license);
                 if (existing == null) {
@@ -196,7 +199,7 @@
         for (final Archive archive : archives) {
 
             Templates
-                    .template("legal/archive-licenses.vm")
+                    .template("legal/archive-licenses.vm", this.ioSystem)
                     .add("archive", archive)
                     .add("reports", this.reports)
                     .write(new File(this.local, this.reports.licenses(archive)));
@@ -215,7 +218,7 @@
 
         for (final File file : files) {
 
-            final License license = new License(IO.slurp(file));
+            final License license = new License(this.ioSystem.slurp(file));
 
             undeclared.remove(license);
 
@@ -253,7 +256,7 @@
 
             for (final File file : files) {
 
-                final Notice notice = new Notice(IO.slurp(file));
+                final Notice notice = new Notice(this.ioSystem.slurp(file));
 
                 undeclared.remove(notice);
             }
@@ -274,7 +277,7 @@
                 }
             }
 
-            Templates.template("legal/archive-notices.vm")
+            Templates.template("legal/archive-notices.vm", this.ioSystem)
                     .add("archive", archive).add("reports", this.reports)
                     .write(new File(this.local, this.reports.notices(archive)));
         }
@@ -288,7 +291,7 @@
                     this.fileSystem.collect(contents(archive.getFile()),
                             new NoticeFilter());
             for (final File file : files) {
-                final Notice notice = new Notice(IO.slurp(file));
+                final Notice notice = new Notice(this.ioSystem.slurp(file));
 
                 Notice existing = notices.get(notice);
                 if (existing == null) {
@@ -302,8 +305,8 @@
             }
         }
 
-        Templates.template("legal/notices.vm").add("notices", notices.values())
-                .add("reports", this.reports)
+        Templates.template("legal/notices.vm", this.ioSystem)
+                .add("notices", notices.values()).add("reports", this.reports)
                 .write(new File(this.local, "notices.html"));
     }
 
@@ -379,7 +382,7 @@
         log.info("Unpack " + archive);
 
         try {
-            final ZipInputStream zip = IO.unzip(archive);
+            final ZipInputStream zip = this.ioSystem.unzip(archive);
 
             final File contents = contents(archive);
 
@@ -400,14 +403,14 @@
 
                     // Open the output file
 
-                    IO.copy(zip, fileEntry);
+                    this.ioSystem.copy(zip, fileEntry);
 
                     if (fileEntry.getName().endsWith(".jar")) {
                         unpack(fileEntry);
                     }
                 }
             } finally {
-                IO.close(zip);
+                this.ioSystem.close(zip);
             }
         } catch (final IOException e) {
             log.error("Not a zip " + archive);
@@ -587,7 +590,7 @@
 
         this.fileSystem.mkparent(file);
 
-        IO.copy(IO.read(src), file);
+        this.ioSystem.copy(this.ioSystem.read(src), file);
 
         return file;
     }
diff --git a/src/main/java/org/apache/creadur/tentacles/NexusClient.java b/src/main/java/org/apache/creadur/tentacles/NexusClient.java
index 59bbbd5..2418763 100644
--- a/src/main/java/org/apache/creadur/tentacles/NexusClient.java
+++ b/src/main/java/org/apache/creadur/tentacles/NexusClient.java
@@ -37,10 +37,12 @@
 
     private final DefaultHttpClient client;
     private final FileSystem fileSystem;
+    private final IOSystem ioSystem;
 
-    public NexusClient(final FileSystem fileSystem) {
+    public NexusClient(final FileSystem fileSystem, final IOSystem ioSystem) {
         this.client = new DefaultHttpClient();
         this.fileSystem = fileSystem;
+        this.ioSystem = ioSystem;
     }
 
     public File download(final URI uri, final File file) throws IOException {
@@ -64,7 +66,7 @@
 
         this.fileSystem.mkparent(file);
 
-        IO.copy(content, file);
+        this.ioSystem.copy(content, file);
 
         return file;
     }
diff --git a/src/main/java/org/apache/creadur/tentacles/Templates.java b/src/main/java/org/apache/creadur/tentacles/Templates.java
index accb346..f7f1d5d 100644
--- a/src/main/java/org/apache/creadur/tentacles/Templates.java
+++ b/src/main/java/org/apache/creadur/tentacles/Templates.java
@@ -37,46 +37,60 @@
     private final VelocityEngine engine;
 
     private Templates() {
-        Properties properties = new Properties();
+        final Properties properties = new Properties();
         properties.setProperty("file.resource.loader.cache", "true");
         properties.setProperty("resource.loader", "file, class");
-        properties.setProperty("class.resource.loader.description", "Velocity Classpath Resource Loader");
-        properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
-        properties.setProperty("runtime.log.logsystem.class", CommonsLogLogChute.class.getName());
-        properties.setProperty("runtime.log.logsystem.commons.logging.name", Templates.class.getName());
+        properties.setProperty("class.resource.loader.description",
+                "Velocity Classpath Resource Loader");
+        properties
+                .setProperty("class.resource.loader.class",
+                        "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+        properties.setProperty("runtime.log.logsystem.class",
+                CommonsLogLogChute.class.getName());
+        properties.setProperty("runtime.log.logsystem.commons.logging.name",
+                Templates.class.getName());
 
-        engine = new VelocityEngine();
-        engine.init(properties);
+        this.engine = new VelocityEngine();
+        this.engine.init(properties);
     }
 
-    private void evaluate(String template, Map<String, Object> mapContext, Writer writer) throws IOException {
+    private void evaluate(final String template,
+            final Map<String, Object> mapContext, final Writer writer)
+            throws IOException {
 
-        URL resource = Thread.currentThread().getContextClassLoader().getResource(template);
+        final URL resource =
+                Thread.currentThread().getContextClassLoader()
+                        .getResource(template);
 
-        if (resource == null) throw new IllegalStateException(template);
+        if (resource == null) {
+            throw new IllegalStateException(template);
+        }
 
-        VelocityContext context = new VelocityContext(mapContext);
-        engine.evaluate(context, writer, Templates.class.getName(), new InputStreamReader(resource.openStream()));
+        final VelocityContext context = new VelocityContext(mapContext);
+        this.engine.evaluate(context, writer, Templates.class.getName(),
+                new InputStreamReader(resource.openStream()));
     }
 
-    public static Builder template(String name) {
-        return INSTANCE.new Builder(name);
+    public static Builder template(final String name, final IOSystem ioSystem) {
+        return INSTANCE.new Builder(name, ioSystem);
     }
 
     public class Builder {
+        private final IOSystem ioSystem;
         private final String template;
         private final Map<String, Object> map = new HashMap<String, Object>();
 
-        public Builder(String template) {
+        public Builder(final String template, final IOSystem ioSystem) {
             this.template = template;
+            this.ioSystem = ioSystem;
         }
 
-        public Builder add(String key, Object value) {
-            map.put(key, value);
+        public Builder add(final String key, final Object value) {
+            this.map.put(key, value);
             return this;
         }
 
-        public Builder addAll(Map<String, Object> map) {
+        public Builder addAll(final Map<String, Object> map) {
             this.map.putAll(map);
             return this;
         }
@@ -85,16 +99,17 @@
             final StringWriter writer = new StringWriter();
 
             try {
-                evaluate(template, map, writer);
-            } catch (IOException ioe) {
-                throw new RuntimeException("can't apply template " + template, ioe);
+                evaluate(this.template, this.map, writer);
+            } catch (final IOException ioe) {
+                throw new RuntimeException("can't apply template "
+                        + this.template, ioe);
             }
 
             return writer.toString();
         }
 
-        public File write(File file) throws IOException {
-            IO.writeString(file, apply());
+        public File write(final File file) throws IOException {
+            this.ioSystem.writeString(file, apply());
             return file;
         }
     }