arnaucube
arnaucube/openEventsPlatformAppPublic Self-hosted repository
openEventsPlatformApp/plugins/cordova-plugin-console/www/logger.js
plugins/cordova-plugin-console/www/logger.jsRaw
  1/*
  2 *
  3 * Licensed to the Apache Software Foundation (ASF) under one
  4 * or more contributor license agreements.  See the NOTICE file
  5 * distributed with this work for additional information
  6 * regarding copyright ownership.  The ASF licenses this file
  7 * to you under the Apache License, Version 2.0 (the
  8 * "License"); you may not use this file except in compliance
  9 * with the License.  You may obtain a copy of the License at
 10 *
 11 *   http://www.apache.org/licenses/LICENSE-2.0
 12 *
 13 * Unless required by applicable law or agreed to in writing,
 14 * software distributed under the License is distributed on an
 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 16 * KIND, either express or implied.  See the License for the
 17 * specific language governing permissions and limitations
 18 * under the License.
 19 *
 20*/
 21
 22//------------------------------------------------------------------------------
 23// The logger module exports the following properties/functions:
 24//
 25// LOG                          - constant for the level LOG
 26// ERROR                        - constant for the level ERROR
 27// WARN                         - constant for the level WARN
 28// INFO                         - constant for the level INFO
 29// DEBUG                        - constant for the level DEBUG
 30// logLevel()                   - returns current log level
 31// logLevel(value)              - sets and returns a new log level
 32// useConsole()                 - returns whether logger is using console
 33// useConsole(value)            - sets and returns whether logger is using console
 34// log(message,...)             - logs a message at level LOG
 35// error(message,...)           - logs a message at level ERROR
 36// warn(message,...)            - logs a message at level WARN
 37// info(message,...)            - logs a message at level INFO
 38// debug(message,...)           - logs a message at level DEBUG
 39// logLevel(level,message,...)  - logs a message specified level
 40//
 41//------------------------------------------------------------------------------
 42
 43var logger = exports;
 44
 45var exec    = require('cordova/exec');
 46
 47var UseConsole   = false;
 48var UseLogger    = true;
 49var Queued       = [];
 50var DeviceReady  = false;
 51var CurrentLevel;
 52
 53var originalConsole = console;
 54
 55/**
 56 * Logging levels
 57 */
 58
 59var Levels = [
 60    "LOG",
 61    "ERROR",
 62    "WARN",
 63    "INFO",
 64    "DEBUG"
 65];
 66
 67/*
 68 * add the logging levels to the logger object and
 69 * to a separate levelsMap object for testing
 70 */
 71
 72var LevelsMap = {};
 73for (var i=0; i<Levels.length; i++) {
 74    var level = Levels[i];
 75    LevelsMap[level] = i;
 76    logger[level]    = level;
 77}
 78
 79CurrentLevel = LevelsMap.WARN;
 80
 81/**
 82 * Getter/Setter for the logging level
 83 *
 84 * Returns the current logging level.
 85 *
 86 * When a value is passed, sets the logging level to that value.
 87 * The values should be one of the following constants:
 88 *    logger.LOG
 89 *    logger.ERROR
 90 *    logger.WARN
 91 *    logger.INFO
 92 *    logger.DEBUG
 93 *
 94 * The value used determines which messages get printed.  The logging
 95 * values above are in order, and only messages logged at the logging
 96 * level or above will actually be displayed to the user.  E.g., the
 97 * default level is WARN, so only messages logged with LOG, ERROR, or
 98 * WARN will be displayed; INFO and DEBUG messages will be ignored.
 99 */
100logger.level = function (value) {
101    if (arguments.length) {
102        if (LevelsMap[value] === null) {
103            throw new Error("invalid logging level: " + value);
104        }
105        CurrentLevel = LevelsMap[value];
106    }
107
108    return Levels[CurrentLevel];
109};
110
111/**
112 * Getter/Setter for the useConsole functionality
113 *
114 * When useConsole is true, the logger will log via the
115 * browser 'console' object.
116 */
117logger.useConsole = function (value) {
118    if (arguments.length) UseConsole = !!value;
119
120    if (UseConsole) {
121        if (typeof console == "undefined") {
122            throw new Error("global console object is not defined");
123        }
124
125        if (typeof console.log != "function") {
126            throw new Error("global console object does not have a log function");
127        }
128
129        if (typeof console.useLogger == "function") {
130            if (console.useLogger()) {
131                throw new Error("console and logger are too intertwingly");
132            }
133        }
134    }
135
136    return UseConsole;
137};
138
139/**
140 * Getter/Setter for the useLogger functionality
141 *
142 * When useLogger is true, the logger will log via the
143 * native Logger plugin.
144 */
145logger.useLogger = function (value) {
146    // Enforce boolean
147    if (arguments.length) UseLogger = !!value;
148    return UseLogger;
149};
150
151/**
152 * Logs a message at the LOG level.
153 *
154 * Parameters passed after message are used applied to
155 * the message with utils.format()
156 */
157logger.log   = function(message) { logWithArgs("LOG",   arguments); };
158
159/**
160 * Logs a message at the ERROR level.
161 *
162 * Parameters passed after message are used applied to
163 * the message with utils.format()
164 */
165logger.error = function(message) { logWithArgs("ERROR", arguments); };
166
167/**
168 * Logs a message at the WARN level.
169 *
170 * Parameters passed after message are used applied to
171 * the message with utils.format()
172 */
173logger.warn  = function(message) { logWithArgs("WARN",  arguments); };
174
175/**
176 * Logs a message at the INFO level.
177 *
178 * Parameters passed after message are used applied to
179 * the message with utils.format()
180 */
181logger.info  = function(message) { logWithArgs("INFO",  arguments); };
182
183/**
184 * Logs a message at the DEBUG level.
185 *
186 * Parameters passed after message are used applied to
187 * the message with utils.format()
188 */
189logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
190
191// log at the specified level with args
192function logWithArgs(level, args) {
193    args = [level].concat([].slice.call(args));
194    logger.logLevel.apply(logger, args);
195}
196
197// return the correct formatString for an object
198function formatStringForMessage(message) {
199    return (typeof message === "string") ? "" : "%o"; 
200}
201
202/**
203 * Logs a message at the specified level.
204 *
205 * Parameters passed after message are used applied to
206 * the message with utils.format()
207 */
208logger.logLevel = function(level /* , ... */) {
209    // format the message with the parameters
210    var formatArgs = [].slice.call(arguments, 1);
211    var fmtString = formatStringForMessage(formatArgs[0]);
212    if (fmtString.length > 0){
213        formatArgs.unshift(fmtString); // add formatString
214    }
215
216    var message    = logger.format.apply(logger.format, formatArgs);
217
218    if (LevelsMap[level] === null) {
219        throw new Error("invalid logging level: " + level);
220    }
221
222    if (LevelsMap[level] > CurrentLevel) return;
223
224    // queue the message if not yet at deviceready
225    if (!DeviceReady && !UseConsole) {
226        Queued.push([level, message]);
227        return;
228    }
229
230    // Log using the native logger if that is enabled
231    if (UseLogger) {
232        exec(null, null, "Console", "logLevel", [level, message]);
233    }
234
235    // Log using the console if that is enabled
236    if (UseConsole) {
237        // make sure console is not using logger
238        if (console.useLogger()) {
239            throw new Error("console and logger are too intertwingly");
240        }
241
242        // log to the console
243        switch (level) {
244            case logger.LOG:   originalConsole.log(message); break;
245            case logger.ERROR: originalConsole.log("ERROR: " + message); break;
246            case logger.WARN:  originalConsole.log("WARN: "  + message); break;
247            case logger.INFO:  originalConsole.log("INFO: "  + message); break;
248            case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
249        }
250    }
251};
252
253
254/**
255 * Formats a string and arguments following it ala console.log()
256 *
257 * Any remaining arguments will be appended to the formatted string.
258 *
259 * for rationale, see FireBug's Console API:
260 *    http://getfirebug.com/wiki/index.php/Console_API
261 */
262logger.format = function(formatString, args) {
263    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
264};
265
266
267//------------------------------------------------------------------------------
268/**
269 * Formats a string and arguments following it ala vsprintf()
270 *
271 * format chars:
272 *   %j - format arg as JSON
273 *   %o - format arg as JSON
274 *   %c - format arg as ''
275 *   %% - replace with '%'
276 * any other char following % will format it's
277 * arg via toString().
278 *
279 * Returns an array containing the formatted string and any remaining
280 * arguments.
281 */
282function __format(formatString, args) {
283    if (formatString === null || formatString === undefined) return [""];
284    if (arguments.length == 1) return [formatString.toString()];
285
286    if (typeof formatString != "string")
287        formatString = formatString.toString();
288
289    var pattern = /(.*?)%(.)(.*)/;
290    var rest    = formatString;
291    var result  = [];
292
293    while (args.length) {
294        var match = pattern.exec(rest);
295        if (!match) break;
296
297        var arg   = args.shift();
298        rest = match[3];
299        result.push(match[1]);
300
301        if (match[2] == '%') {
302            result.push('%');
303            args.unshift(arg);
304            continue;
305        }
306
307        result.push(__formatted(arg, match[2]));
308    }
309
310    result.push(rest);
311
312    var remainingArgs = [].slice.call(args);
313    remainingArgs.unshift(result.join(''));
314    return remainingArgs;
315}
316
317function __formatted(object, formatChar) {
318
319    try {
320        switch(formatChar) {
321            case 'j':
322            case 'o': return JSON.stringify(object);
323            case 'c': return '';
324        }
325    }
326    catch (e) {
327        return "error JSON.stringify()ing argument: " + e;
328    }
329
330    if ((object === null) || (object === undefined)) {
331        return Object.prototype.toString.call(object);
332    }
333
334    return object.toString();
335}
336
337
338//------------------------------------------------------------------------------
339// when deviceready fires, log queued messages
340logger.__onDeviceReady = function() {
341    if (DeviceReady) return;
342
343    DeviceReady = true;
344
345    for (var i=0; i<Queued.length; i++) {
346        var messageArgs = Queued[i];
347        logger.logLevel(messageArgs[0], messageArgs[1]);
348    }
349
350    Queued = null;
351};
352
353// add a deviceready event to log queued messages
354document.addEventListener("deviceready", logger.__onDeviceReady, false);