// // // // JaxsonObject = function(config){ var superClasses = []; var that = { isA : function(name){ return (that.getClass && that.getClass() === name) || superClasses[name] !== undefined; }, setSuperClasses : function( arr ){ superClasses = arr; }, getSuperClass : function(name){ return superClasses[name]; }, getSuperClasses : function(){ return superClasses; }, extend : function(sup){ if( that.isA && that.isA(sup) ){ throw "IllegalArgumentException: instance already inherits from " + sup; } var parent = eval( sup ); parent = new parent(config); for( i in parent ){ if( !that[i] ){ that[i] = parent[i]; } } return that; } }; return that; }; // // namespace("org.jaxson.util.collections"); /** * HashMap implemented by wrapping object property key / value pairs * in an internal object. */ org.jaxson.util.collections.Map = function(){ var mapObj = {}; var that={ size : function() { return this.keys().elements.length; }, isEmpty : function() { return this.size() === 0; }, keys : function() { var result = new org.jaxson.util.collections.List(); for( i in mapObj ){ result.add( i ); } return result; }, values : function() { var result = new org.jaxson.util.collections.List(); for( i in mapObj ){ result.add( mapObj[i] ); } return result; }, containsKey : function(key) { return mapObj[key] !== undefined; }, containsValue : function(value) { var values = this.getValues(); for( var i=0; i idx ){ throw "IllegalArgumentException: index must be greater than zero and less than size"; } if( obj[index] !== undefined ){ var nidx = 0; var nobj = {}; for( i in obj ){ if( parseInt(i) === index ){ nobj[index] = value; nidx++; } nobj[nidx++] = obj[i]; } obj = nobj; idx = nidx; } }, get : function(index) { return obj[index]; }, first : function() { return this.isEmpty()?null:get(0); }, last : function() { return this.isEmpty()?null:get(idx); }, remove : function(index) { if( obj[index] !== undefined ){ var nidx = 0; var nobj = {}; for( i in obj ){ if( i === index ){ continue; } nobj[nidx++] = obj[i]; } obj = nobj; idx = nidx; } }, contains : function(value) { return (this.indexOf(value) != -1); }, indexOf : function(value) { if(value) { for( i in obj ){ if( obj[i] === value ){ return i; } } } return -1; }, lastIndexOf : function(value) { if(value) { for( i=idx; i>=0; i-- ){ if( obj[i] === value ){ return i; } } } return -1; }, clear : function() { idx = 0; var arr = this.asArray; delete obj; obj = {}; for( i in arr ){ delete arr[i]; } }, asArray : function(){ var result = new Array(); for( i in obj ){ result.push( obj[i] ); } return result; } /*, toString : function() { return "[" + ns + " List]"; } */ }; inherits ("JaxsonObject", "org.jaxson.util.collections.List", that); return that; }; Throwable = function( message, rootCause ){ if( !message ) var message = ""; if( rootCause ){ if( !rootCause.isA || !rootCause.isA( "Throwable" ) ){ throw new Throwable( "rootCause must be a throwable" ); } } else var rootCause = null; return{ getMessage: function(){ return message; }, getRootCause: function(){ return rootCause; } }; }; EventProxy = new function() { var map = new org.jaxson.util.collections.Map(); var that = { contains: function(name){ return map.containsKey(name); }, add : function( name, func ){ map.put( name, func ); }, remove : function( name, func ){ map.remove( name, func ); }, get : function( name ){ return map.get(name); }, execute: function(name, event){ return map.get(name)(event); } }; return that; }; // // add to and overwrite baseline javascript object defs here String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); }; //Simulates PHP's date function // pinched from http://jacwright.com/projects/javascript/date_format Date.prototype.format=function(format){var returnStr='';var replace=Date.replaceChars;for(var i=0;i 0) ? ("." + splitNs[i]) : ""; eval(builtNs + " = typeof(" + builtNs + ") =='undefined' ? {} : " + builtNs + "; "); } return builtNs; } var uid = Math.random() * 10000; function inherits( sup, subName, sub, config ){ sub.getClass = function(){return subName;}; var uid = uid++; sub.getUid = function(){ return uid; }; if( sub.isA && sub.isA(sup) ){ throw "IllegalArgumentException: instance already inherits from " + sup; } var parent = eval( sup ); parent = new parent(config); // apply superclass methods to subclass for( i in parent ){ if( !sub[i] ){ sub[i] = parent[i]; } } // spoof instanceof if possible var superclasses = []; superclasses[sup] = parent; //superclasses[subName] = sub; var sups = parent.getSuperClasses(); for( i in sups ){ superclasses[i] = sups[i]; } if( superclasses[subName] == null ){ superclasses[subName] = sub; } sub.setSuperClasses(superclasses); return sub; } // RuntimeInformation = new function(){ var ua = navigator.userAgent; return{ isIE : function(){ return ua.indexOf( "MSIE" ) != -1; }, isFF: function(){ return ua.indexOf( "Firefox" ) != -1; } }; }; // application specific javascript config //params will be rendered here ApplicationConfiguration = new function(){ var properties = []; var observers = new org.jaxson.util.collections.Map(); var contextPath = "/services-client"; // expose the context path as a property properties["context.path"] = contextPath; // properties["client.logger.remote"]=false; properties["client.reverse.ajax.error.redirect.url"]="http://www.google.com?q=dismal%20failure"; properties["client.reverse.ajax.url"]="reverseAjax/poll.action"; properties["client.reverse.ajax.poll.interval"]=30; properties["client.logger.remote.batch.size"]=1; properties["client.logger.url"]="logging/remoteLogger"; properties["client.disable.firebug"]=false; properties["client.reverse.ajax.error.reattempts"]=50; if( window["console"] ){ console.log( "application configuration:" ); if( console["dir"] ) console.dir( properties ); } var fire = function( name, props ){ var list = observers.get(name); if( list != null ){ var value = props[name]; for( i=0; i= totalRetries ){ var evt2 = { name: "reverse.ajax.connection.error.limit", rawError : e, totalRetries : totalRetries }; notify( {events:[evt2]} ); } }; var timer = new org.jaxson.util.Timer( function(){ if( !xhr.isChunked() /*&& initialized === false*/ ){ xhr.setMethod( "POST" ); xhr.doRequest( url ); } if( !initialized ){ initialized = true; } }, interval); function notify( result ){ lager.debug( "notify called" ); lager.dump( result ); // for each event... for( i=0; i 0 && !xhrptr.inErrorState() ){ var evt = { name: "reverse.ajax.connection.error.cleared" }; retries = 0; notify( {events:[evt]} ); } // fire the event var response = this.getResponseText(); if( response === undefined || response === null || response.trim().length === 0 ){ return; } eval( "result=" + response ); if( result === null || result === undefined || result.events === undefined ) return; notify( result ); }; //xhr.oncomplete = chunkhandler; //xhr.onrecieved = responseHandler; xhr.oncomplete = responseHandler; var that = { subscribe : function (evtname, func ){ if( subscribers.get(evtname) === null ) { subscribers.put( evtname, new org.jaxson.util.collections.List() ); } var list = subscribers.get( evtname ); list.add( func ); }, unsubscribe : function( evtname, func ){ if( subscribers.get(evtname) === null ) return; var list = subscribers.get( evtname ); list.remove( func ); }, setUrl : function( purl ){ url = purl; }, start : function(){ if( url === null ) throw "url not set."; timer.start(); }, stop : function(){ timer.stop(); }, setLogger: function( logger ){ lager = logger; xhr.setLogger( new Logger( "org.jaxson.util.http.XHR::ReverseAjaxBus", Logger.LEVEL_INFO ) ); } }; // since ApplicationConfiguration relies on reverse ajax // for configuration events pushed from the server, // initialize it when this class has loaded. ApplicationConfiguration.initialize(that); return that; } ReverseAjaxBus = org.jaxson.util.http.ReverseAjaxBus; // ClientLogBatch = function(p_entries) { return{ "class":"org.jaxson.struts.logging.ClientLogBatch", "entries": p_entries === undefined?null:p_entries }; } // LogEntry = function(p_occuredOn, p_level, p_message, p_logger) { return{ "class":"org.jaxson.struts.logging.JavascriptLogEntry", "occuredOn": p_occuredOn === undefined?null:p_occuredOn, "level": p_level === undefined?null:p_level, "message": p_message === undefined?null:p_message, "logger": p_logger === undefined?null:p_logger }; } // LogConfiguration = function(p_loggerName, p_batchSize, p_enableRemote, p_applyGlobally, p_level, p_name) { return{ "class":"org.jaxson.struts.logging.LogConfigurationEvent", "loggerName": p_loggerName === undefined?null:p_loggerName, "batchSize": p_batchSize === undefined?null:p_batchSize, "enableRemote": p_enableRemote === undefined?null:p_enableRemote, "applyGlobally": p_applyGlobally === undefined?null:p_applyGlobally, "level": p_level === undefined?null:p_level, "name": p_name === undefined?null:p_name }; } /** * LogManager */ LogManager = new function() { var loggers = new org.jaxson.util.collections.Map(); var debugEl = null; function configure( logger, event ){ if( event.enableRemote !== null ){ logger.setRemoteLoggingEnabled( event.enableRemote ); } if( event.level !== 0 ){ logger.setLogLevel( event.level ); } if( event.batchSize ){ logger.setRemoteBatchSize(event.batchSize); } } var handleRemoteConfiguration = function( event ){ // apply settings to all loggers if( event.applyGlobally === true ){ var keys = loggers.keys(); for( i=0; i" + "date" + "category" + " message" + "" + ""; logEl = document.getElementById( 'debugLog' ); } } // no debug element, but firebug is installed. if( window["console"] !== undefined ){ switch( llevel ){ case Logger.LEVEL_TRACE: if(console["debug"]) console.debug( args ); break; case Logger.LEVEL_DEBUG: if(console["debug"]) console.debug( name + "::DEBUG", args ); break; case Logger.LEVEL_INFO: if(console["info"]) console.info( name + "::INFO", args ); break; case Logger.LEVEL_WARN: if(console["warn"]) console.warn( name + "::WARN", args ); break; case Logger.LEVEL_ERROR: if(console["error"]) console.error( name + "::ERROR", args ); break; } } // Not firefox and debug el exists... if the debug element exists, append. else if( debugEl !== null) { // ie hack. var func = function(){ if( logEl === null ) return; var foo = logEl.insertRow(0); foo.insertCell( 0 ).innerHTML = new Date(); foo.insertCell( 1 ).innerHTML = name; foo.insertCell( 2 ).innerHTML = msg; debugEl.scrollTop = 100000; // TODO: fix the scroll position to set correctly automagically. }; setTimeout( func, 100 ); } // remote logging enabled if( remoteLoggingEnabled ){ remoteMessages.add( LogEntry( msg, name, level, new Date().getTime() ) ); if( remoteMessages.size() >= remoteMessageBatchSize ){ sendBatch( remoteMessages ); remoteMessages.clear(); } } } that = { dump : function( obj ){ doDir( obj ); }, trace : function(){ println( arguments, Logger.LEVEL_TRACE, this ); }, debug: function(){ println( arguments, Logger.LEVEL_DEBUG, this ); }, info: function(){ println( arguments, Logger.LEVEL_INFO, this ); }, warn: function(){ println( arguments, Logger.LEVEL_WARN, this ); }, error: function(){ println( arguments, Logger.LEVEL_ERROR, this ); }, setRemoteLoggingEnabled: function( flag ){ remoteLoggingEnabled = flag; println( "remote logging " + (flag?"enabled":"disabled") + " in logger " + name, Logger.LEVEL_WARN, this ); }, setRemoteBatchSize: function( size ){ remoteMessageBatchSize = size; }, setDebugId : function( debugId ){ that.debugId = debugId; }, getDebugId : function(){ return that.debugId; }, clear : function(){ debugEl.innerHtml = ""; }, setLogLevel : function( level ){ that.level = level; }, getLogLevel : function(){ return that.level; }, setUrl : function( u ){ return url = u; }, getUrl : function(){ return url; }, getName : function(){ return name; } }; LogManager.addLogger( that ); return that; }; // Logger.LEVEL_TRACE=1; Logger.LEVEL_DEBUG=2; Logger.LEVEL_INFO=3; Logger.LEVEL_WARN=4; Logger.LEVEL_ERROR=5; ReverseAjaxBus.setLogger( new Logger( "org.jaxson.util.http.ReverseAjaxBus", Logger.LEVEL_DEBUG ) ); delete ReverseAjaxBus.setLogger; // // // // namespace( "org.jaxson.util.collections" ); org.jaxson.util.collections.MappedList = function(){ var sup = "org.jaxson.util.collections.Map"; function getList(key){ var list = new org.jaxson.util.collections.List(); if( that.getSuperClass(sup).get(key) !== null ){ list = that.getSuperClass(sup).get(key); } that.getSuperClass(sup).put( key, list ); return list; }; var that = { put : function( key, value ){ getList(key).add( value ); }, remove : function( key ){ getList(key).clear(); that.getSuperClass(sup).remove(key); }, clear : function(){ var values = that.values().asArray(); for( i in values ){ values[i].clear(); } that.getSuperClass(sup).clear(); } }; inherits( sup, "org.jaxson.util.collections.MappedList", that ); return that; }; namespace( "org.jaxson" ); TransactionalEvent = function(name, url, vetoable, global){ var suffixes = [".attempt", ".attempted", ".succeeded", ".failed"]; var events = []; for( i in suffixes ){ events.push({name: name + suffixes[i], url: url, vetoable: vetoable, global: global, tx: true, basename: name} ); } return {events: events}; }; EventDispatcher = new function(){ var map = new org.jaxson.util.collections.Map(); var handlerCache = new org.jaxson.util.collections.MappedList(); var eventCache = new org.jaxson.util.collections.MappedList(); function methodName(evt){ var tokenized = evt.split( "\." ); var method = ""; for( j in tokenized ){ if( j == 0 ){ method += tokenized[j]; continue; } method += tokenized[j].charAt(0).toUpperCase() + tokenized[j].substring(1); } return method; } var that ={ register : function( event, source ){ var wrapper = { event: event, source: source }; map.put( event.name, wrapper ); // bind cached listeners. if( handlerCache.containsKey( event.name ) ){ var list = handlerCache.get( event.name ).asArray(); for( i in list ){ if( list[i] === {} ){ list.remove(i); continue; } that.bind( event.name, list[i] ); } handlerCache.remove( event.name ); } }, fire : function( event ){ if( !that.getSource(event.name) ){ eventCache.put( event.name, event ); } else return that.getSource(event.name).notify(event); }, bindPattern : function( pattern, handler ){ var keys = map.keys().asArray(); for( i in keys ){ if( keys[i].match(pattern) ){ that.bind( keys[i], handler ); } } }, bind : function( event, handler ){ if( map.containsKey(event) ){ that.getSource(event).addObserver(event, handler); } // create a placeholder list else{ handlerCache.put(event, handler); } if( eventCache.containsKey( event ) ){ eventCache.add( event ); var events = eventCache.get( event ).asArray(); for( j in events ) that.fire( events[j] ); eventCache.remove( event ); } }, bindTx : function( eventname, listener ){ var suffixes = [".attempt", ".attempted", ".succeeded", ".failed"]; for( i in suffixes ){ var evt = eventname + suffixes[i]; var method = methodName( evt ); if( listener[method] ){ that.bind(evt, listener[method]); } } }, unbind : function( event, handler ){ that.getSource(event).removeObserver( handler ); }, remove : function( event ){ map.remove( map.get(event).event.name ); }, getSource : function( event ){ return map.get(event) && map.get(event).source?map.get(event).source:null; } }; return that; }; org.jaxson.Observable = function(config){ var observers = new org.jaxson.util.collections.MappedList(); var events = new org.jaxson.util.collections.Map(); var silent = false; var baseEvents = {}; var that ={ // disable firing silence : function( flag ){ silent = flag; }, // events removeEvent: function( name ){ events.remove( name ); }, getEvents : function(){ return events.values().asArray(); }, clearEvents: function(){ events.clear(); }, setPriority: function( name, func, priority ){ if( events.get(name) !== null ){ var list = events.get(name); } }, setVetoable: function( name, vetoable ){ if( events.get(name) !== null ) events.get(name).vetoable = vetoable; }, addEvent: function( event ){ if( event.events ){ that.addEvent(event.events); } else{ if( event.vetoable === undefined ) event.vetoable = false; if( event.global ) EventDispatcher.register( event, that ); events.put( event.name, event ); if( event.global && event.tx && event.basename && !baseEvents[event.basename] ) baseEvents[ event.basename ] = true; } }, getBaseEvents : function(){ return baseEvents; }, bindTxs : function(listener){ for( i in baseEvents ){ EventDispatcher.bindTx( i, listener ); } }, addEvents: function( array ){ for( i in array ){ var evt = array[i]; if( evt.events ){ for( j in evt.events ){ that.addEvent(evt.events[j]); } } else that.addEvent( evt ); } }, // observer mgmt removeObserver : function( obs ){ observers.remove(obs); }, clear : function(){ observers.clear(); }, addObserver : function( name, obs ){ var wrapper = { name: name, obs: obs }; observers.put( name, wrapper); }, notify: function( event ){ var list = observers.get(event.name); if( list === null && !silent ) return true; if( list === null || silent ) return false; var arr = list.asArray(); for( i in arr ){ var wrapper = arr[i]; if( wrapper.name === event.name ){ var evtdef = events.get(event.name); if( evtdef.vetoable === true && !silent ){ var out = wrapper.obs(event); if( out === false ) return out; } else if( evtdef.vetoable === false || evtdef.vetoable === undefined ){ wrapper.obs(event); } } } if( evtdef.vetoable ) return true; } }; inherits( "JaxsonObject", "org.jaxson.Observable", that, config ); return that; }; // // namespace( "org.jaxson.util.http"); org.jaxson.util.http.JsonServiceClient = function(config){ var lager = new Logger( "org.jaxson.util.http.JsonServiceClient", Logger.LEVEL_DEBUG ); function Handler(event, instance){ return { event : event, handle : function(params){ that.txRequest(event.url, event.basename, params, instance); } }; } var that = { txRequest : function(url, evtname, params, source){ var evt = {url: url, params: params, source: source}; evt.name = evtname + ".attempt"; var doit = EventDispatcher.fire( evt ); if( doit === false ) return; var xhr = org.jaxson.util.http.XHR(); xhr.setRequestParameters(params); xhr.setMethod("POST"); xhr.doRequest(url); evt.xhr = xhr; xhr.onerror = function(){ evt.name = evtname + ".failed"; evt.statusCode = xhr.getStatusCode(); lager.debug( "service failure: xhr error", evt ); EventDispatcher.fire( evt ); }; xhr.onsuccess = function(){ var response = xhr.getResponseText(); evt.statusCode = xhr.getStatusCode(); if( response === undefined || response === null || response.trim().length === 0 ){ return; } var result = {response: response}; // TODO: fix this. //if( xhr.getResponseHeaders()["Content-Type"] === "application/json" ) try{ eval( "result = {response: " + response + "}"); } catch( e ){ lager.error( e ); } if( result === null || result === undefined ){ return; } evt.response = result.response; if( result.response.errors && result.response.errors.length > 0 ){ evt.name = evtname + ".failed"; EventDispatcher.fire( evt ); lager.debug( "service failure: action returned errors", evt ); return; } evt.name = evtname + ".succeeded"; lager.debug( "service success", evt ); EventDispatcher.fire( evt ); }; evt.name = evtname + ".attempted"; EventDispatcher.fire( {name: evtname + ".attempted", params: params, url: url, xhr: xhr} ); }, createBindings : function(instance){ var evts = instance.getEvents(); for( i=0; i