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.retrace;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.ClassUtil;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.obfuscate.*;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.io.*;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.*;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.regex.*;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Tool for de-obfuscating stack traces of applications that were obfuscated
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with ProGuard.
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ReTrace
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   MappingProcessor
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String REGEX_OPTION   = "-regex";
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String VERBOSE_OPTION = "-verbose";
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
43b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
4454f59ac04f3e21d5aecdd46bb1e7f4577924ab92Alon Albert    public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c.%m\\s*\\(.*?(?::%l)?\\)\\s*)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)";
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String REGEX_CLASS       = "\\b(?:[A-Za-z0-9_$]+\\.)*[A-Za-z0-9_$]+\\b";
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String REGEX_CLASS_SLASH = "\\b(?:[A-Za-z0-9_$]+/)*[A-Za-z0-9_$]+\\b";
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String REGEX_LINE_NUMBER = "\\b[0-9]+\\b";
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String REGEX_TYPE        = REGEX_CLASS + "(?:\\[\\])*";
50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private static final String REGEX_MEMBER      = "<?\\b[A-Za-z0-9_$]+\\b>?";
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final String REGEX_ARGUMENTS   = "(?:" + REGEX_TYPE + "(?:\\s*,\\s*" + REGEX_TYPE + ")*)?";
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // The class settings.
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final String  regularExpression;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean verbose;
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final File    mappingFile;
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final File    stackTraceFile;
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Map classMap       = new HashMap();
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Map classFieldMap  = new HashMap();
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Map classMethodMap = new HashMap();
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new ReTrace object to process stack traces on the standard
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * input, based on the given mapping file name.
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param regularExpression the regular expression for parsing the lines in
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          the stack trace.
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param verbose           specifies whether the de-obfuscated stack trace
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          should be verbose.
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param mappingFile       the mapping file that was written out by
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          ProGuard.
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ReTrace(String  regularExpression,
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   boolean verbose,
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   File    mappingFile)
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(regularExpression, verbose, mappingFile, null);
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new ReTrace object to process a stack trace from the given file,
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * based on the given mapping file name.
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param regularExpression the regular expression for parsing the lines in
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          the stack trace.
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param verbose           specifies whether the de-obfuscated stack trace
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          should be verbose.
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param mappingFile       the mapping file that was written out by
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          ProGuard.
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param stackTraceFile    the optional name of the file that contains the
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                          stack trace.
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ReTrace(String  regularExpression,
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   boolean verbose,
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   File    mappingFile,
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   File    stackTraceFile)
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.regularExpression = regularExpression;
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.verbose           = verbose;
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.mappingFile       = mappingFile;
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.stackTraceFile    = stackTraceFile;
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Performs the subsequent ReTrace operations.
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void execute() throws IOException
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the mapping file.
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        MappingReader mappingReader = new MappingReader(mappingFile);
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        mappingReader.pump(this);
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        StringBuffer expressionBuffer    = new StringBuffer(regularExpression.length() + 32);
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        char[]       expressionTypes     = new char[32];
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int          expressionTypeCount = 0;
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int index = 0;
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (true)
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int nextIndex = regularExpression.indexOf('%', index);
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (nextIndex < 0                             ||
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextIndex == regularExpression.length()-1 ||
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                expressionTypeCount == expressionTypes.length)
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            expressionBuffer.append(regularExpression.substring(index, nextIndex));
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            expressionBuffer.append('(');
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            char expressionType = regularExpression.charAt(nextIndex + 1);
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch(expressionType)
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 'c':
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_CLASS);
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 'C':
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_CLASS_SLASH);
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 'l':
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_LINE_NUMBER);
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 't':
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_TYPE);
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 'f':
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_MEMBER);
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 'm':
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_MEMBER);
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case 'a':
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    expressionBuffer.append(REGEX_ARGUMENTS);
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            expressionBuffer.append(')');
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            expressionTypes[expressionTypeCount++] = expressionType;
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            index = nextIndex + 2;
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        expressionBuffer.append(regularExpression.substring(index));
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Pattern pattern = Pattern.compile(expressionBuffer.toString());
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the stack trace file.
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        LineNumberReader reader =
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new LineNumberReader(stackTraceFile == null ?
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (Reader)new InputStreamReader(System.in) :
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (Reader)new BufferedReader(new FileReader(stackTraceFile)));
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            StringBuffer outLine = new StringBuffer(256);
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            List         extraOutLines  = new ArrayList();
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String className = null;
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Read the line in the stack trace.
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            while (true)
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                String line = reader.readLine();
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (line == null)
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Matcher matcher = pattern.matcher(line);
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (matcher.matches())
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    int    lineNumber = 0;
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    String type       = null;
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    String arguments  = null;
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Figure out a class name, line number, type, and
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // arguments beforehand.
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++)
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        int startIndex = matcher.start(expressionTypeIndex + 1);
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        if (startIndex >= 0)
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            String match = matcher.group(expressionTypeIndex + 1);
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            char expressionType = expressionTypes[expressionTypeIndex];
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            switch (expressionType)
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'c':
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    className = originalClassName(match);
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'C':
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    className = originalClassName(ClassUtil.externalClassName(match));
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'l':
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    lineNumber = Integer.parseInt(match);
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 't':
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    type = originalType(match);
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'a':
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    arguments = originalArguments(match);
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Actually construct the output line.
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    int lineIndex = 0;
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    outLine.setLength(0);
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    extraOutLines.clear();
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++)
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        int startIndex = matcher.start(expressionTypeIndex + 1);
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        if (startIndex >= 0)
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            int    endIndex = matcher.end(expressionTypeIndex + 1);
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            String match    = matcher.group(expressionTypeIndex + 1);
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Copy a literal piece of input line.
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            outLine.append(line.substring(lineIndex, startIndex));
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            char expressionType = expressionTypes[expressionTypeIndex];
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            switch (expressionType)
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'c':
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    className = originalClassName(match);
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    outLine.append(className);
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'C':
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    className = originalClassName(ClassUtil.externalClassName(match));
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    outLine.append(ClassUtil.internalClassName(className));
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'l':
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    lineNumber = Integer.parseInt(match);
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    outLine.append(match);
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 't':
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    type = originalType(match);
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    outLine.append(type);
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'f':
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    originalFieldName(className,
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      match,
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      type,
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      outLine,
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      extraOutLines);
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'm':
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    originalMethodName(className,
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                       match,
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                       lineNumber,
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                       type,
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                       arguments,
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                       outLine,
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                       extraOutLines);
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                case 'a':
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    arguments = originalArguments(match);
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    outLine.append(arguments);
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    break;
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Skip the original element whose processed version
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // has just been appended.
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            lineIndex = endIndex;
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Copy the last literal piece of input line.
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    outLine.append(line.substring(lineIndex));
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Print out the main line.
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    System.out.println(outLine);
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Print out any additional lines.
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    for (int extraLineIndex = 0; extraLineIndex < extraOutLines.size(); extraLineIndex++)
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        System.out.println(extraOutLines.get(extraLineIndex));
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                else
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Print out the original line.
327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    System.out.println(line);
328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (IOException ex)
332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new IOException("Can't read stack trace (" + ex.getMessage() + ")");
334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        finally
336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (stackTraceFile != null)
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                try
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    reader.close();
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                catch (IOException ex)
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // This shouldn't happen.
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Finds the original field name(s), appending the first one to the out
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * line, and any additional alternatives to the extra lines.
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void originalFieldName(String       className,
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   String       obfuscatedFieldName,
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   String       type,
359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   StringBuffer outLine,
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   List         extraOutLines)
361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int extraIndent = -1;
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Class name -> obfuscated field names.
365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Map fieldMap = (Map)classFieldMap.get(className);
366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (fieldMap != null)
367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Obfuscated field names -> fields.
369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Set fieldSet = (Set)fieldMap.get(obfuscatedFieldName);
370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (fieldSet != null)
371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Find all matching fields.
373b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Iterator fieldInfoIterator = fieldSet.iterator();
374b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                while (fieldInfoIterator.hasNext())
375b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
376b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    FieldInfo fieldInfo = (FieldInfo)fieldInfoIterator.next();
377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (fieldInfo.matches(type))
378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        // Is this the first matching field?
380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        if (extraIndent < 0)
381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            extraIndent = outLine.length();
383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Append the first original name.
385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (verbose)
386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                outLine.append(fieldInfo.type).append(' ');
388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            outLine.append(fieldInfo.originalName);
390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        else
392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Create an additional line with the proper
394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // indentation.
395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            StringBuffer extraBuffer = new StringBuffer();
396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            for (int counter = 0; counter < extraIndent; counter++)
397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                extraBuffer.append(' ');
399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Append the alternative name.
402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (verbose)
403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                extraBuffer.append(fieldInfo.type).append(' ');
405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            extraBuffer.append(fieldInfo.originalName);
407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Store the additional line.
409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            extraOutLines.add(extraBuffer);
410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Just append the obfuscated name if we haven't found any matching
417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // fields.
418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (extraIndent < 0)
419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            outLine.append(obfuscatedFieldName);
421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Finds the original method name(s), appending the first one to the out
427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * line, and any additional alternatives to the extra lines.
428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void originalMethodName(String       className,
430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    String       obfuscatedMethodName,
431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    int          lineNumber,
432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    String       type,
433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    String       arguments,
434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    StringBuffer outLine,
435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    List         extraOutLines)
436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int extraIndent = -1;
438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Class name -> obfuscated method names.
440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Map methodMap = (Map)classMethodMap.get(className);
441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (methodMap != null)
442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Obfuscated method names -> methods.
444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Set methodSet = (Set)methodMap.get(obfuscatedMethodName);
445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (methodSet != null)
446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Find all matching methods.
448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Iterator methodInfoIterator = methodSet.iterator();
449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                while (methodInfoIterator.hasNext())
450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    MethodInfo methodInfo = (MethodInfo)methodInfoIterator.next();
452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (methodInfo.matches(lineNumber, type, arguments))
453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        // Is this the first matching method?
455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        if (extraIndent < 0)
456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            extraIndent = outLine.length();
458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Append the first original name.
460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (verbose)
461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                outLine.append(methodInfo.type).append(' ');
463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            outLine.append(methodInfo.originalName);
465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (verbose)
466b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                outLine.append('(').append(methodInfo.arguments).append(')');
468b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        else
471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Create an additional line with the proper
473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // indentation.
474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            StringBuffer extraBuffer = new StringBuffer();
475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            for (int counter = 0; counter < extraIndent; counter++)
476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                extraBuffer.append(' ');
478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Append the alternative name.
481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (verbose)
482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
483b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                extraBuffer.append(methodInfo.type).append(' ');
484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            extraBuffer.append(methodInfo.originalName);
486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (verbose)
487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                extraBuffer.append('(').append(methodInfo.arguments).append(')');
489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
490b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            // Store the additional line.
492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            extraOutLines.add(extraBuffer);
493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
495b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Just append the obfuscated name if we haven't found any matching
500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // methods.
501b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (extraIndent < 0)
502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            outLine.append(obfuscatedMethodName);
504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the original argument types.
510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String originalArguments(String obfuscatedArguments)
512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        StringBuffer originalArguments = new StringBuffer();
514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
515b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int startIndex = 0;
516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (true)
517b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int endIndex = obfuscatedArguments.indexOf(',', startIndex);
519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (endIndex < 0)
520b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
521b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
522b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
523b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
524b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            originalArguments.append(originalType(obfuscatedArguments.substring(startIndex, endIndex).trim())).append(',');
525b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
526b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            startIndex = endIndex + 1;
527b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
528b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
529b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        originalArguments.append(originalType(obfuscatedArguments.substring(startIndex).trim()));
530b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
531b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return originalArguments.toString();
532b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
533b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
534b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
535b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
536b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the original type.
537b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
538b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String originalType(String obfuscatedType)
539b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
540b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int index = obfuscatedType.indexOf('[');
541b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
542b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return index >= 0 ?
543b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            originalClassName(obfuscatedType.substring(0, index)) + obfuscatedType.substring(index) :
544b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            originalClassName(obfuscatedType);
545b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
546b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
547b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
548b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the original class name.
550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String originalClassName(String obfuscatedClassName)
552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
553b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String originalClassName = (String)classMap.get(obfuscatedClassName);
554b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return originalClassName != null ?
556b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            originalClassName :
557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            obfuscatedClassName;
558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
560b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
561b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for MappingProcessor.
562b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
563b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean processClassMapping(String className, String newClassName)
564b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
565b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Obfuscated class name -> original class name.
566b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        classMap.put(newClassName, className);
567b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
568b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return true;
569b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
570b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
571b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
572b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void processFieldMapping(String className, String fieldType, String fieldName, String newFieldName)
573b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
574b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Original class name -> obfuscated field names.
575b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Map fieldMap = (Map)classFieldMap.get(className);
576b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (fieldMap == null)
577b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
578b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            fieldMap = new HashMap();
579b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classFieldMap.put(className, fieldMap);
580b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
581b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
582b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Obfuscated field name -> fields.
583b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Set fieldSet = (Set)fieldMap.get(newFieldName);
584b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (fieldSet == null)
585b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
586b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            fieldSet = new LinkedHashSet();
587b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            fieldMap.put(newFieldName, fieldSet);
588b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
589b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
590b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Add the field information.
591b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        fieldSet.add(new FieldInfo(fieldType,
592b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   fieldName));
593b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
594b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
595b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
596b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void processMethodMapping(String className, int firstLineNumber, int lastLineNumber, String methodReturnType, String methodName, String methodArguments, String newMethodName)
597b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
598b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Original class name -> obfuscated method names.
599b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Map methodMap = (Map)classMethodMap.get(className);
600b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (methodMap == null)
601b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
602b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            methodMap = new HashMap();
603b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classMethodMap.put(className, methodMap);
604b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
605b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
606b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Obfuscated method name -> methods.
607b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Set methodSet = (Set)methodMap.get(newMethodName);
608b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (methodSet == null)
609b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
610b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            methodSet = new LinkedHashSet();
611b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            methodMap.put(newMethodName, methodSet);
612b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
613b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
614b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Add the method information.
615b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        methodSet.add(new MethodInfo(firstLineNumber,
616b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     lastLineNumber,
617b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     methodReturnType,
618b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     methodArguments,
619b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     methodName));
620b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
621b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
622b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
623b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
624b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * A field record.
625b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
626b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static class FieldInfo
627b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
628b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private String type;
629b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private String originalName;
630b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
631b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
632b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private FieldInfo(String type, String originalName)
633b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
634b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.type         = type;
635b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.originalName = originalName;
636b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
637b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
638b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
639b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private boolean matches(String type)
640b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
641b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return
642b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                type == null || type.equals(this.type);
643b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
644b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
645b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
646b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
647b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
648b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * A method record.
649b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
650b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static class MethodInfo
651b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
652b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private int    firstLineNumber;
653b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private int    lastLineNumber;
654b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private String type;
655b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private String arguments;
656b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private String originalName;
657b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
658b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
659b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private MethodInfo(int firstLineNumber, int lastLineNumber, String type, String arguments, String originalName)
660b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
661b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.firstLineNumber = firstLineNumber;
662b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.lastLineNumber  = lastLineNumber;
663b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.type            = type;
664b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.arguments       = arguments;
665b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.originalName    = originalName;
666b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
667b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
668b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
669b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private boolean matches(int lineNumber, String type, String arguments)
670b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
671b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return
672b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (lineNumber == 0    || (firstLineNumber <= lineNumber && lineNumber <= lastLineNumber) || lastLineNumber == 0) &&
673b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (type       == null || type.equals(this.type))                                                                 &&
674b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (arguments  == null || arguments.equals(this.arguments));
675b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
676b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
677b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
678b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
679b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
680b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * The main program for ReTrace.
681b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
682b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public static void main(String[] args)
683b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
684b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (args.length < 1)
685b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
686b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("Usage: java proguard.ReTrace [-verbose] <mapping_file> [<stacktrace_file>]");
687b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.exit(-1);
688b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
689b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
690b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String  regularExpresssion = STACK_TRACE_EXPRESSION;
691b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        boolean verbose            = false;
692b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
693b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int argumentIndex = 0;
694b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (argumentIndex < args.length)
695b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
696b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String arg = args[argumentIndex];
697b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (arg.equals(REGEX_OPTION))
698b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
699b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                regularExpresssion = args[++argumentIndex];
700b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
701b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (arg.equals(VERBOSE_OPTION))
702b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
703b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                verbose = true;
704b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
705b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
706b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
707b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
708b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
709b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
710b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            argumentIndex++;
711b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
712b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
713b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (argumentIndex >= args.length)
714b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
715b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("Usage: java proguard.ReTrace [-regex <regex>] [-verbose] <mapping_file> [<stacktrace_file>]");
716b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.exit(-1);
717b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
718b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
719b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        File mappingFile    = new File(args[argumentIndex++]);
720b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        File stackTraceFile = argumentIndex < args.length ?
721b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new File(args[argumentIndex]) :
722b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            null;
723b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
724b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ReTrace reTrace = new ReTrace(regularExpresssion, verbose, mappingFile, stackTraceFile);
725b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
726b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
727b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
728b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Execute ReTrace with its given settings.
729b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            reTrace.execute();
730b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
731b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (IOException ex)
732b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
733b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (verbose)
734b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
735b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Print a verbose stack trace.
736b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ex.printStackTrace();
737b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
738b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
739b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
740b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Print just the stack trace message.
741b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.err.println("Error: "+ex.getMessage());
742b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
743b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
744b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.exit(1);
745b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
746b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
747b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        System.exit(0);
748b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
749b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
750