001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.runtime;
017:
018: /**
019: * A support class for implementing <code>$sig</code> and
020: * <code>$type</code>.
021: * This support class is required at runtime
022: * only if <code>$sig</code> or <code>$type</code> is used.
023: */
024: public class Desc {
025:
026: /**
027: * Specifies how a <code>java.lang.Class</code> object is loaded.
028: *
029: * <p>If true, it is loaded by:
030: * <ul><pre>Thread.currentThread().getContextClassLoader().loadClass()</pre></ul>
031: * <p>If false, it is loaded by <code>Class.forName()</code>.
032: * The default value is false.
033: */
034: public static boolean useContextClassLoader = false;
035:
036: private static Class getClassObject(String name)
037: throws ClassNotFoundException {
038: if (useContextClassLoader)
039: return Thread.currentThread().getContextClassLoader()
040: .loadClass(name);
041: else
042: return Class.forName(name);
043: }
044:
045: /**
046: * Interprets the given class name.
047: * It is used for implementing <code>$class</code>.
048: */
049: public static Class getClazz(String name) {
050: try {
051: return getClassObject(name);
052: } catch (ClassNotFoundException e) {
053: throw new RuntimeException("$class: internal error");
054: }
055: }
056:
057: /**
058: * Interprets the given type descriptor representing a method
059: * signature. It is used for implementing <code>$sig</code>.
060: */
061: public static Class[] getParams(String desc) {
062: if (desc.charAt(0) != '(')
063: throw new RuntimeException("$sig: internal error");
064:
065: return getType(desc, desc.length(), 1, 0);
066: }
067:
068: /**
069: * Interprets the given type descriptor.
070: * It is used for implementing <code>$type</code>.
071: */
072: public static Class getType(String desc) {
073: Class[] result = getType(desc, desc.length(), 0, 0);
074: if (result == null || result.length != 1)
075: throw new RuntimeException("$type: internal error");
076:
077: return result[0];
078: }
079:
080: private static Class[] getType(String desc, int descLen, int start,
081: int num) {
082: Class clazz;
083: if (start >= descLen)
084: return new Class[num];
085:
086: char c = desc.charAt(start);
087: switch (c) {
088: case 'Z':
089: clazz = Boolean.TYPE;
090: break;
091: case 'C':
092: clazz = Character.TYPE;
093: break;
094: case 'B':
095: clazz = Byte.TYPE;
096: break;
097: case 'S':
098: clazz = Short.TYPE;
099: break;
100: case 'I':
101: clazz = Integer.TYPE;
102: break;
103: case 'J':
104: clazz = Long.TYPE;
105: break;
106: case 'F':
107: clazz = Float.TYPE;
108: break;
109: case 'D':
110: clazz = Double.TYPE;
111: break;
112: case 'V':
113: clazz = Void.TYPE;
114: break;
115: case 'L':
116: case '[':
117: return getClassType(desc, descLen, start, num);
118: default:
119: return new Class[num];
120: }
121:
122: Class[] result = getType(desc, descLen, start + 1, num + 1);
123: result[num] = clazz;
124: return result;
125: }
126:
127: private static Class[] getClassType(String desc, int descLen,
128: int start, int num) {
129: int end = start;
130: while (desc.charAt(end) == '[')
131: ++end;
132:
133: if (desc.charAt(end) == 'L') {
134: end = desc.indexOf(';', end);
135: if (end < 0)
136: throw new IndexOutOfBoundsException("bad descriptor");
137: }
138:
139: String cname;
140: if (desc.charAt(start) == 'L')
141: cname = desc.substring(start + 1, end);
142: else
143: cname = desc.substring(start, end + 1);
144:
145: Class[] result = getType(desc, descLen, end + 1, num + 1);
146: try {
147: result[num] = getClassObject(cname.replace('/', '.'));
148: } catch (ClassNotFoundException e) {
149: // "new RuntimeException(e)" is not available in JDK 1.3.
150: throw new RuntimeException(e.getMessage());
151: }
152:
153: return result;
154: }
155: }
|