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 */
14package lockedregioncodeinjection;
15
16import java.io.BufferedInputStream;
17import java.io.FileOutputStream;
18import java.io.IOException;
19import java.io.InputStream;
20import java.io.OutputStream;
21import java.util.Collections;
22import java.util.Enumeration;
23import java.util.List;
24import java.util.zip.ZipEntry;
25import java.util.zip.ZipFile;
26import java.util.zip.ZipOutputStream;
27import org.objectweb.asm.ClassReader;
28import org.objectweb.asm.ClassWriter;
29
30public class Main {
31    public static void main(String[] args) throws IOException {
32        String inJar = null;
33        String outJar = null;
34
35        String legacyTargets = null;
36        String legacyPreMethods = null;
37        String legacyPostMethods = null;
38        for (int i = 0; i < args.length; i++) {
39            if ("-i".equals(args[i].trim())) {
40                i++;
41                inJar = args[i].trim();
42            } else if ("-o".equals(args[i].trim())) {
43                i++;
44                outJar = args[i].trim();
45            } else if ("--targets".equals(args[i].trim())) {
46                i++;
47                legacyTargets = args[i].trim();
48            } else if ("--pre".equals(args[i].trim())) {
49                i++;
50                legacyPreMethods = args[i].trim();
51            } else if ("--post".equals(args[i].trim())) {
52                i++;
53                legacyPostMethods = args[i].trim();
54            }
55
56        }
57
58        // TODO(acleung): Better help message than asserts.
59        assert inJar != null;
60        assert outJar != null;
61        assert legacyTargets == null || (legacyPreMethods != null && legacyPostMethods != null);
62
63        ZipFile zipSrc = new ZipFile(inJar);
64        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outJar));
65        List<LockTarget> targets = null;
66        if (legacyTargets != null) {
67            targets = Utils.getTargetsFromLegacyJackConfig(legacyTargets, legacyPreMethods,
68                    legacyPostMethods);
69        } else {
70            targets = Collections.emptyList();
71        }
72
73        Enumeration<? extends ZipEntry> srcEntries = zipSrc.entries();
74        while (srcEntries.hasMoreElements()) {
75            ZipEntry entry = srcEntries.nextElement();
76            ZipEntry newEntry = new ZipEntry(entry.getName());
77            zos.putNextEntry(newEntry);
78            BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry));
79
80            if (entry.getName().endsWith(".class")) {
81                convert(bis, zos, targets);
82            } else {
83                while (bis.available() > 0) {
84                    zos.write(bis.read());
85                }
86                zos.closeEntry();
87                bis.close();
88            }
89        }
90        zos.finish();
91        zos.close();
92        zipSrc.close();
93    }
94
95    private static void convert(InputStream in, OutputStream out, List<LockTarget> targets)
96            throws IOException {
97        ClassReader cr = new ClassReader(in);
98        ClassWriter cw = new ClassWriter(0);
99        LockFindingClassVisitor cv = new LockFindingClassVisitor(targets, cw);
100        cr.accept(cv, 0);
101        byte[] data = cw.toByteArray();
102        out.write(data);
103    }
104}
105