package javassist.bytecode;
import java.io.
DataInputStream;
import java.io.
IOException;
import java.util.
HashMap;
import java.util.
Map;
import javassist.bytecode.annotation.
TypeAnnotationsWriter;
/**
* A class representing
* {@code RuntimeVisibleTypeAnnotations} attribute and
* {@code RuntimeInvisibleTypeAnnotations} attribute.
*
* @since 3.19
*/
public class
TypeAnnotationsAttribute extends
AttributeInfo {
/**
* The name of the {@code RuntimeVisibleTypeAnnotations} attribute.
*/
public static final
String visibleTag = "RuntimeVisibleTypeAnnotations";
/**
* The name of the {@code RuntimeInvisibleTypeAnnotations} attribute.
*/
public static final
String invisibleTag = "RuntimeInvisibleTypeAnnotations";
/**
* Constructs a <code>Runtime(In)VisibleTypeAnnotations_attribute</code>.
*
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @param info the contents of this attribute. It does not
* include <code>attribute_name_index</code> or
* <code>attribute_length</code>.
*/
public
TypeAnnotationsAttribute(
ConstPool cp,
String attrname, byte[]
info) {
super(
cp,
attrname,
info);
}
/**
* @param n the attribute name.
*/
TypeAnnotationsAttribute(
ConstPool cp, int
n,
DataInputStream in)
throws
IOException
{
super(
cp,
n,
in);
}
/**
* Returns <code>num_annotations</code>.
*/
public int
numAnnotations() {
return
ByteArray.
readU16bit(
info, 0);
}
/**
* Copies this attribute and returns a new copy.
*/
public
AttributeInfo copy(
ConstPool newCp,
Map classnames) {
Copier copier = new
Copier(
info,
constPool,
newCp,
classnames);
try {
copier.
annotationArray();
return new
TypeAnnotationsAttribute(
newCp,
getName(),
copier.
close());
}
catch (
Exception e) {
throw new
RuntimeException(
e);
}
}
/**
* @param oldname a JVM class name.
* @param newname a JVM class name.
*/
void
renameClass(
String oldname,
String newname) {
HashMap map = new
HashMap();
map.
put(
oldname,
newname);
renameClass(
map);
}
void
renameClass(
Map classnames) {
Renamer renamer = new
Renamer(
info,
getConstPool(),
classnames);
try {
renamer.
annotationArray();
} catch (
Exception e) {
throw new
RuntimeException(
e);
}
}
void
getRefClasses(
Map classnames) {
renameClass(
classnames); }
/**
* To visit each elements of the type annotation attribute,
* call {@code annotationArray()}.
*
* @see #annotationArray()
*/
static class
TAWalker extends
AnnotationsAttribute.
Walker {
SubWalker subWalker;
TAWalker(byte[]
attrInfo) {
super(
attrInfo);
subWalker = new
SubWalker(
attrInfo);
}
int
annotationArray(int
pos, int
num) throws
Exception {
for (int
i = 0;
i <
num;
i++) {
int
targetType =
info[
pos] & 0xff;
pos =
subWalker.
targetInfo(
pos + 1,
targetType);
pos =
subWalker.
typePath(
pos);
pos =
annotation(
pos);
}
return
pos;
}
}
static class
SubWalker {
byte[]
info;
SubWalker(byte[]
attrInfo) {
info =
attrInfo;
}
final int
targetInfo(int
pos, int
type) throws
Exception {
switch (
type) {
case 0x00:
case 0x01: {
int
index =
info[
pos] & 0xff;
typeParameterTarget(
pos,
type,
index);
return
pos + 1; }
case 0x10: {
int
index =
ByteArray.
readU16bit(
info,
pos);
supertypeTarget(
pos,
index);
return
pos + 2; }
case 0x11:
case 0x12: {
int
param =
info[
pos] & 0xff;
int
bound =
info[
pos + 1] & 0xff;
typeParameterBoundTarget(
pos,
type,
param,
bound);
return
pos + 2; }
case 0x13:
case 0x14:
case 0x15:
emptyTarget(
pos,
type);
return
pos;
case 0x16: {
int
index =
info[
pos] & 0xff;
formalParameterTarget(
pos,
index);
return
pos + 1; }
case 0x17: {
int
index =
ByteArray.
readU16bit(
info,
pos);
throwsTarget(
pos,
index);
return
pos + 2; }
case 0x40:
case 0x41: {
int
len =
ByteArray.
readU16bit(
info,
pos);
return
localvarTarget(
pos + 2,
type,
len); }
case 0x42: {
int
index =
ByteArray.
readU16bit(
info,
pos);
catchTarget(
pos,
index);
return
pos + 2; }
case 0x43:
case 0x44:
case 0x45:
case 0x46: {
int
offset =
ByteArray.
readU16bit(
info,
pos);
offsetTarget(
pos,
type,
offset);
return
pos + 2; }
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b: {
int
offset =
ByteArray.
readU16bit(
info,
pos);
int
index =
info[
pos + 2] & 0xff;
typeArgumentTarget(
pos,
type,
offset,
index);
return
pos + 3; }
default:
throw new
RuntimeException("invalid target type: " +
type);
}
}
void
typeParameterTarget(int
pos, int
targetType, int
typeParameterIndex)
throws
Exception {}
void
supertypeTarget(int
pos, int
superTypeIndex) throws
Exception {}
void
typeParameterBoundTarget(int
pos, int
targetType, int
typeParameterIndex,
int
boundIndex) throws
Exception {}
void
emptyTarget(int
pos, int
targetType) throws
Exception {}
void
formalParameterTarget(int
pos, int
formalParameterIndex) throws
Exception {}
void
throwsTarget(int
pos, int
throwsTypeIndex) throws
Exception {}
int
localvarTarget(int
pos, int
targetType, int
tableLength) throws
Exception {
for (int
i = 0;
i <
tableLength;
i++) {
int
start =
ByteArray.
readU16bit(
info,
pos);
int
length =
ByteArray.
readU16bit(
info,
pos + 2);
int
index =
ByteArray.
readU16bit(
info,
pos + 4);
localvarTarget(
pos,
targetType,
start,
length,
index);
pos += 6;
}
return
pos;
}
void
localvarTarget(int
pos, int
targetType, int
startPc, int
length, int
index)
throws
Exception {}
void
catchTarget(int
pos, int
exceptionTableIndex) throws
Exception {}
void
offsetTarget(int
pos, int
targetType, int
offset) throws
Exception {}
void
typeArgumentTarget(int
pos, int
targetType, int
offset, int
typeArgumentIndex)
throws
Exception {}
final int
typePath(int
pos) throws
Exception {
int
len =
info[
pos++] & 0xff;
return
typePath(
pos,
len);
}
int
typePath(int
pos, int
pathLength) throws
Exception {
for (int
i = 0;
i <
pathLength;
i++) {
int
kind =
info[
pos] & 0xff;
int
index =
info[
pos + 1] & 0xff;
typePath(
pos,
kind,
index);
pos += 2;
}
return
pos;
}
void
typePath(int
pos, int
typePathKind, int
typeArgumentIndex) throws
Exception {}
}
static class
Renamer extends
AnnotationsAttribute.
Renamer {
SubWalker sub;
Renamer(byte[]
attrInfo,
ConstPool cp,
Map map) {
super(
attrInfo,
cp,
map);
sub = new
SubWalker(
attrInfo);
}
int
annotationArray(int
pos, int
num) throws
Exception {
for (int
i = 0;
i <
num;
i++) {
int
targetType =
info[
pos] & 0xff;
pos =
sub.
targetInfo(
pos + 1,
targetType);
pos =
sub.
typePath(
pos);
pos =
annotation(
pos);
}
return
pos;
}
}
static class
Copier extends
AnnotationsAttribute.
Copier {
SubCopier sub;
Copier(byte[]
attrInfo,
ConstPool src,
ConstPool dest,
Map map) {
super(
attrInfo,
src,
dest,
map, false);
TypeAnnotationsWriter w = new
TypeAnnotationsWriter(
output,
dest);
writer =
w;
sub = new
SubCopier(
attrInfo,
src,
dest,
map,
w);
}
int
annotationArray(int
pos, int
num) throws
Exception {
writer.
numAnnotations(
num);
for (int
i = 0;
i <
num;
i++) {
int
targetType =
info[
pos] & 0xff;
pos =
sub.
targetInfo(
pos + 1,
targetType);
pos =
sub.
typePath(
pos);
pos =
annotation(
pos);
}
return
pos;
}
}
static class
SubCopier extends
SubWalker {
ConstPool srcPool,
destPool;
Map classnames;
TypeAnnotationsWriter writer;
SubCopier(byte[]
attrInfo,
ConstPool src,
ConstPool dest,
Map map,
TypeAnnotationsWriter w)
{
super(
attrInfo);
srcPool =
src;
destPool =
dest;
classnames =
map;
writer =
w;
}
void
typeParameterTarget(int
pos, int
targetType, int
typeParameterIndex)
throws
Exception
{
writer.
typeParameterTarget(
targetType,
typeParameterIndex);
}
void
supertypeTarget(int
pos, int
superTypeIndex) throws
Exception {
writer.
supertypeTarget(
superTypeIndex);
}
void
typeParameterBoundTarget(int
pos, int
targetType, int
typeParameterIndex,
int
boundIndex)
throws
Exception
{
writer.
typeParameterBoundTarget(
targetType,
typeParameterIndex,
boundIndex);
}
void
emptyTarget(int
pos, int
targetType) throws
Exception {
writer.
emptyTarget(
targetType);
}
void
formalParameterTarget(int
pos, int
formalParameterIndex) throws
Exception {
writer.
formalParameterTarget(
formalParameterIndex);
}
void
throwsTarget(int
pos, int
throwsTypeIndex) throws
Exception {
writer.
throwsTarget(
throwsTypeIndex);
}
int
localvarTarget(int
pos, int
targetType, int
tableLength) throws
Exception {
writer.
localVarTarget(
targetType,
tableLength);
return super.localvarTarget(
pos,
targetType,
tableLength);
}
void
localvarTarget(int
pos, int
targetType, int
startPc, int
length, int
index)
throws
Exception
{
writer.
localVarTargetTable(
startPc,
length,
index);
}
void
catchTarget(int
pos, int
exceptionTableIndex) throws
Exception {
writer.
catchTarget(
exceptionTableIndex);
}
void
offsetTarget(int
pos, int
targetType, int
offset) throws
Exception {
writer.
offsetTarget(
targetType,
offset);
}
void
typeArgumentTarget(int
pos, int
targetType, int
offset, int
typeArgumentIndex)
throws
Exception
{
writer.
typeArgumentTarget(
targetType,
offset,
typeArgumentIndex);
}
int
typePath(int
pos, int
pathLength) throws
Exception {
writer.
typePath(
pathLength);
return super.typePath(
pos,
pathLength);
}
void
typePath(int
pos, int
typePathKind, int
typeArgumentIndex) throws
Exception {
writer.
typePathPath(
typePathKind,
typeArgumentIndex);
}
}
}