| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199 |
- /**
- * Copyright 2006 Tim Down.
- *
- * Licensed 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.
- */
- /**
- * log4javascript
- *
- * log4javascript is a logging framework for JavaScript based on log4j
- * for Java. This file contains all core log4javascript code and is the only
- * file required to use log4javascript. If you wish to disable log4javascript
- * in production code, replace log4javascript.js with the stub file
- * log4javascript_stub.js, included in the distribution. Also included in the
- * distribution is log4javascript.js, a compressed but functionally
- * identical version of this file.
- *
- * Author: Tim Down <tim@timdown.co.uk>
- * Version: 1.3.1
- * Last modified: 8/11/2006
- * Website: http://www.timdown.co.uk/log4javascript
- */
- /* ------------------------------------------------------------------------- */
- // Array-related stuff
- // Next three methods are solely for IE5, which is missing them
- if (!Array.prototype.push) {
- Array.prototype.push = function() {
- for (var i = 0; i < arguments.length; i++){
- this[this.length] = arguments[i];
- }
- return this.length;
- };
- }
- if (!Array.prototype.shift) {
- Array.prototype.shift = function() {
- if (this.length > 0) {
- var firstItem = this[0];
- for (var i = 0; i < this.length - 1; i++) {
- this[i] = this[i + 1];
- }
- this.length = this.length - 1;
- return firstItem;
- }
- };
- }
- if (!Array.prototype.splice) {
- Array.prototype.splice = function(startIndex, deleteCount) {
- var itemsAfterDeleted = this.slice(startIndex + deleteCount);
- var itemsDeleted = this.slice(startIndex, startIndex + deleteCount);
- this.length = startIndex;
- // Copy the arguments into a proper Array object
- var argumentsArray = [];
- for (var i = 0; i < arguments.length; i++) {
- argumentsArray[i] = arguments[i];
- }
- var itemsToAppend = (argumentsArray.length > 2) ?
- itemsAfterDeleted = argumentsArray.slice(2).concat(itemsAfterDeleted) : itemsAfterDeleted;
- for (i = 0; i < itemsToAppend.length; i++) {
- this.push(itemsToAppend[i]);
- }
- return itemsDeleted;
- };
- }
- /* ------------------------------------------------------------------------- */
- var log4javascript;
- var SimpleDateFormat;
- (function() {
- function isUndefined(obj) {
- return typeof obj == "undefined";
- }
- // Date-related stuff
- (function() {
- var regex = /('[^']*')|(G+|y+|M+|w+|W+|D+|d+|F+|E+|a+|H+|k+|K+|h+|m+|s+|S+|Z+)|([a-zA-Z]+)|([^a-zA-Z']+)/;
- var monthNames = ["January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"];
- var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
- var TEXT2 = 0, TEXT3 = 1, NUMBER = 2, YEAR = 3, MONTH = 4, TIMEZONE = 5;
- var types = {
- G : TEXT2,
- y : YEAR,
- Y : YEAR,
- M : MONTH,
- w : NUMBER,
- W : NUMBER,
- D : NUMBER,
- d : NUMBER,
- F : NUMBER,
- E : TEXT3,
- a : TEXT2,
- H : NUMBER,
- k : NUMBER,
- K : NUMBER,
- h : NUMBER,
- m : NUMBER,
- s : NUMBER,
- S : NUMBER,
- Z : TIMEZONE
- };
- var ONE_DAY = 24 * 60 * 60 * 1000;
- var ONE_WEEK = 7 * ONE_DAY;
- var DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK = 1;
- Date.prototype.getDifference = function(date) {
- return this.getTime() - date.getTime();
- };
- Date.prototype.isBefore = function(d) {
- return this.getTime() < d.getTime();
- };
- Date.prototype.getWeekInYear = function(minimalDaysInFirstWeek) {
- if (isUndefined(this.minimalDaysInFirstWeek)) {
- minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK;
- }
- var previousSunday = new Date(this.getTime() - this.getDay() * ONE_DAY);
- previousSunday = new Date(previousSunday.getFullYear(), previousSunday.getMonth(), previousSunday.getDate());
- var startOfYear = new Date(this.getFullYear(), 0, 1);
- var numberOfSundays = previousSunday.isBefore(startOfYear) ?
- 0 : 1 + Math.floor((previousSunday.getTime() - startOfYear.getTime()) / ONE_WEEK);
- var numberOfDaysInFirstWeek = 7 - startOfYear.getDay();
- var weekInYear = numberOfSundays;
- if (numberOfDaysInFirstWeek >= minimalDaysInFirstWeek) {
- weekInYear++;
- }
- return weekInYear;
- };
- Date.prototype.getWeekInMonth = function(minimalDaysInFirstWeek) {
- if (isUndefined(this.minimalDaysInFirstWeek)) {
- minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK;
- }
- var previousSunday = new Date(this.getTime() - this.getDay() * ONE_DAY);
- previousSunday = new Date(previousSunday.getFullYear(), previousSunday.getMonth(), previousSunday.getDate());
- var startOfMonth = new Date(this.getFullYear(), this.getMonth(), 1);
- var numberOfSundays = previousSunday.isBefore(startOfMonth) ?
- 0 : 1 + Math.floor((previousSunday.getTime() - startOfMonth.getTime()) / ONE_WEEK);
- var numberOfDaysInFirstWeek = 7 - startOfMonth.getDay();
- var weekInMonth = numberOfSundays;
- if (numberOfDaysInFirstWeek >= minimalDaysInFirstWeek) {
- weekInMonth++;
- }
- return weekInMonth;
- };
- Date.prototype.getDayInYear = function() {
- var startOfYear = new Date(this.getFullYear(), 0, 1);
- return 1 + Math.floor((this.getTime() - startOfYear.getTime()) / ONE_DAY);
- };
- /* ----------------------------------------------------------------- */
- SimpleDateFormat = function(formatString) {
- this.formatString = formatString;
- };
- /**
- * Sets the minimum number of days in a week in order for that week to
- * be considered as belonging to a particular month or year
- */
- SimpleDateFormat.prototype.setMinimalDaysInFirstWeek = function(days) {
- this.minimalDaysInFirstWeek = days;
- };
- SimpleDateFormat.prototype.getMinimalDaysInFirstWeek = function(days) {
- return isUndefined(this.minimalDaysInFirstWeek) ?
- DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK : this.minimalDaysInFirstWeek;
- };
- SimpleDateFormat.prototype.format = function(date) {
- var formattedString = "";
- var result;
- var padWithZeroes = function(str, len) {
- while (str.length < len) {
- str = "0" + str;
- }
- return str;
- };
- var formatText = function(data, numberOfLetters, minLength) {
- return (numberOfLetters >= 4) ? data : data.substr(0, Math.max(minLength, numberOfLetters));
- };
- var formatNumber = function(data, numberOfLetters) {
- var dataString = "" + data;
- // Pad with 0s as necessary
- return padWithZeroes(dataString, numberOfLetters);
- };
- var searchString = this.formatString;
- while ((result = regex.exec(searchString))) {
- var matchedString = result[0];
- var quotedString = result[1];
- var patternLetters = result[2];
- var otherLetters = result[3];
- var otherCharacters = result[4];
- // If the pattern matched is quoted string, output the text between the quotes
- if (quotedString) {
- if (quotedString == "''") {
- formattedString += "'";
- } else {
- formattedString += quotedString.substring(1, quotedString.length - 1);
- }
- } else if (otherLetters) {
- // Swallow non-pattern letters by doing nothing here
- } else if (otherCharacters) {
- // Simply output other characters
- formattedString += otherCharacters;
- } else if (patternLetters) {
- // Replace pattern letters
- var patternLetter = patternLetters.charAt(0);
- var numberOfLetters = patternLetters.length;
- var rawData = "";
- switch (patternLetter) {
- case "G":
- rawData = "AD";
- break;
- case "y":
- rawData = date.getFullYear();
- break;
- case "M":
- rawData = date.getMonth();
- break;
- case "w":
- rawData = date.getWeekInYear(this.getMinimalDaysInFirstWeek());
- break;
- case "W":
- rawData = date.getWeekInMonth(this.getMinimalDaysInFirstWeek());
- break;
- case "D":
- rawData = date.getDayInYear();
- break;
- case "d":
- rawData = date.getDate();
- break;
- case "F":
- rawData = 1 + Math.floor((date.getDate() - 1) / 7);
- break;
- case "E":
- rawData = dayNames[date.getDay()];
- break;
- case "a":
- rawData = (date.getHours() >= 12) ? "PM" : "AM";
- break;
- case "H":
- rawData = date.getHours();
- break;
- case "k":
- rawData = 1 + date.getHours();
- break;
- case "K":
- rawData = date.getHours() % 12;
- break;
- case "h":
- rawData = 1 + (date.getHours() % 12);
- break;
- case "m":
- rawData = date.getMinutes();
- break;
- case "s":
- rawData = date.getSeconds();
- break;
- case "S":
- rawData = date.getMilliseconds();
- break;
- case "Z":
- rawData = date.getTimezoneOffset(); // This returns the number of minutes since GMT was this time.
- break;
- }
- // Format the raw data depending on the type
- switch (types[patternLetter]) {
- case TEXT2:
- formattedString += formatText(rawData, numberOfLetters, 2);
- break;
- case TEXT3:
- formattedString += formatText(rawData, numberOfLetters, 3);
- break;
- case NUMBER:
- formattedString += formatNumber(rawData, numberOfLetters);
- break;
- case YEAR:
- if (numberOfLetters <= 2) {
- // Output a 2-digit year
- var dataString = "" + rawData;
- formattedString += dataString.substr(2, 2);
- } else {
- formattedString += formatNumber(rawData, numberOfLetters);
- }
- break;
- case MONTH:
- if (numberOfLetters >= 3) {
- formattedString += formatText(monthNames[rawData], numberOfLetters, numberOfLetters);
- } else {
- // NB. Months returned by getMonth are zero-based
- formattedString += formatNumber(rawData + 1, numberOfLetters);
- }
- break;
- case TIMEZONE:
- var isPositive = (rawData > 0);
- // The following line looks like a mistake but isn't
- // because of the way getTimezoneOffset measures.
- var prefix = isPositive ? "-" : "+";
- var absData = Math.abs(rawData);
- // Hours
- var hours = "" + Math.floor(absData / 60);
- hours = padWithZeroes(hours, 2);
- // Minutes
- var minutes = "" + (absData % 60);
- minutes = padWithZeroes(minutes, 2);
- formattedString += prefix + hours + minutes;
- break;
- }
- }
- searchString = searchString.substr(result.index + result[0].length);
- }
- return formattedString;
- };
- })();
- /* ------------------------------------------------------------------------- */
- var applicationStartDate = new Date();
- var uniqueId = "log4javascript_" + applicationStartDate.getTime() + "_" +
- Math.floor(Math.random() * 100000000);
- var emptyFunction = function() {};
- var newLine = "\r\n";
- // Create logging object; this will be assigned properties and returned
- log4javascript = {};
- log4javascript.version = "1.3.1";
- // Returns a nicely formatted representation of an error
- function getExceptionStringRep(ex) {
- if (ex) {
- var exStr = "Exception: ";
- if (ex.message) {
- exStr += ex.message;
- } else if (ex.description) {
- exStr += ex.description;
- }
- if (ex.lineNumber) {
- exStr += " on line number " + ex.lineNumber;
- }
- if (ex.fileName) {
- exStr += " in file " + ex.fileName;
- }
- if (showStackTraces && ex.stack) {
- exStr += newLine + "Stack trace:" + newLine + ex.stack;
- }
- return exStr;
- }
- return null;
- }
- function formatObjectExpansion(obj, depth, indentation) {
- var i, output, childDepth, childIndentation, childLines;
- if ((obj instanceof Array) && depth > 0) {
- if (!indentation) {
- indentation = "";
- }
- output = "[" + newLine;
- childDepth = depth - 1;
- childIndentation = indentation + " ";
- childLines = [];
- for (i = 0; i < obj.length; i++) {
- childLines.push(childIndentation + formatObjectExpansion(obj[i], childDepth, childIndentation));
- }
- output += childLines.join("," + newLine) + newLine + indentation + "]";
- return output;
- } else if (typeof obj == "object" && depth > 0) {
- if (!indentation) {
- indentation = "";
- }
- output = "" + "{" + newLine;
- childDepth = depth - 1;
- childIndentation = indentation + " ";
- childLines = [];
- for (i in obj) {
- childLines.push(childIndentation + i + ": " + formatObjectExpansion(obj[i], childDepth, childIndentation));
- }
- output += childLines.join("," + newLine) + newLine + indentation + "}";
- return output;
- } else if (typeof obj == "string") {
- return obj;
- } else {
- return obj.toString();
- }
- }
- function escapeNewLines(str) {
- return str.replace(/\r\n|\r|\n/g, "\\r\\n");
- }
- function urlEncode(str) {
- return escape(str).replace(/\+/g, "%2B").replace(/"/g, "%22").replace(/'/g, "%27").replace(/\//g, "%2F");
- }
-
- function bool(obj) {
- return Boolean(obj);
- }
- function array_remove(arr, val) {
- var index = -1;
- for (var i = 0; i < arr.length; i++) {
- if (arr[i] === val) {
- index = i;
- break;
- }
- }
- if (index >= 0) {
- arr.splice(index, 1);
- return true;
- } else {
- return false;
- }
- }
- function extractBooleanFromParam(param, defaultValue) {
- if (isUndefined(param)) {
- return defaultValue;
- } else {
- return bool(param);
- }
- }
- function extractStringFromParam(param, defaultValue) {
- if (isUndefined(param)) {
- return defaultValue;
- } else {
- return String(param);
- }
- }
- function extractIntFromParam(param, defaultValue) {
- if (isUndefined(param)) {
- return defaultValue;
- } else {
- try {
- var value = parseInt(param, 10);
- return isNaN(value) ? defaultValue : value;
- } catch (ex) {
- logLog.warn("Invalid int param " + param, ex);
- return defaultValue;
- }
- }
- }
- function extractFunctionFromParam(param, defaultValue) {
- if (typeof param == "function") {
- return param;
- } else {
- return defaultValue;
- }
- }
- /* --------------------------------------------------------------------- */
- // Simple logging for log4javascript itself
- var logLog = {
- quietMode: false,
- setQuietMode: function(quietMode) {
- this.quietMode = bool(quietMode);
- },
- numberOfErrors: 0,
- alertAllErrors: false,
- setAlertAllErrors: function(alertAllErrors) {
- this.alertAllErrors = alertAllErrors;
- },
- debug: function(message, exception) {
- },
- warn: function(message, exception) {
- },
- error: function(message, exception) {
- if (++this.numberOfErrors == 1 || this.alertAllErrors) {
- if (!this.quietMode) {
- var alertMessage = "log4javascript error: " + message;
- if (exception) {
- alertMessage += newLine + newLine + "Original error: " + getExceptionStringRep(exception);
- }
- alert(alertMessage);
- }
- }
- }
- };
- log4javascript.logLog = logLog;
- /* --------------------------------------------------------------------- */
- var errorListeners = [];
- log4javascript.addErrorListener = function(listener) {
- if (typeof listener == "function") {
- errorListeners.push(listener);
- } else {
- handleError("addErrorListener: listener supplied was not a function");
- }
- };
- log4javascript.removeErrorListener = function(listener) {
- array_remove(errorListeners, listener);
- };
- function handleError(message, exception) {
- logLog.error(message, exception);
- for (var i = 0; i < errorListeners.length; i++) {
- errorListeners[i](message, exception);
- }
- }
- /* --------------------------------------------------------------------- */
- var enabled = (typeof log4javascript_disabled != "undefined") &&
- log4javascript_disabled ? false : true;
- log4javascript.setEnabled = function(enable) {
- enabled = bool(enable);
- };
- log4javascript.isEnabled = function() {
- return enabled;
- };
- // This evaluates the given expression in the current scope, thus allowing
- // scripts to access private variables. Particularly useful for testing
- log4javascript.evalInScope = function(expr) {
- return eval(expr);
- };
- var showStackTraces = false;
- log4javascript.setShowStackTraces = function(show) {
- showStackTraces = bool(show);
- };
- /* --------------------------------------------------------------------- */
- function Logger(name) {
- this.name = name;
- var appenders = [];
- var loggerLevel = Level.DEBUG;
- // Create methods that use the appenders variable in this scope
- this.addAppender = function(appender) {
- if (appender instanceof log4javascript.Appender) {
- appenders.push(appender);
- } else {
- handleError("Logger.addAppender: appender supplied is not a subclass of Appender");
- }
- };
- this.removeAppender = function(appender) {
- array_remove(appenders, appender);
- };
- this.removeAllAppenders = function(appender) {
- appenders.length = 0;
- };
- this.log = function(level, message, exception) {
- if (level.isGreaterOrEqual(loggerLevel)) {
- var loggingEvent = new LoggingEvent(
- this, new Date(), level, message, exception);
- for (var i = 0; i < appenders.length; i++) {
- appenders[i].doAppend(loggingEvent);
- }
- }
- };
- this.setLevel = function(level) {
- loggerLevel = level;
- };
- this.getLevel = function() {
- return loggerLevel;
- };
- }
- Logger.prototype = {
- trace: function(message, exception) {
- this.log(Level.TRACE, message, exception);
- },
- debug: function(message, exception) {
- this.log(Level.DEBUG, message, exception);
- },
- info: function(message, exception) {
- this.log(Level.INFO, message, exception);
- },
- warn: function(message, exception) {
- this.log(Level.WARN, message, exception);
- },
- error: function(message, exception) {
- this.log(Level.ERROR, message, exception);
- },
- fatal: function(message, exception) {
- this.log(Level.FATAL, message, exception);
- }
- };
- Logger.prototype.trace.isEntryPoint = true;
- Logger.prototype.debug.isEntryPoint = true;
- Logger.prototype.info.isEntryPoint = true;
- Logger.prototype.warn.isEntryPoint = true;
- Logger.prototype.error.isEntryPoint = true;
- Logger.prototype.fatal.isEntryPoint = true;
- /* --------------------------------------------------------------------- */
- // Hashtable of loggers keyed by logger name
- var loggers = {};
- log4javascript.getLogger = function(loggerName) {
- // Use default logger if loggerName is not specified or invalid
- if (!(typeof loggerName == "string")) {
- loggerName = "[anonymous]";
- }
- // Create the logger for this name if it doesn't already exist
- if (!loggers[loggerName]) {
- loggers[loggerName] = new Logger(loggerName);
- }
- return loggers[loggerName];
- };
- var defaultLogger = null;
- log4javascript.getDefaultLogger = function() {
- if (!defaultLogger) {
- defaultLogger = log4javascript.getLogger("[default]");
- var a = new log4javascript.PopUpAppender();
- defaultLogger.addAppender(a);
- }
- return defaultLogger;
- };
- var nullLogger = null;
- log4javascript.getNullLogger = function() {
- if (!nullLogger) {
- nullLogger = log4javascript.getLogger("[null]");
- }
- return nullLogger;
- };
- /* --------------------------------------------------------------------- */
- var Level = function(level, name) {
- this.level = level;
- this.name = name;
- };
- Level.prototype = {
- toString: function() {
- return this.name;
- },
- equals: function(level) {
- return this.level == level.level;
- },
- isGreaterOrEqual: function(level) {
- return this.level >= level.level;
- }
- };
- Level.ALL = new Level(Number.MIN_VALUE, "ALL");
- Level.TRACE = new Level(10000, "TRACE");
- Level.DEBUG = new Level(20000, "DEBUG");
- Level.INFO = new Level(30000, "INFO");
- Level.WARN = new Level(40000, "WARN");
- Level.ERROR = new Level(50000, "ERROR");
- Level.FATAL = new Level(60000, "FATAL");
- Level.OFF = new Level(Number.MAX_VALUE, "OFF");
- log4javascript.Level = Level;
- /* --------------------------------------------------------------------- */
- var LoggingEvent = function(logger, timeStamp, level, message,
- exception) {
- this.logger = logger;
- this.timeStamp = timeStamp;
- this.timeStampInSeconds = Math.floor(timeStamp.getTime() / 1000);
- this.level = level;
- this.message = message;
- this.exception = exception;
- };
- LoggingEvent.prototype.getThrowableStrRep = function() {
- return this.exception ?
- getExceptionStringRep(this.exception) : "";
- };
- log4javascript.LoggingEvent = LoggingEvent;
- /* --------------------------------------------------------------------- */
- // Layout "abstract class"
- var Layout = function() {
- };
- Layout.prototype = {
- defaults: {
- loggerKey: "logger",
- timeStampKey: "timestamp",
- levelKey: "level",
- messageKey: "message",
- exceptionKey: "exception",
- urlKey: "url"
- },
- loggerKey: "logger",
- timeStampKey: "timestamp",
- levelKey: "level",
- messageKey: "message",
- exceptionKey: "exception",
- urlKey: "url",
- batchHeader: "",
- batchFooter: "",
- batchSeparator: "",
- format: function(loggingEvent) {
- handleError("Layout.format: layout supplied has no format() method");
- },
- ignoresThrowable: function() {
- handleError("Layout.ignoresThrowable: layout supplied has no ignoresThrowable() method");
- },
- getContentType: function() {
- return "text/plain";
- },
- allowBatching: function() {
- return true;
- },
- getDataValues: function(loggingEvent) {
- var dataValues = [
- [this.loggerKey, loggingEvent.logger.name],
- [this.timeStampKey, loggingEvent.timeStampInSeconds],
- [this.levelKey, loggingEvent.level.name],
- [this.urlKey, window.location.href],
- [this.messageKey, loggingEvent.message]
- ];
- if (loggingEvent.exception) {
- dataValues.push([this.exceptionKey, getExceptionStringRep(loggingEvent.exception)]);
- }
- if (this.hasCustomFields()) {
- for (var i = 0; i < this.customFields.length; i++) {
- dataValues.push([this.customFields[i].name, this.customFields[i].value]);
- }
- }
- return dataValues;
- },
- setKeys: function(loggerKey, timeStampKey, levelKey, messageKey,
- exceptionKey, urlKey) {
- this.loggerKey = extractStringFromParam(loggerKey, this.defaults.loggerKey);
- this.timeStampKey = extractStringFromParam(timeStampKey, this.defaults.timeStampKey);
- this.levelKey = extractStringFromParam(levelKey, this.defaults.levelKey);
- this.messageKey = extractStringFromParam(messageKey, this.defaults.messageKey);
- this.exceptionKey = extractStringFromParam(exceptionKey, this.defaults.exceptionKey);
- this.urlKey = extractStringFromParam(urlKey, this.defaults.urlKey);
- },
- setCustomField: function(name, value) {
- var fieldUpdated = false;
- for (var i = 0; i < this.customFields.length; i++) {
- if (this.customFields[i].name === name) {
- this.customFields[i].value = value;
- fieldUpdated = true;
- }
- }
- if (!fieldUpdated) {
- this.customFields.push({"name": name, "value": value});
- }
- },
- hasCustomFields: function() {
- return (this.customFields.length > 0);
- }
- };
- log4javascript.Layout = Layout;
- /* --------------------------------------------------------------------- */
- // SimpleLayout
- var SimpleLayout = function() {
- this.customFields = [];
- };
- SimpleLayout.prototype = new Layout();
- SimpleLayout.prototype.format = function(loggingEvent) {
- return loggingEvent.level.name + " - " + loggingEvent.message;
- };
- SimpleLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return true;
- };
- log4javascript.SimpleLayout = SimpleLayout;
- /* --------------------------------------------------------------------- */
- // NullLayout
- var NullLayout = function() {
- this.customFields = [];
- };
- NullLayout.prototype = new Layout();
- NullLayout.prototype.format = function(loggingEvent) {
- return loggingEvent.message;
- };
- NullLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return true;
- };
- log4javascript.NullLayout = NullLayout;
- /* --------------------------------------------------------------------- */
- // XmlLayout
- var XmlLayout = function() {
- this.customFields = [];
- };
- XmlLayout.prototype = new Layout();
- XmlLayout.prototype.getContentType = function() {
- return "text/xml";
- };
- XmlLayout.prototype.escapeCdata = function(str) {
- return str.replace(/\]\]>/, "]]>]]><![CDATA[");
- };
- XmlLayout.prototype.format = function(loggingEvent) {
- var str = "<log4javascript:event logger=\"" + loggingEvent.logger.name +
- "\" timestamp=\"" + loggingEvent.timeStampInSeconds +
- "\" level=\"" + loggingEvent.level.name +
- "\">" + newLine + "<log4javascript:message><![CDATA[" +
- this.escapeCdata(loggingEvent.message.toString()) +
- "]]></log4javascript:message>" + newLine;
- if (this.hasCustomFields()) {
- for (var i = 0; i < this.customFields.length; i++) {
- str += "<log4javascript:customfield name=\"" +
- this.customFields[i].name + "\"><![CDATA[" +
- this.customFields[i].value.toString() +
- "]]></log4javascript:customfield>" + newLine;
- }
- }
- if (loggingEvent.exception) {
- str += "<log4javascript:exception><![CDATA[" +
- getExceptionStringRep(loggingEvent.exception) +
- "]]></log4javascript:exception>" + newLine;
- }
- str += "</log4javascript:event>" + newLine + newLine;
- return str;
- };
- XmlLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return false;
- };
- log4javascript.XmlLayout = XmlLayout;
- /* --------------------------------------------------------------------- */
- // JsonLayout
- var JsonLayout = function(readable, loggerKey, timeStampKey,
- levelKey, messageKey, exceptionKey, urlKey) {
- this.readable = bool(readable);
- this.batchHeader = this.readable ? "[" + newLine : "[";
- this.batchFooter = this.readable ? "]" + newLine : "]";
- this.batchSeparator = this.readable ? "," + newLine : ",";
- this.setKeys(loggerKey, timeStampKey, levelKey, messageKey,
- exceptionKey, urlKey);
- this.propertySeparator = this.readable ? ", " : ",";
- this.colon = this.readable ? ": " : ":";
- this.customFields = [];
- };
- JsonLayout.prototype = new Layout();
- JsonLayout.prototype.setReadable = function(readable) {
- this.readable = bool(readable);
- };
- JsonLayout.prototype.isReadable = function() {
- return this.readable;
- };
- JsonLayout.prototype.format = function(loggingEvent) {
- var dataValues = this.getDataValues(loggingEvent);
- var str = "{";
- if (this.readable) {
- str += newLine;
- }
- for (var i = 0; i < dataValues.length; i++) {
- if (this.readable) {
- str += "\t";
- }
- // Check the type of the data value to decide whether quotation marks
- // are required
- var valType = typeof dataValues[i][1];
- var val = (valType != "number" && valType != "boolean") ?
- "\"" + escapeNewLines(dataValues[i][1].toString().replace(/\"/g, "\\\"")) + "\"" :
- dataValues[i][1];
- str += "\"" + dataValues[i][0] + "\"" + this.colon + val;
- if (i < dataValues.length - 1) {
- str += this.propertySeparator;
- }
- if (this.readable) {
- str += newLine;
- }
- }
- str += "}";
- if (this.readable) {
- str += newLine;
- }
- return str;
- };
- JsonLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return false;
- };
- log4javascript.JsonLayout = JsonLayout;
- /* --------------------------------------------------------------------- */
- // HttpPostDataLayout
- var HttpPostDataLayout = function(loggerKey, timeStampKey,
- levelKey, messageKey, exceptionKey, urlKey) {
- this.setKeys(loggerKey, timeStampKey, levelKey, messageKey,
- exceptionKey, urlKey);
- this.customFields = [];
- };
- HttpPostDataLayout.prototype = new Layout();
- // Disable batching
- HttpPostDataLayout.prototype.allowBatching = function() {
- return false;
- };
- HttpPostDataLayout.prototype.format = function(loggingEvent) {
- var dataValues = this.getDataValues(loggingEvent);
- var queryBits = [];
- for (var i = 0; i < dataValues.length; i++) {
- queryBits.push(urlEncode(dataValues[i][0]) + "=" + urlEncode(dataValues[i][1]));
- }
- return queryBits.join("&");
- };
- HttpPostDataLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return false;
- };
- log4javascript.HttpPostDataLayout = HttpPostDataLayout;
- /* --------------------------------------------------------------------- */
- // PatternLayout
- var PatternLayout = function(pattern) {
- if (pattern) {
- this.pattern = pattern;
- } else {
- this.pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
- }
- this.customFields = [];
- };
- PatternLayout.TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n";
- PatternLayout.DEFAULT_CONVERSION_PATTERN = "%m%n";
- PatternLayout.ISO8601_DATEFORMAT = "yyyy-MM-dd HH:mm:ss,SSS";
- PatternLayout.DATETIME_DATEFORMAT = "dd MMM yyyy HH:mm:ss,SSS";
- PatternLayout.ABSOLUTETIME_DATEFORMAT = "HH:mm:ss,SSS";
- PatternLayout.prototype = new Layout();
- PatternLayout.prototype.format = function(loggingEvent) {
- var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([cdfmMnpr%])(\{([^\}]+)\})?|([^%]+)/;
- var formattedString = "";
- var result;
- var searchString = this.pattern;
- // Cannot use regex global flag since it doesn't work with exec in IE5
- while ((result = regex.exec(searchString))) {
- var matchedString = result[0];
- var padding = result[1];
- var truncation = result[2];
- var conversionCharacter = result[3];
- var specifier = result[5];
- var text = result[6];
- // Check if the pattern matched was just normal text
- if (text) {
- formattedString += "" + text;
- } else {
- // Create a raw replacement string based on the conversion
- // character and specifier
- var replacement = "";
- switch(conversionCharacter) {
- case "c": // Logger name
- var loggerName = loggingEvent.logger.name;
- if (specifier) {
- var precision = parseInt(specifier, 10);
- var loggerNameBits = loggingEvent.logger.name.split(".");
- if (precision >= loggerNameBits.length) {
- replacement = loggerName;
- } else {
- replacement = loggerNameBits.slice(loggerNameBits.length - precision).join(".");
- }
- } else {
- replacement = loggerName;
- }
- break;
- case "d": // Date
- var dateFormat = PatternLayout.ISO8601_DATEFORMAT;
- if (specifier) {
- dateFormat = specifier;
- // Pick up special cases
- if (dateFormat == "ISO8601") {
- dateFormat = PatternLayout.ISO8601_DATEFORMAT;
- } else if (dateFormat == "ABSOLUTE") {
- dateFormat = PatternLayout.ABSOLUTETIME_DATEFORMAT;
- } else if (dateFormat == "DATE") {
- dateFormat = PatternLayout.DATETIME_DATEFORMAT;
- }
- }
- // Format the date
- replacement = (new SimpleDateFormat(dateFormat)).format(loggingEvent.timeStamp);
- break;
- case "f": // Custom field
- if (this.hasCustomFields()) {
- var fieldIndex = 0;
- if (specifier) {
- fieldIndex = parseInt(specifier, 10);
- if (isNaN(fieldIndex)) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'f' - should be a number");
- } else if (fieldIndex === 0) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'f' - must be greater than zero");
- } else if (fieldIndex > this.customFields.length) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'f' - there aren't that many custom fields");
- } else {
- fieldIndex = fieldIndex - 1;
- }
- }
- replacement = this.customFields[fieldIndex].value;
- }
- break;
- case "m": // Message
- if (specifier) {
- var depth = parseInt(specifier, 10);
- if (isNaN(depth)) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'm' - should be a number");
- replacement = loggingEvent.message;
- } else {
- replacement = formatObjectExpansion(loggingEvent.message, depth);
- }
- } else {
- replacement = loggingEvent.message;
- }
- break;
- case "n": // New line
- replacement = newLine;
- break;
- case "p": // Level
- replacement = loggingEvent.level.name;
- break;
- case "r": // Milliseconds since log4javascript startup
- replacement = "" + loggingEvent.timeStamp.getDifference(applicationStartDate);
- break;
- case "%": // Literal % sign
- replacement = "%";
- break;
- default:
- replacement = matchedString;
- break;
- }
- // Format the replacement according to any padding or
- // truncation specified
- var len;
- // First, truncation
- if (truncation) {
- len = parseInt(truncation.substr(1), 10);
- var strLen = replacement.length;
- if (len < strLen) {
- replacement = replacement.substring(strLen - len, strLen);
- }
- }
- // Next, padding
- if (padding) {
- if (padding.charAt(0) == "-") {
- len = parseInt(padding.substr(1), 10);
- // Right pad with spaces
- while (replacement.length < len) {
- replacement += " ";
- }
- } else {
- len = parseInt(padding, 10);
- // Left pad with spaces
- while (replacement.length < len) {
- replacement = " " + replacement;
- }
- }
- }
- formattedString += replacement;
- }
- searchString = searchString.substr(result.index + result[0].length);
- }
- return formattedString;
- };
- PatternLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return true;
- };
- log4javascript.PatternLayout = PatternLayout;
- /* --------------------------------------------------------------------- */
- // Appender "abstract class"
- var Appender = function() {};
- // Performs threshold checks before delegating actual logging to the
- // subclass's specific append method.
- Appender.prototype = {
- layout: new PatternLayout(),
- threshold: Level.ALL,
- doAppend: function(loggingEvent) {
- if (enabled && loggingEvent.level.level >= this.threshold.level) {
- this.append(loggingEvent);
- }
- },
- append: function(loggingEvent) {},
- setLayout: function(layout) {
- if (layout instanceof Layout) {
- this.layout = layout;
- } else {
- handleError("Appender.setLayout: layout supplied to " +
- this.toString() + " is not a subclass of Layout");
- }
- },
- getLayout: function() {
- return this.layout;
- },
- setThreshold: function(threshold) {
- if (threshold instanceof Level) {
- this.threshold = threshold;
- } else {
- handleError("Appender.setThreshold: threshold supplied to " +
- this.toString() + " is not a subclass of Level");
- }
- },
- getThreshold: function() {
- return this.threshold;
- },
- toString: function() {
- return "[Base Appender]";
- }
- };
- log4javascript.Appender = Appender;
- /* --------------------------------------------------------------------- */
- // AlertAppender
- var AlertAppender = function(layout) {
- if (layout) {
- this.setLayout(layout);
- }
- };
- AlertAppender.prototype = new Appender();
- AlertAppender.prototype.layout = new SimpleLayout();
- AlertAppender.prototype.append = function(loggingEvent) {
- var formattedMessage = this.getLayout().format(loggingEvent);
- if (this.getLayout().ignoresThrowable()) {
- formattedMessage += loggingEvent.getThrowableStrRep();
- }
- alert(formattedMessage);
- };
- AlertAppender.prototype.toString = function() {
- return "[AlertAppender]";
- };
- log4javascript.AlertAppender = AlertAppender;
- /* --------------------------------------------------------------------- */
- // AjaxAppender
- var AjaxAppender = function(url, layout, timed, waitForResponse,
- batchSize, timerInterval, requestSuccessCallback, failCallback) {
- var appender = this;
- var isSupported = true;
- if (!url) {
- handleError("AjaxAppender: URL must be specified in constructor");
- isSupported = false;
- }
- timed = extractBooleanFromParam(timed, this.defaults.timed);
- waitForResponse = extractBooleanFromParam(waitForResponse, this.defaults.waitForResponse);
- batchSize = extractIntFromParam(batchSize, this.defaults.batchSize);
- timerInterval = extractIntFromParam(timerInterval, this.defaults.timerInterval);
- requestSuccessCallback = extractFunctionFromParam(requestSuccessCallback, this.defaults.requestSuccessCallback);
- failCallback = extractFunctionFromParam(failCallback, this.defaults.failCallback);
- var sessionId = null;
- var queuedLoggingEvents = [];
- var queuedRequests = [];
- var sending = false;
- var initialized = false;
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- function checkCanConfigure(configOptionName) {
- if (initialized) {
- handleError("AjaxAppender: configuration option '" + configOptionName + "' may not be set after the appender has been initialized");
- return false;
- }
- return true;
- }
- this.getSessionId = function() { return sessionId; };
- this.setSessionId = function(sessionIdParam) {
- sessionId = extractStringFromParam(sessionIdParam, null);
- this.layout.setCustomField("sessionid", sessionId);
- };
- this.setLayout = function(layout) {
- if (checkCanConfigure("layout")) {
- this.layout = layout;
- // Set the session id as a custom field on the layout, if not already present
- if (sessionId !== null) {
- this.setSessionId(sessionId);
- }
- }
- };
- if (layout) {
- this.setLayout(layout);
- }
- this.isTimed = function() { return timed; };
- this.setTimed = function(timedParam) {
- if (checkCanConfigure("timed")) {
- timed = bool(timedParam);
- }
- };
- this.getTimerInterval = function() { return timerInterval; };
- this.setTimerInterval = function(timerIntervalParam) {
- if (checkCanConfigure("timerInterval")) {
- timerInterval = extractIntFromParam(timerIntervalParam, timerInterval);
- }
- };
- this.isWaitForResponse = function() { return waitForResponse; };
- this.setWaitForResponse = function(waitForResponseParam) {
- if (checkCanConfigure("waitForResponse")) {
- waitForResponse = bool(waitForResponseParam);
- }
- };
- this.getBatchSize = function() { return batchSize; };
- this.setBatchSize = function(batchSizeParam) {
- if (checkCanConfigure("batchSize")) {
- batchSize = extractIntFromParam(batchSizeParam, batchSize);
- }
- };
- this.setRequestSuccessCallback = function(requestSuccessCallbackParam) {
- requestSuccessCallback = extractFunctionFromParam(requestSuccessCallbackParam, requestSuccessCallback);
- };
- this.setFailCallback = function(failCallbackParam) {
- failCallback = extractFunctionFromParam(failCallbackParam, failCallback);
- };
- // Internal functions
- function sendAll() {
- if (isSupported && enabled) {
- sending = true;
- var currentRequestBatch;
- if (waitForResponse) {
- // Send the first request then use this function as the callback once
- // the response comes back
- if (queuedRequests.length > 0) {
- currentRequestBatch = queuedRequests.shift();
- sendRequest(preparePostData(currentRequestBatch), sendAll);
- } else {
- sending = false;
- if (timed) {
- scheduleSending();
- }
- }
- } else {
- // Rattle off all the requests without waiting to see the response
- while ((currentRequestBatch = queuedRequests.shift())) {
- sendRequest(preparePostData(currentRequestBatch));
- }
- sending = false;
- if (timed) {
- scheduleSending();
- }
- }
- }
- }
- this.sendAll = sendAll;
- function preparePostData(batchedLoggingEvents) {
- // Format the logging events
- var formattedMessages = [];
- var currentLoggingEvent;
- var postData = "";
- while ((currentLoggingEvent = batchedLoggingEvents.shift())) {
- var currentFormattedMessage = appender.getLayout().format(currentLoggingEvent);
- if (appender.getLayout().ignoresThrowable()) {
- currentFormattedMessage += loggingEvent.getThrowableStrRep();
- }
- formattedMessages.push(currentFormattedMessage);
- }
- // Create the post data string
- if (batchedLoggingEvents.length == 1) {
- postData = formattedMessages.join("");
- } else {
- postData = appender.getLayout().batchHeader +
- formattedMessages.join(appender.getLayout().batchSeparator) +
- appender.getLayout().batchFooter;
- }
- return postData;
- }
- function scheduleSending() {
- setTimeout(sendAll, timerInterval);
- }
- function getXmlHttp() {
- var xmlHttp = null;
- if (typeof XMLHttpRequest == "object" || typeof XMLHttpRequest == "function") {
- xmlHttp = new XMLHttpRequest();
- } else {
- try {
- xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
- } catch (e2){
- try {
- xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
- } catch (e3) {
- var msg = "AjaxAppender: could not create XMLHttpRequest object. AjaxAppender disabled";
- handleError(msg);
- isSupported = false;
- if (failCallback) {
- failCallback(msg);
- }
- }
- }
- }
- return xmlHttp;
- }
- function sendRequest(postData, successCallback) {
- try {
- var xmlHttp = getXmlHttp();
- if (isSupported) {
- if (xmlHttp.overrideMimeType) {
- xmlHttp.overrideMimeType(appender.getLayout().getContentType());
- }
- xmlHttp.onreadystatechange = function() {
- if (xmlHttp.readyState == 4) {
- var success = (isUndefined(xmlHttp.status) || xmlHttp.status === 0 ||
- (xmlHttp.status >= 200 && xmlHttp.status < 300));
- if (success) {
- if (requestSuccessCallback) {
- requestSuccessCallback(xmlHttp);
- }
- if (successCallback) {
- successCallback(xmlHttp);
- }
- } else {
- var msg = "AjaxAppender.append: XMLHttpRequest request to URL " +
- url + " returned status code " + xmlHttp.status;
- handleError(msg);
- if (failCallback) {
- failCallback(msg);
- }
- }
- xmlHttp.onreadystatechange = emptyFunction;
- xmlHttp = null;
- }
- };
- xmlHttp.open("POST", url, true);
- try {
- xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- } catch (headerEx) {
- var msg = "AjaxAppender.append: your browser's XMLHttpRequest implementation" +
- " does not support setRequestHeader, therefore cannot post data. AjaxAppender disabled";
- handleError(msg);
- isSupported = false;
- if (failCallback) {
- failCallback(msg);
- }
- return;
- }
- xmlHttp.send(postData);
- }
- } catch (ex) {
- var msg = "AjaxAppender.append: error sending log message to " + url;
- handleError(msg, ex);
- if (failCallback) {
- failCallback(msg + ". Details: " + getExceptionStringRep(ex));
- }
- }
- }
- this.append = function(loggingEvent) {
- if (isSupported) {
- if (!initialized) {
- init();
- }
- queuedLoggingEvents.push(loggingEvent);
- var actualBatchSize = this.getLayout().allowBatching() ? batchSize : 1;
- if (queuedLoggingEvents.length >= actualBatchSize) {
- var currentLoggingEvent;
- var postData = "";
- var batchedLoggingEvents = [];
- while ((currentLoggingEvent = queuedLoggingEvents.shift())) {
- batchedLoggingEvents.push(currentLoggingEvent);
- }
- // Queue this batch of log entries
- queuedRequests.push(batchedLoggingEvents);
- // If using a timer, the queue of requests will be processed by the
- // timer function, so nothing needs to be done here.
- if (!timed) {
- if (!waitForResponse || (waitForResponse && !sending)) {
- sendAll();
- }
- }
- }
- }
- };
- function init() {
- initialized = true;
- // Start timer
- if (timed) {
- scheduleSending();
- }
- }
- };
- AjaxAppender.prototype = new Appender();
- AjaxAppender.prototype.defaults = {
- waitForResponse: false,
- timed: false,
- timerInterval: 1000,
- batchSize: 1,
- requestSuccessCallback: null,
- failCallback: null
- };
- AjaxAppender.prototype.layout = new HttpPostDataLayout();
- AjaxAppender.prototype.toString = function() {
- return "[AjaxAppender]";
- };
- log4javascript.AjaxAppender = AjaxAppender;
- /* --------------------------------------------------------------------- */
- // BaseConsoleAppender
- // Create an anonymous function to protect base console methods
- (function() {
- var getConsoleHtmlLines = function() {
- return [
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
- '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">',
- ' <head>',
- ' <title>log4javascript</title>',
- ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
- ' <script type="text/javascript">',
- ' //<![CDATA[',
- ' var loggingEnabled = true;',
- '',
- ' function toggleLoggingEnabled() {',
- ' setLoggingEnabled($("enableLogging").checked);',
- ' }',
- '',
- ' function setLoggingEnabled(enable) {',
- ' loggingEnabled = enable;',
- ' }',
- '',
- ' var newestAtTop = false;',
- '',
- ' function setNewestAtTop(isNewestAtTop) {',
- ' var oldNewestAtTop = newestAtTop;',
- ' newestAtTop = Boolean(isNewestAtTop);',
- ' if (oldNewestAtTop != newestAtTop) {',
- ' // Invert the order of the log entries',
- ' var lc = getLogContainer();',
- ' var numberOfEntries = lc.childNodes.length;',
- ' var node = null;',
- '',
- ' // Remove all the log container nodes',
- ' var logContainerChildNodes = [];',
- ' while ((node = lc.firstChild)) {',
- ' lc.removeChild(node);',
- ' logContainerChildNodes.push(node);',
- ' }',
- '',
- ' // Put them all back in reverse order',
- ' while ((node = logContainerChildNodes.pop())) {',
- ' lc.appendChild(node);',
- ' }',
- '',
- ' // Reassemble the matches array',
- ' if (currentSearch) {',
- ' var currentMatch = currentSearch.matches[currentMatchIndex];',
- ' var matchIndex = 0;',
- ' var matches = [];',
- ' var actOnLogEntry = function(logEntry) {',
- ' var logEntryMatches = logEntry.getSearchMatches();',
- ' for (var i = 0; i < logEntryMatches.length; i++) {',
- ' matches[matchIndex] = logEntryMatches[i];',
- ' if (currentMatch && logEntryMatches[i].equals(currentMatch)) {',
- ' currentMatchIndex = matchIndex;',
- ' }',
- ' matchIndex++;',
- ' }',
- ' };',
- ' var i;',
- ' if (newestAtTop) {',
- ' for (i = logEntries.length - 1; i >= 0; i--) {',
- ' actOnLogEntry(logEntries[i]);',
- ' }',
- ' } else {',
- ' for (i = 0; i < logEntries.length; i++) {',
- ' actOnLogEntry(logEntries[i]);',
- ' }',
- ' }',
- ' currentSearch.matches = matches;',
- ' if (currentMatch) {',
- ' currentMatch.setCurrent();',
- ' }',
- ' } else if (scrollToLatest) {',
- ' doScrollToLatest();',
- ' }',
- ' }',
- ' $("newestAtTop").checked = isNewestAtTop;',
- ' }',
- '',
- ' function toggleNewestAtTop() {',
- ' var isNewestAtTop = $("newestAtTop").checked;',
- ' setNewestAtTop(isNewestAtTop);',
- ' }',
- '',
- ' var scrollToLatest = true;',
- '',
- ' function setScrollToLatest(isScrollToLatest) {',
- ' scrollToLatest = isScrollToLatest;',
- ' if (scrollToLatest) {',
- ' doScrollToLatest();',
- ' }',
- ' $("scrollToLatest").checked = isScrollToLatest;',
- ' }',
- '',
- ' function toggleScrollToLatest() {',
- ' var isScrollToLatest = $("scrollToLatest").checked;',
- ' setScrollToLatest(isScrollToLatest);',
- ' }',
- '',
- ' function doScrollToLatest() {',
- ' var l = getLogContainer();',
- ' if (typeof l.scrollTop != "undefined") {',
- ' if (newestAtTop) {',
- ' l.scrollTop = 0;',
- ' } else {',
- ' var latestLogEntry = l.lastChild;',
- ' if (latestLogEntry) {',
- ' l.scrollTop = l.scrollHeight;',
- ' }',
- ' }',
- ' }',
- ' }',
- '',
- ' var maxMessages = null;',
- '',
- ' function setMaxMessages(max) {',
- ' maxMessages = max;',
- ' pruneLogEntries();',
- ' }',
- '',
- ' var logQueuedEventsTimer = null;',
- ' var logEntries = [];',
- ' var isCssWrapSupported;',
- ' var renderDelay = 100;',
- '',
- ' function log(logLevel, formattedMessage) {',
- ' if (loggingEnabled) {',
- ' var logEntry = new LogEntry(logLevel, formattedMessage);',
- ' logEntries.push(logEntry);',
- ' if (loaded) {',
- ' if (logQueuedEventsTimer !== null) {',
- ' clearTimeout(logQueuedEventsTimer);',
- ' }',
- ' setTimeout(renderQueuedLogEntries, renderDelay);',
- ' }',
- ' }',
- ' }',
- '',
- ' function renderQueuedLogEntries() {',
- ' logQueuedEventsTimer = null;',
- ' var pruned = pruneLogEntries();',
- '',
- ' // Render any unrendered log entries and apply the current search to them',
- ' var initiallyHasMatches = currentSearch ? currentSearch.hasMatches() : false;',
- ' for (var i = 0; i < logEntries.length; i++) {',
- ' if (!logEntries[i].isRendered) {',
- ' logEntries[i].render();',
- ' logEntries[i].appendToLog();',
- ' if (currentSearch) {',
- ' currentSearch.applyTo(logEntries[i]);',
- ' }',
- ' }',
- ' }',
- ' if (currentSearch) {',
- ' if (pruned) {',
- ' if (currentSearch.hasMatches()) {',
- ' if (currentMatchIndex === null) {',
- ' setCurrentMatchIndex(0);',
- ' }',
- ' displayMatches();',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' } else if (!initiallyHasMatches && currentSearch.hasMatches()) {',
- ' setCurrentMatchIndex(0);',
- ' displayMatches();',
- ' }',
- ' }',
- ' if (scrollToLatest) {',
- ' doScrollToLatest();',
- ' }',
- ' }',
- '',
- ' function pruneLogEntries() {',
- ' if ((maxMessages !== null) && (logEntries.length > maxMessages)) {',
- ' var numberToDelete = logEntries.length - maxMessages;',
- ' for (var i = 0; i < numberToDelete; i++) {',
- ' logEntries[i].remove();',
- ' }',
- ' logEntries = array_removeFromStart(logEntries, numberToDelete);',
- ' if (currentSearch) {',
- ' currentSearch.removePrunedMatches();',
- ' }',
- ' return true;',
- ' }',
- ' return false;',
- ' }',
- '',
- ' function LogEntry(level, formattedMessage) {',
- ' this.level = level;',
- ' this.formattedMessage = formattedMessage;',
- ' this.isRendered = false;',
- ' }',
- '',
- ' LogEntry.prototype = {',
- ' render: function() {',
- ' this.mainDiv = document.createElement("div");',
- ' this.mainDiv.className = "logentry " + this.level.name;',
- ' ',
- ' // Support for the CSS attribute white-space in IE for Windows is',
- ' // non-existent pre version 6 and slightly odd in 6, so instead',
- ' // use two different HTML elements',
- ' if (isCssWrapSupported) {',
- ' this.mainDiv.appendChild(document.createTextNode(this.formattedMessage));',
- ' } else {',
- ' this.formattedMessage = this.formattedMessage.replace(/\\r\\n/g, "\\r"); // Workaround for IE\'s treatment of white space',
- ' this.unwrappedPre = this.mainDiv.appendChild(document.createElement("pre"));',
- ' this.unwrappedPre.appendChild(document.createTextNode(this.formattedMessage));',
- ' this.unwrappedPre.className = "unwrapped";',
- ' this.wrappedSpan = this.mainDiv.appendChild(document.createElement("span"));',
- ' this.wrappedSpan.appendChild(document.createTextNode(this.formattedMessage));',
- ' this.wrappedSpan.className = "wrapped";',
- ' }',
- ' this.content = this.formattedMessage;',
- ' this.isRendered = true;',
- ' },',
- ' ',
- ' appendToLog: function() {',
- ' var lc = getLogContainer();',
- ' if (newestAtTop && lc.hasChildNodes()) {',
- ' lc.insertBefore(this.mainDiv, lc.firstChild);',
- ' } else {',
- ' getLogContainer().appendChild(this.mainDiv);',
- ' }',
- ' },',
- ' ',
- ' setContent: function(content) {',
- ' if (content != this.content) {',
- ' if (getLogContainer().currentStyle) {',
- ' if (content === this.formattedMessage) {',
- ' this.unwrappedPre.innerHTML = "";',
- ' this.unwrappedPre.appendChild(document.createTextNode(this.formattedMessage));',
- ' this.wrappedSpan.innerHTML = "";',
- ' this.wrappedSpan.appendChild(document.createTextNode(this.formattedMessage));',
- ' } else {',
- ' content = content.replace(/\\r\\n/g, "\\r"); // Workaround for IE\'s treatment of white space',
- ' this.unwrappedPre.innerHTML = content;',
- ' this.wrappedSpan.innerHTML = content;',
- ' }',
- ' } else {',
- ' if (content === this.formattedMessage) {',
- ' this.mainDiv.innerHTML = "";',
- ' this.mainDiv.appendChild(document.createTextNode(this.formattedMessage));',
- ' } else {',
- ' this.mainDiv.innerHTML = content;',
- ' }',
- ' }',
- ' this.content = content;',
- ' }',
- ' },',
- '',
- ' getSearchMatches: function() {',
- ' var matches = [];',
- ' if (isCssWrapSupported) {',
- ' var els = getElementsByClass(this.mainDiv, "searchterm", "span");',
- ' for (var i = 0; i < els.length; i++) {',
- ' matches[i] = new Match(this.level, els[i]);',
- ' }',
- ' } else {',
- ' var unwrappedEls = getElementsByClass(this.unwrappedPre, "searchterm", "span");',
- ' var wrappedEls = getElementsByClass(this.wrappedSpan, "searchterm", "span");',
- ' for (i = 0; i < unwrappedEls.length; i++) {',
- ' matches[i] = new Match(this.level, null, unwrappedEls[i], wrappedEls[i]);',
- ' }',
- ' }',
- ' return matches;',
- ' },',
- '',
- ' remove: function() {',
- ' if (this.isRendered) {',
- ' this.mainDiv.parentNode.removeChild(this.mainDiv);',
- ' this.mainDiv = null;',
- ' }',
- ' }',
- ' };',
- '',
- ' function mainPageReloaded() {',
- ' var separator = document.createElement("div");',
- ' separator.className = "separator";',
- ' separator.innerHTML = " ";',
- ' getLogContainer().appendChild(separator);',
- ' }',
- '',
- ' window.onload = function() {',
- ' isCssWrapSupported = (typeof getLogContainer().currentStyle == "undefined");',
- ' setLogContainerHeight();',
- ' toggleLoggingEnabled();',
- ' toggleSearchEnabled();',
- ' toggleSearchFilter();',
- ' toggleSearchHighlight();',
- ' applyFilters();',
- ' toggleWrap();',
- ' toggleNewestAtTop();',
- ' toggleScrollToLatest();',
- ' //doSearch();',
- ' renderQueuedLogEntries();',
- ' loaded = true;',
- ' // Workaround to make sure log div starts at the correct size',
- ' setTimeout(setLogContainerHeight, 20);',
- '',
- ' // Remove "Close" button if not in pop-up mode',
- ' if (window != top) {',
- ' $("closeButton").style.display = "none";',
- ' }',
- ' };',
- '',
- ' var loaded = false;',
- '',
- ' var logLevels = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"];',
- '',
- ' function getCheckBox(logLevel) {',
- ' return $("switch_" + logLevel);',
- ' }',
- '',
- ' function getLogContainer() {',
- ' return $("log");',
- ' }',
- '',
- ' function applyFilters() {',
- ' for (var i = 0; i < logLevels.length; i++) {',
- ' if (getCheckBox(logLevels[i]).checked) {',
- ' addClass(getLogContainer(), logLevels[i]);',
- ' } else {',
- ' removeClass(getLogContainer(), logLevels[i]);',
- ' }',
- ' }',
- ' updateSearchFromFilters();',
- ' }',
- '',
- ' function toggleAllLevels() {',
- ' var turnOn = $("switch_ALL").checked;',
- ' for (var i = 0; i < logLevels.length; i++) {',
- ' getCheckBox(logLevels[i]).checked = turnOn;',
- ' if (turnOn) {',
- ' addClass(getLogContainer(), logLevels[i]);',
- ' } else {',
- ' removeClass(getLogContainer(), logLevels[i]);',
- ' }',
- ' }',
- ' }',
- '',
- ' function checkAllLevels() {',
- ' for (var i = 0; i < logLevels.length; i++) {',
- ' if (!getCheckBox(logLevels[i]).checked) {',
- ' getCheckBox("ALL").checked = false;',
- ' return;',
- ' }',
- ' }',
- ' getCheckBox("ALL").checked = true;',
- ' }',
- '',
- ' function clearLog() {',
- ' getLogContainer().innerHTML = "";',
- ' logEntries = [];',
- ' doSearch();',
- ' }',
- '',
- ' function toggleWrap() {',
- ' var enable = $("wrap").checked;',
- ' if (enable) {',
- ' addClass(getLogContainer(), "wrap");',
- ' } else {',
- ' removeClass(getLogContainer(), "wrap");',
- ' }',
- ' refreshCurrentMatch();',
- ' }',
- '',
- ' /* ------------------------------------------------------------------- */',
- '',
- ' // Search',
- '',
- ' var searchTimer = null;',
- '',
- ' function scheduleSearch() {',
- ' try {',
- ' clearTimeout(searchTimer);',
- ' } catch (ex) {',
- ' // Do nothing',
- ' }',
- ' searchTimer = setTimeout(doSearch, 500);',
- ' }',
- '',
- ' function Search(searchTerm, isRegex, searchRegex, isCaseSensitive) {',
- ' this.searchTerm = searchTerm;',
- ' this.isRegex = isRegex;',
- ' this.searchRegex = searchRegex;',
- ' this.isCaseSensitive = isCaseSensitive;',
- ' this.matches = [];',
- ' }',
- '',
- ' Search.prototype = {',
- ' hasMatches: function() {',
- ' return this.matches.length > 0;',
- ' },',
- '',
- ' hasVisibleMatches: function() {',
- ' if (this.hasMatches()) {',
- ' for (var i = 0; i <= this.matches.length; i++) {',
- ' if (this.matches[i].isVisible()) {',
- ' return true;',
- ' }',
- ' }',
- ' }',
- ' return false;',
- ' },',
- '',
- ' match: function(logEntry) {',
- ' var entryText = logEntry.formattedMessage;',
- ' var matchesSearch = false;',
- ' if (this.isRegex) {',
- ' matchesSearch = this.searchRegex.test(entryText);',
- ' } else if (this.isCaseSensitive) {',
- ' matchesSearch = (entryText.indexOf(this.searchTerm) > -1);',
- ' } else {',
- ' matchesSearch = (entryText.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1);',
- ' }',
- ' return matchesSearch;',
- ' },',
- ' ',
- ' getNextVisibleMatchIndex: function() {',
- ' for (var i = currentMatchIndex + 1; i < this.matches.length; i++) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' // Start again from the first match',
- ' for (var i = 0; i <= currentMatchIndex; i++) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' return -1;',
- ' },',
- '',
- ' getPreviousVisibleMatchIndex: function() {',
- ' for (var i = currentMatchIndex - 1; i >= 0; i--) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' // Start again from the last match',
- ' for (var i = this.matches.length - 1; i >= currentMatchIndex; i--) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' return -1;',
- ' },',
- '',
- ' applyTo: function(logEntry) {',
- ' var doesMatch = this.match(logEntry);',
- ' if (doesMatch) {',
- ' replaceClass(logEntry.mainDiv, "searchmatch", "searchnonmatch");',
- ' var logEntryContent;',
- ' if (this.isRegex) {',
- ' var flags = this.isCaseSensitive ? "g" : "gi";',
- ' var capturingRegex = new RegExp("(" + this.searchRegex.source + ")", flags);',
- ' logEntryContent = logEntry.formattedMessage.replace(capturingRegex, "<span class=\\\"searchterm\\\">$1</span>");',
- ' } else {',
- ' logEntryContent = "";',
- ' var searchTermReplacementStartTag = "<span class=\\\"searchterm\\\">";',
- ' var searchTermReplacementEndTag = "</span>";',
- ' var searchTermReplacementLength = searchTermReplacementStartTag.length + this.searchTerm.length + searchTermReplacementEndTag.length;',
- ' var searchTermLength = this.searchTerm.length;',
- ' var startIndex = 0;',
- ' var searchIndex;',
- ' var searchTermLowerCase = this.searchTerm.toLowerCase();',
- ' var logTextLowerCase = logEntry.formattedMessage.toLowerCase();',
- ' while ((searchIndex = logTextLowerCase.indexOf(searchTermLowerCase, startIndex)) > -1) {',
- ' var searchTermReplacement = searchTermReplacementStartTag + logEntry.formattedMessage.substr(searchIndex, this.searchTerm.length) + searchTermReplacementEndTag;',
- ' logEntryContent += logEntry.formattedMessage.substring(startIndex, searchIndex) + searchTermReplacement;',
- ' startIndex = searchIndex + searchTermLength;',
- ' }',
- ' logEntryContent += logEntry.formattedMessage.substr(startIndex);',
- ' }',
- ' logEntry.setContent(logEntryContent);',
- ' var logEntryMatches = logEntry.getSearchMatches();',
- ' this.matches = this.matches.concat(logEntryMatches);',
- ' } else {',
- ' replaceClass(logEntry.mainDiv, "searchnonmatch", "searchmatch");',
- ' logEntry.setContent(logEntry.formattedMessage);',
- ' }',
- ' return doesMatch;',
- ' },',
- '',
- ' removePrunedMatches: function() {',
- ' var matchesToRemoveCount = 0;',
- ' var currentMatchRemoved = false;',
- ' for (var i = 0; i < this.matches.length; i++) {',
- ' if (this.matches[i].isOrphan()) {',
- ' this.matches[i].remove();',
- ' if (i === currentMatchIndex) {',
- ' currentMatchRemoved = true;',
- ' }',
- ' matchesToRemoveCount++;',
- ' }',
- ' }',
- ' if (matchesToRemoveCount > 0) {',
- ' array_removeFromStart(this.matches, matchesToRemoveCount);',
- ' var newMatchIndex = currentMatchRemoved ? 0 :',
- ' currentMatchIndex - matchesToRemoveCount;',
- ' if (this.hasMatches()) {',
- ' setCurrentMatchIndex(newMatchIndex);',
- ' } else {',
- ' currentMatchIndex = null;',
- ' }',
- ' }',
- ' }',
- ' };',
- '',
- ' function getPageOffsetTop(el) {',
- ' var currentEl = el;',
- ' var y = 0;',
- ' while (currentEl) {',
- ' y += currentEl.offsetTop;',
- ' currentEl = currentEl.offsetParent;',
- ' }',
- ' return y;',
- ' }',
- '',
- ' function scrollIntoView(el) {',
- ' getLogContainer().scrollLeft = el.offsetLeft;',
- ' getLogContainer().scrollTop = getPageOffsetTop(el) - getToolBarsHeight();',
- ' }',
- '',
- ' function Match(logEntryLevel, spanInMainDiv, spanInUnwrappedPre, spanInWrappedSpan) {',
- ' this.logEntryLevel = logEntryLevel;',
- ' this.spanInMainDiv = spanInMainDiv;',
- ' if (!isCssWrapSupported) {',
- ' this.spanInUnwrappedPre = spanInUnwrappedPre;',
- ' this.spanInWrappedSpan = spanInWrappedSpan;',
- ' }',
- ' this.mainSpan = isCssWrapSupported ? spanInMainDiv : spanInUnwrappedPre;',
- ' }',
- '',
- ' Match.prototype = {',
- ' equals: function(match) {',
- ' return this.mainSpan === match.mainSpan;',
- ' },',
- '',
- ' setCurrent: function() {',
- ' if (isCssWrapSupported) {',
- ' addClass(this.spanInMainDiv, "currentmatch");',
- ' scrollIntoView(this.spanInMainDiv);',
- ' } else {',
- ' addClass(this.spanInUnwrappedPre, "currentmatch");',
- ' addClass(this.spanInWrappedSpan, "currentmatch");',
- ' // Scroll the visible one into view',
- ' var elementToScroll = $("wrap").checked ? this.spanInWrappedSpan : this.spanInUnwrappedPre;',
- ' scrollIntoView(elementToScroll);',
- ' }',
- ' },',
- '',
- ' setNotCurrent: function() {',
- ' if (isCssWrapSupported) {',
- ' removeClass(this.spanInMainDiv, "currentmatch");',
- ' } else {',
- ' removeClass(this.spanInUnwrappedPre, "currentmatch");',
- ' removeClass(this.spanInWrappedSpan, "currentmatch");',
- ' }',
- ' },',
- '',
- ' isOrphan: function() {',
- ' return isOrphan(this.mainSpan);',
- ' },',
- '',
- ' isVisible: function() {',
- ' return getCheckBox(this.logEntryLevel).checked;',
- ' },',
- '',
- ' remove: function() {',
- ' if (isCssWrapSupported) {',
- ' this.spanInMainDiv = null;',
- ' } else {',
- ' this.spanInUnwrappedPre = null;',
- ' this.spanInWrappedSpan = null;',
- ' }',
- ' }',
- ' };',
- '',
- ' var currentSearch = null;',
- ' var currentMatchIndex = null;',
- '',
- ' function doSearch() {',
- ' var searchBox = $("searchBox");',
- ' var searchTerm = searchBox.value;',
- ' var isRegex = $("searchRegex").checked;',
- ' var isCaseSensitive = $("searchCaseSensitive").checked;',
- ' var i;',
- '',
- ' if (searchTerm === "") {',
- ' $("searchReset").disabled = true;',
- ' $("searchNav").style.display = "none";',
- ' removeClass(document.body, "searching");',
- ' removeClass(searchBox, "hasmatches");',
- ' removeClass(searchBox, "nomatches");',
- ' for (i = 0; i < logEntries.length; i++) {',
- ' removeClass(logEntries[i].mainDiv, "searchmatch");',
- ' removeClass(logEntries[i].mainDiv, "searchnonmatch");',
- ' logEntries[i].setContent(logEntries[i].formattedMessage);',
- ' }',
- ' currentSearch = null;',
- ' setLogContainerHeight();',
- ' } else {',
- ' $("searchReset").disabled = false;',
- ' $("searchNav").style.display = "block";',
- ' var searchRegex;',
- ' var regexValid;',
- ' if (isRegex) {',
- ' try {',
- ' searchRegex = isCaseSensitive ? new RegExp(searchTerm, "g") : new RegExp(searchTerm, "gi");',
- ' regexValid = true;',
- ' replaceClass(searchBox, "validregex", "invalidregex");',
- ' searchBox.title = "Valid regex";',
- ' } catch (ex) {',
- ' regexValid = false;',
- ' replaceClass(searchBox, "invalidregex", "validregex");',
- ' searchBox.title = "Invalid regex: " + (ex.message ? ex.message : (ex.description ? ex.description : "unknown error"));',
- ' return;',
- ' }',
- ' } else {',
- ' searchBox.title = "";',
- ' removeClass(searchBox, "validregex");',
- ' removeClass(searchBox, "invalidregex");',
- ' }',
- ' addClass(document.body, "searching");',
- ' currentSearch = new Search(searchTerm, isRegex, searchRegex, isCaseSensitive);',
- ' for (i = 0; i < logEntries.length; i++) {',
- ' currentSearch.applyTo(logEntries[i]);',
- ' }',
- ' setLogContainerHeight();',
- '',
- ' // Highlight the first search match',
- ' if (currentSearch.hasMatches()) {',
- ' setCurrentMatchIndex(0);',
- ' displayMatches();',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' }',
- ' }',
- ' ',
- ' function updateSearchFromFilters() {',
- ' if (currentSearch && currentSearch.hasMatches()) {',
- ' var currentMatch = currentSearch.matches[currentMatchIndex];',
- ' if (currentMatch.isVisible()) {',
- ' displayMatches();',
- ' setCurrentMatchIndex(currentMatchIndex);',
- ' } else {',
- ' currentMatch.setNotCurrent();',
- ' // Find the next visible match, if one exists',
- ' var nextVisibleMatchIndex = currentSearch.getNextVisibleMatchIndex();',
- ' if (nextVisibleMatchIndex > -1) {',
- ' setCurrentMatchIndex(nextVisibleMatchIndex);',
- ' displayMatches();',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' }',
- ' }',
- ' }',
- '',
- ' function refreshCurrentMatch() {',
- ' if (currentSearch && currentSearch.hasMatches()) {',
- ' setCurrentMatchIndex(currentMatchIndex);',
- ' }',
- ' }',
- '',
- ' function displayMatches() {',
- ' replaceClass($("searchBox"), "hasmatches", "nomatches");',
- ' $("searchBox").title = "" + currentSearch.matches.length + " matches found";',
- ' $("searchNav").style.display = "block";',
- ' setLogContainerHeight();',
- ' }',
- '',
- ' function displayNoMatches() {',
- ' replaceClass($("searchBox"), "nomatches", "hasmatches");',
- ' $("searchBox").title = "No matches found";',
- ' $("searchNav").style.display = "none";',
- ' setLogContainerHeight();',
- ' }',
- '',
- ' function toggleSearchEnabled(enable) {',
- ' enable = (typeof enable == "undefined") ? !$("searchDisable").checked : enable;',
- ' $("searchBox").disabled = !enable;',
- ' $("searchReset").disabled = !enable;',
- ' $("searchRegex").disabled = !enable;',
- ' $("searchNext").disabled = !enable;',
- ' $("searchPrevious").disabled = !enable;',
- ' $("searchCaseSensitive").disabled = !enable;',
- ' $("searchNav").style.display = (enable && ($("searchBox").value !== "")) ?',
- ' "block" : "none";',
- ' if (enable) {',
- ' removeClass($("search"), "greyedout");',
- ' addClass(document.body, "searching");',
- ' if ($("searchHighlight").checked) {',
- ' addClass(getLogContainer(), "searchhighlight");',
- ' } else {',
- ' removeClass(getLogContainer(), "searchhighlight");',
- ' }',
- ' if ($("searchFilter").checked) {',
- ' addClass(getLogContainer(), "searchfilter");',
- ' } else {',
- ' removeClass(getLogContainer(), "searchfilter");',
- ' }',
- ' $("searchDisable").checked = !enable;',
- ' } else {',
- ' addClass($("search"), "greyedout");',
- ' removeClass(document.body, "searching");',
- ' removeClass(getLogContainer(), "searchhighlight");',
- ' removeClass(getLogContainer(), "searchfilter");',
- ' }',
- ' setLogContainerHeight();',
- ' }',
- '',
- ' function toggleSearchFilter() {',
- ' var enable = $("searchFilter").checked;',
- ' if (enable) {',
- ' addClass(getLogContainer(), "searchfilter");',
- ' } else {',
- ' removeClass(getLogContainer(), "searchfilter");',
- ' }',
- ' refreshCurrentMatch();',
- ' }',
- '',
- ' function toggleSearchHighlight() {',
- ' var enable = $("searchHighlight").checked;',
- ' if (enable) {',
- ' addClass(getLogContainer(), "searchhighlight");',
- ' } else {',
- ' removeClass(getLogContainer(), "searchhighlight");',
- ' }',
- ' }',
- '',
- ' function clearSearch() {',
- ' $("searchBox").value = "";',
- ' doSearch();',
- ' }',
- '',
- ' function searchNext() {',
- ' try {',
- ' if (currentSearch !== null && currentMatchIndex !== null) {',
- ' currentSearch.matches[currentMatchIndex].setNotCurrent();',
- ' var nextMatchIndex = currentSearch.getNextVisibleMatchIndex();',
- ' if (nextMatchIndex > currentMatchIndex || confirm("Reached the end of the page. Start from the top?")) {',
- ' setCurrentMatchIndex(nextMatchIndex);',
- ' }',
- ' }',
- ' } catch (err) {',
- ' alert("currentMatchIndex is " + currentMatchIndex);',
- ' }',
- ' }',
- '',
- ' function searchPrevious() {',
- ' if (currentSearch !== null && currentMatchIndex !== null) {',
- ' currentSearch.matches[currentMatchIndex].setNotCurrent();',
- ' var previousMatchIndex = currentSearch.getPreviousVisibleMatchIndex();',
- ' if (previousMatchIndex < currentMatchIndex || confirm("Reached the start of the page. Continue from the bottom?")) {',
- ' setCurrentMatchIndex(previousMatchIndex);',
- ' }',
- ' }',
- ' }',
- '',
- ' function setCurrentMatchIndex(index) {',
- ' currentMatchIndex = index;',
- ' currentSearch.matches[currentMatchIndex].setCurrent();',
- ' }',
- '',
- ' /* ------------------------------------------------------------------------- */',
- '',
- ' // CSS Utilities',
- '',
- ' function addClass(el, cssClass) {',
- ' if (!hasClass(el, cssClass)) {',
- ' if (el.className) {',
- ' el.className += " " + cssClass;',
- ' } else {',
- ' el.className = cssClass;',
- ' }',
- ' }',
- ' }',
- '',
- ' function hasClass(el, cssClass) {',
- ' if (el.className) {',
- ' var classNames = el.className.split(" ");',
- ' return array_contains(classNames, cssClass);',
- ' }',
- ' return false;',
- ' }',
- '',
- ' function removeClass(el, cssClass) {',
- ' if (hasClass(el, cssClass)) {',
- ' // Rebuild the className property',
- ' var existingClasses = el.className.split(" ");',
- ' var newClasses = [];',
- ' for (var i = 0; i < existingClasses.length; i++) {',
- ' if (existingClasses[i] != cssClass) {',
- ' newClasses[newClasses.length] = existingClasses[i];',
- ' }',
- ' }',
- ' el.className = newClasses.join(" ");',
- ' }',
- ' }',
- '',
- ' function replaceClass(el, newCssClass, oldCssClass) {',
- ' removeClass(el, oldCssClass);',
- ' addClass(el, newCssClass);',
- ' }',
- '',
- ' /* ------------------------------------------------------------------------- */',
- '',
- ' // Other utility functions',
- '',
- ' function getElementsByClass(el, cssClass, tagName) {',
- ' var elements = el.getElementsByTagName(tagName);',
- ' var matches = [];',
- ' for (var i = 0; i < elements.length; i++) {',
- ' if (hasClass(elements[i], cssClass)) {',
- ' matches.push(elements[i]);',
- ' }',
- ' }',
- ' return matches;',
- ' }',
- '',
- ' // Syntax borrowed from Prototype library',
- ' function $(id) {',
- ' return document.getElementById(id);',
- ' }',
- '',
- ' function isOrphan(node) {',
- ' var currentNode = node;',
- ' while (currentNode) {',
- ' if (currentNode == document.body) {',
- ' return false;',
- ' }',
- ' currentNode = currentNode.parentNode;',
- ' }',
- ' return true;',
- ' }',
- '',
- ' function getWindowWidth() {',
- ' if (window.innerWidth) {',
- ' return window.innerWidth;',
- ' } else if (document.documentElement && document.documentElement.clientWidth) {',
- ' return document.documentElement.clientWidth;',
- ' } else if (document.body) {',
- ' return document.body.clientWidth;',
- ' }',
- ' return 0;',
- ' }',
- '',
- ' function getWindowHeight() {',
- ' if (window.innerHeight) {',
- ' return window.innerHeight;',
- ' } else if (document.documentElement && document.documentElement.clientHeight) {',
- ' return document.documentElement.clientHeight;',
- ' } else if (document.body) {',
- ' return document.body.clientHeight;',
- ' }',
- ' return 0;',
- ' }',
- '',
- ' function getToolBarsHeight() {',
- ' return $("switches").offsetHeight;',
- ' }',
- '',
- ' function setLogContainerHeight() {',
- ' var windowHeight = getWindowHeight();',
- ' $("body").style.height = getWindowHeight() + "px";',
- ' getLogContainer().style.height = "" +',
- ' (windowHeight - getToolBarsHeight()) + "px";',
- ' }',
- ' window.onresize = setLogContainerHeight;',
- '',
- ' if (!Array.prototype.push) {',
- ' Array.prototype.push = function() {',
- ' for (var i = 0; i < arguments.length; i++){',
- ' this[this.length] = arguments[i];',
- ' }',
- ' return this.length;',
- ' };',
- ' }',
- '',
- ' if (!Array.prototype.pop) {',
- ' Array.prototype.pop = function() {',
- ' if (this.length > 0) {',
- ' var val = this[this.length - 1];',
- ' this.length = this.length - 1;',
- ' return val;',
- ' }',
- ' };',
- ' }',
- '',
- ' if (!Array.prototype.shift) {',
- ' Array.prototype.shift = function() {',
- ' if (this.length > 0) {',
- ' var firstItem = this[0];',
- ' for (var i = 0; i < this.length - 1; i++) {',
- ' this[i] = this[i + 1];',
- ' }',
- ' this.length = this.length - 1;',
- ' return firstItem;',
- ' }',
- ' };',
- ' }',
- '',
- ' function array_removeFromStart(array, numberToRemove) {',
- ' if (Array.prototype.splice) {',
- ' array.splice(0, numberToRemove);',
- ' } else {',
- ' for (var i = numberToRemove; i < array.length; i++) {',
- ' array[i - numberToRemove] = array[i];',
- ' }',
- ' array.length = array.length - numberToRemove;',
- ' }',
- ' return array;',
- ' }',
- '',
- ' function array_contains(arr, val) {',
- ' for (var i = 0; i < arr.length; i++) {',
- ' if (arr[i] == val) {',
- ' return true;',
- ' }',
- ' }',
- ' return false;',
- ' }',
- ' //]]>',
- ' </script>',
- ' <style type="text/css">',
- ' body {',
- ' background-color: white;',
- ' color: black;',
- ' padding: 0px;',
- ' margin: 0px;',
- ' font-family: tahoma, verdana, arial, helvetica, sans-serif;',
- ' overflow: hidden;',
- ' }',
- '',
- ' div#switchesContainer input {',
- ' margin-bottom: 0px;',
- ' }',
- '',
- ' div#switches div.toolbar {',
- ' border-top: solid #ffffff 1px;',
- ' border-bottom: solid #aca899 1px;',
- ' background-color: #f1efe7;',
- ' padding: 3px 5px;',
- ' font-size: 68.75%;',
- ' }',
- '',
- ' div#switches div.toolbar, div#search input {',
- ' font-family: tahoma, verdana, arial, helvetica, sans-serif;',
- ' }',
- '',
- ' div#switches input.button {',
- ' padding: 0px 5px;',
- ' font-size: 100%;',
- ' }',
- '',
- ' div#switches input#clearButton {',
- ' margin-left: 20px;',
- ' }',
- '',
- ' div#levels label {',
- ' font-weight: bold;',
- ' }',
- '',
- ' div#levels label, div#options label {',
- ' margin-right: 5px;',
- ' }',
- '',
- ' div#levels label#wrapLabel {',
- ' font-weight: normal;',
- ' }',
- '',
- ' div#search {',
- ' padding: 5px 0px;',
- ' }',
- '',
- ' div#search label {',
- ' margin-right: 10px;',
- ' }',
- '',
- ' div#search label.searchboxlabel {',
- ' margin-right: 0px;',
- ' }',
- '',
- ' div#search input {',
- ' font-size: 100%;',
- ' }',
- '',
- ' div#search input.validregex {',
- ' color: green;',
- ' }',
- '',
- ' div#search input.invalidregex {',
- ' color: red;',
- ' }',
- '',
- ' div#search input.nomatches {',
- ' color: white;',
- ' background-color: #ff6666;',
- ' }',
- '',
- ' div#search input.nomatches {',
- ' color: white;',
- ' background-color: #ff6666;',
- ' }',
- '',
- ' *.greyedout {',
- ' color: gray;',
- ' }',
- '',
- ' *.greyedout *.alwaysenabled {',
- ' color: black;',
- ' }',
- '',
- ' div#log {',
- ' font-family: Courier New, Courier;',
- ' font-size: 75%;',
- ' width: 100%;',
- ' overflow: auto;',
- ' }',
- '',
- ' *.logentry {',
- ' overflow: visible;',
- ' display: none;',
- ' white-space: pre;',
- ' }',
- '',
- ' *.logentry pre.unwrapped {',
- ' display: inline;',
- ' }',
- '',
- ' *.logentry span.wrapped {',
- ' display: none;',
- ' }',
- '',
- ' body.searching *.logentry span.currentmatch {',
- ' color: white !important;',
- ' background-color: green !important;',
- ' }',
- '',
- ' body.searching div.searchhighlight *.logentry span.searchterm {',
- ' /*font-weight: bold;*/',
- ' color: black;',
- ' background-color: yellow;',
- ' }',
- '',
- ' div.wrap *.logentry {',
- ' white-space: normal !important;',
- ' border-width: 0px 0px 1px 0px;',
- ' border-color: #dddddd;',
- ' border-style: dotted;',
- ' }',
- '',
- ' div.wrap *.logentry pre.unwrapped {',
- ' display: none;',
- ' }',
- '',
- ' div.wrap *.logentry span.wrapped {',
- ' display: inline;',
- ' }',
- '',
- ' div.searchfilter *.searchnonmatch {',
- ' display: none !important;',
- ' }',
- '',
- ' div#log *.TRACE, label#label_TRACE {',
- ' color: #666666;',
- ' }',
- '',
- ' div#log *.DEBUG, label#label_DEBUG {',
- ' color: green;',
- ' }',
- '',
- ' div#log *.INFO, label#label_INFO {',
- ' color: #000099;',
- ' }',
- '',
- ' div#log *.WARN, label#label_WARN {',
- ' color: #999900;',
- ' }',
- '',
- ' div#log *.ERROR, label#label_ERROR {',
- ' color: red;',
- ' }',
- '',
- ' div#log *.FATAL, label#label_FATAL {',
- ' color: #660066;',
- ' }',
- '',
- ' div.TRACE#log *.TRACE,',
- ' div.DEBUG#log *.DEBUG,',
- ' div.INFO#log *.INFO,',
- ' div.WARN#log *.WARN,',
- ' div.ERROR#log *.ERROR,',
- ' div.FATAL#log *.FATAL {',
- ' display: block;',
- ' }',
- '',
- ' div#log div.separator {',
- ' background-color: #cccccc;',
- ' margin: 5px 0px;',
- ' line-height: 1px;',
- ' }',
- ' </style>',
- ' </head>',
- '',
- ' <body id="body">',
- ' <div id="switchesContainer">',
- ' <div id="switches">',
- ' <div id="levels" class="toolbar">',
- ' Filters:',
- ' <input type="checkbox" id="switch_TRACE" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide trace messages" /><label for="switch_TRACE" id="label_TRACE">trace</label>',
- ' <input type="checkbox" id="switch_DEBUG" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide debug messages" /><label for="switch_DEBUG" id="label_DEBUG">debug</label>',
- ' <input type="checkbox" id="switch_INFO" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide info messages" /><label for="switch_INFO" id="label_INFO">info</label>',
- ' <input type="checkbox" id="switch_WARN" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide warn messages" /><label for="switch_WARN" id="label_WARN">warn</label>',
- ' <input type="checkbox" id="switch_ERROR" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide error messages" /><label for="switch_ERROR" id="label_ERROR">error</label>',
- ' <input type="checkbox" id="switch_FATAL" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide fatal messages" /><label for="switch_FATAL" id="label_FATAL">fatal</label>',
- ' <input type="checkbox" id="switch_ALL" onclick="toggleAllLevels(); applyFilters()" checked="checked" title="Show/hide all messages" /><label for="switch_ALL" id="label_ALL">all</label>',
- ' </div>',
- ' <div id="search" class="toolbar">',
- ' <label for="searchBox" class="searchboxlabel">Search:</label> <input type="text" id="searchBox" onclick="toggleSearchEnabled(true)" onkeyup="scheduleSearch()" size="20" />',
- ' <input type="button" id="searchReset" disabled="disabled" value="Reset" onclick="clearSearch()" class="button" title="Reset the search" />',
- ' <input type="checkbox" id="searchRegex" onclick="doSearch()" title="If checked, search is treated as a regular expression" /><label for="searchRegex">Regex</label>',
- ' <input type="checkbox" id="searchCaseSensitive" onclick="doSearch()" title="If checked, search is case sensitive" /><label for="searchCaseSensitive">Match case</label>',
- ' <input type="checkbox" id="searchDisable" onclick="toggleSearchEnabled()" title="Enable/disable search" /><label for="searchDisable" class="alwaysenabled">Disable</label>',
- ' <div id="searchNav">',
- ' <input type="button" id="searchNext" disabled="disabled" value="Next" onclick="searchNext()" class="button" title="Go to the next matching log entry" />',
- ' <input type="button" id="searchPrevious" disabled="disabled" value="Previous" onclick="searchPrevious()" class="button" title="Go to the previous matching log entry" />',
- ' <input type="checkbox" id="searchFilter" onclick="toggleSearchFilter()" title="If checked, non-matching log entries are filtered out" /><label for="searchFilter">Filter</label>',
- ' <input type="checkbox" id="searchHighlight" onclick="toggleSearchHighlight()" title="Highlight matched search terms" /><label for="searchHighlight" class="alwaysenabled">Highlight all</label>',
- ' </div>',
- ' </div>',
- ' <div id="options" class="toolbar">',
- ' Options:',
- ' <input type="checkbox" id="enableLogging" onclick="toggleLoggingEnabled()" checked="checked" title="Enable/disable logging" /><label for="enableLogging" id="wrapLabel">Log</label>',
- ' <input type="checkbox" id="wrap" onclick="toggleWrap()" title="Enable / disable word wrap" /><label for="wrap" id="wrapLabel">Wrap</label>',
- ' <input type="checkbox" id="newestAtTop" onclick="toggleNewestAtTop()" title="If checked, causes newest messages to appear at the top" /><label for="newestAtTop" id="newestAtTopLabel">Newest at the top</label>',
- ' <input type="checkbox" id="scrollToLatest" onclick="toggleScrollToLatest()" checked="checked" title="If checked, window automatically scrolls to a new message when it is added" /><label for="scrollToLatest" id="scrollToLatestLabel">Scroll to latest</label>',
- ' <input type="button" id="clearButton" value="Clear" onclick="clearLog()" class="button" title="Clear all log messages" />',
- ' <input type="button" id="closeButton" value="Close" onclick="window.close()" class="button" title="Close the window" />',
- ' </div>',
- ' </div>',
- '',
- ' </div>',
- ' <div id="log" class="TRACE DEBUG INFO WARN ERROR FATAL"></div>',
- ' </body>',
- '</html>'
- ];
- };
- function ConsoleAppender() {}
- var consoleAppenderIdCounter = 1;
- ConsoleAppender.prototype = new Appender();
- ConsoleAppender.prototype.create = function(inPage, containerElement,
- layout, lazyInit, focusConsoleWindow, useOldPopUp,
- complainAboutPopUpBlocking, newestMessageAtTop,
- scrollToLatestMessage, initiallyMinimized, width, height,
- reopenWhenClosed, maxMessages) {
- var appender = this;
- // Common properties
- if (layout) {
- this.setLayout(layout);
- } else {
- this.setLayout(this.defaults.layout);
- }
- var initialized = false;
- var consoleWindowLoaded = false;
- var queuedLoggingEvents = [];
- var isSupported = true;
- var consoleAppenderId = consoleAppenderIdCounter++;
- // Params
- lazyInit = extractBooleanFromParam(lazyInit, true);
- newestMessageAtTop = extractBooleanFromParam(newestMessageAtTop, this.defaults.newestMessageAtTop);
- scrollToLatestMessage = extractBooleanFromParam(scrollToLatestMessage, this.defaults.scrollToLatestMessage);
- width = width ? width : this.defaults.width;
- height = height ? height : this.defaults.height;
- maxMessages = maxMessages ? maxMessages : this.defaults.maxMessages;
- // Functions whose implementations vary between subclasses
- var init, safeToAppend, getConsoleWindow;
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- var appenderName = inPage ? "InPageAppender" : "PopUpAppender";
- var checkCanConfigure = function(configOptionName) {
- if (initialized) {
- handleError(appenderName + ": configuration option '" + configOptionName + "' may not be set after the appender has been initialized");
- return false;
- }
- return true;
- };
- this.isNewestMessageAtTop = function() { return newestMessageAtTop; };
- this.setNewestMessageAtTop = function(newestMessageAtTopParam) {
- newestMessageAtTop = bool(newestMessageAtTopParam);
- if (consoleWindowLoaded && isSupported) {
- getConsoleWindow().setNewestAtTop(newestMessageAtTop);
- }
- };
- this.isScrollToLatestMessage = function() { return scrollToLatestMessage; };
- this.setScrollToLatestMessage = function(scrollToLatestMessageParam) {
- scrollToLatestMessage = bool(scrollToLatestMessageParam);
- if (consoleWindowLoaded && isSupported) {
- getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
- }
- };
- this.getWidth = function() { return width; };
- this.setWidth = function(widthParam) {
- if (checkCanConfigure("width")) {
- width = extractStringFromParam(widthParam, width);
- }
- };
- this.getHeight = function() { return height; };
- this.setHeight = function(heightParam) {
- if (checkCanConfigure("height")) {
- height = extractStringFromParam(heightParam, height);
- }
- };
- this.getMaxMessages = function() { return maxMessages; };
- this.setMaxMessages = function(maxMessagesParam) {
- maxMessages = extractIntFromParam(maxMessagesParam, maxMessages);
- if (consoleWindowLoaded && isSupported) {
- getConsoleWindow().setMaxMessages(maxMessages);
- }
- };
- // Common methods
- this.append = function(loggingEvent) {
- if (isSupported) {
- queuedLoggingEvents.push(loggingEvent);
- // Force a check of whether the window is closed
- var isSafeToAppend = safeToAppend();
- if (!initialized || (consoleClosed && reopenWhenClosed)) {
- init();
- }
- if (safeToAppend()) {
- appendQueuedLoggingEvents();
- }
- }
- };
- var appendQueuedLoggingEvents = function(loggingEvent) {
- while (queuedLoggingEvents.length > 0) {
- var currentLoggingEvent = queuedLoggingEvents.shift();
- var formattedMessage = appender.getLayout().format(currentLoggingEvent);
- if (appender.getLayout().ignoresThrowable()) {
- formattedMessage += currentLoggingEvent.getThrowableStrRep();
- }
- getConsoleWindow().log(currentLoggingEvent.level, formattedMessage);
- }
- if (focusConsoleWindow) {
- getConsoleWindow().focus();
- }
- };
- var writeHtml = function(doc) {
- var lines = getConsoleHtmlLines();
- doc.open();
- for (var i = 0; i < lines.length; i++) {
- doc.writeln(lines[i]);
- }
- doc.close();
- };
- var consoleClosed = false;
- var pollConsoleWindow = function(windowTest, successCallback, errorMessage) {
- function pollConsoleWindowLoaded() {
- try {
- // Test if the console has been closed while polling
- if (consoleClosed) {
- clearInterval(poll);
- }
- if (windowTest(getConsoleWindow())) {
- clearInterval(poll);
- successCallback();
- }
- } catch (ex) {
- clearInterval(poll);
- isSupported = false;
- handleError(errorMessage, ex);
- }
- }
- // Poll the pop-up since the onload event is not reliable
- var poll = setInterval(pollConsoleWindowLoaded, 100);
- };
- // Define methods and properties that vary between subclasses
- if (inPage) {
- // InPageAppender
- // Extract params
- if (!containerElement || !containerElement.appendChild) {
- isSupported = false;
- handleError("InPageAppender.init: a container DOM element must be supplied for the console window");
- return;
- }
- initiallyMinimized = extractBooleanFromParam(initiallyMinimized, appender.defaults.initiallyMinimized);
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- this.isInitiallyMinimized = function() { return initiallyMinimized; };
- this.setInitiallyMinimized = function(initiallyMinimizedParam) {
- if (checkCanConfigure("initiallyMinimized")) {
- initiallyMinimized = bool(initiallyMinimizedParam);
- }
- };
- // Define useful variables
- var minimized = false;
- var iframeContainerDiv;
- var iframeId = uniqueId + "_InPageAppender_" + consoleAppenderId;
- this.hide = function() {
- iframeContainerDiv.style.display = "none";
- minimized = true;
- };
- this.show = function() {
- iframeContainerDiv.style.display = "block";
- minimized = false;
- };
- this.isVisible = function() {
- return !minimized;
- };
- this.close = function() {
- if (!consoleClosed) {
- iframeContainerDiv.parentNode.removeChild(iframeContainerDiv);
- consoleClosed = true;
- }
- };
- // Create init, getConsoleWindow and safeToAppend functions
- init = function() {
- var initErrorMessage = "InPageAppender.init: unable to create console iframe";
- function finalInit() {
- try {
- getConsoleWindow().setNewestAtTop(newestMessageAtTop);
- getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
- getConsoleWindow().setMaxMessages(maxMessages);
- consoleWindowLoaded = true;
- appendQueuedLoggingEvents();
- if (initiallyMinimized) {
- appender.hide();
- }
- } catch (ex) {
- isSupported = false;
- handleError(initErrorMessage, ex);
- }
- }
- function writeToDocument() {
- try {
- var windowTest = function(win) { return bool(win.loaded); };
- writeHtml(getConsoleWindow().document);
- if (windowTest(getConsoleWindow())) {
- finalInit();
- } else {
- pollConsoleWindow(windowTest, finalInit, initErrorMessage);
- }
- } catch (ex) {
- isSupported = false;
- handleError(initErrorMessage, ex);
- }
- }
- minimized = initiallyMinimized;
- iframeContainerDiv = containerElement.appendChild(document.createElement("div"));
- iframeContainerDiv.style.width = width;
- iframeContainerDiv.style.height = height;
- iframeContainerDiv.style.border = "solid gray 1px";
- // Adding an iframe using the DOM would be preferable, but it doesn't work
- // in IE5 on Windows, or in Konqueror prior to version 3.5 - in Konqueror
- // it creates the iframe fine but I haven't been able to find a way to obtain
- // the iframe's window object
- var iframeHtml = "<iframe id='" + iframeId + "' name='" + iframeId +
- "' width='100%' height='100%' frameborder='0'" +
- "scrolling='no'></iframe>";
- iframeContainerDiv.innerHTML = iframeHtml;
- consoleClosed = false;
- // Write the console HTML to the iframe
- var iframeDocumentExistsTest = function(win) { return bool(win) && bool(win.document); };
- if (iframeDocumentExistsTest(getConsoleWindow())) {
- writeToDocument();
- } else {
- pollConsoleWindow(iframeDocumentExistsTest, writeToDocument, initErrorMessage);
- }
- initialized = true;
- };
- getConsoleWindow = function() {
- var iframe = window.frames[iframeId];
- if (iframe) {
- return iframe;
- }
- };
- safeToAppend = function() {
- if (isSupported && !consoleClosed) {
- if (!consoleWindowLoaded && getConsoleWindow() && getConsoleWindow().loaded) {
- consoleWindowLoaded = true;
- }
- return consoleWindowLoaded;
- }
- return false;
- };
- } else {
- // PopUpAppender
- // Extract params
- useOldPopUp = extractBooleanFromParam(useOldPopUp, appender.defaults.useOldPopUp);
- complainAboutPopUpBlocking = extractBooleanFromParam(complainAboutPopUpBlocking, appender.defaults.complainAboutPopUpBlocking);
- reopenWhenClosed = extractBooleanFromParam(reopenWhenClosed, this.defaults.reopenWhenClosed);
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- this.isUseOldPopUp = function() { return useOldPopUp; };
- this.setUseOldPopUp = function(useOldPopUpParam) {
- if (checkCanConfigure("useOldPopUp")) {
- useOldPopUp = bool(useOldPopUpParam);
- }
- };
- this.isComplainAboutPopUpBlocking = function() { return complainAboutPopUpBlocking; };
- this.setComplainAboutPopUpBlocking = function(complainAboutPopUpBlockingParam) {
- if (checkCanConfigure("complainAboutPopUpBlocking")) {
- complainAboutPopUpBlocking = bool(complainAboutPopUpBlockingParam);
- }
- };
- this.isFocusPopUp = function() { return focusConsoleWindow; };
- this.setFocusPopUp = function(focusPopUpParam) {
- // This property can be safely altered after logging has started
- focusConsoleWindow = bool(focusPopUpParam);
- };
- this.isReopenWhenClosed = function() { return reopenWhenClosed; };
- this.setReopenWhenClosed = function(reopenWhenClosedParam) {
- // This property can be safely altered after logging has started
- reopenWhenClosed = bool(reopenWhenClosedParam);
- };
- this.close = function() {
- try {
- popUp.close();
- } catch (e) {
- // Do nothing
- }
- consoleClosed = true;
- };
- // Define useful variables
- var popUp;
- // Create init, getConsoleWindow and safeToAppend functions
- init = function() {
- var windowProperties = "width=" + width + ",height=" + height + ",status,resizable";
- var windowName = "PopUp_" + location.host.replace(/[^a-z0-9]/gi, "_") + "_" + consoleAppenderId;
- if (!useOldPopUp) {
- // Ensure a previous window isn't used by using a unique name
- windowName = windowName + "_" + uniqueId;
- }
- function finalInit() {
- consoleWindowLoaded = true;
- getConsoleWindow().setNewestAtTop(newestMessageAtTop);
- getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
- getConsoleWindow().setMaxMessages(maxMessages);
- appendQueuedLoggingEvents();
- }
- try {
- popUp = window.open("", windowName, windowProperties);
- consoleClosed = false;
- if (popUp) {
- if (useOldPopUp && popUp.loaded) {
- popUp.mainPageReloaded();
- finalInit();
- } else {
- writeHtml(popUp.document);
- // Check if the pop-up window object is available
- var popUpLoadedTest = function(win) { return bool(win) && win.loaded; };
- if (popUp.loaded) {
- finalInit();
- } else {
- pollConsoleWindow(popUpLoadedTest, finalInit, "PopUpAppender.init: unable to create console window");
- }
- }
- } else {
- isSupported = false;
- logLog.warn("PopUpAppender.init: pop-ups blocked, please unblock to use PopUpAppender");
- if (complainAboutPopUpBlocking) {
- handleError("log4javascript: pop-up windows appear to be blocked. Please unblock them to use pop-up logging.");
- }
- }
- } catch (ex) {
- handleError("PopUpAppender.init: error creating pop-up", ex);
- }
- initialized = true;
- };
- getConsoleWindow = function() {
- return popUp;
- };
- safeToAppend = function() {
- if (isSupported && !isUndefined(popUp) && !consoleClosed) {
- if (popUp.closed ||
- (consoleWindowLoaded && isUndefined(popUp.closed))) { // Extra check for Opera
- consoleClosed = true;
- logLog.debug("PopUpAppender: pop-up closed");
- return false;
- }
- if (!consoleWindowLoaded && popUp.loaded) {
- consoleWindowLoaded = true;
- }
- }
- return isSupported && consoleWindowLoaded && !consoleClosed;
- };
- }
- if (enabled && !lazyInit) {
- init();
- }
- // Expose getConsoleWindow so that automated tests can check the DOM
- this.getConsoleWindow = getConsoleWindow;
- };
- /* ----------------------------------------------------------------- */
- var PopUpAppender = function(lazyInit, layout, focusPopUp,
- useOldPopUp, complainAboutPopUpBlocking, newestMessageAtTop,
- scrollToLatestMessage, reopenWhenClosed, width, height,
- maxMessages) {
- var focusConsoleWindow = extractBooleanFromParam(focusPopUp, this.defaults.focusPopUp);
- this.create(false, null, layout, lazyInit, focusConsoleWindow,
- useOldPopUp, complainAboutPopUpBlocking,
- newestMessageAtTop, scrollToLatestMessage, null, width, height,
- reopenWhenClosed, maxMessages);
- };
- PopUpAppender.prototype = new ConsoleAppender();
- PopUpAppender.prototype.defaults = {
- layout: new PatternLayout("%d{HH:mm:ss} %-5p - %m{1}%n"),
- focusPopUp: false,
- lazyInit: true,
- useOldPopUp: true,
- complainAboutPopUpBlocking: true,
- newestMessageAtTop: false,
- scrollToLatestMessage: true,
- width: "600",
- height: "400",
- reopenWhenClosed: false,
- maxMessages: null
- };
- PopUpAppender.prototype.toString = function() {
- return "[PopUpAppender]";
- };
- log4javascript.PopUpAppender = PopUpAppender;
- /* ----------------------------------------------------------------- */
- var InPageAppender = function(containerElement, lazyInit,
- layout, initiallyMinimized, newestMessageAtTop,
- scrollToLatestMessage, width, height, maxMessages) {
- this.create(true, containerElement, layout, lazyInit, false,
- null, null, newestMessageAtTop, scrollToLatestMessage,
- initiallyMinimized, width, height, null, maxMessages);
- };
- InPageAppender.prototype = new ConsoleAppender();
- InPageAppender.prototype.defaults = {
- layout: new PatternLayout("%d{HH:mm:ss} %-5p - %m{1}%n"),
- initiallyMinimized: false,
- lazyInit: true,
- newestMessageAtTop: false,
- scrollToLatestMessage: true,
- width: "100%",
- height: "250px",
- maxMessages: null
- };
- InPageAppender.prototype.toString = function() {
- return "[InPageAppender]";
- };
- log4javascript.InPageAppender = InPageAppender;
- // Next line for backwards compatibility
- log4javascript.InlineAppender = InPageAppender;
- })();
- /* --------------------------------------------------------------------- */
- // BrowserConsoleAppender (only works in Opera and Safari and Firefox with
- // FireBug extension)
- var BrowserConsoleAppender = function(layout) {
- if (layout) {
- this.setLayout(layout);
- }
- };
- BrowserConsoleAppender.prototype = new log4javascript.Appender();
- BrowserConsoleAppender.prototype.layout = new NullLayout();
- BrowserConsoleAppender.prototype.threshold = Level.DEBUG;
- BrowserConsoleAppender.prototype.append = function(loggingEvent) {
- var appender = this;
- var getFormattedMessage = function() {
- var layout = appender.getLayout();
- var formattedMessage = layout.format(loggingEvent);
- if (layout.ignoresThrowable() && loggingEvent.exception) {
- formattedMessage += loggingEvent.getThrowableStrRep();
- }
- return formattedMessage;
- };
- if ((typeof opera != "undefined") && opera.postError) { // Opera
- opera.postError(getFormattedMessage());
- } else if (window.console && window.console.log) { // Safari and FireBug
- var formattedMesage = getFormattedMessage();
- // Log to FireBug using its logging methods or revert to the console.log
- // method in Safari
- if (window.console.debug && Level.DEBUG.isGreaterOrEqual(loggingEvent.level)) {
- window.console.debug(formattedMesage);
- } else if (window.console.info && Level.INFO.equals(loggingEvent.level)) {
- window.console.info(formattedMesage);
- } else if (window.console.warn && Level.WARN.equals(loggingEvent.level)) {
- window.console.warn(formattedMesage);
- } else if (window.console.error && loggingEvent.level.isGreaterOrEqual(Level.ERROR)) {
- window.console.error(formattedMesage);
- } else {
- window.console.log(formattedMesage);
- }
- }
- };
- BrowserConsoleAppender.prototype.toString = function() {
- return "[BrowserConsoleAppender]";
- };
- log4javascript.BrowserConsoleAppender = BrowserConsoleAppender;
- })();
|