KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > classfile > util > MethodLinker


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 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.classfile.util;
22
23 import proguard.classfile.*;
24 import proguard.classfile.visitor.*;
25
26 import java.util.*;
27
28 /**
29  * This ClassVisitor links all corresponding non-private methods in the class
30  * hierarchies of all visited classes. Visited classes are typically all class
31  * files that are not being subclassed. Chains of links that have been created
32  * in previous invocations are merged with new chains of links, in order to
33  * create a consistent set of chains.
34  * <p>
35  * As a MemberVisitor, it links all corresponding class members that it visits,
36  * including fields and private class members.
37  * <p>
38  * Class initialization methods and constructors are always ignored.
39  *
40  * @author Eric Lafortune
41  */

42 public class MethodLinker
43 extends SimplifiedVisitor
44 implements ClassVisitor,
45              MemberVisitor
46 {
47     // An object that is reset and reused every time.
48
// The map: [class member name+' '+descriptor - class member info]
49
private final Map memberMap = new HashMap();
50
51
52     // Implementations for ClassVisitor.
53

54     public void visitAnyClass(Clazz clazz)
55     {
56         // Collect all non-private members in this class hierarchy.
57
clazz.hierarchyAccept(true, true, true, false,
58             new AllMethodVisitor(
59             new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
60             this)));
61
62         // Clean up for the next class hierarchy.
63
memberMap.clear();
64     }
65
66
67     // Implementations for MemberVisitor.
68

69     public void visitAnyMember(Clazz clazz, Member member)
70     {
71         // Get the class member's name and descriptor.
72
String JavaDoc name = member.getName(clazz);
73         String JavaDoc descriptor = member.getDescriptor(clazz);
74
75         // Special cases: <clinit> and <init> are always kept unchanged.
76
// We can ignore them here.
77
if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ||
78             name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
79         {
80             return;
81         }
82
83         // Get the last method in the chain.
84
Member thisLastMember = lastMember(member);
85
86         // See if we've already come across a method with the same name and
87
// descriptor.
88
String JavaDoc key = name + ' ' + descriptor;
89         Member otherMember = (Member)memberMap.get(key);
90
91         if (otherMember == null)
92         {
93             // Store the new class method in the map.
94
memberMap.put(key, thisLastMember);
95         }
96         else
97         {
98             // Get the last method in the other chain.
99
Member otherLastMember = lastMember(otherMember);
100
101             // Check if both link chains aren't already ending in the same element.
102
if (!thisLastMember.equals(otherLastMember))
103             {
104                 // Merge the two chains, with the library members last.
105
if (otherLastMember instanceof LibraryMember)
106                 {
107                     thisLastMember.setVisitorInfo(otherLastMember);
108                 }
109                 else
110                 {
111                     otherLastMember.setVisitorInfo(thisLastMember);
112                 }
113             }
114         }
115     }
116
117
118     // Small utility methods.
119

120     /**
121      * Finds the last class member in the linked list of related class members.
122      * @param member the given class member.
123      * @return the last class member in the linked list.
124      */

125     public static Member lastMember(Member member)
126     {
127         Member lastMember = member;
128         while (lastMember.getVisitorInfo() != null &&
129                lastMember.getVisitorInfo() instanceof Member)
130         {
131             lastMember = (Member)lastMember.getVisitorInfo();
132         }
133
134         return lastMember;
135     }
136
137
138     /**
139      * Finds the last visitor accepter in the linked list of visitors.
140      * @param visitorAccepter the given method.
141      * @return the last method in the linked list.
142      */

143     public static VisitorAccepter lastVisitorAccepter(VisitorAccepter visitorAccepter)
144     {
145         VisitorAccepter lastVisitorAccepter = visitorAccepter;
146         while (lastVisitorAccepter.getVisitorInfo() != null &&
147                lastVisitorAccepter.getVisitorInfo() instanceof VisitorAccepter)
148         {
149             lastVisitorAccepter = (VisitorAccepter)lastVisitorAccepter.getVisitorInfo();
150         }
151
152         return lastVisitorAccepter;
153     }
154 }
155
Popular Tags