1 //
2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.OutputStreamWriter;
24 import java.io.Writer;
25 import java.util.TimeZone;
26
27 import org.eclipse.jetty.util.RolloverFileOutputStream;
28 import org.eclipse.jetty.util.StringUtil;
29 import org.eclipse.jetty.util.annotation.ManagedAttribute;
30 import org.eclipse.jetty.util.annotation.ManagedObject;
31
32 /**
33 * This {@link RequestLog} implementation outputs logs in the pseudo-standard
34 * NCSA common log format. Configuration options allow a choice between the
35 * standard Common Log Format (as used in the 3 log format) and the Combined Log
36 * Format (single log format). This log format can be output by most web
37 * servers, and almost all web log analysis software can understand these
38 * formats.
39 */
40 @ManagedObject("NCSA standard format request log")
41 public class NCSARequestLog extends AbstractNCSARequestLog
42 {
43 private String _filename;
44 private boolean _append;
45 private int _retainDays;
46 private boolean _closeOut;
47 private String _filenameDateFormat = null;
48 private transient OutputStream _out;
49 private transient OutputStream _fileOut;
50 private transient Writer _writer;
51
52 /* ------------------------------------------------------------ */
53 /**
54 * Create request log object with default settings.
55 */
56 public NCSARequestLog()
57 {
58 setExtended(true);
59 _append = true;
60 _retainDays = 31;
61 }
62
63 /* ------------------------------------------------------------ */
64 /**
65 * Create request log object with specified output file name.
66 *
67 * @param filename the file name for the request log.
68 * This may be in the format expected
69 * by {@link RolloverFileOutputStream}
70 */
71 public NCSARequestLog(String filename)
72 {
73 setExtended(true);
74 _append = true;
75 _retainDays = 31;
76 setFilename(filename);
77 }
78
79 /* ------------------------------------------------------------ */
80 /**
81 * Set the output file name of the request log.
82 * The file name may be in the format expected by
83 * {@link RolloverFileOutputStream}.
84 *
85 * @param filename file name of the request log
86 *
87 */
88 public void setFilename(String filename)
89 {
90 if (filename != null)
91 {
92 filename = filename.trim();
93 if (filename.length() == 0)
94 filename = null;
95 }
96 _filename = filename;
97 }
98
99 /* ------------------------------------------------------------ */
100 /**
101 * Retrieve the output file name of the request log.
102 *
103 * @return file name of the request log
104 */
105 @ManagedAttribute("file of log")
106 public String getFilename()
107 {
108 return _filename;
109 }
110
111 /* ------------------------------------------------------------ */
112 /**
113 * Retrieve the file name of the request log with the expanded
114 * date wildcard if the output is written to the disk using
115 * {@link RolloverFileOutputStream}.
116 *
117 * @return file name of the request log, or null if not applicable
118 */
119 public String getDatedFilename()
120 {
121 if (_fileOut instanceof RolloverFileOutputStream)
122 return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
123 return null;
124 }
125
126 /* ------------------------------------------------------------ */
127 @Override
128 protected boolean isEnabled()
129 {
130 return (_fileOut != null);
131 }
132
133 /* ------------------------------------------------------------ */
134 /**
135 * Set the number of days before rotated log files are deleted.
136 *
137 * @param retainDays number of days to keep a log file
138 */
139 public void setRetainDays(int retainDays)
140 {
141 _retainDays = retainDays;
142 }
143
144 /* ------------------------------------------------------------ */
145 /**
146 * Retrieve the number of days before rotated log files are deleted.
147 *
148 * @return number of days to keep a log file
149 */
150 @ManagedAttribute("number of days that log files are kept")
151 public int getRetainDays()
152 {
153 return _retainDays;
154 }
155
156 /* ------------------------------------------------------------ */
157 /**
158 * Set append to log flag.
159 *
160 * @param append true - request log file will be appended after restart,
161 * false - request log file will be overwritten after restart
162 */
163 public void setAppend(boolean append)
164 {
165 _append = append;
166 }
167
168 /* ------------------------------------------------------------ */
169 /**
170 * Retrieve append to log flag.
171 *
172 * @return value of the flag
173 */
174 @ManagedAttribute("existing log files are appends to the new one")
175 public boolean isAppend()
176 {
177 return _append;
178 }
179
180 /* ------------------------------------------------------------ */
181 /**
182 * Set the log file name date format.
183 * @see RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
184 *
185 * @param logFileDateFormat format string that is passed to {@link RolloverFileOutputStream}
186 */
187 public void setFilenameDateFormat(String logFileDateFormat)
188 {
189 _filenameDateFormat = logFileDateFormat;
190 }
191
192 /* ------------------------------------------------------------ */
193 /**
194 * Retrieve the file name date format string.
195 *
196 * @return the log File Date Format
197 */
198 public String getFilenameDateFormat()
199 {
200 return _filenameDateFormat;
201 }
202
203 /* ------------------------------------------------------------ */
204 @Override
205 public void write(String requestEntry) throws IOException
206 {
207 synchronized(this)
208 {
209 if (_writer==null)
210 return;
211 _writer.write(requestEntry);
212 _writer.write(StringUtil.__LINE_SEPARATOR);
213 _writer.flush();
214 }
215 }
216
217 /* ------------------------------------------------------------ */
218 /**
219 * Set up request logging and open log file.
220 *
221 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
222 */
223 @Override
224 protected synchronized void doStart() throws Exception
225 {
226 if (_filename != null)
227 {
228 _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(getLogTimeZone()),_filenameDateFormat,null);
229 _closeOut = true;
230 LOG.info("Opened " + getDatedFilename());
231 }
232 else
233 _fileOut = System.err;
234
235 _out = _fileOut;
236
237 synchronized(this)
238 {
239 _writer = new OutputStreamWriter(_out);
240 }
241 super.doStart();
242 }
243
244 /* ------------------------------------------------------------ */
245 /**
246 * Close the log file and perform cleanup.
247 *
248 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
249 */
250 @Override
251 protected void doStop() throws Exception
252 {
253 synchronized (this)
254 {
255 super.doStop();
256 try
257 {
258 if (_writer != null)
259 _writer.flush();
260 }
261 catch (IOException e)
262 {
263 LOG.ignore(e);
264 }
265 if (_out != null && _closeOut)
266 try
267 {
268 _out.close();
269 }
270 catch (IOException e)
271 {
272 LOG.ignore(e);
273 }
274
275 _out = null;
276 _fileOut = null;
277 _closeOut = false;
278 _writer = null;
279 }
280 }
281 }