diff options
Diffstat (limited to 'webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log')
11 files changed, 1580 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/AlertAppender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/AlertAppender.js new file mode 100644 index 0000000000..4be7b9e9b5 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/AlertAppender.js @@ -0,0 +1,67 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Andreas Ecker (ecker) + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that writes each message to a native alert(). + * <p> + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * <p> + * It allows to go through the log messages step-by-step, since the alert + * window temporarily halts the regular program execution. That way even + * the dispose process can easily be debugged. + */ +qx.OO.defineClass("qx.log.AlertAppender", qx.log.Appender, +function() { + qx.log.Appender.call(this); +}); + + +// overridden +qx.OO.changeProperty({ name:"useLongFormat", type:"boolean", defaultValue:false, allowNull:false }); + +// overridden +qx.Proto.appendLogEvent = function(evt) { + + // Append the message + var text = evt.logger.getName(); + if (evt.instanceId != null) { + text += " (" + evt.instanceId + ")"; + } + + alert("\n" + text + "\n" + this.formatLogEvent(evt)); +} + + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + return qx.log.Appender.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Appender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Appender.js new file mode 100644 index 0000000000..5df3dd3f5e --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Appender.js @@ -0,0 +1,183 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * An appender. Does the actual logging. + */ +qx.OO.defineClass("qx.log.Appender", qx.log.LogEventProcessor, +function() { + qx.log.LogEventProcessor.call(this); +}); + + +/** Whether the logger name and log level should be included in the formatted log message. */ +qx.OO.addProperty({ name:"useLongFormat", type:"boolean", defaultValue:true, allowNull:false }); + + +// overridden +qx.Proto.handleLogEvent = function(evt) { + if (this.decideLogEvent(evt) != qx.log.Filter.DENY) { + this.appendLogEvent(evt); + } +} + + +/** + * Appends a log event to the log. + * + * @param evt {Map} The event to append. + */ +qx.Proto.appendLogEvent = function(evt) { + throw new Error("appendLogEvent is abstract"); +} + + +/** + * Formats a log event. + * + * @param evt {Map} The log event to format. + * @return {String} The formatted event. + */ +qx.Proto.formatLogEvent = function(evt) { + var Logger = qx.log.Logger; + + var text = ""; + + // Append the time stamp + var time = new String(new Date().getTime() - qx._LOADSTART); + while (time.length < 6) { + time = "0" + time; + } + text += time; + + // Append the level + if (this.getUseLongFormat()) { + switch (evt.level) { + case Logger.LEVEL_DEBUG: text += " DEBUG: "; break; + case Logger.LEVEL_INFO: text += " INFO: "; break; + case Logger.LEVEL_WARN: text += " WARN: "; break; + case Logger.LEVEL_ERROR: text += " ERROR: "; break; + case Logger.LEVEL_FATAL: text += " FATAL: "; break; + } + } else { + text += ": "; + } + + // Append the indent + var indent = ""; + for (var i = 0; i < evt.indent; i++) { + indent += " "; + } + text += indent; + + // Append the logger name and instance + if (this.getUseLongFormat()) { + text += evt.logger.getName(); + if (evt.instanceId != null) { + text += "[" + evt.instanceId + "]"; + } + text += ": "; + } + + // Append the message + if (typeof evt.message == "string") { + text += evt.message; + } else { + // The message is an object -> Log a dump of the object + var obj = evt.message; + if (obj == null) { + text += "Object is null"; + } else { + text += "--- Object: " + obj + " ---\n"; + var attrArr = new Array(); + try { + for (var attr in obj) { + attrArr.push(attr); + } + } catch (exc) { + text += indent + " [not readable: " + exc + "]\n"; + } + attrArr.sort(); + for (var i = 0; i < attrArr.length; i++) { + try { + text += indent + " " + attrArr[i] + "=" + obj[attrArr[i]] + "\n"; + } + catch (exc) { + text += indent + " " + attrArr[i] + "=[not readable: " + exc + "]\n"; + } + } + text += indent + "--- End of object ---"; + } + } + + // Append the throwable + if (evt.throwable != null) { + var thr = evt.throwable; + + if (thr.name == null) { + text += ": " + thr; + } else { + text += ": " + thr.name; + } + if (thr.message != null) { + text += " - " + thr.message; + } + if (thr.number != null) { + text += " (#" + thr.number + ")"; + } + + if (thr.stack != null) { + text += "\n" + this._beautyStackTrace(thr.stack); + } + } + + return text; +} + + +/** + * Beautifies a stack trace. + * + * @param stack {String} the stack trace to beautify. + * @return {String} the beautified stack trace. + */ +qx.Proto._beautyStackTrace = function(stack) { + // e.g. "()@http://localhost:8080/webcomponent-test-SNAPSHOT/webcomponent/js/com/ptvag/webcomponent/common/log/Logger:253" + var lineRe = /@(.+):(\d+)$/gm; + var hit; + var out = ""; + var scriptDir = "/script/"; + while ((hit = lineRe.exec(stack)) != null) { + var url = hit[1]; + + var jsPos = url.indexOf(scriptDir); + var className = (jsPos == -1) ? url : url.substring(jsPos + scriptDir.length).replace(/\//g, "."); + + var lineNumber = hit[2]; + out += " at " + className + ":" + lineNumber + "\n"; + } + return out; +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/DefaultFilter.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/DefaultFilter.js new file mode 100644 index 0000000000..47c18df4db --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/DefaultFilter.js @@ -0,0 +1,59 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * The default filter. Has a minimum level and can be enabled or disabled. + */ +qx.OO.defineClass("qx.log.DefaultFilter", qx.log.Filter, +function() { + qx.log.Filter.call(this); +}); + + +/** + * Whether the filter should be enabled. If set to false all log events + * will be denied. + */ +qx.OO.addProperty({ name:"enabled", type:"boolean", defaultValue:true, allowNull:false, getAlias:"isEnabled" }); + +/** + * The minimum log level. If set only log messages with a level greater or equal + * to the set level will be accepted. + */ +qx.OO.addProperty({ name:"minLevel", type:"number", defaultValue:null }); + + +// overridden +qx.Proto.decide = function(evt) { + var Filter = qx.log.Filter; + if (! this.isEnabled()) { + return Filter.DENY; + } else if (this.getMinLevel() == null) { + return Filter.NEUTRAL; + } else { + return (evt.level >= this.getMinLevel()) ? Filter.ACCEPT : Filter.DENY; + } +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/DivAppender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/DivAppender.js new file mode 100644 index 0000000000..506cae32a1 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/DivAppender.js @@ -0,0 +1,166 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to a div element. + * + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * + * @param divId {String ? "qx_log"} the ID of the div element to write the + * messages to. + */ +qx.OO.defineClass("qx.log.DivAppender", qx.log.Appender, +function(divId) { + qx.log.Appender.call(this); + + this._divId = divId ? divId : "qx_log"; +}); + + +/** + * The maximum number of messages to show. If null the number of messages is not + * limited. + */ +qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:500 }); + +// overridden +qx.OO.changeProperty({ name:"useLongFormat", type:"boolean", defaultValue:false, allowNull:false }); + +/** The CSS class name for the head div {containing the clear button}. */ +qx.OO.addProperty({ name:"headClassName", type:"string", defaultValue:"log-head" }); + +/** The CSS class name for the body div {containing the log messages}. */ +qx.OO.addProperty({ name:"bodyClassName", type:"string", defaultValue:"log-body" }); + +/** The CSS class name for a div showing the name of the current group. */ +qx.OO.addProperty({ name:"groupClassName", type:"string", defaultValue:"log-group" }); + +/** The CSS class name for a div showing a debug message. */ +qx.OO.addProperty({ name:"debugClassName", type:"string", defaultValue:"log-debug" }); + +/** The CSS class name for a div showing a info message. */ +qx.OO.addProperty({ name:"infoClassName", type:"string", defaultValue:"log-info" }); + +/** The CSS class name for a div showing a warn message. */ +qx.OO.addProperty({ name:"warnClassName", type:"string", defaultValue:"log-warn" }); + +/** The CSS class name for a div showing a error message. */ +qx.OO.addProperty({ name:"errorClassName", type:"string", defaultValue:"log-error" }); + + +/** + * Creates an onclick handler that clears a div element. This method is used to + * create a minimum closure. + * + * @param logElem {Element} the element to clear when the handler is called. + * @return {Function} the handler. + */ +qx.Proto._createClearButtonHandler = function(logElem) { + return function(evt) { + logElem.innerHTML = ""; + } +} + + +// overridden +qx.Proto.appendLogEvent = function(evt) { + var Logger = qx.log.Logger; + + // Initialize the log element if nessesary + if (this._logElem == null) { + var divElem = document.getElementById(this._divId); + if (divElem == null) { + throw new Error("Logging div with ID " + this._divId + " not found"); + } + divElem.innerHTML = '<div class="' + this.getHeadClassName() + '"><button>Clear</button></div>' + + '<div class="' + this.getBodyClassName() + '"></div>'; + + this._clearBt = divElem.firstChild.firstChild; + this._logElem = divElem.lastChild; + + this._clearBt.onclick = this._createClearButtonHandler(this._logElem); + } + + // Append the group when needed + var group = evt.logger.getName(); + if (evt.instanceId != null) { + group += "[" + evt.instanceId + "]"; + } + + if (group != this._lastGroup) { + var elem = document.createElement("div"); + elem.className = this.getGroupClassName(); + elem.innerHTML = group; + + this._logElem.appendChild(elem); + this._lastGroup = group; + } + + // Append the message + var elem = document.createElement("div"); + switch (evt.level) { + case Logger.LEVEL_DEBUG: elem.className = this.getDebugClassName(); break; + case Logger.LEVEL_INFO: elem.className = this.getInfoClassName(); break; + case Logger.LEVEL_WARN: elem.className = this.getWarnClassName(); break; + case Logger.LEVEL_ERROR: elem.className = this.getErrorClassName(); break; + } + elem.innerHTML = this.formatLogEvent(evt).replace(/&/g, "&") + .replace(/</g, "<").replace(/ /g, "  ").replace(/[\n]/g, "<br>"); + this._logElem.appendChild(elem); + + // Remove superflous messages + while (this._logElem.childNodes.length > this.getMaxMessages()) { + this._logElem.removeChild(this._logElem.firstChild); + + if (this._removedMessageCount == null) { + this._removedMessageCount = 1; + } else { + this._removedMessageCount++; + } + } + + if (this._removedMessageCount != null) { + this._logElem.firstChild.className = ""; + this._logElem.firstChild.innerHTML = "(" + this._removedMessageCount + + " messages removed)"; + } +} + + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + if (this._clearBt) { + this._clearBt.onclick = null; + this._clearBt = null; + } + this._logElem = null; + + return qx.log.Appender.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Filter.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Filter.js new file mode 100644 index 0000000000..8cfc739307 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Filter.js @@ -0,0 +1,53 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * A filter for log events. + */ +qx.OO.defineClass("qx.log.Filter", qx.core.Object, +function() { + qx.core.Object.call(this); +}); + +/** + * Decidies whether a log event is accepted. + * + * @param evt {Map} The event to check. + * @return {Integer} {@link #ACCEPT}, {@link #DENY} or {@link #NEUTRAL}. + */ +qx.Proto.decide = function(evt) { + throw new Error("decide is abstract"); +} + + +/** {int} Specifies that the log event is accepted. */ +qx.Class.ACCEPT = 1; + +/** {int} Specifies that the log event is denied. */ +qx.Class.DENY = 2; + +/** {int} Specifies that the filter is neutral to the log event. */ +qx.Class.NEUTRAL = 3; diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/FireBugAppender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/FireBugAppender.js new file mode 100644 index 0000000000..6b27588303 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/FireBugAppender.js @@ -0,0 +1,74 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 David Perez + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * David Perez (david-perez) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to FireBug, a nice extension for debugging and developing under Firefox. + * <p> + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * </p> + */ +qx.OO.defineClass('qx.log.FireBugAppender', qx.log.Appender, function() { + qx.log.Appender.call(this); +}); + +qx.Proto.appendLogEvent = function(evt) +{ + if (typeof console != 'undefined') + { + var log = qx.log.Logger; + var msg = this.formatLogEvent(evt); + + switch (evt.level) + { + case log.LEVEL_DEBUG: + if (console.debug) { + console.debug(msg); + } + break; + case log.LEVEL_INFO: + if (console.info) { + console.info(msg); + } + break; + case log.LEVEL_WARN: + if (console.warn) { + console.warn(msg); + } + break; + default: + if (console.error) { + console.error(msg); + } + break; + } + // Force a stack dump, for helping locating the error + if (evt.level > log.LEVEL_WARN && (!evt.throwable || !evt.throwable.stack) && console.trace) + { + console.trace(); + } + } +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/ForwardAppender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/ForwardAppender.js new file mode 100644 index 0000000000..05cc183a38 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/ForwardAppender.js @@ -0,0 +1,43 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that forwards all log events to a log event processor. + * + * @param targetProcessor {LogEventProcessor} The log event processor Where to + * pass the log events. + */ +qx.OO.defineClass("qx.log.ForwardAppender", qx.log.Appender, +function(targetProcessor) { + qx.log.Appender.call(this); + + this._targetProcessor = targetProcessor; +}); + + +// overridden +qx.Proto.appendLogEvent = function(evt) { + this._targetProcessor.handleLogEvent(evt); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/LogEventProcessor.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/LogEventProcessor.js new file mode 100644 index 0000000000..a7ee918035 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/LogEventProcessor.js @@ -0,0 +1,143 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) + +************************************************************************ */ + +/** + * Processes log events. May be configured with filters in order to specify + * which log events should be processed. + */ +qx.OO.defineClass("qx.log.LogEventProcessor", qx.core.Object, +function() { + qx.core.Object.call(this); +}); + + +/** + * Appends a filter to the filter chain. + * + * @param filter {Filter} The filter to append. + */ +qx.Proto.addFilter = function(filter) { + if (this._filterArr == null) { + this._filterArr = [] + } + this._filterArr.push(filter); +} + + +/** + * Clears the filter chain. + */ +qx.Proto.clearFilters = function() { + this._filterArr = null; +} + + +/** + * Returns the head filter from the chain. Returns null if there are no filters. + * + * @return {Filter} the head filter from the chain. + */ +qx.Proto.getHeadFilter = function() { + return (this._filterArr == null || this._filterArr.length == 0) ? null : this._filterArr[0]; +} + + +/** + * Returns the default filter from the chain. If the head filter is no default + * filter, the chain will be cleared and a default filter will be created. + * + * @return {Filter} the default filter. + */ +qx.Proto._getDefaultFilter = function() { + var headFilter = this.getHeadFilter(); + if (! (headFilter instanceof qx.log.DefaultFilter)) { + // The head filter of the appender is no DefaultFilter + // (or the appender has no filters at all) + // -> Create a default handler and append it + this.clearFilters(); + headFilter = new qx.log.DefaultFilter(); + this.addFilter(headFilter); + } + + return headFilter; +} + + +/** + * Sets whether event processing should be enabled. + * <p> + * Note: This will clear all custom filters. + * + * @param enabled {Boolean} whether event processing should be enabled. + */ +qx.Proto.setEnabled = function(enabled) { + this._getDefaultFilter().setEnabled(enabled); +} + + +/** + * Sets the min level an event must have in order to be processed. + * <p> + * Note: This will clear all custom filters. + * + * @param minLevel {Integer} the new min level. + */ +qx.Proto.setMinLevel = function(minLevel) { + this._getDefaultFilter().setMinLevel(minLevel); +} + + +/** + * Decides whether a log event is processed. + * + * @param evt {Map} the event to check. + * @return {Integer} {@link Filter#ACCEPT}, {@link Filter#DENY} or + * {@link Filter#NEUTRAL}. + */ +qx.Proto.decideLogEvent = function(evt) { + var NEUTRAL = qx.log.Filter.NEUTRAL; + + if (this._filterArr != null) { + for (var i = 0; i < this._filterArr.length; i++) { + var decision = this._filterArr[i].decide(evt); + if (decision != NEUTRAL) { + return decision; + } + } + } + + // All filters are neutral, so are we + return NEUTRAL; +} + + +/** + * Processes a log event. + * + * @param evt {Map} The log event to process. + */ +qx.Proto.handleLogEvent = function(evt) { + throw new Error("handleLogEvent is abstract"); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Logger.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Logger.js new file mode 100644 index 0000000000..8f16559191 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/Logger.js @@ -0,0 +1,382 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) +#require(qx.log.WindowAppender) +#require(qx.log.FireBugAppender) +* +************************************************************************ */ + +/** + * A logger. Logs messages of one log category. + * + * @param name {String} The category name of this logger. (Normally a class or + * package name) + * @param parentLogger {Logger} The parent logger. + */ +qx.OO.defineClass("qx.log.Logger", qx.log.LogEventProcessor, +function(name, parentLogger) { + qx.log.LogEventProcessor.call(this); + + this._name = name; + this._parentLogger = parentLogger; +}); + + +/** + * Returns the name of this logger. (Normally a class or package name) + * + * @return {String} the name. + */ +qx.Proto.getName = function() { + return this._name; +} + + +/** + * Returns the parent logger. + * + * @return {Logger} the parent logger. + */ +qx.Proto.getParentLogger = function() { + return this._parentLogger; +} + + +/** + * Indents all following log messages by one. + * <p> + * This affects all log messages. Even those of other loggers. + */ +qx.Proto.indent = function() { + qx.log.Logger._indent++; +} + + +/** + * Unindents all following log messages by one. + * <p> + * This affects all log messages. Even those of other loggers. + */ +qx.Proto.unindent = function() { + qx.log.Logger._indent--; +} + + +/** + * Adds an appender. + * <p> + * If a logger has an appender, log events will not be passed to the + * appenders of parent loggers. If you want this behaviour, also append a + * {@link ForwardAppender}. + * + * @param appender {Appender} the appender to add. + */ +qx.Proto.addAppender = function(appender) { + if (this._appenderArr == null) { + this._appenderArr = []; + } + + this._appenderArr.push(appender); +} + + +/** + * Removes an appender. + * + * @param appender {Appender} the appender to remove. + */ +qx.Proto.removeAppender = function(appender) { + if (this._appenderArr != null) { + this._appenderArr.remove(appender); + } +} + + +/** + * Removes all appenders. + */ +qx.Proto.removeAllAppenders = function() { + this._appenderArr = null; +} + + +// overridden +qx.Proto.handleLogEvent = function(evt) { + var Filter = qx.log.Filter; + + var decision = Filter.NEUTRAL; + var logger = this; + while (decision == Filter.NEUTRAL && logger != null) { + decision = logger.decideLogEvent(evt); + logger = logger.getParentLogger(); + } + + if (decision != Filter.DENY) { + this.appendLogEvent(evt); + } +} + + +/** + * Passes a log event to the appenders. If the logger has no appenders the + * event will be passed to the appenders of the parent logger, and so on. + * + * @param evt {Map} The event to append. + */ +qx.Proto.appendLogEvent = function(evt) { + if (this._appenderArr != null && this._appenderArr.length != 0) { + for (var i = 0; i < this._appenderArr.length; i++) { + this._appenderArr[i].handleLogEvent(evt); + } + } else if (this._parentLogger != null) { + this._parentLogger.appendLogEvent(evt); + } +} + + +/** + * Logs a message. + * + * @param level {Integer} the log level. + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.log = function(level, msg, instanceId, exc) { + var evt = { logger:this, level:level, message:msg, throwable:exc, + indent:qx.log.Logger._indent, instanceId:instanceId } + this.handleLogEvent(evt); +} + + +/** + * Logs a debug message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.debug = function(msg, instanceId, exc) { + this.log(qx.log.Logger.LEVEL_DEBUG, msg, instanceId, exc); +} + + +/** + * Logs an info message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.info = function(msg, instanceId, exc) { + this.log(qx.log.Logger.LEVEL_INFO, msg, instanceId, exc); +} + + +/** + * Logs a warning message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.warn = function(msg, instanceId, exc) { + this.log(qx.log.Logger.LEVEL_WARN, msg, instanceId, exc); +} + + +/** + * Logs an error message. + * + * @param msg {var} the message to log. If this is not a string, the + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.error = function(msg, instanceId, exc) { + this.log(qx.log.Logger.LEVEL_ERROR, msg, instanceId, exc); +} + + +/** + * Logs a fatal message. + * + * @param msg {var} the message to log. If this is not a string, its + * object dump will be logged. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.fatal = function(msg, instanceId, exc) { + this.log(qx.log.Logger.LEVEL_FATAL, msg, instanceId, exc); +} + + +/** + * Resets the measure timer. + * + * @see #measure() + */ +qx.Proto.measureReset = function() { + if (this._totalMeasureTime != null) { + this.debug("Measure reset. Total measure time: " + this._totalMeasureTime + " ms"); + } + + this._lastMeasureTime = null; + this._totalMeasureTime = null; +} + + +/** + * Logs a debug message and measures the time since the last call of measure. + * + * @param msg {String} the message to log. + * @param instanceId {var ? null} the ID of the instance the log message comes from. + * @param exc {var ? null} the exception to log. + */ +qx.Proto.measure = function(msg, instanceId, exc) { + if (this._lastMeasureTime == null) { + msg = "(measure start) " + msg; + } else { + var delta = new Date().getTime() - this._lastMeasureTime; + + if (this._totalMeasureTime == null) { + this._totalMeasureTime = 0; + } + + this._totalMeasureTime += delta; + msg = "(passed time: " + delta + " ms) " + msg; + } + + this.debug(msg, instanceId, exc); + + this._lastMeasureTime = new Date().getTime(); +} + + +/** + * Logs the current stack trace as a debug message. + */ +qx.Proto.printStackTrace = function() { + try { + forced_exception.go; + } catch (exc) { + this.debug("Current stack trace", "", exc); + } +} + + +/** + * Returns the logger of a class. + * + * @param clazz {Function} The class of which to return the logger. + */ +qx.Class.getClassLogger = function(clazz) { + var logger = clazz._logger; + if (logger == null) { + // Get the parent logger + var classname = clazz.classname; + var splits = classname.split("."); + var currPackage = window; + var currPackageName = ""; + var parentLogger = qx.log.Logger.ROOT_LOGGER; + for (var i = 0; i < splits.length - 1; i++) { + currPackage = currPackage[splits[i]]; + currPackageName += ((i != 0) ? "." : "") + splits[i]; + + if (currPackage._logger == null) { + // This package has no logger -> Create one + currPackage._logger = new qx.log.Logger(currPackageName, parentLogger); + } + parentLogger = currPackage._logger; + } + + // Create the class logger + logger = new qx.log.Logger(classname, parentLogger); + clazz._logger = logger; + } + return logger; +} + + +/** {Integer} The current indent. */ +qx.Class._indent = 0; + +/** + * {Integer} The ALL level has the lowest possible rank and is intended to turn on + * all logging. + */ +qx.Class.LEVEL_ALL = 0; + +/** + * {Integer} The DEBUG Level designates fine-grained informational events that are + * most useful to debug an application. + */ +qx.Class.LEVEL_DEBUG = 200; + +/** + * {Integer} The INFO level designates informational messages that highlight the + * progress of the application at coarse-grained level. + */ +qx.Class.LEVEL_INFO = 500; + +/** {Integer} The WARN level designates potentially harmful situations. */ +qx.Class.LEVEL_WARN = 600; + +/** + * {Integer} The ERROR level designates error events that might still allow the + * application to continue running. + */ +qx.Class.LEVEL_ERROR = 700; + +/** + * {Integer} The FATAL level designates very severe error events that will + * presumably lead the application to abort. + */ +qx.Class.LEVEL_FATAL = 800; + +/** + * {Integer} The OFF has the highest possible rank and is intended to turn off + * logging. + */ +qx.Class.LEVEL_OFF = 1000; + + +/** + * {Logger} The root logger. This is the root of the logger tree. All loggers + * should be a child or grand child of this root logger. + * <p> + * This logger logs by default everything greater than level INFO to a log + * window. + */ +qx.Class.ROOT_LOGGER = new qx.log.Logger("root", null); +qx.Class.ROOT_LOGGER.setMinLevel(qx.log.Logger.LEVEL_DEBUG); + +if (typeof console != 'undefined' && console.debug) { + qx.Class.ROOT_LOGGER.addAppender(new qx.log.FireBugAppender()); +} else { + qx.Class.ROOT_LOGGER.addAppender(new qx.log.WindowAppender()); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/RingBufferAppender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/RingBufferAppender.js new file mode 100644 index 0000000000..d7c36f8217 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/RingBufferAppender.js @@ -0,0 +1,124 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Carsten Lergenmueller (carstenl) + +************************************************************************ */ + +/* ************************************************************************ + +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to a memory container. The messages + * can be retrieved later, f. i. when an error dialog pops up and the question + * arises what actions have caused the error. + * + */ +qx.OO.defineClass("qx.log.RingBufferAppender", qx.log.Appender, +function() { + qx.log.Appender.call(this); + + this._history = []; + this._nextIndexToStoreTo = 0; + this._appenderToFormatStrings = null; +}); + + +/** + * The maximum number of messages to hold. If null the number of messages is not + * limited. Warning: Changing this property will clear the events logged so far. + */ +qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:50 }); + +qx.Proto._modifyMaxMessages = function(propValue, propOldValue, propData){ + this._history = []; + this._nextIndexToStoreTo = 0; +}; + +// overridden +qx.Proto.appendLogEvent = function(evt) { + var maxMessages = this.getMaxMessages(); + if (this._history.length < maxMessages){ + this._history.push(evt); + } else { + this._history[this._nextIndexToStoreTo++] = evt; + if (this._nextIndexToStoreTo >= maxMessages){ + this._nextIndexToStoreTo = 0; + } + } +}; + +/** + * Returns log events which have been logged previously. + * + * @param count {Integer} The number of events to retreive. If there are more events than the + * given count, the oldest ones will not be returned. + * @return {array} array of stored log events + */ +qx.Proto.retrieveLogEvents = function(count) { + if (count > this._history.length){ + count = this._history.length; + } + + var indexOfYoungestElementInHistory + = this._history.length == this.getMaxMessages() ? this._nextIndexToStoreTo - 1 + : this._history.length - 1; + var startIndex = indexOfYoungestElementInHistory - count + 1; + if (startIndex < 0){ + startIndex += this._history.length; + } + + var result; + if (startIndex <= indexOfYoungestElementInHistory){ + result = this._history.slice(startIndex, indexOfYoungestElementInHistory + 1); + } else { + result = this._history.slice(startIndex, this._history.length).concat( + this._history.slice(0, indexOfYoungestElementInHistory + 1) + ); + } + return result; +}; + +/** + * Returns a string holding the information of log events which have been logged previously. + * + * @param count {Integer} The number of events to retreive. If there are more events than the + * given count, the oldest ones will not be returned. + * @return {String} string + */ +qx.Proto.formatLogEvents = function(count) { + if (this._appenderToFormatStrings == null){ + this._appenderToFormatStrings = new qx.log.Appender(); + } + + var events = this.retrieveLogEvents(count); + var string = ""; + for(var idx=0; idx < events.length; idx++) { + string += this._appenderToFormatStrings.formatLogEvent(events[idx]) + "\n"; + } + return string; +}; + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + return qx.log.Appender.prototype.dispose.call(this); +}; diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/WindowAppender.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/WindowAppender.js new file mode 100644 index 0000000000..4bfc5e5bf4 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/log/WindowAppender.js @@ -0,0 +1,286 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2006 STZ-IDA, Germany, http://www.stz-ida.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Til Schneider (til132) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) +#module(log) + +************************************************************************ */ + +/** + * An appender that writes all messages to a log window. + * <p> + * This class does not depend on qooxdoo widgets, so it also works when there + * are problems with widgets or when the widgets are not yet initialized. + * + * @param name {String ? "qx_log"} the name of the log window. + */ +qx.OO.defineClass("qx.log.WindowAppender", qx.log.Appender, +function(name) { + qx.log.Appender.call(this); + + this._id = qx.log.WindowAppender.register(this); + this._name = (name == null) ? "qx_log" : name; + + this._errorsPreventingAutoCloseCount = 0; + + this._logWindowOpened = false; +}); + + +/** + * The maximum number of messages to show. If null the number of messages is not + * limited. + */ +qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:500 }); + +/** Whether the window should appear under the main window. */ +qx.OO.addProperty({ name:"popUnder", type:"boolean", defaultValue:false, allowNull:false }); + +/** Whether the window should automatically be closed when its creating page is unloaded and + * errors have been logged. Note that errors that have been logged before this property has been + * turned off will be ignored. Warning: Turning this off may create a memory hole because the disposer + * of this class will auto-close the window, i. e. it may stay open after dispose(), still holding + * memory. However, for diagnostics it is often more important to get information about errors + * than to save memory. + */ +qx.OO.addProperty({ name:"autoCloseWithErrors", type:"boolean", defaultValue:true, allowNull:false }); + + +/** + * Creates and opens the log window if it doesn't alread exist. + */ +qx.Proto.openWindow = function() { + if (this._logWindowOpened) { + // The window is already open -> Nothing to do + return; + } + + // Open the logger window + var winWidth = 600; + var winHeight = 350; + var winLeft = window.screen.width - winWidth; + var winTop = window.screen.height - winHeight; + var params = "toolbar=no,scrollbars=yes,resizable=yes," + + "width=" + winWidth + ",height=" + winHeight + + ",left=" + winLeft + ",top=" + winTop; + + // NOTE: In window.open the browser will process the event queue. + // Which means that other log events may arrive during this time. + // The log window is then in an inconsistent state, because the + // this._logElem is not created yet. These events will be added to the + // this._logEventQueue and logged after this._logElem is created. + this._logWindow = window.open("", this._name, params); + + if (!this._logWindow || this._logWindow.closed) + { + if (!this._popupBlockerWarning) { + alert("Couldn't open debug window. Please disable your popup blocker!"); + } + + this._popupBlockerWarning = true; + return; + } + + // Seems to be OK now. + this._popupBlockerWarning = false; + + // Store that window is open + this._logWindowOpened = true; + + if (this.getPopUnder()) { + this._logWindow.blur(); + window.focus(); + } + + var logDocument = this._logWindow.document; + // NOTE: We have to use a static onunload handler, because an onunload + // that is set later using DOM is ignored completely. + // (at least in Firefox, but maybe in IE, too) + logDocument.open(); + logDocument.write("<html><head><title>" + this._name + "</title></head>" + + '<body onload="qx = opener.qx;" onunload="try{qx.log.WindowAppender._registeredAppenders[' + this._id + ']._autoCloseWindow()}catch(e){}">' + + '<pre id="log" wrap="wrap" style="font-size:11"></pre></body></html>'); + logDocument.close(); + + this._logElem = logDocument.getElementById("log"); + + // Log the events from the queue + if (this._logEventQueue != null) { + for (var i = 0; i < this._logEventQueue.length; i++) { + this.appendLogEvent(this._logEventQueue[i]); + } + this._logEventQueue = null; + } +}; + + +/** + * Closes the log window. + */ +qx.Proto.closeWindow = function() { + if (this._logWindow != null) { + this._logWindow.close(); + this._logWindow = null; + this._logElem = null; + this._logWindowOpened = false; + } +}; + +/** + * Called when the window should be automatically closed (because the page that opened + * is is unloaded). Will only close the window if the autoClose***-Properties allow it + */ +qx.Proto._autoCloseWindow = function() { + if (this.getAutoCloseWithErrors() || this._errorsPreventingAutoCloseCount == 0){ + this.closeWindow(); + } else { + //Show message why auto-close has failed + this._showMessageInLog("Log window message: <b>Note: " + this._errorsPreventingAutoCloseCount + + " errors have been recorded, keeping log window open.</b>"); + } +}; + +/** + * Appends a line to the log showing the given text + * @param msg {String} message to show, may be HTML + */ +qx.Proto._showMessageInLog = function(msg) { + //Create dummy log event and use appendLogEvent() + //Reason is that it is rather complicated to get something into the log + //window when it is not already open -> reuse the existing code + //which does event queuing in such a case + var dummyEvent = {message: msg, isDummyEventForMessage : true}; + this.appendLogEvent(dummyEvent); +}; + + +// overridden +qx.Proto.appendLogEvent = function(evt) { + if (!this._logWindowOpened) { + this._logEventQueue = []; + this._logEventQueue.push(evt); + + this.openWindow(); + + // Popup-Blocker was active! + if (!this._logWindowOpened) { + return; + } + } else if (this._logElem == null) { + // The window is currenlty opening, but not yet finished + // -> Put the event in the queue + this._logEventQueue.push(evt); + } else { + var divElem = this._logWindow.document.createElement("div"); + if (evt.level >= qx.log.Logger.LEVEL_ERROR) { + divElem.style.backgroundColor = "#FFEEEE"; + if (!this.getAutoCloseWithErrors()){ + this._errorsPreventingAutoCloseCount += 1; + } + } else if (evt.level == qx.log.Logger.LEVEL_DEBUG) { + divElem.style.color = "gray"; + } + if (evt.isDummyEventForMessage){ + divElem.innerHTML = evt.message; + } else { + divElem.innerHTML = qx.html.String.fromText(this.formatLogEvent(evt)); + } + this._logElem.appendChild(divElem); + + while (this._logElem.childNodes.length > this.getMaxMessages()) { + this._logElem.removeChild(this._logElem.firstChild); + + if (this._removedMessageCount == null) { + this._removedMessageCount = 1; + } else { + this._removedMessageCount++; + } + } + + if (this._removedMessageCount != null) { + this._logElem.firstChild.innerHTML = "(" + this._removedMessageCount + + " messages removed)"; + } + + // Scroll to bottom + this._logWindow.scrollTo(0, this._logElem.offsetHeight); + } +} + +qx.Proto._modifyAutoCloseWithErrors = function(propValue, propOldValue, propData){ + if (!propValue && propOldValue){ + this._errorsPreventingAutoCloseCount = 0; + + //Show message in log so user can see which errors have been counted + this._showMessageInLog("Log window message: Starting error recording, any errors below this line will prevent the log window from closing"); + + } else if (propValue && !propOldValue){ + //Show message in log so user can see which errors have been counted + this._showMessageInLog("Log window message: Stopping error recording, discarding " + this._errorsPreventingAutoCloseCount + " errors."); + } + return true; +} + + + +// overridden +qx.Proto.dispose = function() { + if (this.getDisposed()) { + return true; + } + + this._autoCloseWindow(); + + return qx.log.Appender.prototype.dispose.call(this); +} + + +qx.Class._nextId = 1; +qx.Class._registeredAppenders = {}; + + +/** + * Registers a WindowAppender. This is used by the WindowAppender internally. + * You don't have to call this. + * + * @param appender {WindowAppender} the WindowAppender to register. + * @return {Integer} the ID. + */ +qx.Class.register = function(appender) { + var WindowAppender = qx.log.WindowAppender; + + var id = WindowAppender._nextId++; + WindowAppender._registeredAppenders[id] = appender; + + return id; +} + + +/** + * Returns a prviously registered WindowAppender. + * + * @param id {Integer} the ID of the wanted WindowAppender. + * @return {WindowAppender} the WindowAppender or null if no + * WindowAppender with this ID is registered. + */ +qx.Class.getAppender = function(id) { + return qx.log.WindowAppender._registeredAppenders[id]; +} |