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 */ 019 020package org.apache.bcel.classfile; 021 022import java.io.DataInput; 023import java.io.DataOutputStream; 024import java.io.IOException; 025import java.util.Iterator; 026import java.util.stream.Stream; 027 028import org.apache.bcel.Const; 029 030/** 031 * This class represents a BootstrapMethods attribute. 032 * 033 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format : 034 * The BootstrapMethods Attribute</a> 035 * @since 6.0 036 */ 037public class BootstrapMethods extends Attribute implements Iterable<BootstrapMethod> { 038 039 private BootstrapMethod[] bootstrapMethods; // TODO this could be made final (setter is not used) 040 041 /** 042 * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a 043 * physical copy. 044 * 045 * @param c Source to copy. 046 */ 047 public BootstrapMethods(final BootstrapMethods c) { 048 this(c.getNameIndex(), c.getLength(), c.getBootstrapMethods(), c.getConstantPool()); 049 } 050 051 /** 052 * Constructs a BootstrapMethods attribute. 053 * 054 * @param nameIndex Index in constant pool to CONSTANT_Utf8. 055 * @param length Content length in bytes. 056 * @param bootstrapMethods array of bootstrap methods. 057 * @param constantPool Array of constants. 058 */ 059 public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) { 060 super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, constantPool); 061 setBootstrapMethods(bootstrapMethods); 062 } 063 064 /** 065 * Constructs object from Input stream. 066 * 067 * @param nameIndex Index in constant pool to CONSTANT_Utf8. 068 * @param length Content length in bytes. 069 * @param input Input stream. 070 * @param constantPool Array of constants. 071 * @throws IOException if an I/O error occurs. 072 */ 073 BootstrapMethods(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { 074 this(nameIndex, length, (BootstrapMethod[]) null, constantPool); 075 076 final int numBootstrapMethods = input.readUnsignedShort(); 077 bootstrapMethods = new BootstrapMethod[numBootstrapMethods]; 078 for (int i = 0; i < numBootstrapMethods; i++) { 079 bootstrapMethods[i] = new BootstrapMethod(input); 080 } 081 } 082 083 /** 084 * Accepts a visitor. 085 * 086 * @param v Visitor object. 087 */ 088 @Override 089 public void accept(final Visitor v) { 090 v.visitBootstrapMethods(this); 091 } 092 093 /** 094 * Creates a deep copy of this attribute. 095 * 096 * @param constantPool the constant pool. 097 * @return deep copy of this attribute. 098 */ 099 @Override 100 public BootstrapMethods copy(final ConstantPool constantPool) { 101 final BootstrapMethods c = (BootstrapMethods) clone(); 102 c.bootstrapMethods = new BootstrapMethod[bootstrapMethods.length]; 103 104 for (int i = 0; i < bootstrapMethods.length; i++) { 105 c.bootstrapMethods[i] = bootstrapMethods[i].copy(); 106 } 107 c.setConstantPool(constantPool); 108 return c; 109 } 110 111 /** 112 * Dumps bootstrap methods attribute to file stream in binary format. 113 * 114 * @param file Output file stream. 115 * @throws IOException if an I/O error occurs. 116 */ 117 @Override 118 public final void dump(final DataOutputStream file) throws IOException { 119 super.dump(file); 120 121 file.writeShort(bootstrapMethods.length); 122 for (final BootstrapMethod bootstrapMethod : bootstrapMethods) { 123 bootstrapMethod.dump(file); 124 } 125 } 126 127 /** 128 * Gets the array of bootstrap method records. 129 * 130 * @return array of bootstrap method records. 131 */ 132 public final BootstrapMethod[] getBootstrapMethods() { 133 return bootstrapMethods; 134 } 135 136 @Override 137 public Iterator<BootstrapMethod> iterator() { 138 return Stream.of(bootstrapMethods).iterator(); 139 } 140 141 /** 142 * Sets the bootstrap methods. 143 * 144 * @param bootstrapMethods the array of bootstrap methods. 145 */ 146 public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) { 147 this.bootstrapMethods = bootstrapMethods != null ? bootstrapMethods : BootstrapMethod.EMPTY_ARRAY; 148 } 149 150 /** 151 * @return String representation. 152 */ 153 @Override 154 public final String toString() { 155 final StringBuilder buf = new StringBuilder(); 156 buf.append("BootstrapMethods("); 157 buf.append(bootstrapMethods.length); 158 buf.append("):"); 159 for (int i = 0; i < bootstrapMethods.length; i++) { 160 buf.append("\n"); 161 final int start = buf.length(); 162 buf.append(" ").append(i).append(": "); 163 final int indentCount = buf.length() - start; 164 final String[] lines = bootstrapMethods[i].toString(super.getConstantPool()).split("\\r?\\n"); 165 buf.append(lines[0]); 166 for (int j = 1; j < lines.length; j++) { 167 buf.append("\n").append(" ", 0, indentCount).append(lines[j]); 168 } 169 } 170 return buf.toString(); 171 } 172}