package com.partlyhuman.apollo.logging { import flash.filesystem.File; import flash.filesystem.FileMode; import flash.filesystem.FileStream; import flash.system.Capabilities; import mx.core.mx_internal; import mx.logging.targets.LineFormattedTarget; use namespace mx_internal; /** * Logging target that logs to a file of your choice in the (Apollo) application's * resource directory. You may choose the filename and whether the file will append onto * an existing log (be careful of this one as I don't really cut the log down when it reaches * some size limit, though this would be simple enough to add) or clear the log per session. * * Accepts all options of TraceTarget, so see the documentation there. You may set filters * for the severity of events that are logged, how much information is logged with the message, * the category of events that are logged, etc. * * @author Roger Braunstein | partlyhuman.com * @see mx.logging.targets.TraceTarget */ public class FileTarget extends LineFormattedTarget { [Inspectable(category="General", defaultValue="log.txt")] public var filename:String = "log.txt"; [Inspectable(category="General", defaultValue="false")] public var append:Boolean = false; protected var _outstream:FileStream; protected var failedToOpen:Boolean = false; protected var NEWLINE:String = "\n"; public function FileTarget() { super(); determineNewline(); } /** * Determines what newline character to use. Provided for your overriding. */ protected function determineNewline():void { if (Capabilities.os.match(/Windows/)) NEWLINE = "\r\n"; } /** * Makes sure the filename is something you really want to write to. You might * be careful of relative filenames. But, this value is set in the application * itself, so I'm trusting myself to not be silly about it. * Override this to be less trusting. */ protected function getSanitizedFilename():String { return filename; } /** * Lazily opens the stream. This lets you set the filename outside the constructor * or change it before the first logging event takes place. */ protected function get outstream():FileStream { if (_outstream || failedToOpen) return _outstream; try { var fileref:File = File.appStorageDirectory.resolve(getSanitizedFilename()); _outstream = new FileStream(); _outstream.open(fileref, (append)?FileMode.APPEND:FileMode.WRITE); } catch (e:Error) { _outstream = null; failedToOpen = true; trace("ERROR: FileTarget wasn't able to open log file as specified, nothing will be logged."); } return _outstream; } /** * Using the LineFormattedTarget class to do the "heavy" lifting. */ override mx_internal function internalLog(message:String):void { outstream && outstream.writeUTFBytes(message + NEWLINE); } } }