1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 5b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.obfuscate; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.io.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This class can parse mapping files and invoke a processor for each of the 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * mapping entries. 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class MappingReader 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final File mappingFile; 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public MappingReader(File mappingFile) 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.mappingFile = mappingFile; 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Reads the mapping file, presenting all of the encountered mapping entries 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * to the given processor. 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void pump(MappingProcessor mappingProcessor) throws IOException 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato LineNumberReader reader = new LineNumberReader( 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new BufferedReader( 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new FileReader(mappingFile))); 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String className = null; 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Read the subsequent class mappings and class member mappings. 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (true) 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String line = reader.readLine(); 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (line == null) 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato line = line.trim(); 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The distinction between a class mapping and a class 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // member mapping is the initial whitespace. 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (line.endsWith(":")) 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Process the class mapping and remember the class's 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // old name. 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato className = processClassMapping(line, mappingProcessor); 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (className != null) 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Process the class member mapping, in the context of the 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // current old class name. 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato processClassMemberMapping(className, line, mappingProcessor); 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (IOException ex) 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IOException("Can't process mapping file (" + ex.getMessage() + ")"); 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato finally 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato reader.close(); 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (IOException ex) 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // This shouldn't happen. 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Parses the given line with a class mapping and processes the 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * results with the given mapping processor. Returns the old class name, 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * or null if any subsequent class member lines can be ignored. 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private String processClassMapping(String line, 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MappingProcessor mappingProcessor) 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // See if we can parse "___ -> ___:", containing the original 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // class name and the new class name. 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int arrowIndex = line.indexOf("->"); 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (arrowIndex < 0) 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return null; 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int colonIndex = line.indexOf(':', arrowIndex + 2); 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (colonIndex < 0) 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return null; 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Extract the elements. 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String className = line.substring(0, arrowIndex).trim(); 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String newClassName = line.substring(arrowIndex + 2, colonIndex).trim(); 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Process this class name mapping. 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean interested = mappingProcessor.processClassMapping(className, newClassName); 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return interested ? className : null; 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Parses the given line with a class member mapping and processes the 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * results with the given mapping processor. 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void processClassMemberMapping(String className, 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String line, 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MappingProcessor mappingProcessor) 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // See if we can parse "___:___:___ ___(___) -> ___", 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // containing the optional line numbers, the return type, the original 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // field/method name, optional arguments, and the new field/method name. 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int colonIndex1 = line.indexOf(':'); 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int colonIndex2 = colonIndex1 < 0 ? -1 : line.indexOf(':', colonIndex1 + 1); 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int spaceIndex = line.indexOf(' ', colonIndex2 + 2); 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int argumentIndex1 = line.indexOf('(', spaceIndex + 1); 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int argumentIndex2 = argumentIndex1 < 0 ? -1 : line.indexOf(')', argumentIndex1 + 1); 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int arrowIndex = line.indexOf("->", Math.max(spaceIndex, argumentIndex2) + 1); 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (spaceIndex < 0 || 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato arrowIndex < 0) 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return; 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Extract the elements. 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String type = line.substring(colonIndex2 + 1, spaceIndex).trim(); 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String name = line.substring(spaceIndex + 1, argumentIndex1 >= 0 ? argumentIndex1 : arrowIndex).trim(); 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String newName = line.substring(arrowIndex + 2).trim(); 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Process this class member mapping. 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (type.length() > 0 && 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato name.length() > 0 && 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newName.length() > 0) 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Is it a field or a method? 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (argumentIndex2 < 0) 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato mappingProcessor.processFieldMapping(className, type, name, newName); 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int firstLineNumber = 0; 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int lastLineNumber = 0; 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (colonIndex2 > 0) 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato firstLineNumber = Integer.parseInt(line.substring(0, colonIndex1).trim()); 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lastLineNumber = Integer.parseInt(line.substring(colonIndex1 + 1, colonIndex2).trim()); 185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato String arguments = line.substring(argumentIndex1 + 1, argumentIndex2).trim(); 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato mappingProcessor.processMethodMapping(className, 190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato firstLineNumber, 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lastLineNumber, 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato type, 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato name, 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato arguments, 195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newName); 196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 200