/*
* 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.
DataOutputStream;
import java.io.
IOException;
import java.util.
ArrayList;
import java.util.
List;
import java.util.
Map;
class
ExceptionTableEntry {
int
startPc;
int
endPc;
int
handlerPc;
int
catchType;
ExceptionTableEntry(int
start, int
end, int
handle, int
type) {
startPc =
start;
endPc =
end;
handlerPc =
handle;
catchType =
type;
}
}
/**
* <code>exception_table[]</code> of <code>Code_attribute</code>.
*/
public class
ExceptionTable implements
Cloneable {
private
ConstPool constPool;
private
List<
ExceptionTableEntry>
entries;
/**
* Constructs an <code>exception_table[]</code>.
*
* @param cp constant pool table.
*/
public
ExceptionTable(
ConstPool cp) {
constPool =
cp;
entries = new
ArrayList<
ExceptionTableEntry>();
}
ExceptionTable(
ConstPool cp,
DataInputStream in) throws
IOException {
constPool =
cp;
int
length =
in.
readUnsignedShort();
List<
ExceptionTableEntry>
list = new
ArrayList<
ExceptionTableEntry>(
length);
for (int
i = 0;
i <
length; ++
i) {
int
start =
in.
readUnsignedShort();
int
end =
in.
readUnsignedShort();
int
handle =
in.
readUnsignedShort();
int
type =
in.
readUnsignedShort();
list.
add(new
ExceptionTableEntry(
start,
end,
handle,
type));
}
entries =
list;
}
/**
* Creates and returns a copy of this object.
* The constant pool object is shared between this object
* and the cloned object.
*/
@
Override
public
Object clone() throws
CloneNotSupportedException {
ExceptionTable r = (
ExceptionTable)super.clone();
r.
entries = new
ArrayList<
ExceptionTableEntry>(
entries);
return
r;
}
/**
* Returns <code>exception_table_length</code>, which is the number
* of entries in the <code>exception_table[]</code>.
*/
public int
size() {
return
entries.
size();
}
/**
* Returns <code>startPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
*/
public int
startPc(int
nth) {
return
entries.
get(
nth).
startPc;
}
/**
* Sets <code>startPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
* @param value new value.
*/
public void
setStartPc(int
nth, int
value) {
entries.
get(
nth).
startPc =
value;
}
/**
* Returns <code>endPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
*/
public int
endPc(int
nth) {
return
entries.
get(
nth).
endPc;
}
/**
* Sets <code>endPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
* @param value new value.
*/
public void
setEndPc(int
nth, int
value) {
entries.
get(
nth).
endPc =
value;
}
/**
* Returns <code>handlerPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
*/
public int
handlerPc(int
nth) {
return
entries.
get(
nth).
handlerPc;
}
/**
* Sets <code>handlerPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
* @param value new value.
*/
public void
setHandlerPc(int
nth, int
value) {
entries.
get(
nth).
handlerPc =
value;
}
/**
* Returns <code>catchType</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
* @return an index into the <code>constant_pool</code> table,
* or zero if this exception handler is for all exceptions.
*/
public int
catchType(int
nth) {
return
entries.
get(
nth).
catchType;
}
/**
* Sets <code>catchType</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (>= 0).
* @param value new value.
*/
public void
setCatchType(int
nth, int
value) {
entries.
get(
nth).
catchType =
value;
}
/**
* Copies the given exception table at the specified position
* in the table.
*
* @param index index (>= 0) at which the entry is to be inserted.
* @param offset the offset added to the code position.
*/
public void
add(int
index,
ExceptionTable table, int
offset) {
int
len =
table.
size();
while (--
len >= 0) {
ExceptionTableEntry e =
table.
entries.
get(
len);
add(
index,
e.
startPc +
offset,
e.
endPc +
offset,
e.
handlerPc +
offset,
e.
catchType);
}
}
/**
* Adds a new entry at the specified position in the table.
*
* @param index index (>= 0) at which the entry is to be inserted.
* @param start <code>startPc</code>
* @param end <code>endPc</code>
* @param handler <code>handlerPc</code>
* @param type <code>catchType</code>
*/
public void
add(int
index, int
start, int
end, int
handler, int
type) {
if (
start <
end)
entries.
add(
index,
new
ExceptionTableEntry(
start,
end,
handler,
type));
}
/**
* Appends a new entry at the end of the table.
*
* @param start <code>startPc</code>
* @param end <code>endPc</code>
* @param handler <code>handlerPc</code>
* @param type <code>catchType</code>
*/
public void
add(int
start, int
end, int
handler, int
type) {
if (
start <
end)
entries.
add(new
ExceptionTableEntry(
start,
end,
handler,
type));
}
/**
* Removes the entry at the specified position in the table.
*
* @param index the index of the removed entry.
*/
public void
remove(int
index) {
entries.
remove(
index);
}
/**
* Makes a copy of this <code>exception_table[]</code>.
* 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
ExceptionTable copy(
ConstPool newCp,
Map<
String,
String>
classnames) {
ExceptionTable et = new
ExceptionTable(
newCp);
ConstPool srcCp =
constPool;
for (
ExceptionTableEntry e:
entries) {
int
type =
srcCp.
copy(
e.
catchType,
newCp,
classnames);
et.
add(
e.
startPc,
e.
endPc,
e.
handlerPc,
type);
}
return
et;
}
void
shiftPc(int
where, int
gapLength, boolean
exclusive) {
for (
ExceptionTableEntry e:
entries) {
e.
startPc =
shiftPc(
e.
startPc,
where,
gapLength,
exclusive);
e.
endPc =
shiftPc(
e.
endPc,
where,
gapLength,
exclusive);
e.
handlerPc =
shiftPc(
e.
handlerPc,
where,
gapLength,
exclusive);
}
}
private static int
shiftPc(int
pc, int
where, int
gapLength,
boolean
exclusive) {
if (
pc >
where || (
exclusive &&
pc ==
where))
pc +=
gapLength;
return
pc;
}
void
write(
DataOutputStream out) throws
IOException {
out.
writeShort(
size()); // exception_table_length
for (
ExceptionTableEntry e:
entries) {
out.
writeShort(
e.
startPc);
out.
writeShort(
e.
endPc);
out.
writeShort(
e.
handlerPc);
out.
writeShort(
e.
catchType);
}
}
}