001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.obfuscate;
022:
023: import proguard.classfile.*;
024: import proguard.classfile.attribute.*;
025: import proguard.classfile.attribute.annotation.*;
026: import proguard.classfile.attribute.annotation.visitor.*;
027: import proguard.classfile.attribute.preverification.*;
028: import proguard.classfile.attribute.visitor.*;
029: import proguard.classfile.constant.*;
030: import proguard.classfile.constant.visitor.ConstantVisitor;
031: import proguard.classfile.util.SimplifiedVisitor;
032: import proguard.classfile.visitor.*;
033:
034: /**
035: * This ClassVisitor marks all UTF-8 constant pool entries that are
036: * being used in the program classes it visits.
037: *
038: * @see Utf8Shrinker
039: *
040: * @author Eric Lafortune
041: */
042: public class Utf8UsageMarker extends SimplifiedVisitor implements
043: ClassVisitor, MemberVisitor, ConstantVisitor, AttributeVisitor,
044: InnerClassesInfoVisitor, LocalVariableInfoVisitor,
045: LocalVariableTypeInfoVisitor, AnnotationVisitor,
046: ElementValueVisitor {
047: // A visitor info flag to indicate the UTF-8 constant pool entry is being used.
048: private static final Object USED = new Object();
049:
050: // Implementations for ClassVisitor.
051:
052: public void visitProgramClass(ProgramClass programClass) {
053: // Mark the UTF-8 entries referenced by the other constant pool entries.
054: programClass.constantPoolEntriesAccept(this );
055:
056: // Mark the UTF-8 entries referenced by the fields and methods.
057: programClass.fieldsAccept(this );
058: programClass.methodsAccept(this );
059:
060: // Mark the UTF-8 entries referenced by the attributes.
061: programClass.attributesAccept(this );
062: }
063:
064: // Implementations for MemberVisitor.
065:
066: public void visitProgramMember(ProgramClass programClass,
067: ProgramMember programMember) {
068: // Mark the name and descriptor UTF-8 entries.
069: markCpUtf8Entry(programClass, programMember.u2nameIndex);
070: markCpUtf8Entry(programClass, programMember.u2descriptorIndex);
071:
072: // Mark the UTF-8 entries referenced by the attributes.
073: programMember.attributesAccept(programClass, this );
074: }
075:
076: // Implementations for ConstantVisitor.
077:
078: public void visitAnyConstant(Clazz clazz, Constant constant) {
079: }
080:
081: public void visitStringConstant(Clazz clazz,
082: StringConstant stringConstant) {
083: markCpUtf8Entry(clazz, stringConstant.u2stringIndex);
084: }
085:
086: public void visitClassConstant(Clazz clazz,
087: ClassConstant classConstant) {
088: markCpUtf8Entry(clazz, classConstant.u2nameIndex);
089: }
090:
091: public void visitNameAndTypeConstant(Clazz clazz,
092: NameAndTypeConstant nameAndTypeConstant) {
093: markCpUtf8Entry(clazz, nameAndTypeConstant.u2nameIndex);
094: markCpUtf8Entry(clazz, nameAndTypeConstant.u2descriptorIndex);
095: }
096:
097: // Implementations for AttributeVisitor.
098:
099: public void visitUnknownAttribute(Clazz clazz,
100: UnknownAttribute unknownAttribute) {
101: // This is the best we can do for unknown attributes.
102: markCpUtf8Entry(clazz, unknownAttribute.u2attributeNameIndex);
103: }
104:
105: public void visitSourceFileAttribute(Clazz clazz,
106: SourceFileAttribute sourceFileAttribute) {
107: markCpUtf8Entry(clazz, sourceFileAttribute.u2attributeNameIndex);
108:
109: markCpUtf8Entry(clazz, sourceFileAttribute.u2sourceFileIndex);
110: }
111:
112: public void visitSourceDirAttribute(Clazz clazz,
113: SourceDirAttribute sourceDirAttribute) {
114: markCpUtf8Entry(clazz, sourceDirAttribute.u2attributeNameIndex);
115:
116: markCpUtf8Entry(clazz, sourceDirAttribute.u2sourceDirIndex);
117: }
118:
119: public void visitInnerClassesAttribute(Clazz clazz,
120: InnerClassesAttribute innerClassesAttribute) {
121: markCpUtf8Entry(clazz,
122: innerClassesAttribute.u2attributeNameIndex);
123:
124: // Mark the UTF-8 entries referenced by the inner classes.
125: innerClassesAttribute.innerClassEntriesAccept(clazz, this );
126: }
127:
128: public void visitEnclosingMethodAttribute(Clazz clazz,
129: EnclosingMethodAttribute enclosingMethodAttribute) {
130: markCpUtf8Entry(clazz,
131: enclosingMethodAttribute.u2attributeNameIndex);
132:
133: // These entries have already been marked in the constant pool.
134: //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2classIndex);
135: //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2nameAndTypeIndex);
136: }
137:
138: public void visitDeprecatedAttribute(Clazz clazz,
139: DeprecatedAttribute deprecatedAttribute) {
140: markCpUtf8Entry(clazz, deprecatedAttribute.u2attributeNameIndex);
141: }
142:
143: public void visitSyntheticAttribute(Clazz clazz,
144: SyntheticAttribute syntheticAttribute) {
145: markCpUtf8Entry(clazz, syntheticAttribute.u2attributeNameIndex);
146: }
147:
148: public void visitSignatureAttribute(Clazz clazz,
149: SignatureAttribute signatureAttribute) {
150: markCpUtf8Entry(clazz, signatureAttribute.u2attributeNameIndex);
151:
152: markCpUtf8Entry(clazz, signatureAttribute.u2signatureIndex);
153: }
154:
155: public void visitConstantValueAttribute(Clazz clazz, Field field,
156: ConstantValueAttribute constantValueAttribute) {
157: markCpUtf8Entry(clazz,
158: constantValueAttribute.u2attributeNameIndex);
159: }
160:
161: public void visitExceptionsAttribute(Clazz clazz, Method method,
162: ExceptionsAttribute exceptionsAttribute) {
163: markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex);
164: }
165:
166: public void visitCodeAttribute(Clazz clazz, Method method,
167: CodeAttribute codeAttribute) {
168: markCpUtf8Entry(clazz, codeAttribute.u2attributeNameIndex);
169:
170: // Mark the UTF-8 entries referenced by the attributes.
171: codeAttribute.attributesAccept(clazz, method, this );
172: }
173:
174: public void visitStackMapAttribute(Clazz clazz, Method method,
175: CodeAttribute codeAttribute,
176: StackMapAttribute stackMapAttribute) {
177: markCpUtf8Entry(clazz, stackMapAttribute.u2attributeNameIndex);
178: }
179:
180: public void visitStackMapTableAttribute(Clazz clazz, Method method,
181: CodeAttribute codeAttribute,
182: StackMapTableAttribute stackMapTableAttribute) {
183: markCpUtf8Entry(clazz,
184: stackMapTableAttribute.u2attributeNameIndex);
185: }
186:
187: public void visitLineNumberTableAttribute(Clazz clazz,
188: Method method, CodeAttribute codeAttribute,
189: LineNumberTableAttribute lineNumberTableAttribute) {
190: markCpUtf8Entry(clazz,
191: lineNumberTableAttribute.u2attributeNameIndex);
192: }
193:
194: public void visitLocalVariableTableAttribute(Clazz clazz,
195: Method method, CodeAttribute codeAttribute,
196: LocalVariableTableAttribute localVariableTableAttribute) {
197: markCpUtf8Entry(clazz,
198: localVariableTableAttribute.u2attributeNameIndex);
199:
200: // Mark the UTF-8 entries referenced by the local variables.
201: localVariableTableAttribute.localVariablesAccept(clazz, method,
202: codeAttribute, this );
203: }
204:
205: public void visitLocalVariableTypeTableAttribute(
206: Clazz clazz,
207: Method method,
208: CodeAttribute codeAttribute,
209: LocalVariableTypeTableAttribute localVariableTypeTableAttribute) {
210: markCpUtf8Entry(clazz,
211: localVariableTypeTableAttribute.u2attributeNameIndex);
212:
213: // Mark the UTF-8 entries referenced by the local variable types.
214: localVariableTypeTableAttribute.localVariablesAccept(clazz,
215: method, codeAttribute, this );
216: }
217:
218: public void visitAnyAnnotationsAttribute(Clazz clazz,
219: AnnotationsAttribute annotationsAttribute) {
220: markCpUtf8Entry(clazz,
221: annotationsAttribute.u2attributeNameIndex);
222:
223: // Mark the UTF-8 entries referenced by the annotations.
224: annotationsAttribute.annotationsAccept(clazz, this );
225: }
226:
227: public void visitAnyParameterAnnotationsAttribute(Clazz clazz,
228: Method method,
229: ParameterAnnotationsAttribute parameterAnnotationsAttribute) {
230: markCpUtf8Entry(clazz,
231: parameterAnnotationsAttribute.u2attributeNameIndex);
232:
233: // Mark the UTF-8 entries referenced by the annotations.
234: parameterAnnotationsAttribute.annotationsAccept(clazz, method,
235: this );
236: }
237:
238: public void visitAnnotationDefaultAttribute(Clazz clazz,
239: Method method,
240: AnnotationDefaultAttribute annotationDefaultAttribute) {
241: markCpUtf8Entry(clazz,
242: annotationDefaultAttribute.u2attributeNameIndex);
243:
244: // Mark the UTF-8 entries referenced by the element value.
245: annotationDefaultAttribute.defaultValueAccept(clazz, this );
246: }
247:
248: // Implementations for InnerClassesInfoVisitor.
249:
250: public void visitInnerClassesInfo(Clazz clazz,
251: InnerClassesInfo innerClassesInfo) {
252: if (innerClassesInfo.u2innerNameIndex != 0) {
253: markCpUtf8Entry(clazz, innerClassesInfo.u2innerNameIndex);
254: }
255: }
256:
257: // Implementations for LocalVariableInfoVisitor.
258:
259: public void visitLocalVariableInfo(Clazz clazz, Method method,
260: CodeAttribute codeAttribute,
261: LocalVariableInfo localVariableInfo) {
262: markCpUtf8Entry(clazz, localVariableInfo.u2nameIndex);
263: markCpUtf8Entry(clazz, localVariableInfo.u2descriptorIndex);
264: }
265:
266: // Implementations for LocalVariableTypeInfoVisitor.
267:
268: public void visitLocalVariableTypeInfo(Clazz clazz, Method method,
269: CodeAttribute codeAttribute,
270: LocalVariableTypeInfo localVariableTypeInfo) {
271: markCpUtf8Entry(clazz, localVariableTypeInfo.u2nameIndex);
272: markCpUtf8Entry(clazz, localVariableTypeInfo.u2signatureIndex);
273: }
274:
275: // Implementations for AnnotationVisitor.
276:
277: public void visitAnnotation(Clazz clazz, Annotation annotation) {
278: markCpUtf8Entry(clazz, annotation.u2typeIndex);
279:
280: // Mark the UTF-8 entries referenced by the element values.
281: annotation.elementValuesAccept(clazz, this );
282: }
283:
284: // Implementations for ElementValueVisitor.
285:
286: public void visitConstantElementValue(Clazz clazz,
287: Annotation annotation,
288: ConstantElementValue constantElementValue) {
289: if (constantElementValue.u2elementNameIndex != 0) {
290: markCpUtf8Entry(clazz,
291: constantElementValue.u2elementNameIndex);
292: }
293:
294: // Only the string constant element value refers to a UTF-8 entry.
295: if (constantElementValue.u1tag == ClassConstants.ELEMENT_VALUE_STRING_CONSTANT) {
296: markCpUtf8Entry(clazz,
297: constantElementValue.u2constantValueIndex);
298: }
299: }
300:
301: public void visitEnumConstantElementValue(Clazz clazz,
302: Annotation annotation,
303: EnumConstantElementValue enumConstantElementValue) {
304: if (enumConstantElementValue.u2elementNameIndex != 0) {
305: markCpUtf8Entry(clazz,
306: enumConstantElementValue.u2elementNameIndex);
307: }
308:
309: markCpUtf8Entry(clazz, enumConstantElementValue.u2typeNameIndex);
310: markCpUtf8Entry(clazz,
311: enumConstantElementValue.u2constantNameIndex);
312: }
313:
314: public void visitClassElementValue(Clazz clazz,
315: Annotation annotation, ClassElementValue classElementValue) {
316: if (classElementValue.u2elementNameIndex != 0) {
317: markCpUtf8Entry(clazz, classElementValue.u2elementNameIndex);
318: }
319:
320: markCpUtf8Entry(clazz, classElementValue.u2classInfoIndex);
321: }
322:
323: public void visitAnnotationElementValue(Clazz clazz,
324: Annotation annotation,
325: AnnotationElementValue annotationElementValue) {
326: if (annotationElementValue.u2elementNameIndex != 0) {
327: markCpUtf8Entry(clazz,
328: annotationElementValue.u2elementNameIndex);
329: }
330:
331: // Mark the UTF-8 entries referenced by the annotation.
332: annotationElementValue.annotationAccept(clazz, this );
333: }
334:
335: public void visitArrayElementValue(Clazz clazz,
336: Annotation annotation, ArrayElementValue arrayElementValue) {
337: if (arrayElementValue.u2elementNameIndex != 0) {
338: markCpUtf8Entry(clazz, arrayElementValue.u2elementNameIndex);
339: }
340:
341: // Mark the UTF-8 entries referenced by the element values.
342: arrayElementValue.elementValuesAccept(clazz, annotation, this );
343: }
344:
345: // Small utility methods.
346:
347: /**
348: * Marks the given UTF-8 constant pool entry of the given class.
349: */
350: private void markCpUtf8Entry(Clazz clazz, int index) {
351: markAsUsed((Utf8Constant) ((ProgramClass) clazz)
352: .getConstant(index));
353: }
354:
355: /**
356: * Marks the given VisitorAccepter as being used.
357: * In this context, the VisitorAccepter will be a Utf8Constant object.
358: */
359: private static void markAsUsed(VisitorAccepter visitorAccepter) {
360: visitorAccepter.setVisitorInfo(USED);
361: }
362:
363: /**
364: * Returns whether the given VisitorAccepter has been marked as being used.
365: * In this context, the VisitorAccepter will be a Utf8Constant object.
366: */
367: static boolean isUsed(VisitorAccepter visitorAccepter) {
368: return visitorAccepter.getVisitorInfo() == USED;
369: }
370: }
|