/*
 * Copyright 2019 the original author or authors.
 *
 * 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.
 */


import java.nio.file.Files
import java.util.zip.ZipEntry
import java.util.zip.ZipException
import java.util.zip.ZipFile

import org.gradle.api.artifacts.transform.TransformParameters

// tag::artifact-transform-unzip[]
abstract class Unzip implements TransformAction<TransformParameters.None> { // <1>
    @InputArtifact                                                          // <2>
    abstract Provider<FileSystemLocation> getInputArtifact()

    @Override
    void transform(TransformOutputs outputs) {
        def input = inputArtifact.get().asFile
        def unzipDir = outputs.dir(input.name)                              // <3>
        unzipTo(input, unzipDir)                                            // <4>
    }

    private static void unzipTo(File zipFile, File unzipDir) {
        // implementation...
// end::artifact-transform-unzip[]
        new ZipFile(zipFile).withCloseable { zip ->
            def outputDirectoryCanonicalPath = unzipDir.canonicalPath
            for (entry in zip.entries()) {
                unzipEntryTo(unzipDir, outputDirectoryCanonicalPath, zip, entry)
            }
        }
    }

    private static unzipEntryTo(File outputDirectory, String outputDirectoryCanonicalPath, ZipFile zip, ZipEntry entry) {
        def output = new File(outputDirectory, entry.name)
        if (!output.canonicalPath.startsWith(outputDirectoryCanonicalPath)) {
            throw new ZipException("Zip entry '${entry.name}' is outside of the output directory")
        }
        if (entry.isDirectory) {
            output.mkdirs()
        } else {
            output.parentFile.mkdirs()
            zip.getInputStream(entry).withCloseable { Files.copy(it, output.toPath()) }
        }
// tag::artifact-transform-unzip[]
    }
}
// end::artifact-transform-unzip[]

def usage = Attribute.of('usage', String)
// tag::artifact-transform-registration[]
def artifactType = Attribute.of('artifactType', String)

dependencies {
    registerTransform(Unzip) {
        from.attribute(artifactType, 'jar')
        to.attribute(artifactType, 'java-classes-directory')
    }
}
// end::artifact-transform-registration[]


allprojects {
    dependencies {
        attributesSchema {
            attribute(usage)
        }
    }
    configurations.create("compile") {
        attributes.attribute usage, 'api'
    }
}
