com.github.megatronking.stringfog.plugin.StringFogTransform.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-plugin Show documentation
Show all versions of gradle-plugin Show documentation
A String encryption Library for Android
/*
* Copyright (C) 2017, Megatron King
*
* 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.github.megatronking.stringfog.plugin
import com.android.build.api.transform.*
import com.android.build.gradle.api.BaseVariant
import com.android.utils.FileUtils
import com.github.megatronking.stringfog.IKeyGenerator
import com.github.megatronking.stringfog.plugin.utils.MD5
import com.google.common.collect.ImmutableSet
import com.google.common.io.Files
import groovy.io.FileType
import org.gradle.api.DefaultTask
import org.gradle.api.DomainObjectSet
import org.gradle.api.Project
import org.gradle.api.Task
abstract class StringFogTransform extends Transform {
public static final String FOG_CLASS_NAME = 'StringFog'
private static final String TRANSFORM_NAME = 'stringFog'
protected StringFogClassInjector mInjector
protected StringFogMappingPrinter mMappingPrinter
protected String mImplementation
protected StringFogMode mMode
StringFogTransform(Project project, DomainObjectSet variants) {
project.afterEvaluate {
IKeyGenerator kg = project.stringfog.kg
String[] fogPackages = project.stringfog.fogPackages
String implementation = project.stringfog.implementation
StringFogMode mode = project.stringfog.mode
if (kg == null) {
throw new IllegalArgumentException("Missing stringfog kg config")
}
if (implementation == null || implementation.length() == 0) {
throw new IllegalArgumentException("Missing stringfog implementation config")
}
if (project.stringfog.enable) {
def applicationId = variants.first().applicationId
def manifestFile = project.file("src/main/AndroidManifest.xml")
if (manifestFile.exists()) {
def parsedManifest = new XmlParser().parse(
new InputStreamReader(new FileInputStream(manifestFile), "utf-8"))
if (parsedManifest != null) {
def packageName = parsedManifest.attribute("package")
if (packageName != null) {
applicationId = packageName
}
}
}
createFogClass(project, fogPackages, kg, implementation, mode, variants, applicationId)
} else {
mMappingPrinter = null
mInjector = null
}
mImplementation = implementation
mMode = mode
}
}
void createFogClass(def project, String[] fogPackages, IKeyGenerator kg, String implementation,
def mode, DomainObjectSet variants, def applicationId) {
variants.all { variant ->
def variantName = variant.name.toUpperCase()[0] + variant.name.substring(1, variant.name.length() - 1)
Task generateTask = project.tasks.findByName(variantName)
if (generateTask == null) {
generateTask = project.tasks.create("generate${variantName}StringFog", DefaultTask)
def stringfogDir = new File(project.buildDir, "generated" +
File.separatorChar + "source" + File.separatorChar + "stringfog" + File.separatorChar + variant.name)
def stringfogFile = new File(stringfogDir, applicationId.replace((char)'.', File.separatorChar) + File.separator + "StringFog.java")
variant.registerJavaGeneratingTask(generateTask, stringfogDir)
generateTask.doLast {
mMappingPrinter = new StringFogMappingPrinter(
new File(project.buildDir, "outputs/mapping/${variant.name.toLowerCase()}/stringfog.txt"))
// Create class injector
mInjector = new StringFogClassInjector(fogPackages, kg, implementation, mode,
applicationId + "." + FOG_CLASS_NAME, mMappingPrinter)
// Generate StringFog.java
StringFogClassGenerator.generate(stringfogFile, applicationId, FOG_CLASS_NAME,
implementation, mode)
}
}
}
}
@Override
String getName() {
return TRANSFORM_NAME
}
@Override
Set getInputTypes() {
return ImmutableSet.of(QualifiedContent.DefaultContentType.CLASSES)
}
@Override
Set getScopes() {
return null
}
@Override
boolean isIncremental() {
return true
}
@Override
void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
def dirInputs = new HashSet<>()
def jarInputs = new HashSet<>()
if (!transformInvocation.isIncremental()) {
transformInvocation.getOutputProvider().deleteAll()
}
// Collecting inputs.
transformInvocation.inputs.each { input ->
input.directoryInputs.each { dirInput ->
dirInputs.add(dirInput)
}
input.jarInputs.each { jarInput ->
jarInputs.add(jarInput)
}
}
if (mMappingPrinter != null) {
mMappingPrinter.startMappingOutput(mImplementation, mMode)
}
if (!dirInputs.isEmpty() || !jarInputs.isEmpty()) {
File dirOutput = transformInvocation.outputProvider.getContentLocation(
"classes", getOutputTypes(), getScopes(), Format.DIRECTORY)
FileUtils.mkdirs(dirOutput)
if (!dirInputs.isEmpty()) {
dirInputs.each { dirInput ->
if (transformInvocation.incremental) {
dirInput.changedFiles.each { entry ->
File fileInput = entry.getKey()
File fileOutput = new File(fileInput.getAbsolutePath().replace(
dirInput.file.getAbsolutePath(), dirOutput.getAbsolutePath()))
FileUtils.mkdirs(fileOutput.parentFile)
Status fileStatus = entry.getValue()
switch(fileStatus) {
case Status.ADDED:
case Status.CHANGED:
if (fileInput.isDirectory()) {
return // continue.
}
if (mInjector != null && fileInput.getName().endsWith('.class')) {
mInjector.doFog2Class(fileInput, fileOutput)
} else {
Files.copy(fileInput, fileOutput)
}
break
case Status.REMOVED:
if (fileOutput.exists()) {
if (fileOutput.isDirectory()) {
fileOutput.deleteDir()
} else {
fileOutput.delete()
}
}
break
}
}
} else {
dirInput.file.traverse(type: FileType.FILES) { fileInput ->
File fileOutput = new File(fileInput.getAbsolutePath().replace(dirInput.file.getAbsolutePath(), dirOutput.getAbsolutePath()))
FileUtils.mkdirs(fileOutput.parentFile)
if (mInjector != null && fileInput.getName().endsWith('.class')) {
mInjector.doFog2Class(fileInput, fileOutput)
} else {
Files.copy(fileInput, fileOutput)
}
}
}
}
}
if (!jarInputs.isEmpty()) {
jarInputs.each { jarInput ->
File jarInputFile = jarInput.file
File jarOutputFile = transformInvocation.outputProvider.getContentLocation(
getUniqueHashName(jarInputFile), getOutputTypes(), getScopes(), Format.JAR
)
FileUtils.mkdirs(jarOutputFile.parentFile)
switch (jarInput.status) {
case Status.NOTCHANGED:
if (transformInvocation.incremental) {
break
}
case Status.ADDED:
case Status.CHANGED:
if (mInjector != null) {
mInjector.doFog2Jar(jarInputFile, jarOutputFile)
} else {
Files.copy(jarInputFile, jarOutputFile)
}
break
case Status.REMOVED:
if (jarOutputFile.exists()) {
jarOutputFile.delete()
}
break
}
}
}
}
if (mMappingPrinter != null) {
mMappingPrinter.endMappingOutput()
}
}
static String getUniqueHashName(File fileInput) {
final String fileInputName = fileInput.getName()
if (fileInput.isDirectory()) {
return fileInputName
}
final String parentDirPath = fileInput.getParentFile().getAbsolutePath()
final String pathMD5 = MD5.getMessageDigest(parentDirPath.getBytes())
final int extSepPos = fileInputName.lastIndexOf('.')
final String fileInputNamePrefix =
(extSepPos >= 0 ? fileInputName.substring(0, extSepPos) : fileInputName)
return fileInputNamePrefix + '_' + pathMD5
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy