@SuppressWarnings("unchecked") public static <T>T classForName(final String preferredClassName,final Class<? extends T> defaultClass,final Class<T> sharedClassOrInterface,final ClassLoader classLoader){
  final ClassPathUtilRequestConfig requestConfig=new ClassPathUtilRequestConfig(preferredClassName,defaultClass,sharedClassOrInterface,classLoader);
  try {
    if (cache.containsKey(requestConfig)) {
      final Class<?> cls=cache.get(requestConfig);
      return cls == null ? null : (T)cls.newInstance();
    }
    if (defaultClass != null && !sharedClassOrInterface.isAssignableFrom(defaultClass)) {
      throw new IllegalArgumentException();
    }
    final boolean initialize=false;
    final Class<?> cls=Class.forName(preferredClassName,initialize,classLoader);
    if (sharedClassOrInterface.isAssignableFrom(cls)) {
      if (log.isInfoEnabled()) {
        log.info("Found " + cls.getCanonicalName());
      }
      cache.put(requestConfig,cls);
      return (T)cls.newInstance();
    }
    log.warn(cls.getCanonicalName() + " does not extend " + sharedClassOrInterface.getCanonicalName());
  }
 catch (  ClassNotFoundException|InstantiationException|IllegalAccessException e) {
    if (DEBUG) {
      log.debug("Not found: " + preferredClassName);
    }
  }
  if (defaultClass == null) {
    cache.put(requestConfig,null);
    return null;
  }
  try {
    if (DEBUG) {
      log.debug("Using defaultClass: " + defaultClass.getCanonicalName());
    }
    cache.put(requestConfig,defaultClass);
    return (T)defaultClass.newInstance();
  }
 catch (  InstantiationException|IllegalAccessException e) {
    throw new RuntimeException(e);
  }
}

@ SuppressWarnings ( "unchecked" ) public static < T > T classForName ( final String preferredClassName , final Class < ? extends T > defaultClass , final Class < T > sharedClassOrInterface , final ClassLoader classLoader ) { final ClassPathUtilRequestConfig requestConfig = new ClassPathUtilRequestConfig ( preferredClassName , defaultClass , sharedClassOrInterface , classLoader ) ; try { if ( cache . containsKey ( requestConfig ) ) { final Class < ? > cls = cache . get ( requestConfig ) ; return cls == null ? null : ( T ) cls . newInstance ( ) ; } if ( defaultClass != null && ! sharedClassOrInterface . isAssignableFrom ( defaultClass ) ) { throw new IllegalArgumentException ( ) ; } final boolean initialize = false ; final Class < ? > cls = Class . forName ( preferredClassName , initialize , classLoader ) ; if ( sharedClassOrInterface . isAssignableFrom ( cls ) ) { if ( log . isInfoEnabled ( ) ) { log . info ( "Found " + cls . getCanonicalName ( ) ) ; } cache . put ( requestConfig , cls ) ; return ( T ) cls . newInstance ( ) ; } log . warn ( cls . getCanonicalName ( ) + " does not extend " + sharedClassOrInterface . getCanonicalName ( ) ) ; } catch ( ClassNotFoundException | InstantiationException | IllegalAccessException e ) { if ( DEBUG ) { log . debug ( "Not found: " + preferredClassName ) ; } } if ( defaultClass == null ) { cache . put ( requestConfig , null ) ; return null ; } try { if ( DEBUG ) { log . debug ( "Using defaultClass: " + defaultClass . getCanonicalName ( ) ) ; } cache . put ( requestConfig , defaultClass ) ; return ( T ) defaultClass . newInstance ( ) ; } catch ( InstantiationException | IllegalAccessException e ) { throw new RuntimeException ( e ) ; } }
return an instance of the shared interface . if possible , an instance of the preferred class will be used . if that class is not found or is does not extend the specified interface , then an instance of the default class will be used .
