/* * Copyright (c) 2008-2012 Institut National de l'information Geographique et forestiere France, released under the * BSD license. */ /* * @requires Geoportal/Util.js */ /* * Class: Geoportal.GeoRMHandler * The Geoportal framework GeoRM base class. */ Geoportal.GeoRMHandler= {}; //FIXME: for tiny API, just provide usefull OpenLayers classes and methods ? // where ? build an OpenLayersTiny.js ? OpenLayers= OpenLayers || {}; if (!OpenLayers.getDoc) { /** * APIFunction: getDoc * Return the current working document. * IGNF: _addition_. * * Returns: * {DOMElement} the document */ OpenLayers.getDoc= function() { return OpenLayers._document || document; }; } OpenLayers.Util= OpenLayers.Util || {}; if (!OpenLayers.Util.extend) { /** * APIFunction: OpenLayers.Util.extend * Copy all properties of a source object to a destination object. Modifies * the passed in destination object. Any properties on the source object * that are set to undefined will not be (re)set on the destination * object. * * Parameters: * destination - {Object} The object that will be modified * source - {Object} The object with properties to be set on the destination * * Returns: * {Object} The destination object. */ OpenLayers.Util.extend = function(destination, source) { destination = destination || {}; if(source) { for(var property in source) { var value = source[property]; if(value !== undefined) { destination[property] = value; } } /** * IE doesn't include the toString property when iterating over an * object's * properties with the for(property in object) syntax. Explicitly * check if * the source has its own toString property. */ /* * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative * prototype object" when calling hawOwnProperty if the source object * is an instance of window.Event. */ var sourceIsEvt = typeof window.Event == "function" && source instanceof window.Event; if(!sourceIsEvt && source.hasOwnProperty && source.hasOwnProperty('toString')) { destination.toString = source.toString; } } return destination; }; } if (!OpenLayers.Util.getElement) { /** * Function: getElement * This is the old $() from prototype */ OpenLayers.Util.getElement = function() { var elements = []; for (var i=0, len=arguments.length; i)} List of maps objects using this GeoRMKey */ maps: null, /** * Property: tgts * {Array()} List of HTML documents using this GeoRMKey */ tgts: null, /** * Property: queryUrl * {String} The GeoRM service url with parameters */ queryUrl: null, /** * Property: lastUpdate * {Integer} Time of the last token key update */ lastUpdate: 0, /** * Property: status * {Integer} current state of the token * Values are : *| 0 : valid token *| >0 : update in progress (number of requests) *| -1 : token updated and running queued moveTo calls */ status: 0, /** * Property: domHeads * Array({DOMElement}) internal references to the document's heads. */ domHeads: null, /** * Property: scripts * Array({DOMElement}) internal references to the script tag used to call * the jsonp token in different documents. */ scripts: null, /** * Property: reload * {Boolean} indicate if we need to reload the map when receiving a new token * We need to reload a map if the layer.moveTo calling function was * cancelled due to a previously unavailable token. * Default to *false* */ reload: false, /** * Constant: EVENT_TYPES * {Array(String)} Supported application event types. Register a listener * for a particular event with the following syntax: * (code) * updater.events.register(type, obj, listener); * (end) * * Listeners will be called with a reference to an event object. The * properties of this event depends on exactly what happened. * * All event objects have at least the following properties: * object - {Object} A reference to Geoportal.GeoRMHandler.Updater element. * * Supported geoRM event types: * tokenupdatestart - Triggered when a geoRM token is to be updated. * tokenupdateend - Triggerend when the update process is completed * whatever the state of the token is. * tokenloaded - Triggered when a valid geoRM token has been received. */ EVENT_TYPES: [ "tokenupdatestart", "tokenupdateend", "tokenloaded" ], /** * APIProperty: events * {} */ events: null, /** * APIProperty: onBeforeUpdateToken * {Function} Called before the GeoRM handler ask for creating/renewing the token. * Does nothing by default. */ onBeforeUpdateToken: function() { }, /** * APIProperty: onUpdateTokenFailure * {Function} Called when the GeoRM handler failed in creating/renewing the token. * Does nothing by default. */ onUpdateTokenFailure: function() { }, /** * APIProperty: onUpdateTokenSuccess * {Function} Called when the GeoRM handler succeeded in creating/renewing the token. * Does nothing by default. */ onUpdateTokenSuccess: function() { }, /** * APIProperty: onTokenLoaded * {Function} Callback issued when the token is returned updated. * This function expects an {} as parameter. * Called after for each registered maps. * * Defaults to calling () with current center and zoom. */ onTokenLoaded: function(map) { if (map && map.setCenter) { map.setCenter(map.getCenter(), map.getZoom(), false, true); } }, /** * Constructor: Geoportal.GeoRMHandler.Updater * Geographic Rights Management utility class for getting/updating a GeoRM token. * * Parameters: * geoRMKey - {String} the license key * serverUrl - {String} the server url * ttl - {Integer} the time to live (in seconds) * options - {Object} An optional object whose properties will be set on * this instance. * Currently, the following options are supported : * * transport : indicates the way geographic rights management * information are interchanged with the GeoRM service. Values are : * * json: default value - key is sent by HTTP GET method, result * comes back in JSON. Referrer is sent by the browser as an HTTP * header; * * referrer: same as above, but the __rfrrric__=referrer is * also put in a cookie (for HTTPS connexions); * * all: same as above, but the key=token is also put in * a cookie (Not yet implemented). */ initialize: function(geoRMKey, serverUrl, ttl, options) { OpenLayers.Util.extend(this,options); this.maps= []; this.tgts= []; this.scripts= []; this.domHeads=[]; this.GeoRMKey= geoRMKey; this.lastUpdate= 0; this.serverUrl= serverUrl || Geoportal.GeoRMHandler.GEORM_SERVER_URL; if (this.serverUrl.charAt(this.serverUrl.length - 1) != '/') { this.serverUrl += '/'; } if (ttl) { this.ttl= 1000 * ttl; } this.queryUrl= this.serverUrl + 'getToken?' + "key=" + this.GeoRMKey + '&' + "output=json&callback=Geoportal.GeoRMHandler.U" + this.GeoRMKey + ".callback&"; if (OpenLayers.Events) { this.events= new OpenLayers.Events(this, null, this.EVENT_TYPES); } if (this.eventListeners instanceof Object) { this.eventListeners= []; } this.addOptions(options); if (OpenLayers.Event) { OpenLayers.Event.observe(window, 'unload', this.destroy); } }, /** * Method: addOptions * Process options given on the license key. * Processed options : * * eventListeners; * * Parameters: * options - {Object} */ addOptions: function(options) { if (options) { if (options.eventListeners && options.eventListeners instanceof Object) { if (!this.eventListeners) { this.eventListeners= []; } this.eventListeners.push(options.eventListeners); if (this.events) { this.events.on(options.eventListeners); } } } }, /** * APIMethod: addMap * Register a map using the license key * * Parameters: * map - {} */ addMap: function(map) { for (var i= 0, len= this.maps.length; i= 10) { this.status= 0; // provide hook : this.onUpdateTokenFailure(); if (this.events && this.events.triggerEvent("updatetokenstop")!==false) { if (OpenLayers.Console) { OpenLayers.Console.error(OpenLayers.i18n('geoRM.failed',{'key':this.GeoRMKey})); } } return; } var url= this.queryUrl; for (var key in this.token) { url += key + '=' + this.token[key] + '&'; } for (var i= 0, l=this.domHeads.length; i 0) { this.token= token; if (this.timeout) { window.clearTimeout(this.timeout); this.timeout= null; } this.status= -1; if (this.reload) { for (var i= 0, len= this.maps.length; i. * serverUrl - {String} the url of the token server. If null, use * . * options - {Object} An optional object whose properties will be set on * the rightsManagement key instance : * * onContractsComplete : callback to use when all contracts have been received. * Only used when callback parameter is null; * * capabilities - {Object} holds the following properties : * * proxy - {String} JSON proxy Url, defaults to * ; * * callback - {Function | String} the callback function's name * tocall when receiving service's capabilities. If null, use * ; * * onCapabilitiesComplete - {Function} callback to use when all * capabilities have been received. * Only used when callback option is null. * * Returns: * {Integer} The number of contracts sent. */ Geoportal.GeoRMHandler.getConfig = function (geoRMKey, callback, serverUrl, options) { //FIXME: several getConfig with : // * same key(s) // * different key(s) if (window.gGEOPORTALRIGHTSMANAGEMENT===undefined) { gGEOPORTALRIGHTSMANAGEMENT= { pending: 0, apiKey: [], services: {} }; } // check whether it is callback's return or user's call: if (!geoRMKey) { return 0; } if (typeof(geoRMKey)=='string') { geoRMKey= [geoRMKey]; } if (geoRMKey.length==0) { return 0; } options= options || {}; var gfn= function(f) { if (!f) { return null; } var fn= /\W*function\s+([\w\$]+)\(/.exec(f); if (!fn) { return null; } return fn[1]; }; var callbackName= !callback? 'Geoportal.GeoRMHandler.getContract' : typeof(callback)=='string'? callback : gfn(callback); if (!callbackName) { return 0; } var doc= OpenLayers.getDoc(); var head= (doc.getElementsByTagName("head").length ? doc.getElementsByTagName("head")[0] : doc.body); for (var i= 0, l= geoRMKey.length; i0) { gGEOPORTALRIGHTSMANAGEMENT.pending--; if (contract.error) { OpenLayers.Console.warn(contract.error); } else { var k= gGEOPORTALRIGHTSMANAGEMENT[contract.key]; if (OpenLayers.Util.indexOf(gGEOPORTALRIGHTSMANAGEMENT.apiKey, contract.key)==-1) { gGEOPORTALRIGHTSMANAGEMENT.apiKey.push(contract.key); k= gGEOPORTALRIGHTSMANAGEMENT[contract.key]= { tokenServer:{ url:contract.service, ttl:contract.tokenTimeOut }, tokenTimeOut:contract.tokenTimeOut, bounds: contract.boundingBox? [ contract.boundingBox.minx, contract.boundingBox.miny, contract.boundingBox.maxx, contract.boundingBox.maxy ] : [-180,-90,180,90], allowedGeoportalLayers:[], resources:{} }; } else { if (contract.boundingBox.minxk.bounds[2]) { k.bounds[2]= contract.boundingBox.maxx; } if (contract.boundingBox.maxy>k.bounds[3]) { k.bounds[3]= contract.boundingBox.maxy; } } for (var i= 0, l= contract.resources.length; i. * jsonProxyUrl - {String} the url of the JSON proxy service. If null, use * . * options - {Object} An optional object whose properties will be set on * the rightsManagement key instance : * * onCapabilitiesComplete : callback to use when all capabilities have been received. * Only used when callback parameter is null; * * The returned JSON object contains the following properties : * * http - {Object} contains : * * code - {Integer} the HTTP code of the request; * * url - {String} the proxied service Url; * * xml - {String} the service's capabilities as an XML string. * * Returns: * {Object} the services informations. */ Geoportal.GeoRMHandler.getServicesCapabilities = function (services, callback, jsonProxyUrl, options) { if (window.gGEOPORTALRIGHTSMANAGEMENT===undefined) { gGEOPORTALRIGHTSMANAGEMENT= {}; } if (!services) { if (!gGEOPORTALRIGHTSMANAGEMENT.services) { return null; } services= gGEOPORTALRIGHTSMANAGEMENT.services; } options= options || {}; OpenLayers.Util.applyDefaults(options, gGEOPORTALRIGHTSMANAGEMENT.capabilities); var gfn= function(f) { if (!f) { return null; } var fn= /\W*function\s+([\w\$]+)\(/.exec(f); if (!fn) { return null; } return fn[1]; }; var callbackName= !callback? (options.callback? options.callback : 'Geoportal.GeoRMHandler.getCapabilities') : (typeof(callback)=='string'? callback : gfn(callback)); if (!callbackName) { return null; } for (var u in services) { var srv= services[u]; var stp= srv.type; switch (srv.type) { case 'WFS' : break; case 'WMTS' : break; case 'WMSC' : stp= 'WMS'; break; case 'WMS' : break; default : srv.caps= {}; continue; } var doc= OpenLayers.getDoc(); var head= (doc.getElementsByTagName("head").length ? doc.getElementsByTagName("head")[0] : doc.body); var s= OpenLayers.Util.getElement(srv.id); if (s && s.parentNode ) { s.parentNode.removeChild(s); } s= doc.createElement('script'); s.id= srv.id; s.setAttribute('type', 'text/javascript'); var sUrl= jsonProxyUrl || options.proxy || Geoportal.JSON_PROXY_URL; sUrl= OpenLayers.Util.urlAppend(sUrl, 'url=' + encodeURIComponent(OpenLayers.Util.urlAppend(u, 'SERVICE=' + stp + '&REQUEST=GetCapabilities&')) + '&' + 'callback=' + callbackName + '&'); s.setAttribute('src', sUrl); head.appendChild(s); } if (!callback) { //FIXME: chain getConfig() then getServicesCapabilities() if (options.onCapabilitiesComplete) { gGEOPORTALRIGHTSMANAGEMENT.onCapabilitiesComplete= options.onCapabilitiesComplete; } } return services; }; /** * APIFunction: Geoportal.GeoRMHandler.getCapabilities * Awaits for service's capabilities to be loaded, then call onCapabilitiesComplete * callback when all loaded to finish loading the page. * * Parameters: * obj - {Object} the returned JSON object */ Geoportal.GeoRMHandler.getCapabilities = function(obj) { if (!obj) { obj= {}; } if (!obj.http) { obj.http= {}; } if (!obj.http.code) { obj.http.code= 400; } if (!obj.http.url) { obj.http.url= 'http://localhost/?'; } if (!obj.xml) { obj.xml= ''; } var u= obj.http.url.split('?')[0]; var srv= gGEOPORTALRIGHTSMANAGEMENT.services[u]; if (obj.http.code!=200) { OpenLayers.Console.warn(OpenLayers.i18n('url.error',{'url':obj.http.url,'msg':''})); } else { if (srv) { var doc= OpenLayers.parseXMLString(obj.xml); //TODO utility function for mapping type and parser ? var fmt= null; switch (srv.type) { case 'WFS' : fmt= OpenLayers.Format? OpenLayers.Format.WFSCapabilities : null; break; case 'WMTS' : fmt= OpenLayers.Format? OpenLayers.Format.WMTSCapabilities : null; break; case 'WMSC' : case 'WMS' : fmt= OpenLayers.Format? OpenLayers.Format.WMSCapabilities : null; break; default : break; } if (fmt) { var capsFmt= new fmt(); var caps= null; try { caps= capsFmt.read(doc); } catch (er) { OpenLayers.Console.warn('url.error',{'url':obj.http.url,'msg':''}); } finally { if (caps && caps.exceptions) {//Service Exception var msg= ''; for (var i= 0, l= caps.exceptions.length; i} the map to protect. * options - {Object} An optional object whose properties will be set on * the rightsManagement key instance. * * Returns: * {Object} the rightsManagement key */ Geoportal.GeoRMHandler.addKey = function (geoRMKey, serverUrl, ttl, map, options) { // all except IE<=8 var doc= OpenLayers.getDoc(); var base= (doc.defaultView || doc.parentWindow).Geoportal.GeoRMHandler; if (!base["U" + geoRMKey]) { base["U" + geoRMKey]= new Geoportal.GeoRMHandler.Updater(geoRMKey, serverUrl, ttl, options); base["U" + geoRMKey].getToken(); } else { base["U" + geoRMKey].addOptions(options); } base["U" + geoRMKey].addMap(map); return base["U" + geoRMKey]; }; /** * Constant: Geoportal.GeoRMHandler.GEORM_REFERRER_COOKIENAME * {String} *"__rfrrric__"* */ Geoportal.GeoRMHandler.GEORM_REFERRER_COOKIENAME= "__rfrrric__"; /** * Constant: Geoportal.GeoRMHandler.GEORM_SERVER_URL * {String} *"http://jeton-api.ign.fr/"* */ Geoportal.GeoRMHandler.GEORM_SERVER_URL= "http://jeton-api.ign.fr/"; /** * Constant: Geoportal.JSON_PROXY_URL * {String} *"http://api.ign.fr/geoportail/api/xmlproxy?output=json"* */ Geoportal.JSON_PROXY_URL= "http://api.ign.fr/geoportail/api/xmlproxy?output=json";