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.FileConst, 00196 mango.io.FileConduit; 00197 00198 private import mango.io.model.IBuffer, 00199 mango.io.model.IConduit; 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 IBuffer buffer; 00213 private IConduit conduit; 00214 00215 /*********************************************************************** 00216 00217 Get a unique fingerprint for this class 00218 00219 ***********************************************************************/ 00220 00221 static this() 00222 { 00223 mask = nextMask(); 00224 } 00225 00226 /*********************************************************************** 00227 00228 ***********************************************************************/ 00229 00230 protected this () 00231 { 00232 } 00233 00234 /*********************************************************************** 00235 00236 Create a basic FileAppender to a file with the specified 00237 path. 00238 00239 ***********************************************************************/ 00240 00241 this (FilePath fp) 00242 { 00243 setConduit (new FileConduit (fp, FileStyle.WriteAppending)); 00244 } 00245 00246 /*********************************************************************** 00247 00248 Create a basic FileAppender to a file with the specified 00249 path, and with the given Layout 00250 00251 ***********************************************************************/ 00252 00253 this (FilePath fp, Layout layout) 00254 { 00255 this (fp); 00256 setLayout (layout); 00257 } 00258 00259 /*********************************************************************** 00260 00261 Make sure the file is closed when we're GC'd 00262 00263 ***********************************************************************/ 00264 00265 ~this () 00266 { 00267 close(); 00268 } 00269 00270 /*********************************************************************** 00271 00272 Return the conduit 00273 00274 ***********************************************************************/ 00275 00276 IConduit getConduit () 00277 { 00278 return conduit; 00279 } 00280 00281 /*********************************************************************** 00282 00283 Set the conduit 00284 00285 ***********************************************************************/ 00286 00287 protected IBuffer setConduit (IConduit conduit) 00288 { 00289 // create a new buffer upon this conduit 00290 this.conduit = conduit; 00291 return (buffer = conduit.createBuffer); 00292 } 00293 00294 /*********************************************************************** 00295 00296 Return the fingerprint for this class 00297 00298 ***********************************************************************/ 00299 00300 uint getMask () 00301 { 00302 return mask; 00303 } 00304 00305 /*********************************************************************** 00306 00307 Return the name of this class 00308 00309 ***********************************************************************/ 00310 00311 char[] getName () 00312 { 00313 return this.classinfo.name; 00314 } 00315 00316 /*********************************************************************** 00317 00318 Append an event to the output. 00319 00320 ***********************************************************************/ 00321 00322 synchronized void append (Event event) 00323 { 00324 Layout layout = getLayout; 00325 buffer.append (layout.header (event)); 00326 buffer.append (layout.content (event)); 00327 buffer.append (layout.footer (event)) 00328 .append (FileConst.NewlineString) 00329 .flush (); 00330 } 00331 00332 /*********************************************************************** 00333 00334 Close the file associated with this Appender 00335 00336 ***********************************************************************/ 00337 00338 synchronized void close () 00339 { 00340 if (conduit) 00341 { 00342 conduit.close(); 00343 conduit = null; 00344 } 00345 } 00346 } 00347 } 00348