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