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; 028 029/** 030 * base class for annotations 031 * 032 * @since 6.0 033 */ 034public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> { 035 036 private AnnotationEntry[] annotationTable; 037 private final boolean isRuntimeVisible; 038 039 /** 040 * Constructs an instance. 041 * 042 * @param annotationType the subclass type of the annotation 043 * @param nameIndex Index pointing to the name <em>Code</em> 044 * @param length Content length in bytes 045 * @param annotationTable the actual annotations 046 * @param constantPool Array of constants 047 * @param isRuntimeVisible whether this Annotation visible at runtime 048 */ 049 public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable, 050 final ConstantPool constantPool, final boolean isRuntimeVisible) { 051 super(annotationType, nameIndex, length, constantPool); 052 setAnnotationTable(annotationTable); 053 this.isRuntimeVisible = isRuntimeVisible; 054 } 055 056 /** 057 * Constructs an instance. 058 * 059 * @param annotationType the subclass type of the annotation 060 * @param nameIndex Index pointing to the name <em>Code</em> 061 * @param length Content length in bytes 062 * @param input Input stream 063 * @param constantPool Array of constants 064 * @param isRuntimeVisible whether this Annotation visible at runtime 065 * @throws IOException if an I/O error occurs. 066 */ 067 Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool, 068 final boolean isRuntimeVisible) throws IOException { 069 this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible); 070 final int annotationTableLength = input.readUnsignedShort(); 071 annotationTable = new AnnotationEntry[annotationTableLength]; 072 for (int i = 0; i < annotationTableLength; i++) { 073 annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible); 074 } 075 } 076 077 /** 078 * Called by objects that are traversing the nodes of the tree implicitly 079 * defined by the contents of a Java class. I.e., the hierarchy of methods, 080 * fields, attributes, etc. spawns a tree of objects. 081 * 082 * @param v Visitor object 083 */ 084 @Override 085 public void accept(final Visitor v) { 086 v.visitAnnotation(this); 087 } 088 089 @Override 090 public Attribute copy(final ConstantPool constantPool) { 091 // TODO Auto-generated method stub 092 return null; 093 } 094 095 /** 096 * Gets the array of annotation entries in this annotation 097 */ 098 public AnnotationEntry[] getAnnotationEntries() { 099 return annotationTable; 100 } 101 102 /** 103 * Gets the number of annotation entries in this annotation. 104 * 105 * @return the number of annotation entries in this annotation 106 */ 107 public final int getNumAnnotations() { 108 return annotationTable.length; 109 } 110 111 public boolean isRuntimeVisible() { 112 return isRuntimeVisible; 113 } 114 115 @Override 116 public Iterator<AnnotationEntry> iterator() { 117 return Stream.of(annotationTable).iterator(); 118 } 119 120 /** 121 * Sets the entries to set in this annotation. 122 * 123 * @param annotationTable the entries to set in this annotation 124 */ 125 public final void setAnnotationTable(final AnnotationEntry[] annotationTable) { 126 this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY; 127 } 128 129 /** 130 * Converts to a String representation. 131 * 132 * @return String representation 133 */ 134 @Override 135 public final String toString() { 136 final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag())); 137 buf.append(":\n"); 138 for (int i = 0; i < annotationTable.length; i++) { 139 buf.append(" ").append(annotationTable[i]); 140 if (i < annotationTable.length - 1) { 141 buf.append('\n'); 142 } 143 } 144 return buf.toString(); 145 } 146 147 protected void writeAnnotations(final DataOutputStream dos) throws IOException { 148 dos.writeShort(annotationTable.length); 149 for (final AnnotationEntry element : annotationTable) { 150 element.dump(dos); 151 } 152 } 153 154}