summaryrefslogtreecommitdiff
path: root/gradlePlugin
diff options
context:
space:
mode:
authorYigit Boyar <yboyar@google.com>2015-06-12 13:13:17 -0700
committerYigit Boyar <yboyar@google.com>2015-06-12 14:15:07 -0700
commitb6887f1479c3ecec38a7989748ef33de1fbcd973 (patch)
tree8d8ff47f19e1ce3993d952bcb6e320b61cbe0399 /gradlePlugin
parent30b1bbbcf006dc6600f86a4e4d1bdf6d8a218351 (diff)
downloaddata-binding-b6887f1479c3ecec38a7989748ef33de1fbcd973.tar.gz
Export generated class list from javac
Previously, gradle plugin would figure out generated class names that should be excluded from the packaging. This CL changes that behavior to export the list from java compiler so that it is consistent going forward. This CL also changes exclusion task to always exclude generated binding info class to not to leak any information about user's local. Bug: 21668472 Change-Id: Ibeed24bd854781942b4185f618a5cd1eafe706d3
Diffstat (limited to 'gradlePlugin')
-rw-r--r--gradlePlugin/build.gradle4
-rw-r--r--gradlePlugin/src/main/java/android/databinding/tool/DataBindingExcludeGeneratedTask.java124
-rw-r--r--gradlePlugin/src/main/kotlin/DataBindingExportInfoTask.kt5
-rw-r--r--gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt2
-rw-r--r--gradlePlugin/src/main/kotlin/plugin.kt87
5 files changed, 158 insertions, 64 deletions
diff --git a/gradlePlugin/build.gradle b/gradlePlugin/build.gradle
index 2ffab0ca..83aa27cc 100644
--- a/gradlePlugin/build.gradle
+++ b/gradlePlugin/build.gradle
@@ -46,6 +46,10 @@ dependencies {
compile project(":compiler")
}
+compileJava {
+ options.compilerArgs = ["-proc:none"]
+}
+
uploadArchives {
repositories {
mavenDeployer {
diff --git a/gradlePlugin/src/main/java/android/databinding/tool/DataBindingExcludeGeneratedTask.java b/gradlePlugin/src/main/java/android/databinding/tool/DataBindingExcludeGeneratedTask.java
new file mode 100644
index 00000000..cfc7a98a
--- /dev/null
+++ b/gradlePlugin/src/main/java/android/databinding/tool/DataBindingExcludeGeneratedTask.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 android.databinding.tool;
+
+import com.google.common.base.Preconditions;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.api.tasks.bundling.Jar;
+
+import android.databinding.tool.util.L;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Task to exclude generated classes from the Jar task of a library project
+ */
+public class DataBindingExcludeGeneratedTask extends DefaultTask {
+ private String appPackage;
+ private String infoClassQualifiedName;
+ @Input
+ private File generatedClassListFile;
+ private boolean isLibrary;
+
+ private org.gradle.api.tasks.bundling.Jar packageTask;
+ private final String EXCLUDE_PATTERN = "android/databinding/layouts/*.*";
+
+ public void setAppPackage(String appPackage) {
+ this.appPackage = appPackage;
+ }
+
+ public void setInfoClassQualifiedName(String infoClassQualifiedName) {
+ this.infoClassQualifiedName = infoClassQualifiedName;
+ }
+
+ public void setLibrary(boolean isLibrary) {
+ this.isLibrary = isLibrary;
+ }
+
+ public void setPackageTask(Jar packageTask) {
+ this.packageTask = packageTask;
+ }
+
+ public void setGeneratedClassListFile(File generatedClassListFile) {
+ this.generatedClassListFile = generatedClassListFile;
+ }
+
+ public String getAppPackage() {
+ return appPackage;
+ }
+
+ public String getInfoClassQualifiedName() {
+ return infoClassQualifiedName;
+ }
+
+ public File getGeneratedClassListFile() {
+ return generatedClassListFile;
+ }
+
+ @TaskAction
+ public void excludeGenerated() {
+ L.d("Excluding generated classes from jar. Is library ? %s", isLibrary);
+ String appPkgAsClass = appPackage.replace('.', '/');
+ String infoClassAsClass = infoClassQualifiedName.replace('.', '/');
+ exclude(infoClassAsClass + ".class");
+ exclude(EXCLUDE_PATTERN);
+ if (isLibrary) {
+ exclude(appPkgAsClass + "/BR.*");
+ List<String> generatedClasses = readGeneratedClasses();
+ for (String klass : generatedClasses) {
+ exclude(klass.replace('.', '/') + ".class");
+ }
+ }
+ L.d("Excluding generated classes from library jar is done.");
+ }
+
+ private void exclude(String pattern) {
+ L.d("exclude %s", pattern);
+ packageTask.exclude(pattern);
+ }
+
+ private List<String> readGeneratedClasses() {
+ Preconditions.checkNotNull(generatedClassListFile, "Data binding exclude generated task"
+ + " is not configured properly");
+ Preconditions.checkArgument(generatedClassListFile.exists(),
+ "Generated class list does not exist %s", generatedClassListFile.getAbsolutePath());
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(generatedClassListFile);
+ return IOUtils.readLines(fis);
+ } catch (FileNotFoundException e) {
+ L.e(e, "Unable to read generated class list from %s",
+ generatedClassListFile.getAbsoluteFile());
+ } catch (IOException e) {
+ L.e(e, "Unexpected exception while reading %s",
+ generatedClassListFile.getAbsoluteFile());
+ } finally {
+ IOUtils.closeQuietly(fis);
+ }
+ Preconditions.checkState(false, "Could not read data binding generated class list");
+ return null;
+ }
+}
diff --git a/gradlePlugin/src/main/kotlin/DataBindingExportInfoTask.kt b/gradlePlugin/src/main/kotlin/DataBindingExportInfoTask.kt
index 776e4263..ee99c6b4 100644
--- a/gradlePlugin/src/main/kotlin/DataBindingExportInfoTask.kt
+++ b/gradlePlugin/src/main/kotlin/DataBindingExportInfoTask.kt
@@ -25,10 +25,11 @@ open class DataBindingExportInfoTask : DefaultTask() {
var xmlProcessor: LayoutXmlProcessor by Delegates.notNull()
var sdkDir : File by Delegates.notNull()
var xmlOutFolder : File by Delegates.notNull()
+ var exportClassListTo : File? = null
var enableDebugLogs = false
- [TaskAction]
+ @TaskAction
public fun doIt() {
L.d("running process layouts task %s", getName())
- xmlProcessor.writeInfoClass(sdkDir, xmlOutFolder, enableDebugLogs)
+ xmlProcessor.writeInfoClass(sdkDir, xmlOutFolder, exportClassListTo, enableDebugLogs)
}
} \ No newline at end of file
diff --git a/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt b/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt
index ec8c348c..3bc0e0fb 100644
--- a/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt
+++ b/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt
@@ -27,7 +27,7 @@ open class DataBindingProcessLayoutsTask : DefaultTask() {
var xmlOutFolder : File by Delegates.notNull()
var minSdk: kotlin.Int by Delegates.notNull()
- [TaskAction]
+ @TaskAction
public fun doIt() {
L.d("running process layouts task %s", getName())
xmlProcessor.processResources(minSdk)
diff --git a/gradlePlugin/src/main/kotlin/plugin.kt b/gradlePlugin/src/main/kotlin/plugin.kt
index a5df389c..e63e32df 100644
--- a/gradlePlugin/src/main/kotlin/plugin.kt
+++ b/gradlePlugin/src/main/kotlin/plugin.kt
@@ -37,6 +37,7 @@ import com.android.build.gradle.api.TestVariant
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.build.gradle.internal.api.TestVariantImpl
import com.android.ide.common.res2.ResourceSet
+import com.google.common.base.Preconditions
import org.apache.commons.io.IOUtils
import org.gradle.api.artifacts
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
@@ -54,12 +55,11 @@ import org.gradle.api.plugins.ExtraPropertiesExtension
open class DataBinderPlugin : Plugin<Project> {
- val XPATH_BINDING_CLASS = "/layout/data/@class"
var logger : Logger by Delegates.notNull()
inner class GradleFileWriter(var outputBase: String) : JavaFileWriter() {
override fun writeToFile(canonicalName: String, contents: String) {
- val f = File("$outputBase/${canonicalName.replaceAll("\\.", "/")}.java")
+ val f = File("$outputBase/${canonicalName.replace("\\.".toRegex(), "/")}.java")
logD("Asked to write to ${canonicalName}. outputting to:${f.getAbsolutePath()}")
f.getParentFile().mkdirs()
f.writeText(contents, "utf-8")
@@ -189,11 +189,12 @@ open class DataBinderPlugin : Plugin<Project> {
minSdkVersion.getApiLevel(), isLibrary)
val processResTask = generateRTask
val xmlOutDir = File("${project.getBuildDir()}/layout-info/${configuration.getDirName()}")
+ val generatedClassListOut = if (isLibrary) File(xmlOutDir, "_generated.txt") else null
logD("xml output for ${variantData} is ${xmlOutDir}")
val layoutTaskName = "dataBindingLayouts${processResTask.getName().capitalize()}"
val infoClassTaskName = "dataBindingInfoClass${processResTask.getName().capitalize()}"
- var processLayoutsTask : DataBindingProcessLayoutsTask? = null
+ var processLayoutsTask: DataBindingProcessLayoutsTask? = null
project.getTasks().create(layoutTaskName,
javaClass<DataBindingProcessLayoutsTask>(),
object : Action<DataBindingProcessLayoutsTask> {
@@ -217,76 +218,40 @@ open class DataBinderPlugin : Plugin<Project> {
})
project.getTasks().create(infoClassTaskName,
javaClass<DataBindingExportInfoTask>(),
- object : Action<DataBindingExportInfoTask>{
+ object : Action<DataBindingExportInfoTask> {
override fun execute(task: DataBindingExportInfoTask) {
task.dependsOn(processLayoutsTask!!)
task.dependsOn(processResTask)
task.xmlProcessor = xmlProcessor
task.sdkDir = sdkDir
task.xmlOutFolder = xmlOutDir
+ task.exportClassListTo = generatedClassListOut
task.enableDebugLogs = logger.isEnabled(LogLevel.DEBUG)
variantData.registerJavaGeneratingTask(task, codeGenTargetFolder)
}
})
+ val packageJarTaskName = "package${fullName.capitalize()}Jar"
+ val packageTask = project.getTasks().findByName(packageJarTaskName)
+ if (packageTask is org.gradle.api.tasks.bundling.Jar) {
+ val removeGeneratedTaskName = "dataBindingExcludeGeneratedFrom${packageTask.getName().capitalize()}"
+ if (project.getTasks().findByName(removeGeneratedTaskName) == null) {
+ val javaCompileTask = variantData.javaCompileTask
+ Preconditions.checkNotNull(javaCompileTask)
- if (isLibrary) {
- val resourceSets = variantData.mergeResourcesTask.getInputResourceSets()
- val customBindings = getCustomBindings(resourceSets, packageName)
- val packageJarTaskName = "package${fullName.capitalize()}Jar"
- val packageTask = project.getTasks().findByName(packageJarTaskName)
- if (packageTask !is org.gradle.api.tasks.bundling.Jar) {
- throw RuntimeException("cannot find package task in $project $variantData project $packageJarTaskName")
- }
- val excludePattern = "android/databinding/layouts/*.*"
- val appPkgAsClass = packageName.replace('.', '/')
- packageTask.exclude(excludePattern)
- packageTask.exclude("$appPkgAsClass/databinding/*")
- packageTask.exclude("$appPkgAsClass/BR.*")
- packageTask.exclude(xmlProcessor.getInfoClassFullName().replace('.', '/') + ".class")
- customBindings.forEach {
- packageTask.exclude("${it.replace('.', '/')}.class")
- }
- logD("excludes ${packageTask.getExcludes()}")
- }
- }
-
- fun getCustomBindings(resourceSets : List<ResourceSet>, packageName: String) : List<String> {
- val xPathFactory = XPathFactory.newInstance()
- val xPath = xPathFactory.newXPath()
- val expr = xPath.compile(XPATH_BINDING_CLASS);
- val customBindings = ArrayList<String>()
-
- resourceSets.forEach { set ->
- set.getSourceFiles().forEach({ res ->
- res.listFiles(object : FileFilter {
- override fun accept(file: File?): Boolean {
- return file != null && file.isDirectory() &&
- file.getName().toLowerCase().startsWith("layout")
- }
- })?.forEach { layoutDir ->
-
- layoutDir.listFiles(object : FileFilter {
- override fun accept(file: File?): Boolean {
- return file != null && !file.isDirectory() &&
- file.getName().toLowerCase().endsWith(".xml")
- }
- })?.forEach { xmlFile: File ->
- val document = parseXml(xmlFile)
- val bindingClass = expr.evaluate(document)
- if (bindingClass != null && !bindingClass.isEmpty()) {
- if (bindingClass.startsWith('.')) {
- customBindings.add("${packageName}${bindingClass}")
- } else if (bindingClass.contains(".")) {
- customBindings.add(bindingClass)
- } else {
- customBindings.add(
- "${packageName}.databinding.${bindingClass}")
+ project.getTasks().create(removeGeneratedTaskName,
+ javaClass<DataBindingExcludeGeneratedTask>(),
+ object : Action<DataBindingExcludeGeneratedTask> {
+ override fun execute(task: DataBindingExcludeGeneratedTask) {
+ packageTask.dependsOn(task)
+ task.dependsOn(javaCompileTask)
+ task.setAppPackage(packageName)
+ task.setInfoClassQualifiedName(xmlProcessor.getInfoClassFullName())
+ task.setPackageTask(packageTask)
+ task.setLibrary(isLibrary)
+ task.setGeneratedClassListFile(generatedClassListOut)
}
- }
- }
- }
- })
+ })
+ }
}
- return customBindings
}
}