/** Parse non-root elements, such non-root categories and renderers. */
 protected void parseCatsAndRenderers(Properties props, LoggerRepository hierarchy) {
   Enumeration enumeration = props.propertyNames();
   while (enumeration.hasMoreElements()) {
     String key = (String) enumeration.nextElement();
     if (key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) {
       String loggerName = null;
       if (key.startsWith(CATEGORY_PREFIX)) {
         loggerName = key.substring(CATEGORY_PREFIX.length());
       } else if (key.startsWith(LOGGER_PREFIX)) {
         loggerName = key.substring(LOGGER_PREFIX.length());
       }
       String value = OptionConverter.findAndSubst(key, props);
       Logger logger = hierarchy.getLogger(loggerName, loggerFactory);
       synchronized (logger) {
         parseCategory(props, logger, key, loggerName, value);
         parseAdditivityForLogger(props, logger, loggerName);
       }
     } else if (key.startsWith(RENDERER_PREFIX)) {
       String renderedClass = key.substring(RENDERER_PREFIX.length());
       String renderingClass = OptionConverter.findAndSubst(key, props);
       if (hierarchy instanceof RendererSupport) {
         RendererMap.addRenderer((RendererSupport) hierarchy, renderedClass, renderingClass);
       }
     } else if (key.equals(THROWABLE_RENDERER_PREFIX)) {
       if (hierarchy instanceof ThrowableRendererSupport) {
         ThrowableRenderer tr =
             (ThrowableRenderer)
                 OptionConverter.instantiateByKey(
                     props,
                     THROWABLE_RENDERER_PREFIX,
                     org.apache.log4j.spi.ThrowableRenderer.class,
                     null);
         if (tr == null) {
           LogLog.error("Could not instantiate throwableRenderer.");
         } else {
           PropertySetter setter = new PropertySetter(tr);
           setter.setProperties(props, THROWABLE_RENDERER_PREFIX + ".");
           ((ThrowableRendererSupport) hierarchy).setThrowableRenderer(tr);
         }
       }
     }
   }
 }
  Appender parseAppender(Properties props, String appenderName) {
    Appender appender = registryGet(appenderName);
    if ((appender != null)) {
      LogLog.debug("Appender \"" + appenderName + "\" was already parsed.");
      return appender;
    }
    // Appender was not previously initialized.
    String prefix = APPENDER_PREFIX + appenderName;
    String layoutPrefix = prefix + ".layout";

    appender =
        (Appender)
            OptionConverter.instantiateByKey(props, prefix, org.apache.log4j.Appender.class, null);
    if (appender == null) {
      LogLog.error("Could not instantiate appender named \"" + appenderName + "\".");
      return null;
    }
    appender.setName(appenderName);

    if (appender instanceof OptionHandler) {
      if (appender.requiresLayout()) {
        Layout layout =
            (Layout) OptionConverter.instantiateByKey(props, layoutPrefix, Layout.class, null);
        if (layout != null) {
          appender.setLayout(layout);
          LogLog.debug("Parsing layout options for \"" + appenderName + "\".");
          // configureOptionHandler(layout, layoutPrefix + ".", props);
          PropertySetter.setProperties(layout, props, layoutPrefix + ".");
          LogLog.debug("End of parsing for \"" + appenderName + "\".");
        }
      }
      final String errorHandlerPrefix = prefix + ".errorhandler";
      String errorHandlerClass = OptionConverter.findAndSubst(errorHandlerPrefix, props);
      if (errorHandlerClass != null) {
        ErrorHandler eh =
            (ErrorHandler)
                OptionConverter.instantiateByKey(
                    props, errorHandlerPrefix, ErrorHandler.class, null);
        if (eh != null) {
          appender.setErrorHandler(eh);
          LogLog.debug("Parsing errorhandler options for \"" + appenderName + "\".");
          parseErrorHandler(eh, errorHandlerPrefix, props, repository);
          final Properties edited = new Properties();
          final String[] keys =
              new String[] {
                errorHandlerPrefix + "." + ROOT_REF,
                errorHandlerPrefix + "." + LOGGER_REF,
                errorHandlerPrefix + "." + APPENDER_REF_TAG
              };
          for (Iterator iter = props.entrySet().iterator(); iter.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iter.next();
            int i = 0;
            for (; i < keys.length; i++) {
              if (keys[i].equals(entry.getKey())) break;
            }
            if (i == keys.length) {
              edited.put(entry.getKey(), entry.getValue());
            }
          }
          PropertySetter.setProperties(eh, edited, errorHandlerPrefix + ".");
          LogLog.debug("End of errorhandler parsing for \"" + appenderName + "\".");
        }
      }
      // configureOptionHandler((OptionHandler) appender, prefix + ".", props);
      PropertySetter.setProperties(appender, props, prefix + ".");
      LogLog.debug("Parsed \"" + appenderName + "\" options.");
    }
    parseAppenderFilters(props, appenderName, appender);
    registryPut(appender);
    return appender;
  }