1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package lockedregioncodeinjection;
15 
16 import org.objectweb.asm.ClassReader;
17 import org.objectweb.asm.ClassWriter;
18 
19 import java.io.BufferedInputStream;
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.util.Collections;
25 import java.util.Enumeration;
26 import java.util.List;
27 import java.util.zip.ZipEntry;
28 import java.util.zip.ZipFile;
29 import java.util.zip.ZipOutputStream;
30 
31 public class Main {
main(String[] args)32     public static void main(String[] args) throws IOException {
33         String inJar = null;
34         String outJar = null;
35 
36         String legacyTargets = null;
37         String legacyPreMethods = null;
38         String legacyPostMethods = null;
39         for (int i = 0; i < args.length; i++) {
40             if ("-i".equals(args[i].trim())) {
41                 i++;
42                 inJar = args[i].trim();
43             } else if ("-o".equals(args[i].trim())) {
44                 i++;
45                 outJar = args[i].trim();
46             } else if ("--targets".equals(args[i].trim())) {
47                 i++;
48                 legacyTargets = args[i].trim();
49             } else if ("--pre".equals(args[i].trim())) {
50                 i++;
51                 legacyPreMethods = args[i].trim();
52             } else if ("--post".equals(args[i].trim())) {
53                 i++;
54                 legacyPostMethods = args[i].trim();
55             }
56 
57         }
58 
59         // TODO(acleung): Better help message than asserts.
60         assert inJar != null;
61         assert outJar != null;
62         assert legacyTargets == null || (legacyPreMethods != null && legacyPostMethods != null);
63 
64         ZipFile zipSrc = new ZipFile(inJar);
65         ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outJar));
66         List<LockTarget> targets = null;
67         if (legacyTargets != null) {
68             targets = Utils.getTargetsFromLegacyJackConfig(legacyTargets, legacyPreMethods,
69                     legacyPostMethods);
70         } else {
71             targets = Collections.emptyList();
72         }
73 
74         Enumeration<? extends ZipEntry> srcEntries = zipSrc.entries();
75         while (srcEntries.hasMoreElements()) {
76             ZipEntry entry = srcEntries.nextElement();
77             ZipEntry newEntry = new ZipEntry(entry.getName());
78             newEntry.setTime(entry.getTime());
79             zos.putNextEntry(newEntry);
80             BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry));
81 
82             if (entry.getName().endsWith(".class")) {
83                 convert(bis, zos, targets);
84             } else {
85                 while (bis.available() > 0) {
86                     zos.write(bis.read());
87                 }
88                 zos.closeEntry();
89                 bis.close();
90             }
91         }
92         zos.finish();
93         zos.close();
94         zipSrc.close();
95     }
96 
convert(InputStream in, OutputStream out, List<LockTarget> targets)97     private static void convert(InputStream in, OutputStream out, List<LockTarget> targets)
98             throws IOException {
99         ClassReader cr = new ClassReader(in);
100         ClassWriter cw = new ClassWriter(0);
101         LockFindingClassVisitor cv = new LockFindingClassVisitor(targets, cw);
102         cr.accept(cv, 0);
103         byte[] data = cw.toByteArray();
104         out.write(data);
105     }
106 }
107