/*******************************************************************************
 * Copyright (c) 2012-2015 Codenvy, S.A.
 * 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:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.api.vfs.server.util;

import org.apache.commons.io.input.CountingInputStream;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/** @author andrew00x */
public final class ZipContent {
    /** Memory threshold. If zip stream over this size it spooled in file. */
    private static final int  BUFFER        = 100 * 1024; // 100k
    private static final int  BUFFER_SIZE   = 8 * 1024; // 8k
    /** The threshold after that checking of ZIP ratio started. */
    private static final long ZIP_THRESHOLD = 1000000;
    /**
     * Max compression ratio. If the number of bytes uncompressed data is exceed the number
     * of bytes of compressed stream more than this ratio (and number of uncompressed data
     * is more than threshold) then VirtualFileSystemRuntimeException is thrown.
     */
    private static final int  ZIP_RATIO     = 100;

    public static ZipContent newInstance(InputStream in) throws IOException {
        java.io.File file = null;
        byte[] inMemory = null;

        int count = 0;
        ByteArrayOutputStream inMemorySpool = new ByteArrayOutputStream(BUFFER);

        int bytes;
        final byte[] buff = new byte[BUFFER_SIZE];
        while (count <= BUFFER && (bytes = in.read(buff)) != -1) {
            inMemorySpool.write(buff, 0, bytes);
            count += bytes;
        }

        InputStream spool;
        if (count > BUFFER) {
            file = java.io.File.createTempFile("import", ".zip");
            try (FileOutputStream fileSpool = new FileOutputStream(file)) {
                inMemorySpool.writeTo(fileSpool);
                while ((bytes = in.read(buff)) != -1) {
                    fileSpool.write(buff, 0, bytes);
                }
            }
            spool = new FileInputStream(file);
        } else {
            inMemory = inMemorySpool.toByteArray();
            spool = new ByteArrayInputStream(inMemory);
        }

        ZipInputStream zip = null;
        try {
            // Counts numbers of compressed data.
            final CountingInputStream compressedCounter = new CountingInputStream(spool);
            zip = new ZipInputStream(compressedCounter);
            // Counts number of uncompressed data.
            CountingInputStream uncompressedCounter = new CountingInputStream(zip) {
                @Override
                public int read() throws IOException {
                    int i = super.read();
                    checkCompressionRatio();
                    return i;
                }

                @Override
                public int read(byte[] b, int off, int len) throws IOException {
                    int i = super.read(b, off, len);
                    checkCompressionRatio();
                    return i;
                }

                @Override
                public int read(byte[] b) throws IOException {
                    int i = super.read(b);
                    checkCompressionRatio();
                    return i;
                }

                @Override
                public long skip(long length) throws IOException {
                    long i = super.skip(length);
                    checkCompressionRatio();
                    return i;
                }

                private void checkCompressionRatio() {
                    long uncompressedBytes = getByteCount(); // number of uncompressed bytes
                    if (uncompressedBytes > ZIP_THRESHOLD) {
                        long compressedBytes = compressedCounter.getByteCount(); // number of compressed bytes
                        if (uncompressedBytes > (ZIP_RATIO * compressedBytes)) {
                            throw new RuntimeException("Zip bomb detected. ");
                        }
                    }
                }
            };

            ZipEntry zipEntry;
            while ((zipEntry = zip.getNextEntry()) != null) {
                if (!zipEntry.isDirectory()) {
                    while (uncompressedCounter.read(buff) != -1) {
                        // Read full data from stream to be able detect zip-bomb.
                    }
                }
            }

            return new ZipContent(inMemory != null ? new ByteArrayInputStream(inMemory) : new DeleteOnCloseFileInputStream(file),
                                  file == null);
        } finally {
            if (zip != null) {
                zip.close();
            }
        }
    }

    public final InputStream zippedData;
    public final boolean     inMemory;

    private ZipContent(InputStream zippedData, boolean inMemory) {
        this.zippedData = zippedData;
        this.inMemory = inMemory;
    }
}

@@ -2652,61 +2652,8 @@
  %7D%0A%0A
-        ZipInputStream zip = null;%0A        try %7B%0A    
     
@@ -2702,26 +2702,21 @@
         
-    final 
+try (
 Counting
@@ -2791,16 +2791,32 @@
         
+ ZipInputStream 
 zip = ne
@@ -2850,17 +2850,20 @@
 Counter)
-;
+) %7B%0A
 %0A       
@@ -5013,102 +5013,8 @@
 l);%0A
-        %7D finally %7B%0A            if (zip != null) %7B%0A                zip.close();%0A            %7D%0A
     

Make streams are correctly closed