1 /* 2 **************************************************************** 3 * Licensed Materials - Property of IBM 4 * 5725-S17 IBM MessageSight 5 * (C) Copyright IBM Corp. 2014, 2015. All Rights Reserved. 6 * 7 * US Government Users Restricted Rights - Use, duplication or 8 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 9 **************************************************************** 10 */ 11 MessagingREST = (function (global) { 12 var version = "2.0"; 13 14 /** 15 * The JavaScript application communicates with IBM MessageSight via http plug-in using 16 * a {@link MessagingREST.Client} object. 17 * 18 * The methods are implemented as asynchronous JavaScript methods (even though the 19 * underlying protocol exchange might be synchronous in nature). This means they signal 20 * their completion by calling back to the application via Success or Failure callback 21 * functions provided by the application on the method in question. These callbacks are 22 * called at most once per method invocation and do not persist beyond the lifetime of 23 * the script that made the invocation. 24 * 25 * @name MessagingREST.Client 26 * 27 * @constructor 28 * 29 * @param {string} host - the address of the IBM MessageSight host, as a DNS name or dotted decimal IP address. 30 * @param {number} port - the port number to connect to 31 * @param {string} path - the alias on the IBM MessageSight host. 32 * @param {string} clientid - the MessagingREST client identifier 33 * @param {string} username - the username to authenticate with 34 * @param {string} password - the password for the username provided 35 * 36 */ 37 var Client = function (host, port, path, protocol, clientid, username, password) { 38 39 var trace = function() {}; 40 41 42 if (typeof host !== "string") 43 throw new Error("invalid server name"); 44 45 if (typeof port !== "number" || port < 0) 46 throw new Error("invalid port number"); 47 48 if (typeof path !== "string") 49 throw new Error("invalid path"); 50 51 if (clientid && typeof clientid !== "string") 52 throw new Error("The ClientID is not valid"); 53 54 var ipv6AddSBracket = (host.indexOf(":") != -1 && host.slice(0,1) != "[" && host.slice(-1) != "]"); 55 var url = protocol + "://"+(ipv6AddSBracket?"["+host+"]":host)+":"+port+path; 56 57 trace("Base URL is: " + url); 58 59 60 /** 61 * Set a trace function that the client can use for 62 * logging trace messages. 63 * 64 * @param {function} trace - a trace function that takes one string as an argument 65 */ 66 this.setTrace = function(traceFunction) { 67 if (traceFunction) { 68 trace = traceFunction; 69 } 70 } 71 72 /** 73 * Set the necessary request headers for the a provided 74 * XMLHttpRequest object. Since the request will more than 75 * likely be a CORS request only headers that IBM MessageSight 76 * allows may be set. 77 * @private 78 * 79 * @name MessagingREST.Client#setRequestHeaders 80 * @function 81 * @param {object} request - The XMLHttpRequest object that headers should be set for. 82 * 83 */ 84 this.setRequestHeaders = function(request) { 85 // trace("Enter: Client.setRequestHeaders"); 86 87 if (!request) { 88 return; 89 } 90 91 if (username && password) { 92 var userPass = btoa(username + ":" + password); 93 request.setRequestHeader("Authorization", "Basic " + userPass); 94 } 95 96 if (clientid) { 97 trace("setting header client-id to " + clientid); 98 request.setRequestHeader("ClientID", clientid); 99 } 100 } 101 102 /** 103 * Invoke action to obtain retained messages from topic. 104 * This API will invoke an asynchronous call on the IBM 105 * MessageSight server that will attempt to obtain a retained 106 * message. After successful callback from this API a check 107 * for the retained message can be done with a call to 108 * MessagingREST.Client#retrieveMessages 109 * 110 * 111 * @name MessagingREST.Client#getRetainedMsg 112 * @function 113 * @param {string} topicName - The topic name to obtain a retained message from. 114 * @param {function} onSuccess - Called after a response with a status code of 200 is received 115 * from the server. A single response parameter is passed 116 * to the onSuccess callback: 117 * <ol> 118 * <li>a string that contains the topic 119 * <li>a string that contains any response from the request 120 * </ol> 121 * @param {function} onFailure - Called when a status code other than 200 is received from 122 * the server. Two response parameters are passed to the 123 * onFailure callback: 124 * <ol> 125 * <li>a number that indicates the response code from the server 126 * <li>a string that contains any response text from the server 127 * </ol> 128 * 129 */ 130 this.getRetainedMsg = function(topicName, onSuccess, onFailure) { 131 // trace("Enter: Client.getRetainedMsg"); 132 // GET /restmsg/topic/topicName 133 var topicNameEncoded = encodeURIComponent(topicName); 134 var requestUrl = url + "/message/" + topicNameEncoded; 135 var xhrRetainedMsgs = new XMLHttpRequest(); 136 137 xhrRetainedMsgs.open('GET', requestUrl, true); 138 trace("Request is GET " + requestUrl); 139 this.setRequestHeaders(xhrRetainedMsgs); 140 141 xhrRetainedMsgs.onreadystatechange = function() { 142 if (this.readyState != 4) { return; } 143 if (this.status === 200) { 144 if (onSuccess) { 145 var topic = this.getResponseHeader("Topic"); 146 onSuccess(topic, this.responseText); 147 } 148 } else { 149 if (onFailure) { 150 onFailure(this.status, this.statusText); 151 } 152 } 153 this.onreadystatechange = function() { }; 154 }; 155 xhrRetainedMsgs.send(); 156 } 157 158 /** 159 * Invoke action to delete retained message from a 160 * given topic. 161 * 162 * 163 * @name MessagingREST.Client#deleteRetained 164 * @function 165 * @param {string} topicName - The topic that the retained message should be removed from. 166 * @param {function} onSuccess - Called after a response with a status code of 200 is received 167 * from the server. A single response parameter is passed 168 * to the onSuccess callback: 169 * <ol> 170 * <li>a string that contains any response from the request 171 * </ol> 172 * @param {function} onFailure - Called when a status code other than 200 is received from 173 * the server. Two response parameters are passed to the 174 * onFailure callback: 175 * <ol> 176 * <li>a number that indicates the response code from the server 177 * <li>a string that contains any response text from the server 178 * </ol> 179 * 180 */ 181 this.deleteRetained = function(topicName, onSuccess, onFailure) { 182 // trace("Enter: Client.deleteRetained"); 183 184 // DELETE /restmsg/topic/topicName 185 var topicNameEncoded = encodeURIComponent(topicName); 186 var requestUrl = url + "/message/" + topicNameEncoded; 187 var xhrDeleteRetained = new XMLHttpRequest(); 188 189 trace("Request is DELETE " + requestUrl); 190 xhrDeleteRetained.open('DELETE', requestUrl, true); 191 this.setRequestHeaders(xhrDeleteRetained); 192 193 xhrDeleteRetained.onreadystatechange = function() { 194 if (this.readyState != 4) { return; } 195 if (this.status === 200) { 196 if (onSuccess) { 197 onSuccess(this.responseText); 198 } 199 } else { 200 if (onFailure) { 201 onFailure(this.status, this.statusText); 202 } 203 } 204 this.onreadystatechange = function() { }; 205 }; 206 xhrDeleteRetained.send(null); 207 } 208 209 /** 210 * Publish a message to a specific topic. 211 * 212 * 213 * @name MessagingREST.Client#createTopicSubscription 214 * @function 215 * @param {string} topicName - the topic filter that the subscription should be set to 216 * @param {boolean} persist - if the message should persist 217 * @param {boolean} retain - if the message should be retained 218 * @param {function} onSuccess - Called after a response with a status code of 200 is received 219 * from the server. A single response parameter is passed 220 * to the onSuccess callback: 221 * <ol> 222 * <li>a string that contains any response from the request 223 * </ol> 224 * @param {function} onFailure - Called when a status code other than 200 is received from 225 * the server. Two response parameters are passed to the 226 * onFailure callback: 227 * <ol> 228 * <li>a number that indicates the response code from the server 229 * <li>a string that contains any response text from the server 230 * </ol> 231 */ 232 this.publishMessageTopic = function(topicName, persist, retain, onSuccess, onFailure) { 233 // trace("Enter: Client.publishMessageTopic"); 234 235 // POST /restmsg/topic/topicname?persist=bool&retain=bool 236 var topicNameEncoded = encodeURIComponent(topicName); 237 var requestUrl; 238 var xhrPublish = new XMLHttpRequest(); 239 if (retain) { 240 requestUrl = url + "/message/" + topicNameEncoded; 241 xhrPublish.open('PUT', requestUrl, true); 242 trace("Request is PUT " + requestUrl); 243 } else { 244 requestUrl = url + "/message/" + topicNameEncoded + "?persist=" + persist.toString(); 245 xhrPublish.open('POST', requestUrl, true); 246 trace("Request is POST " + requestUrl); 247 } 248 249 this.setRequestHeaders(xhrPublish); 250 xhrPublish.setRequestHeader("Content-Type", "text/plain"); 251 252 xhrPublish.onreadystatechange = function() { 253 if (this.readyState != 4) { return; } 254 if (this.status === 200) { 255 if (onSuccess) { 256 onSuccess(this.responseText); 257 } 258 } else { 259 if (onFailure) { 260 onFailure(this.status, this.responseText); 261 } 262 } 263 this.onreadystatechange = function() { }; 264 }; 265 266 var msgObj = {message: topicForm.textMessage.value } 267 var msgString = JSON.stringify(msgObj); 268 xhrPublish.send(topicForm.textMessage.value); 269 } 270 }; 271 272 273 // Module contents. 274 return { 275 Client: Client 276 }; 277 278 })(window); 279