All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nbbrd.io.zip.Zip Maven / Gradle / Ivy

/*
 * Copyright 2016 National Bank of Belgium
 *
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://ec.europa.eu/idabc/eupl
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 */
package nbbrd.io.zip;

import internal.io.InternalResource;
import lombok.NonNull;
import nbbrd.io.Resource;
import nbbrd.io.function.IOPredicate;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * Set of utilities related to ZIP.
 *
 * @author Philippe Charles
 */
@lombok.experimental.UtilityClass
public class Zip {

    /**
     * Creates a new loader from a zip file.
     *
     * @param file non-null zip file
     * @return a non-null loader
     * @throws IOException
     */
    public Resource.@NonNull Loader loaderOf(@NonNull File file) throws IOException {
        ZipFile data = new ZipFile(file);
        return Resource.Loader.of(o -> getInputStream(data, o), data);
    }

    /**
     * Creates a new loader by copying the content of a zip file.
     *
     * @param inputStream non-null content of zip file
     * @param filter      non-null filter to avoid copying everything
     * @return a non-null loader
     * @throws IOException
     */
    public Resource.@NonNull Loader loaderCopyOf(@NonNull InputStream inputStream, @NonNull IOPredicate filter) throws IOException {
        Map data = copyOf(inputStream, filter);
        return Resource.Loader.of(o -> getInputStream(data, o));
    }

    private InputStream getInputStream(ZipFile zipFile, String name) throws IOException {
        ZipEntry result = zipFile.getEntry(name);
        if (result == null) {
            throw new IOException("Missing entry '" + name + "' in file '" + zipFile.getName() + "'");
        }
        return zipFile.getInputStream(result);
    }

    private InputStream getInputStream(Map data, String name) throws IOException {
        byte[] result = data.get(name);
        if (result == null) {
            throw new IOException("Missing entry '" + name + "'");
        }
        return new ByteArrayInputStream(result);
    }

    private Map copyOf(InputStream stream, IOPredicate filter) throws IOException {
        Map result = new HashMap<>();
        try (ZipInputStream zis = new ZipInputStream(stream)) {
            Zip.forEach(zis, filter, (k, v) -> result.put(k.getName(), v));
        }
        return result;
    }

    private void forEach(ZipInputStream zis, IOPredicate filter, BiConsumer consumer) throws IOException {
        ZipEntry entry;
        while ((entry = zis.getNextEntry()) != null) {
            if (filter.testWithIO(entry)) {
                consumer.accept(entry, Zip.toByteArray(entry, zis));
            }
        }
    }

    private byte[] toByteArray(ZipEntry entry, ZipInputStream stream) throws IOException {
        long size = entry.getSize();
        if (size >= Integer.MAX_VALUE) {
            throw new IOException("ZIP entry size is too large");
        }
        ByteArrayOutputStream result = new ByteArrayOutputStream(size > 0 ? (int) size : InternalResource.DEFAULT_BUFFER_SIZE);
        InternalResource.transferTo(stream, result);
        return result.toByteArray();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy