/*
 * 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 $sig and $type. This support class is required at runtime only if $sig or $type is used.
/** * 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 java.lang.Class object is loaded.

If true, it is loaded by:

Thread.currentThread().getContextClassLoader().loadClass()

If false, it is loaded by Class.forName(). The default value is false.

/** * 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 useContextClassLoader.
Since:3.25
/** * 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 ThreadLocal.remvoe().
Since:3.25
/** * 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 $class.
/** * 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 $sig.
/** * 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 $type.
/** * 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; } }