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 is derived from <em>Attribute</em> and records the classes and interfaces that 028 * are authorized to claim membership in the nest hosted by the current class or interface. 029 * There may be at most one NestMembers attribute in a ClassFile structure. 030 * 031 * @see Attribute 032 */ 033public final class NestMembers extends Attribute { 034 035 private int[] classes; 036 037 038 /** 039 * Initialize from another object. Note that both objects use the same 040 * references (shallow copy). Use copy() for a physical copy. 041 */ 042 public NestMembers(final NestMembers c) { 043 this(c.getNameIndex(), c.getLength(), c.getClasses(), c.getConstantPool()); 044 } 045 046 047 /** 048 * @param name_index Index in constant pool 049 * @param length Content length in bytes 050 * @param classes Table of indices in constant pool 051 * @param constant_pool Array of constants 052 */ 053 public NestMembers(final int name_index, final int length, final int[] classes, 054 final ConstantPool constant_pool) { 055 super(Const.ATTR_NEST_MEMBERS, name_index, length, constant_pool); 056 this.classes = classes != null ? classes : new int[0]; 057 } 058 059 060 /** 061 * Construct object from input stream. 062 * @param name_index Index in constant pool 063 * @param length Content length in bytes 064 * @param input Input stream 065 * @param constant_pool Array of constants 066 * @throws IOException 067 */ 068 NestMembers(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { 069 this(name_index, length, (int[]) null, constant_pool); 070 final int number_of_classes = input.readUnsignedShort(); 071 classes = new int[number_of_classes]; 072 for (int i = 0; i < number_of_classes; i++) { 073 classes[i] = input.readUnsignedShort(); 074 } 075 } 076 077 078 /** 079 * Called by objects that are traversing the nodes of the tree implicitely 080 * defined by the contents of a Java class. I.e., the hierarchy of methods, 081 * fields, attributes, etc. spawns a tree of objects. 082 * 083 * @param v Visitor object 084 */ 085 @Override 086 public void accept( final Visitor v ) { 087 v.visitNestMembers(this); 088 } 089 090 091 /** 092 * Dump NestMembers attribute to file stream in binary format. 093 * 094 * @param file Output file stream 095 * @throws IOException 096 */ 097 @Override 098 public void dump( final DataOutputStream file ) throws IOException { 099 super.dump(file); 100 file.writeShort(classes.length); 101 for (final int index : classes) { 102 file.writeShort(index); 103 } 104 } 105 106 107 /** 108 * @return array of indices into constant pool of class names. 109 */ 110 public int[] getClasses() { 111 return classes; 112 } 113 114 115 /** 116 * @return Length of classes table. 117 */ 118 public int getNumberClasses() { 119 return classes == null ? 0 : classes.length; 120 } 121 122 123 /** 124 * @return string array of class names 125 */ 126 public String[] getClassNames() { 127 final String[] names = new String[classes.length]; 128 for (int i = 0; i < classes.length; i++) { 129 names[i] = super.getConstantPool().getConstantString(classes[i], 130 Const.CONSTANT_Class).replace('/', '.'); 131 } 132 return names; 133 } 134 135 136 /** 137 * @param classes the list of class indexes 138 * Also redefines number_of_classes according to table length. 139 */ 140 public void setClasses( final int[] classes ) { 141 this.classes = classes != null ? classes : new int[0]; 142 } 143 144 145 /** 146 * @return String representation, i.e., a list of classes. 147 */ 148 @Override 149 public String toString() { 150 final StringBuilder buf = new StringBuilder(); 151 buf.append("NestMembers("); 152 buf.append(classes.length); 153 buf.append("):\n"); 154 for (final int index : classes) { 155 final String class_name = super.getConstantPool().getConstantString(index, Const.CONSTANT_Class); 156 buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n"); 157 } 158 return buf.substring(0, buf.length()-1); // remove the last newline 159 } 160 161 162 /** 163 * @return deep copy of this attribute 164 */ 165 @Override 166 public Attribute copy( final ConstantPool _constant_pool ) { 167 final NestMembers c = (NestMembers) clone(); 168 if (classes != null) { 169 c.classes = new int[classes.length]; 170 System.arraycopy(classes, 0, c.classes, 0, 171 classes.length); 172 } 173 c.setConstantPool(_constant_pool); 174 return c; 175 } 176}