1 /*
2  * Copyright (C) 2015 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 android.databinding.tool;
18 
19 import com.google.common.base.Preconditions;
20 
21 import org.apache.commons.io.FileUtils;
22 import org.apache.commons.io.IOUtils;
23 import org.gradle.api.DefaultTask;
24 import org.gradle.api.tasks.Input;
25 import org.gradle.api.tasks.TaskAction;
26 import org.gradle.api.tasks.bundling.Jar;
27 
28 import android.databinding.tool.processing.Scope;
29 import android.databinding.tool.util.L;
30 
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.util.List;
36 
37 /**
38  * Task to exclude generated classes from the Jar task of a library project
39  */
40 public class DataBindingExcludeGeneratedTask extends DefaultTask {
41     private String appPackage;
42     private String infoClassQualifiedName;
43     @Input
44     private File generatedClassListFile;
45     private boolean isLibrary;
46 
47     private org.gradle.api.tasks.bundling.Jar packageTask;
48     private final String EXCLUDE_PATTERN = "android/databinding/layouts/*.*";
49 
setAppPackage(String appPackage)50     public void setAppPackage(String appPackage) {
51         this.appPackage = appPackage;
52     }
53 
setInfoClassQualifiedName(String infoClassQualifiedName)54     public void setInfoClassQualifiedName(String infoClassQualifiedName) {
55         this.infoClassQualifiedName = infoClassQualifiedName;
56     }
57 
setLibrary(boolean isLibrary)58     public void setLibrary(boolean isLibrary) {
59         this.isLibrary = isLibrary;
60     }
61 
setPackageTask(Jar packageTask)62     public void setPackageTask(Jar packageTask) {
63         this.packageTask = packageTask;
64     }
65 
setGeneratedClassListFile(File generatedClassListFile)66     public void setGeneratedClassListFile(File generatedClassListFile) {
67         this.generatedClassListFile = generatedClassListFile;
68     }
69 
getAppPackage()70     public String getAppPackage() {
71         return appPackage;
72     }
73 
getInfoClassQualifiedName()74     public String getInfoClassQualifiedName() {
75         return infoClassQualifiedName;
76     }
77 
getGeneratedClassListFile()78     public File getGeneratedClassListFile() {
79         return generatedClassListFile;
80     }
81 
82     @TaskAction
excludeGenerated()83     public void excludeGenerated() {
84         L.d("Excluding generated classes from jar. Is library ? %s", isLibrary);
85         String appPkgAsClass = appPackage.replace('.', '/');
86         String infoClassAsClass = infoClassQualifiedName.replace('.', '/');
87         exclude(infoClassAsClass + ".class");
88         exclude(EXCLUDE_PATTERN);
89         if (isLibrary) {
90             exclude(appPkgAsClass + "/BR.*");
91             exclude("android/databinding/DynamicUtil.class");
92             List<String> generatedClasses = readGeneratedClasses();
93             for (String klass : generatedClasses) {
94                 exclude(klass.replace('.', '/') + ".class");
95             }
96         }
97         Scope.assertNoError();
98         L.d("Excluding generated classes from library jar is done.");
99     }
100 
exclude(String pattern)101     private void exclude(String pattern) {
102         L.d("exclude %s", pattern);
103         packageTask.exclude(pattern);
104     }
105 
readGeneratedClasses()106     private List<String> readGeneratedClasses() {
107         Preconditions.checkNotNull(generatedClassListFile, "Data binding exclude generated task"
108                 + " is not configured properly");
109         Preconditions.checkArgument(generatedClassListFile.exists(),
110                 "Generated class list does not exist %s", generatedClassListFile.getAbsolutePath());
111         FileInputStream fis = null;
112         try {
113             fis = new FileInputStream(generatedClassListFile);
114             return IOUtils.readLines(fis);
115         } catch (FileNotFoundException e) {
116             L.e(e, "Unable to read generated class list from %s",
117                     generatedClassListFile.getAbsoluteFile());
118         } catch (IOException e) {
119             L.e(e, "Unexpected exception while reading %s",
120                     generatedClassListFile.getAbsoluteFile());
121         } finally {
122             IOUtils.closeQuietly(fis);
123         }
124         Preconditions.checkState(false, "Could not read data binding generated class list");
125         return null;
126     }
127 }
128