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
135 public void setLogTimeZone(String tz)
136 {
137 _logTimeZone = tz;
138 }
139
140 public String getLogTimeZone()
141 {
142 return _logTimeZone;
143 }
144
145 public void setRetainDays(int retainDays)
146 {
147 _retainDays = retainDays;
148 }
149
150 public int getRetainDays()
151 {
152 return _retainDays;
153 }
154
155 public void setExtended(boolean extended)
156 {
157 _extended = extended;
158 }
159
160 public boolean isExtended()
161 {
162 return _extended;
163 }
164
165 public void setAppend(boolean append)
166 {
167 _append = append;
168 }
169
170 public boolean isAppend()
171 {
172 return _append;
173 }
174
175 public void setIgnorePaths(String[] ignorePaths)
176 {
177 _ignorePaths = ignorePaths;
178 }
179
180 public String[] getIgnorePaths()
181 {
182 return _ignorePaths;
183 }
184
185 public void setLogCookies(boolean logCookies)
186 {
187 _logCookies = logCookies;
188 }
189
190 public boolean getLogCookies()
191 {
192 return _logCookies;
193 }
194
195 public boolean getLogServer()
196 {
197 return _logServer;
198 }
199
200 public void setLogServer(boolean logServer)
201 {
202 _logServer=logServer;
203 }
204
205 public void setLogLatency(boolean logLatency)
206 {
207 _logLatency = logLatency;
208 }
209
210 public boolean getLogLatency()
211 {
212 return _logLatency;
213 }
214
215 public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
216 {
217 _preferProxiedForAddress = preferProxiedForAddress;
218 }
219
220
221 public void log(Request request, Response response)
222 {
223 if (!isStarted())
224 return;
225
226 try
227 {
228 if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
229 return;
230
231 if (_fileOut == null)
232 return;
233
234 Utf8StringBuffer u8buf;
235 StringBuffer buf;
236 synchronized(_writer)
237 {
238 int size=_buffers.size();
239 u8buf = size==0?new Utf8StringBuffer(160):(Utf8StringBuffer)_buffers.remove(size-1);
240 buf = u8buf.getStringBuffer();
241 }
242
243 synchronized(buf)
244 {
245 if (_logServer)
246 {
247 buf.append(request.getServerName());
248 buf.append(' ');
249 }
250
251 String addr = null;
252 if (_preferProxiedForAddress)
253 {
254 addr = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
255 }
256
257 if (addr == null)
258 addr = request.getRemoteAddr();
259
260 buf.append(addr);
261 buf.append(" - ");
262 String user = request.getRemoteUser();
263 buf.append((user == null)? " - " : user);
264 buf.append(" [");
265 if (_logDateCache!=null)
266 buf.append(_logDateCache.format(request.getTimeStamp()));
267 else
268 buf.append(request.getTimeStampBuffer().toString());
269
270 buf.append("] \"");
271 buf.append(request.getMethod());
272 buf.append(' ');
273
274 request.getUri().writeTo(u8buf);
275
276 buf.append(' ');
277 buf.append(request.getProtocol());
278 buf.append("\" ");
279 int status = response.getStatus();
280 if (status<=0)
281 status=404;
282 buf.append((char)('0'+((status/100)%10)));
283 buf.append((char)('0'+((status/10)%10)));
284 buf.append((char)('0'+(status%10)));
285
286
287 long responseLength=response.getContentCount();
288 if (responseLength >=0)
289 {
290 buf.append(' ');
291 if (responseLength > 99999)
292 buf.append(Long.toString(responseLength));
293 else
294 {
295 if (responseLength > 9999)
296 buf.append((char)('0' + ((responseLength / 10000)%10)));
297 if (responseLength > 999)
298 buf.append((char)('0' + ((responseLength /1000)%10)));
299 if (responseLength > 99)
300 buf.append((char)('0' + ((responseLength / 100)%10)));
301 if (responseLength > 9)
302 buf.append((char)('0' + ((responseLength / 10)%10)));
303 buf.append((char)('0' + (responseLength)%10));
304 }
305 buf.append(' ');
306 }
307 else
308 buf.append(" - ");
309
310 }
311
312 if (!_extended && !_logCookies && !_logLatency)
313 {
314 synchronized(_writer)
315 {
316 buf.append(StringUtil.__LINE_SEPARATOR);
317 int l=buf.length();
318 if (l>_copy.length)
319 l=_copy.length;
320 buf.getChars(0,l,_copy,0);
321 _writer.write(_copy,0,l);
322 _writer.flush();
323 u8buf.reset();
324 _buffers.add(u8buf);
325 }
326 }
327 else
328 {
329 synchronized(_writer)
330 {
331 int l=buf.length();
332 if (l>_copy.length)
333 l=_copy.length;
334 buf.getChars(0,l,_copy,0);
335 _writer.write(_copy,0,l);
336 u8buf.reset();
337 _buffers.add(u8buf);
338
339
340 if (_extended)
341 logExtended(request, response, _writer);
342
343
344 if (_logCookies)
345 {
346 Cookie[] cookies = request.getCookies();
347 if (cookies == null || cookies.length == 0)
348 _writer.write(" -");
349 else
350 {
351 _writer.write(" \"");
352 for (int i = 0; i < cookies.length; i++)
353 {
354 if (i != 0)
355 _writer.write(';');
356 _writer.write(cookies[i].getName());
357 _writer.write('=');
358 _writer.write(cookies[i].getValue());
359 }
360 _writer.write('\"');
361 }
362 }
363
364 if (_logLatency)
365 {
366 _writer.write(' ');
367 _writer.write(TypeUtil.toString(System.currentTimeMillis() - request.getTimeStamp()));
368 }
369
370 _writer.write(StringUtil.__LINE_SEPARATOR);
371 _writer.flush();
372 }
373 }
374 }
375 catch (IOException e)
376 {
377 Log.warn(e);
378 }
379
380 }
381
382
383 protected void logExtended(Request request,
384 Response response,
385 Writer writer) throws IOException
386 {
387 String referer = request.getHeader(HttpHeaders.REFERER);
388 if (referer == null)
389 writer.write("\"-\" ");
390 else
391 {
392 writer.write('"');
393 writer.write(referer);
394 writer.write("\" ");
395 }
396
397 String agent = request.getHeader(HttpHeaders.USER_AGENT);
398 if (agent == null)
399 writer.write("\"-\" ");
400 else
401 {
402 writer.write('"');
403 writer.write(agent);
404 writer.write('"');
405 }
406 }
407
408
409 protected void doStart() throws Exception
410 {
411 if (_logDateFormat!=null)
412 {
413 _logDateCache = new DateCache(_logDateFormat, _logLocale);
414 _logDateCache.setTimeZoneID(_logTimeZone);
415 }
416
417 if (_filename != null)
418 {
419 _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null);
420 _closeOut = true;
421 Log.info("Opened "+getDatedFilename());
422 }
423 else
424 _fileOut = System.err;
425
426 _out = _fileOut;
427
428 if (_ignorePaths != null && _ignorePaths.length > 0)
429 {
430 _ignorePathMap = new PathMap();
431 for (int i = 0; i < _ignorePaths.length; i++)
432 _ignorePathMap.put(_ignorePaths[i], _ignorePaths[i]);
433 }
434 else
435 _ignorePathMap = null;
436
437 _writer = new OutputStreamWriter(_out);
438 _buffers = new ArrayList();
439 _copy = new char[1024];
440 super.doStart();
441 }
442
443
444 protected void doStop() throws Exception
445 {
446 super.doStop();
447 try {if (_writer != null) _writer.flush();} catch (IOException e) {Log.ignore(e);}
448 if (_out != null && _closeOut)
449 try {_out.close();} catch (IOException e) {Log.ignore(e);}
450
451 _out = null;
452 _fileOut = null;
453 _closeOut = false;
454 _logDateCache = null;
455 _writer = null;
456 _buffers = null;
457 _copy = null;
458 }
459
460
461
462
463
464 public String getFilenameDateFormat()
465 {
466 return _filenameDateFormat;
467 }
468
469
470
471
472
473
474 public void setFilenameDateFormat(String logFileDateFormat)
475 {
476 _filenameDateFormat=logFileDateFormat;
477 }
478
479 }