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="https://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[] bootstrapMethods;  // 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 bootstrapMethods array of bootstrap methods
050     * @param constant_pool Array of constants
051     */
052    public BootstrapMethods(final int name_index, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constant_pool) {
053        super(Const.ATTR_BOOTSTRAP_METHODS, name_index, length, constant_pool);
054        this.bootstrapMethods = bootstrapMethods;
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        bootstrapMethods = new BootstrapMethod[num_bootstrap_methods];
071        for (int i = 0; i < num_bootstrap_methods; i++) {
072            bootstrapMethods[i] = new BootstrapMethod(input);
073        }
074    }
075
076    /**
077     * @return array of bootstrap method "records"
078     */
079    public final BootstrapMethod[] getBootstrapMethods() {
080        return bootstrapMethods;
081    }
082
083    /**
084     * @param bootstrapMethods the array of bootstrap methods
085     */
086    public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) {
087        this.bootstrapMethods = bootstrapMethods;
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.bootstrapMethods = new BootstrapMethod[bootstrapMethods.length];
105
106        for (int i = 0; i < bootstrapMethods.length; i++) {
107            c.bootstrapMethods[i] = bootstrapMethods[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(bootstrapMethods.length);
124        for (final BootstrapMethod bootstrap_method : bootstrapMethods) {
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(bootstrapMethods.length);
137        buf.append("):");
138        for (int i = 0; i < bootstrapMethods.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 = (bootstrapMethods[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}