jjg@46: /* xdono@54: * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. jjg@46: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@46: * jjg@46: * This code is free software; you can redistribute it and/or modify it jjg@46: * under the terms of the GNU General Public License version 2 only, as jjg@46: * published by the Free Software Foundation. Sun designates this jjg@46: * particular file as subject to the "Classpath" exception as provided jjg@46: * by Sun in the LICENSE file that accompanied this code. jjg@46: * jjg@46: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@46: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@46: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@46: * version 2 for more details (a copy is included in the LICENSE file that jjg@46: * accompanied this code). jjg@46: * jjg@46: * You should have received a copy of the GNU General Public License version jjg@46: * 2 along with this work; if not, write to the Free Software Foundation, jjg@46: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@46: * jjg@46: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, jjg@46: * CA 95054 USA or visit www.sun.com if you need additional information or jjg@46: * have any questions. jjg@46: */ jjg@46: jjg@46: package com.sun.tools.javap; jjg@46: jjg@46: import com.sun.tools.classfile.Annotation; jjg@308: import com.sun.tools.classfile.ExtendedAnnotation; jjg@46: import com.sun.tools.classfile.Annotation.Annotation_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Array_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Class_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Enum_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Primitive_element_value; jjg@338: import com.sun.tools.classfile.ConstantPool; jjg@338: import com.sun.tools.classfile.ConstantPoolException; jjg@338: import com.sun.tools.classfile.Descriptor; jjg@338: import com.sun.tools.classfile.Descriptor.InvalidDescriptor; jjg@46: jjg@46: /** jjg@46: * A writer for writing annotations as text. jjg@46: * jjg@46: *

This is NOT part of any API supported by Sun Microsystems. If jjg@46: * you write code that depends on this, you do so at your own risk. jjg@46: * This code and its internal interfaces are subject to change or jjg@46: * deletion without notice. jjg@46: */ jjg@46: public class AnnotationWriter extends BasicWriter { jjg@46: static AnnotationWriter instance(Context context) { jjg@46: AnnotationWriter instance = context.get(AnnotationWriter.class); jjg@46: if (instance == null) jjg@46: instance = new AnnotationWriter(context); jjg@46: return instance; jjg@46: } jjg@46: jjg@46: protected AnnotationWriter(Context context) { jjg@46: super(context); jjg@338: classWriter = ClassWriter.instance(context); jjg@338: constantWriter = ConstantWriter.instance(context); jjg@46: } jjg@46: jjg@46: public void write(Annotation annot) { jjg@338: write(annot, false); jjg@338: } jjg@338: jjg@338: public void write(Annotation annot, boolean resolveIndices) { jjg@338: writeDescriptor(annot.type_index, resolveIndices); jjg@338: boolean showParens = annot.num_element_value_pairs > 0 || !resolveIndices; jjg@338: if (showParens) jjg@338: print("("); jjg@46: for (int i = 0; i < annot.num_element_value_pairs; i++) { jjg@46: if (i > 0) jjg@46: print(","); jjg@338: write(annot.element_value_pairs[i], resolveIndices); jjg@46: } jjg@338: if (showParens) jjg@338: print(")"); jjg@46: } jjg@46: jjg@308: public void write(ExtendedAnnotation annot) { jjg@338: write(annot, true, false); jjg@338: } jjg@338: jjg@338: public void write(ExtendedAnnotation annot, boolean showOffsets, boolean resolveIndices) { jjg@338: write(annot.annotation, resolveIndices); jjg@338: print(": "); jjg@338: write(annot.position, showOffsets); jjg@338: } jjg@338: jjg@338: public void write(ExtendedAnnotation.Position pos, boolean showOffsets) { jjg@338: print(pos.type); jjg@338: jjg@338: switch (pos.type) { jjg@338: // type case jjg@338: case TYPECAST: jjg@338: case TYPECAST_GENERIC_OR_ARRAY: jjg@338: // object creation jjg@338: case INSTANCEOF: jjg@338: case INSTANCEOF_GENERIC_OR_ARRAY: jjg@338: // new expression jjg@338: case NEW: jjg@338: case NEW_GENERIC_OR_ARRAY: jjg@338: case NEW_TYPE_ARGUMENT: jjg@338: case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: jjg@338: if (showOffsets) { jjg@338: print(", offset="); jjg@338: print(pos.offset); jjg@338: } jjg@338: break; jjg@338: // local variable jjg@338: case LOCAL_VARIABLE: jjg@338: case LOCAL_VARIABLE_GENERIC_OR_ARRAY: jjg@338: print(", {"); jjg@338: for (int i = 0; i < pos.lvarOffset.length; ++i) { jjg@338: if (i != 0) print("; "); jjg@338: if (showOffsets) { jjg@338: print(", start_pc="); jjg@338: print(pos.lvarOffset[i]); jjg@338: } jjg@338: print(", length="); jjg@338: print(pos.lvarLength[i]); jjg@338: print(", index="); jjg@338: print(pos.lvarIndex[i]); jjg@338: } jjg@338: print("}"); jjg@338: break; jjg@338: // method receiver jjg@338: case METHOD_RECEIVER: jjg@338: // Do nothing jjg@338: break; jjg@338: // type parameters jjg@338: case CLASS_TYPE_PARAMETER: jjg@338: case METHOD_TYPE_PARAMETER: jjg@338: print(", param_index="); jjg@338: print(pos.parameter_index); jjg@338: break; jjg@338: // type parameters bound jjg@338: case CLASS_TYPE_PARAMETER_BOUND: jjg@338: case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: jjg@338: case METHOD_TYPE_PARAMETER_BOUND: jjg@338: case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: jjg@338: print(", param_index="); jjg@338: print(pos.parameter_index); jjg@338: print(", bound_index="); jjg@338: print(pos.bound_index); jjg@338: break; jjg@338: // wildcard jjg@338: case WILDCARD_BOUND: jjg@338: case WILDCARD_BOUND_GENERIC_OR_ARRAY: jjg@338: print(", wild_card="); jjg@338: print(pos.wildcard_position); jjg@338: break; jjg@338: // Class extends and implements clauses jjg@338: case CLASS_EXTENDS: jjg@338: case CLASS_EXTENDS_GENERIC_OR_ARRAY: jjg@338: print(", type_index="); jjg@338: print(pos.type_index); jjg@338: break; jjg@338: // throws jjg@338: case THROWS: jjg@338: print(", type_index="); jjg@338: print(pos.type_index); jjg@338: break; jjg@338: case CLASS_LITERAL: jjg@338: if (showOffsets) { jjg@338: print(", offset="); jjg@338: print(pos.offset); jjg@338: } jjg@338: break; jjg@338: // method parameter: not specified jjg@338: case METHOD_PARAMETER_GENERIC_OR_ARRAY: jjg@338: print(", param_index="); jjg@338: print(pos.parameter_index); jjg@338: break; jjg@338: // method type argument: wasn't specified jjg@338: case METHOD_TYPE_ARGUMENT: jjg@338: case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: jjg@338: if (showOffsets) { jjg@338: print(", offset="); jjg@338: print(pos.offset); jjg@338: } jjg@338: print(", type_index="); jjg@338: print(pos.type_index); jjg@338: break; jjg@338: // We don't need to worry abut these jjg@338: case METHOD_RETURN_GENERIC_OR_ARRAY: jjg@338: case FIELD_GENERIC_OR_ARRAY: jjg@338: break; jjg@338: case UNKNOWN: jjg@338: break; jjg@338: default: jjg@338: throw new AssertionError("unknown type: " + pos.type); jjg@338: } jjg@338: jjg@338: // Append location data for generics/arrays. jjg@338: if (pos.type.hasLocation()) { jjg@338: print(", location="); jjg@338: print(pos.location); jjg@338: } jjg@308: } jjg@308: jjg@46: public void write(Annotation.element_value_pair pair) { jjg@338: write(pair, false); jjg@338: } jjg@338: jjg@338: public void write(Annotation.element_value_pair pair, boolean resolveIndices) { jjg@338: writeIndex(pair.element_name_index, resolveIndices); jjg@338: print("="); jjg@338: write(pair.value, resolveIndices); jjg@46: } jjg@46: jjg@46: public void write(Annotation.element_value value) { jjg@338: write(value, false); jjg@338: } jjg@338: jjg@338: public void write(Annotation.element_value value, boolean resolveIndices) { jjg@338: ev_writer.write(value, resolveIndices); jjg@338: } jjg@338: jjg@338: private void writeDescriptor(int index, boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: try { jjg@338: ConstantPool constant_pool = classWriter.getClassFile().constant_pool; jjg@338: Descriptor d = new Descriptor(index); jjg@338: print(d.getFieldType(constant_pool)); jjg@338: return; jjg@338: } catch (ConstantPoolException ignore) { jjg@338: } catch (InvalidDescriptor ignore) { jjg@338: } jjg@338: } jjg@338: jjg@338: print("#" + index); jjg@338: } jjg@338: jjg@338: private void writeIndex(int index, boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: print(constantWriter.stringValue(index)); jjg@338: } else jjg@338: print("#" + index); jjg@46: } jjg@46: jjg@46: element_value_Writer ev_writer = new element_value_Writer(); jjg@46: jjg@338: class element_value_Writer implements Annotation.element_value.Visitor { jjg@338: public void write(Annotation.element_value value, boolean resolveIndices) { jjg@338: value.accept(this, resolveIndices); jjg@46: } jjg@46: jjg@338: public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) { jjg@338: if (resolveIndices) jjg@338: writeIndex(ev.const_value_index, resolveIndices); jjg@338: else jjg@338: print(((char) ev.tag) + "#" + ev.const_value_index); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: writeIndex(ev.type_name_index, resolveIndices); jjg@338: print("."); jjg@338: writeIndex(ev.const_name_index, resolveIndices); jjg@338: } else jjg@338: print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitClass(Class_element_value ev, Boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: writeIndex(ev.class_info_index, resolveIndices); jjg@338: print(".class"); jjg@338: } else jjg@338: print(((char) ev.tag) + "#" + ev.class_info_index); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) { jjg@46: print((char) ev.tag); jjg@338: AnnotationWriter.this.write(ev.annotation_value, resolveIndices); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitArray(Array_element_value ev, Boolean resolveIndices) { jjg@46: print("["); jjg@46: for (int i = 0; i < ev.num_values; i++) { jjg@46: if (i > 0) jjg@46: print(","); jjg@338: write(ev.values[i], resolveIndices); jjg@46: } jjg@46: print("]"); jjg@46: return null; jjg@46: } jjg@46: jjg@46: } jjg@338: jjg@338: private ClassWriter classWriter; jjg@338: private ConstantWriter constantWriter; jjg@46: }