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.4
Committed: Mon Jan 22 12:01:46 2001 UTC (23 years, 3 months ago) by tdb
Branch: MAIN
Changes since 1.3: +3 -3 lines
Log Message:
*** empty log message ***

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: ajm4 $
21 * @version $Id: FileLogger.java,v 1.3 2000/12/12 18:28:19 ajm4 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.3 $";
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 // Check to make sure file is open
87 if(open){
88 // Produce a nicely formatted line for the logfile
89 String line = formatLogLine(source, message);
90 try{
91 // We have to synchronize here due to problems with two write()'s being called before a newLine()
92 synchronized(writer){
93 // Attempt to write the line
94 writer.write(line);
95 // Best to use newLine() as it will use the correct platform encoding
96 writer.newLine();
97 }
98 // Make sure the line is written immeidiately
99 writer.flush();
100 }
101 catch(IOException e){
102 // We'd best log the error
103 System.out.println(formatLogLine(this.toString(), "Writing to logfile failed - " + e.getMessage()));
104 // As it's an IOException we should suspend logging
105 open = false;
106 }
107 }
108 else{
109 // If file is not open we should print this to the screen
110 System.out.println(formatLogLine(this.toString(), "Write failed - file not open"));
111 }
112 }
113
114 /**
115 * The clear() method erases the contents of the logfile. It does
116 * this in a very clumsy way - by closing the writer and opening a
117 * new one which is set not to append. This results in the logfile
118 * being overwritten, which effectively erases it.
119 */
120 public void clear(){
121 // Check file is open
122 if(open){
123 write(toString(), Logger.SYSMSG, "Attempting to clear logfile");
124 try{
125 // Close appending writer
126 open = false;
127 writer.close();
128 // Open a non-appending writer
129 writer = new BufferedWriter(new FileWriter(filename));
130 open = true;
131 }
132 catch(IOException e){
133 // We'd best log the error
134 write(toString(), Logger.ERROR, "Attempt to clear logfile failed - "+e.getMessage());
135 // As it's an IOException we should suspend logging
136 open = false;
137 }
138 }
139 else{
140 // If file is not open we should print this to the screen
141 System.out.println(formatLogLine(toString(), "Clearing failed - file not open"));
142 }
143 }
144
145 /**
146 * The close() method closes the logfile and no more data can be written.
147 * If writing is attempted after close() has been called an error will be
148 * generated. The open() method can be used to reopen or open a new file.
149 */
150 public void close(){
151 // Check to see if a file is open
152 if(open){
153 write(toString(), Logger.SYSMSG, "Attempting to terminate logging");
154 try{
155 open = false;
156 writer.close();
157 }
158 catch(IOException e){
159 write(toString(), Logger.ERROR, "Attempt to close logfile failed - " + e.getMessage());
160 // As it's an IOException we should suspend logging
161 open = false;
162 }
163 }
164 else{
165 // If file is not open we should print this to the screen
166 System.out.println(formatLogLine(toString(), "Close failed - file not open"));
167 }
168 }
169
170 /**
171 * The open() method opens a new file after the close() method has
172 * been called on the FileLog. This enables the user to easily change
173 * the file to which the log is being written. An error is generated
174 * if a file is already open.
175 *
176 * @param filename The new file to write to.
177 * @throws IOException if the file cannot be written to.
178 */
179 public void open(String filename) throws IOException{
180 // Check to see if a file is open
181 if(open){
182 // If file is already open then we should log that this went wrong
183 write(this.toString(), Logger.WARNING, "Open failed - a file is already open");
184 }
185 else{
186 this.filename = filename;
187 if(!fileCheck()) {
188 // Have to system.out.println errors because logging mechanism failed !
189 System.out.println(formatLogLine(toString(), "File check failed, construction terminated"));
190 throw new IOException("File check failed, unable to create FileLog");
191 }
192 try{
193 // Setup the writer
194 writer = new BufferedWriter(new FileWriter(filename, true));
195 // File is now open
196 open = true;
197 }
198 catch(IOException e){
199 System.out.println(formatLogLine(toString(), "Attempt to open writer failed - " + e.getMessage()));
200 }
201 }
202 }
203
204 /**
205 * The suspend() method halts writing to the file by setting the open
206 * boolean to false, and thus blocking the write() method. A line is
207 * written to the logfile beforehand to note that writing has been
208 * suspended.
209 */
210 public void suspend(){
211 // Check to see if a file is open
212 if(open){
213 // Make a note of the fact that writing has been suspended
214 write(toString(), Logger.SYSMSG, "Writing suspended");
215 // Make sure writing not permitted
216 open=false;
217 }
218 else{
219 // If file is not open we should print this to the screen
220 System.out.println(formatLogLine(toString(), "Suspend failed - file not open"));
221 }
222 }
223
224 /**
225 * The resume() method resumes writing to the file by setting the open
226 * boolean to true. A line is written to the logfile to signify this
227 * event occuring.
228 */
229 public void resume(){
230 // Check to see if a file is open
231 if(open){
232 // If file is open we should print this to the screen
233 System.out.println(formatLogLine(toString(), "Resume failed - file open"));
234 }
235 else{
236 // Permit writing again
237 open=true;
238 // Make a note of the fact that writing has been resumed
239 write(toString(), Logger.SYSMSG, "Writing resumed");
240 }
241 }
242
243 /**
244 * Overrides the {@link java.lang.Object#toString() Object.toString()}
245 * method to provide clean logging (every class should have this).
246 *
247 * This uses the uk.ac.ukc.iscream.util.FormatName class
248 * to format the toString()
249 *
250 * @return the name of this class and its CVS revision
251 */
252 public String toString() {
253 return FormatName.getName(
254 _name,
255 getClass().getName(),
256 REVISION);
257 }
258
259 //---PRIVATE METHODS---
260
261 /**
262 * This method generates a nicely formatted line for the log,
263 * including the date/time and the source of the message. The date
264 * and time are formatted using the DateFormat class, and the source
265 * class is formatted using the toString() method found in every
266 * source file. This is then prepended to the message and returned.
267 *
268 * @param source A string representation of the calling object.
269 * @param message The message to be logged.
270 * @return The string to be written to the log.
271 */
272 private String formatLogLine(String source, String message){
273 String date = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).format(new Date());
274 return "[" + date + "] " + source + ": " + message;
275 }
276
277 /**
278 * The fileCheck() method is used to ensure that writing is ok. It
279 * performs so basic checks to make sure that if the file exists
280 * it can be written to, and if not a new file is created. A boolean
281 * result is returned to signify success or failure.
282 *
283 * @return A boolean value signify whether the test was sucessful.
284 */
285 private boolean fileCheck(){
286 boolean fileOK = false;
287 try{
288 File file = new File(filename);
289
290 // File already exists
291 if(file.exists()) {
292 /* Only want success if it is a file (not a directory)
293 * and can be written to.
294 */
295 if(file.isFile() && file.canWrite()) {
296 fileOK = true;
297 }
298 }
299 // Create a new file and suceed
300 else{
301 file.createNewFile();
302 fileOK = true;
303 }
304 }
305 catch(IOException e){
306 System.out.println(formatLogLine(toString(), "File check failed - "+e.getMessage()));
307 }
308
309 return fileOK;
310 }
311
312 //---ACCESSOR/MUTATOR METHODS---
313
314 //---ATTRIBUTES---
315
316 /**
317 * The filename of the currently open, or last open, file.
318 */
319 private String filename;
320
321 /**
322 * The verbosity level of this instance
323 */
324 private int _verbosityLevel;
325
326 /**
327 * A reference to the writer being used.
328 */
329 private BufferedWriter writer;
330
331 /**
332 * A boolean signifying whether a file is open or not.
333 */
334 private boolean open = false;
335
336 /**
337 * This is the friendly identifier of the
338 * component this class is running in.
339 * eg, a Filter may be called "filter1",
340 * If this class does not have an owning
341 * component, a name from the configuration
342 * can be placed here. This name could also
343 * be changed to null for utility classes.
344 */
345 private String _name = Core.NAME;
346
347 //---STATIC ATTRIBUTES---
348
349 }