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.6
Committed: Sun Feb 25 20:34:16 2001 UTC (23 years, 2 months ago) by tdb
Branch: MAIN
Changes since 1.5: +41 -63 lines
Log Message:
Big change in the logging structure. The line is now generated in an external
class, FormatName (in the util package), and the verbosity checking is carried
out in the LoggerServant instead of each logger.
This change was made to try and have behaviour in one place, rather than in each
individual logger.

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