- /*
- * Javassist, a Java-bytecode translator toolkit.
- * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. Alternatively, the contents of this file may be used under
- * the terms of the GNU Lesser General Public License Version 2.1 or later,
- * or the Apache License Version 2.0.
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- */
-
- package javassist.runtime;
-
- /**
- * A support class for implementing <code>$sig</code> and
- * <code>$type</code>.
- * This support class is required at runtime
- * only if <code>$sig</code> or <code>$type</code> is used.
- */
- public class Desc {
-
- /**
- * Specifies how a <code>java.lang.Class</code> object is loaded.
- *
- * <p>If true, it is loaded by:
- * <pre>Thread.currentThread().getContextClassLoader().loadClass()</pre>
- * <p>If false, it is loaded by <code>Class.forName()</code>.
- * The default value is false.
- */
- public static boolean useContextClassLoader = false;
-
- private static final ThreadLocal<Boolean> USE_CONTEXT_CLASS_LOADER_LOCALLY = new ThreadLocal<Boolean>() {
- @Override
- protected Boolean initialValue() {
- return false;
- }
- };
-
- /**
- * Changes so that the current thread will use the context class loader
- * when a class is loaded.
- * This method changes the behavior per thread unlike {@link useContextClassLoader}.
- *
- * @since 3.25
- */
- public static void setUseContextClassLoaderLocally() {
- USE_CONTEXT_CLASS_LOADER_LOCALLY.set(true);
- }
-
- /**
- * Changes so that the current thread will not use the context class loader
- * when a class is loaded.
- * Call this method before releasing the current thread for reuse.
- * It invokes <code>ThreadLocal.remvoe()</code>.
- *
- * @since 3.25
- */
- public static void resetUseContextClassLoaderLocally() {
- USE_CONTEXT_CLASS_LOADER_LOCALLY.remove();
- }
-
- private static Class<?> getClassObject(String name)
- throws ClassNotFoundException
- {
- if (useContextClassLoader || USE_CONTEXT_CLASS_LOADER_LOCALLY.get())
- return Class.forName(name, true, Thread.currentThread().getContextClassLoader());
- return Class.forName(name);
- }
-
- /**
- * Interprets the given class name.
- * It is used for implementing <code>$class</code>.
- */
- public static Class<?> getClazz(String name) {
- try {
- return getClassObject(name);
- }
- catch (ClassNotFoundException e) {
- throw new RuntimeException(
- "$class: internal error, could not find class '" + name
- + "' (Desc.useContextClassLoader: "
- + Boolean.toString(useContextClassLoader) + ")", e);
- }
- }
-
- /**
- * Interprets the given type descriptor representing a method
- * signature. It is used for implementing <code>$sig</code>.
- */
- public static Class<?>[] getParams(String desc) {
- if (desc.charAt(0) != '(')
- throw new RuntimeException("$sig: internal error");
-
- return getType(desc, desc.length(), 1, 0);
- }
-
- /**
- * Interprets the given type descriptor.
- * It is used for implementing <code>$type</code>.
- */
- public static Class<?> getType(String desc) {
- Class<?>[] result = getType(desc, desc.length(), 0, 0);
- if (result == null || result.length != 1)
- throw new RuntimeException("$type: internal error");
-
- return result[0];
- }
-
- private static Class<?>[] getType(String desc, int descLen,
- int start, int num) {
- Class<?> clazz;
- if (start >= descLen)
- return new Class[num];
-
- char c = desc.charAt(start);
- switch (c) {
- case 'Z' :
- clazz = Boolean.TYPE;
- break;
- case 'C' :
- clazz = Character.TYPE;
- break;
- case 'B' :
- clazz = Byte.TYPE;
- break;
- case 'S' :
- clazz = Short.TYPE;
- break;
- case 'I' :
- clazz = Integer.TYPE;
- break;
- case 'J' :
- clazz = Long.TYPE;
- break;
- case 'F' :
- clazz = Float.TYPE;
- break;
- case 'D' :
- clazz = Double.TYPE;
- break;
- case 'V' :
- clazz = Void.TYPE;
- break;
- case 'L' :
- case '[' :
- return getClassType(desc, descLen, start, num);
- default :
- return new Class[num];
- }
-
- Class<?>[] result = getType(desc, descLen, start + 1, num + 1);
- result[num] = clazz;
- return result;
- }
-
- private static Class<?>[] getClassType(String desc, int descLen,
- int start, int num) {
- int end = start;
- while (desc.charAt(end) == '[')
- ++end;
-
- if (desc.charAt(end) == 'L') {
- end = desc.indexOf(';', end);
- if (end < 0)
- throw new IndexOutOfBoundsException("bad descriptor");
- }
-
- String cname;
- if (desc.charAt(start) == 'L')
- cname = desc.substring(start + 1, end);
- else
- cname = desc.substring(start, end + 1);
-
- Class<?>[] result = getType(desc, descLen, end + 1, num + 1);
- try {
- result[num] = getClassObject(cname.replace('/', '.'));
- }
- catch (ClassNotFoundException e) {
- // "new RuntimeException(e)" is not available in JDK 1.3.
- throw new RuntimeException(e.getMessage());
- }
-
- return result;
- }
- }
|