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.ArrayList;
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         List<LockTarget> targets = new ArrayList<>();
40         for (int i = 0; i < args.length; i++) {
41             if ("-i".equals(args[i].trim())) {
42                 i++;
43                 inJar = args[i].trim();
44             } else if ("-o".equals(args[i].trim())) {
45                 i++;
46                 outJar = args[i].trim();
47             } else if ("--targets".equals(args[i].trim())) {
48                 i++;
49                 legacyTargets = args[i].trim();
50             } else if ("--pre".equals(args[i].trim())) {
51                 i++;
52                 legacyPreMethods = args[i].trim();
53             } else if ("--post".equals(args[i].trim())) {
54                 i++;
55                 legacyPostMethods = args[i].trim();
56             } else if ("--scoped".equals(args[i].trim())) {
57                 i++;
58                 targets.add(Utils.getScopedTarget(args[i].trim()));
59             }
60         }
61 
62         if (inJar == null) {
63             throw new RuntimeException("missing input jar path");
64         }
65         if (outJar == null) {
66             throw new RuntimeException("missing output jar path");
67         }
68         assert legacyTargets == null || (legacyPreMethods != null && legacyPostMethods != null);
69 
70         ZipFile zipSrc = new ZipFile(inJar);
71         ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outJar));
72         if (legacyTargets != null) {
73             targets.addAll(Utils.getTargetsFromLegacyJackConfig(legacyTargets, legacyPreMethods,
74                                                                 legacyPostMethods));
75         }
76 
77         Enumeration<? extends ZipEntry> srcEntries = zipSrc.entries();
78         while (srcEntries.hasMoreElements()) {
79             ZipEntry entry = srcEntries.nextElement();
80             ZipEntry newEntry = new ZipEntry(entry.getName());
81             newEntry.setTime(entry.getTime());
82             zos.putNextEntry(newEntry);
83             BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry));
84 
85             if (entry.getName().endsWith(".class")) {
86                 convert(bis, zos, targets);
87             } else {
88                 while (bis.available() > 0) {
89                     zos.write(bis.read());
90                 }
91                 zos.closeEntry();
92                 bis.close();
93             }
94         }
95         zos.finish();
96         zos.close();
97         zipSrc.close();
98     }
99 
convert(InputStream in, OutputStream out, List<LockTarget> targets)100     private static void convert(InputStream in, OutputStream out, List<LockTarget> targets)
101             throws IOException {
102         ClassReader cr = new ClassReader(in);
103         ClassWriter cw = new ClassWriter(0);
104         LockFindingClassVisitor cv = new LockFindingClassVisitor(targets, cw);
105         cr.accept(cv, 0);
106         byte[] data = cw.toByteArray();
107         out.write(data);
108     }
109 }
110