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.1
Committed: Mon Nov 20 18:34:27 2000 UTC (23 years, 6 months ago) by tdb
Branch: MAIN
Log Message:
New FileLogger. Does exactly the same, but implements a Java interface instead.
No CORBA functionality is present in this class, instead it is used by the new
LoggerServant.
Also added new method of acquiring the verbosity directly from the configuration system.

File Contents

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