/*
 * Copyright 2014 Andrew Holland.
 *
 * Licensed 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 uk.co.a1dutch.zipper;

import static uk.co.a1dutch.zipper.ArchiveUtils.*;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class offers a fluent api to decompress and unpackage a zip archive.
 * <p>
 * The following code shows how to unzip an archive:
 * </p>
 * 
 * <pre>
 * Unzipper.archive(myArchive).to(outputDirectory).unzip();
 * </pre>
 * 
 * @author a1dutch
 * @since 1.0.0
 */
public class Unzipper {

    private Logger log = LoggerFactory.getLogger(getClass());

    private File archive;
    private File outputDirectory;

    /**
     * Returns a new Unzipper for the given archive.
     * 
     * @param archive
     *            the archive to be unzipped.
     * 
     * @return a {@link Unzipper} used to collect all parameters.
     */
    public static Unzipper archive(String archive) {
        return archive(new File(archive));
    }

    /**
     * Returns a new Unzipper for the given archive.
     * 
     * @param archive
     *            the archive to be unzipped.
     * 
     * @return a {@link Unzipper} used to collect all parameters.
     */
    public static Unzipper archive(File archive) {
        return new Unzipper(archive);
    }

    private Unzipper(File archive) {
        this.archive = archive;
    }

    /**
     * Sets the directory where the archive should be unzipped too.
     * 
     * @param outputDirectory
     *            the directory where to unzip the archive too.
     * 
     * @return a {@link Unzipper} used to collect all parameters.
     */
    public Unzipper to(File outputDirectory) {
        this.outputDirectory = outputDirectory;
        return this;
    }

    /**
     * Sets the directory where the archive should be unzipped too.
     * 
     * @param outputDirectory
     *            the directory where to unzip the archive too.
     * 
     * @return a {@link Unzipper} used to collect all parameters.
     */
    public Unzipper to(String outputDirectory) {
        return to(new File(normalisePath(outputDirectory)));
    }

    /**
     * Unzips the archive to the given output directory.
     */
    public void unzip() {
        try {
            log.info("unzipping archive: {} into {}", archive, outputDirectory);
            ZipFile zip = new ZipFile(archive);
            for (Enumeration<? extends ZipEntry> elements = zip.entries(); elements.hasMoreElements();) {
                ZipEntry entry = elements.nextElement();

                String outputName = outputDirectory + "/" + entry.getName();
                if (log.isDebugEnabled()) {
                    log.debug("unzipping entry: {}", entry.getName());
                }

                if (entry.isDirectory()) {
                    new File(outputName).mkdirs();
                    continue;
                }

                try (BufferedInputStream bis = new BufferedInputStream(zip.getInputStream(entry));
                        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(outputName)))) {
                    byte[] buffer = new byte[1024];
                    int read = 0;
                    while ((read = bis.read(buffer)) != -1) {
                        bos.write(buffer, 0, read);
                    }
                }
            }
            log.info("unzipped {} entries", zip.size());
            zip.close();
        } catch (IOException e) {
            log.error("failed unzipping archive, {}", e.getMessage());
            throw new UnzipperRuntimeException("Failed to unzip archive", e);
        }
    }
}

@@ -3084,16 +3084,21 @@
         
+try (
 ZipFile 
@@ -3119,26 +3119,32 @@
 ile(archive)
-;%0A
+) %7B%0A    
             
@@ -3253,16 +3253,20 @@
         
+    
 ZipEntry
@@ -3315,16 +3315,20 @@
         
+ 
+   
 String o
@@ -3392,24 +3392,28 @@
             
+    
 if (log.isDe
@@ -3444,24 +3444,28 @@
             
+  
+  
 log.debug(%22u
@@ -3511,32 +3511,36 @@
                 
+    
 %7D%0A%0A             
@@ -3538,24 +3538,28 @@
             
+  
+  
 if (entry.is
@@ -3569,24 +3569,28 @@
 ectory()) %7B%0A
+    
             
@@ -3648,16 +3648,20 @@
         
+   
+ 
 continue
@@ -3670,35 +3670,43 @@
                 
-%7D%0A%0A
+    %7D%0A%0A    
                 
@@ -3812,16 +3812,20 @@
         
+    
 Buffered
@@ -3890,32 +3890,69 @@
 Stream(new File(
+%0A                                    
 outputName)))) %7B
@@ -3948,24 +3948,28 @@
 tName)))) %7B%0A
+    
             
@@ -4028,16 +4028,20 @@
         
+    
 int read
@@ -4066,16 +4066,20 @@
         
+   
+ 
 while ((
@@ -4136,16 +4136,20 @@
         
+    
 bos.writ
@@ -4168,16 +4168,20 @@
  read);%0A
+    
         
@@ -4202,34 +4202,42 @@
                 
-%7D%0A
+    %7D%0A    
             %7D%0A  
@@ -4238,32 +4238,36 @@
   %7D%0A            
+    
 log.info(%22unzipp
@@ -4311,20 +4311,9 @@
     
-zip.close();
+%7D
 %0A   

use try-with-resources