/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2011 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package jdk.internal.org.objectweb.asm;

An AnnotationVisitor that generates annotations in bytecode form.
Author:Eric Bruneton, Eugene Kuleshov
/** * An {@link AnnotationVisitor} that generates annotations in bytecode form. * * @author Eric Bruneton * @author Eugene Kuleshov */
final class AnnotationWriter extends AnnotationVisitor {
The class writer to which this annotation must be added.
/** * The class writer to which this annotation must be added. */
private final ClassWriter cw;
The number of values in this annotation.
/** * The number of values in this annotation. */
private int size;
true if values are named, false otherwise. Annotation writers used for annotation default and annotation arrays use unnamed values.
/** * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation * writers used for annotation default and annotation arrays use unnamed * values. */
private final boolean named;
The annotation values in bytecode form. This byte vector only contains the values themselves, i.e. the number of values must be stored as a unsigned short just before these bytes.
/** * The annotation values in bytecode form. This byte vector only contains * the values themselves, i.e. the number of values must be stored as a * unsigned short just before these bytes. */
private final ByteVector bv;
The byte vector to be used to store the number of values of this annotation. See bv.
/** * The byte vector to be used to store the number of values of this * annotation. See {@link #bv}. */
private final ByteVector parent;
Where the number of values of this annotation must be stored in parent.
/** * Where the number of values of this annotation must be stored in * {@link #parent}. */
private final int offset;
Next annotation writer. This field is used to store annotation lists.
/** * Next annotation writer. This field is used to store annotation lists. */
AnnotationWriter next;
Previous annotation writer. This field is used to store annotation lists.
/** * Previous annotation writer. This field is used to store annotation lists. */
AnnotationWriter prev; // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------
Constructs a new AnnotationWriter.
Params:
  • cw – the class writer to which this annotation must be added.
  • named – true if values are named, false otherwise.
  • bv – where the annotation values must be stored.
  • parent – where the number of annotation values must be stored.
  • offset – where in parent the number of annotation values must be stored.
/** * Constructs a new {@link AnnotationWriter}. * * @param cw * the class writer to which this annotation must be added. * @param named * <tt>true<tt> if values are named, <tt>false</tt> otherwise. * @param bv * where the annotation values must be stored. * @param parent * where the number of annotation values must be stored. * @param offset * where in <tt>parent</tt> the number of annotation values must * be stored. */
AnnotationWriter(final ClassWriter cw, final boolean named, final ByteVector bv, final ByteVector parent, final int offset) { super(Opcodes.ASM5); this.cw = cw; this.named = named; this.bv = bv; this.parent = parent; this.offset = offset; } // ------------------------------------------------------------------------ // Implementation of the AnnotationVisitor abstract class // ------------------------------------------------------------------------ @Override public void visit(final String name, final Object value) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } if (value instanceof String) { bv.put12('s', cw.newUTF8((String) value)); } else if (value instanceof Byte) { bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); } else if (value instanceof Boolean) { int v = ((Boolean) value).booleanValue() ? 1 : 0; bv.put12('Z', cw.newInteger(v).index); } else if (value instanceof Character) { bv.put12('C', cw.newInteger(((Character) value).charValue()).index); } else if (value instanceof Short) { bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); } else if (value instanceof Type) { bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); } else if (value instanceof byte[]) { byte[] v = (byte[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('B', cw.newInteger(v[i]).index); } } else if (value instanceof boolean[]) { boolean[] v = (boolean[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); } } else if (value instanceof short[]) { short[] v = (short[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('S', cw.newInteger(v[i]).index); } } else if (value instanceof char[]) { char[] v = (char[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('C', cw.newInteger(v[i]).index); } } else if (value instanceof int[]) { int[] v = (int[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('I', cw.newInteger(v[i]).index); } } else if (value instanceof long[]) { long[] v = (long[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('J', cw.newLong(v[i]).index); } } else if (value instanceof float[]) { float[] v = (float[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('F', cw.newFloat(v[i]).index); } } else if (value instanceof double[]) { double[] v = (double[]) value; bv.put12('[', v.length); for (int i = 0; i < v.length; i++) { bv.put12('D', cw.newDouble(v[i]).index); } } else { Item i = cw.newConstItem(value); bv.put12(".s.IFJDCS".charAt(i.type), i.index); } } @Override public void visitEnum(final String name, final String desc, final String value) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); } @Override public AnnotationVisitor visitAnnotation(final String name, final String desc) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } // write tag and type, and reserve space for values count bv.put12('@', cw.newUTF8(desc)).putShort(0); return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); } @Override public AnnotationVisitor visitArray(final String name) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } // write tag, and reserve space for array size bv.put12('[', 0); return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); } @Override public void visitEnd() { if (parent != null) { byte[] data = parent.data; data[offset] = (byte) (size >>> 8); data[offset + 1] = (byte) size; } } // ------------------------------------------------------------------------ // Utility methods // ------------------------------------------------------------------------
Returns the size of this annotation writer list.
Returns:the size of this annotation writer list.
/** * Returns the size of this annotation writer list. * * @return the size of this annotation writer list. */
int getSize() { int size = 0; AnnotationWriter aw = this; while (aw != null) { size += aw.bv.length; aw = aw.next; } return size; }
Puts the annotations of this annotation writer list into the given byte vector.
Params:
  • out – where the annotations must be put.
/** * Puts the annotations of this annotation writer list into the given byte * vector. * * @param out * where the annotations must be put. */
void put(final ByteVector out) { int n = 0; int size = 2; AnnotationWriter aw = this; AnnotationWriter last = null; while (aw != null) { ++n; size += aw.bv.length; aw.visitEnd(); // in case user forgot to call visitEnd aw.prev = last; last = aw; aw = aw.next; } out.putInt(size); out.putShort(n); aw = last; while (aw != null) { out.putByteArray(aw.bv.data, 0, aw.bv.length); aw = aw.prev; } }
Puts the given annotation lists into the given byte vector.
Params:
  • panns – an array of annotation writer lists.
  • off – index of the first annotation to be written.
  • out – where the annotations must be put.
/** * Puts the given annotation lists into the given byte vector. * * @param panns * an array of annotation writer lists. * @param off * index of the first annotation to be written. * @param out * where the annotations must be put. */
static void put(final AnnotationWriter[] panns, final int off, final ByteVector out) { int size = 1 + 2 * (panns.length - off); for (int i = off; i < panns.length; ++i) { size += panns[i] == null ? 0 : panns[i].getSize(); } out.putInt(size).putByte(panns.length - off); for (int i = off; i < panns.length; ++i) { AnnotationWriter aw = panns[i]; AnnotationWriter last = null; int n = 0; while (aw != null) { ++n; aw.visitEnd(); // in case user forgot to call visitEnd aw.prev = last; last = aw; aw = aw.next; } out.putShort(n); aw = last; while (aw != null) { out.putByteArray(aw.bv.data, 0, aw.bv.length); aw = aw.prev; } } }
Puts the given type reference and type path into the given bytevector. LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
Params:
  • typeRef – a reference to the annotated type. See TypeReference.
  • typePath – the path to the annotated type argument, wildcard bound, array element type, or static inner type within 'typeRef'. May be null if the annotation targets 'typeRef' as a whole.
  • out – where the type reference and type path must be put.
/** * Puts the given type reference and type path into the given bytevector. * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. * * @param typeRef * a reference to the annotated type. See {@link TypeReference}. * @param typePath * the path to the annotated type argument, wildcard bound, array * element type, or static inner type within 'typeRef'. May be * <tt>null</tt> if the annotation targets 'typeRef' as a whole. * @param out * where the type reference and type path must be put. */
static void putTarget(int typeRef, TypePath typePath, ByteVector out) { switch (typeRef >>> 24) { case 0x00: // CLASS_TYPE_PARAMETER case 0x01: // METHOD_TYPE_PARAMETER case 0x16: // METHOD_FORMAL_PARAMETER out.putShort(typeRef >>> 16); break; case 0x13: // FIELD case 0x14: // METHOD_RETURN case 0x15: // METHOD_RECEIVER out.putByte(typeRef >>> 24); break; case 0x47: // CAST case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT out.putInt(typeRef); break; // case 0x10: // CLASS_EXTENDS // case 0x11: // CLASS_TYPE_PARAMETER_BOUND // case 0x12: // METHOD_TYPE_PARAMETER_BOUND // case 0x17: // THROWS // case 0x42: // EXCEPTION_PARAMETER // case 0x43: // INSTANCEOF // case 0x44: // NEW // case 0x45: // CONSTRUCTOR_REFERENCE // case 0x46: // METHOD_REFERENCE default: out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8); break; } if (typePath == null) { out.putByte(0); } else { int length = typePath.b[typePath.offset] * 2 + 1; out.putByteArray(typePath.b, typePath.offset, length); } } }