~ubuntu-branches/ubuntu/maverick/proguard/maverick

« back to all changes in this revision

Viewing changes to src/proguard/obfuscate/MemberInfoLinker.java

  • Committer: Bazaar Package Importer
  • Author(s): Sam Clegg
  • Date: 2005-11-13 09:42:59 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051113094259-432zf4yyw4890mmn
Tags: 3.4-1
* New upstream release (Closes: #338355)
* debian/control: bump standards version
* debian/copyright: update FSF address
* increase java stack size for proguard and proguardgui

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: MemberInfoLinker.java,v 1.9 2004/11/20 15:41:24 eric Exp $
2
 
 *
3
 
 * ProGuard -- shrinking, optimization, and obfuscation of Java class files.
4
 
 *
5
 
 * Copyright (c) 2002-2004 Eric Lafortune (eric@graphics.cornell.edu)
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify it
8
 
 * under the terms of the GNU General Public License as published by the Free
9
 
 * Software Foundation; either version 2 of the License, or (at your option)
10
 
 * any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
13
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15
 
 * more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License along
18
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
 
 */
21
 
package proguard.obfuscate;
22
 
 
23
 
import proguard.classfile.*;
24
 
import proguard.classfile.visitor.*;
25
 
 
26
 
import java.util.*;
27
 
 
28
 
 
29
 
/**
30
 
 * This ClassFileVisitor links all methods that should get the same names
31
 
 * in the name spaces of all visited class files. A class file's name space
32
 
 * encompasses all of its subclasses and interfaces. It is typically a class file
33
 
 * that is not being subclassed. Chains of links that have been created in
34
 
 * previous invocations are merged with new chains of links, in order to create
35
 
 * a consistent set of chains. Class initialization methods and constructors are
36
 
 * ignored.
37
 
 *
38
 
 * @see MemberInfoObfuscator
39
 
 *
40
 
 * @author Eric Lafortune
41
 
 */
42
 
public class MemberInfoLinker
43
 
  implements ClassFileVisitor,
44
 
             MemberInfoVisitor
45
 
{
46
 
    // An object that is reset and reused every time.
47
 
    // The map: [class member name+descriptor - class member info]
48
 
    private final Map methodInfoMap = new HashMap();
49
 
 
50
 
 
51
 
    // Implementations for ClassFileVisitor.
52
 
 
53
 
    public void visitProgramClassFile(ProgramClassFile programClassFile)
54
 
    {
55
 
        // Collect all members in this class's name space.
56
 
        programClassFile.hierarchyAccept(true, true, true, false,
57
 
                                         new AllMemberInfoVisitor(this));
58
 
 
59
 
        // Clean up for obfuscation of the next name space.
60
 
        methodInfoMap.clear();
61
 
    }
62
 
 
63
 
 
64
 
    public void visitLibraryClassFile(LibraryClassFile libraryClassFile)
65
 
    {
66
 
    }
67
 
 
68
 
 
69
 
    // Implementations for MemberInfoVisitor.
70
 
 
71
 
    public void visitProgramFieldInfo(ProgramClassFile programClassFile, ProgramFieldInfo programFieldInfo)
72
 
    {
73
 
    }
74
 
 
75
 
 
76
 
    public void visitProgramMethodInfo(ProgramClassFile programClassFile, ProgramMethodInfo programMethodInfo)
77
 
    {
78
 
        visitMethodInfo(programClassFile, programMethodInfo);
79
 
    }
80
 
 
81
 
 
82
 
    public void visitLibraryFieldInfo(LibraryClassFile libraryClassFile, LibraryFieldInfo libraryFieldInfo)
83
 
    {
84
 
    }
85
 
 
86
 
 
87
 
    public void visitLibraryMethodInfo(LibraryClassFile libraryClassFile, LibraryMethodInfo libraryMethodInfo)
88
 
    {
89
 
        visitMethodInfo(libraryClassFile, libraryMethodInfo);
90
 
    }
91
 
 
92
 
 
93
 
    /**
94
 
     * Links the given method into the chains of links. Class initialization
95
 
     * methods and constructors are ignored.
96
 
     * @param classFile  the class file of the given method.
97
 
     * @param methodInfo the method to be linked.
98
 
     */
99
 
    private void visitMethodInfo(ClassFile classFile, MethodInfo methodInfo)
100
 
    {
101
 
        // Private methods don't have to be linked.
102
 
        if ((methodInfo.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) != 0)
103
 
        {
104
 
            return;
105
 
        }
106
 
 
107
 
        // Get the method's original name and descriptor.
108
 
        String name       = methodInfo.getName(classFile);
109
 
        String descriptor = methodInfo.getDescriptor(classFile);
110
 
 
111
 
        // Special cases: <clinit> and <init> are always kept unchanged.
112
 
        // We can ignore them here.
113
 
        if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ||
114
 
            name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
115
 
        {
116
 
            return;
117
 
        }
118
 
 
119
 
        // Get the last method in the chain.
120
 
        MemberInfo thisLastMemberInfo = lastMemberInfo(methodInfo);
121
 
 
122
 
        // See if we've already come across a method with the same name and
123
 
        // descriptor.
124
 
        String key = name + descriptor;
125
 
        MethodInfo otherMethodInfo = (MethodInfo)methodInfoMap.get(key);
126
 
 
127
 
        if (otherMethodInfo == null)
128
 
        {
129
 
            // Store the new class method info in the map.
130
 
            methodInfoMap.put(key, thisLastMemberInfo);
131
 
        }
132
 
        else
133
 
        {
134
 
            // Get the last method in the other chain.
135
 
            MemberInfo otherLastMemberInfo = lastMemberInfo(otherMethodInfo);
136
 
 
137
 
            // Check if both link chains aren't already ending in the same element.
138
 
            if (thisLastMemberInfo != otherLastMemberInfo)
139
 
            {
140
 
                // Merge the two chains, making sure LibraryMethodInfo elements,
141
 
                // if any, are at the end of the resulting chain.
142
 
                if (thisLastMemberInfo instanceof LibraryMethodInfo)
143
 
                {
144
 
                    // This class method chain ends with a library class method.
145
 
                    // Link this chain to the end of the other one.
146
 
                    otherLastMemberInfo.setVisitorInfo(thisLastMemberInfo);
147
 
                }
148
 
                /* We can skip this test and go straight to the final case.
149
 
                else if (otherLastVisitorAccepter instanceof LibraryMethodInfo)
150
 
                {
151
 
                    // The other method chain ends with a library class method.
152
 
                    // Link the other chain to the end of this one.
153
 
                    thisLastVisitorAccepter.setVisitorInfo(otherLastVisitorAccepter);
154
 
                }
155
 
                */
156
 
                else
157
 
                {
158
 
                    // We have two non-library methods. Link their chains
159
 
                    // one way or another.
160
 
                    thisLastMemberInfo.setVisitorInfo(otherLastMemberInfo);
161
 
                }
162
 
            }
163
 
        }
164
 
    }
165
 
 
166
 
 
167
 
    // Small utility methods.
168
 
 
169
 
    /**
170
 
     * Finds the last class member in the linked list of class members.
171
 
     * @param memberInfo the given class member.
172
 
     * @return the last class member in the linked list.
173
 
     */
174
 
    static MemberInfo lastMemberInfo(MemberInfo memberInfo)
175
 
    {
176
 
        VisitorAccepter lastVisitorAccepter = memberInfo;
177
 
        while (lastVisitorAccepter.getVisitorInfo() != null &&
178
 
               lastVisitorAccepter.getVisitorInfo() instanceof VisitorAccepter)
179
 
        {
180
 
            lastVisitorAccepter = (VisitorAccepter)lastVisitorAccepter.getVisitorInfo();
181
 
        }
182
 
 
183
 
        return (MemberInfo)lastVisitorAccepter;
184
 
    }
185
 
}