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

com.phloc.commons.lang.ClassHelper Maven / Gradle / Ivy

There is a newer version: 5.0.0
Show newest version
/**
 * Copyright (C) 2006-2014 phloc systems
 * http://www.phloc.com
 * office[at]phloc[dot]com
 *
 * 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.phloc.commons.lang;

import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import com.phloc.commons.ValueEnforcer;
import com.phloc.commons.annotations.PresentForCodeCoverage;
import com.phloc.commons.annotations.ReturnsImmutableObject;
import com.phloc.commons.collections.ContainerHelper;
import com.phloc.commons.priviledged.PrivilegedActionGetClassLoader;
import com.phloc.commons.priviledged.PrivilegedActionGetContextClassLoader;
import com.phloc.commons.priviledged.PrivilegedActionGetSystemClassLoader;

/**
 * Small class helper utility stuff class.
 * 
 * @author Philip Helger
 */
@Immutable
public final class ClassHelper
{
  // WeakHashMap because class is used as a key
  private static final Map , Class > PRIMITIVE_TO_WRAPPER = new WeakHashMap , Class > (8);
  private static final Map , Class > WRAPPER_TO_PRIMITIVE = new WeakHashMap , Class > (8);

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

  private static void _registerPrimitiveMapping (@Nonnull final Class  aPrimitiveType,
                                                 @Nonnull final Class  aPrimitiveWrapperType)
  {
    PRIMITIVE_TO_WRAPPER.put (aPrimitiveType, aPrimitiveWrapperType);
    WRAPPER_TO_PRIMITIVE.put (aPrimitiveWrapperType, aPrimitiveType);
  }

  @PresentForCodeCoverage
  @SuppressWarnings ("unused")
  private static final ClassHelper s_aInstance = new ClassHelper ();

  private ClassHelper ()
  {}

  @Nonnull
  public static ClassLoader getSystemClassLoader ()
  {
    if (System.getSecurityManager () == null)
      return ClassLoader.getSystemClassLoader ();

    return AccessController.doPrivileged (new PrivilegedActionGetSystemClassLoader ());
  }

  @Nonnull
  public static ClassLoader getContextClassLoader ()
  {
    if (System.getSecurityManager () == null)
      return Thread.currentThread ().getContextClassLoader ();

    return AccessController.doPrivileged (new PrivilegedActionGetContextClassLoader ());
  }

  @Nonnull
  public static ClassLoader getClassClassLoader (@Nonnull final Class  aClass)
  {
    if (System.getSecurityManager () == null)
      return aClass.getClassLoader ();

    return AccessController.doPrivileged (new PrivilegedActionGetClassLoader (aClass));
  }

  @Nonnull
  public static ClassLoader getDefaultClassLoader ()
  {
    ClassLoader ret = null;
    try
    {
      ret = getContextClassLoader ();
    }
    catch (final Exception ex) // NOPMD
    {
      // e.g. security exception
    }

    // Fallback to class loader of this class
    if (ret == null)
      ret = getClassClassLoader (ClassHelper.class);

    return ret;
  }

  public static boolean isPublicClass (@Nullable final Class  aClass)
  {
    if (aClass == null)
      return false;

    // Interfaces or annotations are not allowed
    if (aClass.isInterface () || aClass.isAnnotation ())
      return false;

    // Only public classes are allowed
    if (!isPublic (aClass))
      return false;

    // Abstract classes are not allowed
    if (isAbstractClass (aClass))
      return false;

    return true;
  }

  /**
   * Check if the passed class is public, instancable and has a no-argument
   * constructor.
   * 
   * @param aClass
   *        The class to check. May be null.
   * @return true if the class is public, instancable and has a
   *         no-argument constructor that is public.
   */
  public static boolean isInstancableClass (@Nullable final Class  aClass)
  {
    if (!isPublicClass (aClass))
      return false;

    // Check if a default constructor is present
    try
    {
      aClass.getConstructor ((Class  []) null);
    }
    catch (final NoSuchMethodException ex)
    {
      return false;
    }
    return true;
  }

  public static boolean isPublic (@Nullable final Class  aClass)
  {
    return aClass != null && Modifier.isPublic (aClass.getModifiers ());
  }

  /**
   * Check if the passed class is an interface or not. Please note that
   * annotations are also interfaces!
   * 
   * @param aClass
   *        The class to check.
   * @return true if the class is an interface (or an annotation)
   */
  public static boolean isInterface (@Nullable final Class  aClass)
  {
    return aClass != null && Modifier.isInterface (aClass.getModifiers ());
  }

  public static boolean isAnnotationClass (@Nullable final Class  aClass)
  {
    return aClass != null && aClass.isAnnotation ();
  }

  public static boolean isEnumClass (@Nullable final Class  aClass)
  {
    return aClass != null && aClass.isEnum ();
  }

  /**
   * Check if the passed class is abstract or not. Note: interfaces and
   * annotations are also considered as abstract whereas arrays are never
   * abstract.
   * 
   * @param aClass
   *        The class to check.
   * @return true if the passed class is abstract
   */
  public static boolean isAbstractClass (@Nullable final Class  aClass)
  {
    // Special case for arrays (see documentation of Class.getModifiers: only
    // final and interface are set, the rest is indeterministic)
    return aClass != null && !aClass.isArray () && Modifier.isAbstract (aClass.getModifiers ());
  }

  public static boolean isArrayClass (@Nullable final Class  aClass)
  {
    return aClass != null && aClass.isArray ();
  }

  public static boolean isPrimitiveType (@Nullable final Class  aClass)
  {
    return aClass != null && PRIMITIVE_TO_WRAPPER.containsKey (aClass);
  }

  public static boolean isPrimitiveWrapperType (@Nullable final Class  aClass)
  {
    return aClass != null && WRAPPER_TO_PRIMITIVE.containsKey (aClass);
  }

  /**
   * Get the primitive wrapper class of the passed primitive class.
   * 
   * @param aClass
   *        The primitive class. May be null.
   * @return null if the passed class is not a primitive class.
   */
  @Nullable
  public static Class  getPrimitiveWrapperClass (@Nullable final Class  aClass)
  {
    if (isPrimitiveWrapperType (aClass))
      return aClass;
    return PRIMITIVE_TO_WRAPPER.get (aClass);
  }

  /**
   * Get the primitive class of the passed primitive wrapper class.
   * 
   * @param aClass
   *        The primitive wrapper class. May be null.
   * @return null if the passed class is not a primitive wrapper
   *         class.
   */
  @Nullable
  public static Class  getPrimitiveClass (@Nullable final Class  aClass)
  {
    if (isPrimitiveType (aClass))
      return aClass;
    return WRAPPER_TO_PRIMITIVE.get (aClass);
  }

  @Nonnull
  @ReturnsImmutableObject
  public static Set > getAllPrimitiveClasses ()
  {
    return ContainerHelper.makeUnmodifiable (PRIMITIVE_TO_WRAPPER.keySet ());
  }

  @Nonnull
  @ReturnsImmutableObject
  public static Set > getAllPrimitiveWrapperClasses ()
  {
    return ContainerHelper.makeUnmodifiable (WRAPPER_TO_PRIMITIVE.keySet ());
  }

  public static boolean isStringClass (@Nullable final Class  aClass)
  {
    if (aClass == null)
      return false;
    // Base class of String, StringBuffer and StringBuilder
    return CharSequence.class.isAssignableFrom (aClass);
  }

  public static boolean isCharacterClass (@Nullable final Class  aClass)
  {
    if (aClass == null)
      return false;
    return Character.class.isAssignableFrom (aClass) || char.class.isAssignableFrom (aClass);
  }

  public static boolean isBooleanClass (@Nullable final Class  aClass)
  {
    if (aClass == null)
      return false;
    return Boolean.class.isAssignableFrom (aClass) || boolean.class.isAssignableFrom (aClass);
  }

  public static boolean isFloatingPointClass (@Nullable final Class  aClass)
  {
    if (aClass == null)
      return false;
    return Double.class.isAssignableFrom (aClass) ||
           double.class.isAssignableFrom (aClass) ||
           Float.class.isAssignableFrom (aClass) ||
           float.class.isAssignableFrom (aClass) ||
           BigDecimal.class.isAssignableFrom (aClass);
  }

  public static boolean isIntegerClass (@Nullable final Class  aClass)
  {
    if (aClass == null)
      return false;
    return Byte.class.isAssignableFrom (aClass) ||
           byte.class.isAssignableFrom (aClass) ||
           Integer.class.isAssignableFrom (aClass) ||
           int.class.isAssignableFrom (aClass) ||
           Long.class.isAssignableFrom (aClass) ||
           long.class.isAssignableFrom (aClass) ||
           Short.class.isAssignableFrom (aClass) ||
           short.class.isAssignableFrom (aClass) ||
           BigInteger.class.isAssignableFrom (aClass);
  }

  /**
   * Check if the passed classes are convertible. Includes conversion checks
   * between primitive types and primitive wrapper types.
   * 
   * @param aSrcClass
   *        First class. May not be null.
   * @param aDstClass
   *        Second class. May not be null.
   * @return true if the classes are directly convertible.
   */
  public static boolean areConvertibleClasses (@Nonnull final Class  aSrcClass, @Nonnull final Class  aDstClass)
  {
    ValueEnforcer.notNull (aSrcClass, "SrcClass");
    ValueEnforcer.notNull (aDstClass, "DstClass");

    // Same class?
    if (aDstClass.equals (aSrcClass))
      return true;

    // Default assignable
    if (aDstClass.isAssignableFrom (aSrcClass))
      return true;

    // Special handling for "int.class" == "Integer.class" etc.
    if (aDstClass == getPrimitiveWrapperClass (aSrcClass))
      return true;
    if (aDstClass == getPrimitiveClass (aSrcClass))
      return true;

    // Not convertible
    return false;
  }

  /**
   * null-safe helper method to determine the class of an object.
   * 
   * @param aObject
   *        The object to query. May be null.
   * @return null if the passed object is null.
   */
  @Nullable
  public static Class  getClass (@Nullable final Object aObject)
  {
    return aObject == null ? null : aObject.getClass ();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy