gnu.regexp.RE

public class RE extends REToken {
  // This String will be returned by getVersion()
  private static final String VERSION = "1.1.5-dev";

  // The localized strings are kept in a separate file
  private static ResourceBundle messages = PropertyResourceBundle.getBundle("gnu/regexp/MessagesBundle", Locale.getDefault());

  // These are, respectively, the first and last tokens in our linked list
  // If there is only one token, firstToken == lastToken
  private REToken firstToken, lastToken;

  // This is the number of subexpressions in this regular expression,
  // with a minimum value of zero.  Returned by getNumSubs()
  private int numSubs;

    /** Minimum length, in characters, of any possible match. */
    private int minimumLength;

  /**
   * Compilation flag. Do  not  differentiate  case.   Subsequent
   * searches  using  this  RE will be case insensitive.
   */
  public static final int REG_ICASE = 2;

  /**
   * Compilation flag. The match-any-character operator (dot)
   * will match a newline character.  When set this overrides the syntax
   * bit RE_DOT_NEWLINE (see RESyntax for details).  This is equivalent to
   * the "/s" operator in Perl.
   */
  public static final int REG_DOT_NEWLINE = 4;

  /**
   * Compilation flag. Use multiline mode.  In this mode, the ^ and $
   * anchors will match based on newlines within the input. This is
   * equivalent to the "/m" operator in Perl.
   */
  public static final int REG_MULTILINE = 8;

  /**
   * Execution flag.
   * The match-beginning operator (^) will not match at the beginning
   * of the input string. Useful for matching on a substring when you
   * know the context of the input is such that position zero of the
   * input to the match test is not actually position zero of the text.
   *

   * This example demonstrates the results of various ways of matching on
   * a substring.
   *

   *
   * String s = "food bar fool";

   * RE exp = new RE("^foo.");

   * REMatch m0 = exp.getMatch(s);

   * REMatch m1 = exp.getMatch(s.substring(8));

   * REMatch m2 = exp.getMatch(s.substring(8),0,RE.REG_NOTBOL);

   * REMatch m3 = exp.getMatch(s,8);

   * REMatch m4 = exp.getMatch(s,8,RE.REG_ANCHORINDEX);

   *

   * // Results:

   * //  m0.toString(): "food"

   * //  m1.toString(): "fool"

   * //  m2.toString(): null

   * //  m3.toString(): null

   * //  m4.toString(): "fool"

   *
   */
  public static final int REG_NOTBOL = 16;

  /**
   * Execution flag.
   * The match-end operator ($) does not match at the end
   * of the input string. Useful for matching on substrings.
   */
  public static final int REG_NOTEOL = 32;

  /**
   * Execution flag.
   * When a match method is invoked that starts matching at a non-zero
   * index into the input, treat the input as if it begins at the index
   * given.  The effect of this flag is that the engine does not "see"
   * any text in the input before the given index.  This is useful so
   * that the match-beginning operator (^) matches not at position 0
   * in the input string, but at the position the search started at
   * (based on the index input given to the getMatch function).  See
   * the example under REG_NOTBOL.  It also affects the use of the \<
   * and \b operators.
   */
  public static final int REG_ANCHORINDEX = 64;

  /**
   * Execution flag.
   * The substitute and substituteAll methods will not attempt to
   * interpolate occurrences of $1-$9 in the replacement text with
   * the corresponding subexpressions.  For example, you may want to
   * replace all matches of "one dollar" with "$1".
   */
  public static final int REG_NO_INTERPOLATE = 128;

  /** Returns a string representing the version of the gnu.regexp package. */
  public static final String version() {
    return VERSION;
  }

  // Retrieves a message from the ResourceBundle
  static final String getLocalizedMessage(String key) {
    return messages.getString(key);
  }

  /**
   * Constructs a regular expression pattern buffer without any compilation
   * flags set, and using the default syntax (RESyntax.RE_SYNTAX_PERL5).
   *
   * @param pattern A regular expression pattern, in the form of a String,
   *   StringBuffer or char[].  Other input types will be converted to
   *   strings using the toString() method.
   * @exception REException The input pattern could not be parsed.
   * @exception NullPointerException The pattern was null.
   */
  public RE(Object pattern) throws REException {
    this(pattern,0,RESyntax.RE_SYNTAX_PERL5,0,0);
  }

  /**
   * Constructs a regular expression pattern buffer using the specified
   * compilation flags and the default syntax (RESyntax.RE_SYNTAX_PERL5).
   *
   * @param pattern A regular expression pattern, in the form of a String,
   *   StringBuffer, or char[].  Other input types will be converted to
   *   strings using the toString() method.
   * @param cflags The logical OR of any combination of the compilation flags listed above.
   * @exception REException The input pattern could not be parsed.
   * @exception NullPointerException The pattern was null.
   */
  public RE(Object pattern, int cflags) throws REException {
    this(pattern,cflags,RESyntax.RE_SYNTAX_PERL5,0,0);
  }

  /**
   * Constructs a regular expression pattern buffer using the specified
   * compilation flags and regular expression syntax.
   *
   * @param pattern A regular expression pattern, in the form of a String,
   *   StringBuffer, or char[].  Other input types will be converted to
   *   strings using the toString() method.
   * @param cflags The logical OR of any combination of the compilation flags listed above.
   * @param syntax The type of regular expression syntax to use.
   * @exception REException The input pattern could not be parsed.
   * @exception NullPointerException The pattern was null.
   */
  public RE(Object pattern, int cflags, RESyntax syntax) throws REException {
    this(pattern,cflags,syntax,0,0);
  }

  // internal constructor used for alternation
  private RE(REToken first, REToken last,int subs, int subIndex, int minLength) {
    super(subIndex);
    firstToken = first;
    lastToken = last;
    numSubs = subs;
    minimumLength = minLength;
    addToken(new RETokenEndSub(subIndex));
  }

  private RE(Object patternObj, int cflags, RESyntax syntax, int myIndex, int nextSub) throws REException {
    super(myIndex); // Subexpression index of this token.
    initialize(patternObj, cflags, syntax, myIndex, nextSub);
  }

    // For use by subclasses
    protected RE() { super(0); }

    // The meat of construction
  protected void initialize(Object patternObj, int cflags, RESyntax syntax, int myIndex, int nextSub) throws REException {
      char[] pattern;
    if (patternObj instanceof String) {
      pattern = ((String) patternObj).toCharArray();
    } else if (patternObj instanceof char[]) {
      pattern = (char[]) patternObj;
    } else if (patternObj instanceof StringBuffer) {
      pattern = new char [((StringBuffer) patternObj).length()];
      ((StringBuffer) patternObj).getChars(0,pattern.length,pattern,0);
    } else {
	pattern = patternObj.toString().toCharArray();
    }

    int pLength = pattern.length;

    numSubs = 0; // Number of subexpressions in this token.
    Vector branches = null;

    // linked list of tokens (sort of -- some closed loops can exist)
    firstToken = lastToken = null;

    // Precalculate these so we don't pay for the math every time we
    // need to access them.
    boolean insens = ((cflags & REG_ICASE) > 0);

    // Parse pattern into tokens.  Does anyone know if it's more efficient
    // to use char[] than a String.charAt()?  I'm assuming so.

    // index tracks the position in the char array
    int index = 0;

    // this will be the current parse character (pattern[index])
    CharUnit unit = new CharUnit();

    // This is used for {x,y} calculations
    IntPair minMax = new IntPair();

    // Buffer a token so we can create a TokenRepeated, etc.
    REToken currentToken = null;
    char ch;

    while (index < pLength) {
      // read the next character unit (including backslash escapes)
      index = getCharUnit(pattern,index,unit);

      // ALTERNATION OPERATOR
      //  \| or | (if RE_NO_BK_VBAR) or newline (if RE_NEWLINE_ALT)
      //  not available if RE_LIMITED_OPS is set

      // TODO: the '\n' literal here should be a test against REToken.newline,
      // which unfortunately may be more than a single character.
      if ( ( (unit.ch == '|' && (syntax.get(RESyntax.RE_NO_BK_VBAR) ^ unit.bk))
	     || (syntax.get(RESyntax.RE_NEWLINE_ALT) && (unit.ch == '\n') && !unit.bk) )
	   && !syntax.get(RESyntax.RE_LIMITED_OPS)) {
	// make everything up to here be a branch. create vector if nec.
	addToken(currentToken);
	RE theBranch = new RE(firstToken, lastToken, numSubs, subIndex, minimumLength);
	minimumLength = 0;
	if (branches == null) {
	    branches = new Vector();
	}
	branches.addElement(theBranch);
	firstToken = lastToken = currentToken = null;
      }

      // INTERVAL OPERATOR:
      //  {x} | {x,} | {x,y}  (RE_INTERVALS && RE_NO_BK_BRACES)
      //  \{x\} | \{x,\} | \{x,y\} (RE_INTERVALS && !RE_NO_BK_BRACES)
      //
      // OPEN QUESTION:
      //  what is proper interpretation of '{' at start of string?

      else if ((unit.ch == '{') && syntax.get(RESyntax.RE_INTERVALS) && (syntax.get(RESyntax.RE_NO_BK_BRACES) ^ unit.bk)) {
	int newIndex = getMinMax(pattern,index,minMax,syntax);
        if (newIndex > index) {
          if (minMax.first > minMax.second)
            throw new REException(getLocalizedMessage("interval.order"),REException.REG_BADRPT,newIndex);
          if (currentToken == null)
            throw new REException(getLocalizedMessage("repeat.no.token"),REException.REG_BADRPT,newIndex);
          if (currentToken instanceof RETokenRepeated)
            throw new REException(getLocalizedMessage("repeat.chained"),REException.REG_BADRPT,newIndex);
          if (currentToken instanceof RETokenWordBoundary || currentToken instanceof RETokenWordBoundary)
            throw new REException(getLocalizedMessage("repeat.assertion"),REException.REG_BADRPT,newIndex);
          if ((currentToken.getMinimumLength() == 0) && (minMax.second == Integer.MAX_VALUE))
            throw new REException(getLocalizedMessage("repeat.empty.token"),REException.REG_BADRPT,newIndex);
          index = newIndex;
          currentToken = setRepeated(currentToken,minMax.first,minMax.second,index);
        }
        else {
          addToken(currentToken);
          currentToken = new RETokenChar(subIndex,unit.ch,insens);
        }
      }

      // LIST OPERATOR:
      //  [...] | [^...]

      else if ((unit.ch == '[') && !unit.bk) {
	Vector options = new Vector();
	boolean negative = false;
	char lastChar = 0;
	if (index == pLength) throw new REException(getLocalizedMessage("unmatched.bracket"),REException.REG_EBRACK,index);

	// Check for initial caret, negation
	if ((ch = pattern[index]) == '^') {
	  negative = true;
	  if (++index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
	  ch = pattern[index];
	}

	// Check for leading right bracket literal
	if (ch == ']') {
	  lastChar = ch;
	  if (++index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
	}

	while ((ch = pattern[index++]) != ']') {
	  if ((ch == '-') && (lastChar != 0)) {
	    if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
	    if ((ch = pattern[index]) == ']') {
	      options.addElement(new RETokenChar(subIndex,lastChar,insens));
	      lastChar = '-';
	    } else {
	      options.addElement(new RETokenRange(subIndex,lastChar,ch,insens));
	      lastChar = 0;
	      index++;
	    }
          } else if ((ch == '\\') && syntax.get(RESyntax.RE_BACKSLASH_ESCAPE_IN_LISTS)) {
            if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
	    int posixID = -1;
	    boolean negate = false;
            char asciiEsc = 0;
	    if (("dswDSW".indexOf(pattern[index]) != -1) && syntax.get(RESyntax.RE_CHAR_CLASS_ESC_IN_LISTS)) {
	      switch (pattern[index]) {
	      case 'D':
		negate = true;
	      case 'd':
		posixID = RETokenPOSIX.DIGIT;
		break;
	      case 'S':
		negate = true;
	      case 's':
		posixID = RETokenPOSIX.SPACE;
		break;
	      case 'W':
		negate = true;
	      case 'w':
		posixID = RETokenPOSIX.ALNUM;
		break;
	      }
	    }
            else if ("nrt".indexOf(pattern[index]) != -1) {
              switch (pattern[index]) {
                case 'n':
                  asciiEsc = '\n';
                  break;
                case 't':
                  asciiEsc = '\t';
                  break;
                case 'r':
                  asciiEsc = '\r';
                  break;
              }
            }
	    if (lastChar != 0) options.addElement(new RETokenChar(subIndex,lastChar,insens));

	    if (posixID != -1) {
	      options.addElement(new RETokenPOSIX(subIndex,posixID,insens,negate));
	    } else if (asciiEsc != 0) {
	      lastChar = asciiEsc;
	    } else {
	      lastChar = pattern[index];
	    }
	    ++index;
	  } else if ((ch == '[') && (syntax.get(RESyntax.RE_CHAR_CLASSES)) && (index < pLength) && (pattern[index] == ':')) {
	    StringBuffer posixSet = new StringBuffer();
	    index = getPosixSet(pattern,index+1,posixSet);
	    int posixId = RETokenPOSIX.intValue(posixSet.toString());
	    if (posixId != -1)
	      options.addElement(new RETokenPOSIX(subIndex,posixId,insens,false));
	  } else {
	    if (lastChar != 0) options.addElement(new RETokenChar(subIndex,lastChar,insens));
	    lastChar = ch;
	  }
	  if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
	} // while in list
	// Out of list, index is one past ']'

	if (lastChar != 0) options.addElement(new RETokenChar(subIndex,lastChar,insens));

	// Create a new RETokenOneOf
	addToken(currentToken);
	options.trimToSize();
	currentToken = new RETokenOneOf(subIndex,options,negative);
      }

      // SUBEXPRESSIONS
      //  (...) | \(...\) depending on RE_NO_BK_PARENS

      else if ((unit.ch == '(') && (syntax.get(RESyntax.RE_NO_BK_PARENS) ^ unit.bk)) {
	boolean pure = false;
	boolean comment = false;
        boolean lookAhead = false;
        boolean negativelh = false;
	if ((index+1 < pLength) && (pattern[index] == '?')) {
	  switch (pattern[index+1]) {
          case '!':
            if (syntax.get(RESyntax.RE_LOOKAHEAD)) {
              pure = true;
              negativelh = true;
              lookAhead = true;
              index += 2;
            }
            break;
          case '=':
            if (syntax.get(RESyntax.RE_LOOKAHEAD)) {
              pure = true;
              lookAhead = true;
              index += 2;
            }
            break;
	  case ':':
	    if (syntax.get(RESyntax.RE_PURE_GROUPING)) {
	      pure = true;
	      index += 2;
	    }
	    break;
	  case '#':
	    if (syntax.get(RESyntax.RE_COMMENTS)) {
	      comment = true;
	    }
	    break;
          default:
            throw new REException(getLocalizedMessage("repeat.no.token"), REException.REG_BADRPT, index);
	  }
	}

	if (index >= pLength) {
	    throw new REException(getLocalizedMessage("unmatched.paren"), REException.REG_ESUBREG,index);
	}

	// find end of subexpression
	int endIndex = index;
	int nextIndex = index;
	int nested = 0;

	while ( ((nextIndex = getCharUnit(pattern,endIndex,unit)) > 0)
		&& !(nested == 0 && (unit.ch == ')') && (syntax.get(RESyntax.RE_NO_BK_PARENS) ^ unit.bk)) )
	  if ((endIndex = nextIndex) >= pLength)
	    throw new REException(getLocalizedMessage("subexpr.no.end"),REException.REG_ESUBREG,nextIndex);
	  else if (unit.ch == '(' && (syntax.get(RESyntax.RE_NO_BK_PARENS) ^ unit.bk))
	    nested++;
	  else if (unit.ch == ')' && (syntax.get(RESyntax.RE_NO_BK_PARENS) ^ unit.bk))
	    nested--;

	// endIndex is now position at a ')','\)'
	// nextIndex is end of string or position after ')' or '\)'

	if (comment) index = nextIndex;
	else { // not a comment
	  // create RE subexpression as token.
	  addToken(currentToken);
	  if (!pure) {
	    numSubs++;
	  }

	  int useIndex = (pure || lookAhead) ? 0 : nextSub + numSubs;
	  currentToken = new RE(String.valueOf(pattern,index,endIndex-index).toCharArray(),cflags,syntax,useIndex,nextSub + numSubs);
	  numSubs += ((RE) currentToken).getNumSubs();

          if (lookAhead) {
	      currentToken = new RETokenLookAhead(currentToken,negativelh);
	  }

	  index = nextIndex;
	} // not a comment
      } // subexpression

      // UNMATCHED RIGHT PAREN
      // ) or \) throw exception if
      // !syntax.get(RESyntax.RE_UNMATCHED_RIGHT_PAREN_ORD)
      else if (!syntax.get(RESyntax.RE_UNMATCHED_RIGHT_PAREN_ORD) && ((unit.ch == ')') && (syntax.get(RESyntax.RE_NO_BK_PARENS) ^ unit.bk))) {
	throw new REException(getLocalizedMessage("unmatched.paren"),REException.REG_EPAREN,index);
      }

      // START OF LINE OPERATOR
      //  ^

      else if ((unit.ch == '^') && !unit.bk) {
	addToken(currentToken);
	currentToken = null;
	addToken(new RETokenStart(subIndex,((cflags & REG_MULTILINE) > 0) ? syntax.getLineSeparator() : null));
      }

      // END OF LINE OPERATOR
      //  $

      else if ((unit.ch == '$') && !unit.bk) {
	addToken(currentToken);
	currentToken = null;
	addToken(new RETokenEnd(subIndex,((cflags & REG_MULTILINE) > 0) ? syntax.getLineSeparator() : null));
      }

      // MATCH-ANY-CHARACTER OPERATOR (except possibly newline and null)
      //  .

      else if ((unit.ch == '.') && !unit.bk) {
	addToken(currentToken);
	currentToken = new RETokenAny(subIndex,syntax.get(RESyntax.RE_DOT_NEWLINE) || ((cflags & REG_DOT_NEWLINE) > 0),syntax.get(RESyntax.RE_DOT_NOT_NULL));
      }

      // ZERO-OR-MORE REPEAT OPERATOR
      //  *

      else if ((unit.ch == '*') && !unit.bk) {
	if (currentToken == null)
          throw new REException(getLocalizedMessage("repeat.no.token"),REException.REG_BADRPT,index);
	if (currentToken instanceof RETokenRepeated)
          throw new REException(getLocalizedMessage("repeat.chained"),REException.REG_BADRPT,index);
	if (currentToken instanceof RETokenWordBoundary || currentToken instanceof RETokenWordBoundary)
	  throw new REException(getLocalizedMessage("repeat.assertion"),REException.REG_BADRPT,index);
	if (currentToken.getMinimumLength() == 0)
	  throw new REException(getLocalizedMessage("repeat.empty.token"),REException.REG_BADRPT,index);
	currentToken = setRepeated(currentToken,0,Integer.MAX_VALUE,index);
      }

      // ONE-OR-MORE REPEAT OPERATOR
      //  + | \+ depending on RE_BK_PLUS_QM
      //  not available if RE_LIMITED_OPS is set

      else if ((unit.ch == '+') && !syntax.get(RESyntax.RE_LIMITED_OPS) && (!syntax.get(RESyntax.RE_BK_PLUS_QM) ^ unit.bk)) {
	if (currentToken == null)
          throw new REException(getLocalizedMessage("repeat.no.token"),REException.REG_BADRPT,index);
	if (currentToken instanceof RETokenRepeated)
          throw new REException(getLocalizedMessage("repeat.chained"),REException.REG_BADRPT,index);
	if (currentToken instanceof RETokenWordBoundary || currentToken instanceof RETokenWordBoundary)
	  throw new REException(getLocalizedMessage("repeat.assertion"),REException.REG_BADRPT,index);
	if (currentToken.getMinimumLength() == 0)
	  throw new REException(getLocalizedMessage("repeat.empty.token"),REException.REG_BADRPT,index);
	currentToken = setRepeated(currentToken,1,Integer.MAX_VALUE,index);
      }

      // ZERO-OR-ONE REPEAT OPERATOR / STINGY MATCHING OPERATOR
      //  ? | \? depending on RE_BK_PLUS_QM
      //  not available if RE_LIMITED_OPS is set
      //  stingy matching if RE_STINGY_OPS is set and it follows a quantifier

      else if ((unit.ch == '?') && !syntax.get(RESyntax.RE_LIMITED_OPS) && (!syntax.get(RESyntax.RE_BK_PLUS_QM) ^ unit.bk)) {
	if (currentToken == null) throw new REException(getLocalizedMessage("repeat.no.token"),REException.REG_BADRPT,index);

	// Check for stingy matching on RETokenRepeated
	if (currentToken instanceof RETokenRepeated) {
          if (syntax.get(RESyntax.RE_STINGY_OPS) && !((RETokenRepeated)currentToken).isStingy())
            ((RETokenRepeated)currentToken).makeStingy();
          else
            throw new REException(getLocalizedMessage("repeat.chained"),REException.REG_BADRPT,index);
        }
        else if (currentToken instanceof RETokenWordBoundary || currentToken instanceof RETokenWordBoundary)
          throw new REException(getLocalizedMessage("repeat.assertion"),REException.REG_BADRPT,index);
	else
	  currentToken = setRepeated(currentToken,0,1,index);
      }

      // BACKREFERENCE OPERATOR
      //  \1 \2 ... \9
      // not available if RE_NO_BK_REFS is set

      else if (unit.bk && Character.isDigit(unit.ch) && !syntax.get(RESyntax.RE_NO_BK_REFS)) {
	addToken(currentToken);
	currentToken = new RETokenBackRef(subIndex,Character.digit(unit.ch,10),insens);
      }

      // START OF STRING OPERATOR
      //  \A if RE_STRING_ANCHORS is set

      else if (unit.bk && (unit.ch == 'A') && syntax.get(RESyntax.RE_STRING_ANCHORS)) {
	addToken(currentToken);
	currentToken = new RETokenStart(subIndex,null);
      }

      // WORD BREAK OPERATOR
      //  \b if ????

      else if (unit.bk && (unit.ch == 'b') && syntax.get(RESyntax.RE_STRING_ANCHORS)) {
	  addToken(currentToken);
	  currentToken = new RETokenWordBoundary(subIndex, RETokenWordBoundary.BEGIN | RETokenWordBoundary.END, false);
      }

      // WORD BEGIN OPERATOR
      //  \< if ????
      else if (unit.bk && (unit.ch == '<')) {
	  addToken(currentToken);
	  currentToken = new RETokenWordBoundary(subIndex, RETokenWordBoundary.BEGIN, false);
      }

      // WORD END OPERATOR
      //  \> if ????
      else if (unit.bk && (unit.ch == '>')) {
	  addToken(currentToken);
	  currentToken = new RETokenWordBoundary(subIndex, RETokenWordBoundary.END, false);
      }

      // NON-WORD BREAK OPERATOR
      // \B if ????

      else if (unit.bk && (unit.ch == 'B') && syntax.get(RESyntax.RE_STRING_ANCHORS)) {
	  addToken(currentToken);
	  currentToken = new RETokenWordBoundary(subIndex, RETokenWordBoundary.BEGIN | RETokenWordBoundary.END, true);
      }

      // DIGIT OPERATOR
      //  \d if RE_CHAR_CLASS_ESCAPES is set

      else if (unit.bk && (unit.ch == 'd') && syntax.get(RESyntax.RE_CHAR_CLASS_ESCAPES)) {
	addToken(currentToken);
	currentToken = new RETokenPOSIX(subIndex,RETokenPOSIX.DIGIT,insens,false);
      }

      // NON-DIGIT OPERATOR
      //  \D

	else if (unit.bk && (unit.ch == 'D') && syntax.get(RESyntax.RE_CHAR_CLASS_ESCAPES)) {
	  addToken(currentToken);
	  currentToken = new RETokenPOSIX(subIndex,RETokenPOSIX.DIGIT,insens,true);
	}

	// NEWLINE ESCAPE
        //  \n

	else if (unit.bk && (unit.ch == 'n')) {
	  addToken(currentToken);
	  currentToken = new RETokenChar(subIndex,'\n',false);
	}

	// RETURN ESCAPE
        //  \r

	else if (unit.bk && (unit.ch == 'r')) {
	  addToken(currentToken);
	  currentToken = new RETokenChar(subIndex,'\r',false);
	}

	// WHITESPACE OPERATOR
        //  \s if RE_CHAR_CLASS_ESCAPES is set

	else if (unit.bk && (unit.ch == 's') && syntax.get(RESyntax.RE_CHAR_CLASS_ESCAPES)) {
	  addToken(currentToken);
	  currentToken = new RETokenPOSIX(subIndex,RETokenPOSIX.SPACE,insens,false);
	}

	// NON-WHITESPACE OPERATOR
        //  \S

	else if (unit.bk && (unit.ch == 'S') && syntax.get(RESyntax.RE_CHAR_CLASS_ESCAPES)) {
	  addToken(currentToken);
	  currentToken = new RETokenPOSIX(subIndex,RETokenPOSIX.SPACE,insens,true);
	}

	// TAB ESCAPE
        //  \t

	else if (unit.bk && (unit.ch == 't')) {
	  addToken(currentToken);
	  currentToken = new RETokenChar(subIndex,'\t',false);
	}

	// ALPHANUMERIC OPERATOR
        //  \w

	else if (unit.bk && (unit.ch == 'w') && syntax.get(RESyntax.RE_CHAR_CLASS_ESCAPES)) {
	  addToken(currentToken);
	  currentToken = new RETokenPOSIX(subIndex,RETokenPOSIX.ALNUM,insens,false);
	}

	// NON-ALPHANUMERIC OPERATOR
        //  \W

	else if (unit.bk && (unit.ch == 'W') && syntax.get(RESyntax.RE_CHAR_CLASS_ESCAPES)) {
	  addToken(currentToken);
	  currentToken = new RETokenPOSIX(subIndex,RETokenPOSIX.ALNUM,insens,true);
	}

	// END OF STRING OPERATOR
        //  \Z

	else if (unit.bk && (unit.ch == 'Z') && syntax.get(RESyntax.RE_STRING_ANCHORS)) {
	  addToken(currentToken);
	  currentToken = new RETokenEnd(subIndex,null);
	}

	// NON-SPECIAL CHARACTER (or escape to make literal)
        //  c | \* for example

	else {  // not a special character
	  addToken(currentToken);
	  currentToken = new RETokenChar(subIndex,unit.ch,insens);
	}
      } // end while

    // Add final buffered token and an EndSub marker
    addToken(currentToken);

    if (branches != null) {
	branches.addElement(new RE(firstToken,lastToken,numSubs,subIndex,minimumLength));
	branches.trimToSize(); // compact the Vector
	minimumLength = 0;
	firstToken = lastToken = null;
	addToken(new RETokenOneOf(subIndex,branches,false));
    }
    else addToken(new RETokenEndSub(subIndex));

  }

  private static int getCharUnit(char[] input, int index, CharUnit unit) throws REException {
    unit.ch = input[index++];
    if (unit.bk = (unit.ch == '\\'))
      if (index < input.length)
	unit.ch = input[index++];
      else throw new REException(getLocalizedMessage("ends.with.backslash"),REException.REG_ESCAPE,index);
    return index;
  }

  /**
   * Checks if the regular expression matches the input in its entirety.
   *
   * @param input The input text.
   */
  public boolean isMatch(Object input) {
    return isMatch(input,0,0);
  }

  /**
   * Checks if the input string, starting from index, is an exact match of
   * this regular expression.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   */
  public boolean isMatch(Object input,int index) {
    return isMatch(input,index,0);
  }

  /**
   * Checks if the input, starting from index and using the specified
   * execution flags, is an exact match of this regular expression.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   */
  public boolean isMatch(Object input,int index,int eflags) {
    return isMatchImpl(makeCharIndexed(input,index),index,eflags);
  }

  private boolean isMatchImpl(CharIndexed input, int index, int eflags) {
    if (firstToken == null)  // Trivial case
      return (input.charAt(0) == CharIndexed.OUT_OF_BOUNDS);
    REMatch m = new REMatch(numSubs, index, eflags);
    if (firstToken.match(input, m)) {
	while (m != null) {
	    if (input.charAt(m.index) == CharIndexed.OUT_OF_BOUNDS) {
		return true;
	    }
	    m = m.next;
	}
    }
    return false;
  }

  /**
   * Returns the maximum number of subexpressions in this regular expression.
   * If the expression contains branches, the value returned will be the
   * maximum subexpressions in any of the branches.
   */
  public int getNumSubs() {
    return numSubs;
  }

  // Overrides REToken.setUncle
  void setUncle(REToken uncle) {
      if (lastToken != null) {
	  lastToken.setUncle(uncle);
      } else super.setUncle(uncle); // to deal with empty subexpressions
  }

  // Overrides REToken.chain

  boolean chain(REToken next) {
    super.chain(next);
    setUncle(next);
    return true;
  }

  /**
   * Returns the minimum number of characters that could possibly
   * constitute a match of this regular expression.
   */
  public int getMinimumLength() {
      return minimumLength;
  }

  /**
   * Returns an array of all matches found in the input.
   *
   * If the regular expression allows the empty string to match, it will
   * substitute matches at all positions except the end of the input.
   *
   * @param input The input text.
   * @return a non-null (but possibly zero-length) array of matches
   */
  public REMatch[] getAllMatches(Object input) {
    return getAllMatches(input,0,0);
  }

  /**
   * Returns an array of all matches found in the input,
   * beginning at the specified index position.
   *
   * If the regular expression allows the empty string to match, it will
   * substitute matches at all positions except the end of the input.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @return a non-null (but possibly zero-length) array of matches
   */
  public REMatch[] getAllMatches(Object input, int index) {
    return getAllMatches(input,index,0);
  }

  /**
   * Returns an array of all matches found in the input string,
   * beginning at the specified index position and using the specified
   * execution flags.
   *
   * If the regular expression allows the empty string to match, it will
   * substitute matches at all positions except the end of the input.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   * @return a non-null (but possibly zero-length) array of matches
   */
  public REMatch[] getAllMatches(Object input, int index, int eflags) {
    return getAllMatchesImpl(makeCharIndexed(input,index),index,eflags);
  }

  // this has been changed since 1.03 to be non-overlapping matches
  private REMatch[] getAllMatchesImpl(CharIndexed input, int index, int eflags) {
    Vector all = new Vector();
    REMatch m = null;
    while ((m = getMatchImpl(input,index,eflags,null)) != null) {
      all.addElement(m);
      index = m.getEndIndex();
      if (m.end[0] == 0) {   // handle pathological case of zero-length match
	index++;
	input.move(1);
      } else {
	input.move(m.end[0]);
      }
      if (!input.isValid()) break;
    }
    REMatch[] mset = new REMatch[all.size()];
    all.copyInto(mset);
    return mset;
  }

    /* Implements abstract method REToken.match() */
    boolean match(CharIndexed input, REMatch mymatch) {
	if (firstToken == null) return next(input, mymatch);

	// Note the start of this subexpression
	mymatch.start[subIndex] = mymatch.index;

	return firstToken.match(input, mymatch);
    }

  /**
   * Returns the first match found in the input.  If no match is found,
   * null is returned.
   *
   * @param input The input text.
   * @return An REMatch instance referencing the match, or null if none.
   */
  public REMatch getMatch(Object input) {
    return getMatch(input,0,0);
  }

  /**
   * Returns the first match found in the input, beginning
   * the search at the specified index.  If no match is found,
   * returns null.
   *
   * @param input The input text.
   * @param index The offset within the text to begin looking for a match.
   * @return An REMatch instance referencing the match, or null if none.
   */
  public REMatch getMatch(Object input, int index) {
    return getMatch(input,index,0);
  }

  /**
   * Returns the first match found in the input, beginning
   * the search at the specified index, and using the specified
   * execution flags.  If no match is found, returns null.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   * @return An REMatch instance referencing the match, or null if none.
   */
  public REMatch getMatch(Object input, int index, int eflags) {
    return getMatch(input,index,eflags,null);
  }

  /**
   * Returns the first match found in the input, beginning the search
   * at the specified index, and using the specified execution flags.
   * If no match is found, returns null.  If a StringBuffer is
   * provided and is non-null, the contents of the input text from the
   * index to the beginning of the match (or to the end of the input,
   * if there is no match) are appended to the StringBuffer.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   * @param buffer The StringBuffer to save pre-match text in.
   * @return An REMatch instance referencing the match, or null if none.  */
  public REMatch getMatch(Object input, int index, int eflags, StringBuffer buffer) {
    return getMatchImpl(makeCharIndexed(input,index),index,eflags,buffer);
  }

  REMatch getMatchImpl(CharIndexed input, int anchor, int eflags, StringBuffer buffer) {
      // Create a new REMatch to hold results
      REMatch mymatch = new REMatch(numSubs, anchor, eflags);
      do {
	  // Optimization: check if anchor + minimumLength > length
	  if (minimumLength == 0 || input.charAt(minimumLength-1) != CharIndexed.OUT_OF_BOUNDS) {
	      if (match(input, mymatch)) {
		  // Find longest match of them all to observe leftmost longest
		  REMatch longest = mymatch;
		  while ((mymatch = mymatch.next) != null) {
		      if (mymatch.index > longest.index) {
			  longest = mymatch;
		      }
		  }

		  longest.end[0] = longest.index;
		  longest.finish(input);
		  return longest;
	      }
	  }
	  mymatch.clear(++anchor);
	  // Append character to buffer if needed
	  if (buffer != null && input.charAt(0) != CharIndexed.OUT_OF_BOUNDS) {
	      buffer.append(input.charAt(0));
	  }
      } while (input.move(1));

      // Special handling at end of input for e.g. "$"
      if (minimumLength == 0) {
	  if (match(input, mymatch)) {
	      mymatch.finish(input);
	      return mymatch;
	  }
      }

      return null;
  }

  /**
   * Returns an REMatchEnumeration that can be used to iterate over the
   * matches found in the input text.
   *
   * @param input The input text.
   * @return A non-null REMatchEnumeration instance.
   */
  public REMatchEnumeration getMatchEnumeration(Object input) {
    return getMatchEnumeration(input,0,0);
  }

  /**
   * Returns an REMatchEnumeration that can be used to iterate over the
   * matches found in the input text.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @return A non-null REMatchEnumeration instance, with its input cursor
   *  set to the index position specified.
   */
  public REMatchEnumeration getMatchEnumeration(Object input, int index) {
    return getMatchEnumeration(input,index,0);
  }

  /**
   * Returns an REMatchEnumeration that can be used to iterate over the
   * matches found in the input text.
   *
   * @param input The input text.
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   * @return A non-null REMatchEnumeration instance, with its input cursor
   *  set to the index position specified.
   */
  public REMatchEnumeration getMatchEnumeration(Object input, int index, int eflags) {
    return new REMatchEnumeration(this,makeCharIndexed(input,index),index,eflags);
  }

  /**
   * Substitutes the replacement text for the first match found in the input.
   *
   * @param input The input text.
   * @param replace The replacement text, which may contain $x metacharacters (see REMatch.substituteInto).
   * @return A String interpolating the substituted text.
   * @see REMatch#substituteInto
   */
  public String substitute(Object input,String replace) {
    return substitute(input,replace,0,0);
  }

  /**
   * Substitutes the replacement text for the first match found in the input
   * beginning at the specified index position.  Specifying an index
   * effectively causes the regular expression engine to throw away the
   * specified number of characters.
   *
   * @param input The input text.
   * @param replace The replacement text, which may contain $x metacharacters (see REMatch.substituteInto).
   * @param index The offset index at which the search should be begin.
   * @return A String containing the substring of the input, starting
   *   at the index position, and interpolating the substituted text.
   * @see REMatch#substituteInto
   */
  public String substitute(Object input,String replace,int index) {
    return substitute(input,replace,index,0);
  }

  /**
   * Substitutes the replacement text for the first match found in the input
   * string, beginning at the specified index position and using the
   * specified execution flags.
   *
   * @param input The input text.
   * @param replace The replacement text, which may contain $x metacharacters (see REMatch.substituteInto).
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   * @return A String containing the substring of the input, starting
   *   at the index position, and interpolating the substituted text.
   * @see REMatch#substituteInto
   */
  public String substitute(Object input,String replace,int index,int eflags) {
    return substituteImpl(makeCharIndexed(input,index),replace,index,eflags);
  }

  private String substituteImpl(CharIndexed input,String replace,int index,int eflags) {
    StringBuffer buffer = new StringBuffer();
    REMatch m = getMatchImpl(input,index,eflags,buffer);
    if (m==null) return buffer.toString();
    buffer.append( ((eflags & REG_NO_INTERPOLATE) > 0) ?
		   replace : m.substituteInto(replace) );
    if (input.move(m.end[0])) {
      do {
	buffer.append(input.charAt(0));
      } while (input.move(1));
    }
    return buffer.toString();
  }

  /**
   * Substitutes the replacement text for each non-overlapping match found
   * in the input text.
   *
   * @param input The input text.
   * @param replace The replacement text, which may contain $x metacharacters (see REMatch.substituteInto).
   * @return A String interpolating the substituted text.
   * @see REMatch#substituteInto
   */
  public String substituteAll(Object input,String replace) {
    return substituteAll(input,replace,0,0);
  }

  /**
   * Substitutes the replacement text for each non-overlapping match found
   * in the input text, starting at the specified index.
   *
   * If the regular expression allows the empty string to match, it will
   * substitute matches at all positions except the end of the input.
   *
   * @param input The input text.
   * @param replace The replacement text, which may contain $x metacharacters (see REMatch.substituteInto).
   * @param index The offset index at which the search should be begin.
   * @return A String containing the substring of the input, starting
   *   at the index position, and interpolating the substituted text.
   * @see REMatch#substituteInto
   */
  public String substituteAll(Object input,String replace,int index) {
    return substituteAll(input,replace,index,0);
  }

  /**
   * Substitutes the replacement text for each non-overlapping match found
   * in the input text, starting at the specified index and using the
   * specified execution flags.
   *
   * @param input The input text.
   * @param replace The replacement text, which may contain $x metacharacters (see REMatch.substituteInto).
   * @param index The offset index at which the search should be begin.
   * @param eflags The logical OR of any execution flags above.
   * @return A String containing the substring of the input, starting
   *   at the index position, and interpolating the substituted text.
   * @see REMatch#substituteInto
   */
  public String substituteAll(Object input,String replace,int index,int eflags) {
    return substituteAllImpl(makeCharIndexed(input,index),replace,index,eflags);
  }

  private String substituteAllImpl(CharIndexed input,String replace,int index,int eflags) {
    StringBuffer buffer = new StringBuffer();
    REMatch m;
    while ((m = getMatchImpl(input,index,eflags,buffer)) != null) {
	buffer.append( ((eflags & REG_NO_INTERPOLATE) > 0) ?
		       replace : m.substituteInto(replace) );
      index = m.getEndIndex();
      if (m.end[0] == 0) {
	char ch = input.charAt(0);
	if (ch != CharIndexed.OUT_OF_BOUNDS)
	    buffer.append(ch);
	input.move(1);
      } else {
	  input.move(m.end[0]);
      }

      if (!input.isValid()) break;
    }
    return buffer.toString();
  }

  /* Helper function for constructor */
  private void addToken(REToken next) {
    if (next == null) return;
    minimumLength += next.getMinimumLength();
    if (firstToken == null) {
	lastToken = firstToken = next;
    } else {
      // if chain returns false, it "rejected" the token due to
      // an optimization, and next was combined with lastToken
      if (lastToken.chain(next)) {
	  lastToken = next;
      }
    }
  }

  private static REToken setRepeated(REToken current, int min, int max, int index) throws REException {
    if (current == null) throw new REException(getLocalizedMessage("repeat.no.token"),REException.REG_BADRPT,index);
    return new RETokenRepeated(current.subIndex,current,min,max);
  }

  private static int getPosixSet(char[] pattern,int index,StringBuffer buf) {
    // Precondition: pattern[index-1] == ':'
    // we will return pos of closing ']'.
    int i;
    for (i=index; i<(pattern.length-1); i++) {
      if ((pattern[i] == ':') && (pattern[i+1] == ']'))
	return i+2;
      buf.append(pattern[i]);
    }
    return index; // didn't match up
  }

  private int getMinMax(char[] input,int index,IntPair minMax,RESyntax syntax) throws REException {
    // Precondition: input[index-1] == '{', minMax != null

    boolean mustMatch = !syntax.get(RESyntax.RE_NO_BK_BRACES);
    int startIndex = index;
    if (index == input.length) {
      if (mustMatch)
        throw new REException(getLocalizedMessage("unmatched.brace"),REException.REG_EBRACE,index);
      else
        return startIndex;
    }

    int min,max=0;
    CharUnit unit = new CharUnit();
    StringBuffer buf = new StringBuffer();

    // Read string of digits
    do {
      index = getCharUnit(input,index,unit);
      if (Character.isDigit(unit.ch))
        buf.append(unit.ch);
    } while ((index != input.length) && Character.isDigit(unit.ch));

    // Check for {} tomfoolery
    if (buf.length() == 0) {
      if (mustMatch)
        throw new REException(getLocalizedMessage("interval.error"),REException.REG_EBRACE,index);
      else
        return startIndex;
    }

    min = Integer.parseInt(buf.toString());

    if ((unit.ch == '}') && (syntax.get(RESyntax.RE_NO_BK_BRACES) ^ unit.bk))
      max = min;
    else if (index == input.length)
      if (mustMatch)
        throw new REException(getLocalizedMessage("interval.no.end"),REException.REG_EBRACE,index);
      else
        return startIndex;
    else if ((unit.ch == ',') && !unit.bk) {
      buf = new StringBuffer();
      // Read string of digits
      while (((index = getCharUnit(input,index,unit)) != input.length) && Character.isDigit(unit.ch))
	buf.append(unit.ch);

      if (!((unit.ch == '}') && (syntax.get(RESyntax.RE_NO_BK_BRACES) ^ unit.bk)))
        if (mustMatch)
          throw new REException(getLocalizedMessage("interval.error"),REException.REG_EBRACE,index);
        else
          return startIndex;

      // This is the case of {x,}
      if (buf.length() == 0) max = Integer.MAX_VALUE;
      else max = Integer.parseInt(buf.toString());
    } else
      if (mustMatch)
        throw new REException(getLocalizedMessage("interval.error"),REException.REG_EBRACE,index);
      else
        return startIndex;

    // We know min and max now, and they are valid.

    minMax.first = min;
    minMax.second = max;

    // return the index following the '}'
    return index;
  }

   /**
    * Return a human readable form of the compiled regular expression,
    * useful for debugging.
    */
   public String toString() {
     StringBuffer sb = new StringBuffer();
     dump(sb);
     return sb.toString();
   }

  void dump(StringBuffer os) {
    os.append('(');
    if (subIndex == 0)
      os.append("?:");
    if (firstToken != null)
      firstToken.dumpAll(os);
    os.append(')');
  }

  // Cast input appropriately or throw exception
  private static CharIndexed makeCharIndexed(Object input, int index) {
      // We could let a String fall through to final input, but since
      // it's the most likely input type, we check it first.
    if (input instanceof String)
      return new CharIndexedString((String) input,index);
    else if (input instanceof char[])
      return new CharIndexedCharArray((char[]) input,index);
    else if (input instanceof StringBuffer)
      return new CharIndexedStringBuffer((StringBuffer) input,index);
    else if (input instanceof InputStream)
      return new CharIndexedInputStream((InputStream) input,index);
    else if (input instanceof Reader)
	return new CharIndexedReader((Reader) input, index);
    else if (input instanceof CharIndexed)
	return (CharIndexed) input; // do we lose index info?
    else
	return new CharIndexedString(input.toString(), index);

FUNC_DECL RETURN PARAM PARAM CALL LITERAL_ANCHOR

FUNC_DECL RETURN IF PARAM PARAM CALL ASSIGN RETURN BINARY_OP CALL LITERAL_ANCHOR

FUNC_DECL RETURN PARAM PARAM PARAM CALL LITERAL_ANCHOR

FUNC_DECL RETURN PARAM PARAM PARAM PARAM CALL CALL

FUNC_DECL IF IF PARAM BINARY_OP ASSIGN RETURN BINARY_OP IF LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL ASSIGN ASSIGN ASSIGN

FUNC_DECL RETURN VAR_DECL CALL CALL CALL

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

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


org.apache.xalan.xsltc.compiler.Output

final class Output extends TopLevelElement {

    private String  _version;
    private String  _method;
    private String  _encoding;
    private boolean _omitHeader = false;
    private String  _standalone;
    private String  _doctypePublic;
    private String  _doctypeSystem;
    private String  _cdata;
    private boolean _indent = false;
    private String  _mediaType;
    private String  _cdataToMerge;

    private boolean _disabled = false;

    private final static String STRING_SIG = "Ljava/lang/String;";
    private final static String XML_VERSION = "1.0";
    private final static String HTML_VERSION = "4.0";

    /**
     * Displays the contents of this element (for debugging)
     */
    public void display(int indent) {
	indent(indent);
	Util.println("Output " + _method);
    }

    /**
     * Disables this <xsl:output> element in case where there are some other
     * <xsl:output> element (from a different imported/included stylesheet)
     * with higher precedence.
     */
    public void disable() {
	_disabled = true;
    }

    public boolean enabled() {
	return !_disabled;
    }

    public String getCdata() {
	return _cdata;
    }

    public void mergeCdata(String cdata) {
	_cdataToMerge = cdata;
    }

    /**
     * Scans the attribute list for the xsl:output instruction
     */
    public void parseContents(Parser parser) {
	final Properties outputProperties = new Properties();

	parser.setOutput(this);

	if (_disabled) return;

	String attrib = null;

	_version = getAttribute("version");
	if (_version == null || _version.equals(Constants.EMPTYSTRING)) {
	    _version = null;
	}
	else {
	    outputProperties.setProperty(OutputKeys.VERSION, _version);
	}

	_method = getAttribute("method");
	if (_method.equals(Constants.EMPTYSTRING)) {
	    _method = null;
	}
	if (_method != null) {
	    _method = _method.toLowerCase();
	    outputProperties.setProperty(OutputKeys.METHOD, _method);
	}

	_encoding = getAttribute("encoding");
	if (_encoding.equals(Constants.EMPTYSTRING)) {
	    _encoding = null;
	}
	else {
	    try {
        String canonicalEncoding;
        canonicalEncoding = Encodings.convertMime2JavaEncoding(_encoding);
		OutputStreamWriter writer =
		    new OutputStreamWriter(System.out, canonicalEncoding);
	    }
	    catch (java.io.UnsupportedEncodingException e) {
		ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_ENCODING,
					    _encoding, this);
		parser.reportError(Constants.WARNING, msg);
	    }
	    outputProperties.setProperty(OutputKeys.ENCODING, _encoding);
	}

	attrib = getAttribute("omit-xml-declaration");
	if (attrib != null && !attrib.equals(Constants.EMPTYSTRING)) {
	    if (attrib.equals("yes")) {
		_omitHeader = true;
	    }
	    outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, attrib);
	}

	_standalone = getAttribute("standalone");
	if (_standalone.equals(Constants.EMPTYSTRING)) {
	    _standalone = null;
	}
	else {
	    outputProperties.setProperty(OutputKeys.STANDALONE, _standalone);
	}

	_doctypeSystem = getAttribute("doctype-system");
	if (_doctypeSystem.equals(Constants.EMPTYSTRING)) {
	    _doctypeSystem = null;
	}
	else {
	    outputProperties.setProperty(OutputKeys.DOCTYPE_SYSTEM, _doctypeSystem);
	}

	_doctypePublic = getAttribute("doctype-public");
	if (_doctypePublic.equals(Constants.EMPTYSTRING)) {
	    _doctypePublic = null;
	}
	else {
	    outputProperties.setProperty(OutputKeys.DOCTYPE_PUBLIC, _doctypePublic);
	}

	_cdata = getAttribute("cdata-section-elements");
	if (_cdata != null && _cdata.equals(Constants.EMPTYSTRING)) {
	    _cdata = null;
	}
	else {
	    StringBuffer expandedNames = new StringBuffer();
	    StringTokenizer tokens = new StringTokenizer(_cdata);

	    while (tokens.hasMoreTokens()) {
		expandedNames.append(
		   parser.getQName(tokens.nextToken()).toString()).append(' ');
	    }
	    _cdata = expandedNames.toString();
	    if (_cdataToMerge != null) {
		_cdata = _cdata + _cdataToMerge;
	    }
	    outputProperties.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS,
		_cdata);
	}

	attrib = getAttribute("indent");
	if (attrib != null && !attrib.equals(EMPTYSTRING)) {
	    if (attrib.equals("yes")) {
		_indent = true;
	    }
	    outputProperties.setProperty(OutputKeys.INDENT, attrib);
	}
	else if (_method != null && _method.equals("html")) {
	    _indent = true;
	}

	_mediaType = getAttribute("media-type");
	if (_mediaType.equals(Constants.EMPTYSTRING)) {
	    _mediaType = null;
	}
	else {
	    outputProperties.setProperty(OutputKeys.MEDIA_TYPE, _mediaType);
	}

	if (_method != null) {
	    if (_method.equals("html")) {
		if (_version == null) {
		    _version = HTML_VERSION;
		}
		if (_mediaType == null) {
		    _mediaType = "text/html";
		}
	    }
	    else if (_method.equals("text")) {
		if (_mediaType == null) {
		    _mediaType = "text/plain";
		}
	    }
	}

	parser.getCurrentStylesheet().setOutputProperties(outputProperties);
    }

    /**
     * Compile code that passes the information in this <xsl:output> element
     * to the appropriate fields in the translet
     */
    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {

	if (_disabled) return;

	ConstantPoolGen cpg = classGen.getConstantPool();
	InstructionList il = methodGen.getInstructionList();

	int field = 0;
        il.append(classGen.loadTranslet());

	if ((_version != null) && (!_version.equals(XML_VERSION))) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_version", STRING_SIG);
	    il.append(DUP);
	    il.append(new PUSH(cpg, _version));
	    il.append(new PUTFIELD(field));
	}

	if (_method != null) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_method", STRING_SIG);
	    il.append(DUP);
	    il.append(new PUSH(cpg, _method));
	    il.append(new PUTFIELD(field));
	}

	if (_encoding != null) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_encoding", STRING_SIG);
	    il.append(DUP);
	    il.append(new PUSH(cpg, _encoding));
	    il.append(new PUTFIELD(field));
	}

	if (_omitHeader) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_omitHeader", "Z");
	    il.append(DUP);
	    il.append(new PUSH(cpg, _omitHeader));
	    il.append(new PUTFIELD(field));
	}

	if (_standalone != null) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_standalone", STRING_SIG);
	    il.append(DUP);
	    il.append(new PUSH(cpg, _standalone));
	    il.append(new PUTFIELD(field));
	}

	field = cpg.addFieldref(TRANSLET_CLASS,"_doctypeSystem",STRING_SIG);
	il.append(DUP);
	il.append(new PUSH(cpg, _doctypeSystem));
	il.append(new PUTFIELD(field));
	field = cpg.addFieldref(TRANSLET_CLASS,"_doctypePublic",STRING_SIG);
	il.append(DUP);
	il.append(new PUSH(cpg, _doctypePublic));
	il.append(new PUTFIELD(field));

	if (_mediaType != null) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_mediaType", STRING_SIG);
	    il.append(DUP);
	    il.append(new PUSH(cpg, _mediaType));
	    il.append(new PUTFIELD(field));
	}

	if (_indent) {
	    field = cpg.addFieldref(TRANSLET_CLASS, "_indent", "Z");
	    il.append(DUP);
	    il.append(new PUSH(cpg, _indent));
	    il.append(new PUTFIELD(field));
	}

	if (_cdata != null) {
	    int index = cpg.addMethodref(TRANSLET_CLASS,
					 "addCdataElement",
					 "(Ljava/lang/String;)V");

	    StringTokenizer tokens = new StringTokenizer(_cdata);
	    while (tokens.hasMoreTokens()) {
		il.append(DUP);
		il.append(new PUSH(cpg, tokens.nextToken()));
		il.append(new INVOKEVIRTUAL(index));

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


org.apache.tools.ant.taskdefs.Rename

public class Rename extends Task {

    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

    private File src;
    private File dest;
    private boolean replace = true;

    /**
     * Sets the file to be renamed.
     * @param src the file to rename
     */
    public void setSrc(File src) {
        this.src = src;
    }

    /**
     * Sets the new name of the file.
     * @param dest the new name of the file.
     */
    public void setDest(File dest) {
        this.dest = dest;
    }

    /**
     * Sets whether an existing file should be replaced.
     * @param replace on, if an existing file should be replaced.
     */
    public void setReplace(String replace) {
        this.replace = Project.toBoolean(replace);
    }

    /**
     * Renames the file src to dest
     * @exception org.apache.tools.ant.BuildException The exception is
     * thrown, if the rename operation fails.
     */
    public void execute() throws BuildException {
        log("DEPRECATED - The rename task is deprecated.  Use move instead.");

        if (dest == null) {
            throw new BuildException("dest attribute is required", getLocation());
        }

        if (src == null) {
            throw new BuildException("src attribute is required", getLocation());
        }

        if (!replace && dest.exists()) {
            throw new BuildException(dest + " already exists.");
        }

        try {
            FILE_UTILS.rename(src, dest);
        } catch (IOException e) {
            throw new BuildException("Unable to rename " + src + " to "
                + dest, e, getLocation());


org.gjt.sp.jedit.gui.ErrorListDialog

public class ErrorListDialog extends EnhancedDialog
{
	//{{{ ErrorEntry class
	public static class ErrorEntry
	{
		String path;
		String[] messages;

		public ErrorEntry(String path, String messageProp, Object[] args)
		{
			this.path = path;

			String message = jEdit.getProperty(messageProp,args);
			if(message == null)
				message = "Undefined property: " + messageProp;

			Log.log(Log.ERROR,this,path + ":");
			Log.log(Log.ERROR,this,message);

			Vector tokenizedMessage = new Vector();
			int lastIndex = -1;
			for(int i = 0; i < message.length(); i++)
			{
				if(message.charAt(i) == '\n')
				{
					tokenizedMessage.addElement(message.substring(
						lastIndex + 1,i));
					lastIndex = i;
				}
			}

			if(lastIndex != message.length())
			{
				tokenizedMessage.addElement(message.substring(
					lastIndex + 1));
			}

			messages = new String[tokenizedMessage.size()];
			tokenizedMessage.copyInto(messages);
		}
	} //}}}

	//{{{ ErrorListDialog constructor
	public ErrorListDialog(Frame frame, String title, String caption,
		Vector messages, boolean showPluginMgrButton)
	{
		super(frame,title,true);

		JPanel content = new JPanel(new BorderLayout(12,12));
		content.setBorder(new EmptyBorder(12,12,12,12));
		setContentPane(content);

		Box iconBox = new Box(BoxLayout.Y_AXIS);
		iconBox.add(new JLabel(UIManager.getIcon("OptionPane.errorIcon")));
		iconBox.add(Box.createGlue());
		content.add(BorderLayout.WEST,iconBox);

		JPanel centerPanel = new JPanel(new BorderLayout());

		JLabel label = new JLabel(caption);
		label.setBorder(new EmptyBorder(0,0,6,0));
		centerPanel.add(BorderLayout.NORTH,label);

		JList errors = new JList(messages);
		errors.setCellRenderer(new ErrorListCellRenderer());
		errors.setVisibleRowCount(Math.min(messages.size(),4));

		// need this bullshit scroll bar policy for the preferred size
		// hack to work
		JScrollPane scrollPane = new JScrollPane(errors,
			JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
			JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		Dimension size = scrollPane.getPreferredSize();
		size.width = Math.min(size.width,400);
		scrollPane.setPreferredSize(size);

		centerPanel.add(BorderLayout.CENTER,scrollPane);

		content.add(BorderLayout.CENTER,centerPanel);

		Box buttons = new Box(BoxLayout.X_AXIS);
		buttons.add(Box.createGlue());

		ok = new JButton(jEdit.getProperty("common.ok"));
		ok.addActionListener(new ActionHandler());

		if(showPluginMgrButton)
		{
			pluginMgr = new JButton(jEdit.getProperty("error-list.plugin-manager"));
			pluginMgr.addActionListener(new ActionHandler());
			buttons.add(pluginMgr);
			buttons.add(Box.createHorizontalStrut(6));
		}

		buttons.add(ok);

		buttons.add(Box.createGlue());
		content.add(BorderLayout.SOUTH,buttons);

		getRootPane().setDefaultButton(ok);

		pack();
		setLocationRelativeTo(frame);
		show();
	} //}}}

	//{{{ ok() method
	public void ok()
	{
		dispose();
	} //}}}

	//{{{ cancel() method
	public void cancel()
	{
		dispose();
	} //}}}

	//{{{ Private members
	private JButton ok, pluginMgr;
	//}}}

	//{{{ ActionHandler class
	class ActionHandler implements ActionListener
	{
		//{{{ actionPerformed() method
		public void actionPerformed(ActionEvent evt)
		{
			if(evt.getSource() == ok)
				dispose();
			else if(evt.getSource() == pluginMgr)
			{
				new org.gjt.sp.jedit.pluginmgr.PluginManager(
					JOptionPane.getFrameForComponent(
					ErrorListDialog.this));

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


public class POIFSWriterEvent
{
    private DocumentOutputStream stream;
    private POIFSDocumentPath    path;
    private String               documentName;
    private int                  limit;

    /**
     * package scoped constructor
     *
     * @param stream the DocumentOutputStream, freshly opened
     * @param path the path of the document
     * @param documentName the name of the document
     * @param limit the limit, in bytes, that can be written to the
     *              stream
     */

    POIFSWriterEvent(final DocumentOutputStream stream,
                     final POIFSDocumentPath path, final String documentName,
                     final int limit)
    {
        this.stream       = stream;
        this.path         = path;
        this.documentName = documentName;
        this.limit        = limit;
    }

    /**
     * @return the DocumentOutputStream, freshly opened
     */

    public DocumentOutputStream getStream()
    {
        return stream;
    }

    /**
     * @return the document's path
     */

    public POIFSDocumentPath getPath()
    {
        return path;
    }

    /**
     * @return the document's name
     */

    public String getName()
    {
        return documentName;
    }

    /**
     * @return the limit on writing, in bytes
     */

    public int getLimit()
    {
        return limit;

    public int getLimit()
    {
        return limit;

FUNC_DECL PARAM PARAM PARAM PARAM ASSIGN ASSIGN ASSIGN ASSIGN


class SecuritySupport12 extends SecuritySupport {

    ClassLoader getContextClassLoader() {
        return (ClassLoader)
                AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                ClassLoader cl = null;
                try {
                    cl = Thread.currentThread().getContextClassLoader();
                } catch (SecurityException ex) { }
                return cl;
            }
        });
    }

    ClassLoader getSystemClassLoader() {
        return (ClassLoader)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    ClassLoader cl = null;
                    try {
                        cl = ClassLoader.getSystemClassLoader();
                    } catch (SecurityException ex) {}
                    return cl;
                }
            });
    }

    ClassLoader getParentClassLoader(final ClassLoader cl) {
        return (ClassLoader)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    ClassLoader parent = null;
                    try {
                        parent = cl.getParent();
                    } catch (SecurityException ex) {}

                    return (parent == cl) ? null : parent;
                }
            });
    }

    String getSystemProperty(final String propName) {
        return (String)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    return System.getProperty(propName);
                }
            });
    }

    FileInputStream getFileInputStream(final File file)
        throws FileNotFoundException
    {
        try {
            return (FileInputStream)
                AccessController.doPrivileged(new PrivilegedExceptionAction() {
                    public Object run() throws FileNotFoundException {
                        return new FileInputStream(file);
                    }
                });
        } catch (PrivilegedActionException e) {
            throw (FileNotFoundException)e.getException();
        }
    }

    InputStream getResourceAsStream(final ClassLoader cl,
                                           final String name)
    {
        return (InputStream)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    InputStream ris;
                    if (cl == null) {
                        ris = ClassLoader.getSystemResourceAsStream(name);
                    } else {
                        ris = cl.getResourceAsStream(name);
                    }
                    return ris;
                }
            });
    }

    boolean getFileExists(final File f) {
    return ((Boolean)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    return new Boolean(f.exists());
                }
            })).booleanValue();
    }

    long getLastModified(final File f) {
    return ((Long)
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    return new Long(f.lastModified());

FUNC_DECL RETURN CALL CALL FUNC_DECL RETURN TRY VAR_DECL CATCH ASSIGN LITERAL_ANCHOR CALL CALL

FUNC_DECL TRY PARAM CATCH RETURN THROW_RAISE CALL CALL CALL FUNC_DECL RETURN CALL

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

FUNC_DECL RETURN PARAM CALL CALL FUNC_DECL RETURN CALL CALL


public class PrefixResolverDefault implements PrefixResolver
{

  /**
   * The context to resolve the prefix from, if the context
   * is not given.
   */
  Node m_context;

  /**
   * Construct a PrefixResolverDefault object.
   * @param xpathExpressionContext The context from
   * which XPath expression prefixes will be resolved.
   * Warning: This will not work correctly if xpathExpressionContext
   * is an attribute node.
   */
  public PrefixResolverDefault(Node xpathExpressionContext)
  {
    m_context = xpathExpressionContext;
  }

  /**
   * Given a namespace, get the corrisponding prefix.  This assumes that
   * the PrevixResolver hold's it's own namespace context, or is a namespace
   * context itself.
   * @param prefix Prefix to resolve.
   * @return Namespace that prefix resolves to, or null if prefix
   * is not bound.
   */
  public String getNamespaceForPrefix(String prefix)
  {
    return getNamespaceForPrefix(prefix, m_context);
  }

  /**
   * Given a namespace, get the corrisponding prefix.
   * Warning: This will not work correctly if namespaceContext
   * is an attribute node.
   * @param prefix Prefix to resolve.
   * @param namespaceContext Node from which to start searching for a
   * xmlns attribute that binds a prefix to a namespace.
   * @return Namespace that prefix resolves to, or null if prefix
   * is not bound.
   */
  public String getNamespaceForPrefix(String prefix,
                                      org.w3c.dom.Node namespaceContext)
  {

    Node parent = namespaceContext;
    String namespace = null;

    if (prefix.equals("xml"))
    {
      namespace = Constants.S_XMLNAMESPACEURI;
    }
    else
    {
      int type;

      while ((null != parent) && (null == namespace)
             && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
                 || (type == Node.ENTITY_REFERENCE_NODE)))
      {
        if (type == Node.ELEMENT_NODE)
        {
                if (parent.getNodeName().indexOf(prefix+":") == 0)
                        return parent.getNamespaceURI();
          NamedNodeMap nnm = parent.getAttributes();

          for (int i = 0; i < nnm.getLength(); i++)
          {
            Node attr = nnm.item(i);
            String aname = attr.getNodeName();
            boolean isPrefix = aname.startsWith("xmlns:");

            if (isPrefix || aname.equals("xmlns"))
            {
              int index = aname.indexOf(':');
              String p = isPrefix ? aname.substring(index + 1) : "";

              if (p.equals(prefix))
              {
                namespace = attr.getNodeValue();

                break;
              }
            }
          }
        }

        parent = parent.getParentNode();
      }
    }

    return namespace;
  }

  /**
   * Return the base identifier.
   *
   * @return null
   */
  public String getBaseIdentifier()
  {
    return null;
  }
	/**
	 * @see PrefixResolver#handlesNullPrefixes()
	 */
	public boolean handlesNullPrefixes() {
		return false;


org.gjt.sp.jedit.gui.HistoryModel

public class HistoryModel extends DefaultListModel
	implements MutableListModel
{
	//{{{ HistoryModel constructor
	/**
	 * Creates a new history list. Calling this is normally not
	 * necessary.
	 */
	public HistoryModel(String name)
	{
		this.name = name;
	} //}}}

	//{{{ addItem() method
	/**
	 * Adds an item to the end of this history list, trimming the list
	 * to the maximum number of items if necessary.
	 * @param text The item
	 */
	public void addItem(String text)
	{
		if(text == null || text.length() == 0)
			return;

		int index = indexOf(text);
		if(index != -1)
			removeElementAt(index);

		insertElementAt(text,0);

		while(getSize() > max)
			removeElementAt(getSize() - 1);
	} //}}}

	//{{{ insertElementAt() method
	public void insertElementAt(Object obj, int index)
	{
		modified = true;
		super.insertElementAt(obj,index);
	} //}}}

	//{{{ getItem() method
	/**
	 * Returns an item from the history list.
	 * @param index The index
	 */
	public String getItem(int index)
	{
		return (String)elementAt(index);
	} //}}}

	//{{{ removeElement() method
	public boolean removeElement(Object obj)
	{
		modified = true;
		return super.removeElement(obj);
	} //}}}

	//{{{ clear() method
	/**
	 * @deprecated Call removeAllElements() instead.
	 */
	public void clear()
	{
		removeAllElements();
	} //}}}

	//{{{ removeAllElements() method
	public void removeAllElements()
	{
		modified = true;
		super.removeAllElements();
	} //}}}

	//{{{ getName() method
	/**
	 * Returns the name of this history list. This can be passed
	 * to the HistoryTextField constructor.
	 */
	public String getName()
	{
		return name;
	} //}}}

	//{{{ getModel() method
	/**
	 * Returns a named model. If the specified model does not
	 * already exist, it will be created.
	 * @param name The model name
	 */
	public static HistoryModel getModel(String name)
	{
		if(models == null)
			models = Collections.synchronizedMap(new HashMap<String, HistoryModel>());

		HistoryModel model = models.get(name);
		if(model == null)
		{
			model = new HistoryModel(name);
			models.put(name,model);
		}

		return model;
	} //}}}

	//{{{ loadHistory() method
	public static void loadHistory()
	{
		if (saver != null)
			models = saver.load(models);
	} //}}}

	//{{{ saveHistory() method
	public static void saveHistory()
	{
		if (saver != null && modified && saver.save(models))
			modified = false;
	} //}}}

	//{{{ setMax() method
	public static void setMax(int max)
	{
		HistoryModel.max = max;
	} //}}}

	//{{{ setSaver() method
	public static void setSaver(HistoryModelSaver saver)
	{
		HistoryModel.saver = saver;
	} //}}}

	//{{{ Private members
	private static int max;

	private String name;
	private static Map<String, HistoryModel> models;

	private static boolean modified;
	private static HistoryModelSaver saver;

	public String getName()
	{
		return name;


public class JhcProducer extends DefaultProducer<JhcExchange> implements AsyncProcessor {
    public static final String HTTP_RESPONSE_CODE = "http.responseCode";
    public static final Set<String> HEADERS_TO_SKIP = new HashSet<String>(Arrays.asList(
            "content-length", "content-type", HTTP_RESPONSE_CODE.toLowerCase()));

    private static final transient Log LOG = LogFactory.getLog(JhcProducer.class);

    private int nbThreads = 2;
    private ConnectingIOReactor ioReactor;
    private ThreadFactory threadFactory;
    private Thread runner;

    public JhcProducer(JhcEndpoint endpoint) {
        super(endpoint);
    }

    @Override
    public JhcEndpoint getEndpoint() {
        return (JhcEndpoint) super.getEndpoint();
    }

    @Override
    protected void doStart() throws Exception {
        super.doStart();
        HttpParams params = getEndpoint().getParams();
        ioReactor = new DefaultConnectingIOReactor(nbThreads, threadFactory, params);
        BasicHttpProcessor httpproc = new BasicHttpProcessor();
        httpproc.addInterceptor(new RequestContent());
        httpproc.addInterceptor(new RequestTargetHost());
        httpproc.addInterceptor(new RequestConnControl());
        httpproc.addInterceptor(new RequestUserAgent());
        httpproc.addInterceptor(new RequestExpectContinue());
        BufferingHttpClientHandler handler = new BufferingHttpClientHandler(
                httpproc,
                new MyHttpRequestExecutionHandler(),
                new DefaultConnectionReuseStrategy(),
                params);
        handler.setEventListener(new EventLogger());
        final IOEventDispatch ioEventDispatch = new DefaultClientIOEventDispatch(handler, params);
        runner = new Thread(new Runnable() {
            public void run() {
                try {
                    ioReactor.execute(ioEventDispatch);
                } catch (InterruptedIOException ex) {
                    LOG.info("Interrupted");
                } catch (IOException e) {
                    LOG.warn("I/O error: " + e.getMessage());
                }
                LOG.debug("Shutdown");
            }

        });
        runner.start();
    }

    @Override
    protected void doStop() throws Exception {
        ioReactor.shutdown();
        runner.join();
        super.doStop();
    }

    public void process(Exchange exchange) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("process: " + exchange);
        }
        AsyncProcessorHelper.process(this, exchange);
    }

    public boolean process(Exchange exchange, AsyncCallback callback) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("processAsync: " + exchange);
        }
        SocketAddress addr = new InetSocketAddress(getEndpoint().getHost(), getEndpoint().getPort());
        exchange.setProperty(AsyncCallback.class.getName(), callback);
        SessionRequest req = ioReactor.connect(addr, null, exchange, new MySessionRequestCallback());
        return false;
    }

    protected HttpRequest createRequest(Exchange exchange) {
        String uri = getEndpoint().getEndpointUri();
        HttpEntity entity = createEntity(exchange);
        HttpRequest req;
        if (entity == null) {
            req = new BasicHttpRequest("GET", getEndpoint().getPath());
        } else {
            req = new BasicHttpEntityEnclosingRequest("POST", getEndpoint().getPath());
            ((BasicHttpEntityEnclosingRequest)req).setEntity(entity);
        }

        for (String headerName : exchange.getIn().getHeaders().keySet()) {
            String headerValue = exchange.getIn().getHeader(headerName, String.class);
            if (shouldHeaderBePropagated(headerName, headerValue)) {
                req.addHeader(headerName, headerValue);
            }
        }

        return req;
    }

    protected HttpEntity createEntity(Exchange exchange) {
        Message in = exchange.getIn();
        HttpEntity entity = in.getBody(HttpEntity.class);
        if (entity == null) {
            byte[] data = in.getBody(byte[].class);
            if (data == null) {
                return null;
            }
            entity = new ByteArrayEntity(data);
            String contentType = in.getHeader("Content-Type", String.class);
            if (contentType != null) {
                ((ByteArrayEntity) entity).setContentType(contentType);
            }
            String contentEncoding = in.getHeader("Content-Encoding", String.class);
            if (contentEncoding != null) {
                ((ByteArrayEntity) entity).setContentEncoding(contentEncoding);
            }
        }
        return entity;
    }

    protected boolean shouldHeaderBePropagated(String headerName, String headerValue) {
        if (headerValue == null) {
            return false;
        }
        if (headerName.startsWith("org.apache.camel")) {
            return false;
        }
        if (HEADERS_TO_SKIP.contains(headerName.toLowerCase())) {
            return false;
        }
        return true;
    }

    static class MySessionRequestCallback implements SessionRequestCallback {

        public void completed(SessionRequest sessionRequest) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Completed");
            }
        }

        public void failed(SessionRequest sessionRequest) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Failed");
            }
        }

        public void timeout(SessionRequest sessionRequest) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Timeout");
            }
        }

        public void cancelled(SessionRequest sessionRequest) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Cancelled");
            }
        }
    }

    class MyHttpRequestExecutionHandler implements HttpRequestExecutionHandler {

        private static final String REQUEST_SENT       = "request-sent";
        private static final String RESPONSE_RECEIVED  = "response-received";

        public void initalizeContext(HttpContext httpContext, Object o) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Initialize context");
            }
            httpContext.setAttribute(Exchange.class.getName(), (Exchange) o);
        }

        public HttpRequest submitRequest(HttpContext httpContext) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Submit request: " + httpContext);
            }
            Object flag = httpContext.getAttribute(REQUEST_SENT);
            if (flag == null) {
                httpContext.setAttribute(REQUEST_SENT, Boolean.TRUE);
                Exchange e = (Exchange) httpContext.getAttribute(Exchange.class.getName());
                return createRequest(e);
            } else {
                return null;
            }
        }

        public void handleResponse(HttpResponse httpResponse, HttpContext httpContext) throws IOException {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Handle response");
            }
            httpContext.setAttribute(RESPONSE_RECEIVED, Boolean.TRUE);
            Exchange e = (Exchange) httpContext.getAttribute(Exchange.class.getName());
            e.getOut().setBody(httpResponse.getEntity());
            for (Iterator it = httpResponse.headerIterator(); it.hasNext();) {
                Header h = (Header) it.next();
                e.getOut().setHeader(h.getName(), h.getValue());
            }
            e.getOut().setHeader(HTTP_RESPONSE_CODE, httpResponse.getStatusLine().getStatusCode());
            AsyncCallback callback = (AsyncCallback) e.removeProperty(AsyncCallback.class.getName());
            callback.done(false);
        }

        public void finalizeContext(HttpContext httpContext) {
        }
    }

    static class EventLogger implements EventListener {

        public void connectionOpen(final NHttpConnection conn) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Connection open: " + conn);
            }
        }

        public void connectionTimeout(final NHttpConnection conn) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Connection timed out: " + conn);
            }
        }

        public void connectionClosed(final NHttpConnection conn) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Connection closed: " + conn);
            }
        }

        public void fatalIOException(final IOException ex, final NHttpConnection conn) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("I/O error: " + ex.getMessage());
            }
        }

        public void fatalProtocolException(final HttpException ex, final NHttpConnection conn) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("HTTP error: " + ex.getMessage());

FUNC_DECL VAR_DECL VAR_DECL VAR_DECL VAR_DECL CALL ASSIGN CALL CALL CALL CALL CALL CALL ASSIGN CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL FUNC_DECL TRY CALL CATCH CATCH LITERAL_ANCHOR CALL CALL CALL BINARY_OP LITERAL_ANCHOR CALL LITERAL_ANCHOR

FUNC_DECL RETURN VAR_DECL VAR_DECL IF PARAM PARAM LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR CALL CALL CALL CALL CALL BINARY_OP LITERAL_ANCHOR

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


public class FileAppender extends WriterAppender {

  /** Controls file truncatation. The default value for this variable
   * is true, meaning that by default a
   * FileAppender will append to an existing file and not
   * truncate it.
   *
   *
This option is meaningful only if the FileAppender opens the
   * file.
   */
  protected boolean fileAppend = true;

  /**
     The name of the log file. */
  protected String fileName = null;

  /**
     Do we do bufferedIO? */
  protected boolean bufferedIO = false;

  /**
   * Determines the size of IO buffer be. Default is 8K.
   */
  protected int bufferSize = 8*1024;

  /**
     The default constructor does not do anything.
  */
  public
  FileAppender() {
  }

  /**
    Instantiate a FileAppender and open the file
    designated by filename. The opened filename will
    become the output destination for this appender.

If the append parameter is true, the file will be
    appended to. Otherwise, the file designated by
    filename will be truncated before being opened.

If the bufferedIO parameter is true,
    then buffered IO will be used to write to the output file.

  */
  public
  FileAppender(Layout layout, String filename, boolean append, boolean bufferedIO,
	       int bufferSize) throws IOException {
    this.layout = layout;
    this.setFile(filename, append, bufferedIO, bufferSize);
  }

  /**
    Instantiate a FileAppender and open the file designated by
    filename. The opened filename will become the output
    destination for this appender.

If the append parameter is true, the file will be
    appended to. Otherwise, the file designated by
    filename will be truncated before being opened.
  */
  public
  FileAppender(Layout layout, String filename, boolean append)
                                                             throws IOException {
    this.layout = layout;
    this.setFile(filename, append, false, bufferSize);
  }

  /**
     Instantiate a FileAppender and open the file designated by
    filename. The opened filename will become the output
    destination for this appender.

The file will be appended to.  */
  public
  FileAppender(Layout layout, String filename) throws IOException {
    this(layout, filename, true);
  }

  /**
     The File property takes a string value which should be the
     name of the file to append to.

Note that the special values
     "System.out" or "System.err" are no longer honored.

Note: Actual opening of the file is made when {@link
     #activateOptions} is called, not when the options are set.  */
  public void setFile(String file) {
    // Trim spaces from both ends. The users probably does not want
    // trailing spaces in file names.
    String val = file.trim();
    fileName = val;
  }

  /**
      Returns the value of the Append option.
   */
  public
  boolean getAppend() {
    return fileAppend;
  }

  /** Returns the value of the File option. */
  public
  String getFile() {
    return fileName;
  }

  /**
     If the value of File is not null, then {@link
     #setFile} is called with the values of File  and
     Append properties.

     @since 0.8.1 */
  public
  void activateOptions() {
    if(fileName != null) {
      try {
	setFile(fileName, fileAppend, bufferedIO, bufferSize);
      }
      catch(java.io.IOException e) {
	errorHandler.error("setFile("+fileName+","+fileAppend+") call failed.",
			   e, ErrorCode.FILE_OPEN_FAILURE);
      }
    } else {
      //LogLog.error("File option not set for appender ["+name+"].");
      LogLog.warn("File option not set for appender ["+name+"].");
      LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
    }
  }

 /**
     Closes the previously opened file.
  */
  protected
  void closeFile() {
    if(this.qw != null) {
      try {
	this.qw.close();
      }
      catch(java.io.IOException e) {
          if (e instanceof InterruptedIOException) {
              Thread.currentThread().interrupt();
          }
	// Exceptionally, it does not make sense to delegate to an
	// ErrorHandler. Since a closed appender is basically dead.
	LogLog.error("Could not close " + qw, e);
      }
    }
  }

  /**
     Get the value of the BufferedIO option.

BufferedIO will significatnly increase performance on heavily
     loaded systems.

  */
  public
  boolean getBufferedIO() {
    return this.bufferedIO;
  }

  /**
     Get the size of the IO buffer.
  */
  public
  int getBufferSize() {
    return this.bufferSize;
  }

  /**
     The Append option takes a boolean value. It is set to
     true by default. If true, then File
     will be opened in append mode by {@link #setFile setFile} (see
     above). Otherwise, {@link #setFile setFile} will open
     File in truncate mode.

Note: Actual opening of the file is made when {@link
     #activateOptions} is called, not when the options are set.
   */
  public
  void setAppend(boolean flag) {
    fileAppend = flag;
  }

  /**
     The BufferedIO option takes a boolean value. It is set to
     false by default. If true, then File
     will be opened and the resulting {@link java.io.Writer} wrapped
     around a {@link BufferedWriter}.

     BufferedIO will significatnly increase performance on heavily
     loaded systems.

  */
  public
  void setBufferedIO(boolean bufferedIO) {
    this.bufferedIO = bufferedIO;
    if(bufferedIO) {
      immediateFlush = false;
    }
  }

  /**
     Set the size of the IO buffer.
  */
  public
  void setBufferSize(int bufferSize) {
    this.bufferSize = bufferSize;
  }

  /**

Sets and opens the file where the log output will
    go. The specified file must be writable.

If there was already an opened file, then the previous file
    is closed first.

Do not use this method directly. To configure a FileAppender
    or one of its subclasses, set its properties one by one and then
    call activateOptions.

    @param fileName The path to the log file.
    @param append   If true will append to fileName. Otherwise will
        truncate fileName.  */
  public
  synchronized
  void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
                                                            throws IOException {
    LogLog.debug("setFile called: "+fileName+", "+append);

    // It does not make sense to have immediate flush and bufferedIO.
    if(bufferedIO) {
      setImmediateFlush(false);
    }

    reset();
    FileOutputStream ostream = null;
    try {
          //
          //   attempt to create file
          //
          ostream = new FileOutputStream(fileName, append);
    } catch(FileNotFoundException ex) {
          //
          //   if parent directory does not exist then
          //      attempt to create it and try to create file
          //      see bug 9150
          //
          String parentName = new File(fileName).getParent();
          if (parentName != null) {
             File parentDir = new File(parentName);
             if(!parentDir.exists() && parentDir.mkdirs()) {
                ostream = new FileOutputStream(fileName, append);
             } else {
                throw ex;
             }
          } else {
             throw ex;
          }
    }
    Writer fw = createWriter(ostream);
    if(bufferedIO) {
      fw = new BufferedWriter(fw, bufferSize);
    }
    this.setQWForFiles(fw);
    this.fileName = fileName;
    this.fileAppend = append;
    this.bufferedIO = bufferedIO;
    this.bufferSize = bufferSize;
    writeHeader();
    LogLog.debug("setFile ended");
  }

  /**
     Sets the quiet writer being used.

     This method is overriden by {@link RollingFileAppender}.
   */
  protected
  void setQWForFiles(Writer writer) {
     this.qw = new QuietWriter(writer, errorHandler);
  }

  /**
     Close any previously opened file and call the parent's
     reset.  */
  protected
  void reset() {
    closeFile();
    this.fileName = null;
    super.reset();

  String getFile() {
    return fileName;

FUNC_DECL IF PARAM ASSIGN ASSIGN LITERAL_ANCHOR

FUNC_DECL PARAM PARAM PARAM PARAM PARAM ASSIGN CALL

FUNC_DECL PARAM PARAM PARAM ASSIGN CALL LITERAL_ANCHOR


public class XSLProcessorContext
{

  /**
   * Create a processor context to be passed to an extension.
   * (Notice it is a package-only constructor).
   *
   * @param transformer non-null transformer instance
   * @param stylesheetTree The owning stylesheet
   * @param sourceTree The source document
   * @param sourceNode The current source node
   * @param mode the current mode being executed.
   */
  public XSLProcessorContext(TransformerImpl transformer,
                             Stylesheet stylesheetTree)
  {

    this.transformer = transformer;
    this.stylesheetTree = stylesheetTree;
    org.apache.xpath.XPathContext xctxt = transformer.getXPathContext();
    this.mode = transformer.getMode();
    this.sourceNode = xctxt.getCurrentNode();
    this.sourceTree = xctxt.getDTM(this.sourceNode);
  }

  /** An instance of a transformer          */
  private TransformerImpl transformer;

  /**
   * Get the transformer.
   *
   * @return the transformer instance for this context
   */
  public TransformerImpl getTransformer()
  {
    return transformer;
  }

  /** The owning stylesheet for this context          */
  private Stylesheet stylesheetTree;

  /**
   * Get the Stylesheet being executed.
   *
   * @return the Stylesheet being executed.
   */
  public Stylesheet getStylesheet()
  {
    return stylesheetTree;
  }

  /**  The root of the source tree being executed.        */
  private org.apache.xml.dtm.DTM sourceTree;

  /**
   * Get the root of the source tree being executed.
   *
   * @return the root of the source tree being executed.
   */
  public org.w3c.dom.Node getSourceTree()
  {
    return sourceTree.getNode(sourceTree.getDocumentRoot(sourceNode));
  }

  /** the current context node.          */
  private int sourceNode;

  /**
   * Get the current context node.
   *
   * @return the current context node.
   */
  public org.w3c.dom.Node getContextNode()
  {
    return sourceTree.getNode(sourceNode);
  }

  /** the current mode being executed.         */
  private QName mode;

  /**
   * Get the current mode being executed.
   *
   * @return the current mode being executed.
   */
  public QName getMode()
  {
    return mode;
  }

  /**
   * Output an object to the result tree by doing the right conversions.
   * This is public for access by extensions.
   *
   *
   * @param stylesheetTree The owning stylesheet
   * @param obj the Java object to output. If its of an X<something> type
   *        then that conversion is done first and then sent out.
   *
   * @throws TransformerException
   * @throws java.io.FileNotFoundException
   * @throws java.io.IOException
   * @throws java.net.MalformedURLException
   */
  public void outputToResultTree(Stylesheet stylesheetTree, Object obj)
          throws TransformerException, java.net.MalformedURLException,
                 java.io.FileNotFoundException, java.io.IOException
  {

    try
    {
      SerializationHandler rtreeHandler = transformer.getResultTreeHandler();
      XPathContext xctxt = transformer.getXPathContext();
      XObject value;

      if (obj instanceof XObject)
      {
        value = (XObject) obj;
      }
      else if (obj instanceof String)
      {
        value = new XString((String) obj);
      }
      else if (obj instanceof Boolean)
      {
        value = new XBoolean(((Boolean) obj).booleanValue());
      }
      else if (obj instanceof Double)
      {
        value = new XNumber(((Double) obj).doubleValue());
      }
      else if (obj instanceof DocumentFragment)
      {
        int handle = xctxt.getDTMHandleFromNode((DocumentFragment)obj);

        value = new XRTreeFrag(handle, xctxt);
      }
      else if (obj instanceof DTM)
      {
        DTM dtm = (DTM)obj;
        DTMIterator iterator = new DescendantIterator();
        iterator.setRoot(dtm.getDocument(), xctxt);
        value = new XNodeSet(iterator);
      }
      else if (obj instanceof DTMAxisIterator)
      {
        DTMAxisIterator iter = (DTMAxisIterator)obj;
        DTMIterator iterator = new OneStepIterator(iter, -1);
        value = new XNodeSet(iterator);
      }
      else if (obj instanceof DTMIterator)
      {
        value = new XNodeSet((DTMIterator) obj);
      }
      else if (obj instanceof NodeIterator)
      {
        value = new XNodeSet(new org.apache.xpath.NodeSetDTM(((NodeIterator)obj), xctxt));
      }
      else if (obj instanceof org.w3c.dom.Node)
      {
        value =
          new XNodeSet(xctxt.getDTMHandleFromNode((org.w3c.dom.Node) obj),
                       xctxt.getDTMManager());
      }
      else
      {
        value = new XString(obj.toString());
      }

      int type = value.getType();
      String s;

      switch (type)
      {
      case XObject.CLASS_BOOLEAN :
      case XObject.CLASS_NUMBER :
      case XObject.CLASS_STRING :
        s = value.str();

        rtreeHandler.characters(s.toCharArray(), 0, s.length());
        break;

        DTMIterator nl = value.iter();

        int pos;

        while (DTM.NULL != (pos = nl.nextNode()))
        {
          DTM dtm = nl.getDTM(pos);
          int top = pos;

          while (DTM.NULL != pos)
          {
            rtreeHandler.flushPending();
            ClonerToResultTree.cloneToResultTree(pos, dtm.getNodeType(pos),
                                                   dtm, rtreeHandler, true);

            int nextNode = dtm.getFirstChild(pos);

            while (DTM.NULL == nextNode)
            {
              if (DTM.ELEMENT_NODE == dtm.getNodeType(pos))
              {
                rtreeHandler.endElement("", "", dtm.getNodeName(pos));
              }

              if (top == pos)
                break;

              nextNode = dtm.getNextSibling(pos);

              if (DTM.NULL == nextNode)
              {
                pos = dtm.getParent(pos);

                if (top == pos)
                {
                  if (DTM.ELEMENT_NODE == dtm.getNodeType(pos))
                  {
                    rtreeHandler.endElement("", "", dtm.getNodeName(pos));
                  }

                  nextNode = DTM.NULL;

                  break;
                }
              }
            }

            pos = nextNode;
          }
        }
        break;
      case XObject.CLASS_RTREEFRAG :
        SerializerUtils.outputResultTreeFragment(
            rtreeHandler, value, transformer.getXPathContext());
        break;
      }
    }
    catch(org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);

  public QName getMode()
  {
    return mode;

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