001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.springframework.asm; 031 032/** 033 * A non standard class, field, method or code attribute. 034 * 035 * @author Eric Bruneton 036 * @author Eugene Kuleshov 037 */ 038public class Attribute { 039 040 /** 041 * The type of this attribute. 042 */ 043 public final String type; 044 045 /** 046 * The raw value of this attribute, used only for unknown attributes. 047 */ 048 byte[] value; 049 050 /** 051 * The next attribute in this attribute list. May be <tt>null</tt>. 052 */ 053 Attribute next; 054 055 /** 056 * Constructs a new empty attribute. 057 * 058 * @param type 059 * the type of the attribute. 060 */ 061 protected Attribute(final String type) { 062 this.type = type; 063 } 064 065 /** 066 * Returns <tt>true</tt> if this type of attribute is unknown. The default 067 * implementation of this method always returns <tt>true</tt>. 068 * 069 * @return <tt>true</tt> if this type of attribute is unknown. 070 */ 071 public boolean isUnknown() { 072 return true; 073 } 074 075 /** 076 * Returns <tt>true</tt> if this type of attribute is a code attribute. 077 * 078 * @return <tt>true</tt> if this type of attribute is a code attribute. 079 */ 080 public boolean isCodeAttribute() { 081 return false; 082 } 083 084 /** 085 * Returns the labels corresponding to this attribute. 086 * 087 * @return the labels corresponding to this attribute, or <tt>null</tt> if 088 * this attribute is not a code attribute that contains labels. 089 */ 090 protected Label[] getLabels() { 091 return null; 092 } 093 094 /** 095 * Reads a {@link #type type} attribute. This method must return a 096 * <i>new</i> {@link Attribute} object, of type {@link #type type}, 097 * corresponding to the <tt>len</tt> bytes starting at the given offset, in 098 * the given class reader. 099 * 100 * @param cr 101 * the class that contains the attribute to be read. 102 * @param off 103 * index of the first byte of the attribute's content in 104 * {@link ClassReader#b cr.b}. The 6 attribute header bytes, 105 * containing the type and the length of the attribute, are not 106 * taken into account here. 107 * @param len 108 * the length of the attribute's content. 109 * @param buf 110 * buffer to be used to call {@link ClassReader#readUTF8 111 * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} 112 * or {@link ClassReader#readConst readConst}. 113 * @param codeOff 114 * index of the first byte of code's attribute content in 115 * {@link ClassReader#b cr.b}, or -1 if the attribute to be read 116 * is not a code attribute. The 6 attribute header bytes, 117 * containing the type and the length of the attribute, are not 118 * taken into account here. 119 * @param labels 120 * the labels of the method's code, or <tt>null</tt> if the 121 * attribute to be read is not a code attribute. 122 * @return a <i>new</i> {@link Attribute} object corresponding to the given 123 * bytes. 124 */ 125 protected Attribute read(final ClassReader cr, final int off, 126 final int len, final char[] buf, final int codeOff, 127 final Label[] labels) { 128 Attribute attr = new Attribute(type); 129 attr.value = new byte[len]; 130 System.arraycopy(cr.b, off, attr.value, 0, len); 131 return attr; 132 } 133 134 /** 135 * Returns the byte array form of this attribute. 136 * 137 * @param cw 138 * the class to which this attribute must be added. This 139 * parameter can be used to add to the constant pool of this 140 * class the items that corresponds to this attribute. 141 * @param code 142 * the bytecode of the method corresponding to this code 143 * attribute, or <tt>null</tt> if this attribute is not a code 144 * attributes. 145 * @param len 146 * the length of the bytecode of the method corresponding to this 147 * code attribute, or <tt>null</tt> if this attribute is not a 148 * code attribute. 149 * @param maxStack 150 * the maximum stack size of the method corresponding to this 151 * code attribute, or -1 if this attribute is not a code 152 * attribute. 153 * @param maxLocals 154 * the maximum number of local variables of the method 155 * corresponding to this code attribute, or -1 if this attribute 156 * is not a code attribute. 157 * @return the byte array form of this attribute. 158 */ 159 protected ByteVector write(final ClassWriter cw, final byte[] code, 160 final int len, final int maxStack, final int maxLocals) { 161 ByteVector v = new ByteVector(); 162 v.data = value; 163 v.length = value.length; 164 return v; 165 } 166 167 /** 168 * Returns the length of the attribute list that begins with this attribute. 169 * 170 * @return the length of the attribute list that begins with this attribute. 171 */ 172 final int getCount() { 173 int count = 0; 174 Attribute attr = this; 175 while (attr != null) { 176 count += 1; 177 attr = attr.next; 178 } 179 return count; 180 } 181 182 /** 183 * Returns the size of all the attributes in this attribute list. 184 * 185 * @param cw 186 * the class writer to be used to convert the attributes into 187 * byte arrays, with the {@link #write write} method. 188 * @param code 189 * the bytecode of the method corresponding to these code 190 * attributes, or <tt>null</tt> if these attributes are not code 191 * attributes. 192 * @param len 193 * the length of the bytecode of the method corresponding to 194 * these code attributes, or <tt>null</tt> if these attributes 195 * are not code attributes. 196 * @param maxStack 197 * the maximum stack size of the method corresponding to these 198 * code attributes, or -1 if these attributes are not code 199 * attributes. 200 * @param maxLocals 201 * the maximum number of local variables of the method 202 * corresponding to these code attributes, or -1 if these 203 * attributes are not code attributes. 204 * @return the size of all the attributes in this attribute list. This size 205 * includes the size of the attribute headers. 206 */ 207 final int getSize(final ClassWriter cw, final byte[] code, final int len, 208 final int maxStack, final int maxLocals) { 209 Attribute attr = this; 210 int size = 0; 211 while (attr != null) { 212 cw.newUTF8(attr.type); 213 size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; 214 attr = attr.next; 215 } 216 return size; 217 } 218 219 /** 220 * Writes all the attributes of this attribute list in the given byte 221 * vector. 222 * 223 * @param cw 224 * the class writer to be used to convert the attributes into 225 * byte arrays, with the {@link #write write} method. 226 * @param code 227 * the bytecode of the method corresponding to these code 228 * attributes, or <tt>null</tt> if these attributes are not code 229 * attributes. 230 * @param len 231 * the length of the bytecode of the method corresponding to 232 * these code attributes, or <tt>null</tt> if these attributes 233 * are not code attributes. 234 * @param maxStack 235 * the maximum stack size of the method corresponding to these 236 * code attributes, or -1 if these attributes are not code 237 * attributes. 238 * @param maxLocals 239 * the maximum number of local variables of the method 240 * corresponding to these code attributes, or -1 if these 241 * attributes are not code attributes. 242 * @param out 243 * where the attributes must be written. 244 */ 245 final void put(final ClassWriter cw, final byte[] code, final int len, 246 final int maxStack, final int maxLocals, final ByteVector out) { 247 Attribute attr = this; 248 while (attr != null) { 249 ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); 250 out.putShort(cw.newUTF8(attr.type)).putInt(b.length); 251 out.putByteArray(b.data, 0, b.length); 252 attr = attr.next; 253 } 254 } 255}