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.classfile.io;
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.preverification.visitor.*;
029: import proguard.classfile.attribute.visitor.*;
030: import proguard.classfile.constant.*;
031: import proguard.classfile.constant.visitor.ConstantVisitor;
032: import proguard.classfile.util.*;
033: import proguard.classfile.visitor.*;
034:
035: import java.io.DataInput;
036:
037: /**
038: * This ClassVisitor fills out the ProgramClass objects that it visits with data
039: * from the given DataInput object.
040: *
041: * @author Eric Lafortune
042: */
043: public class ProgramClassReader extends SimplifiedVisitor implements
044: ClassVisitor, MemberVisitor, ConstantVisitor, AttributeVisitor,
045: InnerClassesInfoVisitor, ExceptionInfoVisitor,
046: StackMapFrameVisitor, VerificationTypeVisitor,
047: LineNumberInfoVisitor, LocalVariableInfoVisitor,
048: LocalVariableTypeInfoVisitor, AnnotationVisitor,
049: ElementValueVisitor {
050: private final RuntimeDataInput dataInput;
051:
052: /**
053: * Creates a new ProgramClassReader for reading from the given DataInput.
054: */
055: public ProgramClassReader(DataInput dataInput) {
056: this .dataInput = new RuntimeDataInput(dataInput);
057: }
058:
059: // Implementations for ClassVisitor.
060:
061: public void visitProgramClass(ProgramClass programClass) {
062: // Read and check the magic number.
063: programClass.u4magic = dataInput.readInt();
064:
065: ClassUtil.checkMagicNumber(programClass.u4magic);
066:
067: // Read and check the version numbers.
068: int u2minorVersion = dataInput.readUnsignedShort();
069: int u2majorVersion = dataInput.readUnsignedShort();
070:
071: programClass.u4version = ClassUtil.internalClassVersion(
072: u2majorVersion, u2minorVersion);
073:
074: ClassUtil.checkVersionNumbers(programClass.u4version);
075:
076: // Read the constant pool. Note that the first entry is not used.
077: programClass.u2constantPoolCount = dataInput
078: .readUnsignedShort();
079:
080: programClass.constantPool = new Constant[programClass.u2constantPoolCount];
081: for (int index = 1; index < programClass.u2constantPoolCount; index++) {
082: Constant constant = createConstant();
083: constant.accept(programClass, this );
084: programClass.constantPool[index] = constant;
085:
086: // Long constants and double constants take up two entries in the
087: // constant pool.
088: int tag = constant.getTag();
089: if (tag == ClassConstants.CONSTANT_Long
090: || tag == ClassConstants.CONSTANT_Double) {
091: programClass.constantPool[++index] = null;
092: }
093: }
094:
095: // Read the general class information.
096: programClass.u2accessFlags = dataInput.readUnsignedShort();
097: programClass.u2this Class = dataInput.readUnsignedShort();
098: programClass.u2super Class = dataInput.readUnsignedShort();
099:
100: // Read the interfaces.
101: programClass.u2interfacesCount = dataInput.readUnsignedShort();
102:
103: programClass.u2interfaces = new int[programClass.u2interfacesCount];
104: for (int index = 0; index < programClass.u2interfacesCount; index++) {
105: programClass.u2interfaces[index] = dataInput
106: .readUnsignedShort();
107: }
108:
109: // Read the fields.
110: programClass.u2fieldsCount = dataInput.readUnsignedShort();
111:
112: programClass.fields = new ProgramField[programClass.u2fieldsCount];
113: for (int index = 0; index < programClass.u2fieldsCount; index++) {
114: ProgramField programField = new ProgramField();
115: this .visitProgramField(programClass, programField);
116: programClass.fields[index] = programField;
117: }
118:
119: // Read the methods.
120: programClass.u2methodsCount = dataInput.readUnsignedShort();
121:
122: programClass.methods = new ProgramMethod[programClass.u2methodsCount];
123: for (int index = 0; index < programClass.u2methodsCount; index++) {
124: ProgramMethod programMethod = new ProgramMethod();
125: this .visitProgramMethod(programClass, programMethod);
126: programClass.methods[index] = programMethod;
127: }
128:
129: // Read the class attributes.
130: programClass.u2attributesCount = dataInput.readUnsignedShort();
131:
132: programClass.attributes = new Attribute[programClass.u2attributesCount];
133: for (int index = 0; index < programClass.u2attributesCount; index++) {
134: Attribute attribute = createAttribute(programClass);
135: attribute.accept(programClass, this );
136: programClass.attributes[index] = attribute;
137: }
138: }
139:
140: public void visitLibraryClass(LibraryClass libraryClass) {
141: }
142:
143: // Implementations for MemberVisitor.
144:
145: public void visitProgramField(ProgramClass programClass,
146: ProgramField programField) {
147: // Read the general field information.
148: programField.u2accessFlags = dataInput.readUnsignedShort();
149: programField.u2nameIndex = dataInput.readUnsignedShort();
150: programField.u2descriptorIndex = dataInput.readUnsignedShort();
151:
152: // Read the field attributes.
153: programField.u2attributesCount = dataInput.readUnsignedShort();
154:
155: programField.attributes = new Attribute[programField.u2attributesCount];
156: for (int index = 0; index < programField.u2attributesCount; index++) {
157: Attribute attribute = createAttribute(programClass);
158: attribute.accept(programClass, programField, this );
159: programField.attributes[index] = attribute;
160: }
161: }
162:
163: public void visitProgramMethod(ProgramClass programClass,
164: ProgramMethod programMethod) {
165: // Read the general method information.
166: programMethod.u2accessFlags = dataInput.readUnsignedShort();
167: programMethod.u2nameIndex = dataInput.readUnsignedShort();
168: programMethod.u2descriptorIndex = dataInput.readUnsignedShort();
169:
170: // Read the method attributes.
171: programMethod.u2attributesCount = dataInput.readUnsignedShort();
172:
173: programMethod.attributes = new Attribute[programMethod.u2attributesCount];
174: for (int index = 0; index < programMethod.u2attributesCount; index++) {
175: Attribute attribute = createAttribute(programClass);
176: attribute.accept(programClass, programMethod, this );
177: programMethod.attributes[index] = attribute;
178: }
179: }
180:
181: public void visitLibraryMember(LibraryClass libraryClass,
182: LibraryMember libraryMember) {
183: }
184:
185: // Implementations for ConstantVisitor.
186:
187: public void visitIntegerConstant(Clazz clazz,
188: IntegerConstant integerConstant) {
189: integerConstant.u4value = dataInput.readInt();
190: }
191:
192: public void visitLongConstant(Clazz clazz, LongConstant longConstant) {
193: longConstant.u8value = dataInput.readLong();
194: }
195:
196: public void visitFloatConstant(Clazz clazz,
197: FloatConstant floatConstant) {
198: floatConstant.f4value = dataInput.readFloat();
199: }
200:
201: public void visitDoubleConstant(Clazz clazz,
202: DoubleConstant doubleConstant) {
203: doubleConstant.f8value = dataInput.readDouble();
204: }
205:
206: public void visitStringConstant(Clazz clazz,
207: StringConstant stringConstant) {
208: stringConstant.u2stringIndex = dataInput.readUnsignedShort();
209: }
210:
211: public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) {
212: int u2length = dataInput.readUnsignedShort();
213:
214: // Read the UTF-8 bytes.
215: byte[] bytes = new byte[u2length];
216: dataInput.readFully(bytes);
217: utf8Constant.setBytes(bytes);
218: }
219:
220: public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) {
221: refConstant.u2classIndex = dataInput.readUnsignedShort();
222: refConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort();
223: }
224:
225: public void visitClassConstant(Clazz clazz,
226: ClassConstant classConstant) {
227: classConstant.u2nameIndex = dataInput.readUnsignedShort();
228: }
229:
230: public void visitNameAndTypeConstant(Clazz clazz,
231: NameAndTypeConstant nameAndTypeConstant) {
232: nameAndTypeConstant.u2nameIndex = dataInput.readUnsignedShort();
233: nameAndTypeConstant.u2descriptorIndex = dataInput
234: .readUnsignedShort();
235: }
236:
237: // Implementations for AttributeVisitor.
238:
239: public void visitUnknownAttribute(Clazz clazz,
240: UnknownAttribute unknownAttribute) {
241: // Read the unknown information.
242: byte[] info = new byte[unknownAttribute.u4attributeLength];
243: dataInput.readFully(info);
244: unknownAttribute.info = info;
245: }
246:
247: public void visitSourceFileAttribute(Clazz clazz,
248: SourceFileAttribute sourceFileAttribute) {
249: sourceFileAttribute.u2sourceFileIndex = dataInput
250: .readUnsignedShort();
251: }
252:
253: public void visitSourceDirAttribute(Clazz clazz,
254: SourceDirAttribute sourceDirAttribute) {
255: sourceDirAttribute.u2sourceDirIndex = dataInput
256: .readUnsignedShort();
257: }
258:
259: public void visitInnerClassesAttribute(Clazz clazz,
260: InnerClassesAttribute innerClassesAttribute) {
261: // Read the inner classes.
262: innerClassesAttribute.u2classesCount = dataInput
263: .readUnsignedShort();
264:
265: innerClassesAttribute.classes = new InnerClassesInfo[innerClassesAttribute.u2classesCount];
266: for (int index = 0; index < innerClassesAttribute.u2classesCount; index++) {
267: InnerClassesInfo innerClassesInfo = new InnerClassesInfo();
268: this .visitInnerClassesInfo(clazz, innerClassesInfo);
269: innerClassesAttribute.classes[index] = innerClassesInfo;
270: }
271: }
272:
273: public void visitEnclosingMethodAttribute(Clazz clazz,
274: EnclosingMethodAttribute enclosingMethodAttribute) {
275: enclosingMethodAttribute.u2classIndex = dataInput
276: .readUnsignedShort();
277: enclosingMethodAttribute.u2nameAndTypeIndex = dataInput
278: .readUnsignedShort();
279: }
280:
281: public void visitDeprecatedAttribute(Clazz clazz,
282: DeprecatedAttribute deprecatedAttribute) {
283: // This attribute does not contain any additional information.
284: }
285:
286: public void visitSyntheticAttribute(Clazz clazz,
287: SyntheticAttribute syntheticAttribute) {
288: // This attribute does not contain any additional information.
289: }
290:
291: public void visitSignatureAttribute(Clazz clazz,
292: SignatureAttribute signatureAttribute) {
293: signatureAttribute.u2signatureIndex = dataInput
294: .readUnsignedShort();
295: }
296:
297: public void visitConstantValueAttribute(Clazz clazz, Field field,
298: ConstantValueAttribute constantValueAttribute) {
299: constantValueAttribute.u2constantValueIndex = dataInput
300: .readUnsignedShort();
301: }
302:
303: public void visitExceptionsAttribute(Clazz clazz, Method method,
304: ExceptionsAttribute exceptionsAttribute) {
305: // Read the exceptions.
306: exceptionsAttribute.u2exceptionIndexTableLength = dataInput
307: .readUnsignedShort();
308:
309: exceptionsAttribute.u2exceptionIndexTable = new int[exceptionsAttribute.u2exceptionIndexTableLength];
310: for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) {
311: exceptionsAttribute.u2exceptionIndexTable[index] = dataInput
312: .readUnsignedShort();
313: }
314: }
315:
316: public void visitCodeAttribute(Clazz clazz, Method method,
317: CodeAttribute codeAttribute) {
318: // Read the stack size and local variable frame size.
319: codeAttribute.u2maxStack = dataInput.readUnsignedShort();
320: codeAttribute.u2maxLocals = dataInput.readUnsignedShort();
321:
322: // Read the byte code.
323: codeAttribute.u4codeLength = dataInput.readInt();
324:
325: byte[] code = new byte[codeAttribute.u4codeLength];
326: dataInput.readFully(code);
327: codeAttribute.code = code;
328:
329: // Read the exceptions.
330: codeAttribute.u2exceptionTableLength = dataInput
331: .readUnsignedShort();
332:
333: codeAttribute.exceptionTable = new ExceptionInfo[codeAttribute.u2exceptionTableLength];
334: for (int index = 0; index < codeAttribute.u2exceptionTableLength; index++) {
335: ExceptionInfo exceptionInfo = new ExceptionInfo();
336: this .visitExceptionInfo(clazz, method, codeAttribute,
337: exceptionInfo);
338: codeAttribute.exceptionTable[index] = exceptionInfo;
339: }
340:
341: // Read the code attributes.
342: codeAttribute.u2attributesCount = dataInput.readUnsignedShort();
343:
344: codeAttribute.attributes = new Attribute[codeAttribute.u2attributesCount];
345: for (int index = 0; index < codeAttribute.u2attributesCount; index++) {
346: Attribute attribute = createAttribute(clazz);
347: attribute.accept(clazz, method, codeAttribute, this );
348: codeAttribute.attributes[index] = attribute;
349: }
350: }
351:
352: public void visitStackMapAttribute(Clazz clazz, Method method,
353: CodeAttribute codeAttribute,
354: StackMapAttribute stackMapAttribute) {
355: // Read the stack map frames (only full frames, without tag).
356: stackMapAttribute.u2stackMapFramesCount = dataInput
357: .readUnsignedShort();
358:
359: stackMapAttribute.stackMapFrames = new FullFrame[stackMapAttribute.u2stackMapFramesCount];
360: for (int index = 0; index < stackMapAttribute.u2stackMapFramesCount; index++) {
361: FullFrame stackMapFrame = new FullFrame();
362: this .visitFullFrame(clazz, method, codeAttribute, index,
363: stackMapFrame);
364: stackMapAttribute.stackMapFrames[index] = stackMapFrame;
365: }
366: }
367:
368: public void visitStackMapTableAttribute(Clazz clazz, Method method,
369: CodeAttribute codeAttribute,
370: StackMapTableAttribute stackMapTableAttribute) {
371: // Read the stack map frames.
372: stackMapTableAttribute.u2stackMapFramesCount = dataInput
373: .readUnsignedShort();
374:
375: stackMapTableAttribute.stackMapFrames = new StackMapFrame[stackMapTableAttribute.u2stackMapFramesCount];
376: for (int index = 0; index < stackMapTableAttribute.u2stackMapFramesCount; index++) {
377: StackMapFrame stackMapFrame = createStackMapFrame();
378: stackMapFrame.accept(clazz, method, codeAttribute, 0, this );
379: stackMapTableAttribute.stackMapFrames[index] = stackMapFrame;
380: }
381: }
382:
383: public void visitLineNumberTableAttribute(Clazz clazz,
384: Method method, CodeAttribute codeAttribute,
385: LineNumberTableAttribute lineNumberTableAttribute) {
386: // Read the line numbers.
387: lineNumberTableAttribute.u2lineNumberTableLength = dataInput
388: .readUnsignedShort();
389:
390: lineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength];
391: for (int index = 0; index < lineNumberTableAttribute.u2lineNumberTableLength; index++) {
392: LineNumberInfo lineNumberInfo = new LineNumberInfo();
393: this .visitLineNumberInfo(clazz, method, codeAttribute,
394: lineNumberInfo);
395: lineNumberTableAttribute.lineNumberTable[index] = lineNumberInfo;
396: }
397: }
398:
399: public void visitLocalVariableTableAttribute(Clazz clazz,
400: Method method, CodeAttribute codeAttribute,
401: LocalVariableTableAttribute localVariableTableAttribute) {
402: // Read the local variables.
403: localVariableTableAttribute.u2localVariableTableLength = dataInput
404: .readUnsignedShort();
405:
406: localVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength];
407: for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++) {
408: LocalVariableInfo localVariableInfo = new LocalVariableInfo();
409: this .visitLocalVariableInfo(clazz, method, codeAttribute,
410: localVariableInfo);
411: localVariableTableAttribute.localVariableTable[index] = localVariableInfo;
412: }
413: }
414:
415: public void visitLocalVariableTypeTableAttribute(
416: Clazz clazz,
417: Method method,
418: CodeAttribute codeAttribute,
419: LocalVariableTypeTableAttribute localVariableTypeTableAttribute) {
420: // Read the local variable types.
421: localVariableTypeTableAttribute.u2localVariableTypeTableLength = dataInput
422: .readUnsignedShort();
423:
424: localVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength];
425: for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++) {
426: LocalVariableTypeInfo localVariableTypeInfo = new LocalVariableTypeInfo();
427: this .visitLocalVariableTypeInfo(clazz, method,
428: codeAttribute, localVariableTypeInfo);
429: localVariableTypeTableAttribute.localVariableTypeTable[index] = localVariableTypeInfo;
430: }
431: }
432:
433: public void visitAnyAnnotationsAttribute(Clazz clazz,
434: AnnotationsAttribute annotationsAttribute) {
435: // Read the annotations.
436: annotationsAttribute.u2annotationsCount = dataInput
437: .readUnsignedShort();
438:
439: annotationsAttribute.annotations = new Annotation[annotationsAttribute.u2annotationsCount];
440: for (int index = 0; index < annotationsAttribute.u2annotationsCount; index++) {
441: Annotation annotation = new Annotation();
442: this .visitAnnotation(clazz, annotation);
443: annotationsAttribute.annotations[index] = annotation;
444: }
445: }
446:
447: public void visitAnyParameterAnnotationsAttribute(Clazz clazz,
448: Method method,
449: ParameterAnnotationsAttribute parameterAnnotationsAttribute) {
450: // Read the parameter annotations.
451: parameterAnnotationsAttribute.u2parametersCount = dataInput
452: .readUnsignedByte();
453: parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u2parametersCount];
454: parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u2parametersCount][];
455:
456: for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) {
457: // Read the parameter annotations of the given parameter.
458: int u2annotationsCount = dataInput.readUnsignedShort();
459:
460: Annotation[] annotations = new Annotation[u2annotationsCount];
461:
462: for (int index = 0; index < u2annotationsCount; index++) {
463: Annotation annotation = new Annotation();
464: this .visitAnnotation(clazz, annotation);
465: annotations[index] = annotation;
466: }
467:
468: parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] = u2annotationsCount;
469: parameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = annotations;
470: }
471: }
472:
473: public void visitAnnotationDefaultAttribute(Clazz clazz,
474: Method method,
475: AnnotationDefaultAttribute annotationDefaultAttribute) {
476: // Read the default element value.
477: ElementValue elementValue = createElementValue();
478: elementValue.accept(clazz, null, this );
479: annotationDefaultAttribute.defaultValue = elementValue;
480: }
481:
482: // Implementations for InnerClassesInfoVisitor.
483:
484: public void visitInnerClassesInfo(Clazz clazz,
485: InnerClassesInfo innerClassesInfo) {
486: innerClassesInfo.u2innerClassIndex = dataInput
487: .readUnsignedShort();
488: innerClassesInfo.u2outerClassIndex = dataInput
489: .readUnsignedShort();
490: innerClassesInfo.u2innerNameIndex = dataInput
491: .readUnsignedShort();
492: innerClassesInfo.u2innerClassAccessFlags = dataInput
493: .readUnsignedShort();
494: }
495:
496: // Implementations for ExceptionInfoVisitor.
497:
498: public void visitExceptionInfo(Clazz clazz, Method method,
499: CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) {
500: exceptionInfo.u2startPC = dataInput.readUnsignedShort();
501: exceptionInfo.u2endPC = dataInput.readUnsignedShort();
502: exceptionInfo.u2handlerPC = dataInput.readUnsignedShort();
503: exceptionInfo.u2catchType = dataInput.readUnsignedShort();
504: }
505:
506: // Implementations for StackMapFrameVisitor.
507:
508: public void visitSameZeroFrame(Clazz clazz, Method method,
509: CodeAttribute codeAttribute, int offset,
510: SameZeroFrame sameZeroFrame) {
511: if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) {
512: sameZeroFrame.u2offsetDelta = dataInput.readUnsignedShort();
513: }
514: }
515:
516: public void visitSameOneFrame(Clazz clazz, Method method,
517: CodeAttribute codeAttribute, int offset,
518: SameOneFrame sameOneFrame) {
519: if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) {
520: sameOneFrame.u2offsetDelta = dataInput.readUnsignedShort();
521: }
522:
523: // Read the verification type of the stack entry.
524: VerificationType verificationType = createVerificationType();
525: verificationType.accept(clazz, method, codeAttribute, offset,
526: this );
527: sameOneFrame.stackItem = verificationType;
528: }
529:
530: public void visitLessZeroFrame(Clazz clazz, Method method,
531: CodeAttribute codeAttribute, int offset,
532: LessZeroFrame lessZeroFrame) {
533: lessZeroFrame.u2offsetDelta = dataInput.readUnsignedShort();
534: }
535:
536: public void visitMoreZeroFrame(Clazz clazz, Method method,
537: CodeAttribute codeAttribute, int offset,
538: MoreZeroFrame moreZeroFrame) {
539: moreZeroFrame.u2offsetDelta = dataInput.readUnsignedShort();
540:
541: // Read the verification types of the additional local variables.
542: moreZeroFrame.additionalVariables = new VerificationType[moreZeroFrame.additionalVariablesCount];
543: for (int index = 0; index < moreZeroFrame.additionalVariablesCount; index++) {
544: VerificationType verificationType = createVerificationType();
545: verificationType.accept(clazz, method, codeAttribute,
546: offset, this );
547: moreZeroFrame.additionalVariables[index] = verificationType;
548: }
549: }
550:
551: public void visitFullFrame(Clazz clazz, Method method,
552: CodeAttribute codeAttribute, int offset, FullFrame fullFrame) {
553: fullFrame.u2offsetDelta = dataInput.readUnsignedShort();
554:
555: // Read the verification types of the local variables.
556: fullFrame.variablesCount = dataInput.readUnsignedShort();
557: fullFrame.variables = new VerificationType[fullFrame.variablesCount];
558: for (int index = 0; index < fullFrame.variablesCount; index++) {
559: VerificationType verificationType = createVerificationType();
560: verificationType.variablesAccept(clazz, method,
561: codeAttribute, offset, index, this );
562: fullFrame.variables[index] = verificationType;
563: }
564:
565: // Read the verification types of the stack entries.
566: fullFrame.stackCount = dataInput.readUnsignedShort();
567: fullFrame.stack = new VerificationType[fullFrame.stackCount];
568: for (int index = 0; index < fullFrame.stackCount; index++) {
569: VerificationType verificationType = createVerificationType();
570: verificationType.stackAccept(clazz, method, codeAttribute,
571: offset, index, this );
572: fullFrame.stack[index] = verificationType;
573: }
574: }
575:
576: // Implementations for VerificationTypeVisitor.
577:
578: public void visitAnyVerificationType(Clazz clazz, Method method,
579: CodeAttribute codeAttribute, int offset,
580: VerificationType verificationType) {
581: // Most verification types don't contain any additional information.
582: }
583:
584: public void visitObjectType(Clazz clazz, Method method,
585: CodeAttribute codeAttribute, int offset,
586: ObjectType objectType) {
587: objectType.u2classIndex = dataInput.readUnsignedShort();
588: }
589:
590: public void visitUninitializedType(Clazz clazz, Method method,
591: CodeAttribute codeAttribute, int offset,
592: UninitializedType uninitializedType) {
593: uninitializedType.u2newInstructionOffset = dataInput
594: .readUnsignedShort();
595: }
596:
597: // Implementations for LineNumberInfoVisitor.
598:
599: public void visitLineNumberInfo(Clazz clazz, Method method,
600: CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) {
601: lineNumberInfo.u2startPC = dataInput.readUnsignedShort();
602: lineNumberInfo.u2lineNumber = dataInput.readUnsignedShort();
603: }
604:
605: // Implementations for LocalVariableInfoVisitor.
606:
607: public void visitLocalVariableInfo(Clazz clazz, Method method,
608: CodeAttribute codeAttribute,
609: LocalVariableInfo localVariableInfo) {
610: localVariableInfo.u2startPC = dataInput.readUnsignedShort();
611: localVariableInfo.u2length = dataInput.readUnsignedShort();
612: localVariableInfo.u2nameIndex = dataInput.readUnsignedShort();
613: localVariableInfo.u2descriptorIndex = dataInput
614: .readUnsignedShort();
615: localVariableInfo.u2index = dataInput.readUnsignedShort();
616: }
617:
618: // Implementations for LocalVariableTypeInfoVisitor.
619:
620: public void visitLocalVariableTypeInfo(Clazz clazz, Method method,
621: CodeAttribute codeAttribute,
622: LocalVariableTypeInfo localVariableTypeInfo) {
623: localVariableTypeInfo.u2startPC = dataInput.readUnsignedShort();
624: localVariableTypeInfo.u2length = dataInput.readUnsignedShort();
625: localVariableTypeInfo.u2nameIndex = dataInput
626: .readUnsignedShort();
627: localVariableTypeInfo.u2signatureIndex = dataInput
628: .readUnsignedShort();
629: localVariableTypeInfo.u2index = dataInput.readUnsignedShort();
630: }
631:
632: // Implementations for AnnotationVisitor.
633:
634: public void visitAnnotation(Clazz clazz, Annotation annotation) {
635: // Read the annotation type.
636: annotation.u2typeIndex = dataInput.readUnsignedShort();
637:
638: // Read the element value pairs.
639: annotation.u2elementValuesCount = dataInput.readUnsignedShort();
640:
641: annotation.elementValues = new ElementValue[annotation.u2elementValuesCount];
642: for (int index = 0; index < annotation.u2elementValuesCount; index++) {
643: int u2elementNameIndex = dataInput.readUnsignedShort();
644: ElementValue elementValue = createElementValue();
645: elementValue.u2elementNameIndex = u2elementNameIndex;
646: elementValue.accept(clazz, annotation, this );
647: annotation.elementValues[index] = elementValue;
648: }
649: }
650:
651: // Implementations for ElementValueVisitor.
652:
653: public void visitConstantElementValue(Clazz clazz,
654: Annotation annotation,
655: ConstantElementValue constantElementValue) {
656: constantElementValue.u2constantValueIndex = dataInput
657: .readUnsignedShort();
658: }
659:
660: public void visitEnumConstantElementValue(Clazz clazz,
661: Annotation annotation,
662: EnumConstantElementValue enumConstantElementValue) {
663: enumConstantElementValue.u2typeNameIndex = dataInput
664: .readUnsignedShort();
665: enumConstantElementValue.u2constantNameIndex = dataInput
666: .readUnsignedShort();
667: }
668:
669: public void visitClassElementValue(Clazz clazz,
670: Annotation annotation, ClassElementValue classElementValue) {
671: classElementValue.u2classInfoIndex = dataInput
672: .readUnsignedShort();
673: }
674:
675: public void visitAnnotationElementValue(Clazz clazz,
676: Annotation annotation,
677: AnnotationElementValue annotationElementValue) {
678: // Read the annotation.
679: Annotation annotationValue = new Annotation();
680: this .visitAnnotation(clazz, annotationValue);
681: annotationElementValue.annotationValue = annotationValue;
682: }
683:
684: public void visitArrayElementValue(Clazz clazz,
685: Annotation annotation, ArrayElementValue arrayElementValue) {
686: // Read the element values.
687: arrayElementValue.u2elementValuesCount = dataInput
688: .readUnsignedShort();
689:
690: arrayElementValue.elementValues = new ElementValue[arrayElementValue.u2elementValuesCount];
691: for (int index = 0; index < arrayElementValue.u2elementValuesCount; index++) {
692: ElementValue elementValue = createElementValue();
693: elementValue.accept(clazz, annotation, this );
694: arrayElementValue.elementValues[index] = elementValue;
695: }
696: }
697:
698: // Small utility methods.
699:
700: private Constant createConstant() {
701: int u1tag = dataInput.readUnsignedByte();
702:
703: switch (u1tag) {
704: case ClassConstants.CONSTANT_Utf8:
705: return new Utf8Constant();
706: case ClassConstants.CONSTANT_Integer:
707: return new IntegerConstant();
708: case ClassConstants.CONSTANT_Float:
709: return new FloatConstant();
710: case ClassConstants.CONSTANT_Long:
711: return new LongConstant();
712: case ClassConstants.CONSTANT_Double:
713: return new DoubleConstant();
714: case ClassConstants.CONSTANT_String:
715: return new StringConstant();
716: case ClassConstants.CONSTANT_Fieldref:
717: return new FieldrefConstant();
718: case ClassConstants.CONSTANT_Methodref:
719: return new MethodrefConstant();
720: case ClassConstants.CONSTANT_InterfaceMethodref:
721: return new InterfaceMethodrefConstant();
722: case ClassConstants.CONSTANT_Class:
723: return new ClassConstant();
724: case ClassConstants.CONSTANT_NameAndType:
725: return new NameAndTypeConstant();
726:
727: default:
728: throw new RuntimeException("Unknown constant type ["
729: + u1tag + "] in constant pool");
730: }
731: }
732:
733: private Attribute createAttribute(Clazz clazz) {
734: int u2attributeNameIndex = dataInput.readUnsignedShort();
735: int u4attributeLength = dataInput.readInt();
736: String attributeName = clazz.getString(u2attributeNameIndex);
737: Attribute attribute = attributeName
738: .equals(ClassConstants.ATTR_SourceFile) ? (Attribute) new SourceFileAttribute()
739: : attributeName.equals(ClassConstants.ATTR_SourceDir) ? (Attribute) new SourceDirAttribute()
740: : attributeName
741: .equals(ClassConstants.ATTR_InnerClasses) ? (Attribute) new InnerClassesAttribute()
742: : attributeName
743: .equals(ClassConstants.ATTR_EnclosingMethod) ? (Attribute) new EnclosingMethodAttribute()
744: : attributeName
745: .equals(ClassConstants.ATTR_Deprecated) ? (Attribute) new DeprecatedAttribute()
746: : attributeName
747: .equals(ClassConstants.ATTR_Synthetic) ? (Attribute) new SyntheticAttribute()
748: : attributeName
749: .equals(ClassConstants.ATTR_Signature) ? (Attribute) new SignatureAttribute()
750: : attributeName
751: .equals(ClassConstants.ATTR_ConstantValue) ? (Attribute) new ConstantValueAttribute()
752: : attributeName
753: .equals(ClassConstants.ATTR_Exceptions) ? (Attribute) new ExceptionsAttribute()
754: : attributeName
755: .equals(ClassConstants.ATTR_Code) ? (Attribute) new CodeAttribute()
756: : attributeName
757: .equals(ClassConstants.ATTR_StackMap) ? (Attribute) new StackMapAttribute()
758: : attributeName
759: .equals(ClassConstants.ATTR_StackMapTable) ? (Attribute) new StackMapTableAttribute()
760: : attributeName
761: .equals(ClassConstants.ATTR_LineNumberTable) ? (Attribute) new LineNumberTableAttribute()
762: : attributeName
763: .equals(ClassConstants.ATTR_LocalVariableTable) ? (Attribute) new LocalVariableTableAttribute()
764: : attributeName
765: .equals(ClassConstants.ATTR_LocalVariableTypeTable) ? (Attribute) new LocalVariableTypeTableAttribute()
766: : attributeName
767: .equals(ClassConstants.ATTR_RuntimeVisibleAnnotations) ? (Attribute) new RuntimeVisibleAnnotationsAttribute()
768: : attributeName
769: .equals(ClassConstants.ATTR_RuntimeInvisibleAnnotations) ? (Attribute) new RuntimeInvisibleAnnotationsAttribute()
770: : attributeName
771: .equals(ClassConstants.ATTR_RuntimeVisibleParameterAnnotations) ? (Attribute) new RuntimeVisibleParameterAnnotationsAttribute()
772: : attributeName
773: .equals(ClassConstants.ATTR_RuntimeInvisibleParameterAnnotations) ? (Attribute) new RuntimeInvisibleParameterAnnotationsAttribute()
774: : attributeName
775: .equals(ClassConstants.ATTR_AnnotationDefault) ? (Attribute) new AnnotationDefaultAttribute()
776: : (Attribute) new UnknownAttribute(
777: u4attributeLength);
778: attribute.u2attributeNameIndex = u2attributeNameIndex;
779:
780: return attribute;
781: }
782:
783: private StackMapFrame createStackMapFrame() {
784: int u1tag = dataInput.readUnsignedByte();
785:
786: return u1tag < StackMapFrame.SAME_ONE_FRAME ? (StackMapFrame) new SameZeroFrame(
787: u1tag)
788: : u1tag < StackMapFrame.SAME_ONE_FRAME_EXTENDED ? (StackMapFrame) new SameOneFrame(
789: u1tag)
790: : u1tag < StackMapFrame.LESS_ZERO_FRAME ? (StackMapFrame) new SameOneFrame(
791: u1tag)
792: : u1tag < StackMapFrame.SAME_ZERO_FRAME_EXTENDED ? (StackMapFrame) new LessZeroFrame(
793: u1tag)
794: : u1tag < StackMapFrame.MORE_ZERO_FRAME ? (StackMapFrame) new SameZeroFrame(
795: u1tag)
796: : u1tag < StackMapFrame.FULL_FRAME ? (StackMapFrame) new MoreZeroFrame(
797: u1tag)
798: : (StackMapFrame) new FullFrame();
799: }
800:
801: private VerificationType createVerificationType() {
802: int u1tag = dataInput.readUnsignedByte();
803:
804: switch (u1tag) {
805: case VerificationType.INTEGER_TYPE:
806: return new IntegerType();
807: case VerificationType.FLOAT_TYPE:
808: return new FloatType();
809: case VerificationType.LONG_TYPE:
810: return new LongType();
811: case VerificationType.DOUBLE_TYPE:
812: return new DoubleType();
813: case VerificationType.TOP_TYPE:
814: return new TopType();
815: case VerificationType.OBJECT_TYPE:
816: return new ObjectType();
817: case VerificationType.NULL_TYPE:
818: return new NullType();
819: case VerificationType.UNINITIALIZED_TYPE:
820: return new UninitializedType();
821: case VerificationType.UNINITIALIZED_THIS_TYPE:
822: return new UninitializedThisType();
823:
824: default:
825: throw new RuntimeException("Unknown verification type ["
826: + u1tag + "] in stack map frame");
827: }
828: }
829:
830: private ElementValue createElementValue() {
831: int u1tag = dataInput.readUnsignedByte();
832:
833: switch (u1tag) {
834: case ClassConstants.INTERNAL_TYPE_BOOLEAN:
835: case ClassConstants.INTERNAL_TYPE_BYTE:
836: case ClassConstants.INTERNAL_TYPE_CHAR:
837: case ClassConstants.INTERNAL_TYPE_SHORT:
838: case ClassConstants.INTERNAL_TYPE_INT:
839: case ClassConstants.INTERNAL_TYPE_FLOAT:
840: case ClassConstants.INTERNAL_TYPE_LONG:
841: case ClassConstants.INTERNAL_TYPE_DOUBLE:
842: case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT:
843: return new ConstantElementValue(u1tag);
844:
845: case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT:
846: return new EnumConstantElementValue();
847: case ClassConstants.ELEMENT_VALUE_CLASS:
848: return new ClassElementValue();
849: case ClassConstants.ELEMENT_VALUE_ANNOTATION:
850: return new AnnotationElementValue();
851: case ClassConstants.ELEMENT_VALUE_ARRAY:
852: return new ArrayElementValue();
853:
854: default:
855: throw new IllegalArgumentException(
856: "Unknown element value tag [" + u1tag + "]");
857: }
858: }
859: }
|