| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| //------------------------------------------------------------------------------ |
| // The logger module exports the following properties/functions: |
| // |
| // LOG - constant for the level LOG |
| // ERROR - constant for the level ERROR |
| // WARN - constant for the level WARN |
| // INFO - constant for the level INFO |
| // DEBUG - constant for the level DEBUG |
| // logLevel() - returns current log level |
| // logLevel(value) - sets and returns a new log level |
| // useConsole() - returns whether logger is using console |
| // useConsole(value) - sets and returns whether logger is using console |
| // log(message,...) - logs a message at level LOG |
| // error(message,...) - logs a message at level ERROR |
| // warn(message,...) - logs a message at level WARN |
| // info(message,...) - logs a message at level INFO |
| // debug(message,...) - logs a message at level DEBUG |
| // logLevel(level,message,...) - logs a message specified level |
| // |
| //------------------------------------------------------------------------------ |
| |
| var logger = exports; |
| |
| var exec = require('cordova/exec'); |
| var utils = require('cordova/utils'); |
| |
| var UseConsole = false; |
| var UseLogger = true; |
| var Queued = []; |
| var DeviceReady = false; |
| var CurrentLevel; |
| |
| var originalConsole = console; |
| |
| /** |
| * Logging levels |
| */ |
| |
| var Levels = [ |
| "LOG", |
| "ERROR", |
| "WARN", |
| "INFO", |
| "DEBUG" |
| ]; |
| |
| /* |
| * add the logging levels to the logger object and |
| * to a separate levelsMap object for testing |
| */ |
| |
| var LevelsMap = {}; |
| for (var i=0; i<Levels.length; i++) { |
| var level = Levels[i]; |
| LevelsMap[level] = i; |
| logger[level] = level; |
| } |
| |
| CurrentLevel = LevelsMap.WARN; |
| |
| /** |
| * Getter/Setter for the logging level |
| * |
| * Returns the current logging level. |
| * |
| * When a value is passed, sets the logging level to that value. |
| * The values should be one of the following constants: |
| * logger.LOG |
| * logger.ERROR |
| * logger.WARN |
| * logger.INFO |
| * logger.DEBUG |
| * |
| * The value used determines which messages get printed. The logging |
| * values above are in order, and only messages logged at the logging |
| * level or above will actually be displayed to the user. E.g., the |
| * default level is WARN, so only messages logged with LOG, ERROR, or |
| * WARN will be displayed; INFO and DEBUG messages will be ignored. |
| */ |
| logger.level = function (value) { |
| if (arguments.length) { |
| if (LevelsMap[value] === null) { |
| throw new Error("invalid logging level: " + value); |
| } |
| CurrentLevel = LevelsMap[value]; |
| } |
| |
| return Levels[CurrentLevel]; |
| }; |
| |
| /** |
| * Getter/Setter for the useConsole functionality |
| * |
| * When useConsole is true, the logger will log via the |
| * browser 'console' object. |
| */ |
| logger.useConsole = function (value) { |
| if (arguments.length) UseConsole = !!value; |
| |
| if (UseConsole) { |
| if (typeof console == "undefined") { |
| throw new Error("global console object is not defined"); |
| } |
| |
| if (typeof console.log != "function") { |
| throw new Error("global console object does not have a log function"); |
| } |
| |
| if (typeof console.useLogger == "function") { |
| if (console.useLogger()) { |
| throw new Error("console and logger are too intertwingly"); |
| } |
| } |
| } |
| |
| return UseConsole; |
| }; |
| |
| /** |
| * Getter/Setter for the useLogger functionality |
| * |
| * When useLogger is true, the logger will log via the |
| * native Logger plugin. |
| */ |
| logger.useLogger = function (value) { |
| // Enforce boolean |
| if (arguments.length) UseLogger = !!value; |
| return UseLogger; |
| }; |
| |
| /** |
| * Logs a message at the LOG level. |
| * |
| * Parameters passed after message are used applied to |
| * the message with utils.format() |
| */ |
| logger.log = function(message) { logWithArgs("LOG", arguments); }; |
| |
| /** |
| * Logs a message at the ERROR level. |
| * |
| * Parameters passed after message are used applied to |
| * the message with utils.format() |
| */ |
| logger.error = function(message) { logWithArgs("ERROR", arguments); }; |
| |
| /** |
| * Logs a message at the WARN level. |
| * |
| * Parameters passed after message are used applied to |
| * the message with utils.format() |
| */ |
| logger.warn = function(message) { logWithArgs("WARN", arguments); }; |
| |
| /** |
| * Logs a message at the INFO level. |
| * |
| * Parameters passed after message are used applied to |
| * the message with utils.format() |
| */ |
| logger.info = function(message) { logWithArgs("INFO", arguments); }; |
| |
| /** |
| * Logs a message at the DEBUG level. |
| * |
| * Parameters passed after message are used applied to |
| * the message with utils.format() |
| */ |
| logger.debug = function(message) { logWithArgs("DEBUG", arguments); }; |
| |
| // log at the specified level with args |
| function logWithArgs(level, args) { |
| args = [level].concat([].slice.call(args)); |
| logger.logLevel.apply(logger, args); |
| } |
| |
| // return the correct formatString for an object |
| function formatStringForMessage(message) { |
| return (typeof message === "string") ? "" : "%o"; |
| } |
| |
| /** |
| * Logs a message at the specified level. |
| * |
| * Parameters passed after message are used applied to |
| * the message with utils.format() |
| */ |
| logger.logLevel = function(level /* , ... */) { |
| // format the message with the parameters |
| var formatArgs = [].slice.call(arguments, 1); |
| var fmtString = formatStringForMessage(formatArgs[0]); |
| if (fmtString.length > 0){ |
| formatArgs.unshift(fmtString); // add formatString |
| } |
| |
| var message = logger.format.apply(logger.format, formatArgs); |
| |
| if (LevelsMap[level] === null) { |
| throw new Error("invalid logging level: " + level); |
| } |
| |
| if (LevelsMap[level] > CurrentLevel) return; |
| |
| // queue the message if not yet at deviceready |
| if (!DeviceReady && !UseConsole) { |
| Queued.push([level, message]); |
| return; |
| } |
| |
| // Log using the native logger if that is enabled |
| if (UseLogger) { |
| exec(null, null, "Console", "logLevel", [level, message]); |
| } |
| |
| // Log using the console if that is enabled |
| if (UseConsole) { |
| // make sure console is not using logger |
| if (console.useLogger()) { |
| throw new Error("console and logger are too intertwingly"); |
| } |
| |
| // log to the console |
| switch (level) { |
| case logger.LOG: originalConsole.log(message); break; |
| case logger.ERROR: originalConsole.log("ERROR: " + message); break; |
| case logger.WARN: originalConsole.log("WARN: " + message); break; |
| case logger.INFO: originalConsole.log("INFO: " + message); break; |
| case logger.DEBUG: originalConsole.log("DEBUG: " + message); break; |
| } |
| } |
| }; |
| |
| |
| /** |
| * Formats a string and arguments following it ala console.log() |
| * |
| * Any remaining arguments will be appended to the formatted string. |
| * |
| * for rationale, see FireBug's Console API: |
| * http://getfirebug.com/wiki/index.php/Console_API |
| */ |
| logger.format = function(formatString, args) { |
| return __format(arguments[0], [].slice.call(arguments,1)).join(' '); |
| }; |
| |
| |
| //------------------------------------------------------------------------------ |
| /** |
| * Formats a string and arguments following it ala vsprintf() |
| * |
| * format chars: |
| * %j - format arg as JSON |
| * %o - format arg as JSON |
| * %c - format arg as '' |
| * %% - replace with '%' |
| * any other char following % will format it's |
| * arg via toString(). |
| * |
| * Returns an array containing the formatted string and any remaining |
| * arguments. |
| */ |
| function __format(formatString, args) { |
| if (formatString === null || formatString === undefined) return [""]; |
| if (arguments.length == 1) return [formatString.toString()]; |
| |
| if (typeof formatString != "string") |
| formatString = formatString.toString(); |
| |
| var pattern = /(.*?)%(.)(.*)/; |
| var rest = formatString; |
| var result = []; |
| |
| while (args.length) { |
| var match = pattern.exec(rest); |
| if (!match) break; |
| |
| var arg = args.shift(); |
| rest = match[3]; |
| result.push(match[1]); |
| |
| if (match[2] == '%') { |
| result.push('%'); |
| args.unshift(arg); |
| continue; |
| } |
| |
| result.push(__formatted(arg, match[2])); |
| } |
| |
| result.push(rest); |
| |
| var remainingArgs = [].slice.call(args); |
| remainingArgs.unshift(result.join('')); |
| return remainingArgs; |
| } |
| |
| function __formatted(object, formatChar) { |
| |
| try { |
| switch(formatChar) { |
| case 'j': |
| case 'o': return JSON.stringify(object); |
| case 'c': return ''; |
| } |
| } |
| catch (e) { |
| return "error JSON.stringify()ing argument: " + e; |
| } |
| |
| if ((object === null) || (object === undefined)) { |
| return Object.prototype.toString.call(object); |
| } |
| |
| return object.toString(); |
| } |
| |
| |
| //------------------------------------------------------------------------------ |
| // when deviceready fires, log queued messages |
| logger.__onDeviceReady = function() { |
| if (DeviceReady) return; |
| |
| DeviceReady = true; |
| |
| for (var i=0; i<Queued.length; i++) { |
| var messageArgs = Queued[i]; |
| logger.logLevel(messageArgs[0], messageArgs[1]); |
| } |
| |
| Queued = null; |
| }; |
| |
| // add a deviceready event to log queued messages |
| document.addEventListener("deviceready", logger.__onDeviceReady, false); |