/** * Fills the time buffer with the formatted time. * * @param date current time in milliseconds */ private void fillTime(long date) throws IOException { synchronized (_timeBuffer) { if (date / 1000 == _lastTime / 1000) return; if (_timeFormatSecondOffset >= 0 && date / 3600000 == _lastTime / 3600000) { byte[] bBuf = _timeBuffer.getBuffer(); int min = (int) (date / 60000 % 60); int sec = (int) (date / 1000 % 60); bBuf[_timeFormatMinuteOffset + 0] = (byte) ('0' + min / 10); bBuf[_timeFormatMinuteOffset + 1] = (byte) ('0' + min % 10); bBuf[_timeFormatSecondOffset + 0] = (byte) ('0' + sec / 10); bBuf[_timeFormatSecondOffset + 1] = (byte) ('0' + sec % 10); _lastTime = date; return; } _timeCharBuffer.clear(); QDate.formatLocal(_timeCharBuffer, date, _timeFormat); if (_timeFormatSecondOffset >= 0) { _timeFormatSecondOffset = _timeCharBuffer.lastIndexOf(':') + 1; _timeFormatMinuteOffset = _timeFormatSecondOffset - 3; } char[] cBuf = _timeCharBuffer.getBuffer(); int length = _timeCharBuffer.getLength(); _timeBuffer.setLength(length); byte[] bBuf = _timeBuffer.getBuffer(); for (int i = length - 1; i >= 0; i--) bBuf[i] = (byte) cBuf[i]; } _lastTime = date; }
/** * Logs a request using the current format. * * @param request the servlet request. * @param response the servlet response. * @param buffer byte buffer containing the response * @param offset buffer starting offset * @param length length allowed in the buffer * @return the new tail of the buffer */ private int log( HttpServletRequestImpl request, HttpServletResponseImpl responseFacade, AbstractHttpResponse response, byte[] buffer, int offset, int length) throws IOException { AbstractHttpRequest absRequest = request.getAbstractHttpRequest(); int len = _segments.length; for (int i = 0; i < len; i++) { Segment segment = _segments[i]; String value = null; CharSegment csValue = null; switch (segment._code) { case Segment.TEXT: int sublen = segment._data.length; byte[] data = segment._data; for (int j = 0; j < sublen; j++) buffer[offset++] = data[j]; break; case Segment.CHAR: buffer[offset++] = segment._ch; break; case 'b': if (responseFacade.getStatus() == 304) buffer[offset++] = (byte) '-'; else offset = print(buffer, offset, response.getContentLength()); break; // cookie case 'c': Cookie cookie = request.getCookie(segment._string); if (cookie == null) cookie = responseFacade.getCookie(segment._string); if (cookie == null) buffer[offset++] = (byte) '-'; else offset = print(buffer, offset, cookie.getValue()); break; // set cookie case Segment.SET_COOKIE: ArrayList<Cookie> cookies = responseFacade.getCookies(); if (cookies == null || cookies.size() == 0) buffer[offset++] = (byte) '-'; else { _cb.clear(); response.fillCookie(_cb, (Cookie) cookies.get(0), 0, 0, false); offset = print(buffer, offset, _cb.getBuffer(), 0, _cb.getLength()); } break; case 'h': if (isHostnameDnsLookup()) { String addrName = request.getRemoteAddr(); InetAddress addr = InetAddress.getByName(addrName); offset = print(buffer, offset, addr.getHostName()); } else offset = absRequest.printRemoteAddr(buffer, offset); break; // input header case 'i': csValue = absRequest.getHeaderBuffer(segment._string); if (csValue == null) buffer[offset++] = (byte) '-'; else offset = print(buffer, offset, csValue); break; case 'l': buffer[offset++] = (byte) '-'; break; // request attribute case 'n': Object oValue = request.getAttribute(segment._string); if (oValue == null) buffer[offset++] = (byte) '-'; else offset = print(buffer, offset, String.valueOf(oValue)); break; // output header case 'o': value = response.getHeader(segment._string); if (value == null) buffer[offset++] = (byte) '-'; else offset = print(buffer, offset, value); break; case 'r': offset = print(buffer, offset, request.getMethod()); buffer[offset++] = (byte) ' '; data = absRequest.getUriBuffer(); sublen = absRequest.getUriLength(); // server/02e9 if (buffer.length - offset - 128 < sublen) { sublen = buffer.length - offset - 128; System.arraycopy(data, 0, buffer, offset, sublen); offset += sublen; buffer[offset++] = (byte) '.'; buffer[offset++] = (byte) '.'; buffer[offset++] = (byte) '.'; } else { System.arraycopy(data, 0, buffer, offset, sublen); offset += sublen; } buffer[offset++] = (byte) ' '; offset = print(buffer, offset, request.getProtocol()); break; case 's': int status = responseFacade.getStatus(); buffer[offset++] = (byte) ('0' + (status / 100) % 10); buffer[offset++] = (byte) ('0' + (status / 10) % 10); buffer[offset++] = (byte) ('0' + status % 10); break; case 't': long date = Alarm.getCurrentTime(); if (date / 1000 != _lastTime / 1000) fillTime(date); sublen = _timeBuffer.getLength(); data = _timeBuffer.getBuffer(); synchronized (_timeBuffer) { System.arraycopy(data, 0, buffer, offset, sublen); } offset += sublen; break; case 'T': { long startTime = request.getStartTime(); long endTime = Alarm.getCurrentTime(); offset = print(buffer, offset, (int) ((endTime - startTime + 500) / 1000)); break; } case 'D': { long startTime = request.getStartTime(); long endTime = Alarm.getCurrentTime(); offset = print(buffer, offset, (int) ((endTime - startTime) * 1000)); break; } case 'u': value = request.getRemoteUser(false); if (value == null) buffer[offset++] = (byte) '-'; else { buffer[offset++] = (byte) '"'; offset = print(buffer, offset, value); buffer[offset++] = (byte) '"'; } break; case 'v': value = request.getServerName(); if (value == null) buffer[offset++] = (byte) '-'; else { offset = print(buffer, offset, value); } break; case 'U': offset = print(buffer, offset, request.getRequestURI()); break; default: throw new IOException(); } } return offset; }
/** 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; }