/**
  * Instantiate an object given a class name. Check that the <code>className</code> is a subclass
  * of <code>superClass</code>. If that test fails or the object could not be instantiated, then
  * <code>defaultValue</code> is returned.
  *
  * @param className The fully qualified class name of the object to instantiate.
  * @param superClass The class to which the new object should belong.
  * @param defaultValue The object to return in case of non-fulfillment
  */
 public static Object instantiateByClassName(
     String className, Class superClass, Object defaultValue) {
   if (className != null) {
     try {
       Class classObj = Loader.loadClass(className);
       if (!superClass.isAssignableFrom(classObj)) {
         LogLog.error(
             "A \""
                 + className
                 + "\" object is not assignable to a \""
                 + superClass.getName()
                 + "\" variable.");
         LogLog.error("The class \"" + superClass.getName() + "\" was loaded by ");
         LogLog.error("[" + superClass.getClassLoader() + "] whereas object of type ");
         LogLog.error(
             "\"" + classObj.getName() + "\" was loaded by [" + classObj.getClassLoader() + "].");
         return defaultValue;
       }
       return classObj.newInstance();
     } catch (Exception e) {
       LogLog.error("Could not instantiate class [" + className + "].", e);
     }
   }
   return defaultValue;
 }
  /**
   * Converts a standard or custom priority level to a Level object.
   *
   * <p>If <code>value</code> is of form "level#classname", then the specified class' toLevel method
   * is called to process the specified level string; if no '#' character is present, then the
   * default {@link org.apache.log4j.Level} class is used to process the level value.
   *
   * <p>As a special case, if the <code>value</code> parameter is equal to the string "NULL", then
   * the value <code>null</code> will be returned.
   *
   * <p>If any error occurs while converting the value to a level, the <code>defaultValue</code>
   * parameter, which may be <code>null</code>, is returned.
   *
   * <p>Case of <code>value</code> is insignificant for the level level, but is significant for the
   * class name part, if present.
   *
   * @since 1.1
   */
  public static Level toLevel(String value, Level defaultValue) {
    if (value == null) return defaultValue;

    value = value.trim();

    int hashIndex = value.indexOf('#');
    if (hashIndex == -1) {
      if ("NULL".equalsIgnoreCase(value)) {
        return null;
      } else {
        // no class name specified : use standard Level class
        return (Level) Level.toLevel(value, defaultValue);
      }
    }

    Level result = defaultValue;

    String clazz = value.substring(hashIndex + 1);
    String levelName = value.substring(0, hashIndex);

    // This is degenerate case but you never know.
    if ("NULL".equalsIgnoreCase(levelName)) {
      return null;
    }

    LogLog.debug("toLevel" + ":class=[" + clazz + "]" + ":pri=[" + levelName + "]");

    try {
      Class customLevel = Loader.loadClass(clazz);

      // get a ref to the specified class' static method
      // toLevel(String, org.apache.log4j.Level)
      Class[] paramTypes = new Class[] {String.class, org.apache.log4j.Level.class};
      java.lang.reflect.Method toLevelMethod = customLevel.getMethod("toLevel", paramTypes);

      // now call the toLevel method, passing level string + default
      Object[] params = new Object[] {levelName, defaultValue};
      Object o = toLevelMethod.invoke(null, params);

      result = (Level) o;
    } catch (ClassNotFoundException e) {
      LogLog.warn("custom level class [" + clazz + "] not found.");
    } catch (NoSuchMethodException e) {
      LogLog.warn(
          "custom level class ["
              + clazz
              + "]"
              + " does not have a constructor which takes one string parameter",
          e);
    } catch (java.lang.reflect.InvocationTargetException e) {
      LogLog.warn("custom level class [" + clazz + "]" + " could not be instantiated", e);
    } catch (ClassCastException e) {
      LogLog.warn("class [" + clazz + "] is not a subclass of org.apache.log4j.Level", e);
    } catch (IllegalAccessException e) {
      LogLog.warn("class [" + clazz + "] cannot be instantiated due to access restrictions", e);
    } catch (Exception e) {
      LogLog.warn("class [" + clazz + "], level [" + levelName + "] conversion failed.", e);
    }
    return result;
  }