001: /*
002: * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * - Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: *
013: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
014: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
015: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
016: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
017: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
018: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
019: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
020: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
021: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
022: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
023: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
024: */
025: package classycle.classfile;
026:
027: import java.io.DataInputStream;
028: import java.io.IOException;
029:
030: /**
031: * Abstract super class of all type of constants in the constant pool of
032: * a class file.
033: *
034: * @author Franz-Josef Elmer
035: */
036: public abstract class Constant {
037: private static final int MAGIC = 0xcafebabe;
038: private static final int CONSTANT_CLASS = 7, CONSTANT_FIELDREF = 9,
039: CONSTANT_METHODREF = 10, CONSTANT_INTERFACE_METHODREF = 11,
040: CONSTANT_STRING = 8, CONSTANT_INTEGER = 3,
041: CONSTANT_FLOAT = 4, CONSTANT_LONG = 5, CONSTANT_DOUBLE = 6,
042: CONSTANT_NAME_AND_TYPE = 12, CONSTANT_UTF8 = 1;
043:
044: /**
045: * Extracts the constant pool from the specified data stream of a class file.
046: * @param stream Input stream of a class file starting at the first byte.
047: * @return extracted array of constants.
048: * @throws IOException in case of reading errors or invalid class file.
049: */
050: public static Constant[] extractConstantPool(DataInputStream stream)
051: throws IOException {
052: Constant[] pool = null;
053: if (stream.readInt() == MAGIC) {
054: stream.readUnsignedShort();
055: stream.readUnsignedShort();
056: pool = new Constant[stream.readUnsignedShort()];
057: for (int i = 1; i < pool.length;) {
058: boolean skipIndex = false;
059: Constant c = null;
060: int type = stream.readUnsignedByte();
061: switch (type) {
062: case CONSTANT_CLASS:
063: c = new ClassConstant(pool, stream
064: .readUnsignedShort());
065: break;
066: case CONSTANT_FIELDREF:
067: c = new FieldRefConstant(pool, stream
068: .readUnsignedShort(), stream
069: .readUnsignedShort());
070: break;
071: case CONSTANT_METHODREF:
072: c = new MethodRefConstant(pool, stream
073: .readUnsignedShort(), stream
074: .readUnsignedShort());
075: break;
076: case CONSTANT_INTERFACE_METHODREF:
077: c = new InterfaceMethodRefConstant(pool, stream
078: .readUnsignedShort(), stream
079: .readUnsignedShort());
080: break;
081: case CONSTANT_STRING:
082: c = new StringConstant(pool, stream
083: .readUnsignedShort());
084: break;
085: case CONSTANT_INTEGER:
086: c = new IntConstant(pool, stream.readInt());
087: break;
088: case CONSTANT_FLOAT:
089: c = new FloatConstant(pool, stream.readFloat());
090: break;
091: case CONSTANT_LONG:
092: c = new LongConstant(pool, stream.readLong());
093: skipIndex = true;
094: break;
095: case CONSTANT_DOUBLE:
096: c = new DoubleConstant(pool, stream.readDouble());
097: skipIndex = true;
098: break;
099: case CONSTANT_NAME_AND_TYPE:
100: c = new NameAndTypeConstant(pool, stream
101: .readUnsignedShort(), stream
102: .readUnsignedShort());
103: break;
104: case CONSTANT_UTF8:
105: c = new UTF8Constant(pool, stream.readUTF());
106: break;
107: }
108: pool[i] = c;
109: i += skipIndex ? 2 : 1; // double and long constants occupy two entries
110: }
111: return pool;
112: }
113: throw new IOException("Not a class file: Magic number missing.");
114: }
115:
116: private Constant[] _pool;
117:
118: /**
119: * Creates an instance.
120: * @param pool The poole which will be needed to resolve references.
121: */
122: public Constant(Constant[] pool) {
123: _pool = pool;
124: }
125:
126: /**
127: * Returns the specified constant from the pool.
128: * @param index Index of requested constant.
129: */
130: public Constant getConstant(int index) {
131: return _pool[index];
132: }
133: } //class
|