001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1999 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: *
054: */
055:
056: package com.sun.portal.providers.jsp.jasper3.jasper.compiler;
057:
058: import com.sun.portal.providers.jsp.jasper3.jasper.JasperException;
059:
060: import java.io.DataInputStream;
061: import java.io.FileInputStream;
062: import java.io.InputStream;
063: import java.io.IOException;
064:
065: import com.sun.portal.providers.jsp.jasper3.jasper.Constants;
066:
067: /**
068: * Parse a .class file to figure out the name of the class from which
069: * it was generated.
070: *
071: * @author Anil Vijendran
072: */
073: public class ClassName {
074:
075: static String processClassData(InputStream in)
076: throws JasperException, IOException {
077: DataInputStream din = new DataInputStream(in);
078: din.readInt(); // magic
079: din.readUnsignedShort(); // majorVersion
080: din.readUnsignedShort(); // minorVersion
081: int count = din.readUnsignedShort(); // #constant pool entries
082: ConstantPool[] constantPool = new ConstantPool[count];
083: constantPool[0] = new ConstantPool();
084: for (int i = 1; i < constantPool.length; i++) {
085: constantPool[i] = new ConstantPool();
086: if (!constantPool[i].read(din))
087: throw new JasperException(Constants
088: .getString("jsp.error.classname"));
089: // These two types take up "two" spots in the table
090: if ((constantPool[i].type == ConstantPool.LONG)
091: || (constantPool[i].type == ConstantPool.DOUBLE))
092: i++;
093: }
094:
095: for (int i = 1; i < constantPool.length; i++) {
096: if (constantPool[i] == null)
097: continue;
098: if (constantPool[i].index1 > 0)
099: constantPool[i].arg1 = constantPool[constantPool[i].index1];
100: if (constantPool[i].index2 > 0)
101: constantPool[i].arg2 = constantPool[constantPool[i].index2];
102: }
103: int accessFlags = din.readUnsignedShort();
104: ConstantPool this Class = constantPool[din.readUnsignedShort()];
105: din.close();
106: return printClassName(this Class.arg1.strValue);
107: }
108:
109: private static String printClassName(String s) {
110: StringBuffer x;
111:
112: if (s.charAt(0) == '[') {
113: return (typeString(s, ""));
114: }
115:
116: x = new StringBuffer();
117: for (int j = 0; j < s.length(); j++) {
118: if (s.charAt(j) == '/')
119: x.append('.');
120: else
121: x.append(s.charAt(j));
122: }
123: return (x.toString());
124: }
125:
126: private static String typeString(String typeString, String varName) {
127: int isArray = 0;
128: int ndx = 0;
129: StringBuffer x = new StringBuffer();
130:
131: while (typeString.charAt(ndx) == '[') {
132: isArray++;
133: ndx++;
134: }
135:
136: switch (typeString.charAt(ndx)) {
137: case 'B':
138: x.append("byte ");
139: break;
140: case 'C':
141: x.append("char ");
142: break;
143: case 'D':
144: x.append("double ");
145: break;
146: case 'F':
147: x.append("float ");
148: break;
149: case 'I':
150: x.append("int ");
151: break;
152: case 'J':
153: x.append("long ");
154: break;
155: case 'L':
156: for (int i = ndx + 1; i < typeString.indexOf(';'); i++) {
157: if (typeString.charAt(i) != '/')
158: x.append(typeString.charAt(i));
159: else
160: x.append('.');
161: }
162: x.append(" ");
163: break;
164: case 'V':
165: x.append("void ");
166: break;
167: case 'S':
168: x.append("short ");
169: break;
170: case 'Z':
171: x.append("boolean ");
172: break;
173: }
174: x.append(varName);
175: while (isArray > 0) {
176: x.append("[]");
177: isArray--;
178: }
179: return (x.toString());
180: }
181:
182: public static String getClassName(String classFile)
183: throws JasperException {
184: try {
185: // System.out.println("Getting class name from class data");
186: FileInputStream fin = new FileInputStream(classFile);
187: return processClassData(fin);
188: } catch (IOException ex) {
189: throw new JasperException(Constants
190: .getString("jsp.error.classname"), ex);
191: }
192: }
193:
194: public static void main(String[] args) {
195: try {
196: for (int i = 0; i < args.length; i++)
197: System.out.println("Filename: " + args[i]
198: + " Classname: " + getClassName(args[i]));
199: } catch (Exception ex) {
200: ex.printStackTrace();
201: }
202: }
203: }
204:
205: class ConstantPool {
206: int type; // type of this item
207: String name; // String for the type
208: ConstantPool arg1; // index to first argument
209: ConstantPool arg2; // index to second argument
210: int index1, index2;
211: String strValue; // ASCIZ String value
212: int intValue;
213: long longValue;
214: float floatValue;
215: double doubleValue;
216:
217: public static final int CLASS = 7;
218: public static final int FIELDREF = 9;
219: public static final int METHODREF = 10;
220: public static final int STRING = 8;
221: public static final int INTEGER = 3;
222: public static final int FLOAT = 4;
223: public static final int LONG = 5;
224: public static final int DOUBLE = 6;
225: public static final int INTERFACE = 11;
226: public static final int NAMEANDTYPE = 12;
227: public static final int ASCIZ = 1;
228: public static final int UNICODE = 2;
229:
230: /**
231: * Generic constructor
232: */
233: public ConstantPool() {
234: index1 = -1;
235: index2 = -1;
236: arg1 = null;
237: arg2 = null;
238: type = -1;
239: }
240:
241: public boolean read(DataInputStream din) throws IOException {
242: int len;
243: char c;
244:
245: type = din.readByte();
246: switch (type) {
247: case CLASS:
248: name = "Class";
249: index1 = din.readUnsignedShort();
250: index2 = -1;
251: break;
252: case FIELDREF:
253: name = "Field Reference";
254: index1 = din.readUnsignedShort();
255: index2 = din.readUnsignedShort();
256: break;
257: case METHODREF:
258: name = "Method Reference";
259: index1 = din.readUnsignedShort();
260: index2 = din.readUnsignedShort();
261: break;
262: case INTERFACE:
263: name = "Interface Method Reference";
264: index1 = din.readUnsignedShort();
265: index2 = din.readUnsignedShort();
266: break;
267: case NAMEANDTYPE:
268: name = "Name and Type";
269: index1 = din.readUnsignedShort();
270: index2 = din.readUnsignedShort();
271: break;
272: case STRING:
273: name = "String";
274: index1 = din.readUnsignedShort();
275: index2 = -1;
276: break;
277: case INTEGER:
278: name = "Integer";
279: intValue = din.readInt();
280: break;
281: case FLOAT:
282: name = "Float";
283: floatValue = din.readFloat();
284: break;
285: case LONG:
286: name = "Long";
287: longValue = din.readLong();
288: break;
289: case DOUBLE:
290: name = "Double";
291: doubleValue = din.readDouble();
292: break;
293: case ASCIZ:
294: case UNICODE:
295: if (type == ASCIZ)
296: name = "ASCIZ";
297: else
298: name = "UNICODE";
299:
300: StringBuffer xxBuf = new StringBuffer();
301:
302: len = din.readUnsignedShort();
303: while (len > 0) {
304: c = (char) (din.readByte());
305: xxBuf.append(c);
306: len--;
307: }
308: strValue = xxBuf.toString();
309: break;
310: default:
311: System.err.println(Constants
312: .getString("jsp.warning.bad.type"));
313: }
314: return (true);
315: }
316: }
|