1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 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.classfile.util;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.Attribute;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.*;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.ConstantVisitor;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.ClassVisitor;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This ClassVisitor shares strings in the class files that it visits.
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class StringSharer
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   ClassVisitor,
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             ConstantVisitor,
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             AttributeVisitor
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // A fields acting as an argument for the visitor methods.
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String name;
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String type;
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ClassVisitor.
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramClass(ProgramClass programClass)
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace name strings in the constant pool by shared strings.
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClass.constantPoolEntriesAccept(this);
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace attribute name strings in the constant pool by internalized
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // strings.
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClass.attributesAccept(this);
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitLibraryClass(LibraryClass libraryClass)
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace the super class name string by the shared name string.
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Clazz superClass = libraryClass.superClass;
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (superClass != null)
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            libraryClass.superClassName = superClass.getName();
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
67b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
68b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Replace the interface name strings by the shared name strings.
69b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (libraryClass.interfaceNames != null)
70b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
71b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            String[] interfaceNames   = libraryClass.interfaceNames;
72b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            Clazz[]  interfaceClasses = new Clazz[interfaceNames.length];
73b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
74b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            for (int index = 0; index < interfaceNames.length; index++)
75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            {
76b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Keep a reference to the interface class.
77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                Clazz interfaceClass = interfaceClasses[index];
78b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                if (interfaceClass != null)
79b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                {
80b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    interfaceNames[index] = interfaceClass.getName();
81b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                }
82b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            }
83b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ConstantVisitor.
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyConstant(Clazz clazz, Constant constant) {}
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
93b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Member referencedMember = stringConstant.referencedMember;
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (referencedMember != null)
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Clazz referencedClass = stringConstant.referencedClass;
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Put the actual class member's name in the class pool.
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            name = referencedMember.getName(referencedClass);
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            clazz.constantPoolEntryAccept(stringConstant.u2stringIndex, this);
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Member referencedMember = refConstant.referencedMember;
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (referencedMember != null)
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Clazz referencedClass = refConstant.referencedClass;
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Put the actual class member's name and type strings in the class
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // pool.
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            name = referencedMember.getName(referencedClass);
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            type = referencedMember.getDescriptor(referencedClass);
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            clazz.constantPoolEntryAccept(refConstant.u2nameAndTypeIndex, this);
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (name != null)
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Put the actual class member's name and type strings in the class
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // pool.
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            clazz.constantPoolEntryAccept(nameAndTypeConstant.u2nameIndex, this);
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            name = type;
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            clazz.constantPoolEntryAccept(nameAndTypeConstant.u2descriptorIndex, this);
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Clazz referencedClass = classConstant.referencedClass;
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (referencedClass != null)
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Put the actual class's name string in the class pool.
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            name = referencedClass.getName();
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this);
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Do we have a new string to put into this constant?
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (name != null)
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Replace the string, if it's actually the same.
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (name.equals(utf8Constant.getString()))
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                utf8Constant.setString(name);
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            name = null;
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for AttributeVisitor.
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyAttribute(Clazz clazz, Attribute attribute)
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Put the internalized attribute's name string in the class pool.
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        name = attribute.getAttributeName(clazz).intern();
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        clazz.constantPoolEntryAccept(attribute.u2attributeNameIndex, this);
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
173