|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | package com.sun.org.apache.bcel.internal.classfile; | 
|  |  | 
|  | import java.io.DataInput; | 
|  | import java.io.DataInputStream; | 
|  | import java.io.DataOutputStream; | 
|  | import java.io.IOException; | 
|  | import java.util.HashMap; | 
|  | import java.util.Map; | 
|  |  | 
|  | import com.sun.org.apache.bcel.internal.Const; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | public abstract class Attribute implements Cloneable, Node { | 
|  |  | 
|  |     private int name_index;  | 
|  |     private int length;  | 
|  |     private final byte tag;  | 
|  |     private ConstantPool constant_pool; | 
|  |  | 
|  |     protected Attribute(final byte tag, final int name_index, final int length, final ConstantPool constant_pool) { | 
|  |         this.tag = tag; | 
|  |         this.name_index = name_index; | 
|  |         this.length = length; | 
|  |         this.constant_pool = constant_pool; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public abstract void accept(Visitor v); | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void dump(final DataOutputStream file) throws IOException { | 
|  |         file.writeShort(name_index); | 
|  |         file.writeInt(length); | 
|  |     } | 
|  |  | 
|  |     private static final Map<String, Object> readers = new HashMap<>(); | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static void addAttributeReader(final String name, final UnknownAttributeReader r) { | 
|  |         readers.put(name, r); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static void removeAttributeReader(final String name) { | 
|  |         readers.remove(name); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static Attribute readAttribute(final DataInputStream file, final ConstantPool constant_pool) | 
|  |             throws IOException, ClassFormatException { | 
|  |         return readAttribute((DataInput) file, constant_pool); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool) | 
|  |             throws IOException, ClassFormatException { | 
|  |         byte tag = Const.ATTR_UNKNOWN;  | 
|  |          | 
|  |         final int name_index = file.readUnsignedShort(); | 
|  |         final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); | 
|  |         final String name = c.getBytes(); | 
|  |  | 
|  |          | 
|  |         final int length = file.readInt(); | 
|  |  | 
|  |          | 
|  |         for (byte i = 0; i < Const.KNOWN_ATTRIBUTES; i++) { | 
|  |             if (name.equals(Const.getAttributeName(i))) { | 
|  |                 tag = i;  | 
|  |                 break; | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |         switch (tag) { | 
|  |             case Const.ATTR_UNKNOWN: | 
|  |                 final Object r = readers.get(name); | 
|  |                 if (r instanceof UnknownAttributeReader) { | 
|  |                     return ((UnknownAttributeReader) r).createAttribute(name_index, length, file, constant_pool); | 
|  |                 } | 
|  |                 return new Unknown(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_CONSTANT_VALUE: | 
|  |                 return new ConstantValue(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_SOURCE_FILE: | 
|  |                 return new SourceFile(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_CODE: | 
|  |                 return new Code(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_EXCEPTIONS: | 
|  |                 return new ExceptionTable(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_LINE_NUMBER_TABLE: | 
|  |                 return new LineNumberTable(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_LOCAL_VARIABLE_TABLE: | 
|  |                 return new LocalVariableTable(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_INNER_CLASSES: | 
|  |                 return new InnerClasses(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_SYNTHETIC: | 
|  |                 return new Synthetic(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_DEPRECATED: | 
|  |                 return new Deprecated(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_PMG: | 
|  |                 return new PMGClass(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_SIGNATURE: | 
|  |                 return new Signature(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_STACK_MAP: | 
|  |                 return new StackMap(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: | 
|  |                 return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: | 
|  |                 return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: | 
|  |                 return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: | 
|  |                 return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_ANNOTATION_DEFAULT: | 
|  |                 return new AnnotationDefault(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE: | 
|  |                 return new LocalVariableTypeTable(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_ENCLOSING_METHOD: | 
|  |                 return new EnclosingMethod(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_STACK_MAP_TABLE: | 
|  |                 return new StackMap(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_BOOTSTRAP_METHODS: | 
|  |                 return new BootstrapMethods(name_index, length, file, constant_pool); | 
|  |             case Const.ATTR_METHOD_PARAMETERS: | 
|  |                 return new MethodParameters(name_index, length, file, constant_pool); | 
|  |             default: | 
|  |                  | 
|  |                 throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public String getName() { | 
|  |         final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); | 
|  |         return c.getBytes(); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final int getLength() { | 
|  |         return length; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setLength(final int length) { | 
|  |         this.length = length; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setNameIndex(final int name_index) { | 
|  |         this.name_index = name_index; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final int getNameIndex() { | 
|  |         return name_index; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public final byte getTag() { | 
|  |         return tag; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public final ConstantPool getConstantPool() { | 
|  |         return constant_pool; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public final void setConstantPool(final ConstantPool constant_pool) { | 
|  |         this.constant_pool = constant_pool; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public Object clone() { | 
|  |         Attribute attr = null; | 
|  |         try { | 
|  |             attr = (Attribute) super.clone(); | 
|  |         } catch (final CloneNotSupportedException e) { | 
|  |             throw new Error("Clone Not Supported");  | 
|  |         } | 
|  |         return attr; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public abstract Attribute copy(ConstantPool _constant_pool); | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public String toString() { | 
|  |         return Const.getAttributeName(tag); | 
|  |     } | 
|  | } |