ModifyClassTransform.groovy 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package com.gradle
  2. import com.android.build.api.transform.*
  3. import com.google.common.collect.ImmutableSet
  4. import com.google.common.io.Files
  5. import org.apache.commons.codec.digest.DigestUtils
  6. import org.apache.commons.io.FileUtils
  7. import org.gradle.api.Project
  8. /**
  9. * Created by Glen on 2017/2/7.
  10. */
  11. public abstract class ModifyClassTransform extends Transform {
  12. protected Project project;
  13. public ModifyClassTransform(Project project) {
  14. this.project = project
  15. MyLogger.init(project.name)
  16. }
  17. @Override
  18. public String getName() {
  19. return "Modify"
  20. }
  21. @Override
  22. public Set<QualifiedContent.ContentType> getInputTypes() {
  23. return ImmutableSet.of(QualifiedContent.DefaultContentType.CLASSES)
  24. }
  25. @Override
  26. public Set<QualifiedContent.Scope> getScopes() {
  27. return ImmutableSet.of(
  28. QualifiedContent.Scope.PROJECT,// app class
  29. QualifiedContent.Scope.PROJECT_LOCAL_DEPS,// app libs local jar
  30. QualifiedContent.Scope.SUB_PROJECTS,//sub lib class
  31. QualifiedContent.Scope.SUB_PROJECTS_LOCAL_DEPS,//sub lib libs local jar
  32. QualifiedContent.Scope.EXTERNAL_LIBRARIES//compile dependencies
  33. )
  34. }
  35. @Override
  36. public boolean isIncremental() {
  37. return true
  38. }
  39. @Override
  40. void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
  41. long time = System.currentTimeMillis()
  42. // Collecting inputs.
  43. transformInvocation.inputs.each { input ->
  44. input.directoryInputs.each { dirInput ->
  45. if (transformInvocation.incremental) {
  46. File dirOutput = transformInvocation.outputProvider.getContentLocation(dirInput.file.name, dirInput.contentTypes, dirInput.scopes, Format.DIRECTORY)
  47. if (!dirOutput.exists()) {
  48. dirOutput.mkdirs()
  49. }
  50. dirInput.changedFiles.each { changedFile ->
  51. File fileInput = changedFile.getKey()
  52. File fileOutput = new File(fileInput.getAbsolutePath().replace(
  53. dirInput.file.getAbsolutePath(), dirOutput.getAbsolutePath()))
  54. if (!fileOutput.exists()) {
  55. fileOutput.getParentFile().mkdirs()
  56. }
  57. switch (changedFile.value) {
  58. case Status.ADDED:
  59. case Status.CHANGED:
  60. if (fileInput.isDirectory()) {
  61. return // continue.
  62. }
  63. handleChangedFile(fileInput)
  64. if (fileInput.getName().endsWith('.class')) {
  65. Files.copy(fileInput, fileOutput)
  66. }
  67. break
  68. case Status.REMOVED:
  69. if (fileOutput.exists()) {
  70. if (fileOutput.isDirectory()) {
  71. fileOutput.deleteDir()
  72. } else {
  73. fileOutput.delete()
  74. }
  75. }
  76. break
  77. }
  78. }
  79. } else {
  80. dirInput.file.eachFileRecurse { File file ->
  81. handleChangedFile(file)
  82. }
  83. //output modify class file
  84. File file = transformInvocation.outputProvider.getContentLocation(dirInput.file.name, dirInput.contentTypes, dirInput.scopes, Format.DIRECTORY)
  85. if (file.exists()) file.deleteDir()
  86. FileUtils.copyDirectory(dirInput.file, file)
  87. }
  88. }
  89. input.jarInputs.each { jarInput ->
  90. File file = transformInvocation.outputProvider.getContentLocation(getUniqueFileName(jarInput.file), jarInput.contentTypes, jarInput.scopes, Format.JAR)
  91. switch (jarInput.status) {
  92. case Status.NOTCHANGED:
  93. if (transformInvocation.incremental) break
  94. case Status.ADDED:
  95. case Status.CHANGED:
  96. file.deleteOnExit()
  97. handleChangedFile(jarInput.file)
  98. //output modify jar file
  99. FileUtils.copyFile(jarInput.file, file)
  100. break
  101. case Status.REMOVED:
  102. file.deleteOnExit()
  103. break
  104. }
  105. }
  106. }
  107. this.project.logger.error(":" + this.project.name + ":" + getName() + " consume time " + (System.currentTimeMillis() - time) + "ms")
  108. }
  109. /**
  110. * 生成唯一文件名
  111. * @param fileInput
  112. * @return
  113. */
  114. protected String getUniqueFileName(File fileInput) {
  115. final String fileInputName = fileInput.getName()
  116. if (fileInput.isDirectory()) {
  117. return fileInputName
  118. }
  119. final String parentDirPath = fileInput.getParentFile().getAbsolutePath()
  120. final String pathMD5 = DigestUtils.md5Hex(parentDirPath.getBytes()).substring(0, 6)
  121. final int extSepPos = fileInputName.lastIndexOf('.')
  122. final String fileInputNamePrefix =
  123. (extSepPos >= 0 ? fileInputName.substring(0, extSepPos) : fileInputName)
  124. return fileInputNamePrefix + '_' + pathMD5
  125. }
  126. /**
  127. * 增量文件
  128. * @param input
  129. */
  130. protected abstract void handleChangedFile(File input)
  131. }