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 (Mango) 00044 { 00045 private import mango.io.FileSystem, 00046 mango.io.FileConduit; 00047 00048 private import mango.io.model.IConduit; 00049 00050 /******************************************************************************* 00051 00052 Append log messages to a file. This basic version has no rollover 00053 support, so it just keeps on adding to the file. There's also a 00054 RollingFileAppender that may suit your needs. 00055 00056 *******************************************************************************/ 00057 00058 public class FileAppender : Appender 00059 { 00060 private static uint mask; 00061 private IBuffer buffer; 00062 private IConduit conduit; 00063 00064 /*********************************************************************** 00065 00066 Get a unique fingerprint for this class 00067 00068 ***********************************************************************/ 00069 00070 static this() 00071 { 00072 mask = nextMask(); 00073 } 00074 00075 /*********************************************************************** 00076 00077 ***********************************************************************/ 00078 00079 protected this () 00080 { 00081 } 00082 00083 /*********************************************************************** 00084 00085 Create a basic FileAppender to a file with the specified 00086 path. 00087 00088 ***********************************************************************/ 00089 00090 this (FilePath fp) 00091 { 00092 setConduit (new FileConduit (fp, FileStyle.WriteAppending)); 00093 } 00094 00095 /*********************************************************************** 00096 00097 Create a basic FileAppender to a file with the specified 00098 path, and with the given Layout 00099 00100 ***********************************************************************/ 00101 00102 this (FilePath fp, Layout layout) 00103 { 00104 this (fp); 00105 setLayout (layout); 00106 } 00107 00108 /*********************************************************************** 00109 00110 Make sure the file is closed when we're GC'd 00111 00112 ***********************************************************************/ 00113 00114 ~this () 00115 { 00116 close(); 00117 } 00118 00119 /*********************************************************************** 00120 00121 Return the conduit 00122 00123 ***********************************************************************/ 00124 00125 IConduit getConduit () 00126 { 00127 return conduit; 00128 } 00129 00130 /*********************************************************************** 00131 00132 Set the conduit 00133 00134 ***********************************************************************/ 00135 00136 protected IBuffer setConduit (IConduit conduit) 00137 { 00138 // create a new buffer upon this conduit 00139 this.conduit = conduit; 00140 return (buffer = conduit.createBuffer); 00141 } 00142 00143 /*********************************************************************** 00144 00145 Return the fingerprint for this class 00146 00147 ***********************************************************************/ 00148 00149 uint getMask () 00150 { 00151 return mask; 00152 } 00153 00154 /*********************************************************************** 00155 00156 Return the name of this class 00157 00158 ***********************************************************************/ 00159 00160 char[] getName () 00161 { 00162 return this.classinfo.name; 00163 } 00164 00165 /*********************************************************************** 00166 00167 Append an event to the output. 00168 00169 ***********************************************************************/ 00170 00171 synchronized void append (Event event) 00172 { 00173 Layout layout = getLayout; 00174 buffer.append (layout.header (event)); 00175 buffer.append (layout.content (event)); 00176 buffer.append (layout.footer (event)) 00177 .append (FileSystem.NewlineString) 00178 .flush (); 00179 } 00180 00181 /*********************************************************************** 00182 00183 Close the file associated with this Appender 00184 00185 ***********************************************************************/ 00186 00187 synchronized void close () 00188 { 00189 if (conduit) 00190 { 00191 conduit.close(); 00192 conduit = null; 00193 } 00194 } 00195 } 00196 } 00197 else 00198 { 00199 private import std.stream; 00200 00201 /******************************************************************************* 00202 00203 Append log messages to a file. This basic version has no rollover 00204 support, so it just keeps on adding to the file. There's also a 00205 RollingFileAppender that may suit your needs. 00206 00207 *******************************************************************************/ 00208 00209 public class FileAppender : Appender 00210 { 00211 private static uint mask; 00212 private File file; 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 (char[] fp) 00241 { 00242 setFile (new File (fp, FileMode.OutNew)); 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 (char[] 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 file 00272 00273 ***********************************************************************/ 00274 00275 File getFile () 00276 { 00277 return file; 00278 } 00279 00280 /*********************************************************************** 00281 00282 Set the file 00283 00284 ***********************************************************************/ 00285 00286 protected void setFile (File file) 00287 { 00288 this.file = file; 00289 } 00290 00291 /*********************************************************************** 00292 00293 Return the fingerprint for this class 00294 00295 ***********************************************************************/ 00296 00297 uint getMask () 00298 { 00299 return mask; 00300 } 00301 00302 /*********************************************************************** 00303 00304 Return the name of this class 00305 00306 ***********************************************************************/ 00307 00308 char[] getName () 00309 { 00310 return this.classinfo.name; 00311 } 00312 00313 /*********************************************************************** 00314 00315 Append an event to the output. 00316 00317 ***********************************************************************/ 00318 00319 synchronized void append (Event event) 00320 { 00321 Layout layout = getLayout; 00322 file.writeString (layout.header (event)); 00323 file.writeString (layout.content (event)); 00324 file.writeString (layout.footer (event)); 00325 file.writeLine (null); 00326 file.flush (); 00327 } 00328 00329 /*********************************************************************** 00330 00331 Close the file associated with this Appender 00332 00333 ***********************************************************************/ 00334 00335 synchronized void close () 00336 { 00337 if (file) 00338 { 00339 file.close(); 00340 file = null; 00341 } 00342 } 00343 } 00344 }