1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.ant;
22 
23 import org.apache.tools.ant.*;
24 import proguard.*;
25 
26 import java.io.IOException;
27 import java.util.*;
28 
29 /**
30  * This Task allows to define a ProGuard configuration from Ant.
31  *
32  * @author Eric Lafortune
33  */
34 public class ConfigurationTask extends Task
35 {
36     protected final Configuration configuration = new Configuration();
37 
38 
39     /**
40      * Adds the contents of this configuration task to the given configuration.
41      * @param configuration the configuration to be extended.
42      */
appendTo(Configuration configuration)43     public void appendTo(Configuration configuration)
44     {
45         // Append all of these configuration entries to the given configuration.
46         configuration.programJars               = extendClassPath(configuration.programJars,
47                                                                   this.configuration.programJars);
48 
49         configuration.libraryJars               = extendClassPath(configuration.libraryJars,
50                                                                   this.configuration.libraryJars);
51 
52         configuration.keep                      = extendClassSpecifications(configuration.keep,
53                                                                             this.configuration.keep);
54 
55         configuration.keepDirectories           = extendList(configuration.keepDirectories,
56                                                              this.configuration.keepDirectories);
57 
58         configuration.whyAreYouKeeping          = extendClassSpecifications(configuration.whyAreYouKeeping,
59                                                                             this.configuration.whyAreYouKeeping);
60 
61         configuration.optimizations             = extendClassSpecifications(configuration.optimizations,
62                                                                             this.configuration.optimizations);
63 
64         configuration.assumeNoSideEffects       = extendClassSpecifications(configuration.assumeNoSideEffects,
65                                                                             this.configuration.assumeNoSideEffects);
66 
67         configuration.keepPackageNames          = extendList(configuration.keepPackageNames,
68                                                              this.configuration.keepPackageNames);
69 
70         configuration.keepAttributes            = extendList(configuration.keepAttributes,
71                                                              this.configuration.keepAttributes);
72 
73         configuration.adaptClassStrings         = extendList(configuration.adaptClassStrings,
74                                                              this.configuration.adaptClassStrings);
75 
76         configuration.adaptResourceFileNames    = extendList(configuration.adaptResourceFileNames,
77                                                              this.configuration.adaptResourceFileNames);
78 
79         configuration.adaptResourceFileContents = extendList(configuration.adaptResourceFileContents,
80                                                              this.configuration.adaptResourceFileContents);
81 
82         configuration.note                      = extendList(configuration.note,
83                                                              this.configuration.note);
84 
85         configuration.warn                      = extendList(configuration.warn,
86                                                              this.configuration.warn);
87     }
88 
89 
90     // Ant task nested elements.
91 
addConfiguredInjar(ClassPathElement classPathElement)92     public void addConfiguredInjar(ClassPathElement classPathElement)
93     {
94         configuration.programJars = extendClassPath(configuration.programJars,
95                                                     classPathElement,
96                                                     false);
97     }
98 
99 
addConfiguredOutjar(ClassPathElement classPathElement)100     public void addConfiguredOutjar(ClassPathElement classPathElement)
101     {
102         configuration.programJars = extendClassPath(configuration.programJars,
103                                                     classPathElement,
104                                                     true);
105     }
106 
107 
addConfiguredLibraryjar(ClassPathElement classPathElement)108     public void addConfiguredLibraryjar(ClassPathElement classPathElement)
109     {
110         configuration.libraryJars = extendClassPath(configuration.libraryJars,
111                                                     classPathElement,
112                                                     false);
113     }
114 
115 
addConfiguredKeepdirectory(FilterElement filterElement)116     public void addConfiguredKeepdirectory(FilterElement filterElement)
117     {
118         configuration.keepDirectories = extendFilter(configuration.keepDirectories,
119                                                      filterElement);
120     }
121 
122 
addConfiguredKeepdirectories(FilterElement filterElement)123     public void addConfiguredKeepdirectories(FilterElement filterElement)
124     {
125         configuration.keepDirectories = extendFilter(configuration.keepDirectories,
126                                                      filterElement);
127     }
128 
129 
addConfiguredKeep(KeepSpecificationElement keepSpecificationElement)130     public void addConfiguredKeep(KeepSpecificationElement keepSpecificationElement)
131     {
132         configuration.keep = extendKeepSpecifications(configuration.keep,
133                                                       keepSpecificationElement,
134                                                       true,
135                                                       false);
136     }
137 
138 
addConfiguredKeepclassmembers(KeepSpecificationElement keepSpecificationElement)139     public void addConfiguredKeepclassmembers(KeepSpecificationElement keepSpecificationElement)
140     {
141         configuration.keep = extendKeepSpecifications(configuration.keep,
142                                                       keepSpecificationElement,
143                                                       false,
144                                                       false);
145     }
146 
147 
addConfiguredKeepclasseswithmembers(KeepSpecificationElement keepSpecificationElement)148     public void addConfiguredKeepclasseswithmembers(KeepSpecificationElement keepSpecificationElement)
149     {
150         configuration.keep = extendKeepSpecifications(configuration.keep,
151                                                       keepSpecificationElement,
152                                                       true,
153                                                       true);
154     }
155 
156 
addConfiguredKeepnames(KeepSpecificationElement keepSpecificationElement)157     public void addConfiguredKeepnames(KeepSpecificationElement keepSpecificationElement)
158     {
159         // Set the shrinking flag, based on the name (backward compatibility).
160         keepSpecificationElement.setAllowshrinking(true);
161 
162         configuration.keep = extendKeepSpecifications(configuration.keep,
163                                                       keepSpecificationElement,
164                                                       true,
165                                                       false);
166     }
167 
168 
addConfiguredKeepclassmembernames(KeepSpecificationElement keepSpecificationElement)169     public void addConfiguredKeepclassmembernames(KeepSpecificationElement keepSpecificationElement)
170     {
171         // Set the shrinking flag, based on the name (backward compatibility).
172         keepSpecificationElement.setAllowshrinking(true);
173 
174         configuration.keep = extendKeepSpecifications(configuration.keep,
175                                                       keepSpecificationElement,
176                                                       false,
177                                                       false);
178     }
179 
180 
addConfiguredKeepclasseswithmembernames(KeepSpecificationElement keepSpecificationElement)181     public void addConfiguredKeepclasseswithmembernames(KeepSpecificationElement keepSpecificationElement)
182     {
183         // Set the shrinking flag, based on the name (backward compatibility).
184         keepSpecificationElement.setAllowshrinking(true);
185 
186         configuration.keep = extendKeepSpecifications(configuration.keep,
187                                                       keepSpecificationElement,
188                                                       true,
189                                                       true);
190     }
191 
192 
addConfiguredWhyareyoukeeping(ClassSpecificationElement classSpecificationElement)193     public void addConfiguredWhyareyoukeeping(ClassSpecificationElement classSpecificationElement)
194     {
195         configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping,
196                                                                    classSpecificationElement);
197     }
198 
199 
addConfiguredAssumenosideeffects(ClassSpecificationElement classSpecificationElement)200     public void addConfiguredAssumenosideeffects(ClassSpecificationElement classSpecificationElement)
201     {
202         configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects,
203                                                                       classSpecificationElement);
204     }
205 
206 
addConfiguredOptimizations(FilterElement filterElement)207     public void addConfiguredOptimizations(FilterElement filterElement)
208     {
209         addConfiguredOptimization(filterElement);
210     }
211 
212 
addConfiguredOptimization(FilterElement filterElement)213     public void addConfiguredOptimization(FilterElement filterElement)
214     {
215         configuration.optimizations = extendFilter(configuration.optimizations,
216                                                    filterElement);
217     }
218 
219 
addConfiguredKeeppackagename(FilterElement filterElement)220     public void addConfiguredKeeppackagename(FilterElement filterElement)
221     {
222         configuration.keepPackageNames = extendFilter(configuration.keepPackageNames,
223                                                       filterElement,
224                                                       true);
225     }
226 
227 
addConfiguredKeeppackagenames(FilterElement filterElement)228     public void addConfiguredKeeppackagenames(FilterElement filterElement)
229     {
230         configuration.keepPackageNames = extendFilter(configuration.keepPackageNames,
231                                                       filterElement,
232                                                       true);
233     }
234 
235 
addConfiguredKeepattributes(FilterElement filterElement)236     public void addConfiguredKeepattributes(FilterElement filterElement)
237     {
238         addConfiguredKeepattribute(filterElement);
239     }
240 
241 
addConfiguredKeepattribute(FilterElement filterElement)242     public void addConfiguredKeepattribute(FilterElement filterElement)
243     {
244         configuration.keepAttributes = extendFilter(configuration.keepAttributes,
245                                                     filterElement);
246     }
247 
248 
addConfiguredAdaptclassstrings(FilterElement filterElement)249     public void addConfiguredAdaptclassstrings(FilterElement filterElement)
250     {
251         configuration.adaptClassStrings = extendFilter(configuration.adaptClassStrings,
252                                                        filterElement, true);
253     }
254 
255 
addConfiguredAdaptresourcefilenames(FilterElement filterElement)256     public void addConfiguredAdaptresourcefilenames(FilterElement filterElement)
257     {
258         configuration.adaptResourceFileNames = extendFilter(configuration.adaptResourceFileNames,
259                                                             filterElement);
260     }
261 
262 
addConfiguredAdaptresourcefilecontents(FilterElement filterElement)263     public void addConfiguredAdaptresourcefilecontents(FilterElement filterElement)
264     {
265         configuration.adaptResourceFileContents = extendFilter(configuration.adaptResourceFileContents,
266                                                                filterElement);
267     }
268 
269 
addConfiguredDontnote(FilterElement filterElement)270     public void addConfiguredDontnote(FilterElement filterElement)
271     {
272         configuration.note = extendFilter(configuration.note, filterElement, true);
273     }
274 
275 
addConfiguredDontwarn(FilterElement filterElement)276     public void addConfiguredDontwarn(FilterElement filterElement)
277     {
278         configuration.warn = extendFilter(configuration.warn, filterElement, true);
279     }
280 
281 
addConfiguredConfiguration(ConfigurationElement configurationElement)282     public void addConfiguredConfiguration(ConfigurationElement configurationElement)
283     {
284         configurationElement.appendTo(configuration);
285     }
286 
287 
288     // Implementations for Task.
289 
addText(String text)290     public void addText(String text) throws BuildException
291     {
292         try
293         {
294             Project project = getProject();
295 
296             // Replace Ant-style properties ('${...}').
297             String arg = project.replaceProperties(text);
298 
299             // Get the combined system properties and Ant properties, for
300             // replacing ProGuard-style properties ('<...>').
301             Properties properties = new Properties();
302             properties.putAll(project.getProperties());
303 
304             ConfigurationParser parser = new ConfigurationParser(arg,
305                                                                  "embedded configuration",
306                                                                  project.getBaseDir(),
307                                                                  properties);
308 
309             try
310             {
311                 parser.parse(configuration);
312             }
313             catch (ParseException ex)
314             {
315                 throw new BuildException(ex.getMessage());
316             }
317             finally
318             {
319                 parser.close();
320             }
321         }
322         catch (IOException ex)
323         {
324             throw new BuildException(ex.getMessage());
325         }
326     }
327 
328 
329     // Small utility methods.
330 
extendClassPath(ClassPath classPath, ClassPathElement classPathElement, boolean output)331     private ClassPath extendClassPath(ClassPath        classPath,
332                                       ClassPathElement classPathElement,
333                                       boolean          output)
334     {
335         if (classPath == null)
336         {
337             classPath = new ClassPath();
338         }
339 
340         classPathElement.appendClassPathEntriesTo(classPath,
341                                                   output);
342 
343         return classPath;
344     }
345 
346 
extendClassPath(ClassPath classPath, ClassPath additionalClassPath)347     private ClassPath extendClassPath(ClassPath classPath,
348                                       ClassPath additionalClassPath)
349     {
350         if (additionalClassPath != null)
351         {
352             if (classPath == null)
353             {
354                 classPath = new ClassPath();
355             }
356 
357             classPath.addAll(additionalClassPath);
358         }
359 
360         return classPath;
361     }
362 
363 
extendKeepSpecifications(List keepSpecifications, KeepSpecificationElement keepSpecificationElement, boolean markClasses, boolean markClassesConditionally)364     private List extendKeepSpecifications(List                     keepSpecifications,
365                                           KeepSpecificationElement keepSpecificationElement,
366                                           boolean                  markClasses,
367                                           boolean                  markClassesConditionally)
368     {
369         if (keepSpecifications == null)
370         {
371             keepSpecifications = new ArrayList();
372         }
373 
374         keepSpecificationElement.appendTo(keepSpecifications,
375                                           markClasses,
376                                           markClassesConditionally);
377 
378         return keepSpecifications;
379     }
380 
381 
extendClassSpecifications(List classSpecifications, ClassSpecificationElement classSpecificationElement)382     private List extendClassSpecifications(List                      classSpecifications,
383                                            ClassSpecificationElement classSpecificationElement)
384     {
385         if (classSpecifications == null)
386         {
387             classSpecifications = new ArrayList();
388         }
389 
390         classSpecificationElement.appendTo(classSpecifications);
391 
392         return classSpecifications;
393     }
394 
395 
extendClassSpecifications(List classSpecifications, List additionalClassSpecifications)396     private List extendClassSpecifications(List classSpecifications,
397                                            List additionalClassSpecifications)
398     {
399         if (additionalClassSpecifications != null)
400         {
401             if (classSpecifications == null)
402             {
403                 classSpecifications = new ArrayList();
404             }
405 
406             classSpecifications.addAll(additionalClassSpecifications);
407         }
408 
409         return classSpecifications;
410     }
411 
412 
extendFilter(List filter, FilterElement filterElement)413     private List extendFilter(List          filter,
414                               FilterElement filterElement)
415     {
416         return extendFilter(filter, filterElement, false);
417     }
418 
419 
extendFilter(List filter, FilterElement filterElement, boolean internal)420     private List extendFilter(List          filter,
421                               FilterElement filterElement,
422                               boolean       internal)
423     {
424         if (filter == null)
425         {
426             filter = new ArrayList();
427         }
428 
429         filterElement.appendTo(filter, internal);
430 
431         return filter;
432     }
433 
434 
extendList(List list, List additionalList)435     private List extendList(List list,
436                             List additionalList)
437     {
438         if (additionalList != null)
439         {
440             if (list == null)
441             {
442                 list = new ArrayList();
443             }
444 
445             list.addAll(additionalList);
446         }
447 
448         return list;
449     }
450 }
451