OpenPKG CVS Repository http://cvs.openpkg.org/ ____________________________________________________________________________
Server: cvs.openpkg.org Name: Ralf S. Engelschall Root: /v/openpkg/cvs Email: r...@openpkg.org Module: openpkg-src Date: 21-Oct-2009 21:13:52 Branch: HEAD Handle: 2009102120135200 Added files: openpkg-src/activemq activemq-ajax.js Modified files: openpkg-src/activemq activemq.spec Log: provide JavaScript side of AJAX service, too Summary: Revision Changes Path 1.1 +329 -0 openpkg-src/activemq/activemq-ajax.js 1.9 +5 -1 openpkg-src/activemq/activemq.spec ____________________________________________________________________________ patch -p0 <<'@@ .' Index: openpkg-src/activemq/activemq-ajax.js ============================================================================ $ cvs diff -u -r0 -r1.1 activemq-ajax.js --- /dev/null 2009-10-21 21:13:50 +0200 +++ activemq-ajax.js 2009-10-21 21:13:52 +0200 @@ -0,0 +1,329 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// AMQ Ajax handler +// This class provides the main API for using the Ajax features of AMQ. It +// allows JMS messages to be sent and received from javascript when used +// with the org.apache.activemq.web.MessageListenerServlet. +// +// This version of the file provides an adapter interface for the jquery library +// and a namespace for the Javascript file, private/public variables and +// methods, and other scripting niceties. -- jim cook 2007/08/28 + +var org = org || {}; +org.activemq = org.activemq || {}; + +org.activemq.Amq = function() { + var connectStatusHandler; + + // Just a shortcut to eliminate some redundant typing. + var adapter = org.activemq.AmqAdapter; + + if (typeof adapter == 'undefined') + throw "An org.activemq.AmqAdapter must be loaded beforehand!"; + + // The URI of the AjaxServlet. + var uri; + + // The number of seconds that the long-polling socket will stay connected. + // Best to keep this to a value less than one minute. + var timeout; + + // Poll delay. if set to positive integer, this is the time to wait in ms + // before sending the next poll after the last completes. + var pollDelay; + + // Inidicates whether logging is active or not. Not by default. + var logging = false; + + // 5 second delay if an error occurs during poll. This could be due to + // server capacity problems or a timeout condition. + var pollErrorDelay = 5000; + + // Map of handlers that will respond to message receipts. The id used during + // addListener(id, destination, handler) is used to key the callback + // handler. + var messageHandlers = {}; + + // Indicates whether an AJAX post call is in progress. + var batchInProgress = false; + + // A collection of pending messages that accumulate when an AJAX call is in + // progress. These messages will be delivered as soon as the current call + // completes. The array contains objects in the format { destination, + // message, messageType }. + var messageQueue = []; + + /** + * Iterate over the returned XML and for each message in the response, + * invoke the handler with the matching id. + */ + var messageHandler = function(data) { + var response = data.getElementsByTagName("ajax-response"); + if (response != null && response.length == 1) { + connectStatusHandler(true); + var responses = response[0].childNodes; // <response> + for (var i = 0; i < responses.length; i++) { + var responseElement = responses[i]; + + // only process nodes of type element..... + if (responseElement.nodeType != 1) continue; + + var id = responseElement.getAttribute('id'); + + var handler = messageHandlers[id]; + + if (logging && handler == null) { + adapter.log('No handler found to match message with id = ' + id); + continue; + } + + // Loop thru and handle each <message> + for (var j = 0; j < responseElement.childNodes.length; j++) { + handler(responseElement.childNodes[j]); + } + } + } + }; + + var errorHandler = function(xhr, status, ex) { + connectStatusHandler(false); + if (logging) + adapter.log('Error occurred in AJAX call. HTTP result: ' + xhr.status + ', status: ' + status); + } + + var pollErrorHandler = function(xhr, status, ex) { + connectStatusHandler(false); + if (status === 'error' && xhr.status === 0) { + if (logging) + adapter.log('Server connection dropped.'); + setTimeout(function() { sendPoll(); }, pollErrorDelay); + return; + } + if (logging) + adapter.log('Error occurred in AJAX call (poll). HTTP result: ' + xhr.status + ', status: ' + status); + setTimeout(function() { sendPoll(); }, pollErrorDelay); + } + + var pollHandler = function(data) { + try { + messageHandler(data); + } catch(e) { + if (logging) + adapter.log('Exception in the poll handler: ' + data, e); + throw(e); + } finally { + setTimeout(function() { sendPoll(); }, pollDelay); + } + }; + + var sendPoll = function() { + // Workaround IE6 bug where it caches the response + // Generate a unique query string with date and random + var now = new Date(); + var data = 'timeout=' + timeout * 1000 + + '&d=' + now.getTime() + + '&r=' + Math.random(); + var options = { + method: 'get', + data: data, + success: pollHandler, + error: pollErrorHandler + }; + if (logging) + adapter.log("AJAX call: method=GET uri=\"" + uri + "\" data=\"" + data + "\""); + adapter.ajax(uri, options); + }; + + var sendJmsMessage = function(destination, message, type) { + if (batchInProgress) { + // Add message to outbound queue + messageQueue[messageQueue.length] = { + destination: destination, + message: message, + messageType: type + }; + } else { + org.activemq.Amq.startBatch(); + var data = 'destination=' + encodeURIComponent(destination) + '&message=' + encodeURIComponent(message) + '&type=' + encodeURIComponent(type); + if (logging) + adapter.log("AJAX call: method=POST uri=\"" + uri + "\" data=\"" + data + "\""); + adapter.ajax(uri, { + method: 'post', + data: data, + error: errorHandler, + success: org.activemq.Amq.endBatch + }); + } + }; + + var buildParams = function(msgs) { + var s = []; + for (var i = 0, c = msgs.length; i < c; i++) { + if (i != 0) + s[s.length] = '&'; + s[s.length] = ((i == 0) ? 'destination' : 'd' + i); + s[s.length] = '='; + s[s.length] = msgs[i].destination; + s[s.length] = ((i == 0) ? '&message' : '&m' + i); + s[s.length] = '='; + s[s.length] = msgs[i].message; + s[s.length] = ((i == 0) ? '&type' : '&t' + i); + s[s.length] = '='; + s[s.length] = msgs[i].messageType; + } + return s.join(''); + } + + return { + init: function(options) { + connectStatusHandler = options.connectStatusHandler || function(connected){}; + uri = options.uri || '/amq'; + pollDelay = typeof options.pollDelay == 'number' ? options.pollDelay : 0; + timeout = typeof options.timeout == 'number' ? options.timeout : 25; + logging = options.logging; + adapter.init(options); + sendJmsMessage("topic://ActiveMQ.Ajax", 'ping', 'send'); // RSE + sendPoll(); + }, + + startBatch: function() { + batchInProgress = true; + }, + + endBatch: function() { + if (messageQueue.length > 0) { + var body = buildParams(messageQueue); + messageQueue.length = 0; + org.activemq.Amq.startBatch(); + if (logging) + adapter.log("AJAX call: method=POST uri=\"" + uri + "\" data=\"" + body + "\""); + adapter.ajax(uri, { + method: 'post', + data: body, + success: org.activemq.Amq.endBatch, + error: errorHandler + }); + } else { + batchInProgress = false; + } + }, + + // Send a JMS message to a destination (eg topic://MY.TOPIC). Message + // should be xml or encoded xml content. + sendMessage: function(destination, message) { + sendJmsMessage(destination, message, 'send'); + }, + + // Listen on a channel or topic. + // handler must be a function taking a message argument + addListener: function(id, destination, handler) { + messageHandlers[id] = handler; + sendJmsMessage(destination, id, 'listen'); + }, + + // remove Listener from channel or topic. + removeListener: function(id, destination) { + messageHandlers[id] = null; + sendJmsMessage(destination, id, 'unlisten'); + } + }; +}(); + +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// AMQ Ajax Adapter for jQuery +// This class provides an adapter interface for the jquery library to perform +// some of the library-dependent tasks...namely logging and ajax. + +var org = org || {}; +org.activemq = org.activemq || {}; + +org.activemq.AmqAdapter = { + + init: function(options) { + }, + + /** + * Implement this method to make an AJAX call to the AjaxServlet. An + * options object will accompany this class and will contain the properties + * that describe the details of the AJAX call. The options object will + * have the following properties: + * + * - method: 'get' or 'post' + * - data: query data to accompany the post or get. + * - success: A callback function that is invoked upon successful + * completion of the AJAX call. The parameter is: + * - data: The result of the AJAX call. In the case of XML + * data should resolve to a Document element. + * - error: A callback when some type of error occurs. The callback + * function's parameters should be: + * - xhr: The XmlHttpRequest object. + * - status: A text string of the status. + * - ex: The exception that caused the error. + */ + ajax: function(uri, options) { + if (options.method == 'post') { + jQuery.ajax({ + type: "POST", + url: uri, + data: options.data, + success: options.success || function(){}, + error: options.error || function(){}, + beforeSend: function(xhr) { + /* Force "Connection: close" for Mozilla browsers to work around + * a bug where XMLHttpRequest sends an incorrect Content-length + * header. See Mozilla Bugzilla #246651. + */ + xhr.setRequestHeader("Connection", 'close'); + } + }); + } else { + jQuery.ajax({ + type: "GET", + url: uri, + data: options.data, + success: options.success || function(){}, + error: options.error || function(){}, + dataType: 'xml' + }); + } + }, + + log: function(message, exception) { + if (typeof console != 'undefined' && console.log) + console.log("AMQAJAX: " + message); + } +}; + @@ . patch -p0 <<'@@ .' Index: openpkg-src/activemq/activemq.spec ============================================================================ $ cvs diff -u -r1.8 -r1.9 activemq.spec --- openpkg-src/activemq/activemq.spec 21 Oct 2009 17:07:44 -0000 1.8 +++ openpkg-src/activemq/activemq.spec 21 Oct 2009 19:13:52 -0000 1.9 @@ -37,7 +37,8 @@ # list of sources Source0: http://www.apache.org/dist/activemq/apache-activemq/%{version}/apache-activemq-%{version}-bin.tar.gz Source1: activemq.txt -Source2: rc.activemq +Source2: activemq-ajax.js +Source3: rc.activemq # build information Prefix: %{l_prefix} @@ -116,6 +117,9 @@ conf/broker.ks $RPM_BUILD_ROOT%{l_prefix}/etc/activemq/activemq.broker.ks %{l_shtool} install -c -m 644 \ conf/broker.ts $RPM_BUILD_ROOT%{l_prefix}/etc/activemq/activemq.broker.ts + %{l_shtool} install -c -m 644 \ + %{SOURCE activemq-ajax.js} \ + $RPM_BUILD_ROOT%{l_prefix}/share/activemq/service/ajax.js # determine installation files %{l_rpmtool} files -v -ofiles -r$RPM_BUILD_ROOT \ @@ . ______________________________________________________________________ OpenPKG http://openpkg.org CVS Repository Commit List openpkg-cvs@openpkg.org