1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * ASM: a very small and fast Java bytecode manipulation framework
  32  * Copyright (c) 2000-2011 INRIA, France Telecom
  33  * All rights reserved.
  34  *
  35  * Redistribution and use in source and binary forms, with or without
  36  * modification, are permitted provided that the following conditions
  37  * are met:
  38  * 1. Redistributions of source code must retain the above copyright
  39  *    notice, this list of conditions and the following disclaimer.
  40  * 2. Redistributions in binary form must reproduce the above copyright
  41  *    notice, this list of conditions and the following disclaimer in the
  42  *    documentation and/or other materials provided with the distribution.
  43  * 3. Neither the name of the copyright holders nor the names of its
  44  *    contributors may be used to endorse or promote products derived from
  45  *    this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 package jdk.internal.org.objectweb.asm;
  60 
  61 import java.util.Arrays;
  62 
  63 /**
  64  * A non standard class, field, method or code attribute.
  65  *
  66  * @author Eric Bruneton
  67  * @author Eugene Kuleshov
  68  */
  69 public class Attribute {
  70 
  71     /**
  72      * The type of this attribute.
  73      */
  74     public final String type;
  75 
  76     /**
  77      * The raw value of this attribute, used only for unknown attributes.
  78      */
  79     byte[] value;
  80 
  81     /**
  82      * The next attribute in this attribute list. May be <tt>null</tt>.
  83      */
  84     Attribute next;
  85 
  86     /**
  87      * Constructs a new empty attribute.
  88      *
  89      * @param type
  90      *            the type of the attribute.
  91      */
  92     protected Attribute(final String type) {
  93         this.type = type;
  94     }
  95 
  96     /**
  97      * Returns <tt>true</tt> if this type of attribute is unknown. The default
  98      * implementation of this method always returns <tt>true</tt>.
  99      *
 100      * @return <tt>true</tt> if this type of attribute is unknown.
 101      */
 102     public boolean isUnknown() {
 103         return true;
 104     }
 105 
 106     /**
 107      * Returns <tt>true</tt> if this type of attribute is a code attribute.
 108      *
 109      * @return <tt>true</tt> if this type of attribute is a code attribute.
 110      */
 111     public boolean isCodeAttribute() {
 112         return false;
 113     }
 114 
 115     /**
 116      * Returns the labels corresponding to this attribute.
 117      *
 118      * @return the labels corresponding to this attribute, or <tt>null</tt> if
 119      *         this attribute is not a code attribute that contains labels.
 120      */
 121     protected Label[] getLabels() {
 122         return null;
 123     }
 124 
 125     /**
 126      * Reads a {@link #type type} attribute. This method must return a
 127      * <i>new</i> {@link Attribute} object, of type {@link #type type},
 128      * corresponding to the <tt>len</tt> bytes starting at the given offset, in
 129      * the given class reader.
 130      *
 131      * @param cr
 132      *            the class that contains the attribute to be read.
 133      * @param off
 134      *            index of the first byte of the attribute's content in
 135      *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,
 136      *            containing the type and the length of the attribute, are not
 137      *            taken into account here.
 138      * @param len
 139      *            the length of the attribute's content.
 140      * @param buf
 141      *            buffer to be used to call {@link ClassReader#readUTF8
 142      *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
 143      *            or {@link ClassReader#readConst readConst}.
 144      * @param codeOff
 145      *            index of the first byte of code's attribute content in
 146      *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read
 147      *            is not a code attribute. The 6 attribute header bytes,
 148      *            containing the type and the length of the attribute, are not
 149      *            taken into account here.
 150      * @param labels
 151      *            the labels of the method's code, or <tt>null</tt> if the
 152      *            attribute to be read is not a code attribute.
 153      * @return a <i>new</i> {@link Attribute} object corresponding to the given
 154      *         bytes.
 155      */
 156     protected Attribute read(final ClassReader cr, final int off,
 157             final int len, final char[] buf, final int codeOff,
 158             final Label[] labels) {
 159         Attribute attr = new Attribute(type);
 160         attr.value = new byte[len];
 161         System.arraycopy(cr.b, off, attr.value, 0, len);
 162         return attr;
 163     }
 164 
 165     /**
 166      * Returns the byte array form of this attribute.
 167      *
 168      * @param cw
 169      *            the class to which this attribute must be added. This
 170      *            parameter can be used to add to the constant pool of this
 171      *            class the items that corresponds to this attribute.
 172      * @param code
 173      *            the bytecode of the method corresponding to this code
 174      *            attribute, or <tt>null</tt> if this attribute is not a code
 175      *            attributes.
 176      * @param len
 177      *            the length of the bytecode of the method corresponding to this
 178      *            code attribute, or <tt>null</tt> if this attribute is not a
 179      *            code attribute.
 180      * @param maxStack
 181      *            the maximum stack size of the method corresponding to this
 182      *            code attribute, or -1 if this attribute is not a code
 183      *            attribute.
 184      * @param maxLocals
 185      *            the maximum number of local variables of the method
 186      *            corresponding to this code attribute, or -1 if this attribute
 187      *            is not a code attribute.
 188      * @return the byte array form of this attribute.
 189      */
 190     protected ByteVector write(final ClassWriter cw, final byte[] code,
 191             final int len, final int maxStack, final int maxLocals) {
 192         ByteVector v = new ByteVector();
 193         v.data = value;
 194         v.length = value.length;
 195         return v;
 196     }
 197 
 198     /**
 199      * Returns the length of the attribute list that begins with this attribute.
 200      *
 201      * @return the length of the attribute list that begins with this attribute.
 202      */
 203     final int getCount() {
 204         int count = 0;
 205         Attribute attr = this;
 206         while (attr != null) {
 207             count += 1;
 208             attr = attr.next;
 209         }
 210         return count;
 211     }
 212 
 213     /**
 214      * Returns the size of all the attributes in this attribute list.
 215      *
 216      * @param cw
 217      *            the class writer to be used to convert the attributes into
 218      *            byte arrays, with the {@link #write write} method.
 219      * @param code
 220      *            the bytecode of the method corresponding to these code
 221      *            attributes, or <tt>null</tt> if these attributes are not code
 222      *            attributes.
 223      * @param len
 224      *            the length of the bytecode of the method corresponding to
 225      *            these code attributes, or <tt>null</tt> if these attributes
 226      *            are not code attributes.
 227      * @param maxStack
 228      *            the maximum stack size of the method corresponding to these
 229      *            code attributes, or -1 if these attributes are not code
 230      *            attributes.
 231      * @param maxLocals
 232      *            the maximum number of local variables of the method
 233      *            corresponding to these code attributes, or -1 if these
 234      *            attributes are not code attributes.
 235      * @return the size of all the attributes in this attribute list. This size
 236      *         includes the size of the attribute headers.
 237      */
 238     final int getSize(final ClassWriter cw, final byte[] code, final int len,
 239             final int maxStack, final int maxLocals) {
 240         Attribute attr = this;
 241         int size = 0;
 242         while (attr != null) {
 243             cw.newUTF8(attr.type);
 244             size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
 245             attr = attr.next;
 246         }
 247         return size;
 248     }
 249 
 250     /**
 251      * Writes all the attributes of this attribute list in the given byte
 252      * vector.
 253      *
 254      * @param cw
 255      *            the class writer to be used to convert the attributes into
 256      *            byte arrays, with the {@link #write write} method.
 257      * @param code
 258      *            the bytecode of the method corresponding to these code
 259      *            attributes, or <tt>null</tt> if these attributes are not code
 260      *            attributes.
 261      * @param len
 262      *            the length of the bytecode of the method corresponding to
 263      *            these code attributes, or <tt>null</tt> if these attributes
 264      *            are not code attributes.
 265      * @param maxStack
 266      *            the maximum stack size of the method corresponding to these
 267      *            code attributes, or -1 if these attributes are not code
 268      *            attributes.
 269      * @param maxLocals
 270      *            the maximum number of local variables of the method
 271      *            corresponding to these code attributes, or -1 if these
 272      *            attributes are not code attributes.
 273      * @param out
 274      *            where the attributes must be written.
 275      */
 276     final void put(final ClassWriter cw, final byte[] code, final int len,
 277             final int maxStack, final int maxLocals, final ByteVector out) {
 278         Attribute attr = this;
 279         while (attr != null) {
 280             ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
 281             out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
 282             out.putByteArray(b.data, 0, b.length);
 283             attr = attr.next;
 284         }
 285     }
 286 
 287     //The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely removed.
 288     //see also changes in ClassReader.accept.
 289 
 290     public static class NestMembers extends Attribute {
 291         public NestMembers() {
 292             super("NestMembers");
 293         }
 294 
 295         byte[] bytes;
 296         String[] classes;
 297 
 298         @Override
 299         protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
 300             int offset = off;
 301             NestMembers a = new NestMembers();
 302             int size = cr.readShort(off);
 303             a.classes = new String[size];
 304             off += 2;
 305             for (int i = 0; i < size ; i++) {
 306                 a.classes[i] = cr.readClass(off, buf);
 307                 off += 2;
 308             }
 309             a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
 310             return a;
 311         }
 312 
 313         @Override
 314         protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
 315             ByteVector v = new ByteVector(bytes.length);
 316             v.putShort(classes.length);
 317             for (String s : classes) {
 318                 v.putShort(cw.newClass(s));
 319             }
 320             return v;
 321         }
 322     }
 323 
 324     public static class MemberOfNest extends Attribute {
 325 
 326         byte[] bytes;
 327         String clazz;
 328 
 329         public MemberOfNest() {
 330             super("MemberOfNest");
 331         }
 332 
 333         @Override
 334         protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
 335             int offset = off;
 336             MemberOfNest a = new MemberOfNest();
 337             a.clazz = cr.readClass(off, buf);
 338             a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
 339             return a;
 340         }
 341 
 342         @Override
 343         protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
 344             ByteVector v = new ByteVector(bytes.length);
 345             v.putShort(cw.newClass(clazz));
 346             return v;
 347         }
 348     }
 349 
 350     static final Attribute[] DEFAULT_ATTRIBUTE_PROTOS = new Attribute[] {
 351         new NestMembers(),
 352         new MemberOfNest()
 353     };
 354 }