• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 Google Inc.
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 com.tonicsystems.jarjar;
18 
19 import com.android.jarjar.RemoveAndroidCompatAnnotationsJarTransformer;
20 import com.android.jarjar.StripAnnotation;
21 import com.android.jarjar.StripAnnotationsJarTransformer;
22 import com.tonicsystems.jarjar.util.EntryStruct;
23 import com.tonicsystems.jarjar.util.JarProcessor;
24 import com.tonicsystems.jarjar.util.JarProcessorChain;
25 import com.tonicsystems.jarjar.util.JarTransformerChain;
26 import com.tonicsystems.jarjar.util.RemappingClassTransformer;
27 import com.tonicsystems.jarjar.util.StandaloneJarProcessor;
28 import java.io.File;
29 import java.io.IOException;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 
37 class MainProcessor implements JarProcessor {
38   private final boolean verbose;
39   private final JarProcessorChain chain;
40   private final KeepProcessor kp;
41   private final Map<String, String> renames = new HashMap<>();
42 
43   // ANDROID-BEGIN: b/146418363 Add an Android-specific transformer to strip compat annotation
MainProcessor(List<PatternElement> patterns, boolean verbose, boolean skipManifest)44   public MainProcessor(List<PatternElement> patterns, boolean verbose, boolean skipManifest) {
45     this(patterns, verbose, skipManifest, false /* removeAndroidCompatAnnotations */);
46   }
47 
MainProcessor( List<PatternElement> patterns, boolean verbose, boolean skipManifest, boolean removeAndroidCompatAnnotations)48   public MainProcessor(
49       List<PatternElement> patterns,
50       boolean verbose,
51       boolean skipManifest,
52       boolean removeAndroidCompatAnnotations) {
53     // ANDROID-END: b/146418363 Add an Android-specific transformer to strip compat annotation
54     this.verbose = verbose;
55     List<Zap> zapList = new ArrayList<>();
56     List<Rule> ruleList = new ArrayList<>();
57     List<Keep> keepList = new ArrayList<>();
58     // ANDROID-BEGIN: b/222743634 Strip annotations from system module stubs
59     List<StripAnnotation> stripAnnotationList = new ArrayList<StripAnnotation>();
60     // ANDROID-END: b/222743634 Strip annotations from system module stubs
61     for (PatternElement pattern : patterns) {
62       if (pattern instanceof Zap) {
63         zapList.add((Zap) pattern);
64       } else if (pattern instanceof Rule) {
65         ruleList.add((Rule) pattern);
66       } else if (pattern instanceof Keep) {
67         keepList.add((Keep) pattern);
68       // ANDROID-BEGIN: b/222743634 Strip annotations from system module stubs
69       } else if (pattern instanceof StripAnnotation) {
70         stripAnnotationList.add((StripAnnotation) pattern);
71       }
72       // ANDROID-END: b/222743634 Strip annotations from system module stubs
73     }
74 
75     PackageRemapper pr = new PackageRemapper(ruleList, verbose);
76     kp = keepList.isEmpty() ? null : new KeepProcessor(keepList);
77 
78     List<JarProcessor> processors = new ArrayList<>();
79     if (skipManifest) {
80       processors.add(ManifestProcessor.getInstance());
81     }
82     if (kp != null) {
83       processors.add(kp);
84     }
85     processors.add(new ZapProcessor(zapList));
86     // ANDROID-BEGIN: b/146418363 Add an Android-specific transformer to strip compat annotation
87     if (removeAndroidCompatAnnotations)
88       processors.add(new RemoveAndroidCompatAnnotationsJarTransformer(pr));
89     // ANDROID-END: b/146418363 Add an Android-specific transformer to strip compat annotation
90     // ANDROID-BEGIN: b/222743634 Strip annotations from system module stubs
91     if (!stripAnnotationList.isEmpty()) {
92       processors.add(new StripAnnotationsJarTransformer(stripAnnotationList));
93     }
94     // ANDROID-END: b/222743634 Strip annotations from system module stubs
95     processors.add(
96         new JarTransformerChain(
97             new RemappingClassTransformer[] {new RemappingClassTransformer(pr)}));
98     processors.add(new ResourceProcessor(pr));
99     processors.add(new ServiceProcessor(pr));
100     chain = new JarProcessorChain(processors.toArray(new JarProcessor[0]));
101   }
102 
strip(File file)103   public void strip(File file) throws IOException {
104     if (kp == null) {
105       return;
106     }
107     Set<String> excludes = getExcludes();
108     if (!excludes.isEmpty()) {
109       StandaloneJarProcessor.run(file, file, new ExcludeProcessor(excludes, verbose));
110     }
111   }
112 
113   /**
114    * Returns the <code>.class</code> files to delete. As well the root-parameter as the rename ones
115    * are taken in consideration, so that the concerned files are not listed in the result.
116    *
117    * @return the paths of the files in the jar-archive, including the <code>.class</code> suffix
118    */
getExcludes()119   private Set<String> getExcludes() {
120     Set<String> result = new HashSet<>();
121     for (String exclude : kp.getExcludes()) {
122       String name = exclude + ".class";
123       String renamed = renames.get(name);
124       result.add((renamed != null) ? renamed : name);
125     }
126     return result;
127   }
128 
129   /**
130    * @param struct
131    * @return <code>true</code> if the entry is to include in the output jar
132    * @throws IOException
133    */
process(EntryStruct struct)134   public boolean process(EntryStruct struct) throws IOException {
135     String name = struct.name;
136     boolean keepIt = chain.process(struct);
137     if (keepIt) {
138       if (!name.equals(struct.name)) {
139         if (kp != null) {
140           renames.put(name, struct.name);
141         }
142         if (verbose) {
143           System.err.println("Renamed " + name + " -> " + struct.name);
144         }
145       }
146     } else {
147       if (verbose) {
148         System.err.println("Removed " + name);
149       }
150     }
151     return keepIt;
152   }
153 }
154