Beispiel #1
0
  /** Initialize the server. */
  private void serverInit(CauchoRequest req) throws ServletException {
    if (_urlPrefix != null) return;

    WebApp app = (WebApp) getServletContext();

    // calculate the URL prefix
    _servletId = req.getServletPath();

    CharBuffer cb = CharBuffer.allocate();

    if (!"default".equals(app.getAdmin().getHost().getName())
        && !"".equals(app.getAdmin().getHost().getName())) {
      String hostName = app.getAdmin().getHost().getURL();

      cb.append(hostName);
      cb.append(app.getContextPath());
      cb.append(_servletId);
    } else {
      cb.append(req.getScheme());
      cb.append("://");
      cb.append(req.getServerName());
      cb.append(":");
      cb.append(req.getServerPort());
      cb.append(app.getContextPath());
      cb.append(_servletId);
    }

    _urlPrefix = cb.close();

    initProtocol();
  }
 /**
  * The location of a javadoc generated api, can be a url, required.
  *
  * <p>Examples:
  *
  * <ul>
  *   <li>http://java.sun.com/j2se/1.4.2/docs/api
  *   <li>file://usr/local/java/axis_1-1/docs/apiDocs
  *   <li>resin/
  * </ul>
  */
 public void setLocation(String location) {
   if (!location.endsWith("/")) {
     CharBuffer cb = CharBuffer.allocate();
     cb.append(location);
     cb.append('/');
     _location = cb.close();
   } else _location = location;
 }
  public void doFilter(
      ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
      throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;

    String uri = request.getRequestURI();

    String servletPath = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
    String pathInfo;
    String queryString;

    if (servletPath == null) {
      servletPath = request.getServletPath();
      pathInfo = request.getPathInfo();

      if (isUseQuery()) queryString = request.getQueryString();
      else queryString = null;
    } else {
      pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);

      if (isUseQuery())
        queryString = (String) request.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING);
      else queryString = null;
    }

    String name;

    if (pathInfo == null && queryString == null) name = servletPath;
    else {
      CharBuffer nameBuilder = new CharBuffer();

      nameBuilder.append(servletPath);

      if (pathInfo != null) nameBuilder.append(pathInfo);

      if (queryString != null) {
        nameBuilder.append('?');
        nameBuilder.append(queryString);
      }

      name = nameBuilder.toString();
    }

    ProfilerPoint profilerPoint = _profilerManager.getProfilerPoint(name);

    if (log.isLoggable(Level.FINEST)) log.finest(profilerPoint.toString());

    Profiler profiler = profilerPoint.start();

    try {
      chain.doFilter(request, response);
    } finally {
      profiler.finish();
    }
  }
Beispiel #4
0
  private int parseHeaders(HttpServletResponse res, InputStream is) throws IOException {
    CharBuffer key = new CharBuffer();
    CharBuffer value = new CharBuffer();

    int ch = is.read();

    if (ch < 0) {
      log.fine("Can't contact FastCGI");
      res.sendError(404);
      return -1;
    }

    while (ch >= 0) {
      key.clear();
      value.clear();

      for (; ch >= 0 && ch != ' ' && ch != '\r' && ch != '\n' && ch != ':'; ch = is.read()) {
        key.append((char) ch);
      }

      for (; ch >= 0 && ch == ' ' || ch == ':'; ch = is.read()) {}

      for (; ch >= 0 && ch != '\r' && ch != '\n'; ch = is.read()) {
        value.append((char) ch);
      }

      if (ch == '\r') {
        ch = is.read();
        if (ch == '\n') ch = is.read();
      }

      if (key.length() == 0) return ch;

      if (log.isLoggable(Level.FINE)) log.fine("fastcgi:" + key + ": " + value);

      if (key.equalsIgnoreCase("status")) {
        int status = 0;
        int len = value.length();

        for (int i = 0; i < len; i++) {
          char digit = value.charAt(i);

          if ('0' <= digit && digit <= '9') status = 10 * status + digit - '0';
          else break;
        }

        res.setStatus(status);
      } else if (key.startsWith("http") || key.startsWith("HTTP")) {
      } else if (key.equalsIgnoreCase("location")) {
        res.sendRedirect(value.toString());
      } else res.addHeader(key.toString(), value.toString());
    }

    return ch;
  }
  /** Generates the join expression. */
  public void generateJoin(CharBuffer cb) {
    cb.append('(');

    for (int i = 0; i < _components.size(); i++) {
      if (i != 0) cb.append(" OR ");

      AmberExpr expr = _components.get(i);

      expr.generateJoin(cb);
    }

    cb.append(')');
  }
  public String toSignatureString() {
    CharBuffer cb = new CharBuffer();

    cb.append(_methodName);
    cb.append("(");
    for (int i = 0; _paramTypes != null && i < _paramTypes.size(); i++) {
      if (i != 0) cb.append(", ");
      cb.append(_paramTypes.get(i));
    }
    cb.append(")");

    return cb.toString();
  }
Beispiel #7
0
  private CharBuffer convertHeader(CharBuffer cb, String key) {
    cb.clear();

    cb.append("HTTP_");

    for (int i = 0; i < key.length(); i++) {
      char ch = key.charAt(i);
      if (ch == '-') cb.append('_');
      else if (ch >= 'a' && ch <= 'z') cb.append((char) (ch + 'A' - 'a'));
      else cb.append(ch);
    }

    return cb;
  }
  private void generateInternalWhere(CharBuffer cb, boolean select) {
    cb.append('(');

    for (int i = 0; i < _components.size(); i++) {
      if (i != 0) cb.append(" OR ");

      AmberExpr expr = _components.get(i);

      if (select) expr.generateWhere(cb);
      else expr.generateUpdateWhere(cb);
    }

    cb.append(')');
  }
  /**
   * A location href, relative to the web-app root, appropriately rewritten to handle remote
   * locations and locations that are local absolute.
   */
  String getLocationHref(String file) {
    CharBuffer cb = CharBuffer.allocate();

    if (_isLocalAbsolute) {
      cb.append(_id);
      cb.append('/');
    } else {
      cb.append(_location);
    }

    cb.append(file);

    return cb.close();
  }
Beispiel #10
0
  /** Joins the array. */
  public static String join(String[] array, String sep) {
    if (array == null) return "";

    if (sep == null) sep = "";

    CharBuffer result = CharBuffer.allocate();

    for (int i = 0; i < array.length; i++) {
      if (i != 0) result.append(sep);

      result.append(array[i]);
    }

    return result.close();
  }
  /**
   * Logs a message to the error log.
   *
   * @param log the error log to write the message.
   * @param message the message to write
   * @param e the exception to write
   */
  public void log(
      String message,
      Throwable e,
      HttpServletRequest request,
      HttpServletResponse response,
      ServletContext application)
      throws IOException {
    WriteStream logStream = getLogStream();

    if (logStream == null) return;

    Throwable t = e;
    while (t != null) {
      e = t;

      if (e instanceof ServletException) t = ((ServletException) e).getRootCause();
      else if (e instanceof ExceptionWrapper) t = ((ExceptionWrapper) e).getRootCause();
      else t = null;
    }

    CharBuffer cb = CharBuffer.allocate();

    QDate.formatLocal(cb, CurrentTime.getCurrentTime(), "[%Y/%m/%d %H:%M:%S] ");

    cb.append(message);

    logStream.log(cb.close());

    if (e != null && !(e instanceof CompileException)) logStream.log(e);

    logStream.flush();
  }
    public Object next() {
      _cb.clear();

      char ch;
      final int startDelims = _delims.length - 1;
      loop:
      for (; _i < _length; _i++) {
        ch = _value.charAt(_i);

        for (int j = startDelims; j >= 0; j--) {
          if (_delims[j] == ch) break loop;
        }

        _cb.append(ch);
      }

      for (_i++; _i < _length; _i++) {
        ch = _value.charAt(_i);

        boolean hasDelim = false;
        for (int j = startDelims; j >= 0; j--) {
          if (_delims[j] == ch) {
            hasDelim = true;
            break;
          }
        }

        if (!hasDelim) return _cb.toString();
      }

      return _cb.toString();
    }
  public void init() throws ConfigException {
    if (_id == null) throw new ConfigException(L.l("`{0}' is required", "id"));

    if (_location == null) throw new ConfigException(L.l("`{0}' is required", "location"));

    if (_name == null) _name = _location.toString();

    if (_indexString == null) _indexString = "index-all.html";

    _locationPath = Vfs.lookup(_location);

    int split = _indexString.indexOf('#');

    if (split > -1) {
      CharBuffer before = new CharBuffer(_indexString.substring(0, split));
      CharBuffer after = new CharBuffer(_indexString.substring(split + 1));
      CharBuffer index = CharBuffer.allocate();

      boolean isIndex = false;

      for (int i = 1; i <= 27; i++) {
        index.append(before);
        index.append(i);
        index.append(after);

        Path indexPath = _locationPath.lookup(index.toString());

        if (indexPath.exists()) {
          isIndex = true;
          _index.add(indexPath);
        }

        index.clear();
      }

      if (!isIndex) {
        throw new ConfigException(L.l("`{0}' not found", _locationPath.lookup(_indexString)));
      }
    } else _index.add(_locationPath.lookup(_indexString));

    if (_locationPath.getScheme().equals("file")) {
      _isLocal = true;
      Path pwd = Vfs.getPwd();

      if (!_locationPath.getPath().startsWith(pwd.getPath())) _isLocalAbsolute = true;
    }
  }
  private void handleExternalBody(String url) throws JspException, ServletException, IOException {
    URL netURL = new URL(url);

    URLConnection conn = netURL.openConnection();

    if (conn instanceof HttpURLConnection) ((HttpURLConnection) conn).setFollowRedirects(true);

    InputStream is = conn.getInputStream();
    try {
      ReadStream in = Vfs.openRead(is);
      String encoding = conn.getContentEncoding();
      String contentType = conn.getContentType();

      if (_charEncoding != null) {
        encoding = _charEncoding;
        if (encoding != null && !encoding.equals("")) in.setEncoding(encoding);
      } else if (encoding != null) in.setEncoding(encoding);
      else if (contentType != null) {
        int p = contentType.indexOf("charset=");
        if (p > 0) {
          CharBuffer cb = new CharBuffer();
          for (int i = p + 8; i < contentType.length(); i++) {
            int ch = contentType.charAt(i);
            if (ch == '"' || ch == '\'') {
            } else if (ch >= 'a' && ch <= 'z') cb.append((char) ch);
            else if (ch >= 'A' && ch <= 'Z') cb.append((char) ch);
            else if (ch >= '0' && ch <= '9') cb.append((char) ch);
            else if (ch == '-' || ch == '_') cb.append((char) ch);
            else break;
          }
          encoding = cb.toString();

          in.setEncoding(encoding);
        }
      }

      JspWriter out = pageContext.getOut();

      int ch;
      while ((ch = in.readChar()) >= 0) out.print((char) ch);
    } finally {
      is.close();
    }
  }
Beispiel #15
0
  /**
   * Returns the server container responsible for handling the request
   *
   * @param pathInfo the path info of the request
   * @return the server bean responsible for handling the request
   */
  Skeleton getSkeleton(String pathInfo, String queryString) throws Exception {
    CharBuffer cb = CharBuffer.allocate();
    cb.append(pathInfo);
    cb.append('?');
    cb.append(queryString);

    Skeleton skeleton = (Skeleton) _beanMap.get(cb);

    if (skeleton != null) {
      cb.free();
      return skeleton;
    }

    skeleton = _protocolContainer.getSkeleton(pathInfo, queryString);

    _beanMap.put(cb, skeleton);

    return skeleton;
  }
  /**
   * Return the normalized name.
   *
   * @param tag the raw name in the XML file.
   * @return the normalized name.
   */
  QName getName(CharBuffer tag) {
    if (!toLower) return super.getName(tag);

    cb.clear();
    cb.append(tag);
    cb.toLowerCase();

    int name = cbNames.get(cb);

    if (name >= 0) return super.getName(cb);
    else return super.getName(tag);
  }
  public String toString() {
    if (_components.size() == 1) {
      return _components.get(0).toString();
    } else {
      CharBuffer cb = new CharBuffer();

      cb.append('(');

      for (int i = 0; i < _components.size(); i++) {
        if (i != 0) cb.append(" OR ");

        AmberExpr expr = _components.get(i);

        cb.append(expr);
      }

      cb.append(')');

      return cb.toString();
    }
  }
Beispiel #18
0
  /** Escapes the XML string. */
  public static String escapeXml(String string) {
    if (string == null) return "";

    CharBuffer cb = CharBuffer.allocate();

    for (int i = 0; i < string.length(); i++) {
      int ch = string.charAt(i);

      switch (ch) {
        case '<':
          cb.append("&lt;");
          break;
        case '>':
          cb.append("&gt;");
          break;
        case '&':
          cb.append("&amp;");
          break;
        case '\'':
          cb.append("&#039;");
          break;
        case '"':
          cb.append("&#034;");
          break;
        default:
          cb.append((char) ch);
          break;
      }
    }

    return cb.close();
  }
Beispiel #19
0
  /** Replaces substrings. */
  public static String replace(String input, String before, String after) {
    if (input == null) return "";

    if (before == null || before.equals("")) return input;

    if (after == null) after = "";

    CharBuffer result = CharBuffer.allocate();

    int head = 0;
    int next;
    while ((next = input.indexOf(before, head)) >= 0) {
      result.append(input.substring(head, next));

      result.append(after);

      head = next + before.length();
    }

    result.append(input.substring(head));

    return result.close();
  }
  public RequestDispatcher getRequestDispatcher(String path) {
    if (path == null || path.length() == 0) return null;
    else if (path.charAt(0) == '/') return getWebApp().getRequestDispatcher(path);
    else {
      CharBuffer cb = new CharBuffer();

      WebApp webApp = getWebApp();

      String servletPath = getPageServletPath();
      if (servletPath != null) cb.append(servletPath);
      String pathInfo = getPagePathInfo();
      if (pathInfo != null) cb.append(pathInfo);

      int p = cb.lastIndexOf('/');
      if (p >= 0) cb.setLength(p);
      cb.append('/');
      cb.append(path);

      if (webApp != null) return webApp.getRequestDispatcher(cb.toString());

      return null;
    }
  }
  QName getAttributeName(CharBuffer eltName, CharBuffer source) {
    if (!toLower) return super.getName(source);

    cb.clear();
    cb.append(eltName);
    cb.toLowerCase();
    int name = cbNames.get(cb);

    if (name < 0) return super.getName(source);
    else {
      source.toLowerCase();
      return super.getName(source);
    }
  }
  /** Returns a printable version. */
  public String toString() {
    CharBuffer cb = new CharBuffer();
    cb.append("AttributesImpl[");
    for (int i = 0; i < _size; i++) {
      cb.append(" ");
      cb.append(_names[i]);
      cb.append("=\"");
      cb.append(_values[i]);
      cb.append("\"");
    }
    cb.append("]");

    return cb.close();
  }
  private static String parseName(ReadStream is) throws IOException {
    int ch;

    for (ch = is.read(); ch > 0 && ch != '"'; ch = is.read()) {}

    if (ch < 0) return null;

    CharBuffer cb = new CharBuffer();

    for (ch = is.read(); ch > 0 && ch != '"'; ch = is.read()) {
      cb.append((char) ch);
    }

    if (ch < 0) return null;

    return cb.toString();
  }
  /**
   * Logs an error.
   *
   * @param message the error message
   * @param request the servlet request
   * @param response the servlet response
   * @param application the servlet context
   */
  public void log(
      String message,
      HttpServletRequest request,
      HttpServletResponse response,
      ServletContext application)
      throws IOException {
    WriteStream logStream = getLogStream();

    if (logStream == null) return;

    CharBuffer cb = CharBuffer.allocate();

    QDate.formatLocal(cb, CurrentTime.getCurrentTime(), "[%Y/%m/%d %H:%M:%S] ");

    cb.append(message);

    logStream.log(cb.close());

    logStream.flush();
  }
  /** Adds a parameter. */
  public void addParam(String name, String value) {
    if (name == null) return;

    if (value == null) value = "";

    if (_query.length() != 0) _query.append('&');

    _query.append(name);
    _query.append('=');
    int len = value.length();
    for (int i = 0; i < len; i++) {
      char ch = value.charAt(i);

      switch (ch) {
        case '&':
          _query.append("%26");
          break;

        case '%':
          _query.append("%25");
          break;

        case '+':
          _query.append("%2b");
          break;

        case '=':
          _query.append("%3d");
          break;

        default:
          _query.append(ch);
          break;
      }
    }
  }
Beispiel #26
0
  /**
   * Walk down the path starting from the portion immediately following the scheme. i.e. schemeWalk
   * is responsible for parsing the host and port from the URL.
   *
   * @param userPath the user's passed in path
   * @param attributes the attributes for the new path
   * @param uri the normalized full uri
   * @param offset offset into the uri to start processing, i.e. after the scheme.
   * @return the looked-up path.
   */
  @Override
  public Path schemeWalk(String userPath, Map<String, Object> attributes, String uri, int offset) {
    int length = uri.length();

    if (length < 2 + offset || uri.charAt(offset) != '/' || uri.charAt(offset + 1) != '/')
      throw new RuntimeException(L.l("bad scheme in `{0}'", uri));

    CharBuffer buf = CharBuffer.allocate();
    int i = 2 + offset;
    int ch = 0;
    boolean isInBrace = false;

    for (;
        i < length && ((ch = uri.charAt(i)) != ':' || isInBrace) && ch != '/' && ch != '?';
        i++) {
      buf.append((char) ch);

      if (ch == '[') isInBrace = true;
      else if (ch == ']') isInBrace = false;
    }

    String host = buf.close();
    if (host.length() == 0) throw new RuntimeException(L.l("bad host in `{0}'", uri));

    int port = 0;
    if (ch == ':') {
      for (i++; i < length && (ch = uri.charAt(i)) >= '0' && ch <= '9'; i++) {
        port = 10 * port + uri.charAt(i) - '0';
      }
    }

    if (port == 0) port = 80;

    HttpPath root = create(host, port);

    return root.fsWalk(userPath, attributes, uri.substring(i));
  }
  public ESString toSource(IntMap map, boolean isLoopPass) throws Throwable {
    CharBuffer cb = new CharBuffer();
    Global resin = Global.getGlobalProto();

    int mark = map.get(this);

    if (mark > 0 && isLoopPass) return null;
    else if (mark > 0) {
      cb.append("#" + mark + "=");
      map.put(this, -mark);
    } else if (mark == 0 && isLoopPass) {
      map.put(this, resin.addMark());
      return null;
    } else if (mark < 0 && !isLoopPass) {
      return ESString.create("#" + -mark + "#");
    }

    cb.append("{");

    if (isLoopPass) map.put(this, 0);

    Iterator e = keys();

    boolean isFirst = true;
    while (e.hasNext()) {
      if (!isFirst) cb.append(", ");
      isFirst = false;

      ESString key = (ESString) e.next();

      cb.append(key);
      cb.append(":");
      ESBase value = getProperty(key);
      if (isLoopPass) value.toSource(map, isLoopPass);
      else cb.append(value.toSource(map, isLoopPass));
    }

    cb.append("}");

    return new ESString(cb.toString());
  }
Beispiel #28
0
  /**
   * Execute a request. The path-info of the request selects the bean. Once the bean's selected, it
   * will be applied.
   */
  public void service(ServletRequest request, ServletResponse response)
      throws IOException, ServletException {
    CauchoRequest req = (CauchoRequest) request;
    CauchoResponse res = (CauchoResponse) response;

    if (_urlPrefix == null) {
      synchronized (this) {
        if (_urlPrefix == null) serverInit(req);
      }
    }

    if (!req.getMethod().equals("POST")) {
      if (log.isLoggable(Level.FINE))
        log.log(Level.FINE, this + " unexpected method " + req.getMethod());

      String protocol = _protocolContainer.getName();
      res.setStatus(500, protocol + " Protocol Error");
      PrintWriter out = res.getWriter();
      out.println(protocol + " expects a POST containing an RPC call.");
      return;
    }

    try {
      String pathInfo = req.getPathInfo();
      String queryString = req.getQueryString();

      CharBuffer cb = new CharBuffer();
      cb.append(pathInfo);
      cb.append('?');
      cb.append(queryString);

      InputStream is = req.getInputStream();

      if (_isDebug) {}

      Skeleton skeleton = (Skeleton) _beanMap.get(cb);

      if (skeleton == null) {
        // If this was a load just to force the initialization, then return
        if (req.getParameter("ejb-load") != null) return;

        if (_exception != null) throw _exception;

        try {
          if (pathInfo == null) pathInfo = "";

          skeleton = _protocolContainer.getSkeleton(pathInfo, queryString);
        } catch (Exception e) {
          log.log(Level.WARNING, e.toString(), e);

          skeleton = _protocolContainer.getExceptionSkeleton();

          if (skeleton != null) {
            skeleton._service(req.getInputStream(), res.getOutputStream(), e);

            return;
          } else throw e;
        }

        if (skeleton == null)
          throw new ServletException(
              L.l("Can't load skeleton for '{0}?{1}'", pathInfo, queryString));

        if (skeleton != null) {
          skeleton.setDebug(_isDebug);
          _beanMap.put(cb, skeleton);
        }
      }

      skeleton._service(req.getInputStream(), res.getOutputStream());
    } catch (ServletException e) {
      e.printStackTrace();
      throw e;
    } catch (Throwable e) {
      e.printStackTrace();
      log.log(Level.WARNING, e.toString(), e);

      throw new ServletException(e);
    }
  }
Beispiel #29
0
  /** Parse the headers returned from the server. */
  private void parseHeaders() throws IOException {
    CharBuffer line = new CharBuffer();

    // Skip blank lines
    int count = 0;
    do {
      line.clear();
      if (!_rs.readln(line)) {
        _isKeepalive = false;
        return;
      }
    } while (line.length() == 0 && ++count < 10);

    if (line.length() == 0) {
      _isKeepalive = false;
      return;
    }

    if (line.startsWith("HTTP/1.1 100")) {
      count = 100;
      do {
        line.clear();
        if (!_rs.readln(line)) {
          _isKeepalive = false;
          return;
        }
      } while (line.length() != 0 && count-- > 0);

      count = 100;
      do {
        line.clear();
        if (!_rs.readln(line)) {
          _isKeepalive = false;
          return;
        }
      } while (line.length() == 0 && count-- > 0);
    }

    if (line.length() == 0) {
      _isKeepalive = false;
      return;
    }

    int i = 0;
    for (i = 0; i < line.length() && line.charAt(i) != ' '; i++) {}

    for (; i < line.length() && line.charAt(i) == ' '; i++) {}

    int status = 0;
    for (; i < line.length(); i++) {
      char ch = line.charAt(i);
      if (ch >= '0' && ch <= '9') status = 10 * status + ch - '0';
      else break;
    }

    if (status != 200) _isKeepalive = false;
    else if (!line.startsWith("HTTP/1.1 ")) _isKeepalive = false;

    _attributes.put("status", String.valueOf(status));
    _attributes.put("status-message", line.toString());

    CharBuffer key = new CharBuffer();
    while (true) {
      line.clear();
      if (!_rs.readln(line) || line.length() == 0) break;

      int lineLength = line.length();

      for (i = 0; i < lineLength && Character.isWhitespace(line.charAt(i)); i++) {}

      key.clear();
      for (;
          i < lineLength && !Character.isWhitespace(line.charAt(i)) && line.charAt(i) != ':';
          i++) {
        key.append((char) line.charAt(i));
      }

      for (; i < lineLength && Character.isWhitespace(line.charAt(i)); i++) {}

      if (key.length() == 0 || lineLength <= i || line.charAt(i) != ':') continue;

      for (i++; i < lineLength && Character.isWhitespace(line.charAt(i)); i++) {}

      key.toLowerCase();
      String value = line.substring(i);

      if (log.isLoggable(Level.FINE)) log.fine(key + ": " + value);

      if (key.matchesIgnoreCase("content-length")) {
        _contentLength = Integer.parseInt(value.trim());
      } else if (key.matchesIgnoreCase("connection") && value.equalsIgnoreCase("close")) {
        _isKeepalive = false;
      } else if (key.matchesIgnoreCase("transfer-encoding") && value.equalsIgnoreCase("chunked")) {

        _isChunked = true;
        _chunkLength = 0;
      }

      String keyString = key.toLowerCase().toString();

      String oldValue = (String) _attributes.put(keyString, value);

      if (oldValue != null) {
        value = oldValue + '\n' + value;
      }

      _attributes.put(keyString, value);
    }
  }
  /** Parses the access log string. */
  private ArrayList<Segment> parseFormat(String format) {
    ArrayList<Segment> segments = new ArrayList<Segment>();
    CharBuffer cb = new CharBuffer();

    int i = 0;
    while (i < _format.length()) {
      char ch = _format.charAt(i++);

      if (ch != '%' || i >= _format.length()) {
        cb.append((char) ch);
        continue;
      }

      String arg = null;
      ch = _format.charAt(i++);
      if (ch == '>') ch = _format.charAt(i++);
      else if (ch == '{') {
        if (cb.length() > 0) segments.add(new Segment(this, Segment.TEXT, cb.toString()));
        cb.clear();
        while (i < _format.length() && _format.charAt(i++) != '}') cb.append(_format.charAt(i - 1));
        arg = cb.toString();
        cb.clear();

        ch = _format.charAt(i++);
      }

      switch (ch) {
        case 'b':
        case 'c':
        case 'h':
        case 'i':
        case 'l':
        case 'n':
        case 'r':
        case 's':
        case 'T':
        case 'D':
        case 'o':
        case 'u':
        case 'U':
        case 'v':
          if (cb.length() > 0) segments.add(new Segment(this, Segment.TEXT, cb.toString()));
          cb.clear();
          segments.add(new Segment(this, ch, arg));
          break;

        case 't':
          if (cb.length() > 0) segments.add(new Segment(this, Segment.TEXT, cb.toString()));
          cb.clear();
          if (arg != null) _timeFormat = arg;
          segments.add(new Segment(this, ch, arg));
          break;

        default:
          cb.append('%');
          i--;
          break;
      }
    }

    cb.append(CauchoSystem.getNewlineString());
    segments.add(new Segment(this, Segment.TEXT, cb.toString()));

    return segments;
  }