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

com.gitee.starblues.plugin.pack.utils.PackageZip Maven / Gradle / Ivy

There is a newer version: 3.1.2
Show newest version
/**
 * Copyright [2019-Present] [starBlues]
 *
 * 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 com.gitee.starblues.plugin.pack.utils;

import com.gitee.starblues.common.PackageStructure;
import com.gitee.starblues.utils.FilesUtils;
import com.gitee.starblues.utils.ObjectUtils;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.UnixStat;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.jar.Manifest;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;

import static com.gitee.starblues.common.PackageStructure.*;

/**
 * zip 打包工具
 *
 * @author starBlues
 * @since 3.0.0
 * @version 3.0.0
 */
public class PackageZip implements Closeable{


    private static final int UNIX_FILE_MODE = UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM;

    private static final int UNIX_DIR_MODE = UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM;

    private final File file;
    private final ArchiveOutputStream outputStream;


    public PackageZip(File file) throws Exception {
        this.file = file;
        this.outputStream = getOutputStream(file);
    }

    public PackageZip(String outputDirectory, String packageName) throws Exception{
        String rootPath = FilesUtils.joiningFilePath(outputDirectory, packageName);
        this.file = getPackageFile(rootPath);
        this.outputStream = getOutputStream(file);
    }

    public File getFile(){
        return file;
    }

    public String getFileName(){
        return file.getName();
    }

    protected File getPackageFile(String rootPath) throws Exception {
        String fileSuffix = getPackageFileSuffix();
        File file = new File(rootPath + "." + fileSuffix);
        CommonUtils.deleteFile(file);
        if(file.createNewFile()){
            return file;
        }
        throw new IOException("Create file '" + file.getPath() + "' failure.");
    }

    protected String getPackageFileSuffix(){
        return "zip";
    }

    protected ArchiveOutputStream getOutputStream(File packFile) throws Exception {
        return new ZipArchiveOutputStream(Files.newOutputStream(packFile.toPath()));
    }

    public void copyDirToPackage(File rootDir, String packageDir) throws Exception {
        if(packageDir == null){
            packageDir = rootDir.getName();
        }
        if (rootDir.isDirectory()) {
            File[] childFiles = rootDir.listFiles();
            if(ObjectUtils.isEmpty(packageDir)){
                packageDir = "";
            } else {
                packageDir = packageDir + "/";
                putDirEntry(packageDir);
            }
            if(childFiles == null){
                return;
            }
            for (File childFile : childFiles) {
                copyDirToPackage(childFile, packageDir + childFile.getName());
            }
        } else {
            putFileEntry(rootDir, packageDir);
        }
    }

    public void copyZipToPackage(File sourceZipFile) throws Exception {
        if(sourceZipFile == null || !sourceZipFile.exists()){
            return;
        }
        try (ZipFile zipFile = new ZipFile(sourceZipFile)){
            Enumeration entries = zipFile.getEntries();
            while (entries.hasMoreElements()){
                ZipArchiveEntry zipArchiveEntry = entries.nextElement();
                String name = zipArchiveEntry.getName();
                if(name.contains(PackageStructure.META_INF_NAME)){
                    // 不拷贝 mate-inf
                    continue;
                }
                if(zipArchiveEntry.isDirectory()){
                    putDirEntry(name);
                } else {
                    try (InputStream inputStream = zipFile.getInputStream(zipArchiveEntry)){
                        putInputStreamEntry(name, inputStream);
                    }
                }
            }
        }
    }

    public String writeDependency(File dependencyFile, String libDirEntryName) throws Exception {
        String indexName = libDirEntryName + dependencyFile.getName();
        ZipArchiveEntry entry = getArchiveEntry(indexName);
        entry.setTime(System.currentTimeMillis());
        entry.setUnixMode(indexName.endsWith("/") ? UNIX_DIR_MODE : UNIX_FILE_MODE);
        entry.getGeneralPurposeBit().useUTF8ForNames(true);
        try(FileInputStream inputStream = new FileInputStream(dependencyFile)){
            new CrcAndSize(inputStream).setupStoredEntry(entry);
        }
        try (FileInputStream inputStream = new FileInputStream(dependencyFile)){
            outputStream.putArchiveEntry(entry);
            IOUtils.copy(inputStream, outputStream);
            outputStream.closeArchiveEntry();
        }
        return indexName;
    }

    public void putFileEntry(File destFile, String rootDir) throws Exception {
        if(!destFile.exists()){
            throw new FileNotFoundException("Not found file : " + destFile.getPath());
        }
        outputStream.putArchiveEntry(getArchiveEntry(rootDir));
        FileUtils.copyFile(destFile, outputStream);
        outputStream.closeArchiveEntry();
    }

    public void putInputStreamEntry(String name, InputStream inputStream) throws Exception {
        outputStream.putArchiveEntry(getArchiveEntry(name));
        IOUtils.copy(inputStream, outputStream);
        outputStream.closeArchiveEntry();
    }

    public void write(String name, String content) throws Exception {
        outputStream.putArchiveEntry(getArchiveEntry(name));
        IOUtils.write(content, outputStream, CHARSET_NAME);
        outputStream.closeArchiveEntry();
    }

    public void write(String name, Writer writer) throws Exception {
        outputStream.putArchiveEntry(getArchiveEntry(name));
        writer.write(outputStream);
        outputStream.closeArchiveEntry();
    }

    public void write(String name, File file) throws Exception {
        outputStream.putArchiveEntry(getArchiveEntry(name));
        try (FileInputStream fileInputStream = new FileInputStream(file)){
            IOUtils.copy(fileInputStream, outputStream);
            outputStream.closeArchiveEntry();
        }
    }

    public void writeManifest(Manifest manifest) throws Exception {
        putDirEntry(META_INF_NAME + SEPARATOR);
        write(PROD_MANIFEST_PATH, manifest::write);
    }

    public void putDirEntry(String dir) throws IOException {
        outputStream.putArchiveEntry(getArchiveEntry(dir));
        outputStream.closeArchiveEntry();
    }

    protected ZipArchiveEntry getArchiveEntry(String name){
        return new ZipArchiveEntry(name);
    }


    @Override
    public void close() throws IOException {
        outputStream.finish();
        outputStream.close();
    }

    private static class CrcAndSize {

        private static final int BUFFER_SIZE = 32 * 1024;

        private final CRC32 crc = new CRC32();

        private long size;

        CrcAndSize(InputStream inputStream) throws IOException {
            load(inputStream);
        }

        private void load(InputStream inputStream) throws IOException {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                this.crc.update(buffer, 0, bytesRead);
                this.size += bytesRead;
            }
        }

        void setupStoredEntry(ZipArchiveEntry entry) {
            entry.setSize(this.size);
            entry.setCompressedSize(this.size);
            entry.setCrc(this.crc.getValue());
            entry.setMethod(ZipEntry.STORED);
        }

    }

    @FunctionalInterface
    public interface Writer{
        void write(ArchiveOutputStream outputStream) throws Exception;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy