public class DOMConfigurator implements Configurator {

  static final String CONFIGURATION_TAG = "log4j:configuration";
  static final String OLD_CONFIGURATION_TAG = "configuration";
  static final String RENDERER_TAG      = "renderer";
  private static final String THROWABLE_RENDERER_TAG = "throwableRenderer";
  static final String APPENDER_TAG 	= "appender";
  static final String APPENDER_REF_TAG 	= "appender-ref";
  static final String PARAM_TAG    	= "param";
  static final String LAYOUT_TAG	= "layout";
  static final String CATEGORY		= "category";
  static final String LOGGER		= "logger";
  static final String LOGGER_REF	= "logger-ref";
  static final String CATEGORY_FACTORY_TAG  = "categoryFactory";
  static final String LOGGER_FACTORY_TAG  = "loggerFactory";
  static final String NAME_ATTR		= "name";
  static final String CLASS_ATTR        = "class";
  static final String VALUE_ATTR	= "value";
  static final String ROOT_TAG		= "root";
  static final String ROOT_REF		= "root-ref";
  static final String LEVEL_TAG	        = "level";
  static final String PRIORITY_TAG      = "priority";
  static final String FILTER_TAG	= "filter";
  static final String ERROR_HANDLER_TAG	= "errorHandler";
  static final String REF_ATTR		= "ref";
  static final String ADDITIVITY_ATTR    = "additivity";
  static final String THRESHOLD_ATTR       = "threshold";
  static final String CONFIG_DEBUG_ATTR  = "configDebug";
  static final String INTERNAL_DEBUG_ATTR  = "debug";
  private static final String RESET_ATTR  = "reset";
  static final String RENDERING_CLASS_ATTR = "renderingClass";
  static final String RENDERED_CLASS_ATTR = "renderedClass";

  static final String EMPTY_STR = "";
  static final Class[] ONE_STRING_PARAM = new Class[] {String.class};

  final static String dbfKey = "javax.xml.parsers.DocumentBuilderFactory";

  // key: appenderName, value: appender
  Hashtable appenderBag;

  Properties props;
  LoggerRepository repository;

  protected LoggerFactory catFactory = null;

  /**
     No argument constructor.
  */
  public
  DOMConfigurator () {
    appenderBag = new Hashtable();
  }

  /**
     Used internally to parse appenders by IDREF name.
  */
  protected
  Appender findAppenderByName(Document doc, String appenderName)  {
    Appender appender = (Appender) appenderBag.get(appenderName);

    if(appender != null) {
      return appender;
    } else {
      // Doesn't work on DOM Level 1 :
      // Element element = doc.getElementById(appenderName);

      // Endre's hack:
      Element element = null;
      NodeList list = doc.getElementsByTagName("appender");
      for (int t=0; t < list.getLength(); t++) {
	Node node = list.item(t);
	NamedNodeMap map= node.getAttributes();
	Node attrNode = map.getNamedItem("name");
	if (appenderName.equals(attrNode.getNodeValue())) {
	  element = (Element) node;
	  break;
	}
      }
      // Hack finished.

      if(element == null) {
	LogLog.error("No appender named ["+appenderName+"] could be found.");
	return null;
      } else {
	      appender = parseAppender(element);
          if (appender != null) {
            appenderBag.put(appenderName, appender);
          }
    return appender;
      }
    }
  }
  /**
     Used internally to parse appenders by IDREF element.
   */
  protected
  Appender findAppenderByReference(Element appenderRef) {
    String appenderName = subst(appenderRef.getAttribute(REF_ATTR));
    Document doc = appenderRef.getOwnerDocument();
    return findAppenderByName(doc, appenderName);
  }

    /**
     * Delegates unrecognized content to created instance if
     * it supports UnrecognizedElementParser.
     * @since 1.2.15
     * @param instance instance, may be null.
     * @param element element, may not be null.
     * @param props properties
     * @throws IOException thrown if configuration of owner object
     * should be abandoned.
     */
  private static void parseUnrecognizedElement(final Object instance,
                                        final Element element,
                                        final Properties props) throws Exception {
      boolean recognized = false;
      if (instance instanceof UnrecognizedElementHandler) {
          recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
                  element, props);
      }
      if (!recognized) {
          LogLog.warn("Unrecognized element " + element.getNodeName());
      }
  }

    /**
      * Delegates unrecognized content to created instance if
      * it supports UnrecognizedElementParser and catches and
     *  logs any exception.
      * @since 1.2.15
      * @param instance instance, may be null.
      * @param element element, may not be null.
      * @param props properties
      */
   private static void quietParseUnrecognizedElement(final Object instance,
                                          final Element element,
                                          final Properties props) {
      try {
          parseUnrecognizedElement(instance, element, props);
      } catch (Exception ex) {
          if (ex instanceof InterruptedException || ex instanceof InterruptedIOException) {
              Thread.currentThread().interrupt();
          }
          LogLog.error("Error in extension content: ", ex);
      }
  }

  /**
     Used internally to parse an appender element.
   */
  protected
  Appender parseAppender (Element appenderElement) {
    String className = subst(appenderElement.getAttribute(CLASS_ATTR));
    LogLog.debug("Class name: [" + className+']');
    try {
      Object instance 	= Loader.loadClass(className).newInstance();
      Appender appender	= (Appender)instance;
      PropertySetter propSetter = new PropertySetter(appender);

      appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));

      NodeList children	= appenderElement.getChildNodes();
      final int length 	= children.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = children.item(loop);

	/* We're only interested in Elements */
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element)currentNode;

	  // Parse appender parameters
	  if (currentElement.getTagName().equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  }
	  // Set appender layout
	  else if (currentElement.getTagName().equals(LAYOUT_TAG)) {
	    appender.setLayout(parseLayout(currentElement));
	  }
	  // Add filters
	  else if (currentElement.getTagName().equals(FILTER_TAG)) {
	    parseFilters(currentElement, appender);
	  }
	  else if (currentElement.getTagName().equals(ERROR_HANDLER_TAG)) {
	    parseErrorHandler(currentElement, appender);
	  }
	  else if (currentElement.getTagName().equals(APPENDER_REF_TAG)) {
	    String refName = subst(currentElement.getAttribute(REF_ATTR));
	    if(appender instanceof AppenderAttachable) {
	      AppenderAttachable aa = (AppenderAttachable) appender;
	      LogLog.debug("Attaching appender named ["+ refName+
			   "] to appender named ["+ appender.getName()+"].");
	      aa.addAppender(findAppenderByReference(currentElement));
	    } else {
	      LogLog.error("Requesting attachment of appender named ["+
			   refName+ "] to appender named ["+ appender.getName()+
                "] which does not implement org.apache.log4j.spi.AppenderAttachable.");
	    }
	  } else {
          parseUnrecognizedElement(instance, currentElement, props);
      }
	}
      }
      propSetter.activate();
      return appender;
    }
    /* Yes, it's ugly.  But all of these exceptions point to the same
       problem: we can't create an Appender */
    catch (Exception oops) {
        if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
            Thread.currentThread().interrupt();
        }
      LogLog.error("Could not create an Appender. Reported error follows.",
		   oops);
      return null;
    }
  }

  /**
     Used internally to parse an {@link ErrorHandler} element.
   */
  protected
  void parseErrorHandler(Element element, Appender appender) {
    ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
                                       subst(element.getAttribute(CLASS_ATTR)),
                                       org.apache.log4j.spi.ErrorHandler.class,
 				       null);

    if(eh != null) {
      eh.setAppender(appender);

      PropertySetter propSetter = new PropertySetter(eh);
      NodeList children = element.getChildNodes();
      final int length 	= children.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = children.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element) currentNode;
	  String tagName = currentElement.getTagName();
	  if(tagName.equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  } else if(tagName.equals(APPENDER_REF_TAG)) {
	    eh.setBackupAppender(findAppenderByReference(currentElement));
	  } else if(tagName.equals(LOGGER_REF)) {
	    String loggerName = currentElement.getAttribute(REF_ATTR);
	    Logger logger = (catFactory == null) ? repository.getLogger(loggerName)
                : repository.getLogger(loggerName, catFactory);
	    eh.setLogger(logger);
	  } else if(tagName.equals(ROOT_REF)) {
	    Logger root = repository.getRootLogger();
	    eh.setLogger(root);
	  } else {
          quietParseUnrecognizedElement(eh, currentElement, props);
      }
	}
      }
      propSetter.activate();
      appender.setErrorHandler(eh);
    }
  }

  /**
     Used internally to parse a filter element.
   */
  protected
  void parseFilters(Element element, Appender appender) {
    String clazz = subst(element.getAttribute(CLASS_ATTR));
    Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz,
                                                Filter.class, null);

    if(filter != null) {
      PropertySetter propSetter = new PropertySetter(filter);
      NodeList children = element.getChildNodes();
      final int length 	= children.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = children.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element) currentNode;
	  String tagName = currentElement.getTagName();
	  if(tagName.equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  } else {
            quietParseUnrecognizedElement(filter, currentElement, props);
      }
	}
      }
      propSetter.activate();
      LogLog.debug("Adding filter of type ["+filter.getClass()
		   +"] to appender named ["+appender.getName()+"].");
      appender.addFilter(filter);
    }
  }

  /**
     Used internally to parse an category element.
  */
  protected
  void parseCategory (Element loggerElement) {
    // Create a new org.apache.log4j.Category object from the <category> element.
    String catName = subst(loggerElement.getAttribute(NAME_ATTR));

    Logger cat;

    String className = subst(loggerElement.getAttribute(CLASS_ATTR));

    if(EMPTY_STR.equals(className)) {
      LogLog.debug("Retreiving an instance of org.apache.log4j.Logger.");
      cat = (catFactory == null) ? repository.getLogger(catName) : repository.getLogger(catName, catFactory);
    }
    else {
      LogLog.debug("Desired logger sub-class: ["+className+']');
       try {
	 Class clazz = Loader.loadClass(className);
	 Method getInstanceMethod = clazz.getMethod("getLogger",
						    ONE_STRING_PARAM);
	 cat = (Logger) getInstanceMethod.invoke(null, new Object[] {catName});
       } catch (InvocationTargetException oops) {
          if (oops.getTargetException() instanceof InterruptedException
                  || oops.getTargetException() instanceof InterruptedIOException) {
              Thread.currentThread().interrupt();
          }
          LogLog.error("Could not retrieve category ["+catName+
		      "]. Reported error follows.", oops);
	      return;
       } catch (Exception oops) {
	      LogLog.error("Could not retrieve category ["+catName+
		      "]. Reported error follows.", oops);
	      return;
       }
    }

    // Setting up a category needs to be an atomic operation, in order
    // to protect potential log operations while category
    // configuration is in progress.
    synchronized(cat) {
      boolean additivity = OptionConverter.toBoolean(
                           subst(loggerElement.getAttribute(ADDITIVITY_ATTR)),
			   true);

      LogLog.debug("Setting ["+cat.getName()+"] additivity to ["+additivity+"].");
      cat.setAdditivity(additivity);
      parseChildrenOfLoggerElement(loggerElement, cat, false);
    }
  }

  /**
     Used internally to parse the category factory element.
  */
  protected
  void parseCategoryFactory(Element factoryElement) {
    String className = subst(factoryElement.getAttribute(CLASS_ATTR));

    if(EMPTY_STR.equals(className)) {
      LogLog.error("Category Factory tag " + CLASS_ATTR + " attribute not found.");
      LogLog.debug("No Category Factory configured.");
    }
    else {
      LogLog.debug("Desired category factory: ["+className+']');
      Object factory = OptionConverter.instantiateByClassName(className,
                                                                 LoggerFactory.class,
                                                                 null);
      if (factory instanceof LoggerFactory) {
          catFactory = (LoggerFactory) factory;
      } else {
          LogLog.error("Category Factory class " + className + " does not implement org.apache.log4j.LoggerFactory");
      }
      PropertySetter propSetter = new PropertySetter(factory);

      Element  currentElement = null;
      Node     currentNode    = null;
      NodeList children       = factoryElement.getChildNodes();
      final int length        = children.getLength();

      for (int loop=0; loop < length; loop++) {
        currentNode = children.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  currentElement = (Element)currentNode;
	  if (currentElement.getTagName().equals(PARAM_TAG)) {
	    setParameter(currentElement, propSetter);
	  } else {
           quietParseUnrecognizedElement(factory, currentElement, props);
      }
	}
      }
    }
  }

  /**
     Used internally to parse the roor category element.
  */
  protected
  void parseRoot (Element rootElement) {
    Logger root = repository.getRootLogger();
    // category configuration needs to be atomic
    synchronized(root) {
      parseChildrenOfLoggerElement(rootElement, root, true);
    }
  }

  /**
     Used internally to parse the children of a category element.
  */
  protected
  void parseChildrenOfLoggerElement(Element catElement,
				      Logger cat, boolean isRoot) {

    PropertySetter propSetter = new PropertySetter(cat);

    // Remove all existing appenders from cat. They will be
    // reconstructed if need be.
    cat.removeAllAppenders();

    NodeList children 	= catElement.getChildNodes();
    final int length 	= children.getLength();

    for (int loop = 0; loop < length; loop++) {
      Node currentNode = children.item(loop);

      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	Element currentElement = (Element) currentNode;
	String tagName = currentElement.getTagName();

	if (tagName.equals(APPENDER_REF_TAG)) {
	  Element appenderRef = (Element) currentNode;
	  Appender appender = findAppenderByReference(appenderRef);
	  String refName =  subst(appenderRef.getAttribute(REF_ATTR));
	  if(appender != null)
	    LogLog.debug("Adding appender named ["+ refName+
			 "] to category ["+cat.getName()+"].");
	  else
	    LogLog.debug("Appender named ["+ refName + "] not found.");

	  cat.addAppender(appender);

	} else if(tagName.equals(LEVEL_TAG)) {
	  parseLevel(currentElement, cat, isRoot);
	} else if(tagName.equals(PRIORITY_TAG)) {
	  parseLevel(currentElement, cat, isRoot);
	} else if(tagName.equals(PARAM_TAG)) {
          setParameter(currentElement, propSetter);
	} else {
        quietParseUnrecognizedElement(cat, currentElement, props);
    }
      }
    }
    propSetter.activate();
  }

  /**
     Used internally to parse a layout element.
  */
  protected
  Layout parseLayout (Element layout_element) {
    String className = subst(layout_element.getAttribute(CLASS_ATTR));
    LogLog.debug("Parsing layout of class: \""+className+"\"");
    try {
      Object instance 	= Loader.loadClass(className).newInstance();
      Layout layout   	= (Layout)instance;
      PropertySetter propSetter = new PropertySetter(layout);

      NodeList params 	= layout_element.getChildNodes();
      final int length 	= params.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = (Node)params.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element) currentNode;
	  String tagName = currentElement.getTagName();
	  if(tagName.equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  } else {
          parseUnrecognizedElement(instance, currentElement, props);
      }
	}
      }

      propSetter.activate();
      return layout;
    }
    catch (Exception oops) {
        if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
            Thread.currentThread().interrupt();
        }
      LogLog.error("Could not create the Layout. Reported error follows.",
		   oops);
      return null;
    }
  }

  protected
  void parseRenderer(Element element) {
    String renderingClass = subst(element.getAttribute(RENDERING_CLASS_ATTR));
    String renderedClass = subst(element.getAttribute(RENDERED_CLASS_ATTR));
    if(repository instanceof RendererSupport) {
      RendererMap.addRenderer((RendererSupport) repository, renderedClass,
			      renderingClass);
    }
  }

    /**
     * Parses throwable renderer.
     * @param element throwableRenderer element.
     * @return configured throwable renderer.
     * @since 1.2.16.
     */
    protected ThrowableRenderer parseThrowableRenderer(final Element element) {
        String className = subst(element.getAttribute(CLASS_ATTR));
        LogLog.debug("Parsing throwableRenderer of class: \""+className+"\"");
        try {
          Object instance 	= Loader.loadClass(className).newInstance();
          ThrowableRenderer tr   	= (ThrowableRenderer)instance;
          PropertySetter propSetter = new PropertySetter(tr);

          NodeList params 	= element.getChildNodes();
          final int length 	= params.getLength();

          for (int loop = 0; loop < length; loop++) {
                Node currentNode = (Node)params.item(loop);
                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element currentElement = (Element) currentNode;
                    String tagName = currentElement.getTagName();
                    if(tagName.equals(PARAM_TAG)) {
                        setParameter(currentElement, propSetter);
                    } else {
                        parseUnrecognizedElement(instance, currentElement, props);
                    }
                }
          }

          propSetter.activate();
          return tr;
        }
        catch (Exception oops) {
            if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
                Thread.currentThread().interrupt();
            }
            LogLog.error("Could not create the ThrowableRenderer. Reported error follows.",
               oops);
          return null;
        }
    }

  /**
     Used internally to parse a level  element.
  */
  protected
  void parseLevel(Element element, Logger logger, boolean isRoot) {
    String catName = logger.getName();
    if(isRoot) {
      catName = "root";
    }

    String priStr = subst(element.getAttribute(VALUE_ATTR));
    LogLog.debug("Level value for "+catName+" is  ["+priStr+"].");

    if(INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
      if(isRoot) {
	LogLog.error("Root level cannot be inherited. Ignoring directive.");
      } else {
	logger.setLevel(null);
      }
    } else {
      String className = subst(element.getAttribute(CLASS_ATTR));
      if(EMPTY_STR.equals(className)) {
	logger.setLevel(OptionConverter.toLevel(priStr, Level.DEBUG));
      } else {
	LogLog.debug("Desired Level sub-class: ["+className+']');
	try {
	  Class clazz = Loader.loadClass(className);
	  Method toLevelMethod = clazz.getMethod("toLevel",
						    ONE_STRING_PARAM);
	  Level pri = (Level) toLevelMethod.invoke(null,
						    new Object[] {priStr});
	  logger.setLevel(pri);
	} catch (Exception oops) {
        if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
            Thread.currentThread().interrupt();
        }
	  LogLog.error("Could not create level ["+priStr+
		       "]. Reported error follows.", oops);
	  return;
	}
      }
    }
    LogLog.debug(catName + " level set to " + logger.getLevel());
  }

  protected
  void setParameter(Element elem, PropertySetter propSetter) {
      String name = subst(elem.getAttribute(NAME_ATTR));
      String value = (elem.getAttribute(VALUE_ATTR));
      value = subst(OptionConverter.convertSpecialChars(value));
      propSetter.setProperty(name, value);
  }

  /**
     Configure log4j using a <code>configuration</code> element as
     defined in the log4j.dtd.

  */
  static
  public
  void configure (Element element) {
    DOMConfigurator configurator = new DOMConfigurator();
    configurator.doConfigure(element,  LogManager.getLoggerRepository());
  }

 /**
     Like {@link #configureAndWatch(String, long)} except that the
     default delay as defined by {@link FileWatchdog#DEFAULT_DELAY} is
     used.

     @param configFilename A log4j configuration file in XML format.

  */
  static
  public
  void configureAndWatch(String configFilename) {
    configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
  }

  /**
     Read the configuration file <code>configFilename</code> if it
     exists. Moreover, a thread will be created that will periodically
     check if <code>configFilename</code> has been created or
     modified. The period is determined by the <code>delay</code>
     argument. If a change or file creation is detected, then
     <code>configFilename</code> is read to configure log4j.

      @param configFilename A log4j configuration file in XML format.
      @param delay The delay in milliseconds to wait between each check.
  */
  static
  public
  void configureAndWatch(String configFilename, long delay) {
    XMLWatchdog xdog = new XMLWatchdog(configFilename);
    xdog.setDelay(delay);
    xdog.start();
  }

  private interface ParseAction {
      Document parse(final DocumentBuilder parser) throws SAXException, IOException;
  }

  public
  void doConfigure(final String filename, LoggerRepository repository) {
    ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              return parser.parse(new File(filename));
          }
          public String toString() {
              return "file [" + filename + "]";
          }
    };
    doConfigure(action, repository);
  }

  public
  void doConfigure(final URL url, LoggerRepository repository) {
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              URLConnection uConn = url.openConnection();
              uConn.setUseCaches(false);
              InputStream stream = uConn.getInputStream();
              try {
                InputSource src = new InputSource(stream);
                src.setSystemId(url.toString());
                return parser.parse(src);
              } finally {
                stream.close();
              }
          }
          public String toString() {
              return "url [" + url.toString() + "]";
          }
      };
      doConfigure(action, repository);
  }

  /**
     Configure log4j by reading in a log4j.dtd compliant XML
     configuration file.

  */
  public
  void doConfigure(final InputStream inputStream, LoggerRepository repository)
                                          throws FactoryConfigurationError {
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              InputSource inputSource = new InputSource(inputStream);
              inputSource.setSystemId("dummy://log4j.dtd");
              return parser.parse(inputSource);
          }
          public String toString() {
              return "input stream [" + inputStream.toString() + "]";
          }
      };
      doConfigure(action, repository);
  }

  /**
     Configure log4j by reading in a log4j.dtd compliant XML
     configuration file.

  */
  public
  void doConfigure(final Reader reader, LoggerRepository repository)
                                          throws FactoryConfigurationError {
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              InputSource inputSource = new InputSource(reader);
              inputSource.setSystemId("dummy://log4j.dtd");
              return parser.parse(inputSource);
          }
          public String toString() {
              return "reader [" + reader.toString() + "]";
          }
      };
    doConfigure(action, repository);
  }

  /**
     Configure log4j by reading in a log4j.dtd compliant XML
     configuration file.

  */
  protected
  void doConfigure(final InputSource inputSource, LoggerRepository repository)
                                          throws FactoryConfigurationError {
      if (inputSource.getSystemId() == null) {
          inputSource.setSystemId("dummy://log4j.dtd");
      }
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              return parser.parse(inputSource);
          }
          public String toString() {
              return "input source [" + inputSource.toString() + "]";
          }
      };
      doConfigure(action, repository);
    }

  private final void doConfigure(final ParseAction action, final LoggerRepository repository)
         throws FactoryConfigurationError {
    DocumentBuilderFactory dbf = null;
    this.repository = repository;
    try {
      LogLog.debug("System property is :"+
  	                        OptionConverter.getSystemProperty(dbfKey,
								  null));
      dbf = DocumentBuilderFactory.newInstance();
      LogLog.debug("Standard DocumentBuilderFactory search succeded.");
      LogLog.debug("DocumentBuilderFactory is: "+dbf.getClass().getName());
    } catch(FactoryConfigurationError fce) {
      Exception e = fce.getException();
      LogLog.debug("Could not instantiate a DocumentBuilderFactory.", e);
      throw fce;
    }

    try {
      dbf.setValidating(true);

      DocumentBuilder docBuilder = dbf.newDocumentBuilder();

      docBuilder.setErrorHandler(new SAXErrorHandler());
      docBuilder.setEntityResolver(new Log4jEntityResolver());

      Document doc = action.parse(docBuilder);
      parse(doc.getDocumentElement());
    } catch (Exception e) {
        if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
            Thread.currentThread().interrupt();
        }
      // I know this is miserable...
      LogLog.error("Could not parse "+ action.toString() + ".", e);
    }
  }

  /**
     Configure by taking in an DOM element.
  */
  public void doConfigure(Element element, LoggerRepository repository) {
    this.repository = repository;
    parse(element);
  }

  /**
     A static version of {@link #doConfigure(String, LoggerRepository)}.  */
  static
  public
  void configure(String filename) throws FactoryConfigurationError {
    new DOMConfigurator().doConfigure(filename,
				      LogManager.getLoggerRepository());
  }

  /**
     A static version of {@link #doConfigure(URL, LoggerRepository)}.
   */
  static
  public
  void configure(URL url) throws FactoryConfigurationError {
    new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
  }

  /**
     Used internally to configure the log4j framework by parsing a DOM
     tree of XML elements based on <a
     href="doc-files/log4j.dtd">log4j.dtd</a>.

  */
  protected
  void parse(Element element) {

    String rootElementName = element.getTagName();

    if (!rootElementName.equals(CONFIGURATION_TAG)) {
      if(rootElementName.equals(OLD_CONFIGURATION_TAG)) {
	LogLog.warn("The <"+OLD_CONFIGURATION_TAG+
		     "> element has been deprecated.");
	LogLog.warn("Use the <"+CONFIGURATION_TAG+"> element instead.");
      } else {
	LogLog.error("DOM element is - not a <"+CONFIGURATION_TAG+"> element.");
	return;
      }
    }

    String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));

    LogLog.debug("debug attribute= \"" + debugAttrib +"\".");
    // if the log4j.dtd is not specified in the XML file, then the
    // "debug" attribute is returned as the empty string.
    if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {
      LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
    } else {
      LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
    }

      //
      //   reset repository before configuration if reset="true"
      //       on configuration element.
      //
    String resetAttrib = subst(element.getAttribute(RESET_ATTR));
    LogLog.debug("reset attribute= \"" + resetAttrib +"\".");
    if(!("".equals(resetAttrib))) {
         if (OptionConverter.toBoolean(resetAttrib, false)) {
             repository.resetConfiguration();
         }
    }

    String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
    if(!confDebug.equals("") && !confDebug.equals("null")) {
      LogLog.warn("The \""+CONFIG_DEBUG_ATTR+"\" attribute is deprecated.");
      LogLog.warn("Use the \""+INTERNAL_DEBUG_ATTR+"\" attribute instead.");
      LogLog.setInternalDebugging(OptionConverter.toBoolean(confDebug, true));
    }

    String thresholdStr = subst(element.getAttribute(THRESHOLD_ATTR));
    LogLog.debug("Threshold =\"" + thresholdStr +"\".");
    if(!"".equals(thresholdStr) && !"null".equals(thresholdStr)) {
      repository.setThreshold(thresholdStr);
    }

    //Hashtable appenderBag = new Hashtable(11);

    /* Building Appender objects, placing them in a local namespace
       for future reference */

    // First configure each category factory under the root element.
    // Category factories need to be configured before any of
    // categories they support.
    //
    String   tagName = null;
    Element  currentElement = null;
    Node     currentNode = null;
    NodeList children = element.getChildNodes();
    final int length = children.getLength();

    for (int loop = 0; loop < length; loop++) {
      currentNode = children.item(loop);
      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	currentElement = (Element) currentNode;
	tagName = currentElement.getTagName();

	if (tagName.equals(CATEGORY_FACTORY_TAG) || tagName.equals(LOGGER_FACTORY_TAG)) {
	  parseCategoryFactory(currentElement);
	}
      }
    }

    for (int loop = 0; loop < length; loop++) {
      currentNode = children.item(loop);
      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	currentElement = (Element) currentNode;
	tagName = currentElement.getTagName();

	if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
	  parseCategory(currentElement);
	} else if (tagName.equals(ROOT_TAG)) {
	  parseRoot(currentElement);
	} else if(tagName.equals(RENDERER_TAG)) {
	  parseRenderer(currentElement);
    } else if(tagName.equals(THROWABLE_RENDERER_TAG)) {
        if (repository instanceof ThrowableRendererSupport) {
            ThrowableRenderer tr = parseThrowableRenderer(currentElement);
            if (tr != null) {
                ((ThrowableRendererSupport) repository).setThrowableRenderer(tr);
            }
        }
    } else if (!(tagName.equals(APPENDER_TAG)
            || tagName.equals(CATEGORY_FACTORY_TAG)
            || tagName.equals(LOGGER_FACTORY_TAG))) {
        quietParseUnrecognizedElement(repository, currentElement, props);
    }
      }
    }
  }

  protected
  String subst(final String value) {
      return subst(value, props);
  }

    /**
     * Substitutes property value for any references in expression.
     *
     * @param value value from configuration file, may contain
     *              literal text, property references or both
     * @param props properties.
     * @return evaluated expression, may still contain expressions
     *         if unable to expand.
     * @since 1.2.15
     */
    public static String subst(final String value, final Properties props) {
        try {
            return OptionConverter.substVars(value, props);
        } catch (IllegalArgumentException e) {
            LogLog.warn("Could not perform variable substitution.", e);
            return value;
        }
    }

    /**
     * Sets a parameter based from configuration file content.
     *
     * @param elem       param element, may not be null.
     * @param propSetter property setter, may not be null.
     * @param props      properties
     * @since 1.2.15
     */
    public static void setParameter(final Element elem,
                                    final PropertySetter propSetter,
                                    final Properties props) {
        String name = subst(elem.getAttribute("name"), props);
        String value = (elem.getAttribute("value"));
        value = subst(OptionConverter.convertSpecialChars(value), props);
        propSetter.setProperty(name, value);
    }

    /**
     * Creates an object and processes any nested param elements
     * but does not call activateOptions.  If the class also supports
     * UnrecognizedElementParser, the parseUnrecognizedElement method
     * will be call for any child elements other than param.
     *
     * @param element       element, may not be null.
     * @param props         properties
     * @param expectedClass interface or class expected to be implemented
     *                      by created class
     * @return created class or null.
     * @throws Exception thrown if the contain object should be abandoned.
     * @since 1.2.15
     */
    public static Object parseElement(final Element element,
                                             final Properties props,
                                             final Class expectedClass) throws Exception {
        String clazz = subst(element.getAttribute("class"), props);
        Object instance = OptionConverter.instantiateByClassName(clazz,
                expectedClass, null);

        if (instance != null) {
            PropertySetter propSetter = new PropertySetter(instance);
            NodeList children = element.getChildNodes();
            final int length = children.getLength();

            for (int loop = 0; loop < length; loop++) {
                Node currentNode = children.item(loop);
                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element currentElement = (Element) currentNode;
                    String tagName = currentElement.getTagName();
                    if (tagName.equals("param")) {
                        setParameter(currentElement, propSetter, props);
                    } else {
                         parseUnrecognizedElement(instance, currentElement, props);
                    }
                }
            }
            return instance;
        }
        return null;

FUNC_DECL RETURN VAR_DECL VAR_DECL PARAM CALL CALL CALL CALL

FUNC_DECL TRY PARAM PARAM PARAM CATCH IF CALL CALL BINARY_OP LITERAL_ANCHOR BINARY_OP BINARY_OP CALL CALL

FUNC_DECL VAR_DECL VAR_DECL PARAM PARAM CALL ASSIGN CALL CALL CALL CALL CALL

FUNC_DECL VAR_DECL PARAM PARAM CALL CALL CALL

FUNC_DECL TRY PARAM PARAM CATCH RETURN RETURN CALL CALL LITERAL_ANCHOR

FUNC_DECL VAR_DECL VAR_DECL PARAM PARAM PARAM CALL ASSIGN CALL CALL CALL CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR


@XmlRootElement(name = "message")
@XmlAccessorType(value = XmlAccessType.FIELD)
public class MessageType {
    @XmlElementRef(type = HeaderType.class)
    List<HeaderType> headers = new ArrayList<HeaderType>();
    @XmlAnyElement(lax = true)
    @XmlMixed
    private List content = new ArrayList();
    @XmlTransient
    private Object body;

    public Object getBody() {
        if (body == null) {
            if (content != null) {
                if (content.size() == 1) {
                    return content.get(0);
                }
                else {
                    return content;
                }
            }
        }
        return body;
    }

    public void setBody(Object body) {
        this.body = body;
        if (body instanceof List) {
            content = (List) body;
        }
        else {
            content = new ArrayList();
            content.add(body);
        }
    }

    public List<HeaderType> getHeaders() {
        return headers;
    }

    public void setHeaders(List<HeaderType> headers) {
        this.headers = headers;
    }

    public Map<String, Object> getHeaderMap() {
        Map<String, Object> answer = new HashMap<String, Object>();
        for (HeaderType header : headers) {
            answer.put(header.getName(), header.getValue());
        }
        return answer;
    }

    /**
     * Copies the headers and body of this object from the given Camel message
     *
     * @param message the Camel message to read the headers and body from
     */
    public void copyFrom(Message message) {
        headers.clear();
        Set<Map.Entry<String, Object>> entries = message.getHeaders().entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            Object value = entry.getValue();
            if (value != null) {
                headers.add(createHeader(entry.getKey(), value));
            }
        }
        setBody(message.getBody());
    }

    /**
     * Copies the headers and body of this object to the given Camel message
     *
     * @param message the camel message to overwrite its headers and body
     */
    public void copyTo(Message message) {
        message.setHeaders(getHeaderMap());
        message.setBody(getBody());
    }

    protected HeaderType createHeader(String key, Object value) {
        if (value instanceof String) {
            return new StringHeader(key, (String) value);
        }
        else if (value instanceof Integer) {
            return new IntegerHeader(key, (Integer) value);
        }
        else if (value instanceof Long) {
            return new LongHeader(key, (Long) value);
        }
        else {
            return new StringHeader(key, value.toString());

FUNC_DECL IF PARAM BINARY_OP ASSIGN CALL ASSIGN ASSIGN CALL

FUNC_DECL RETURN LOOP VAR_DECL CALL CALL CALL CALL

FUNC_DECL LOOP VAR_DECL PARAM CALL CALL CALL IF VAR_DECL CALL BINARY_OP CALL LITERAL_ANCHOR CALL CALL CALL CALL

FUNC_DECL IF PARAM PARAM IF BINARY_OP IF BINARY_OP RETURN BINARY_OP RETURN CALL RETURN RETURN CALL CALL CALL CALL


org.gjt.sp.jedit.io.Encoding

public interface Encoding
{
	/**
	* Map an InputStream to a Reader.
	* Decode-error while reading from this Reader should be reported
	* by throwing an IOException.
	*/
	public Reader getTextReader(InputStream in) throws IOException;

	/**
	* Map an OutputStream to a Writer.
	* Encode-error while writing to this Writer should be reported
	* by throwing an IOException.
	*/
	public Writer getTextWriter(OutputStream out) throws IOException;

	/**
	* Map an InputStream to a Reader.
	* Decode-error while reading from this Reader should be ignored
	* or replaced.
	*/
	public Reader getPermissiveTextReader(InputStream in)


public class PrintTraceListener implements TraceListenerEx2
{

  /**
   * Construct a trace listener.
   *
   * @param pw PrintWriter to use for tracing events
   */
  public PrintTraceListener(java.io.PrintWriter pw)
  {
    m_pw = pw;
  }

  /**
   * The print writer where the events should be written.
   */
  java.io.PrintWriter m_pw;

  /**
   * This needs to be set to true if the listener is to print an event whenever a template is invoked.
   */
  public boolean m_traceTemplates = false;

  /**
   * Set to true if the listener is to print events that occur as each node is 'executed' in the stylesheet.
   */
  public boolean m_traceElements = false;

  /**
   * Set to true if the listener is to print information after each result-tree generation event.
   */
  public boolean m_traceGeneration = false;

  /**
   * Set to true if the listener is to print information after each selection event.
   */
  public boolean m_traceSelection = false;

  /**
   * Print information about a TracerEvent.
   *
   * @param ev the trace event.
   */
  public void _trace(TracerEvent ev)
  {

    switch (ev.m_styleNode.getXSLToken())
    {
    case Constants.ELEMNAME_TEXTLITERALRESULT :
      if (m_traceElements)
      {
        m_pw.print(ev.m_styleNode.getSystemId()+ " Line #" + ev.m_styleNode.getLineNumber() + ", "
                   + "Column #" + ev.m_styleNode.getColumnNumber() + " -- "
                   + ev.m_styleNode.getNodeName() + ": ");

        ElemTextLiteral etl = (ElemTextLiteral) ev.m_styleNode;
        String chars = new String(etl.getChars(), 0, etl.getChars().length);

        m_pw.println("    " + chars.trim());
      }
      break;
    case Constants.ELEMNAME_TEMPLATE :
      if (m_traceTemplates || m_traceElements)
      {
        ElemTemplate et = (ElemTemplate) ev.m_styleNode;

        m_pw.print(et.getSystemId()+ " Line #" + et.getLineNumber() + ", " + "Column #"
                   + et.getColumnNumber() + ": " + et.getNodeName() + " ");

        if (null != et.getMatch())
        {
          m_pw.print("match='" + et.getMatch().getPatternString() + "' ");
        }

        if (null != et.getName())
        {
          m_pw.print("name='" + et.getName() + "' ");
        }

        m_pw.println();
      }
      break;
    default :
      if (m_traceElements)
      {
        m_pw.println(ev.m_styleNode.getSystemId()+ " Line #" + ev.m_styleNode.getLineNumber() + ", "
                     + "Column #" + ev.m_styleNode.getColumnNumber() + ": "
                     + ev.m_styleNode.getNodeName());
      }
    }
  }

  int m_indent = 0;

  /**
   * Print information about a TracerEvent.
   *
   * @param ev the trace event.
   */
  public void trace(TracerEvent ev)
  {
	_trace(ev);
  }

  /**
   * Method that is called when the end of a trace event occurs.
   * The method is blocking.  It must return before processing continues.
   *
   * @param ev the trace event.
   */
  public void traceEnd(TracerEvent ev)
  {
  }

  /**
   * Method that is called just after a select attribute has been evaluated.
   *
   * @param ev the generate event.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public void selected(SelectionEvent ev) throws javax.xml.transform.TransformerException
  {

    if (m_traceSelection)
    {
      ElemTemplateElement ete = (ElemTemplateElement) ev.m_styleNode;
      Node sourceNode = ev.m_sourceNode;

      SourceLocator locator = null;
      if (sourceNode instanceof DTMNodeProxy)
      {
        int nodeHandler = ((DTMNodeProxy)sourceNode).getDTMNodeNumber();
        locator = ((DTMNodeProxy)sourceNode).getDTM().getSourceLocatorFor(nodeHandler);
      }

      if (locator != null)
        m_pw.println("Selected source node '" + sourceNode.getNodeName()
                 + "', at " + locator);
      else
        m_pw.println("Selected source node '" + sourceNode.getNodeName() +"'");

      if (ev.m_styleNode.getLineNumber() == 0)
      {

        ElemTemplateElement parent =
          (ElemTemplateElement) ete.getParentElem();

        if (parent == ete.getStylesheetRoot().getDefaultRootRule())
        {
          m_pw.print("(default root rule) ");
        }
        else if (parent == ete.getStylesheetRoot().getDefaultTextRule())
        {
          m_pw.print("(default text rule) ");
        }
        else if (parent == ete.getStylesheetRoot().getDefaultRule())
        {
          m_pw.print("(default rule) ");
        }

        m_pw.print(ete.getNodeName() + ", " + ev.m_attributeName + "='"
                   + ev.m_xpath.getPatternString() + "': ");
      }
      else
      {
        m_pw.print(ev.m_styleNode.getSystemId()+ " Line #" + ev.m_styleNode.getLineNumber() + ", "
                   + "Column #" + ev.m_styleNode.getColumnNumber() + ": "
                   + ete.getNodeName() + ", " + ev.m_attributeName + "='"
                   + ev.m_xpath.getPatternString() + "': ");
      }

                        if (ev.m_selection.getType() == ev.m_selection.CLASS_NODESET)
                        {
                                m_pw.println();

                                org.apache.xml.dtm.DTMIterator nl = ev.m_selection.iter();

                                try
                                {
                                        nl = nl.cloneWithReset();
                                }
                                catch(CloneNotSupportedException cnse)
                                {
                                        m_pw.println("     [Can't trace nodelist because it it threw a CloneNotSupportedException]");
                                        return;
                                }
                                int pos = nl.nextNode();

                                if (DTM.NULL == pos)
                                {
                                        m_pw.println("     [empty node list]");
                                }
                                else
                                {
                                        while (DTM.NULL != pos)
                                        {
                                                DTM dtm = ev.m_processor.getXPathContext().getDTM(pos);
                                                m_pw.print("     ");
                                                m_pw.print(Integer.toHexString(pos));
                                                m_pw.print(": ");
                                                m_pw.println(dtm.getNodeName(pos));

                                                pos = nl.nextNode();
                                        }
                                }
                        }
      else
      {
        m_pw.println(ev.m_selection.str());
      }
    }
  }

  /**
   * Method that is called after an xsl:apply-templates or xsl:for-each
   * selection occurs.
   *
   * @param ev the generate event.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public void selectEnd(EndSelectionEvent ev)
     throws javax.xml.transform.TransformerException
  {
  }

  /**
   * Print information about a Generate event.
   *
   * @param ev the trace event.
   */
  public void generated(GenerateEvent ev)
  {

    if (m_traceGeneration)
    {
      switch (ev.m_eventtype)
      {
      case GenerateEvent.EVENTTYPE_STARTDOCUMENT :
        m_pw.println("STARTDOCUMENT");
        break;
      case GenerateEvent.EVENTTYPE_ENDDOCUMENT :
        m_pw.println("ENDDOCUMENT");
        break;
      case GenerateEvent.EVENTTYPE_STARTELEMENT :
        m_pw.println("STARTELEMENT: " + ev.m_name);
        break;
      case GenerateEvent.EVENTTYPE_ENDELEMENT :
        m_pw.println("ENDELEMENT: " + ev.m_name);
        break;
      case GenerateEvent.EVENTTYPE_CHARACTERS :
      {
        String chars = new String(ev.m_characters, ev.m_start, ev.m_length);

        m_pw.println("CHARACTERS: " + chars);
      }
      break;
      case GenerateEvent.EVENTTYPE_CDATA :
      {
        String chars = new String(ev.m_characters, ev.m_start, ev.m_length);

        m_pw.println("CDATA: " + chars);
      }
      break;
      case GenerateEvent.EVENTTYPE_COMMENT :
        m_pw.println("COMMENT: " + ev.m_data);
        break;
      case GenerateEvent.EVENTTYPE_PI :
        m_pw.println("PI: " + ev.m_name + ", " + ev.m_data);
        break;
      case GenerateEvent.EVENTTYPE_ENTITYREF :
        m_pw.println("ENTITYREF: " + ev.m_name);
        break;
      case GenerateEvent.EVENTTYPE_IGNORABLEWHITESPACE :
        m_pw.println("IGNORABLEWHITESPACE");
        break;


public class ElemLiteralResult extends ElemUse
{

  /**
   * Tells if this element represents a root element
   * that is also the stylesheet element.
   * TODO: This should be a derived class.
   * @serial
   */
  private boolean isLiteralResultAsStylesheet = false;

  /**
   * Set whether this element represents a root element
   * that is also the stylesheet element.
   *
   *
   * @param b boolean flag indicating whether this element
   * represents a root element that is also the stylesheet element.
   */
  public void setIsLiteralResultAsStylesheet(boolean b)
  {
    isLiteralResultAsStylesheet = b;
  }

  /**
   * Return whether this element represents a root element
   * that is also the stylesheet element.
   *
   *
   * @return boolean flag indicating whether this element
   * represents a root element that is also the stylesheet element.
   */
  public boolean getIsLiteralResultAsStylesheet()
  {
    return isLiteralResultAsStylesheet;
  }

  /**
   * This function is called after everything else has been
   * recomposed, and allows the template to set remaining
   * values that may be based on some other property that
   * depends on recomposition.
   */
  public void compose(StylesheetRoot sroot) throws TransformerException
  {
    super.compose(sroot);
    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
    java.util.Vector vnames = cstate.getVariableNames();
    if (null != m_avts)
    {
      int nAttrs = m_avts.size();

      for (int i = (nAttrs - 1); i >= 0; i--)
      {
        AVT avt = (AVT) m_avts.elementAt(i);
        avt.fixupVariables(vnames, cstate.getGlobalsSize());
      }
    }
  }

  /**
   * The created element node will have the attribute nodes
   * that were present on the element node in the stylesheet tree,
   * other than attributes with names in the XSLT namespace.
   * @serial
   */
  private Vector m_avts = null;

  /** List of attributes with the XSLT namespace.
   *  @serial */
  private Vector m_xslAttr = null;

  /**
   * Set a literal result attribute (AVTs only).
   *
   * @param avt literal result attribute to add (AVT only)
   */
  public void addLiteralResultAttribute(AVT avt)
  {

    if (null == m_avts)
      m_avts = new Vector();

    m_avts.addElement(avt);
  }

  /**
   * Set a literal result attribute (used for xsl attributes).
   *
   * @param att literal result attribute to add
   */
  public void addLiteralResultAttribute(String att)
  {

    if (null == m_xslAttr)
      m_xslAttr = new Vector();

    m_xslAttr.addElement(att);
  }

  /**
   * Set the "xml:space" attribute.
   * A text node is preserved if an ancestor element of the text node
   * has an xml:space attribute with a value of preserve, and
   * no closer ancestor element has xml:space with a value of default.
   *
   * @param v  Enumerated value, either Constants.ATTRVAL_PRESERVE
   * or Constants.ATTRVAL_STRIP.
   */
  public void setXmlSpace(AVT avt)
  {
    addLiteralResultAttribute(avt);
    String val = avt.getSimpleString();
    if(val.equals("default"))
    {
      super.setXmlSpace(Constants.ATTRVAL_STRIP);
    }
    else if(val.equals("preserve"))
    {
      super.setXmlSpace(Constants.ATTRVAL_PRESERVE);
    }
  }

  /**
   * Get a literal result attribute by name.
   *
   * @param name Name of literal result attribute to get
   *
   * @return literal result attribute (AVT)
   */
  public AVT getLiteralResultAttribute(String name)
  {

    if (null != m_avts)
    {
      int nAttrs = m_avts.size();

      for (int i = (nAttrs - 1); i >= 0; i--)
      {
        AVT avt = (AVT) m_avts.elementAt(i);

        if (avt.getRawName().equals(name))
        {
          return avt;
        }
	  }
    }

    return null;
  }

  /**
   * Get whether or not the passed URL is flagged by
   * the "extension-element-prefixes" or "exclude-result-prefixes"
   * properties.
   *
   * @param prefix non-null reference to prefix that might be excluded.(not currently used)
   * @param uri reference to namespace that prefix maps to
   *
   * @return true if the prefix should normally be excluded.
   */
  public boolean containsExcludeResultPrefix(String prefix, String uri)
  {
    if (uri == null ||
				(null == m_excludeResultPrefixes &&
				 null == m_ExtensionElementURIs)
				)
      return super.containsExcludeResultPrefix(prefix, uri);

    if (prefix.length() == 0)
      prefix = Constants.ATTRVAL_DEFAULT_PREFIX;

		if(m_excludeResultPrefixes!=null)
			for (int i =0; i< m_excludeResultPrefixes.size(); i++)
			{
				if (uri.equals(getNamespaceForPrefix(m_excludeResultPrefixes.elementAt(i))))
					return true;
			}

    if(m_ExtensionElementURIs!=null && m_ExtensionElementURIs.contains(uri))
       return true;

		return super.containsExcludeResultPrefix(prefix, uri);
  }

  /**
   * Augment resolvePrefixTables, resolving the namespace aliases once
   * the superclass has resolved the tables.
   *
   * @throws TransformerException
   */
  public void resolvePrefixTables() throws TransformerException
  {

    super.resolvePrefixTables();

    StylesheetRoot stylesheet = getStylesheetRoot();

    if ((null != m_namespace) && (m_namespace.length() > 0))
    {
      NamespaceAlias nsa = stylesheet.getNamespaceAliasComposed(m_namespace);

      if (null != nsa)
      {
        m_namespace = nsa.getResultNamespace();

        if ((null != resultPrefix) && (resultPrefix.length() > 0))
          m_rawName = resultPrefix + ":" + m_localName;
        else
          m_rawName = m_localName;
      }
    }

    if (null != m_avts)
    {
      int n = m_avts.size();

      for (int i = 0; i < n; i++)
      {
        AVT avt = (AVT) m_avts.elementAt(i);

        String ns = avt.getURI();

        if ((null != ns) && (ns.length() > 0))
        {
          NamespaceAlias nsa = 0;

          if (null != nsa)
          {
            String namespace = nsa.getResultNamespace();

            String rawName = avt.getName();

            if ((null != resultPrefix) && (resultPrefix.length() > 0))
              rawName = resultPrefix + ":" + rawName;

            avt.setURI(namespace);
            avt.setRawName(rawName);
          }
        }
      }
    }
  }

  /**
   * Return whether we need to check namespace prefixes
   * against the exclude result prefixes or extensions lists.
   * Note that this will create a new prefix table if one
   * has not been created already.
   *
   * NEEDSDOC ($objectName$) @return
   */
  boolean needToCheckExclude()
  {
    if (null == m_excludeResultPrefixes && null == m_prefixTable
				)
      return false;
    else
    {

      if (null == m_prefixTable)
        m_prefixTable = new Vector();

      return true;
    }
  }

  /**
   * The namespace of the element to be created.
   * @serial
   */
  private String m_namespace;

  /**
   * Set the namespace URI of the result element to be created.
   * Note that after resolvePrefixTables has been called, this will
   * return the aliased result namespace, not the original stylesheet
   * namespace.
   *
   * @param ns The Namespace URI, or the empty string if the
   *        element has no Namespace URI.
   */
  public void setNamespace(String ns)
  {
      ns = "";
    m_namespace = ns;
  }

  /**
   * Get the original namespace of the Literal Result Element.
   *
   * %REVIEW% Why isn't this overriding the getNamespaceURI method
   * rather than introducing a new one?
   *
   * @return The Namespace URI, or the empty string if the
   *        element has no Namespace URI.
   */
  public String getNamespace()
  {
    return m_namespace;
  }

  /**
   * The local name of the element to be created.
   * @serial
   */
  private String m_localName;

  /**
   * Set the local name of the LRE.
   *
   * @param localName The local name (without prefix) of the result element
   *                  to be created.
   */
  public void setLocalName(String localName)
  {
    m_localName = localName;
  }

  /**
   * Get the local name of the Literal Result Element.
   * Note that after resolvePrefixTables has been called, this will
   * return the aliased name prefix, not the original stylesheet
   * namespace prefix.
   *
   * @return The local name (without prefix) of the result element
   *                  to be created.
   */
  public String getLocalName()
  {
    return m_localName;
  }

  /**
   * The raw name of the element to be created.
   * @serial
   */
  private String m_rawName;

  /**
   * Set the raw name of the LRE.
   *
   * @param rawName The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   */
  public void setRawName(String rawName)
  {
    m_rawName = rawName;
  }

  /**
   * Get the raw name of the Literal Result Element.
   *
   * @return  The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   */
  public String getRawName()
  {
    return m_rawName;
  }

 /**
   * Get the prefix part of the raw name of the Literal Result Element.
   *
   * @return The prefix, or the empty string if noprefix was provided.
   */
  public String getPrefix()
  {
		int len=m_rawName.length()-m_localName.length()-1;
    return (len>0)
			? m_rawName.substring(0,len)
			: "";
  }

  /**
   * The "extension-element-prefixes" property, actually contains URIs.
   * @serial
   */
  private StringVector m_ExtensionElementURIs;

  /**
   * Set the "extension-element-prefixes" property.
   *
   * @param v Vector of URIs (not prefixes) to set as the "extension-element-prefixes" property
   */
  public void setExtensionElementPrefixes(StringVector v)
  {
    m_ExtensionElementURIs = v;
  }

  /**
   * Get an "extension-element-prefix" property.
   *
   * @param i Index of URI ("extension-element-prefix" property) to get
   *
   * @return URI at given index ("extension-element-prefix" property)
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public String getExtensionElementPrefix(int i)
          throws ArrayIndexOutOfBoundsException
  {

    if (null == m_ExtensionElementURIs)
      throw new ArrayIndexOutOfBoundsException();

    return m_ExtensionElementURIs.elementAt(i);
  }

  /**
   * Get the number of "extension-element-prefixes" Strings.
   *
   * @return the number of "extension-element-prefixes" Strings
   */
  public int getExtensionElementPrefixCount()
  {
    return (null != m_ExtensionElementURIs)
           ? m_ExtensionElementURIs.size() : 0;
  }

  /**
   * Find out if the given "extension-element-prefix" property is defined.
   *
   * @param uri The URI to find
   *
   * @return True if the given URI is found
   */
  public boolean containsExtensionElementURI(String uri)
  {

    if (null == m_ExtensionElementURIs)
      return false;

    return m_ExtensionElementURIs.contains(uri);
  }

  /**
   * Get an int constant identifying the type of element.
   * @see org.apache.xalan.templates.Constants
   *
   * @return The token ID for this element
   */
  public int getXSLToken()
  {
    return Constants.ELEMNAME_LITERALRESULT;
  }

  /**
   * Return the node name.
   *
   * @return The element's name
   */
  public String getNodeName()
  {

    return m_rawName;
  }

  /**
   * The XSLT version as specified by this element.
   * @serial
   */
  private String m_version;

  /**
   * Set the "version" property.
   *
   * @param v Version property value to set
   */
  public void setVersion(String v)
  {
    m_version = v;
  }

  /**
   * Get the "version" property.
   *
   * @return Version property value
   */
  public String getVersion()
  {
    return m_version;
  }

  /**
   * The "exclude-result-prefixes" property.
   * @serial
   */
  private StringVector m_excludeResultPrefixes;

  /**
   * Set the "exclude-result-prefixes" property.
   * The designation of a namespace as an excluded namespace is
   * effective within the subtree of the stylesheet rooted at
   * the element bearing the exclude-result-prefixes or
   * xsl:exclude-result-prefixes attribute; a subtree rooted
   * at an xsl:stylesheet element does not include any stylesheets
   * imported or included by children of that xsl:stylesheet element.
   *
   * @param v vector of prefixes that are resolvable to strings.
   */
  public void setExcludeResultPrefixes(StringVector v)
  {
    m_excludeResultPrefixes = v;
  }

  /**
   * Tell if the result namespace decl should be excluded.  Should be called before
   * namespace aliasing (I think).
   *
   * @param prefix Prefix of namespace to check
   * @param uri URI of namespace to check
   *
   * @return True if the given namespace should be excluded
   *
   * @throws TransformerException
   */
  private boolean excludeResultNSDecl(String prefix, String uri)
          throws TransformerException
  {

    if (null != m_excludeResultPrefixes)
    {
      return containsExcludeResultPrefix(prefix, uri);
    }

    return false;
  }

  /**
   * Copy a Literal Result Element into the Result tree, copy the
   * non-excluded namespace attributes, copy the attributes not
   * of the XSLT namespace, and execute the children of the LRE.
   *
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @throws TransformerException
   */
  public void execute(
          TransformerImpl transformer)
            throws TransformerException
  {

    try
    {
      ResultTreeHandler rhandler = transformer.getResultTreeHandler();

			rhandler.startPrefixMapping(getPrefix(),getNamespace());

      executeNSDecls(transformer);
      rhandler.startElement(getNamespace(), getLocalName(), getRawName(), null);

      try
      {

        super.execute(transformer);

        if (null != m_avts)
        {
          int nAttrs = m_avts.size();

          for (int i = (nAttrs - 1); i >= 0; i--)
          {
            AVT avt = (AVT) m_avts.elementAt(i);
            XPathContext xctxt = transformer.getXPathContext();
            int sourceNode = xctxt.getCurrentNode();
            String stringedValue = avt.evaluate(xctxt, sourceNode, this);

            if (null != stringedValue)
            {

              rhandler.addAttribute(avt.getURI(), avt.getName(),
                                    avt.getRawName(), "CDATA", stringedValue);
            }
		  }
        }

        transformer.executeChildTemplates(this, true);
      }
      finally
      {
        rhandler.endElement(getNamespace(), getLocalName(), getRawName());
        unexecuteNSDecls(transformer);

				rhandler.endPrefixMapping(getPrefix());
      }
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
  }

  /**
   * Compiling templates requires that we be able to list the AVTs
   * ADDED 9/5/2000 to support compilation experiment
   *
   * @return an Enumeration of the literal result attributes associated
   * with this element.
   */
  public Enumeration enumerateLiteralResultAttributes()
  {
    return (null == m_avts) ? null : m_avts.elements();
  }

    /**
     * Accept a visitor and call the appropriate method
     * for this class.
     *
     * @param visitor The visitor whose appropriate method will be called.
     * @return true if the children of the object should be visited.
     */
    protected boolean accept(XSLTVisitor visitor)
    {
      return visitor.visitLiteralResultElement(this);
    }

    /**
     * Call the children visitors.
     * @param visitor The visitor whose appropriate method will be called.
     */
    protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
    {
      if (callAttrs && null != m_avts)
      {
        int nAttrs = m_avts.size();

        for (int i = (nAttrs - 1); i >= 0; i--)
        {
          AVT avt = (AVT) m_avts.elementAt(i);
          avt.callVisitors(visitor);
        }
      }
      super.callChildVisitors(visitor, callAttrs);


public class StreamEndpoint extends DefaultEndpoint<Exchange> {
    private static final transient Log LOG = LogFactory.getLog(StreamEndpoint.class);

    private String uri;
    private String file;
    private String url;
    private long delay;
    private String encoding;

    public StreamEndpoint(String endpointUri, Component component) throws Exception {
        super(endpointUri, component);
        this.uri = endpointUri;
    }

    public StreamEndpoint(String endpointUri) {
        super(endpointUri);
        this.uri = endpointUri;
    }

    public Consumer<Exchange> createConsumer(Processor processor) throws Exception {
        return new StreamConsumer(this, processor, uri);
    }

    public Producer<Exchange> createProducer() throws Exception {
        return new StreamProducer(this, uri);
    }

    public boolean isSingleton() {
        return true;
    }

    public String getFile() {
        return file;
    }

    /**
     * @deprecated use camel-file component. Will be removed in Camel 2.0
     */
    public void setFile(String file) {
        this.file = file;
    }

    public String getUrl() {
        return url;
    }

    /**
     * @deprecated use camel-jetty or camel-http component. Will be removed in Camel 2.0
     */
    public void setUrl(String url) {
        this.url = url;
    }

    public long getDelay() {
        return delay;
    }

    public void setDelay(long delay) {
        this.delay = delay;
    }

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    Charset getCharset() {
        if (encoding == null) {
            encoding = Charset.defaultCharset().name();
            if (LOG.isDebugEnabled()) {
                LOG.debug("No encoding parameter using default charset: " + encoding);
            }
        }
        if (!Charset.isSupported(encoding)) {
            throw new IllegalArgumentException("The encoding: " + encoding + " is not supported");
        }

        return Charset.forName(encoding);

    public String getFile() {
        return file;

    public String getUrl() {
        return url;

    public long getDelay() {
        return delay;


org.apache.tools.ant.util.JavaEnvUtils

public class JavaEnvUtils {

    /** Are we on a DOS-based system */
    private static final boolean isDos = Os.isFamily("dos");
    /** Are we on Novell NetWare */
    private static final boolean isNetware = Os.isName("netware");
    /** Are we on AIX */
    private static final boolean isAix = Os.isName("aix");

    /** shortcut for System.getProperty("java.home") */
    private static final String javaHome = System.getProperty("java.home");

    /** FileUtils instance for path normalization */
    private static final FileUtils fileUtils = FileUtils.newFileUtils();

    /** Version of currently running VM. */
    private static String javaVersion;

    /** floating version of the JVM */
    private static int javaVersionNumber;

    /** Version constant for Java 1.0 */
    public static final String JAVA_1_0 = "1.0";
    /** Version constant for Java 1.1 */
    public static final String JAVA_1_1 = "1.1";
    /** Version constant for Java 1.2 */
    public static final String JAVA_1_2 = "1.2";
    /** Version constant for Java 1.3 */
    public static final String JAVA_1_3 = "1.3";
    /** Version constant for Java 1.4 */
    public static final String JAVA_1_4 = "1.4";

    /** array of packages in the runtime */
    private static Vector jrePackages;

    static {

        try {
            javaVersion = JAVA_1_0;
            javaVersionNumber=10;
            Class.forName("java.lang.Void");
            javaVersion = JAVA_1_1;
            javaVersionNumber++;
            Class.forName("java.lang.ThreadLocal");
            javaVersion = JAVA_1_2;
            javaVersionNumber++;
            Class.forName("java.lang.StrictMath");
            javaVersion = JAVA_1_3;
            javaVersionNumber++;
            Class.forName("java.lang.CharSequence");
            javaVersion = JAVA_1_4;
            javaVersionNumber++;
        } catch (Throwable t) {
        }
    }

    /**
     * Returns the version of Java this class is running under.
     * @return the version of Java as a String, e.g. "1.1"
     */
    public static String getJavaVersion() {
        return javaVersion;
    }

    /**
     * Compares the current Java version to the passed in String -
     * assumes the argument is one of the constants defined in this
     * class.
     * @return true if the version of Java is the same as the given
     * version.
     * @since Ant 1.5
     */
    public static boolean isJavaVersion(String version) {
        return javaVersion == version;
    }

    /**
     * Finds an executable that is part of a JRE installation based on
     * the java.home system property.
     *
     *
java, keytool,
     * policytool, orbd, rmid,
     * rmiregistry, servertool and
     * tnameserv are JRE executables on Sun based
     * JRE's.

     *
     *
You typically find them in JAVA_HOME/jre/bin if
     * JAVA_HOME points to your JDK installation.  JDK
     * < 1.2 has them in the same directory as the JDK
     * executables.

     *
     * @since Ant 1.5
     */
    public static String getJreExecutable(String command) {
        if (isNetware) {
            return command;
        }

        File jExecutable = null;

        if (isAix) {
            jExecutable = findInDir(javaHome + "/sh", command);
        }

        if (jExecutable == null) {
            jExecutable = findInDir(javaHome + "/bin", command);
        }

        if (jExecutable != null) {
            return jExecutable.getAbsolutePath();
        } else {
            return addExtension(command);
        }
    }

    /**
     * Finds an executable that is part of a JDK installation based on
     * the java.home system property.
     *
     *
You typically find them in JAVA_HOME/bin if
     * JAVA_HOME points to your JDK installation.

     *
     * @since Ant 1.5
     */
    public static String getJdkExecutable(String command) {
        if (isNetware) {
            return command;
        }

        File jExecutable = null;

        if (isAix) {
            jExecutable = findInDir(javaHome + "/../sh", command);
        }

        if (jExecutable == null) {
            jExecutable = findInDir(javaHome + "/../bin", command);
        }

        if (jExecutable != null) {
            return jExecutable.getAbsolutePath();
        } else {
            return getJreExecutable(command);
        }
    }

    /**
     * Adds a system specific extension to the name of an executable.
     *
     * @since Ant 1.5
     */
    private static String addExtension(String command) {
        return command + (isDos ? ".exe" : "");
    }

    /**
     * Look for an executable in a given directory.
     *
     * @return null if the executable cannot be found.
     */
    private static File findInDir(String dirName, String commandName) {
        File dir = fileUtils.normalize(dirName);
        File executable = null;
        if (dir.exists()) {
            executable = new File(dir, addExtension(commandName));
            if (!executable.exists()) {
                executable = null;
            }
        }
        return executable;
    }

    /**
     * demand creation of the package list.
     * When you add a new package, add a new test below
     */

    private static void buildJrePackages() {
        jrePackages=new Vector();
        switch(javaVersionNumber) {
            case 14:
                jrePackages.addElement("org.apache.crimson");
                jrePackages.addElement("org.apache.xalan");
                jrePackages.addElement("org.apache.xml");
                jrePackages.addElement("org.apache.xpath");
                jrePackages.addElement("org.ietf.jgss");
                jrePackages.addElement("org.w3c.dom");
                jrePackages.addElement("org.xml.sax");
            case 13:
                jrePackages.addElement("org.omg");
                jrePackages.addElement("com.sun.corba");
                jrePackages.addElement("com.sun.jndi");
                jrePackages.addElement("com.sun.media");
                jrePackages.addElement("com.sun.naming");
                jrePackages.addElement("com.sun.org.omg");
                jrePackages.addElement("com.sun.rmi");
                jrePackages.addElement("sunw.io");
                jrePackages.addElement("sunw.util");
            case 12:
                jrePackages.addElement("com.sun.java");
                jrePackages.addElement("com.sun.image");
            case 11:
            default:
                jrePackages.addElement("sun");
                jrePackages.addElement("java");
                jrePackages.addElement("javax");
                break;
        }
    }

    /**
     * Testing helper method; kept here for unification of changes.
     */
    public static Vector getJrePackageTestCases() {
        Vector tests=new Vector();
        tests.addElement("java.lang.Object");
        switch(javaVersionNumber) {
            case 14:
                tests.addElement("sun.audio.AudioPlayer");
                tests.addElement("org.apache.crimson.parser.ContentModel");
                tests.addElement("org.apache.xalan.processor.ProcessorImport");
                tests.addElement("org.apache.xml.utils.URI");
                tests.addElement("org.apache.xpath.XPathFactory");
                tests.addElement("org.ietf.jgss.Oid");
                tests.addElement("org.w3c.dom.Attr");
                tests.addElement("org.xml.sax.XMLReader");
            case 13:
                tests.addElement("org.omg.CORBA.Any");
                tests.addElement("com.sun.corba.se.internal.corba.AnyImpl");
                tests.addElement("com.sun.jndi.ldap.LdapURL");
                tests.addElement("com.sun.media.sound.Printer");
                tests.addElement("com.sun.naming.internal.VersionHelper");
                tests.addElement("com.sun.org.omg.CORBA.Initializer");
                tests.addElement("sunw.io.Serializable");
                tests.addElement("sunw.util.EventListener");
            case 12:
                tests.addElement("javax.accessibility.Accessible");
                tests.addElement("sun.misc.BASE64Encoder");
                tests.addElement("com.sun.image.codec.jpeg.JPEGCodec");
            case 11:
            default:
                tests.addElement("sun.reflect.SerializationConstructorAccessorImpl");
                tests.addElement("sun.net.www.http.HttpClient");
                tests.addElement("sun.audio.AudioPlayer");
                break;
        }
        return tests;
    }
    /**
     * get a vector of strings of packages built into
     * that platforms runtime jar(s)
     * @return list of packages
     */
    public static Vector getJrePackages() {
        if(jrePackages==null) {
            buildJrePackages();
        }
        return jrePackages;

FUNC_DECL RETURN IF VAR_DECL VAR_DECL PARAM PARAM CALL IF LITERAL_ANCHOR CALL CALL ASSIGN CALL ASSIGN CALL LITERAL_ANCHOR


org.apache.poi.util.LongField

public class LongField
    implements FixedField
{
    private long      _value;
    private final int _offset;

    /**
     * construct the LongField with its offset into its containing
     * byte array
     *
     * @param offset of the field within its byte array
     *
     * @exception ArrayIndexOutOfBoundsException if offset is negative
     */

    public LongField(final int offset)
        throws ArrayIndexOutOfBoundsException
    {
        if (offset < 0)
        {
            throw new ArrayIndexOutOfBoundsException("Illegal offset: "
                                                     + offset);
        }
        _offset = offset;
    }

    /**
     * construct the LongField with its offset into its containing
     * byte array and initialize its value
     *
     * @param offset of the field within its byte array
     * @param value the initial value
     *
     * @exception ArrayIndexOutOfBoundsException if offset is negative
     */

    public LongField(final int offset, final long value)
        throws ArrayIndexOutOfBoundsException
    {
        this(offset);
        set(value);
    }

    /**
     * Construct the LongField with its offset into its containing
     * byte array and initialize its value from its byte array
     *
     * @param offset of the field within its byte array
     * @param data the byte array to read the value from
     *
     * @exception ArrayIndexOutOfBoundsException if the offset is not
     *            within the range of 0..(data.length - 1)
     */

    public LongField(final int offset, final byte [] data)
        throws ArrayIndexOutOfBoundsException
    {
        this(offset);
        readFromBytes(data);
    }

    /**
     * construct the LongField with its offset into its containing
     * byte array, initialize its value, and write the value to a byte
     * array
     *
     * @param offset of the field within its byte array
     * @param value the initial value
     * @param data the byte array to write the value to
     *
     * @exception ArrayIndexOutOfBoundsException if offset is negative
     */

    public LongField(final int offset, final long value, final byte [] data)
        throws ArrayIndexOutOfBoundsException
    {
        this(offset);
        set(value, data);
    }

    /**
     * get the LongField's current value
     *
     * @return current value
     */

    public long get()
    {
        return _value;
    }

    /**
     * set the LongField's current value
     *
     * @param value to be set
     */

    public void set(final long value)
    {
        _value = value;
    }

    /**
     * set the LongField's current value and write it to a byte array
     *
     * @param value to be set
     * @param data the byte array to write the value to
     *
     * @exception ArrayIndexOutOfBoundsException if the offset is out
     *            of range
     */

    public void set(final long value, final byte [] data)
        throws ArrayIndexOutOfBoundsException
    {
        _value = value;
        writeToBytes(data);
    }

    /* ********** START implementation of FixedField ********** */

    /**
     * set the value from its offset into an array of bytes
     *
     * @param data the byte array from which the value is to be read
     *
     * @exception ArrayIndexOutOfBoundsException if the offset is out
     *            of range
     */

    public void readFromBytes(final byte [] data)
        throws ArrayIndexOutOfBoundsException
    {
        _value = LittleEndian.getLong(data, _offset);
    }

    /**
     * set the value from an InputStream
     *
     * @param stream the InputStream from which the value is to be
     *               read
     *
     * @exception BufferUnderrunException if there is not enough data
     *            available from the InputStream
     * @exception IOException if an IOException is thrown from reading
     *            the InputStream
     */

    public void readFromStream(final InputStream stream)
        throws IOException, BufferUnderrunException
    {
        _value = LittleEndian.readLong(stream);
    }

    /**
     * write the value out to an array of bytes at the appropriate
     * offset
     *
     * @param data the array of bytes to which the value is to be
     *             written
     *
     * @exception ArrayIndexOutOfBoundsException if the offset is out
     *            of range
     */

    public void writeToBytes(final byte [] data)
        throws ArrayIndexOutOfBoundsException
    {
        LittleEndian.putLong(data, _offset, _value);
    }

    /**
     * return the value as a String
     *
     * @return the value as a String
     */

    public String toString()
    {
        return String.valueOf(_value);

    public long get()
    {
        return _value;