ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/core/loggers/FileLogger.java
Revision: 1.5
Committed: Sun Jan 28 19:57:59 2001 UTC (23 years, 3 months ago) by tdb
Branch: MAIN
Changes since 1.4: +31 -29 lines
Log Message:
A stupid verbosity level checking bug.

File Contents

# Content
1 //---PACKAGE DECLARATION---
2 package uk.ac.ukc.iscream.core.loggers;
3
4 //---IMPORTS---
5 import uk.ac.ukc.iscream.util.*;
6 import uk.ac.ukc.iscream.core.*;
7 import java.util.Date;
8 import java.text.DateFormat;
9 import java.util.Locale;
10 import java.io.BufferedWriter;
11 import java.io.File;
12 import java.io.FileWriter;
13 import java.io.IOException;
14
15 /**
16 * The FileLogger is an implementation of the LoggerImpl defined
17 * in the associated interface. It provides quite extensive features to allow
18 * logging ot a text file.
19 *
20 * @author $Author: tdb1 $
21 * @version $Id: FileLogger.java,v 1.4 2001/01/22 12:01:46 tdb1 Exp $
22 */
23 public class FileLogger implements LoggerImpl {
24
25 //---FINAL ATTRIBUTES---
26
27 /**
28 * The current CVS revision of this class
29 */
30 public final String REVISION = "$Revision: 1.4 $";
31
32 //---STATIC METHODS---
33
34 //---CONSTRUCTORS---
35
36 /**
37 * Creates a new FileLogger.
38 *
39 * The constructor checks that writing will be ok, then sets up the
40 * writer. It makes use of the fileCheck() method found later on to
41 * ensure writing will be ok, and throws an IOException if there is
42 * a problem. Errors at this stage cannot be logged because the
43 * logging mechanism has not be setup completely, so any problems
44 * are printed to the screen in the same format used for logging.
45 *
46 * @throws IOException if there is a problem with the file check.
47 */
48 public FileLogger() throws IOException{
49 _verbosityLevel = Integer.parseInt(System.getProperty("uk.ac.ukc.iscream.Verbosity"));
50 filename = System.getProperty("uk.ac.ukc.iscream.LoggerClass.FileLogger.filename");
51 // Perform file check to make sure writing is ok
52 if(!fileCheck()){
53 // Have to system.out.println errors because logging mechanism failed !
54 System.out.println(formatLogLine(this.toString(), "File check failed, construction terminated"));
55 throw new IOException("File check failed, unable to create FileLog");
56 }
57 try{
58 // Setup the writer
59 writer = new BufferedWriter(new FileWriter(filename, true));
60 // File is now open
61 open = true;
62 }
63 catch(IOException e){
64 System.out.println(formatLogLine(toString(), "Attempt to setup writer failed - " + e.getMessage()));
65 }
66 // Put an initial line into the log
67 write(toString(), Logger.SYSINIT, "started");
68 write(toString(), Logger.SYSMSG, "using verbosity " + _verbosityLevel);
69 }
70
71 //---PUBLIC METHODS---
72
73 /**
74 * The write() method writes a line of log to the file, prepending
75 * it with some information about where to line came from and the
76 * date. This formatting is handled by the formatLogLine() method.
77 * There is some synchronisation here due to problems with the logfiles
78 * having multiple lines written on the same line, followed by dotted
79 * newlines in the wrong places. This is due to this method being
80 * called by multiple threads.
81 *
82 * @param source A string representation of the calling object.
83 * @param message The message to be logged.
84 */
85 public synchronized void write(String source, int verbosity, String message) {
86 if (verbosity <= _verbosityLevel) {
87 // Check to make sure file is open
88 if(open){
89 // Produce a nicely formatted line for the logfile
90 String line = formatLogLine(source, message);
91 try{
92 // We have to synchronize here due to problems with two write()'s being called before a newLine()
93 synchronized(writer){
94 // Attempt to write the line
95 writer.write(line);
96 // Best to use newLine() as it will use the correct platform encoding
97 writer.newLine();
98 }
99 // Make sure the line is written immeidiately
100 writer.flush();
101 }
102 catch(IOException e){
103 // We'd best log the error
104 System.out.println(formatLogLine(this.toString(), "Writing to logfile failed - " + e.getMessage()));
105 // As it's an IOException we should suspend logging
106 open = false;
107 }
108 }
109 else{
110 // If file is not open we should print this to the screen
111 System.out.println(formatLogLine(this.toString(), "Write failed - file not open"));
112 }
113 }
114 }
115
116 /**
117 * The clear() method erases the contents of the logfile. It does
118 * this in a very clumsy way - by closing the writer and opening a
119 * new one which is set not to append. This results in the logfile
120 * being overwritten, which effectively erases it.
121 */
122 public void clear(){
123 // Check file is open
124 if(open){
125 write(toString(), Logger.SYSMSG, "Attempting to clear logfile");
126 try{
127 // Close appending writer
128 open = false;
129 writer.close();
130 // Open a non-appending writer
131 writer = new BufferedWriter(new FileWriter(filename));
132 open = true;
133 }
134 catch(IOException e){
135 // We'd best log the error
136 write(toString(), Logger.ERROR, "Attempt to clear logfile failed - "+e.getMessage());
137 // As it's an IOException we should suspend logging
138 open = false;
139 }
140 }
141 else{
142 // If file is not open we should print this to the screen
143 System.out.println(formatLogLine(toString(), "Clearing failed - file not open"));
144 }
145 }
146
147 /**
148 * The close() method closes the logfile and no more data can be written.
149 * If writing is attempted after close() has been called an error will be
150 * generated. The open() method can be used to reopen or open a new file.
151 */
152 public void close(){
153 // Check to see if a file is open
154 if(open){
155 write(toString(), Logger.SYSMSG, "Attempting to terminate logging");
156 try{
157 open = false;
158 writer.close();
159 }
160 catch(IOException e){
161 write(toString(), Logger.ERROR, "Attempt to close logfile failed - " + e.getMessage());
162 // As it's an IOException we should suspend logging
163 open = false;
164 }
165 }
166 else{
167 // If file is not open we should print this to the screen
168 System.out.println(formatLogLine(toString(), "Close failed - file not open"));
169 }
170 }
171
172 /**
173 * The open() method opens a new file after the close() method has
174 * been called on the FileLog. This enables the user to easily change
175 * the file to which the log is being written. An error is generated
176 * if a file is already open.
177 *
178 * @param filename The new file to write to.
179 * @throws IOException if the file cannot be written to.
180 */
181 public void open(String filename) throws IOException{
182 // Check to see if a file is open
183 if(open){
184 // If file is already open then we should log that this went wrong
185 write(this.toString(), Logger.WARNING, "Open failed - a file is already open");
186 }
187 else{
188 this.filename = filename;
189 if(!fileCheck()) {
190 // Have to system.out.println errors because logging mechanism failed !
191 System.out.println(formatLogLine(toString(), "File check failed, construction terminated"));
192 throw new IOException("File check failed, unable to create FileLog");
193 }
194 try{
195 // Setup the writer
196 writer = new BufferedWriter(new FileWriter(filename, true));
197 // File is now open
198 open = true;
199 }
200 catch(IOException e){
201 System.out.println(formatLogLine(toString(), "Attempt to open writer failed - " + e.getMessage()));
202 }
203 }
204 }
205
206 /**
207 * The suspend() method halts writing to the file by setting the open
208 * boolean to false, and thus blocking the write() method. A line is
209 * written to the logfile beforehand to note that writing has been
210 * suspended.
211 */
212 public void suspend(){
213 // Check to see if a file is open
214 if(open){
215 // Make a note of the fact that writing has been suspended
216 write(toString(), Logger.SYSMSG, "Writing suspended");
217 // Make sure writing not permitted
218 open=false;
219 }
220 else{
221 // If file is not open we should print this to the screen
222 System.out.println(formatLogLine(toString(), "Suspend failed - file not open"));
223 }
224 }
225
226 /**
227 * The resume() method resumes writing to the file by setting the open
228 * boolean to true. A line is written to the logfile to signify this
229 * event occuring.
230 */
231 public void resume(){
232 // Check to see if a file is open
233 if(open){
234 // If file is open we should print this to the screen
235 System.out.println(formatLogLine(toString(), "Resume failed - file open"));
236 }
237 else{
238 // Permit writing again
239 open=true;
240 // Make a note of the fact that writing has been resumed
241 write(toString(), Logger.SYSMSG, "Writing resumed");
242 }
243 }
244
245 /**
246 * Overrides the {@link java.lang.Object#toString() Object.toString()}
247 * method to provide clean logging (every class should have this).
248 *
249 * This uses the uk.ac.ukc.iscream.util.FormatName class
250 * to format the toString()
251 *
252 * @return the name of this class and its CVS revision
253 */
254 public String toString() {
255 return FormatName.getName(
256 _name,
257 getClass().getName(),
258 REVISION);
259 }
260
261 //---PRIVATE METHODS---
262
263 /**
264 * This method generates a nicely formatted line for the log,
265 * including the date/time and the source of the message. The date
266 * and time are formatted using the DateFormat class, and the source
267 * class is formatted using the toString() method found in every
268 * source file. This is then prepended to the message and returned.
269 *
270 * @param source A string representation of the calling object.
271 * @param message The message to be logged.
272 * @return The string to be written to the log.
273 */
274 private String formatLogLine(String source, String message){
275 String date = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).format(new Date());
276 return "[" + date + "] " + source + ": " + message;
277 }
278
279 /**
280 * The fileCheck() method is used to ensure that writing is ok. It
281 * performs so basic checks to make sure that if the file exists
282 * it can be written to, and if not a new file is created. A boolean
283 * result is returned to signify success or failure.
284 *
285 * @return A boolean value signify whether the test was sucessful.
286 */
287 private boolean fileCheck(){
288 boolean fileOK = false;
289 try{
290 File file = new File(filename);
291
292 // File already exists
293 if(file.exists()) {
294 /* Only want success if it is a file (not a directory)
295 * and can be written to.
296 */
297 if(file.isFile() && file.canWrite()) {
298 fileOK = true;
299 }
300 }
301 // Create a new file and suceed
302 else{
303 file.createNewFile();
304 fileOK = true;
305 }
306 }
307 catch(IOException e){
308 System.out.println(formatLogLine(toString(), "File check failed - "+e.getMessage()));
309 }
310
311 return fileOK;
312 }
313
314 //---ACCESSOR/MUTATOR METHODS---
315
316 //---ATTRIBUTES---
317
318 /**
319 * The filename of the currently open, or last open, file.
320 */
321 private String filename;
322
323 /**
324 * The verbosity level of this instance
325 */
326 private int _verbosityLevel;
327
328 /**
329 * A reference to the writer being used.
330 */
331 private BufferedWriter writer;
332
333 /**
334 * A boolean signifying whether a file is open or not.
335 */
336 private boolean open = false;
337
338 /**
339 * This is the friendly identifier of the
340 * component this class is running in.
341 * eg, a Filter may be called "filter1",
342 * If this class does not have an owning
343 * component, a name from the configuration
344 * can be placed here. This name could also
345 * be changed to null for utility classes.
346 */
347 private String _name = Core.NAME;
348
349 //---STATIC ATTRIBUTES---
350
351 }