/** * Makes the given class visitor visit this class. * * @param cv a class visitor. */ public void accept(final ClassVisitor cv) { // visits header String[] interfaces = new String[this.interfaces.size()]; this.interfaces.toArray(interfaces); cv.visit(version, access, name, signature, superName, interfaces); // visits source if (sourceFile != null || sourceDebug != null) { cv.visitSource(sourceFile, sourceDebug); } // visits outer class if (outerClass != null) { cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); } // visits attributes int i, n; n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); for (i = 0; i < n; ++i) { AnnotationNode an = visibleAnnotations.get(i); an.accept(cv.visitAnnotation(an.desc, true)); } n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); for (i = 0; i < n; ++i) { AnnotationNode an = invisibleAnnotations.get(i); an.accept(cv.visitAnnotation(an.desc, false)); } n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); for (i = 0; i < n; ++i) { TypeAnnotationNode an = visibleTypeAnnotations.get(i); an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, true)); } n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations.size(); for (i = 0; i < n; ++i) { TypeAnnotationNode an = invisibleTypeAnnotations.get(i); an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, false)); } n = attrs == null ? 0 : attrs.size(); for (i = 0; i < n; ++i) { cv.visitAttribute(attrs.get(i)); } // visits inner classes for (i = 0; i < innerClasses.size(); ++i) { innerClasses.get(i).accept(cv); } // visits fields for (i = 0; i < fields.size(); ++i) { fields.get(i).accept(cv); } // visits methods for (i = 0; i < methods.size(); ++i) { methods.get(i).accept(cv); } // visits end cv.visitEnd(); }
/** * Handle a bizarre special case. Nested classes (static classes declared inside another class) * that are protected have their access bit set to public in their class files to deal with some * odd reflection situation. Our SVUID computation must do as the JVM does and ignore access bits * in the class file in favor of the access bits InnerClass attribute. */ @Override public void visitInnerClass( final String aname, final String outerName, final String innerName, final int attr_access) { if ((name != null) && name.equals(aname)) { this.access = attr_access; } super.visitInnerClass(aname, outerName, innerName, attr_access); }
/* * Add the SVUID if class doesn't have one */ @Override public void visitEnd() { // compute SVUID and add it to the class if (computeSVUID && !hasSVUID) { try { addSVUID(computeSVUID()); } catch (Throwable e) { throw new RuntimeException("Error while computing SVUID for " + name, e); } } super.visitEnd(); }
/* * Visit class header and get class name, access , and interfaces * information (step 1,2, and 3) for SVUID computation. */ @Override public void visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0; if (computeSVUID) { this.name = name; this.access = access; this.interfaces = new String[interfaces.length]; System.arraycopy(interfaces, 0, this.interfaces, 0, interfaces.length); } super.visit(version, access, name, signature, superName, interfaces); }