Home | History | Annotate | Download | only in standalone
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tools.build.jetifier.standalone
     18 
     19 import com.android.tools.build.jetifier.processor.archive.Archive
     20 import com.android.tools.build.jetifier.processor.archive.ArchiveFile
     21 import com.android.tools.build.jetifier.processor.archive.ArchiveItemVisitor
     22 import com.android.tools.build.jetifier.processor.transform.pom.PomDocument
     23 import java.io.File
     24 import java.nio.file.Paths
     25 import java.security.MessageDigest
     26 
     27 /**
     28  * Utility to rebuild de-jetified zipped maven repo.
     29  */
     30 class TopOfTreeBuilder {
     31 
     32     companion object {
     33         const val DIR_PREFIX = "m2repository"
     34     }
     35 
     36     fun rebuildFrom(inputZip: File, outputZip: File) {
     37         val archive = Archive.Builder.extract(inputZip, recursive = false)
     38 
     39         // Find poms
     40         val pomFilter = FileFilter({ it.isPomFile() })
     41         archive.accept(pomFilter)
     42         val pomFiles = pomFilter.files
     43 
     44         // Find archives
     45         val archivesFilter = FileFilter({
     46             return@FileFilter it.fileName.endsWith(".aar")
     47                 || (it.fileName.endsWith("jar")
     48                 && !it.fileName.contains("sources") && !it.fileName.contains("javadoc"))
     49         })
     50         archive.accept(archivesFilter)
     51         val libFiles = archivesFilter.files
     52 
     53         // Process
     54         val newFiles = mutableSetOf<ArchiveFile>()
     55         pomFiles.forEach {
     56             pomFile -> run {
     57                 val name = pomFile.relativePath.toFile().nameWithoutExtension
     58                 val nameAar = name + ".aar"
     59                 val nameJar = name + ".jar"
     60                 val artifactFile = libFiles.first {
     61                     it.fileName == nameAar || it.fileName == nameJar
     62                 }
     63 
     64                 process(pomFile, artifactFile, newFiles)
     65             }
     66         }
     67 
     68         // Write the result
     69         val finalArchive = Archive(outputZip.toPath(), newFiles.toList())
     70         finalArchive.writeSelf()
     71     }
     72 
     73     private fun process(
     74             pomFile: ArchiveFile,
     75             artifactFile: ArchiveFile,
     76             resultSet: MutableSet<ArchiveFile>
     77     ) {
     78         val pomDep = PomDocument.loadFrom(pomFile).getAsPomDependency()
     79 
     80         val groupAsPath = pomDep.groupId!!.replace('.', '/')
     81 
     82         val packaging = artifactFile.relativePath.toFile().extension
     83         val baseFileName = "${pomDep.artifactId}-${pomDep.version}"
     84 
     85         val artifactDir = Paths.get(DIR_PREFIX, groupAsPath, pomDep.artifactId, pomDep.version!!)
     86         val newLibFilePath = Paths.get(artifactDir.toString(), "$baseFileName.$packaging")
     87         val newPomFilePath = Paths.get(artifactDir.toString(), "$baseFileName.pom")
     88 
     89         val newArtifactFile = ArchiveFile(newLibFilePath, artifactFile.data)
     90         val newPomFile = ArchiveFile(newPomFilePath, pomFile.data)
     91 
     92         resultSet.add(newArtifactFile)
     93         resultSet.add(getHashFileOf(newArtifactFile, "MD5"))
     94         resultSet.add(getHashFileOf(newArtifactFile, "SHA1"))
     95 
     96         resultSet.add(newPomFile)
     97         resultSet.add(getHashFileOf(newPomFile, "MD5"))
     98         resultSet.add(getHashFileOf(newPomFile, "SHA1"))
     99     }
    100 
    101     private fun getHashFileOf(file: ArchiveFile, hashType: String): ArchiveFile {
    102         val md = MessageDigest.getInstance(hashType)
    103         val result = md.digest(file.data)
    104         return ArchiveFile(Paths.get(
    105             file.relativePath.toString() + "." + hashType.toLowerCase()), result)
    106     }
    107 
    108     private class FileFilter(private val filter: (ArchiveFile) -> Boolean) : ArchiveItemVisitor {
    109 
    110         val files = mutableSetOf<ArchiveFile>()
    111 
    112         override fun visit(archiveFile: ArchiveFile) {
    113             if (filter(archiveFile)) {
    114                 files.add(archiveFile)
    115             }
    116         }
    117 
    118         override fun visit(archive: Archive) {
    119             archive.files.forEach { it.accept(this) }
    120         }
    121     }
    122 }