001: /*
002: * Copyright 2004 Brian S O'Neill
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.cojen.classfile;
018:
019: import java.io.DataInput;
020: import java.io.DataOutput;
021: import java.io.IOException;
022: import org.cojen.classfile.constant.ConstantClassInfo;
023:
024: /**
025: * This class corresponds to the exception_table structure as defined in
026: * section 4.7.4 of <i>The Java Virtual Machine Specification</i>.
027: *
028: * @author Brian S O'Neill
029: */
030: public class ExceptionHandler implements LocationRange {
031: private Location mStart;
032: private Location mEnd;
033: private Location mCatch;
034: private ConstantClassInfo mCatchType;
035:
036: /**
037: * @param startLocation
038: * @param endLocation
039: * @param catchLocation
040: * @param catchType if null, then catch every object.
041: */
042: public ExceptionHandler(Location startLocation,
043: Location endLocation, Location catchLocation,
044: ConstantClassInfo catchType) {
045: mStart = startLocation;
046: mEnd = endLocation;
047: mCatch = catchLocation;
048: mCatchType = catchType;
049: }
050:
051: public Location getStartLocation() {
052: return mStart;
053: }
054:
055: public Location getEndLocation() {
056: return mEnd;
057: }
058:
059: public Location getCatchLocation() {
060: return mCatch;
061: }
062:
063: /**
064: * Returns null if every object is caught by this handler.
065: */
066: public ConstantClassInfo getCatchType() {
067: return mCatchType;
068: }
069:
070: public void writeTo(DataOutput dout) throws IOException {
071: int start_pc = getStartLocation().getLocation();
072: int end_pc = getEndLocation().getLocation();
073: int handler_pc = getCatchLocation().getLocation();
074: int catch_type;
075: ConstantClassInfo catchType = getCatchType();
076: if (catchType == null) {
077: catch_type = 0;
078: } else {
079: catch_type = catchType.getIndex();
080: }
081:
082: check("exception start PC", start_pc);
083: check("exception end PC", end_pc);
084: check("exception handler PC", handler_pc);
085:
086: dout.writeShort(start_pc);
087: dout.writeShort(end_pc);
088: dout.writeShort(handler_pc);
089: dout.writeShort(catch_type);
090: }
091:
092: private void check(String type, int addr)
093: throws IllegalStateException {
094: if (addr < 0 || addr > 65535) {
095: throw new IllegalStateException("Value for " + type
096: + " out of " + "valid range: " + addr);
097:
098: }
099: }
100:
101: public static ExceptionHandler readFrom(ConstantPool cp,
102: DataInput din) throws IOException {
103: int start_pc = din.readUnsignedShort();
104: int end_pc = din.readUnsignedShort();
105: int handler_pc = din.readUnsignedShort();
106: int catch_type = din.readUnsignedShort();
107:
108: ConstantClassInfo catchTypeConstant;
109: if (catch_type == 0) {
110: catchTypeConstant = null;
111: } else {
112: catchTypeConstant = (ConstantClassInfo) cp
113: .getConstant(catch_type);
114: }
115:
116: return new ExceptionHandler(new FixedLocation(start_pc),
117: new FixedLocation(end_pc),
118: new FixedLocation(handler_pc), catchTypeConstant);
119: }
120: }
|