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

org.paleozogt.gradle.zip.SymUnzip.groovy Maven / Gradle / Ivy

package org.paleozogt.gradle.zip

import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.WorkResult;
import org.gradle.api.tasks.AbstractCopyTask;
import org.gradle.api.internal.file.copy.CopyAction;
import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
import org.gradle.api.internal.tasks.SimpleWorkResult;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
import org.gradle.api.tasks.OutputDirectory;

import org.gradle.api.internal.file.copy.CopySpecInternal;
import org.gradle.api.internal.file.copy.DestinationRootCopySpec;
import org.gradle.internal.reflect.Instantiator;

import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.UnicodeExtraFieldPolicy;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.archivers.zip.UnixStat;
import org.apache.commons.compress.archivers.ArchiveEntry;

import java.nio.file.Files;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.FilenameUtils;

class SymUnzip extends AbstractCopyTask {
    @Override
    protected CopyAction createCopyAction() {
        File destinationDir = getDestinationDir();
        if (destinationDir == null) {
            throw new InvalidUserDataException("No copy destination directory has been specified, use 'into' to specify a target directory.");
        }
        return new FileCopyAction(getFileLookup().getFileResolver(destinationDir));
    }

    @Override
    protected CopySpecInternal createRootSpec() {
        Instantiator instantiator = getInstantiator();
        FileResolver fileResolver = getFileResolver();

        return instantiator.newInstance(DestinationRootCopySpec.class, fileResolver, super.createRootSpec());
    }

    @Override
    public DestinationRootCopySpec getRootSpec() {
        return (DestinationRootCopySpec) super.getRootSpec();
    }

    /**
     * Returns the directory to copy files into.
     *
     * @return The destination dir.
     */
    @OutputDirectory
    public File getDestinationDir() {
        return getRootSpec().getDestinationDir();
    }

    /**
     * Sets the directory to copy files into. This is the same as calling {@link #into(Object)} on this task.
     *
     * @param destinationDir The destination directory. Must not be null.
     */
    public void setDestinationDir(File destinationDir) {
        into(destinationDir);
    }

    class FileCopyAction implements CopyAction {
        private final FileResolver fileResolver;

        public FileCopyAction(FileResolver fileResolver) {
            this.fileResolver = fileResolver;
        }

        public WorkResult execute(CopyActionProcessingStream stream) {
            FileCopyDetailsInternalAction action = new FileCopyDetailsInternalAction();
            stream.process(action);
            return new SimpleWorkResult(action.didWork);
        }

        private class FileCopyDetailsInternalAction implements CopyActionProcessingStreamAction {
            private boolean didWork;

            public void processFile(FileCopyDetailsInternal details) {
                File target = fileResolver.resolve(details.getRelativePath().getPathString());

                String sourceExt = FilenameUtils.getExtension(details.getFile().toString()).toLowerCase();
                if (sourceExt.equals("zip")) {
                    explodeZip(details, target.getParentFile());
                    didWork= true;
                } else {
                    boolean copied = details.copyTo(target);
                    if (copied) {
                        didWork = true;
                    }
                }
            }

            protected void explodeZip(FileCopyDetails fileDetails, File target) {
                ZipFile zipFile= new ZipFile(fileDetails.getFile());

                // TODO: for-each?
                Enumeration entries= zipFile.getEntries();
                while (entries.hasMoreElements()) {
                    ZipArchiveEntry entry=(ZipArchiveEntry)entries.nextElement();
                    File entryFile= new File(target, entry.getName());
                    entryFile.getParentFile().mkdirs();
                    getLogger().debug("zip entry {} mode={} symlink={}", entry, entry.getUnixMode(), entry.isUnixSymlink());
                    if (entry.isUnixSymlink()) {
                        String linkEntry= getEntryContents(zipFile, entry);
                        File linkEntryFile= new File(linkEntry);
                        Files.createSymbolicLink(entryFile.toPath(), linkEntryFile.toPath());
                    } else if (!entry.isDirectory()) {
                        IOUtils.copy(zipFile.getInputStream(entry), new FileOutputStream(entryFile));
                        getFileSystem().chmod(entryFile, getEntryMode(entry));
                    }
                }
            }

            protected static int getEntryMode(ZipArchiveEntry entry) {
                int unixMode = entry.getUnixMode() & 0777;
                if(unixMode == 0){
                    //no mode infos available - fall back to defaults
                    if(isDirectory()){
                        unixMode = FileSystem.DEFAULT_DIR_MODE;
                    }else{
                        unixMode = FileSystem.DEFAULT_FILE_MODE;
                    }
                }
                return unixMode;
            }

            protected static String getEntryContents(ZipFile zipFile, ZipArchiveEntry entry) throws IOException {
                InputStream entryStream= zipFile.getInputStream(entry);
                ByteArrayOutputStream contents= new ByteArrayOutputStream();
                IOUtils.copy(entryStream, contents);
                return contents.toString();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy