All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ovea.tajin.framework.jmx.ClassUtils Maven / Gradle / Ivy

There is a newer version: 3.9
Show newest version
/**
 * Copyright (C) 2011 Ovea 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ovea.tajin.framework.jmx;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author Mathieu Carbou ([email protected])
 */
public final class ClassUtils {

    private ClassUtils() {
    }

    /**
     * Suffix for array class names: "[]"
     */
    private static final String ARRAY_SUFFIX = "[]";

    /**
     * Prefix for internal array class names: "["
     */
    private static final String INTERNAL_ARRAY_PREFIX = "[";

    /**
     * Prefix for internal non-primitive array class names: "[L"
     */
    private static final String NON_PRIMITIVE_ARRAY_PREFIX = "[L";

    /**
     * The package separator character '.'
     */
    private static final char PACKAGE_SEPARATOR = '.';

    /**
     * The inner class separator character '$'
     */
    private static final char INNER_CLASS_SEPARATOR = '$';

    /**
     * The CGLIB class separator character "$$"
     */
    private static final String CGLIB_CLASS_SEPARATOR = "$$";

    /**
     * Map with primitive wrapper type as key and corresponding primitive
     * type as value, for example: Integer.class -> int.class.
     */
    private static final Map, Class> primitiveWrapperTypeMap = new HashMap, Class>(8);

    /**
     * Map with primitive type name as key and corresponding primitive
     * type as value, for example: "int" -> "int.class".
     */
    private static final Map> primitiveTypeNameMap = new HashMap>(16);

    /**
     * Map with common "java.lang" class name as key and corresponding Class as value.
     * Primarily for efficient deserialization of remote invocations.
     */
    private static final Map> commonClassCache = new HashMap>(32);

    static {
        primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
        primitiveWrapperTypeMap.put(Byte.class, byte.class);
        primitiveWrapperTypeMap.put(Character.class, char.class);
        primitiveWrapperTypeMap.put(Double.class, double.class);
        primitiveWrapperTypeMap.put(Float.class, float.class);
        primitiveWrapperTypeMap.put(Integer.class, int.class);
        primitiveWrapperTypeMap.put(Long.class, long.class);
        primitiveWrapperTypeMap.put(Short.class, short.class);

        for (Map.Entry, Class> entry : primitiveWrapperTypeMap.entrySet()) {
            registerCommonClasses(entry.getKey());
        }

        Set> primitiveTypes = new HashSet>(16);
        primitiveTypes.addAll(primitiveWrapperTypeMap.values());
        primitiveTypes.addAll(Arrays.asList(
            boolean[].class, byte[].class, char[].class, double[].class,
            float[].class, int[].class, long[].class, short[].class));
        for (Class primitiveType : primitiveTypes) {
            primitiveTypeNameMap.put(primitiveType.getName(), primitiveType);
        }

        registerCommonClasses(Boolean[].class, Byte[].class, Character[].class, Double[].class,
            Float[].class, Integer[].class, Long[].class, Short[].class);
        registerCommonClasses(Number.class, Number[].class, String.class, String[].class,
            Object.class, Object[].class, Class.class, Class[].class);
        registerCommonClasses(Throwable.class, Exception.class, RuntimeException.class,
            Error.class, StackTraceElement.class, StackTraceElement[].class);
    }

    private static void registerCommonClasses(Class... commonClasses) {
        for (Class clazz : commonClasses) {
            commonClassCache.put(clazz.getName(), clazz);

        }
    }

    /**
     * Return the default ClassLoader to use: typically the thread context
     * ClassLoader, if available; the ClassLoader that loaded the ClassUtils
     * class will be used as fallback.
     * 

Call this method if you intend to use the thread context ClassLoader * in a scenario where you absolutely need a non-null ClassLoader reference: * for example, for class path resource loading (but not necessarily for * Class.forName, which accepts a null ClassLoader * reference as well). * * @return the default ClassLoader (never null) * @see Thread#getContextClassLoader() */ public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back to system class loader... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassUtils.class.getClassLoader(); } return cl; } /** * Replacement for Class.forName() that also returns Class instances * for primitives (e.g."int") and array class names (e.g. "String[]"). * Furthermore, it is also capable of resolving inner class names in Java source * style (e.g. "java.lang.Thread.State" instead of "java.lang.Thread$State"). * * @param name the name of the Class * @param classLoader the class loader to use * (may be null, which indicates the default class loader) * @return Class instance for the supplied name * @throws ClassNotFoundException if the class was not found * @throws LinkageError if the class file could not be loaded * @see Class#forName(String, boolean, ClassLoader) */ public static Class forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError { Class clazz = resolvePrimitiveClassName(name); if (clazz == null) { clazz = commonClassCache.get(name); } if (clazz != null) { return clazz; } // "java.lang.String[]" style arrays if (name.endsWith(ARRAY_SUFFIX)) { String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); Class elementClass = forName(elementClassName, classLoader); return Array.newInstance(elementClass, 0).getClass(); } // "[Ljava.lang.String;" style arrays if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) { String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1); Class elementClass = forName(elementName, classLoader); return Array.newInstance(elementClass, 0).getClass(); } // "[[I" or "[[Ljava.lang.String;" style arrays if (name.startsWith(INTERNAL_ARRAY_PREFIX)) { String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length()); Class elementClass = forName(elementName, classLoader); return Array.newInstance(elementClass, 0).getClass(); } ClassLoader classLoaderToUse = classLoader; if (classLoaderToUse == null) { classLoaderToUse = getDefaultClassLoader(); } try { return classLoaderToUse.loadClass(name); } catch (ClassNotFoundException ex) { int lastDotIndex = name.lastIndexOf('.'); if (lastDotIndex != -1) { String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1); try { return classLoaderToUse.loadClass(innerClassName); } catch (ClassNotFoundException ex2) { // swallow - let original exception get through } } throw ex; } } /** * Resolve the given class name as primitive class, if appropriate, * according to the JVM's naming rules for primitive classes. *

Also supports the JVM's internal class names for primitive arrays. * Does not support the "[]" suffix notation for primitive arrays; * this is only supported by {@link #forName(String, ClassLoader)}. * * @param name the name of the potentially primitive class * @return the primitive class, or null if the name does not denote * a primitive class or primitive array class */ public static Class resolvePrimitiveClassName(String name) { Class result = null; // Most class names will be quite long, considering that they // SHOULD sit in a package, so a length check is worthwhile. if (name != null && name.length() <= 8) { // Could be a primitive - likely. result = primitiveTypeNameMap.get(name); } return result; } /** * Determine whether the {@link Class} identified by the supplied name is present * and can be loaded. Will return false if either the class or * one of its dependencies is not present or cannot be loaded. * * @param className the name of the class to check * @param classLoader the class loader to use * (may be null, which indicates the default class loader) * @return whether the specified class is present */ public static boolean isPresent(String className, ClassLoader classLoader) { try { forName(className, classLoader); return true; } catch (Throwable ex) { // Class or one of its dependencies is not present... return false; } } /** * Get the class name without the qualified package name. * * @param className the className to get the short name for * @return the class name of the class without the package name * @throws IllegalArgumentException if the className is empty */ public static String getShortName(String className) { int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR); if (nameEndIndex == -1) { nameEndIndex = className.length(); } String shortName = className.substring(lastDotIndex + 1, nameEndIndex); shortName = shortName.replace(INNER_CLASS_SEPARATOR, PACKAGE_SEPARATOR); return shortName; } /** * Get the class name without the qualified package name. * * @param clazz the class to get the short name for * @return the class name of the class without the package name */ public static String getShortName(Class clazz) { return getShortName(getQualifiedName(clazz)); } /** * Determine the name of the package of the given class: * e.g. "java.lang" for the java.lang.String class. * * @param clazz the class * @return the package name, or the empty String if the class * is defined in the default package */ public static String getPackageName(Class clazz) { String className = clazz.getName(); int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); return (lastDotIndex != -1 ? className.substring(0, lastDotIndex) : ""); } /** * Return the qualified name of the given class: usually simply * the class name, but component type class name + "[]" for arrays. * * @param clazz the class * @return the qualified name of the class */ public static String getQualifiedName(Class clazz) { if (clazz.isArray()) { return getQualifiedNameForArray(clazz); } else { return clazz.getName(); } } /** * Build a nice qualified name for an array: * component type class name + "[]". * * @param clazz the array class * @return a qualified name for the array class */ private static String getQualifiedNameForArray(Class clazz) { StringBuilder result = new StringBuilder(); while (clazz.isArray()) { clazz = clazz.getComponentType(); result.append(ClassUtils.ARRAY_SUFFIX); } result.insert(0, clazz.getName()); return result.toString(); } /** * Check if the right-hand side type may be assigned to the left-hand side * type, assuming setting by reflection. Considers primitive wrapper * classes as assignable to the corresponding primitive types. * * @param lhsType the target type * @param rhsType the value type that should be assigned to the target type * @return if the target type is assignable from the value type */ public static boolean isAssignable(Class lhsType, Class rhsType) { return (lhsType.isAssignableFrom(rhsType) || lhsType.equals(primitiveWrapperTypeMap.get(rhsType))); } /** * Determine if the given type is assignable from the given value, * assuming setting by reflection. Considers primitive wrapper classes * as assignable to the corresponding primitive types. * * @param type the target type * @param value the value that should be assigned to the type * @return if the type is assignable from the value */ public static boolean isAssignableValue(Class type, Object value) { return (value != null ? isAssignable(type, value.getClass()) : !type.isPrimitive()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy