1 /*!
  2 * This file is part of Aloha Editor Project http://aloha-editor.org
  3 * Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
  4 * Contributors http://aloha-editor.org/contribution.php 
  5 * Licensed unter the terms of http://www.aloha-editor.org/license.html
  6 *//*
  7 * Aloha Editor is free software: you can redistribute it and/or modify
  8 * it under the terms of the GNU Affero General Public License as published by
  9 * the Free Software Foundation, either version 3 of the License, or
 10 * (at your option) any later version.*
 11 *
 12 * Aloha Editor is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15 * GNU Affero General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU Affero General Public License
 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 19 */
 20 
 21 define(
 22 ['aloha/core', 'util/class', 'aloha/jquery'],
 23 function(Aloha, Class, jQuery ) {
 24 	"use strict";
 25 	
 26 	var
 27 //		$ = jQuery,
 28 //		Aloha = window.Aloha,
 29 		console = window.console;
 30 //		Class = window.Class
 31 //		GENTICS = window.GENTICS;
 32 
 33 /**
 34  * This is the aloha Log
 35  * @namespace Aloha
 36  * @class Log
 37  * @singleton
 38  */
 39 var alohaConsole = Class.extend({
 40 	/**
 41 	 * Initialize the logging
 42 	 * @hide
 43 	 */
 44 	init: function() {
 45 		
 46 		// initialize the logging settings (if not present)
 47 		if (typeof Aloha.settings.logLevels === 'undefined' || !Aloha.settings.logLevels) {
 48 			Aloha.settings.logLevels = {'error' : true, 'warn' : true};
 49 		}
 50 
 51 		// initialize the logHistory settings (if not present)
 52 		if (typeof Aloha.settings.logHistory === 'undefined' || !Aloha.settings.logHistory) {
 53 			Aloha.settings.logHistory = {};
 54 		}
 55 		// set the default values for the loghistory
 56 		if (!Aloha.settings.logHistory.maxEntries) {
 57 			Aloha.settings.logHistory.maxEntries = 100;
 58 		}
 59 		if (!Aloha.settings.logHistory.highWaterMark) {
 60 			Aloha.settings.logHistory.highWaterMark = 90;
 61 		}
 62 		if (!Aloha.settings.logHistory.levels) {
 63 			Aloha.settings.logHistory.levels = {'error' : true, 'warn' : true};
 64 		}
 65 		this.flushLogHistory();
 66 		
 67 		Aloha.trigger('aloha-logger-ready');
 68 	},
 69 
 70 	/**
 71 	 * Log History as array of Message Objects. Every object has the properties
 72 	 * 'level', 'component' and 'message'
 73 	 * @property
 74 	 * @type Array
 75 	 * @hide
 76 	 */
 77 	logHistory: [],
 78 
 79 	/**
 80 	 * Flag, which is set as soon as the highWaterMark for the log history is reached.
 81 	 * This flag is reset on every call of flushLogHistory()
 82 	 * @hide
 83 	 */
 84 	highWaterMarkReached: false,
 85 
 86 	/**
 87 	 * Logs a message to the console
 88 	 * @method
 89 	 * @param {String} level Level of the log ('error', 'warn' or 'info', 'debug')
 90 	 * @param {String} component Component that calls the log
 91 	 * @param {String} message log message
 92 	 */
 93 	log: function(level, component, message) {
 94 		
 95 
 96 		// log ('Logging message');
 97 		if ( typeof component === 'undefined' ) {
 98 			message = level;
 99 		}
100 		if ( typeof component !== 'string' && component && component.toString ) {
101 			component = component.toString();
102 		}
103 		
104 		// log ('warn', 'Warning message');
105 		if ( typeof message === 'undefined' ) {
106 			message = component;
107 			component = undefined;
108 		}
109 
110 		if (typeof level === 'undefined' || !level) {
111 			level = 'log';
112 		}
113 		
114 		level = level.toLowerCase();
115 		
116 		if ( typeof Aloha.settings.logLevels === "undefined" ) {
117 			return;
118 		}
119 120 		
121 		// now check whether the log level is activated
122 		if ( !Aloha.settings.logLevels[ level ] ) {
123 			return;
124 		}
125 		
126 		component = component || "Unkown Aloha Component";
127 
128 		this.addToLogHistory({'level' : level, 'component' : component, 'message' : message, 'date' : new Date()});
129 		
130 		switch (level) {
131 		case 'error':
132 			if (window.console && console.error) {
133 				// FIXME:
134 				// Using console.error rather than throwing an error is very
135 				// problematic because we get not stack.
136 				// We ought to consider doing the following:
137 				// throw component + ': ' + message;
138 				if(!component && !message) {
139 					console.error("Error occured without message and component");
140 				} else {
141 					console.error(component + ': ' + message);
142 				}
143 			}
144 			break;
145 		case 'warn':
146 			if (window.console && console.warn) {
147 				console.warn(component + ': ' + message);
148 			}
149 			break;
150 		case 'info':
151 			if (window.console && console.info) {
152 				console.info(component + ': ' + message);
153 154 			}
155 			break;
156 		case 'debug':
157 			if (window.console && console.log) {
158 				console.log(component + ' [' + level + ']: ' + message);
159 			}
160 			break;
161 		default:
162 			if (window.console && console.log) {
163 				console.log(component + ' [' + level + ']: ' + message);
164 			}
165 			break;
166 		}
167 	},
168 
169 	/**
170 	 * Log a message of log level 'error'
171 	 * @method
172 	 * @param {String} component Component that calls the log
173 	 * @param {String} message log message
174 	 */
175 	error: function(component, message) {
176 		this.log('error', component, message);
177 	},
178 
179 	/**
180 	 * Log a message of log level 'warn'
181 	 * @method
182 	 * @param {String} component Component that calls the log
183 	 * @param {String} message log message
184 	 */
185 	warn: function(component, message) {
186 		this.log('warn', component, message);
187 	},
188 
189 	/**
190 	 * Log a message of log level 'info'
191 	 * @method
192 	 * @param {String} component Component that calls the log
193 	 * @param {String} message log message
194 	 */
195 	info: function(component, message) {
196 		this.log('info', component, message);
197 	},
198 
199 	/**
200 	 * Log a message of log level 'debug'
201 	 * @param {String} component Component that calls the log
202 	 * @param {String} message log message
203 	 */
204 	debug: function(component, message) {
205 		this.log('debug', component, message);
206 	},
207 
208 	/**
209 	 * Methods to mark function as deprecated for developers.
210 	 * @param {String} component String that calls the log
211 	 * @param {String} message log message
212 	 */
213 	deprecated: function(component, message) {
214 		this.log( 'warn', component, message );
215 		// help the developer to locate the call.
216 		 if ( Aloha.settings.logLevels[ 'deprecated' ] ) {
217 			 throw new Error ( message );
218 		 }
219 	},
220 	
221 	/**
222 	 * Check whether the given log level is currently enabled
223 	 * @param {String} level
224 	 * @return true when log level is enabled, false if not
225 	 */
226 	isLogLevelEnabled: function(level) {
227 		return Aloha.settings && Aloha.settings.logLevels && Aloha.settings.logLevels[level];
228 	},
229 
230 	/**
231 	 * Check whether error logging is enabled
232 	 * @return true if error logging is enabled, false if not
233 	 */
234 	isErrorEnabled: function() {
235 		return this.isLogLevelEnabled('error');
236 	},
237 
238 	/**
239 	 * Check whether warn logging is enabled
240 	 * @return true if warn logging is enabled, false if not
241 	 */
242 	isWarnEnabled: function() {
243 		return this.isLogLevelEnabled('warn');
244 	},
245 
246 	/**
247 	 * Check whether info logging is enabled
248 	 * @return true if info logging is enabled, false if not
249 	 */
250 	isInfoEnabled: function() {
251 		return this.isLogLevelEnabled('info');
252 	},
253 
254 	/**
255 	 * Check whether debug logging is enabled
256 	 * @return true if debug logging is enabled, false if not
257 	 */
258 	isDebugEnabled: function() {
259 		return this.isLogLevelEnabled('debug');
260 	},
261 
262 	/**
263 	 * Add the given entry to the log history. Check whether the highWaterMark has been reached, and fire an event if yes.
264 	 * @param {Object} entry entry to be added to the log history
265 	 * @hide
266 	 */
267 	addToLogHistory: function(entry) {
268 		
269 		if ( !Aloha.settings.logHistory ) {
270 			this.init();
271 		}
272 
273 		// when maxEntries is set to something illegal, we do nothing (log history is disabled)
274 		// check whether the level is one we like to have logged
275 		if ( Aloha.settings.logHistory.maxEntries <= 0
276 				|| !Aloha.settings.logHistory.levels[ entry.level ]
277 			) {
278 			
279 			return;
280 		}
281 
282 		// first add the entry as last element to the history array
283 		this.logHistory.push( entry );
284 
285 		// check whether the highWaterMark was reached, if so, fire an event
286 		if ( !this.highWaterMarkReached ) {
287 			
288 			if ( this.logHistory.length >= Aloha.settings.logHistory.maxEntries * Aloha.settings.logHistory.highWaterMark / 100 ) {
289 				
290 				// fire the event
291 				Aloha.trigger('aloha-log-full');
292 				// set the flag (so we will not fire the event again until the logHistory is flushed)
293 				this.highWaterMarkReached = true;
294 			}
295 		}
296 
297 		// check whether the log is full and eventually remove the oldest entries
298 		while ( this.logHistory.length > Aloha.settings.logHistory.maxEntries ) {
299 			this.logHistory.shift();
300 		}
301 	},
302 
303 	/**
304 	 * Get the log history
305 	 * @return log history as array of objects
306 	 * @hide
307 	 */
308 	getLogHistory: function() {
309 		return this.logHistory;
310 	},
311 
312 	/**
313 	 * Flush the log history. Remove all log entries and reset the flag for the highWaterMark
314 	 * @return void
315 	 * @hide
316 	 */
317 	flushLogHistory: function() {
318 		this.logHistory = [];
319 		this.highWaterMarkReached = false;
320 	}
321 });
322 
323 /**
324  * Create the Log object
325  * @hide
326  */
327 alohaConsole = new alohaConsole();
328 
329 // add to log namespace for compatiblility.
330 return Aloha.Log = Aloha.Console = alohaConsole;
331 
332 });
333