1*f1fbf3c2SXin Li /* 2*f1fbf3c2SXin Li * Javassist, a Java-bytecode translator toolkit. 3*f1fbf3c2SXin Li * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 4*f1fbf3c2SXin Li * 5*f1fbf3c2SXin Li * The contents of this file are subject to the Mozilla Public License Version 6*f1fbf3c2SXin Li * 1.1 (the "License"); you may not use this file except in compliance with 7*f1fbf3c2SXin Li * the License. Alternatively, the contents of this file may be used under 8*f1fbf3c2SXin Li * the terms of the GNU Lesser General Public License Version 2.1 or later, 9*f1fbf3c2SXin Li * or the Apache License Version 2.0. 10*f1fbf3c2SXin Li * 11*f1fbf3c2SXin Li * Software distributed under the License is distributed on an "AS IS" basis, 12*f1fbf3c2SXin Li * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13*f1fbf3c2SXin Li * for the specific language governing rights and limitations under the 14*f1fbf3c2SXin Li * License. 15*f1fbf3c2SXin Li */ 16*f1fbf3c2SXin Li 17*f1fbf3c2SXin Li package javassist.bytecode; 18*f1fbf3c2SXin Li 19*f1fbf3c2SXin Li import java.io.DataInputStream; 20*f1fbf3c2SXin Li import java.io.DataOutputStream; 21*f1fbf3c2SXin Li import java.io.IOException; 22*f1fbf3c2SXin Li import java.util.ArrayList; 23*f1fbf3c2SXin Li import java.util.Arrays; 24*f1fbf3c2SXin Li import java.util.List; 25*f1fbf3c2SXin Li import java.util.Map; 26*f1fbf3c2SXin Li 27*f1fbf3c2SXin Li // Note: if you define a new subclass of AttributeInfo, then 28*f1fbf3c2SXin Li // update AttributeInfo.read(), .copy(), and (maybe) write(). 29*f1fbf3c2SXin Li 30*f1fbf3c2SXin Li /** 31*f1fbf3c2SXin Li * <code>attribute_info</code> structure. 32*f1fbf3c2SXin Li * 33*f1fbf3c2SXin Li * @see ClassFile#getAttribute(String) 34*f1fbf3c2SXin Li * @see MethodInfo#getAttribute(String) 35*f1fbf3c2SXin Li * @see FieldInfo#getAttribute(String) 36*f1fbf3c2SXin Li */ 37*f1fbf3c2SXin Li public class AttributeInfo { 38*f1fbf3c2SXin Li protected ConstPool constPool; 39*f1fbf3c2SXin Li int name; 40*f1fbf3c2SXin Li byte[] info; 41*f1fbf3c2SXin Li AttributeInfo(ConstPool cp, int attrname, byte[] attrinfo)42*f1fbf3c2SXin Li protected AttributeInfo(ConstPool cp, int attrname, byte[] attrinfo) { 43*f1fbf3c2SXin Li constPool = cp; 44*f1fbf3c2SXin Li name = attrname; 45*f1fbf3c2SXin Li info = attrinfo; 46*f1fbf3c2SXin Li } 47*f1fbf3c2SXin Li AttributeInfo(ConstPool cp, String attrname)48*f1fbf3c2SXin Li protected AttributeInfo(ConstPool cp, String attrname) { 49*f1fbf3c2SXin Li this(cp, attrname, (byte[])null); 50*f1fbf3c2SXin Li } 51*f1fbf3c2SXin Li 52*f1fbf3c2SXin Li /** 53*f1fbf3c2SXin Li * Constructs an <code>attribute_info</code> structure. 54*f1fbf3c2SXin Li * 55*f1fbf3c2SXin Li * @param cp constant pool table 56*f1fbf3c2SXin Li * @param attrname attribute name 57*f1fbf3c2SXin Li * @param attrinfo <code>info</code> field 58*f1fbf3c2SXin Li * of <code>attribute_info</code> structure. 59*f1fbf3c2SXin Li */ AttributeInfo(ConstPool cp, String attrname, byte[] attrinfo)60*f1fbf3c2SXin Li public AttributeInfo(ConstPool cp, String attrname, byte[] attrinfo) { 61*f1fbf3c2SXin Li this(cp, cp.addUtf8Info(attrname), attrinfo); 62*f1fbf3c2SXin Li } 63*f1fbf3c2SXin Li AttributeInfo(ConstPool cp, int n, DataInputStream in)64*f1fbf3c2SXin Li protected AttributeInfo(ConstPool cp, int n, DataInputStream in) 65*f1fbf3c2SXin Li throws IOException 66*f1fbf3c2SXin Li { 67*f1fbf3c2SXin Li constPool = cp; 68*f1fbf3c2SXin Li name = n; 69*f1fbf3c2SXin Li int len = in.readInt(); 70*f1fbf3c2SXin Li info = new byte[len]; 71*f1fbf3c2SXin Li if (len > 0) 72*f1fbf3c2SXin Li in.readFully(info); 73*f1fbf3c2SXin Li } 74*f1fbf3c2SXin Li read(ConstPool cp, DataInputStream in)75*f1fbf3c2SXin Li static AttributeInfo read(ConstPool cp, DataInputStream in) 76*f1fbf3c2SXin Li throws IOException 77*f1fbf3c2SXin Li { 78*f1fbf3c2SXin Li int name = in.readUnsignedShort(); 79*f1fbf3c2SXin Li String nameStr = cp.getUtf8Info(name); 80*f1fbf3c2SXin Li char first = nameStr.charAt(0); 81*f1fbf3c2SXin Li if (first < 'E') 82*f1fbf3c2SXin Li if (nameStr.equals(AnnotationDefaultAttribute.tag)) 83*f1fbf3c2SXin Li return new AnnotationDefaultAttribute(cp, name, in); 84*f1fbf3c2SXin Li else if (nameStr.equals(BootstrapMethodsAttribute.tag)) 85*f1fbf3c2SXin Li return new BootstrapMethodsAttribute(cp, name, in); 86*f1fbf3c2SXin Li else if (nameStr.equals(CodeAttribute.tag)) 87*f1fbf3c2SXin Li return new CodeAttribute(cp, name, in); 88*f1fbf3c2SXin Li else if (nameStr.equals(ConstantAttribute.tag)) 89*f1fbf3c2SXin Li return new ConstantAttribute(cp, name, in); 90*f1fbf3c2SXin Li else if (nameStr.equals(DeprecatedAttribute.tag)) 91*f1fbf3c2SXin Li return new DeprecatedAttribute(cp, name, in); 92*f1fbf3c2SXin Li 93*f1fbf3c2SXin Li if (first < 'M') 94*f1fbf3c2SXin Li if (nameStr.equals(EnclosingMethodAttribute.tag)) 95*f1fbf3c2SXin Li return new EnclosingMethodAttribute(cp, name, in); 96*f1fbf3c2SXin Li else if (nameStr.equals(ExceptionsAttribute.tag)) 97*f1fbf3c2SXin Li return new ExceptionsAttribute(cp, name, in); 98*f1fbf3c2SXin Li else if (nameStr.equals(InnerClassesAttribute.tag)) 99*f1fbf3c2SXin Li return new InnerClassesAttribute(cp, name, in); 100*f1fbf3c2SXin Li else if (nameStr.equals(LineNumberAttribute.tag)) 101*f1fbf3c2SXin Li return new LineNumberAttribute(cp, name, in); 102*f1fbf3c2SXin Li else if (nameStr.equals(LocalVariableAttribute.tag)) 103*f1fbf3c2SXin Li return new LocalVariableAttribute(cp, name, in); 104*f1fbf3c2SXin Li else if (nameStr.equals(LocalVariableTypeAttribute.tag)) 105*f1fbf3c2SXin Li return new LocalVariableTypeAttribute(cp, name, in); 106*f1fbf3c2SXin Li 107*f1fbf3c2SXin Li if (first < 'S') 108*f1fbf3c2SXin Li /* Note that the names of Annotations attributes begin with 'R'. */ 109*f1fbf3c2SXin Li if (nameStr.equals(MethodParametersAttribute.tag)) 110*f1fbf3c2SXin Li return new MethodParametersAttribute(cp, name, in); 111*f1fbf3c2SXin Li else if (nameStr.equals(NestHostAttribute.tag)) 112*f1fbf3c2SXin Li return new NestHostAttribute(cp, name, in); 113*f1fbf3c2SXin Li else if (nameStr.equals(NestMembersAttribute.tag)) 114*f1fbf3c2SXin Li return new NestMembersAttribute(cp, name, in); 115*f1fbf3c2SXin Li else if (nameStr.equals(AnnotationsAttribute.visibleTag) 116*f1fbf3c2SXin Li || nameStr.equals(AnnotationsAttribute.invisibleTag)) 117*f1fbf3c2SXin Li // RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations 118*f1fbf3c2SXin Li return new AnnotationsAttribute(cp, name, in); 119*f1fbf3c2SXin Li else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag) 120*f1fbf3c2SXin Li || nameStr.equals(ParameterAnnotationsAttribute.invisibleTag)) 121*f1fbf3c2SXin Li return new ParameterAnnotationsAttribute(cp, name, in); 122*f1fbf3c2SXin Li else if (nameStr.equals(TypeAnnotationsAttribute.visibleTag) 123*f1fbf3c2SXin Li || nameStr.equals(TypeAnnotationsAttribute.invisibleTag)) 124*f1fbf3c2SXin Li return new TypeAnnotationsAttribute(cp, name, in); 125*f1fbf3c2SXin Li 126*f1fbf3c2SXin Li if (first >= 'S') 127*f1fbf3c2SXin Li if (nameStr.equals(SignatureAttribute.tag)) 128*f1fbf3c2SXin Li return new SignatureAttribute(cp, name, in); 129*f1fbf3c2SXin Li else if (nameStr.equals(SourceFileAttribute.tag)) 130*f1fbf3c2SXin Li return new SourceFileAttribute(cp, name, in); 131*f1fbf3c2SXin Li else if (nameStr.equals(SyntheticAttribute.tag)) 132*f1fbf3c2SXin Li return new SyntheticAttribute(cp, name, in); 133*f1fbf3c2SXin Li else if (nameStr.equals(StackMap.tag)) 134*f1fbf3c2SXin Li return new StackMap(cp, name, in); 135*f1fbf3c2SXin Li else if (nameStr.equals(StackMapTable.tag)) 136*f1fbf3c2SXin Li return new StackMapTable(cp, name, in); 137*f1fbf3c2SXin Li 138*f1fbf3c2SXin Li return new AttributeInfo(cp, name, in); 139*f1fbf3c2SXin Li } 140*f1fbf3c2SXin Li 141*f1fbf3c2SXin Li /** 142*f1fbf3c2SXin Li * Returns an attribute name. 143*f1fbf3c2SXin Li */ getName()144*f1fbf3c2SXin Li public String getName() { 145*f1fbf3c2SXin Li return constPool.getUtf8Info(name); 146*f1fbf3c2SXin Li } 147*f1fbf3c2SXin Li 148*f1fbf3c2SXin Li /** 149*f1fbf3c2SXin Li * Returns a constant pool table. 150*f1fbf3c2SXin Li */ getConstPool()151*f1fbf3c2SXin Li public ConstPool getConstPool() { return constPool; } 152*f1fbf3c2SXin Li 153*f1fbf3c2SXin Li /** 154*f1fbf3c2SXin Li * Returns the length of this <code>attribute_info</code> 155*f1fbf3c2SXin Li * structure. 156*f1fbf3c2SXin Li * The returned value is <code>attribute_length + 6</code>. 157*f1fbf3c2SXin Li */ length()158*f1fbf3c2SXin Li public int length() { 159*f1fbf3c2SXin Li return info.length + 6; 160*f1fbf3c2SXin Li } 161*f1fbf3c2SXin Li 162*f1fbf3c2SXin Li /** 163*f1fbf3c2SXin Li * Returns the <code>info</code> field 164*f1fbf3c2SXin Li * of this <code>attribute_info</code> structure. 165*f1fbf3c2SXin Li * 166*f1fbf3c2SXin Li * <p>This method is not available if the object is an instance 167*f1fbf3c2SXin Li * of <code>CodeAttribute</code>. 168*f1fbf3c2SXin Li */ get()169*f1fbf3c2SXin Li public byte[] get() { return info; } 170*f1fbf3c2SXin Li 171*f1fbf3c2SXin Li /** 172*f1fbf3c2SXin Li * Sets the <code>info</code> field 173*f1fbf3c2SXin Li * of this <code>attribute_info</code> structure. 174*f1fbf3c2SXin Li * 175*f1fbf3c2SXin Li * <p>This method is not available if the object is an instance 176*f1fbf3c2SXin Li * of <code>CodeAttribute</code>. 177*f1fbf3c2SXin Li */ set(byte[] newinfo)178*f1fbf3c2SXin Li public void set(byte[] newinfo) { info = newinfo; } 179*f1fbf3c2SXin Li 180*f1fbf3c2SXin Li /** 181*f1fbf3c2SXin Li * Makes a copy. Class names are replaced according to the 182*f1fbf3c2SXin Li * given <code>Map</code> object. 183*f1fbf3c2SXin Li * 184*f1fbf3c2SXin Li * @param newCp the constant pool table used by the new copy. 185*f1fbf3c2SXin Li * @param classnames pairs of replaced and substituted 186*f1fbf3c2SXin Li * class names. 187*f1fbf3c2SXin Li */ copy(ConstPool newCp, Map<String,String> classnames)188*f1fbf3c2SXin Li public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) 189*f1fbf3c2SXin Li { 190*f1fbf3c2SXin Li return new AttributeInfo(newCp, getName(), Arrays.copyOf(info, info.length)); 191*f1fbf3c2SXin Li } 192*f1fbf3c2SXin Li write(DataOutputStream out)193*f1fbf3c2SXin Li void write(DataOutputStream out) throws IOException 194*f1fbf3c2SXin Li { 195*f1fbf3c2SXin Li out.writeShort(name); 196*f1fbf3c2SXin Li out.writeInt(info.length); 197*f1fbf3c2SXin Li if (info.length > 0) 198*f1fbf3c2SXin Li out.write(info); 199*f1fbf3c2SXin Li } 200*f1fbf3c2SXin Li getLength(List<AttributeInfo> attributes)201*f1fbf3c2SXin Li static int getLength(List<AttributeInfo> attributes) { 202*f1fbf3c2SXin Li int size = 0; 203*f1fbf3c2SXin Li 204*f1fbf3c2SXin Li for (AttributeInfo attr:attributes) 205*f1fbf3c2SXin Li size += attr.length(); 206*f1fbf3c2SXin Li 207*f1fbf3c2SXin Li return size; 208*f1fbf3c2SXin Li } 209*f1fbf3c2SXin Li lookup(List<AttributeInfo> attributes, String name)210*f1fbf3c2SXin Li static AttributeInfo lookup(List<AttributeInfo> attributes, String name) { 211*f1fbf3c2SXin Li if (attributes == null) 212*f1fbf3c2SXin Li return null; 213*f1fbf3c2SXin Li 214*f1fbf3c2SXin Li for (AttributeInfo ai:attributes) 215*f1fbf3c2SXin Li if (ai.getName().equals(name)) 216*f1fbf3c2SXin Li return ai; 217*f1fbf3c2SXin Li 218*f1fbf3c2SXin Li return null; // no such attribute 219*f1fbf3c2SXin Li } 220*f1fbf3c2SXin Li remove(List<AttributeInfo> attributes, String name)221*f1fbf3c2SXin Li static synchronized AttributeInfo remove(List<AttributeInfo> attributes, String name) { 222*f1fbf3c2SXin Li if (attributes == null) 223*f1fbf3c2SXin Li return null; 224*f1fbf3c2SXin Li 225*f1fbf3c2SXin Li for (AttributeInfo ai:attributes) 226*f1fbf3c2SXin Li if (ai.getName().equals(name)) 227*f1fbf3c2SXin Li if (attributes.remove(ai)) 228*f1fbf3c2SXin Li return ai; 229*f1fbf3c2SXin Li 230*f1fbf3c2SXin Li return null; 231*f1fbf3c2SXin Li } 232*f1fbf3c2SXin Li writeAll(List<AttributeInfo> attributes, DataOutputStream out)233*f1fbf3c2SXin Li static void writeAll(List<AttributeInfo> attributes, DataOutputStream out) 234*f1fbf3c2SXin Li throws IOException 235*f1fbf3c2SXin Li { 236*f1fbf3c2SXin Li if (attributes == null) 237*f1fbf3c2SXin Li return; 238*f1fbf3c2SXin Li 239*f1fbf3c2SXin Li for (AttributeInfo attr:attributes) 240*f1fbf3c2SXin Li attr.write(out); 241*f1fbf3c2SXin Li } 242*f1fbf3c2SXin Li copyAll(List<AttributeInfo> attributes, ConstPool cp)243*f1fbf3c2SXin Li static List<AttributeInfo> copyAll(List<AttributeInfo> attributes, ConstPool cp) { 244*f1fbf3c2SXin Li if (attributes == null) 245*f1fbf3c2SXin Li return null; 246*f1fbf3c2SXin Li 247*f1fbf3c2SXin Li List<AttributeInfo> newList = new ArrayList<AttributeInfo>(); 248*f1fbf3c2SXin Li for (AttributeInfo attr:attributes) 249*f1fbf3c2SXin Li newList.add(attr.copy(cp, null)); 250*f1fbf3c2SXin Li 251*f1fbf3c2SXin Li return newList; 252*f1fbf3c2SXin Li } 253*f1fbf3c2SXin Li 254*f1fbf3c2SXin Li /* The following two methods are used to implement 255*f1fbf3c2SXin Li * ClassFile.renameClass(). 256*f1fbf3c2SXin Li * Only CodeAttribute, LocalVariableAttribute, 257*f1fbf3c2SXin Li * AnnotationsAttribute, and SignatureAttribute 258*f1fbf3c2SXin Li * override these methods. 259*f1fbf3c2SXin Li */ renameClass(String oldname, String newname)260*f1fbf3c2SXin Li void renameClass(String oldname, String newname) {} renameClass(Map<String,String> classnames)261*f1fbf3c2SXin Li void renameClass(Map<String,String> classnames) {} 262*f1fbf3c2SXin Li renameClass(List<AttributeInfo> attributes, String oldname, String newname)263*f1fbf3c2SXin Li static void renameClass(List<AttributeInfo> attributes, String oldname, String newname) { 264*f1fbf3c2SXin Li if (attributes == null) 265*f1fbf3c2SXin Li return; 266*f1fbf3c2SXin Li 267*f1fbf3c2SXin Li for (AttributeInfo ai:attributes) 268*f1fbf3c2SXin Li ai.renameClass(oldname, newname); 269*f1fbf3c2SXin Li } 270*f1fbf3c2SXin Li renameClass(List<AttributeInfo> attributes, Map<String,String> classnames)271*f1fbf3c2SXin Li static void renameClass(List<AttributeInfo> attributes, Map<String,String> classnames) { 272*f1fbf3c2SXin Li if (attributes == null) 273*f1fbf3c2SXin Li return; 274*f1fbf3c2SXin Li 275*f1fbf3c2SXin Li for (AttributeInfo ai:attributes) 276*f1fbf3c2SXin Li ai.renameClass(classnames); 277*f1fbf3c2SXin Li } 278*f1fbf3c2SXin Li getRefClasses(Map<String,String> classnames)279*f1fbf3c2SXin Li void getRefClasses(Map<String,String> classnames) {} 280*f1fbf3c2SXin Li getRefClasses(List<AttributeInfo> attributes, Map<String,String> classnames)281*f1fbf3c2SXin Li static void getRefClasses(List<AttributeInfo> attributes, Map<String,String> classnames) { 282*f1fbf3c2SXin Li if (attributes == null) 283*f1fbf3c2SXin Li return; 284*f1fbf3c2SXin Li 285*f1fbf3c2SXin Li for (AttributeInfo ai:attributes) 286*f1fbf3c2SXin Li ai.getRefClasses(classnames); 287*f1fbf3c2SXin Li } 288*f1fbf3c2SXin Li } 289