/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package javassist.bytecode;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;

InnerClasses_attribute.
/** * <code>InnerClasses_attribute</code>. */
public class InnerClassesAttribute extends AttributeInfo {
The name of this attribute "InnerClasses".
/** * The name of this attribute <code>"InnerClasses"</code>. */
public static final String tag = "InnerClasses"; InnerClassesAttribute(ConstPool cp, int n, DataInputStream in) throws IOException { super(cp, n, in); } private InnerClassesAttribute(ConstPool cp, byte[] info) { super(cp, tag, info); }
Constructs an empty InnerClasses attribute.
See Also:
  • append(String, String, String, int)
/** * Constructs an empty InnerClasses attribute. * * @see #append(String, String, String, int) */
public InnerClassesAttribute(ConstPool cp) { super(cp, tag, new byte[2]); ByteArray.write16bit(0, get(), 0); }
Returns number_of_classes.
/** * Returns <code>number_of_classes</code>. */
public int tableLength() { return ByteArray.readU16bit(get(), 0); }
Returns classes[nth].inner_class_info_index.
/** * Returns <code>classes[nth].inner_class_info_index</code>. */
public int innerClassIndex(int nth) { return ByteArray.readU16bit(get(), nth * 8 + 2); }
Returns the class name indicated by classes[nth].inner_class_info_index. The class name is fully-qualified and separated by dot.
See Also:
Returns:null or the class name.
/** * Returns the class name indicated * by <code>classes[nth].inner_class_info_index</code>. * The class name is fully-qualified and separated by dot. * * @return null or the class name. * @see ConstPool#getClassInfo(int) */
public String innerClass(int nth) { int i = innerClassIndex(nth); if (i == 0) return null; return constPool.getClassInfo(i); }
Sets classes[nth].inner_class_info_index to the given index.
/** * Sets <code>classes[nth].inner_class_info_index</code> to * the given index. */
public void setInnerClassIndex(int nth, int index) { ByteArray.write16bit(index, get(), nth * 8 + 2); }
Returns classes[nth].outer_class_info_index.
/** * Returns <code>classes[nth].outer_class_info_index</code>. */
public int outerClassIndex(int nth) { return ByteArray.readU16bit(get(), nth * 8 + 4); }
Returns the class name indicated by classes[nth].outer_class_info_index.
Returns:null or the class name.
/** * Returns the class name indicated * by <code>classes[nth].outer_class_info_index</code>. * * @return null or the class name. */
public String outerClass(int nth) { int i = outerClassIndex(nth); if (i == 0) return null; return constPool.getClassInfo(i); }
Sets classes[nth].outer_class_info_index to the given index.
/** * Sets <code>classes[nth].outer_class_info_index</code> to * the given index. */
public void setOuterClassIndex(int nth, int index) { ByteArray.write16bit(index, get(), nth * 8 + 4); }
Returns classes[nth].inner_name_index.
/** * Returns <code>classes[nth].inner_name_index</code>. */
public int innerNameIndex(int nth) { return ByteArray.readU16bit(get(), nth * 8 + 6); }
Returns the simple class name indicated by classes[nth].inner_name_index.
Returns:null or the class name.
/** * Returns the simple class name indicated * by <code>classes[nth].inner_name_index</code>. * * @return null or the class name. */
public String innerName(int nth) { int i = innerNameIndex(nth); if (i == 0) return null; return constPool.getUtf8Info(i); }
Sets classes[nth].inner_name_index to the given index.
/** * Sets <code>classes[nth].inner_name_index</code> to * the given index. */
public void setInnerNameIndex(int nth, int index) { ByteArray.write16bit(index, get(), nth * 8 + 6); }
Returns classes[nth].inner_class_access_flags.
/** * Returns <code>classes[nth].inner_class_access_flags</code>. */
public int accessFlags(int nth) { return ByteArray.readU16bit(get(), nth * 8 + 8); }
Sets classes[nth].inner_class_access_flags to the given index.
/** * Sets <code>classes[nth].inner_class_access_flags</code> to * the given index. */
public void setAccessFlags(int nth, int flags) { ByteArray.write16bit(flags, get(), nth * 8 + 8); }
Finds the entry for the given inner class.
Params:
  • name – the fully-qualified class name separated by dot and $.
Returns:the index or -1 if not found.
Since:3.22
/** * Finds the entry for the given inner class. * * @param name the fully-qualified class name separated by dot and $. * @return the index or -1 if not found. * @since 3.22 */
public int find(String name) { int n = tableLength(); for (int i = 0; i < n; i++) if (name.equals(innerClass(i))) return i; return -1; }
Appends a new entry.
Params:
  • inner – inner_class_info_index
  • outer – outer_class_info_index
  • name – inner_name_index
  • flags – inner_class_access_flags
/** * Appends a new entry. * * @param inner <code>inner_class_info_index</code> * @param outer <code>outer_class_info_index</code> * @param name <code>inner_name_index</code> * @param flags <code>inner_class_access_flags</code> */
public void append(String inner, String outer, String name, int flags) { int i = constPool.addClassInfo(inner); int o = constPool.addClassInfo(outer); int n = constPool.addUtf8Info(name); append(i, o, n, flags); }
Appends a new entry.
Params:
  • inner – inner_class_info_index
  • outer – outer_class_info_index
  • name – inner_name_index
  • flags – inner_class_access_flags
/** * Appends a new entry. * * @param inner <code>inner_class_info_index</code> * @param outer <code>outer_class_info_index</code> * @param name <code>inner_name_index</code> * @param flags <code>inner_class_access_flags</code> */
public void append(int inner, int outer, int name, int flags) { byte[] data = get(); int len = data.length; byte[] newData = new byte[len + 8]; for (int i = 2; i < len; ++i) newData[i] = data[i]; int n = ByteArray.readU16bit(data, 0); ByteArray.write16bit(n + 1, newData, 0); ByteArray.write16bit(inner, newData, len); ByteArray.write16bit(outer, newData, len + 2); ByteArray.write16bit(name, newData, len + 4); ByteArray.write16bit(flags, newData, len + 6); set(newData); }
Removes the nth entry. It does not eliminate constant pool items that the removed entry refers to. ClassFile.compact() should be executed to remove these unnecessary items.
Params:
  • nth – 0, 1, 2, ...
See Also:
Returns: the number of items after the removal.
/** * Removes the {@code nth} entry. It does not eliminate * constant pool items that the removed entry refers to. * {@link ClassFile#compact()} should be executed to remove * these unnecessary items. * * @param nth 0, 1, 2, ... * @return the number of items after the removal. * @see ClassFile#compact() */
public int remove(int nth) { byte[] data = get(); int len = data.length; if (len < 10) return 0; int n = ByteArray.readU16bit(data, 0); int nthPos = 2 + nth * 8; if (n <= nth) return n; byte[] newData = new byte[len - 8]; ByteArray.write16bit(n - 1, newData, 0); int i = 2, j = 2; while (i < len) if (i == nthPos) i += 8; else newData[j++] = data[i++]; set(newData); return n - 1; }
Makes a copy. Class names are replaced according to the given Map object.
Params:
  • newCp – the constant pool table used by the new copy.
  • classnames – pairs of replaced and substituted class names.
/** * Makes a copy. Class names are replaced according to the * given <code>Map</code> object. * * @param newCp the constant pool table used by the new copy. * @param classnames pairs of replaced and substituted * class names. */
@Override public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { byte[] src = get(); byte[] dest = new byte[src.length]; ConstPool cp = getConstPool(); InnerClassesAttribute attr = new InnerClassesAttribute(newCp, dest); int n = ByteArray.readU16bit(src, 0); ByteArray.write16bit(n, dest, 0); int j = 2; for (int i = 0; i < n; ++i) { int innerClass = ByteArray.readU16bit(src, j); int outerClass = ByteArray.readU16bit(src, j + 2); int innerName = ByteArray.readU16bit(src, j + 4); int innerAccess = ByteArray.readU16bit(src, j + 6); if (innerClass != 0) innerClass = cp.copy(innerClass, newCp, classnames); ByteArray.write16bit(innerClass, dest, j); if (outerClass != 0) outerClass = cp.copy(outerClass, newCp, classnames); ByteArray.write16bit(outerClass, dest, j + 2); if (innerName != 0) innerName = cp.copy(innerName, newCp, classnames); ByteArray.write16bit(innerName, dest, j + 4); ByteArray.write16bit(innerAccess, dest, j + 6); j += 8; } return attr; } }