1 /* 2 * Copyright (C) 2009 The Android Open Source Project 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.android.mkstubs; 18 19 import com.android.mkstubs.Main.Logger; 20 21 import org.objectweb.asm.ClassReader; 22 23 import java.io.IOException; 24 import java.util.Enumeration; 25 import java.util.Iterator; 26 import java.util.Map; 27 import java.util.Set; 28 import java.util.TreeMap; 29 import java.util.zip.ZipEntry; 30 import java.util.zip.ZipFile; 31 32 /** 33 * Analyzes an input Jar to get all the relevant classes according to the given filter. 34 * <p/> 35 * This is mostly a helper extracted for convenience. Callers will want to use 36 * {@link #parseInputJar(String)} followed by {@link #filter(Map, Filter, Logger)}. 37 */ 38 class AsmAnalyzer { 39 40 /** 41 * Parses a JAR file and returns a list of all classes founds using a map 42 * class name => ASM ClassReader. Class names are in the form "android.view.View". 43 */ parseInputJar(String inputJarPath)44 Map<String,ClassReader> parseInputJar(String inputJarPath) throws IOException { 45 TreeMap<String, ClassReader> classes = new TreeMap<>(); 46 47 ZipFile zip = new ZipFile(inputJarPath); 48 Enumeration<? extends ZipEntry> entries = zip.entries(); 49 ZipEntry entry; 50 while (entries.hasMoreElements()) { 51 entry = entries.nextElement(); 52 if (entry.getName().endsWith(".class")) { 53 ClassReader cr = new ClassReader(zip.getInputStream(entry)); 54 String className = classReaderToAsmName(cr); 55 classes.put(className, cr); 56 } 57 } 58 59 return classes; 60 } 61 62 /** 63 * Utility that returns the fully qualified ASM class name for a ClassReader. 64 * E.g. it returns something like android/view/View. 65 */ classReaderToAsmName(ClassReader classReader)66 static String classReaderToAsmName(ClassReader classReader) { 67 if (classReader == null) { 68 return null; 69 } else { 70 return classReader.getClassName(); 71 } 72 } 73 74 /** 75 * Filters the set of classes. Removes all classes that should not be included in the 76 * filter or that should be excluded. This modifies the map in-place. 77 * 78 * @param classes The in-out map of classes to examine and filter. The map is filtered 79 * in-place. 80 * @param filter A filter describing which classes to include and which ones to exclude. 81 * @param log 82 */ filter(Map<String, ClassReader> classes, Filter filter, Logger log)83 void filter(Map<String, ClassReader> classes, Filter filter, Logger log) { 84 85 Set<String> keys = classes.keySet(); 86 for(Iterator<String> it = keys.iterator(); it.hasNext(); ) { 87 String key = it.next(); 88 89 // TODO: We *could* filter out all private classes here: classes.get(key).getAccess(). 90 91 // remove if we don't keep it 92 if (!filter.accept(key)) { 93 log.debug("- Remove class " + key); 94 it.remove(); 95 } 96 } 97 } 98 99 } 100