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

leap.lang.Classes Maven / Gradle / Ivy

/*
 * Copyright 2013 the original author or authors.
 *
 * 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 leap.lang;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import leap.lang.exception.NestedClassNotFoundException;
import leap.lang.io.IO;

public class Classes {
	
	//Maps a primitive class name to its corresponding abbreviation used in array class names.
	private static final Map abbreviationMap = new HashMap();
	
	//Maps an abbreviation used in array class names to corresponding primitive class name.
	private static final Map reverseAbbreviationMap = new HashMap();
	
	static {
		addAbbreviation("int", "I");
		addAbbreviation("boolean", "Z");
		addAbbreviation("float", "F");
		addAbbreviation("long", "J");
		addAbbreviation("short", "S");
		addAbbreviation("byte", "B");
		addAbbreviation("double", "D");
		addAbbreviation("char", "C");
	}	
	
	public static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[]{};
	
	public static final String CLASS_FILE_SUFFIX          = ".class";
	public static final char   PACKAGE_SEPARATOR_CHAR     = '.';
	public static final String PACKAGE_SEPARATOR          = ".";
	public static final char   INNER_CLASS_SEPARATOR_CHAR = '$';

    /**
     * Returns the first class not a void.class or Void.class in the given array.
     */
    public static Class firstNonVoid(Class... cs) {
        if(null == cs) {
            return null;
        }

        for(Class c : cs) {
            if(!(void.class.equals(c) || Void.class.equals(c))) {
                return c;
            }
        }

        return null;
    }
	
	/**
	 * Returns true if the given class name is present.
	 */
	public static boolean isPresent(String className) {
		return tryForName(className) != null;
	}
	
	/**
	 * Returns true if the given class name is present.
	 */
	public static boolean isPresent(ClassLoader classLoader,String className) {
		return tryForName(classLoader,className) != null;
	}
	
	/**
	 * Returns the (initialized) class represented by {@code className} using the current thread's context class loader.
	 * 
	 * @throws NestedClassNotFoundException if the class is not found
	 */
	public static Class forName(String className) throws NestedClassNotFoundException {
		return forName(getClassLoader(),className,true);
	}
	
	/**
	 * Returns the (initialized) class represented by {@code className} using the current thread's context class loader.
	 * 
	 * 

* * returns {@code null} if the class is not found */ public static Class tryForName(String className) { try { return forName(getClassLoader(),className,true); } catch (NestedClassNotFoundException e) { return null; } } /** * Returns the (initialized) class represented by {@code className} using the given class loader. * * @throws NestedClassNotFoundException if the class is not found */ public static Class forName(ClassLoader classLoader, String className) throws NestedClassNotFoundException { return forName(classLoader, className, true); } /** * Returns the (initialized) class represented by {@code className} using the given class loader. * *

* * returns {@code null} if the class is not found */ public static Class tryForName(ClassLoader classLoader, String className) { try { return forName(classLoader, className, true); } catch (NestedClassNotFoundException e) { return null; } } /** * Returns the (initialized) class represented by {@code className} using the given class's loader. * *

* * returns {@code null} if the class is not found */ public static Class tryForName(Class loaderClass,String className) { return tryForName(getClassLoader(loaderClass),className); } /** * Returns the (initialized) class represented by {@code className} using the given class's loader. * * @throws NestedClassNotFoundException if the class is not found */ public static Class forName(Class loaderClass,String className) throws NestedClassNotFoundException { return forName(getClassLoader(loaderClass),className); } /** * returns null if the given class is not a primitive type. * *

* * returns the not null default value if the given class is a primitive type. */ public static Object getDefaultValue(Class type){ if(Integer.TYPE == type){ return 0; } if(Boolean.TYPE == type){ return false; } if(Long.TYPE == type){ return 0L; } if(Float.TYPE == type){ return 0.0f; } if(Double.TYPE == type){ return 0.0d; } if(Short.TYPE == type){ return 0; } if(Byte.TYPE == type){ return 0; } if(Character.TYPE == type){ return '\u0000'; } return null; } public static ClassLoader getClassLoader() { 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 = Classes.class.getClassLoader(); } return cl; } public static ClassLoader getClassLoader(Class clazz) { 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 = clazz.getClassLoader(); } return cl; } public static String getResourceAsString(Class loaderClass,String resource){ return getResourceAsString(loaderClass, resource, Charsets.defaultCharset()); } public static String getResourceAsString(Class loaderClass,String resource,Charset charset){ InputStream is = null; try{ is = loaderClass.getResourceAsStream(resource); if(null == is){ return null; } return IO.readString(is,charset); }finally{ IO.close(is); } } /** * Determine the name of the package of the given class, * e.g. "java.lang" for the {@code 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) { Args.notNull(clazz, "Class must not be null"); return getPackageName(clazz.getName()); } /** * Determine the name of the package of the given fully-qualified class name, * e.g. "java.lang" for the {@code java.lang.String} class name. * @param fqClassName the fully-qualified class name * @return the package name, or the empty String if the class * is defined in the default package */ public static String getPackageName(String fqClassName) { Args.notNull(fqClassName, "Class name must not be null"); int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR); return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : ""); } /** * get the resource path of class object's package. * *

* * a resource path can be used as the input argument of {@link ClassLoader#getResource(String)}. * *

* * e.g. all foo.bar.A.class -> foo/bar * * @return return "" if clazz is null or no package, else return the resource path */ public static String getPackageResourcePath(Class clazz){ if (clazz == null) { return ""; } String className = clazz.getName(); int packageEndIndex = className.lastIndexOf('.'); if (packageEndIndex == -1) { return ""; } String packageName = className.substring(0, packageEndIndex); return packageName.replace('.', '/'); } /** * get the resource path of class object. * *

* * a resource path can be used as the input argument of {@link ClassLoader#getResource(String)}. * *

* * e.g. all foo.bar.A.class -> foo/bar/A.class */ public static String getClassResourcePath(Class clazz){ return clazz.getName().replace('.','/') + CLASS_FILE_SUFFIX; } /** * get the file name of the class file relative to the class object's package. * *

* * e.g java.lang.String.class -> String.class */ public static String getClassFileName(Class clazz) { Args.notNull(clazz, "Class"); String className = clazz.getName(); int lastDotIndex = className.lastIndexOf("."); return className.substring(lastDotIndex + 1) + CLASS_FILE_SUFFIX; } /** *

* Gets the class name minus the package name from a {@code Class}. *

* *

* Consider using the Java 5 API {@link Class#getSimpleName()} instead. The one known difference is that this code * will return {@code "Map.Entry"} while the {@code java.lang.Class} variant will simply return {@code "Entry"}. *

* * @param cls the class to get the short name for. * * @return the class name without the package name or an empty string */ //from apache commons lang public static String getShortName(Class cls) { if (cls == null) { return Strings.EMPTY; } return getShortName(cls.getName()); } /** *

* Gets the class name minus the package name from a String. *

* *

* The string passed in is assumed to be a class name - it is not checked. *

* *

* Note that this method differs from Class.getSimpleName() in that this will return {@code "Map.Entry"} whilst the * {@code java.lang.Class} variant will simply return {@code "Entry"}. *

* * @param className the className to get the short name for * @return the class name of the class without the package name or an empty string */ //from apache commons lang public static String getShortName(String className) { if (className == null) { return Strings.EMPTY; } if (className.length() == 0) { return Strings.EMPTY; } StringBuilder arrayPrefix = new StringBuilder(); // Handle array encoding if (className.startsWith("[")) { while (className.charAt(0) == '[') { className = className.substring(1); arrayPrefix.append("[]"); } // Strip Object type encoding if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') { className = className.substring(1, className.length() - 1); } } if (reverseAbbreviationMap.containsKey(className)) { className = reverseAbbreviationMap.get(className); } int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); int innerIdx = className.indexOf(INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1); String out = className.substring(lastDotIdx + 1); if (innerIdx != -1) { out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR); } return out + arrayPrefix; } public static Annotation[] getAnnotations(Class c) { try { return null == c ? EMPTY_ANNOTATION_ARRAY : c.getAnnotations(); }catch (java.lang.ArrayStoreException e) { //java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy return EMPTY_ANNOTATION_ARRAY; } } public static T getAnnotation(Class c, Class annotationType) { try { return null == c ? null : c.getAnnotation(annotationType); }catch (java.lang.ArrayStoreException e) { //java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy return null; } } public static T getAnnotation(Annotation[] annotations,Class annotationType){ return getAnnotation(annotations, annotationType, false); } @SuppressWarnings("unchecked") public static T getAnnotation(Annotation[] annotations,Class annotationType, boolean meta){ if(null == annotations || annotations.length == 0 || null == annotationType){ return null; } for(int i=0;i metaAnnotationType) { for(Annotation a : annotations){ if(a.annotationType().isAnnotationPresent(metaAnnotationType)){ return a; } } return null; } public static boolean isAnnotationPresent(Class c, Class type) { try { return null != c && c.isAnnotationPresent(type); }catch (java.lang.ArrayStoreException e) { //java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy return false; } } public static boolean isAnnotationPresent(Annotation[] annotations, Class annotationType){ return null != getAnnotation(annotations, annotationType); } public static boolean isAnnotationPresent(Annotation[] annotations, Class annotationType, boolean meta){ return null != getAnnotation(annotations, annotationType, meta); } /** *

* Checks if one {@code Class} can be assigned to a variable of another {@code Class}. *

* *

* Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this method takes into account widenings of * primitive classes and {@code null}s. *

* *

* Primitive widenings allow an int to be assigned to a long, float or double. This method returns the correct * result for these cases. *

* *

* {@code Null} may be assigned to any reference type. This method will return {@code true} if {@code null} is * passed in and the toClass is non-primitive. *

* *

* Specifically, this method tests whether the type represented by the specified {@code Class} parameter can be * converted to the type represented by this {@code Class} object via an identity conversion widening primitive or * widening reference conversion. See * The Java Language Specification, sections 5.1.1, 5.1.2 * and 5.1.4 for details. *

* * @param cls the Class to check, may be null * @param toClass the Class to try to assign into, returns false if null * @return {@code true} if assignment possible */ public static boolean isAssignable(Class cls, Class toClass) { if (toClass == null) { return false; } // have to check for null, as isAssignableFrom doesn't if (cls == null) { return !toClass.isPrimitive(); } //autoboxing: if (cls.isPrimitive() && !toClass.isPrimitive()) { cls = Primitives.wrap(cls); if (cls == null) { return false; } } if (toClass.isPrimitive() && !cls.isPrimitive()) { cls = Primitives.unwrap(cls); if (cls == null) { return false; } } if (cls.equals(toClass)) { return true; } if (cls.isPrimitive()) { if (toClass.isPrimitive() == false) { return false; } if (Integer.TYPE.equals(cls)) { return Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Long.TYPE.equals(cls)) { return Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Boolean.TYPE.equals(cls)) { return false; } if (Double.TYPE.equals(cls)) { return false; } if (Float.TYPE.equals(cls)) { return Double.TYPE.equals(toClass); } if (Character.TYPE.equals(cls)) { return Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Short.TYPE.equals(cls)) { return Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Byte.TYPE.equals(cls)) { return Short.TYPE.equals(toClass) || Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } // should never get here return false; } return toClass.isAssignableFrom(cls); } /** *

Is the specified class an inner class or static nested class.

*/ public static boolean isInnerClass(Class clazz) { return clazz != null && clazz.getEnclosingClass() != null; } /** * Checks if given class is a concrete one; that is, not an interface or abstract class. */ public static boolean isConcreteClass(Class clazz) { if(null == clazz){ return false; } return ! (Modifier.isInterface(clazz.getModifiers()) || Modifier.isAbstract(clazz.getModifiers())); } /** * Check if the given class represents a primitive (i.e. boolean, byte, * char, short, int, long, float, or double) or a primitive wrapper * (i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double). * @param clazz the class to check * @return whether the given class is a primitive or primitive wrapper class */ public static boolean isPrimitiveOrWrapper(Class clazz) { if(null == clazz){ return false; } return (clazz.isPrimitive() || Primitives.isWrapperType(clazz)); } /** * Check if the given type represents a "simple" value type: * a primitive, a String or other CharSequence, a Number, a Date, a Caleandar, a Charset, * a URI, a URL, a Locale or a Class. * @param clazz the type to check * @return whether the given type represents a "simple" value type */ public static boolean isSimpleValueType(Class clazz) { if(null == clazz){ return false; } return isPrimitiveOrWrapper(clazz) || clazz.isEnum() || CharSequence.class.isAssignableFrom(clazz) || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || clazz.equals(Calendar.class) || clazz.equals(Charset.class) || clazz.equals(URI.class) || clazz.equals(URL.class) || clazz.equals(Locale.class) || clazz.equals(Class.class); } public static boolean isVoid(Class clazz){ return null != clazz && (Void.TYPE.equals(clazz) || Void.class.equals(clazz)); } public static boolean isString(Class clazz){ return null == clazz ? false : clazz.equals(String.class); } public static boolean isBoolean(Class clazz){ return null == clazz ? false : clazz.equals(Boolean.TYPE) || clazz.equals(Boolean.class); } public static boolean isDouble(Class clazz){ return null == clazz ? false : clazz.equals(Double.TYPE) || clazz.equals(Double.class); } public static boolean isInteger(Class clazz){ return null == clazz ? false : clazz.equals(Integer.TYPE) || clazz.equals(Integer.class); } public static boolean isLong(Class clazz){ return null == clazz ? false : clazz.equals(Long.TYPE) || clazz.equals(Long.class); } public static boolean isShort(Class clazz){ return null == clazz ? false : clazz.equals(Short.TYPE) || clazz.equals(Short.class); } public static boolean isFloat(Class clazz){ return null == clazz ? false : clazz.equals(Float.TYPE) || clazz.equals(Float.class); } public static boolean isBigDecimal(Class clazz){ return null == clazz ? false : clazz.equals(BigDecimal.class); } public static boolean isBigInteger(Class clazz){ return null == clazz ? false : clazz.equals(BigInteger.class); } public static boolean isCharacter(Class clazz){ return null == clazz ? false : clazz.equals(Character.TYPE) || clazz.equals(Character.class); } //--------------------private methods--------------------------------------------------------------------------------- /** * Returns the class represented by {@code className} using the {@code classLoader}. * *

* * This implementation supports the syntaxes : * *

	 * "{@code int}",
	 * "{@code java.util.Map.Entry[]}", 
	 * "{@code java.util.Map$Entry[]}",
	 * "{@code [Ljava.util.Map.Entry;}", 
	 * "{@code [Ljava.util.Map$Entry;}".
	 * 
* * @throws NestedClassNotFoundException if the class is not found */ private static Class forName(ClassLoader classLoader, String className, boolean initialize) throws NestedClassNotFoundException { try { Class clazz; if (abbreviationMap.containsKey(className)) { String clsName = "[" + abbreviationMap.get(className); clazz = Class.forName(clsName, initialize, classLoader).getComponentType(); } else { clazz = Class.forName(toCanonicalName(className), initialize, classLoader); } return clazz; } catch (NoClassDefFoundError|ClassNotFoundException ex) { // allow path separators (.) as inner class name separators int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); if (lastDotIndex != -1) { try { return forName(classLoader, className.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1), initialize); } catch (NestedClassNotFoundException ex2) { // NOPMD // ignore exception } } throw new NestedClassNotFoundException("Class not found : " + ex.getMessage(),ex); } } /** * Converts a class name to a JLS style class name. */ private static String toCanonicalName(String className) { className = Strings.trim(className); if (className.endsWith("[]")) { StringBuilder classNameBuffer = new StringBuilder(); while (className.endsWith("[]")) { className = className.substring(0, className.length() - 2); classNameBuffer.append("["); } String abbreviation = abbreviationMap.get(className); if (abbreviation != null) { classNameBuffer.append(abbreviation); } else { classNameBuffer.append("L").append(className).append(";"); } className = classNameBuffer.toString(); } return className; } /** * Add primitive type abbreviation to maps of abbreviations. */ private static void addAbbreviation(String primitive, String abbreviation) { abbreviationMap.put(primitive, abbreviation); reverseAbbreviationMap.put(abbreviation, primitive); } protected Classes(){ } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy