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 * @return the array of annotation entries in this annotation. 099 */ 100 public AnnotationEntry[] getAnnotationEntries() { 101 return annotationTable; 102 } 103 104 /** 105 * Gets the number of annotation entries in this annotation. 106 * 107 * @return the number of annotation entries in this annotation. 108 */ 109 public final int getNumAnnotations() { 110 return annotationTable.length; 111 } 112 113 /** 114 * Gets whether this annotation is runtime visible. 115 * 116 * @return true if this annotation is runtime visible. 117 */ 118 public boolean isRuntimeVisible() { 119 return isRuntimeVisible; 120 } 121 122 @Override 123 public Iterator<AnnotationEntry> iterator() { 124 return Stream.of(annotationTable).iterator(); 125 } 126 127 /** 128 * Sets the entries to set in this annotation. 129 * 130 * @param annotationTable the entries to set in this annotation. 131 */ 132 public final void setAnnotationTable(final AnnotationEntry[] annotationTable) { 133 this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY; 134 } 135 136 /** 137 * Converts to a String representation. 138 * 139 * @return String representation. 140 */ 141 @Override 142 public final String toString() { 143 final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag())); 144 buf.append(":\n"); 145 for (int i = 0; i < annotationTable.length; i++) { 146 buf.append(" ").append(annotationTable[i]); 147 if (i < annotationTable.length - 1) { 148 buf.append('\n'); 149 } 150 } 151 return buf.toString(); 152 } 153 154 /** 155 * Writes the annotations to a DataOutputStream. 156 * 157 * @param dos the data output stream. 158 * @throws IOException if an I/O error occurs. 159 */ 160 protected void writeAnnotations(final DataOutputStream dos) throws IOException { 161 dos.writeShort(annotationTable.length); 162 for (final AnnotationEntry element : annotationTable) { 163 element.dump(dos); 164 } 165 } 166 167}