From 99ad70e80add112593874ef1219ce0bb5555cd36 Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 23 Dec 2011 00:57:46 +0000 Subject: [PATCH] 6.1.26 base for reference --- .../src/org/mortbay/http/I2PRequestLog.java | 594 +++++++++++++----- 1 file changed, 450 insertions(+), 144 deletions(-) diff --git a/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java b/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java index c83756332..384ae0155 100644 --- a/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java +++ b/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java @@ -1,182 +1,488 @@ -// ======================================================================== -// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $ -// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== +//======================================================================== +//Copyright 1997-2006 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +//http://www.apache.org/licenses/LICENSE-2.0 +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +//======================================================================== -package org.mortbay.http; +package org.mortbay.jetty; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.util.ArrayList; import java.util.Locale; import java.util.TimeZone; import javax.servlet.http.Cookie; -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; +import org.mortbay.component.AbstractLifeCycle; +import org.mortbay.jetty.servlet.PathMap; +import org.mortbay.log.Log; import org.mortbay.util.DateCache; -import org.mortbay.util.LogSupport; import org.mortbay.util.RolloverFileOutputStream; import org.mortbay.util.StringUtil; +import org.mortbay.util.TypeUtil; +import org.mortbay.util.Utf8StringBuffer; - -/* ------------------------------------------------------------ */ -/** NCSA HTTP Request Log. - * - * Override log() to put in the requestor's destination hash, - * instead of 127.0.0.1, - * which is placed in the X-I2P-DestHash field in the request headers - * by I2PTunnelHTTPServer. - * - * NCSA common or NCSA extended (combined) request log. - * @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $ - * @author Tony Thompson +/** + * This {@link RequestLog} implementation outputs logs in the pseudo-standard NCSA common log format. + * Configuration options allow a choice between the standard Common Log Format (as used in the 3 log format) + * and the Combined Log Format (single log format). + * This log format can be output by most web servers, and almost all web log analysis software can understand + * these formats. * @author Greg Wilkins + * @author Nigel Canonizado + * + * @org.apache.xbean.XBean element="ncsaLog" */ -public class I2PRequestLog extends NCSARequestLog +public class NCSARequestLog extends AbstractLifeCycle implements RequestLog { - /* ------------------------------------------------------------ */ - /** Constructor. - */ - public I2PRequestLog() + private String _filename; + private boolean _extended; + private boolean _append; + private int _retainDays; + private boolean _closeOut; + private boolean _preferProxiedForAddress; + private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss Z"; + private String _filenameDateFormat = null; + private Locale _logLocale = Locale.getDefault(); + private String _logTimeZone = "GMT"; + private String[] _ignorePaths; + private boolean _logLatency = false; + private boolean _logCookies = false; + private boolean _logServer = false; + + private transient OutputStream _out; + private transient OutputStream _fileOut; + private transient DateCache _logDateCache; + private transient PathMap _ignorePathMap; + private transient Writer _writer; + private transient ArrayList _buffers; + private transient char[] _copy; + + + public NCSARequestLog() { - super(); + _extended = true; + _append = true; + _retainDays = 31; } /* ------------------------------------------------------------ */ - /** Constructor. - * @param filename Filename, which can be in - * rolloverFileOutputStream format - * @see org.mortbay.util.RolloverFileOutputStream - * @exception IOException + /** + * @param filename The filename for the request log. This may be in the format expected by {@link RolloverFileOutputStream} */ - public I2PRequestLog(String filename) - throws IOException + public NCSARequestLog(String filename) { - super(filename); + _extended = true; + _append = true; + _retainDays = 31; + setFilename(filename); + } + + /* ------------------------------------------------------------ */ + /** + * @param filename The filename for the request log. This may be in the format expected by {@link RolloverFileOutputStream} + */ + public void setFilename(String filename) + { + if (filename != null) + { + filename = filename.trim(); + if (filename.length() == 0) + filename = null; + } + _filename = filename; + } + + public String getFilename() + { + return _filename; + } + + public String getDatedFilename() + { + if (_fileOut instanceof RolloverFileOutputStream) + return ((RolloverFileOutputStream)_fileOut).getDatedFilename(); + return null; + } + + /* ------------------------------------------------------------ */ + /** + * @param format Format for the timestamps in the log file. If not set, + * the pre-formated request timestamp is used. + */ + public void setLogDateFormat(String format) + { + _logDateFormat = format; + } + + public String getLogDateFormat() + { + return _logDateFormat; + } + + public void setLogLocale(Locale logLocale) + { + _logLocale = logLocale; + } + + public Locale getLogLocale() + { + return _logLocale; + } + + public void setLogTimeZone(String tz) + { + _logTimeZone = tz; + } + + public String getLogTimeZone() + { + return _logTimeZone; + } + + public void setRetainDays(int retainDays) + { + _retainDays = retainDays; + } + + public int getRetainDays() + { + return _retainDays; + } + + public void setExtended(boolean extended) + { + _extended = extended; + } + + public boolean isExtended() + { + return _extended; + } + + public void setAppend(boolean append) + { + _append = append; + } + + public boolean isAppend() + { + return _append; + } + + public void setIgnorePaths(String[] ignorePaths) + { + _ignorePaths = ignorePaths; + } + + public String[] getIgnorePaths() + { + return _ignorePaths; + } + + public void setLogCookies(boolean logCookies) + { + _logCookies = logCookies; + } + + public boolean getLogCookies() + { + return _logCookies; + } + + public boolean getLogServer() + { + return _logServer; + } + + public void setLogServer(boolean logServer) + { + _logServer=logServer; + } + + public void setLogLatency(boolean logLatency) + { + _logLatency = logLatency; + } + + public boolean getLogLatency() + { + return _logLatency; + } + + public void setPreferProxiedForAddress(boolean preferProxiedForAddress) + { + _preferProxiedForAddress = preferProxiedForAddress; } /* ------------------------------------------------------------ */ - /** Log a request. - * @param request The request - * @param response The response to this request. - * @param responseLength The bytes written to the response. - */ - public void log(HttpRequest request, - HttpResponse response, - int responseLength) + public void log(Request request, Response response) { - try{ - // ignore ignorables - if (_ignorePathMap != null && - _ignorePathMap.getMatch(request.getPath()) != null) + if (!isStarted()) + return; + + try + { + if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null) + return; + + if (_fileOut == null) return; - // log the rest - if (_fileOut==null) - return; - - StringBuilder buf = new StringBuilder(160); - - String addr = request.getField("X-I2P-DestHash"); - if(addr != null) - buf.append(addr).append(".i2p"); - else - buf.append(request.getRemoteAddr()); - - buf.append(" - "); - String user = request.getAuthUser(); - buf.append((user==null)?"-":user); - buf.append(" ["); - buf.append(_logDateCache.format(request.getTimeStamp())); - buf.append("] \""); - buf.append(request.getMethod()); - buf.append(' '); - buf.append(request.getURI()); - buf.append(' '); - buf.append(request.getVersion()); - buf.append("\" "); - int status=response.getStatus(); - buf.append((char)('0'+((status/100)%10))); - buf.append((char)('0'+((status/10)%10))); - buf.append((char)('0'+(status%10))); - if (responseLength>=0) - { - buf.append(' '); - if (responseLength>99999) - buf.append(Integer.toString(responseLength)); - else - { - if (responseLength>9999) - buf.append((char)('0'+((responseLength/10000)%10))); - if (responseLength>999) - buf.append((char)('0'+((responseLength/1000)%10))); - if (responseLength>99) - buf.append((char)('0'+((responseLength/100)%10))); - if (responseLength>9) - buf.append((char)('0'+((responseLength/10)%10))); - buf.append((char)('0'+(responseLength%10))); - } - buf.append(' '); - } - else - buf.append(" - "); - - String log =buf.toString(); + Utf8StringBuffer u8buf; + StringBuffer buf; synchronized(_writer) { - _writer.write(log); - if (isExtended()) - { - logExtended(request,response,_writer); - if (!getLogCookies()) - _writer.write(" -"); - } - - if (getLogCookies()) - { - Cookie[] cookies = request.getCookies(); - if (cookies==null || cookies.length==0) - _writer.write(" -"); - else - { - _writer.write(" \""); - for (int i=0;i=0) + { + buf.append(' '); + if (responseLength > 99999) + buf.append(Long.toString(responseLength)); + else + { + if (responseLength > 9999) + buf.append((char)('0' + ((responseLength / 10000)%10))); + if (responseLength > 999) + buf.append((char)('0' + ((responseLength /1000)%10))); + if (responseLength > 99) + buf.append((char)('0' + ((responseLength / 100)%10))); + if (responseLength > 9) + buf.append((char)('0' + ((responseLength / 10)%10))); + buf.append((char)('0' + (responseLength)%10)); + } + buf.append(' '); + } + else + buf.append(" - "); + + } + + if (!_extended && !_logCookies && !_logLatency) + { + synchronized(_writer) + { + buf.append(StringUtil.__LINE_SEPARATOR); + int l=buf.length(); + if (l>_copy.length) + l=_copy.length; + buf.getChars(0,l,_copy,0); + _writer.write(_copy,0,l); + _writer.flush(); + u8buf.reset(); + _buffers.add(u8buf); + } + } + else + { + synchronized(_writer) + { + int l=buf.length(); + if (l>_copy.length) + l=_copy.length; + buf.getChars(0,l,_copy,0); + _writer.write(_copy,0,l); + u8buf.reset(); + _buffers.add(u8buf); + + // TODO do outside synchronized scope + if (_extended) + logExtended(request, response, _writer); + + // TODO do outside synchronized scope + if (_logCookies) + { + Cookie[] cookies = request.getCookies(); + if (cookies == null || cookies.length == 0) + _writer.write(" -"); + else + { + _writer.write(" \""); + for (int i = 0; i < cookies.length; i++) + { + if (i != 0) + _writer.write(';'); + _writer.write(cookies[i].getName()); + _writer.write('='); + _writer.write(cookies[i].getValue()); + } + _writer.write('\"'); + } + } + + if (_logLatency) + { + _writer.write(' '); + _writer.write(TypeUtil.toString(System.currentTimeMillis() - request.getTimeStamp())); + } + + _writer.write(StringUtil.__LINE_SEPARATOR); + _writer.flush(); + } + } + } + catch (IOException e) { - log.warn(LogSupport.EXCEPTION,e); + Log.warn(e); } + + } + + /* ------------------------------------------------------------ */ + protected void logExtended(Request request, + Response response, + Writer writer) throws IOException + { + String referer = request.getHeader(HttpHeaders.REFERER); + if (referer == null) + writer.write("\"-\" "); + else + { + writer.write('"'); + writer.write(referer); + writer.write("\" "); + } + + String agent = request.getHeader(HttpHeaders.USER_AGENT); + if (agent == null) + writer.write("\"-\" "); + else + { + writer.write('"'); + writer.write(agent); + writer.write('"'); + } + } + + /* ------------------------------------------------------------ */ + protected void doStart() throws Exception + { + if (_logDateFormat!=null) + { + _logDateCache = new DateCache(_logDateFormat, _logLocale); + _logDateCache.setTimeZoneID(_logTimeZone); + } + + if (_filename != null) + { + _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null); + _closeOut = true; + Log.info("Opened "+getDatedFilename()); + } + else + _fileOut = System.err; + + _out = _fileOut; + + if (_ignorePaths != null && _ignorePaths.length > 0) + { + _ignorePathMap = new PathMap(); + for (int i = 0; i < _ignorePaths.length; i++) + _ignorePathMap.put(_ignorePaths[i], _ignorePaths[i]); + } + else + _ignorePathMap = null; + + _writer = new OutputStreamWriter(_out); + _buffers = new ArrayList(); + _copy = new char[1024]; + super.doStart(); + } + + /* ------------------------------------------------------------ */ + protected void doStop() throws Exception + { + super.doStop(); + try {if (_writer != null) _writer.flush();} catch (IOException e) {Log.ignore(e);} + if (_out != null && _closeOut) + try {_out.close();} catch (IOException e) {Log.ignore(e);} + + _out = null; + _fileOut = null; + _closeOut = false; + _logDateCache = null; + _writer = null; + _buffers = null; + _copy = null; + } + + /* ------------------------------------------------------------ */ + /** + * @return the log File Date Format + */ + public String getFilenameDateFormat() + { + return _filenameDateFormat; + } + + /* ------------------------------------------------------------ */ + /** Set the log file date format. + * @see {@link RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)} + * @param logFileDateFormat the logFileDateFormat to pass to {@link RolloverFileOutputStream} + */ + public void setFilenameDateFormat(String logFileDateFormat) + { + _filenameDateFormat=logFileDateFormat; } } -