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

# User Rev Content
1 tdb 1.1 //---PACKAGE DECLARATION---
2 ajm 1.2 package uk.ac.ukc.iscream.core.loggers;
3 tdb 1.1
4     //---IMPORTS---
5 ajm 1.3 import uk.ac.ukc.iscream.util.*;
6     import uk.ac.ukc.iscream.core.*;
7 tdb 1.1 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 tdb 1.5 * @author $Author: tdb1 $
21 tdb 1.6 * @version $Id: FileLogger.java,v 1.5 2001/01/28 19:57:59 tdb1 Exp $
22 tdb 1.1 */
23 tdb 1.4 public class FileLogger implements LoggerImpl {
24 tdb 1.1
25     //---FINAL ATTRIBUTES---
26    
27     /**
28     * The current CVS revision of this class
29     */
30 tdb 1.6 public final String REVISION = "$Revision: 1.5 $";
31 tdb 1.1
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 ajm 1.3 filename = System.getProperty("uk.ac.ukc.iscream.LoggerClass.FileLogger.filename");
50 tdb 1.1 // Perform file check to make sure writing is ok
51     if(!fileCheck()){
52     // Have to system.out.println errors because logging mechanism failed !
53 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "File check failed, construction terminated"));
54 tdb 1.1 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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "Attempt to setup writer failed - " + e.getMessage()));
64 tdb 1.1 }
65     // Put an initial line into the log
66 ajm 1.3 write(toString(), Logger.SYSINIT, "started");
67 tdb 1.1 }
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 tdb 1.6 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 tdb 1.1 }
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 ajm 1.3 write(toString(), Logger.SYSMSG, "Attempting to clear logfile");
121 tdb 1.1 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 ajm 1.3 write(toString(), Logger.ERROR, "Attempt to clear logfile failed - "+e.getMessage());
132 tdb 1.1 // 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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "Clearing failed - file not open"));
139 tdb 1.1 }
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 ajm 1.3 write(toString(), Logger.SYSMSG, "Attempting to terminate logging");
151 tdb 1.1 try{
152     open = false;
153     writer.close();
154     }
155     catch(IOException e){
156 ajm 1.3 write(toString(), Logger.ERROR, "Attempt to close logfile failed - " + e.getMessage());
157 tdb 1.1 // 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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "Close failed - file not open"));
164 tdb 1.1 }
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 ajm 1.3 write(this.toString(), Logger.WARNING, "Open failed - a file is already open");
181 tdb 1.1 }
182     else{
183     this.filename = filename;
184     if(!fileCheck()) {
185     // Have to system.out.println errors because logging mechanism failed !
186 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "File check failed, construction terminated"));
187 tdb 1.1 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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "Attempt to open writer failed - " + e.getMessage()));
197 tdb 1.1 }
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 ajm 1.3 write(toString(), Logger.SYSMSG, "Writing suspended");
212 tdb 1.1 // 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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "Suspend failed - file not open"));
218 tdb 1.1 }
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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "Resume failed - file open"));
231 tdb 1.1 }
232     else{
233     // Permit writing again
234     open=true;
235     // Make a note of the fact that writing has been resumed
236 ajm 1.3 write(toString(), Logger.SYSMSG, "Writing resumed");
237 tdb 1.1 }
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 ajm 1.3 * This uses the uk.ac.ukc.iscream.util.FormatName class
245     * to format the toString()
246     *
247 tdb 1.1 * @return the name of this class and its CVS revision
248     */
249     public String toString() {
250 ajm 1.3 return FormatName.getName(
251     _name,
252     getClass().getName(),
253     REVISION);
254 tdb 1.1 }
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 tdb 1.6 System.out.println(FormatName.formatLogLine(this.toString(), Logger.FATAL, "File check failed - "+e.getMessage()));
288 tdb 1.1 }
289    
290     return fileOK;
291     }
292    
293 tdb 1.6 private void write(String source, int verbosity, String message) {
294     write(FormatName.formatLogLine(source, verbosity, message), verbosity);
295     }
296    
297 tdb 1.1 //---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 ajm 1.3
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 tdb 1.1
327     //---STATIC ATTRIBUTES---
328    
329     }