/*
* 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.util.
Map;
import java.io.
IOException;
/**
* <code>InnerClasses_attribute</code>.
*/
public class
InnerClassesAttribute extends
AttributeInfo {
/**
* 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 #append(String, String, String, int)
*/
public
InnerClassesAttribute(
ConstPool cp) {
super(
cp,
tag, new byte[2]);
ByteArray.
write16bit(0,
get(), 0);
}
/**
* Returns <code>number_of_classes</code>.
*/
public int
tableLength() { return
ByteArray.
readU16bit(
get(), 0); }
/**
* 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 <code>classes[nth].inner_class_info_index</code>.
*
* @return null or the class name.
*/
public
String innerClass(int
nth) {
int
i =
innerClassIndex(
nth);
if (
i == 0)
return null;
else
return
constPool.
getClassInfo(
i);
}
/**
* 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 <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 <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;
else
return
constPool.
getClassInfo(
i);
}
/**
* 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 <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 <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;
else
return
constPool.
getUtf8Info(
i);
}
/**
* 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 <code>classes[nth].inner_class_access_flags</code>.
*/
public int
accessFlags(int
nth) {
return
ByteArray.
readU16bit(
get(),
nth * 8 + 8);
}
/**
* 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);
}
/**
* 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.
*
* @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);
}
/**
* 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.
*/
public
AttributeInfo copy(
ConstPool newCp,
Map 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;
}
}