1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty;
16
17 import java.io.IOException;
18 import java.io.OutputStream;
19 import java.io.OutputStreamWriter;
20 import java.io.Writer;
21 import java.util.ArrayList;
22 import java.util.Locale;
23 import java.util.TimeZone;
24
25 import javax.servlet.http.Cookie;
26
27 import org.mortbay.component.AbstractLifeCycle;
28 import org.mortbay.jetty.servlet.PathMap;
29 import org.mortbay.log.Log;
30 import org.mortbay.util.DateCache;
31 import org.mortbay.util.RolloverFileOutputStream;
32 import org.mortbay.util.StringUtil;
33 import org.mortbay.util.TypeUtil;
34 import org.mortbay.util.Utf8StringBuffer;
35
36
37
38
39
40
41
42
43
44
45
46
47 public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
48 {
49 private String _filename;
50 private boolean _extended;
51 private boolean _append;
52 private int _retainDays;
53 private boolean _closeOut;
54 private boolean _preferProxiedForAddress;
55 private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss Z";
56 private String _filenameDateFormat = null;
57 private Locale _logLocale = Locale.getDefault();
58 private String _logTimeZone = "GMT";
59 private String[] _ignorePaths;
60 private boolean _logLatency = false;
61 private boolean _logCookies = false;
62 private boolean _logServer = false;
63
64 private transient OutputStream _out;
65 private transient OutputStream _fileOut;
66 private transient DateCache _logDateCache;
67 private transient PathMap _ignorePathMap;
68 private transient Writer _writer;
69 private transient ArrayList _buffers;
70 private transient char[] _copy;
71
72
73 public NCSARequestLog()
74 {
75 _extended = true;
76 _append = true;
77 _retainDays = 31;
78 }
79
80
81
82
83
84 public NCSARequestLog(String filename)
85 {
86 _extended = true;
87 _append = true;
88 _retainDays = 31;
89 setFilename(filename);
90 }
91
92
93
94
95
96 public void setFilename(String filename)
97 {
98 if (filename != null)
99 {
100 filename = filename.trim();
101 if (filename.length() == 0)
102 filename = null;
103 }
104 _filename = filename;
105 }
106
107 public String getFilename()
108 {
109 return _filename;
110 }
111
112 public String getDatedFilename()
113 {
114 if (_fileOut instanceof RolloverFileOutputStream)
115 return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
116 return null;
117 }
118
119
120
121
122
123
124 public void setLogDateFormat(String format)
125 {
126 _logDateFormat = format;
127 }
128
129 public String getLogDateFormat()
130 {
131 return _logDateFormat;
132 }
133
134 public void setLogLocale(Locale logLocale)
135 {
136 _logLocale = logLocale;
137 }
138
139 public Locale getLogLocale()
140 {
141 return _logLocale;
142 }
143
144 public void setLogTimeZone(String tz)
145 {
146 _logTimeZone = tz;
147 }
148
149 public String getLogTimeZone()
150 {
151 return _logTimeZone;
152 }
153
154 public void setRetainDays(int retainDays)
155 {
156 _retainDays = retainDays;
157 }
158
159 public int getRetainDays()
160 {
161 return _retainDays;
162 }
163
164 public void setExtended(boolean extended)
165 {
166 _extended = extended;
167 }
168
169 public boolean isExtended()
170 {
171 return _extended;
172 }
173
174 public void setAppend(boolean append)
175 {
176 _append = append;
177 }
178
179 public boolean isAppend()
180 {
181 return _append;
182 }
183
184 public void setIgnorePaths(String[] ignorePaths)
185 {
186 _ignorePaths = ignorePaths;
187 }
188
189 public String[] getIgnorePaths()
190 {
191 return _ignorePaths;
192 }
193
194 public void setLogCookies(boolean logCookies)
195 {
196 _logCookies = logCookies;
197 }
198
199 public boolean getLogCookies()
200 {
201 return _logCookies;
202 }
203
204 public boolean getLogServer()
205 {
206 return _logServer;
207 }
208
209 public void setLogServer(boolean logServer)
210 {
211 _logServer=logServer;
212 }
213
214 public void setLogLatency(boolean logLatency)
215 {
216 _logLatency = logLatency;
217 }
218
219 public boolean getLogLatency()
220 {
221 return _logLatency;
222 }
223
224 public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
225 {
226 _preferProxiedForAddress = preferProxiedForAddress;
227 }
228
229
230 public void log(Request request, Response response)
231 {
232 if (!isStarted())
233 return;
234
235 try
236 {
237 if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
238 return;
239
240 if (_fileOut == null)
241 return;
242
243 Utf8StringBuffer u8buf;
244 StringBuffer buf;
245 synchronized(_writer)
246 {
247 int size=_buffers.size();
248 u8buf = size==0?new Utf8StringBuffer(160):(Utf8StringBuffer)_buffers.remove(size-1);
249 buf = u8buf.getStringBuffer();
250 }
251
252 synchronized(buf)
253 {
254 if (_logServer)
255 {
256 buf.append(request.getServerName());
257 buf.append(' ');
258 }
259
260 String addr = null;
261 if (_preferProxiedForAddress)
262 {
263 addr = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
264 }
265
266 if (addr == null)
267 addr = request.getRemoteAddr();
268
269 buf.append(addr);
270 buf.append(" - ");
271 String user = request.getRemoteUser();
272 buf.append((user == null)? " - " : user);
273 buf.append(" [");
274 if (_logDateCache!=null)
275 buf.append(_logDateCache.format(request.getTimeStamp()));
276 else
277 buf.append(request.getTimeStampBuffer().toString());
278
279 buf.append("] \"");
280 buf.append(request.getMethod());
281 buf.append(' ');
282
283 request.getUri().writeTo(u8buf);
284
285 buf.append(' ');
286 buf.append(request.getProtocol());
287 buf.append("\" ");
288 int status = response.getStatus();
289 if (status<=0)
290 status=404;
291 buf.append((char)('0'+((status/100)%10)));
292 buf.append((char)('0'+((status/10)%10)));
293 buf.append((char)('0'+(status%10)));
294
295
296 long responseLength=response.getContentCount();
297 if (responseLength >=0)
298 {
299 buf.append(' ');
300 if (responseLength > 99999)
301 buf.append(Long.toString(responseLength));
302 else
303 {
304 if (responseLength > 9999)
305 buf.append((char)('0' + ((responseLength / 10000)%10)));
306 if (responseLength > 999)
307 buf.append((char)('0' + ((responseLength /1000)%10)));
308 if (responseLength > 99)
309 buf.append((char)('0' + ((responseLength / 100)%10)));
310 if (responseLength > 9)
311 buf.append((char)('0' + ((responseLength / 10)%10)));
312 buf.append((char)('0' + (responseLength)%10));
313 }
314 buf.append(' ');
315 }
316 else
317 buf.append(" - ");
318
319 }
320
321 if (!_extended && !_logCookies && !_logLatency)
322 {
323 synchronized(_writer)
324 {
325 buf.append(StringUtil.__LINE_SEPARATOR);
326 int l=buf.length();
327 if (l>_copy.length)
328 l=_copy.length;
329 buf.getChars(0,l,_copy,0);
330 _writer.write(_copy,0,l);
331 _writer.flush();
332 u8buf.reset();
333 _buffers.add(u8buf);
334 }
335 }
336 else
337 {
338 synchronized(_writer)
339 {
340 int l=buf.length();
341 if (l>_copy.length)
342 l=_copy.length;
343 buf.getChars(0,l,_copy,0);
344 _writer.write(_copy,0,l);
345 u8buf.reset();
346 _buffers.add(u8buf);
347
348
349 if (_extended)
350 logExtended(request, response, _writer);
351
352
353 if (_logCookies)
354 {
355 Cookie[] cookies = request.getCookies();
356 if (cookies == null || cookies.length == 0)
357 _writer.write(" -");
358 else
359 {
360 _writer.write(" \"");
361 for (int i = 0; i < cookies.length; i++)
362 {
363 if (i != 0)
364 _writer.write(';');
365 _writer.write(cookies[i].getName());
366 _writer.write('=');
367 _writer.write(cookies[i].getValue());
368 }
369 _writer.write('\"');
370 }
371 }
372
373 if (_logLatency)
374 {
375 _writer.write(' ');
376 _writer.write(TypeUtil.toString(System.currentTimeMillis() - request.getTimeStamp()));
377 }
378
379 _writer.write(StringUtil.__LINE_SEPARATOR);
380 _writer.flush();
381 }
382 }
383 }
384 catch (IOException e)
385 {
386 Log.warn(e);
387 }
388
389 }
390
391
392 protected void logExtended(Request request,
393 Response response,
394 Writer writer) throws IOException
395 {
396 String referer = request.getHeader(HttpHeaders.REFERER);
397 if (referer == null)
398 writer.write("\"-\" ");
399 else
400 {
401 writer.write('"');
402 writer.write(referer);
403 writer.write("\" ");
404 }
405
406 String agent = request.getHeader(HttpHeaders.USER_AGENT);
407 if (agent == null)
408 writer.write("\"-\" ");
409 else
410 {
411 writer.write('"');
412 writer.write(agent);
413 writer.write('"');
414 }
415 }
416
417
418 protected void doStart() throws Exception
419 {
420 if (_logDateFormat!=null)
421 {
422 _logDateCache = new DateCache(_logDateFormat, _logLocale);
423 _logDateCache.setTimeZoneID(_logTimeZone);
424 }
425
426 if (_filename != null)
427 {
428 _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null);
429 _closeOut = true;
430 Log.info("Opened "+getDatedFilename());
431 }
432 else
433 _fileOut = System.err;
434
435 _out = _fileOut;
436
437 if (_ignorePaths != null && _ignorePaths.length > 0)
438 {
439 _ignorePathMap = new PathMap();
440 for (int i = 0; i < _ignorePaths.length; i++)
441 _ignorePathMap.put(_ignorePaths[i], _ignorePaths[i]);
442 }
443 else
444 _ignorePathMap = null;
445
446 _writer = new OutputStreamWriter(_out);
447 _buffers = new ArrayList();
448 _copy = new char[1024];
449 super.doStart();
450 }
451
452
453 protected void doStop() throws Exception
454 {
455 super.doStop();
456 try {if (_writer != null) _writer.flush();} catch (IOException e) {Log.ignore(e);}
457 if (_out != null && _closeOut)
458 try {_out.close();} catch (IOException e) {Log.ignore(e);}
459
460 _out = null;
461 _fileOut = null;
462 _closeOut = false;
463 _logDateCache = null;
464 _writer = null;
465 _buffers = null;
466 _copy = null;
467 }
468
469
470
471
472
473 public String getFilenameDateFormat()
474 {
475 return _filenameDateFormat;
476 }
477
478
479
480
481
482
483 public void setFilenameDateFormat(String logFileDateFormat)
484 {
485 _filenameDateFormat=logFileDateFormat;
486 }
487
488 }