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.2
Committed: Wed Nov 29 21:27:25 2000 UTC (23 years, 5 months ago) by ajm
Branch: MAIN
Branch point for: SERVER_PACKAGEBUILD
Changes since 1.1: +5 -3 lines
Log Message:
Update for package move.

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.2 import uk.ac.ukc.iscream.core.LoggerImpl;
6     import uk.ac.ukc.iscream.core.Logger;
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 ajm 1.2 * @author $Author: tdb1 $
21     * @version $Id: FileLogger.java,v 1.1 2000/11/20 18:34:27 tdb1 Exp $
22 tdb 1.1 */
23     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.1 $";
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.LoggerClassParam1");
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(this.toString(), "Attemp to setup writer failed: "+e.getMessage()));
65     }
66     // Put an initial line into the log
67     write(this.toString(), Logger.SYSINIT, "started");
68     write(this.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(this.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(this.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(this.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(this.toString(), Logger.SYSMSG, "Attempting to terminate logging");
154     try{
155     open = false;
156     writer.close();
157     }
158     catch(IOException e){
159     write(this.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(this.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(this.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(this.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(this.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(this.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(this.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(this.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     * @return the name of this class and its CVS revision
248     */
249     public String toString() {
250     return this.getClass().getName() + "(" + REVISION.substring(11, REVISION.length() - 2) + ")";
251     }
252    
253     //---PRIVATE METHODS---
254    
255     /**
256     * This method generates a nicely formatted line for the log,
257     * including the date/time and the source of the message. The date
258     * and time are formatted using the DateFormat class, and the source
259     * class is formatted using the toString() method found in every
260     * source file. This is then prepended to the message and returned.
261     *
262     * @param source A string representation of the calling object.
263     * @param message The message to be logged.
264     * @return The string to be written to the log.
265     */
266     private String formatLogLine(String source, String message){
267     String date = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).format(new Date());
268     return "[" + date + "] " + source + ": " + message;
269     }
270    
271     /**
272     * The fileCheck() method is used to ensure that writing is ok. It
273     * performs so basic checks to make sure that if the file exists
274     * it can be written to, and if not a new file is created. A boolean
275     * result is returned to signify success or failure.
276     *
277     * @return A boolean value signify whether the test was sucessful.
278     */
279     private boolean fileCheck(){
280     boolean fileOK = false;
281     try{
282     File file = new File(filename);
283    
284     // File already exists
285     if(file.exists()) {
286     /* Only want success if it is a file (not a directory)
287     * and can be written to.
288     */
289     if(file.isFile() && file.canWrite()) {
290     fileOK = true;
291     }
292     }
293     // Create a new file and suceed
294     else{
295     file.createNewFile();
296     fileOK = true;
297     }
298     }
299     catch(IOException e){
300     System.out.println(formatLogLine(this.toString(), "File check failed: "+e.getMessage()));
301     }
302    
303     return fileOK;
304     }
305    
306     //---ACCESSOR/MUTATOR METHODS---
307    
308     //---ATTRIBUTES---
309    
310     /**
311     * The filename of the currently open, or last open, file.
312     */
313     private String filename;
314    
315     /**
316     * The verbosity level of this instance
317     */
318     private int _verbosityLevel;
319    
320     /**
321     * A reference to the writer being used.
322     */
323     private BufferedWriter writer;
324    
325     /**
326     * A boolean signifying whether a file is open or not.
327     */
328     private boolean open = false;
329    
330     //---STATIC ATTRIBUTES---
331    
332     }