001 package serp.bytecode; 002 003 import java.io.*; 004 import java.lang.reflect.*; 005 import java.util.*; 006 007 import serp.bytecode.lowlevel.*; 008 import serp.bytecode.visitor.*; 009 import serp.util.*; 010 011 /** 012 * In bytecode attributes are used to represent anything that is not 013 * part of the class structure. This includes the source file name, code of 014 * methods, the line number table, etc. All attributes contain at a minimum 015 * an immutable name that also determines the attribute's type. 016 * 017 * @author Abe White 018 */ 019 public abstract class Attribute extends Attributes implements VisitAcceptor { 020 private int _nameIndex = 0; 021 private Attributes _owner = null; 022 023 Attribute(int nameIndex, Attributes owner) { 024 _owner = owner; 025 _nameIndex = nameIndex; 026 } 027 028 /** 029 * Create an attribute of the appropriate type based on the 030 * the attribute name. 031 */ 032 static Attribute create(String name, Attributes owner) { 033 // special case for annotations 034 int nameIndex = owner.getPool().findUTF8Entry(name, true); 035 if ("RuntimeVisibleAnnotations".equals(name) 036 || "RuntimeInvisibleAnnotations".equals(name)) 037 return new Annotations(nameIndex, owner); 038 039 try { 040 Class type = Class.forName("serp.bytecode." + name); 041 Constructor cons = type.getDeclaredConstructor(new Class[] { 042 int.class, Attributes.class 043 }); 044 return (Attribute) cons.newInstance(new Object[] { 045 Numbers.valueOf(nameIndex), owner 046 }); 047 } catch (Throwable t) { 048 return new UnknownAttribute(nameIndex, owner); 049 } 050 } 051 052 /** 053 * Return the {@link Attributes} that owns this attribute. The entity 054 * might be a {@link BCClass}, {@link BCField}, {@link BCMethod}, or other 055 * attribute. 056 */ 057 public Attributes getOwner() { 058 return _owner; 059 } 060 061 /** 062 * Return the index in the {@link ConstantPool} of the {@link UTF8Entry} 063 * holding the name of this attribute. 064 */ 065 public int getNameIndex() { 066 return _nameIndex; 067 } 068 069 /** 070 * Return the name of this attribute. 071 */ 072 public String getName() { 073 return ((UTF8Entry) getPool().getEntry(_nameIndex)).getValue(); 074 } 075 076 public Project getProject() { 077 return _owner.getProject(); 078 } 079 080 public ConstantPool getPool() { 081 return _owner.getPool(); 082 } 083 084 public ClassLoader getClassLoader() { 085 return _owner.getClassLoader(); 086 } 087 088 public boolean isValid() { 089 return _owner != null; 090 } 091 092 Collection getAttributesHolder() { 093 return Collections.EMPTY_LIST; 094 } 095 096 /** 097 * Invalidate this attribute. 098 */ 099 void invalidate() { 100 _owner = null; 101 } 102 103 /** 104 * Return the length of the bytecode representation of this attribute 105 * in bytes, excluding the name index. 106 */ 107 int getLength() { 108 return 0; 109 } 110 111 /** 112 * Copy the information from the given attribute to this one. Does 113 * nothing by default. 114 */ 115 void read(Attribute other) { 116 } 117 118 /** 119 * Read the attribute bytecode from the given stream, up to length 120 * bytes, excluding the name index. Does nothing by default. 121 */ 122 void read(DataInput in, int length) throws IOException { 123 } 124 125 /** 126 * Write the attribute bytecode to the given stream, up to length bytes, 127 * excluding the name index. Does nothing by default. 128 */ 129 void write(DataOutput out, int length) throws IOException { 130 } 131 }