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