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; 023import java.util.Arrays; 024 025import org.apache.bcel.Const; 026 027/** 028 * This class represents a bootstrap method attribute, i.e., the bootstrap method ref, the number of bootstrap arguments 029 * and an array of the bootstrap arguments. 030 * 031 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format : 032 * The BootstrapMethods Attribute</a> 033 * @since 6.0 034 */ 035public class BootstrapMethod implements Cloneable { 036 037 /** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */ 038 private int bootstrapMethodRef; 039 040 /** Array of references to the constant_pool table */ 041 private int[] bootstrapArguments; 042 043 /** 044 * Initialize from another object. 045 * 046 * @param c Source to copy. 047 */ 048 public BootstrapMethod(final BootstrapMethod c) { 049 this(c.getBootstrapMethodRef(), c.getBootstrapArguments()); 050 } 051 052 /** 053 * Constructs object from input stream. 054 * 055 * @param input Input stream 056 * @throws IOException if an I/O error occurs. 057 */ 058 BootstrapMethod(final DataInput input) throws IOException { 059 this(input.readUnsignedShort(), input.readUnsignedShort()); 060 061 for (int i = 0; i < bootstrapArguments.length; i++) { 062 bootstrapArguments[i] = input.readUnsignedShort(); 063 } 064 } 065 066 // helper method 067 private BootstrapMethod(final int bootstrapMethodRef, final int numBootstrapArguments) { 068 this(bootstrapMethodRef, new int[numBootstrapArguments]); 069 } 070 071 /** 072 * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle 073 * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info 074 */ 075 public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArguments) { 076 this.bootstrapMethodRef = bootstrapMethodRef; 077 this.bootstrapArguments = bootstrapArguments; 078 } 079 080 /** 081 * @return deep copy of this object 082 */ 083 public BootstrapMethod copy() { 084 try { 085 return (BootstrapMethod) clone(); 086 } catch (final CloneNotSupportedException e) { 087 // TODO should this throw? 088 } 089 return null; 090 } 091 092 /** 093 * Dump object to file stream in binary format. 094 * 095 * @param file Output file stream 096 * @throws IOException if an I/O error occurs. 097 */ 098 public final void dump(final DataOutputStream file) throws IOException { 099 file.writeShort(bootstrapMethodRef); 100 file.writeShort(bootstrapArguments.length); 101 for (final int bootstrapArgument : bootstrapArguments) { 102 file.writeShort(bootstrapArgument); 103 } 104 } 105 106 /** 107 * @return int[] of bootstrap_method indices into constant_pool of CONSTANT_[type]_info 108 */ 109 public int[] getBootstrapArguments() { 110 return bootstrapArguments; 111 } 112 113 /** 114 * @return index into constant_pool of bootstrap_method 115 */ 116 public int getBootstrapMethodRef() { 117 return bootstrapMethodRef; 118 } 119 120 /** 121 * @return count of number of boostrap arguments 122 */ 123 public int getNumBootstrapArguments() { 124 return bootstrapArguments.length; 125 } 126 127 /** 128 * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info 129 */ 130 public void setBootstrapArguments(final int[] bootstrapArguments) { 131 this.bootstrapArguments = bootstrapArguments; 132 } 133 134 /** 135 * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle 136 */ 137 public void setBootstrapMethodRef(final int bootstrapMethodRef) { 138 this.bootstrapMethodRef = bootstrapMethodRef; 139 } 140 141 /** 142 * @return String representation. 143 */ 144 @Override 145 public final String toString() { 146 return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", " + Arrays.toString(bootstrapArguments) + ")"; 147 } 148 149 /** 150 * @return Resolved string representation 151 */ 152 public final String toString(final ConstantPool constantPool) { 153 final StringBuilder buf = new StringBuilder(); 154 final String bootstrapMethodName = constantPool.constantToString(bootstrapMethodRef, Const.CONSTANT_MethodHandle); 155 buf.append(Utility.compactClassName(bootstrapMethodName, false)); 156 final int bootstrapArgumentsLen = bootstrapArguments.length; 157 if (bootstrapArgumentsLen > 0) { 158 buf.append("\nMethod Arguments:"); 159 for (int i = 0; i < bootstrapArgumentsLen; i++) { 160 buf.append("\n ").append(i).append(": "); 161 buf.append(constantPool.constantToString(constantPool.getConstant(bootstrapArguments[i]))); 162 } 163 } 164 return buf.toString(); 165 } 166}