00001 /******************************************************************************* 00002 00003 @file FileAppender.d 00004 00005 Copyright (c) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 4. Derivative works are permitted, but they must carry this notice 00027 in full and credit the original source. 00028 00029 00030 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00031 00032 00033 @version Initial version, May 2004 00034 @author Kris 00035 00036 00037 *******************************************************************************/ 00038 00039 module mango.log.FileAppender; 00040 00041 private import mango.log.Appender; 00042 00043 version (Isolated) 00044 { 00045 private import std.stream; 00046 00047 /******************************************************************************* 00048 00049 Append log messages to a file. This basic version has no rollover 00050 support, so it just keeps on adding to the file. There's also a 00051 RollingFileAppender that may suit your needs. 00052 00053 *******************************************************************************/ 00054 00055 public class FileAppender : Appender 00056 { 00057 private static uint mask; 00058 private File file; 00059 00060 /*********************************************************************** 00061 00062 Get a unique fingerprint for this class 00063 00064 ***********************************************************************/ 00065 00066 static this() 00067 { 00068 mask = nextMask(); 00069 } 00070 00071 /*********************************************************************** 00072 00073 ***********************************************************************/ 00074 00075 protected this () 00076 { 00077 } 00078 00079 /*********************************************************************** 00080 00081 Create a basic FileAppender to a file with the specified 00082 path. 00083 00084 ***********************************************************************/ 00085 00086 this (char[] fp) 00087 { 00088 setFile (new File (fp, FileMode.OutNew)); 00089 } 00090 00091 /*********************************************************************** 00092 00093 Create a basic FileAppender to a file with the specified 00094 path, and with the given Layout 00095 00096 ***********************************************************************/ 00097 00098 this (char[] fp, Layout layout) 00099 { 00100 this (fp); 00101 setLayout (layout); 00102 } 00103 00104 /*********************************************************************** 00105 00106 Make sure the file is closed when we're GC'd 00107 00108 ***********************************************************************/ 00109 00110 ~this () 00111 { 00112 close(); 00113 } 00114 00115 /*********************************************************************** 00116 00117 Return the file 00118 00119 ***********************************************************************/ 00120 00121 File getFile () 00122 { 00123 return file; 00124 } 00125 00126 /*********************************************************************** 00127 00128 Set the file 00129 00130 ***********************************************************************/ 00131 00132 protected void setFile (File file) 00133 { 00134 this.file = file; 00135 } 00136 00137 /*********************************************************************** 00138 00139 Return the fingerprint for this class 00140 00141 ***********************************************************************/ 00142 00143 uint getMask () 00144 { 00145 return mask; 00146 } 00147 00148 /*********************************************************************** 00149 00150 Return the name of this class 00151 00152 ***********************************************************************/ 00153 00154 char[] getName () 00155 { 00156 return this.classinfo.name; 00157 } 00158 00159 /*********************************************************************** 00160 00161 Append an event to the output. 00162 00163 ***********************************************************************/ 00164 00165 synchronized void append (Event event) 00166 { 00167 Layout layout = getLayout; 00168 file.writeString (layout.header (event)); 00169 file.writeString (layout.content (event)); 00170 file.writeString (layout.footer (event)); 00171 file.writeLine (null); 00172 file.flush (); 00173 } 00174 00175 /*********************************************************************** 00176 00177 Close the file associated with this Appender 00178 00179 ***********************************************************************/ 00180 00181 synchronized void close () 00182 { 00183 if (file) 00184 { 00185 file.close(); 00186 file = null; 00187 } 00188 } 00189 } 00190 } 00191 00192 else 00193 00194 { 00195 private import mango.io.FileSystem, 00196 mango.io.FileConduit; 00197 00198 private import mango.io.model.IConduit; 00199 00200 /******************************************************************************* 00201 00202 Append log messages to a file. This basic version has no rollover 00203 support, so it just keeps on adding to the file. There's also a 00204 RollingFileAppender that may suit your needs. 00205 00206 *******************************************************************************/ 00207 00208 public class FileAppender : Appender 00209 { 00210 private static uint mask; 00211 private IBuffer buffer; 00212 private IConduit conduit; 00213 00214 /*********************************************************************** 00215 00216 Get a unique fingerprint for this class 00217 00218 ***********************************************************************/ 00219 00220 static this() 00221 { 00222 mask = nextMask(); 00223 } 00224 00225 /*********************************************************************** 00226 00227 ***********************************************************************/ 00228 00229 protected this () 00230 { 00231 } 00232 00233 /*********************************************************************** 00234 00235 Create a basic FileAppender to a file with the specified 00236 path. 00237 00238 ***********************************************************************/ 00239 00240 this (FilePath fp) 00241 { 00242 setConduit (new FileConduit (fp, FileStyle.WriteAppending)); 00243 } 00244 00245 /*********************************************************************** 00246 00247 Create a basic FileAppender to a file with the specified 00248 path, and with the given Layout 00249 00250 ***********************************************************************/ 00251 00252 this (FilePath fp, Layout layout) 00253 { 00254 this (fp); 00255 setLayout (layout); 00256 } 00257 00258 /*********************************************************************** 00259 00260 Make sure the file is closed when we're GC'd 00261 00262 ***********************************************************************/ 00263 00264 ~this () 00265 { 00266 close(); 00267 } 00268 00269 /*********************************************************************** 00270 00271 Return the conduit 00272 00273 ***********************************************************************/ 00274 00275 IConduit getConduit () 00276 { 00277 return conduit; 00278 } 00279 00280 /*********************************************************************** 00281 00282 Set the conduit 00283 00284 ***********************************************************************/ 00285 00286 protected IBuffer setConduit (IConduit conduit) 00287 { 00288 // create a new buffer upon this conduit 00289 this.conduit = conduit; 00290 return (buffer = conduit.createBuffer); 00291 } 00292 00293 /*********************************************************************** 00294 00295 Return the fingerprint for this class 00296 00297 ***********************************************************************/ 00298 00299 uint getMask () 00300 { 00301 return mask; 00302 } 00303 00304 /*********************************************************************** 00305 00306 Return the name of this class 00307 00308 ***********************************************************************/ 00309 00310 char[] getName () 00311 { 00312 return this.classinfo.name; 00313 } 00314 00315 /*********************************************************************** 00316 00317 Append an event to the output. 00318 00319 ***********************************************************************/ 00320 00321 synchronized void append (Event event) 00322 { 00323 Layout layout = getLayout; 00324 buffer.append (layout.header (event)); 00325 buffer.append (layout.content (event)); 00326 buffer.append (layout.footer (event)) 00327 .append (FileSystem.NewlineString) 00328 .flush (); 00329 } 00330 00331 /*********************************************************************** 00332 00333 Close the file associated with this Appender 00334 00335 ***********************************************************************/ 00336 00337 synchronized void close () 00338 { 00339 if (conduit) 00340 { 00341 conduit.close(); 00342 conduit = null; 00343 } 00344 } 00345 } 00346 } 00347