/** This method must work for the root category as well. */
  void parseCategory(
      Properties props, Logger logger, String optionKey, String loggerName, String value) {

    LogLog.debug("Parsing for [" + loggerName + "] with value=[" + value + "].");
    // We must skip over ',' but not white space
    StringTokenizer st = new StringTokenizer(value, ",");

    // If value is not in the form ", appender.." or "", then we should set
    // the level of the loggeregory.

    if (!(value.startsWith(",") || value.equals(""))) {

      // just to be on the safe side...
      if (!st.hasMoreTokens()) return;

      String levelStr = st.nextToken();
      LogLog.debug("Level token is [" + levelStr + "].");

      // If the level value is inherited, set category level value to
      // null. We also check that the user has not specified inherited for the
      // root category.
      if (INHERITED.equalsIgnoreCase(levelStr) || NULL.equalsIgnoreCase(levelStr)) {
        if (loggerName.equals(INTERNAL_ROOT_NAME)) {
          LogLog.warn("The root logger cannot be set to null.");
        } else {
          logger.setLevel(null);
        }
      } else {
        logger.setLevel(OptionConverter.toLevel(levelStr, (Level) Level.DEBUG));
      }
      LogLog.debug("Category " + loggerName + " set to " + logger.getLevel());
    }

    // Begin by removing all existing appenders.
    logger.removeAllAppenders();

    Appender appender;
    String appenderName;
    while (st.hasMoreTokens()) {
      appenderName = st.nextToken().trim();
      if (appenderName == null || appenderName.equals(",")) continue;
      LogLog.debug("Parsing appender named \"" + appenderName + "\".");
      appender = parseAppender(props, appenderName);
      if (appender != null) {
        logger.addAppender(appender);
      }
    }
  }
  /**
   * Read configuration options from <code>properties</code>.
   *
   * <p>See {@link #doConfigure(String, LoggerRepository)} for the expected format.
   */
  public void doConfigure(Properties properties, LoggerRepository hierarchy) {
    repository = hierarchy;
    String value = properties.getProperty(LogLog.DEBUG_KEY);
    if (value == null) {
      value = properties.getProperty("log4j.configDebug");
      if (value != null)
        LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
    }

    if (value != null) {
      LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
    }

    //
    //   if log4j.reset=true then
    //        reset hierarchy
    String reset = properties.getProperty(RESET_KEY);
    if (reset != null && OptionConverter.toBoolean(reset, false)) {
      hierarchy.resetConfiguration();
    }

    String thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PREFIX, properties);
    if (thresholdStr != null) {
      hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr, (Level) Level.ALL));
      LogLog.debug("Hierarchy threshold set to [" + hierarchy.getThreshold() + "].");
    }

    configureRootCategory(properties, hierarchy);
    configureLoggerFactory(properties);
    parseCatsAndRenderers(properties, hierarchy);

    LogLog.debug("Finished configuring.");
    // We don't want to hold references to appenders preventing their
    // garbage collection.
    registry.clear();
  }