001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.taskdefs.optional.jlink;
019:
020: import java.io.DataInput;
021: import java.io.DataInputStream;
022: import java.io.IOException;
023: import java.io.InputStream;
024:
025: /**
026: * Reads just enough of a class file to determine the class' full name.
027: *
028: * <p>Extremely minimal constant pool implementation, mainly to support extracting
029: * strings from a class file.
030: */
031: class ConstantPool {
032: // CheckStyle:VisibilityModifier OFF - bc
033: static final byte UTF8 = 1, UNUSED = 2, INTEGER = 3, FLOAT = 4,
034: LONG = 5, DOUBLE = 6, CLASS = 7, STRING = 8, FIELDREF = 9,
035: METHODREF = 10, INTERFACEMETHODREF = 11, NAMEANDTYPE = 12;
036:
037: byte[] types;
038:
039: Object[] values;
040:
041: // CheckStyle:VisibilityModifier ON
042:
043: /**
044: * Create a constant pool.
045: * @param data the data input containing the class.
046: * @throws IOException if there is an error.
047: */
048: ConstantPool(DataInput data) throws IOException {
049: super ();
050:
051: int count = data.readUnsignedShort();
052: types = new byte[count];
053: values = new Object[count];
054: // read in all constant pool entries.
055: for (int i = 1; i < count; i++) {
056: byte type = data.readByte();
057: types[i] = type;
058: switch (type) {
059: case UTF8:
060: values[i] = data.readUTF();
061: break;
062:
063: case UNUSED:
064: break;
065:
066: case INTEGER:
067: values[i] = new Integer(data.readInt());
068: break;
069:
070: case FLOAT:
071: values[i] = new Float(data.readFloat());
072: break;
073:
074: case LONG:
075: values[i] = new Long(data.readLong());
076: ++i;
077: break;
078:
079: case DOUBLE:
080: values[i] = new Double(data.readDouble());
081: ++i;
082: break;
083:
084: case CLASS:
085: case STRING:
086: values[i] = new Integer(data.readUnsignedShort());
087: break;
088:
089: case FIELDREF:
090: case METHODREF:
091: case INTERFACEMETHODREF:
092: case NAMEANDTYPE:
093: values[i] = new Integer(data.readInt());
094: break;
095: default:
096: // Do nothing
097: }
098: }
099: }
100: }
101:
102: /**
103: * Provides a quick and dirty way to determine the true name of a class
104: * given just an InputStream. Reads in just enough to perform this
105: * minimal task only.
106: */
107: public class ClassNameReader extends Object {
108:
109: /**
110: * Get the class name of a class in an input stream.
111: *
112: * @param input an <code>InputStream</code> value
113: * @return the name of the class
114: * @exception IOException if an error occurs
115: */
116: public static String getClassName(InputStream input)
117: throws IOException {
118: DataInputStream data = new DataInputStream(input);
119: // verify this is a valid class file.
120: int cookie = data.readInt();
121: if (cookie != 0xCAFEBABE) {
122: return null;
123: }
124: /* int version = */data.readInt();
125: // read the constant pool.
126: ConstantPool constants = new ConstantPool(data);
127: Object[] values = constants.values;
128: // read access flags and class index.
129: /* int accessFlags = */data.readUnsignedShort();
130: int classIndex = data.readUnsignedShort();
131: Integer stringIndex = (Integer) values[classIndex];
132: String className = (String) values[stringIndex.intValue()];
133: return className;
134: }
135:
136: }
|