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