KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > NCSARequestLog


1 // ========================================================================
2
// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
3
// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17
18 import java.io.IOException JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.io.OutputStreamWriter JavaDoc;
21 import java.io.Writer JavaDoc;
22 import java.util.Locale JavaDoc;
23 import java.util.TimeZone JavaDoc;
24
25 import javax.servlet.http.Cookie JavaDoc;
26
27 import org.apache.commons.logging.Log;
28 import org.mortbay.log.LogFactory;
29 import org.mortbay.util.DateCache;
30 import org.mortbay.util.LogSupport;
31 import org.mortbay.util.RolloverFileOutputStream;
32 import org.mortbay.util.StringUtil;
33
34
35 /* ------------------------------------------------------------ */
36 /** NCSA HTTP Request Log.
37  * NCSA common or NCSA extended (combined) request log.
38  * @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
39  * @author Tony Thompson
40  * @author Greg Wilkins
41  */

42 public class NCSARequestLog implements RequestLog
43 {
44     private static Log log = LogFactory.getLog(NCSARequestLog.class);
45
46     private String JavaDoc _filename;
47     private boolean _extended;
48     private boolean _append;
49     private int _retainDays;
50     private boolean _closeOut;
51     private boolean _preferProxiedForAddress;
52     private String JavaDoc _logDateFormat="dd/MMM/yyyy:HH:mm:ss ZZZ";
53     private Locale JavaDoc _logLocale=Locale.getDefault();
54     private String JavaDoc _logTimeZone=TimeZone.getDefault().getID();
55     private String JavaDoc[] _ignorePaths;
56     private boolean _logLatency=false;
57     private boolean _logCookies=false;
58     
59     private transient OutputStream JavaDoc _out;
60     private transient OutputStream JavaDoc _fileOut;
61     private transient DateCache _logDateCache;
62     private transient PathMap _ignorePathMap;
63     private transient Writer JavaDoc _writer;
64     
65     /* ------------------------------------------------------------ */
66     /** Constructor.
67      */

68     public NCSARequestLog()
69     {
70         _extended=true;
71         _append=true;
72         _retainDays=31;
73     }
74     
75     /* ------------------------------------------------------------ */
76     /** Constructor.
77      * @param filename Filename, which can be in
78      * rolloverFileOutputStream format
79      * @see org.mortbay.util.RolloverFileOutputStream
80      * @exception IOException
81      */

82     public NCSARequestLog(String JavaDoc filename)
83         throws IOException JavaDoc
84     {
85         _extended=true;
86         _append=true;
87         _retainDays=31;
88         setFilename(filename);
89     }
90
91     /* ------------------------------------------------------------ */
92     /** Set the log filename.
93      * @see NCSARequestLog#setRetainDays(int)
94      * @param filename The filename to use. If the filename contains the
95      * string "yyyy_mm_dd", then a RolloverFileOutputStream is used and the
96      * log is rolled over nightly and aged according setRetainDays. If no
97      * filename is set or a null filename
98      * passed, then requests are logged to System.err.
99      */

100     public void setFilename(String JavaDoc filename)
101     {
102         if (filename!=null)
103         {
104             filename=filename.trim();
105             if (filename.length()==0)
106                 filename=null;
107         }
108         _filename=filename;
109     }
110
111     /* ------------------------------------------------------------ */
112     /** Get the log filename.
113      * @see NCSARequestLog#getDatedFilename()
114      * @return The log filename without any date expansion.
115      */

116     public String JavaDoc getFilename()
117     {
118         return _filename;
119     }
120
121     /* ------------------------------------------------------------ */
122     /** Get the dated log filename.
123      * @see NCSARequestLog#getFilename()
124      * @return The log filename with any date encoding expanded.
125      */

126     public String JavaDoc getDatedFilename()
127     {
128         if (_fileOut instanceof RolloverFileOutputStream)
129             return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
130         return null;
131     }
132     
133     
134     /* ------------------------------------------------------------ */
135     /**
136      * @param format The date format to use within the log file.
137      */

138     public void setLogDateFormat(String JavaDoc format)
139     {
140         _logDateFormat=format;
141     }
142
143     /* ------------------------------------------------------------ */
144     /**
145      * @return The date format to use within the log file.
146      */

147     public String JavaDoc getLogDateFormat()
148     {
149         return _logDateFormat;
150     }
151     
152     /* ------------------------------------------------------------ */
153     /**
154      * @param tz The date format timezone to use within the log file.
155      */

156     public void setLogTimeZone(String JavaDoc tz)
157     {
158         _logTimeZone=tz;
159     }
160
161     /* ------------------------------------------------------------ */
162     /**
163      * @return The date format timezone to use within the log file.
164      */

165     public String JavaDoc getLogTimeZone()
166     {
167         return _logTimeZone;
168     }
169     
170     /* ------------------------------------------------------------ */
171     /**
172      * @return The number of days to retain rollovered log files.
173      */

174     public int getRetainDays()
175     {
176         return _retainDays;
177     }
178
179     /* ------------------------------------------------------------ */
180     /**
181      * @param retainDays The number of days to retain rollovered log files.
182      */

183     public void setRetainDays(int retainDays)
184     {
185         _retainDays = retainDays;
186     }
187
188     /* ------------------------------------------------------------ */
189     /**
190      * @return True if NCSA extended format is to be used.
191      */

192     public boolean isExtended()
193     {
194         return _extended;
195     }
196
197     /* ------------------------------------------------------------ */
198     /**
199      * @param e True if NCSA extended format is to be used.
200      */

201     public void setExtended(boolean e)
202     {
203         _extended=e;
204     }
205     
206     /* ------------------------------------------------------------ */
207     /**
208      * @return True if logs are appended to existing log files.
209      */

210     public boolean isAppend()
211     {
212         return _append;
213     }
214
215     /* ------------------------------------------------------------ */
216     /**
217      * @param a True if logs are appended to existing log files.
218      */

219     public void setAppend(boolean a)
220     {
221         _append=a;
222     }
223     
224     /* ------------------------------------------------------------ */
225     /**
226      * @deprecated ignored
227      */

228     public void setBuffered(boolean b)
229     {}
230     
231     /* ------------------------------------------------------------ */
232     /** Set which paths to ignore.
233      *
234      * @param ignorePaths Array of path specifications to ignore
235      */

236     public void setIgnorePaths(String JavaDoc[] ignorePaths)
237     {
238         // Contributed by Martin Vilcans (martin@jadestone.se)
239
_ignorePaths = ignorePaths;
240     }
241
242     /* ------------------------------------------------------------ */
243     public String JavaDoc[] getIgnorePaths()
244     {
245         return _ignorePaths;
246     }
247
248     /* ------------------------------------------------------------ */
249     /**
250      * @return Returns the logCookies.
251      */

252     public boolean getLogCookies()
253     {
254         return _logCookies;
255     }
256     /* ------------------------------------------------------------ */
257     /**
258      * @param logCookies The logCookies to set.
259      */

260     public void setLogCookies(boolean logCookies)
261     {
262         _logCookies = logCookies;
263     }
264     
265     /* ------------------------------------------------------------ */
266     /**
267      * @return Returns true if logging latency
268      */

269     public boolean getLogLatency()
270     {
271         return _logLatency;
272     }
273     
274     /* ------------------------------------------------------------ */
275     /**
276      * @param logLatency If true, latency is logged at the end of the log line
277      */

278     public void setLogLatency(boolean logLatency)
279     {
280         _logLatency = logLatency;
281     }
282     
283     /* ------------------------------------------------------------ */
284     /**
285     * Prefer to log the proxied-for IP address (if present in
286     * the request header) over the native requester IP address.
287     * Useful in reverse-proxy situations when you'd rather see
288     * the IP address of the host before the most recent proxy
289     * server, as opposed to your own proxy server(s) every time.
290     *
291     * jlrobins@socialserve.com, March 2004.
292     **/

293     public void setPreferProxiedForAddress(boolean value)
294     {
295        _preferProxiedForAddress = value;
296     }
297     
298     /* ------------------------------------------------------------ */
299     public void start()
300         throws Exception JavaDoc
301     {
302         _logDateCache=new DateCache(_logDateFormat,_logLocale);
303         _logDateCache.setTimeZoneID(_logTimeZone);
304         
305         if (_filename != null)
306         {
307             _fileOut=new RolloverFileOutputStream(_filename,_append,_retainDays);
308             _closeOut=true;
309         }
310         else
311             _fileOut=System.err;
312
313         _out=_fileOut;
314
315         if (_ignorePaths!=null && _ignorePaths.length>0)
316         {
317             _ignorePathMap=new PathMap();
318             for (int i=0;i<_ignorePaths.length;i++)
319                 _ignorePathMap.put(_ignorePaths[i],_ignorePaths[i]);
320         }
321         else
322             _ignorePathMap=null;
323
324         _writer=new OutputStreamWriter JavaDoc(_out);
325     }
326
327     /* ------------------------------------------------------------ */
328     public boolean isStarted()
329     {
330         return _fileOut!=null;
331     }
332     
333     /* ------------------------------------------------------------ */
334     public void stop()
335     {
336         try{if (_writer!=null)_writer.flush();} catch (IOException JavaDoc e){LogSupport.ignore(log,e);}
337         if (_out!=null && _closeOut)
338             try{_out.close();}catch(IOException JavaDoc e){LogSupport.ignore(log,e);}
339         _out=null;
340         _fileOut=null;
341         _closeOut=false;
342         _logDateCache=null;
343         _writer=null;
344     }
345     
346     /* ------------------------------------------------------------ */
347     /** Log a request.
348      * @param request The request
349      * @param response The response to this request.
350      * @param responseLength The bytes written to the response.
351      */

352     public void log(HttpRequest request,
353                     HttpResponse response,
354                     int responseLength)
355     {
356         try{
357             // ignore ignorables
358
if (_ignorePathMap != null &&
359                 _ignorePathMap.getMatch(request.getPath()) != null)
360                 return;
361
362             // log the rest
363
if (_fileOut==null)
364                 return;
365
366             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(160);
367             
368             String JavaDoc addr = null;
369             if(_preferProxiedForAddress)
370             {
371                 // If header is not present, addr will remain null ...
372
addr = request.getField(HttpFields.__XForwardedFor);
373             }
374             if(addr == null)
375                 addr = request.getRemoteAddr();
376             buf.append(addr);
377             
378             buf.append(" - ");
379             String JavaDoc user = request.getAuthUser();
380             buf.append((user==null)?"-":user);
381             buf.append(" [");
382             buf.append(_logDateCache.format(request.getTimeStamp()));
383             buf.append("] \"");
384             buf.append(request.getMethod());
385             buf.append(' ');
386             buf.append(request.getURI());
387             buf.append(' ');
388             buf.append(request.getVersion());
389             buf.append("\" ");
390             int status=response.getStatus();
391             buf.append((char)('0'+((status/100)%10)));
392             buf.append((char)('0'+((status/10)%10)));
393             buf.append((char)('0'+(status%10)));
394             if (responseLength>=0)
395             {
396                 buf.append(' ');
397                 if (responseLength>99999)
398                     buf.append(Integer.toString(responseLength));
399                 else
400                 {
401                     if (responseLength>9999)
402                         buf.append((char)('0'+((responseLength/10000)%10)));
403                     if (responseLength>999)
404                         buf.append((char)('0'+((responseLength/1000)%10)));
405                     if (responseLength>99)
406                         buf.append((char)('0'+((responseLength/100)%10)));
407                     if (responseLength>9)
408                         buf.append((char)('0'+((responseLength/10)%10)));
409                     buf.append((char)('0'+(responseLength%10)));
410                 }
411                 buf.append(' ');
412             }
413             else
414                 buf.append(" - ");
415
416             String JavaDoc log =buf.toString();
417             synchronized(_writer)
418             {
419                 _writer.write(log);
420                 if (_extended)
421                 {
422                     logExtended(request,response,_writer);
423                     if (!_logCookies)
424                         _writer.write(" -");
425                 }
426                 
427                 if (_logCookies)
428                 {
429                     Cookie JavaDoc[] cookies = request.getCookies();
430                     if (cookies==null || cookies.length==0)
431                         _writer.write(" -");
432                     else
433                     {
434                         _writer.write(" \"");
435                         for (int i=0;i<cookies.length;i++)
436                         {
437                             if (i!=0)
438                                 _writer.write(';');
439                             _writer.write(cookies[i].getName());
440                             _writer.write('=');
441                             _writer.write(cookies[i].getValue());
442                         }
443                         _writer.write("\"");
444                     }
445                 }
446                 
447                 if (_logLatency)
448                     _writer.write(" "+(System.currentTimeMillis()-request.getTimeStamp()));
449                 
450                 _writer.write(StringUtil.__LINE_SEPARATOR);
451                 _writer.flush();
452             }
453         }
454         catch(IOException JavaDoc e)
455         {
456             log.warn(LogSupport.EXCEPTION,e);
457         }
458     }
459
460     /* ------------------------------------------------------------ */
461     /** Log Extended fields.
462      * This method can be extended by a derived class to add extened fields to
463      * each log entry. It is called by the log method after all standard
464      * fields have been added, but before the line terminator.
465      * Derived implementations should write extra fields to the Writer
466      * provided.
467      * The default implementation writes the referer and user agent.
468      * @param request The request to log.
469      * @param response The response to log.
470      * @param log The writer to write the extra fields to.
471      * @exception IOException Problem writing log
472      */

473     protected void logExtended(HttpRequest request,
474                                HttpResponse response,
475                                Writer JavaDoc log)
476         throws IOException JavaDoc
477     {
478         String JavaDoc referer = request.getField(HttpFields.__Referer);
479         if(referer==null)
480             log.write("\"-\" ");
481         else
482         {
483             log.write('"');
484             log.write(referer);
485             log.write("\" ");
486         }
487         
488         String JavaDoc agent = request.getField(HttpFields.__UserAgent);
489         if(agent==null)
490             log.write("\"-\"");
491         else
492         {
493             log.write('"');
494             log.write(agent);
495             log.write('"');
496         }
497         
498
499     }
500 }
501
502
Popular Tags