/*
* Copyright 2004-2010 Brian S O'Neill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cojen.classfile;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.cojen.classfile.constant.ConstantClassInfo;
/**
* This class corresponds to the exception_table structure as defined in
* section 4.7.4 of <i>The Java Virtual Machine Specification</i>.
*
* @author Brian S O'Neill
*/
public class ExceptionHandler<L extends Location> implements LocationRange<L> {
private L mStart;
private L mEnd;
private L mCatch;
private ConstantClassInfo mCatchType;
/**
* @param startLocation
* @param endLocation
* @param catchLocation
* @param catchType if null, then catch every object.
*/
public ExceptionHandler(L startLocation,
L endLocation,
L catchLocation,
ConstantClassInfo catchType) {
mStart = startLocation;
mEnd = endLocation;
mCatch = catchLocation;
mCatchType = catchType;
}
public L getStartLocation() {
return mStart;
}
public L getEndLocation() {
return mEnd;
}
public L getCatchLocation() {
return mCatch;
}
/**
* Returns null if every object is caught by this handler.
*/
public ConstantClassInfo getCatchType() {
return mCatchType;
}
public void writeTo(DataOutput dout) throws IOException {
int start_pc = getStartLocation().getLocation();
int end_pc = getEndLocation().getLocation();
int handler_pc = getCatchLocation().getLocation();
int catch_type;
ConstantClassInfo catchType = getCatchType();
if (catchType == null) {
catch_type = 0;
}
else {
catch_type = catchType.getIndex();
}
check("exception start PC", start_pc);
check("exception end PC", end_pc);
check("exception handler PC", handler_pc);
dout.writeShort(start_pc);
dout.writeShort(end_pc);
dout.writeShort(handler_pc);
dout.writeShort(catch_type);
}
private void check(String type, int addr) throws IllegalStateException {
if (addr < 0 || addr > 65535) {
throw new IllegalStateException("Value for " + type + " out of " +
"valid range: " + addr);
}
}
public static ExceptionHandler<FixedLocation> readFrom(ConstantPool cp, DataInput din)
throws IOException
{
int start_pc = din.readUnsignedShort();
int end_pc = din.readUnsignedShort();
int handler_pc = din.readUnsignedShort();
int catch_type = din.readUnsignedShort();
ConstantClassInfo catchTypeConstant;
if (catch_type == 0) {
catchTypeConstant = null;
} else {
catchTypeConstant = (ConstantClassInfo)cp.getConstant(catch_type);
}
return new ExceptionHandler<FixedLocation>(new FixedLocation(start_pc),
new FixedLocation(end_pc),
new FixedLocation(handler_pc),
catchTypeConstant);
}
}