001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataOutputStream; 023import java.io.IOException; 024import java.util.Iterator; 025import java.util.stream.Stream; 026 027import org.apache.bcel.Const; 028import org.apache.bcel.util.Args; 029 030/** 031 * base class for annotations 032 * 033 * @since 6.0 034 */ 035public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> { 036 037 private AnnotationEntry[] annotationTable; 038 private final boolean isRuntimeVisible; 039 040 /** 041 * Constructs an instance. 042 * 043 * @param annotationType The subclass type of the annotation. 044 * @param nameIndex Index pointing to the name <em>Code</em>. 045 * @param length Content length in bytes. 046 * @param annotationTable The actual annotations. 047 * @param constantPool Array of constants. 048 * @param isRuntimeVisible whether this Annotation visible at runtime. 049 */ 050 public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable, 051 final ConstantPool constantPool, final boolean isRuntimeVisible) { 052 super(annotationType, nameIndex, length, constantPool); 053 setAnnotationTable(annotationTable); 054 this.isRuntimeVisible = isRuntimeVisible; 055 } 056 057 /** 058 * Constructs an instance. 059 * 060 * @param annotationType The subclass type of the annotation. 061 * @param nameIndex Index pointing to the name <em>Code</em>. 062 * @param length Content length in bytes. 063 * @param input Input stream. 064 * @param constantPool Array of constants. 065 * @param isRuntimeVisible whether this Annotation visible at runtime. 066 * @throws IOException Thrown if an I/O error occurs. 067 */ 068 Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool, 069 final boolean isRuntimeVisible) throws IOException { 070 this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible); 071 final int annotationTableLength = input.readUnsignedShort(); 072 annotationTable = new AnnotationEntry[annotationTableLength]; 073 for (int i = 0; i < annotationTableLength; i++) { 074 annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible); 075 } 076 } 077 078 /** 079 * Called by objects that are traversing the nodes of the tree implicitly 080 * defined by the contents of a Java class. I.e., the hierarchy of methods, 081 * fields, attributes, etc. spawns a tree of objects. 082 * 083 * @param v Visitor object. 084 */ 085 @Override 086 public void accept(final Visitor v) { 087 v.visitAnnotation(this); 088 } 089 090 @Override 091 public Attribute copy(final ConstantPool constantPool) { 092 // TODO Auto-generated method stub 093 return null; 094 } 095 096 /** 097 * Gets the array of annotation entries in this annotation. 098 * 099 * @return The array of annotation entries in this annotation. 100 */ 101 public AnnotationEntry[] getAnnotationEntries() { 102 return annotationTable; 103 } 104 105 /** 106 * Gets the number of annotation entries in this annotation. 107 * 108 * @return The number of annotation entries in this annotation. 109 */ 110 public final int getNumAnnotations() { 111 return annotationTable.length; 112 } 113 114 /** 115 * Gets whether this annotation is runtime visible. 116 * 117 * @return true if this annotation is runtime visible. 118 */ 119 public boolean isRuntimeVisible() { 120 return isRuntimeVisible; 121 } 122 123 @Override 124 public Iterator<AnnotationEntry> iterator() { 125 return Stream.of(annotationTable).iterator(); 126 } 127 128 /** 129 * Sets the entries to set in this annotation. 130 * 131 * @param annotationTable The entries to set in this annotation. 132 */ 133 public final void setAnnotationTable(final AnnotationEntry[] annotationTable) { 134 this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY; 135 } 136 137 /** 138 * Converts to a String representation. 139 * 140 * @return String representation. 141 */ 142 @Override 143 public final String toString() { 144 final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag())); 145 buf.append(":\n"); 146 for (int i = 0; i < annotationTable.length; i++) { 147 buf.append(" ").append(annotationTable[i]); 148 if (i < annotationTable.length - 1) { 149 buf.append('\n'); 150 } 151 } 152 return buf.toString(); 153 } 154 155 /** 156 * Writes the annotations to a DataOutputStream. 157 * 158 * @param dos The data output stream. 159 * @throws IOException Thrown if an I/O error occurs. 160 */ 161 protected void writeAnnotations(final DataOutputStream dos) throws IOException { 162 dos.writeShort(Args.requireU2(annotationTable.length, "annotationTable.length")); 163 for (final AnnotationEntry element : annotationTable) { 164 element.dump(dos); 165 } 166 } 167 168}