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