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