torquebox-web 1.0.1-java → 1.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
|
|
1
|
+
Usage:
|
2
|
+
rails generate websockets_client [options]
|
3
|
+
|
4
|
+
Runtime options:
|
5
|
+
-f, [--force] # Overwrite files that already exist
|
6
|
+
-p, [--pretend] # Run but do not make any changes
|
7
|
+
-s, [--skip] # Skip files that already exist
|
8
|
+
-q, [--quiet] # Suppress status output
|
9
|
+
|
10
|
+
Description:
|
11
|
+
Generates the websockets javascript client library for this app.
|
12
|
+
|
13
|
+
Example:
|
14
|
+
rails generate websockets_client
|
15
|
+
|
16
|
+
This will create:
|
17
|
+
public/javascripts/torquebox_ws_client.js
|
@@ -0,0 +1,358 @@
|
|
1
|
+
/*
|
2
|
+
* Based upon Stomp client (c) 2010 by Jeff Mesnil -- http://jmesnil.net/
|
3
|
+
*
|
4
|
+
*/
|
5
|
+
|
6
|
+
(function(window) {
|
7
|
+
|
8
|
+
var Stomp = {};
|
9
|
+
var TorqueBox = {};
|
10
|
+
TorqueBox.WebSockets = {};
|
11
|
+
TorqueBox.WebSockets.Assembly = {};
|
12
|
+
|
13
|
+
|
14
|
+
TorqueBox.WebSockets.Types = {
|
15
|
+
|
16
|
+
any : 0,
|
17
|
+
generic : 1,
|
18
|
+
|
19
|
+
registerMediaType: function(mediaName, mediaType) {
|
20
|
+
this[mediaName] = mediaType;
|
21
|
+
return this[mediaName];
|
22
|
+
}
|
23
|
+
|
24
|
+
};
|
25
|
+
|
26
|
+
TorqueBox.WebSockets.Commands = {
|
27
|
+
handshake : 0x01,
|
28
|
+
handshake_response : 0x02,
|
29
|
+
normal : 0x03
|
30
|
+
};
|
31
|
+
|
32
|
+
TorqueBox.WebSockets.State = {
|
33
|
+
disconnected : 0,
|
34
|
+
handshake : 1,
|
35
|
+
ready : 2
|
36
|
+
};
|
37
|
+
|
38
|
+
TorqueBox.WebSockets.Frame = function(type, command, data) {
|
39
|
+
this.type = type || TorqueBox.WebSockets.Types.generic;
|
40
|
+
this.command = command || TorqueBox.WebSockets.Commands.normal;
|
41
|
+
this.data = data;
|
42
|
+
return this;
|
43
|
+
}
|
44
|
+
|
45
|
+
TorqueBox.WebSockets.Assembly.decode = function(message) {
|
46
|
+
return new TorqueBox.WebSockets.Frame(
|
47
|
+
message.charCodeAt(0),
|
48
|
+
message.charCodeAt(1),
|
49
|
+
message.substring(2));
|
50
|
+
};
|
51
|
+
|
52
|
+
TorqueBox.WebSockets.Assembly.encode = function(frame) {
|
53
|
+
var encodedFrame = [ String.fromCharCode(frame.type),String.fromCharCode(frame.command), frame.data ].join('');
|
54
|
+
return encodedFrame;
|
55
|
+
};
|
56
|
+
|
57
|
+
TorqueBox.WebSockets.client = function(id, url) {
|
58
|
+
|
59
|
+
var uuid = id;
|
60
|
+
var websocket = null;
|
61
|
+
var state = TorqueBox.WebSockets.State.disconnected;
|
62
|
+
var log = window.console;
|
63
|
+
var listeners = {};
|
64
|
+
|
65
|
+
var onopen = function(event) {
|
66
|
+
state = TorqueBox.WebSockets.State.handshake;
|
67
|
+
log.debug("Sending UUID handshake " + uuid);
|
68
|
+
var frame = new TorqueBox.WebSockets.Frame(TorqueBox.WebSockets.Types.generic,
|
69
|
+
TorqueBox.WebSockets.Commands.handshake,
|
70
|
+
uuid);
|
71
|
+
this.send(TorqueBox.WebSockets.Assembly.encode(frame));
|
72
|
+
};
|
73
|
+
|
74
|
+
var onerror = function(error, event) {
|
75
|
+
raise('THERE IS AN ERROR');
|
76
|
+
};
|
77
|
+
|
78
|
+
this.addEventListener = function(event, type, callback, scopeObject) {
|
79
|
+
if (!listeners[event]) listeners[event] = [];
|
80
|
+
listeners[event].push({
|
81
|
+
mediaType: type,
|
82
|
+
fn: callback,
|
83
|
+
scope: scopeObject || this
|
84
|
+
});
|
85
|
+
};
|
86
|
+
|
87
|
+
this.connect = function() {
|
88
|
+
var that = this;
|
89
|
+
websocket = new WebSocket(url);
|
90
|
+
websocket.onmessage = function(message) {
|
91
|
+
onmessage(message, that);
|
92
|
+
}
|
93
|
+
websocket.onclose = function() {
|
94
|
+
onclose(that);
|
95
|
+
};
|
96
|
+
websocket.onerror = onerror;
|
97
|
+
websocket.onopen = onopen;
|
98
|
+
};
|
99
|
+
|
100
|
+
this.notifyListeners = function(event, type, arguments) {
|
101
|
+
var evtListeners = listeners[event];
|
102
|
+
for (var i = 0; i < evtListeners.length; i++) {
|
103
|
+
if (evtListeners[i].mediaType == type || evtListeners[i].mediaType == TorqueBox.WebSockets.Types.any)
|
104
|
+
evtListeners[i].fn.apply(evtListeners[i].scope, arguments);
|
105
|
+
}
|
106
|
+
};
|
107
|
+
|
108
|
+
var onmessage = function(message, client) {
|
109
|
+
var frame = TorqueBox.WebSockets.Assembly.decode(message.data);
|
110
|
+
if (state == TorqueBox.WebSockets.State.handshake) {
|
111
|
+
if (frame.data != uuid) {
|
112
|
+
client.onerror("UUID received from server does not match generated UUID.");
|
113
|
+
websocket.close();
|
114
|
+
} // end if
|
115
|
+
state = TorqueBox.WebSockets.State.ready;
|
116
|
+
client.onready();
|
117
|
+
} else {
|
118
|
+
client.notifyListeners('onmessage', frame.type, [message]);
|
119
|
+
}
|
120
|
+
};
|
121
|
+
|
122
|
+
var onclose = function(client) {
|
123
|
+
client.state = TorqueBox.WebSockets.State.disconnected;
|
124
|
+
client.onclose();
|
125
|
+
}
|
126
|
+
|
127
|
+
this.send = function(frame) {
|
128
|
+
if (state != TorqueBox.WebSockets.State.ready) {
|
129
|
+
this.onerror("The websocket client is not ready!");
|
130
|
+
}
|
131
|
+
var message = TorqueBox.WebSockets.Assembly.encode(frame);
|
132
|
+
websocket.send(message);
|
133
|
+
}
|
134
|
+
|
135
|
+
this.close = function() {
|
136
|
+
websocket.close();
|
137
|
+
};
|
138
|
+
|
139
|
+
this.onready = function() {
|
140
|
+
};
|
141
|
+
|
142
|
+
this.onclose = function() {
|
143
|
+
};
|
144
|
+
|
145
|
+
this.onerror = function(error) {
|
146
|
+
log.error(error);
|
147
|
+
if (state != TorqueBox.WebSockets.State.ready) {
|
148
|
+
log.error("Closing web socket, since we haven't completed the handshake yet.");
|
149
|
+
websocket.close(); // start again if we haven't completed the handshake.
|
150
|
+
}
|
151
|
+
};
|
152
|
+
|
153
|
+
};
|
154
|
+
|
155
|
+
Stomp.mediaType = TorqueBox.WebSockets.Types.registerMediaType('stomp', 0x02);
|
156
|
+
|
157
|
+
Stomp.frame = function(command, headers, body) {
|
158
|
+
return {
|
159
|
+
command : command,
|
160
|
+
headers : headers,
|
161
|
+
body : body,
|
162
|
+
toString : function() {
|
163
|
+
var out = command + '\n';
|
164
|
+
if (headers) {
|
165
|
+
for (header in headers) {
|
166
|
+
if (headers.hasOwnProperty(header)) {
|
167
|
+
out = out + header + ': ' + headers[header] + '\n';
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
out = out + '\n';
|
172
|
+
if (body) {
|
173
|
+
out = out + body;
|
174
|
+
}
|
175
|
+
return out;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
};
|
179
|
+
|
180
|
+
trim = function(str) {
|
181
|
+
return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
182
|
+
};
|
183
|
+
|
184
|
+
Stomp.unmarshal = function(data) {
|
185
|
+
var divider = data.search(/\n\n/), headerLines = data.substring(0,
|
186
|
+
divider).split('\n'), command = headerLines.shift(), headers = {}, body = '';
|
187
|
+
|
188
|
+
// Parse headers
|
189
|
+
var line = idx = null;
|
190
|
+
for ( var i = 0; i < headerLines.length; i++) {
|
191
|
+
line = headerLines[i];
|
192
|
+
idx = line.indexOf(':');
|
193
|
+
headers[trim(line.substring(0, idx))] = trim(line
|
194
|
+
.substring(idx + 1));
|
195
|
+
}
|
196
|
+
|
197
|
+
// Parse body, stopping at the first \0 found.
|
198
|
+
// TODO: Add support for content-length header.
|
199
|
+
var chr = null;
|
200
|
+
for ( var i = divider + 2; i < data.length; i++) {
|
201
|
+
chr = data.charAt(i);
|
202
|
+
if (chr === '\0') {
|
203
|
+
break;
|
204
|
+
}
|
205
|
+
body += chr;
|
206
|
+
}
|
207
|
+
|
208
|
+
return Stomp.frame(command, headers, body);
|
209
|
+
};
|
210
|
+
|
211
|
+
Stomp.marshal = function(command, headers, body) {
|
212
|
+
return Stomp.frame(command, headers, body).toString() + '\0';
|
213
|
+
};
|
214
|
+
|
215
|
+
Stomp.client = function(name, url) {
|
216
|
+
|
217
|
+
var that, login, passcode;
|
218
|
+
var ws = null;
|
219
|
+
var counter = 0; // used to index subscribers
|
220
|
+
// subscription callbacks indexed by subscriber's ID
|
221
|
+
var subscriptions = {};
|
222
|
+
var listeners = {};
|
223
|
+
|
224
|
+
var log = window.console;
|
225
|
+
|
226
|
+
var notifyListeners = function(event, arguments) {
|
227
|
+
var ocListeners = listeners[event];
|
228
|
+
if (ocListeners) {
|
229
|
+
for ( var i = 0; i < ocListeners.length; i++) {
|
230
|
+
ocListeners[i].fn.apply(ocListeners[i].scope, arguments);
|
231
|
+
}
|
232
|
+
} // end if (listeners are defined)
|
233
|
+
}
|
234
|
+
|
235
|
+
onmessage = function(event) {
|
236
|
+
var tbFrame = TorqueBox.WebSockets.Assembly.decode(event.data);
|
237
|
+
log.debug('<<< ' + tbFrame.data);
|
238
|
+
var frame = Stomp.unmarshal(tbFrame.data);
|
239
|
+
if (frame.command === "CONNECTED") {
|
240
|
+
notifyListeners('onconnect', [ frame ]);
|
241
|
+
} else if (frame.command === "MESSAGE") {
|
242
|
+
var onreceive = subscriptions[frame.headers.subscription];
|
243
|
+
if (onreceive) {
|
244
|
+
onreceive(frame);
|
245
|
+
}
|
246
|
+
} else if (frame.command === "RECEIPT" && that.onreceipt) {
|
247
|
+
that.onreceipt(frame);
|
248
|
+
} else if (frame.command === "ERROR" && that.onerror) {
|
249
|
+
notifyListeners('onerror', [ frame ]);
|
250
|
+
} else if (frame.command == "DISCONNECTED")
|
251
|
+
alert('disconnected');
|
252
|
+
};
|
253
|
+
|
254
|
+
transmit = function(command, headers, body) {
|
255
|
+
var out = Stomp.marshal(command, headers, body);
|
256
|
+
log.debug(">>> " + out);
|
257
|
+
var frame = new TorqueBox.WebSockets.Frame();
|
258
|
+
frame.type = Stomp.mediaType;
|
259
|
+
frame.data = out;
|
260
|
+
ws.send(frame);
|
261
|
+
};
|
262
|
+
|
263
|
+
that = {};
|
264
|
+
|
265
|
+
that.addEventListener = function(event, callback, scopeObject) {
|
266
|
+
if (!listeners[event])
|
267
|
+
listeners[event] = [];
|
268
|
+
listeners[event].push({
|
269
|
+
scope : scopeObject || this,
|
270
|
+
fn : callback
|
271
|
+
});
|
272
|
+
}
|
273
|
+
|
274
|
+
that.close = function() {
|
275
|
+
ws.close();
|
276
|
+
}
|
277
|
+
|
278
|
+
that.connect = function(login_, passcode_) {
|
279
|
+
log.debug("Opening Web Socket...");
|
280
|
+
ws = new TorqueBox.WebSockets.client(name, url);
|
281
|
+
ws.addEventListener('onmessage', Stomp.mediaType, onmessage);
|
282
|
+
ws.addEventListener('ondisconnect', Stomp.mediaType, function() {
|
283
|
+
this.close();
|
284
|
+
});
|
285
|
+
ws.onclose = function() {
|
286
|
+
var msg = "Disconnected from STOMP server.";
|
287
|
+
log.debug(msg);
|
288
|
+
notifyListeners('onerror', [ msg ]);
|
289
|
+
};
|
290
|
+
ws.onready = function() {
|
291
|
+
log.debug("Web socket opened... connecting to STOMP server.")
|
292
|
+
transmit("CONNECT", {
|
293
|
+
login : login,
|
294
|
+
passcode : passcode
|
295
|
+
});
|
296
|
+
};
|
297
|
+
login = login_;
|
298
|
+
passcode = passcode_;
|
299
|
+
ws.connect();
|
300
|
+
};
|
301
|
+
|
302
|
+
that.disconnect = function(disconnectCallback) {
|
303
|
+
transmit("DISCONNECT");
|
304
|
+
};
|
305
|
+
|
306
|
+
that.send = function(destination, headers, body) {
|
307
|
+
var headers = headers || {};
|
308
|
+
headers.destination = destination;
|
309
|
+
transmit("SEND", headers, body);
|
310
|
+
};
|
311
|
+
|
312
|
+
that.subscribe = function(destination, callback, headers) {
|
313
|
+
var headers = headers || {};
|
314
|
+
var id = "sub-" + counter++;
|
315
|
+
headers.destination = destination;
|
316
|
+
headers.id = id;
|
317
|
+
subscriptions[id] = callback;
|
318
|
+
transmit("SUBSCRIBE", headers);
|
319
|
+
return id;
|
320
|
+
};
|
321
|
+
|
322
|
+
that.unsubscribe = function(id, headers) {
|
323
|
+
var headers = headers || {};
|
324
|
+
headers.id = id;
|
325
|
+
delete subscriptions[id];
|
326
|
+
transmit("UNSUBSCRIBE", headers);
|
327
|
+
};
|
328
|
+
|
329
|
+
that.begin = function(transaction, headers) {
|
330
|
+
var headers = headers || {};
|
331
|
+
headers.transaction = transaction;
|
332
|
+
transmit("BEGIN", headers);
|
333
|
+
};
|
334
|
+
|
335
|
+
that.commit = function(transaction, headers) {
|
336
|
+
var headers = headers || {};
|
337
|
+
headers.transaction = transaction;
|
338
|
+
transmit("COMMIT", headers);
|
339
|
+
};
|
340
|
+
|
341
|
+
that.abort = function(transaction, headers) {
|
342
|
+
var headers = headers || {};
|
343
|
+
headers.transaction = transaction;
|
344
|
+
transmit("ABORT", headers);
|
345
|
+
};
|
346
|
+
|
347
|
+
that.ack = function(message_id, headers) {
|
348
|
+
var headers = headers || {};
|
349
|
+
headers["message-id"] = message_id;
|
350
|
+
transmit("ACK", headers);
|
351
|
+
};
|
352
|
+
return that;
|
353
|
+
};
|
354
|
+
|
355
|
+
window.Stomp = Stomp;
|
356
|
+
window.TorqueBox = TorqueBox;
|
357
|
+
|
358
|
+
})(window);
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
class WebsocketsClientGenerator < Rails::Generators::Base
|
3
|
+
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
def generate
|
7
|
+
puts "generating ws client"
|
8
|
+
copy_file "torquebox_ws_client.js", "public/javascripts/torquebox_ws_client.js"
|
9
|
+
puts "done generating ws client"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
data/lib/torquebox-web.jar
CHANGED
Binary file
|
data/lib/torquebox-web.rb
CHANGED
metadata
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
name: torquebox-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: "1.1"
|
6
6
|
platform: java
|
7
|
-
authors: []
|
7
|
+
authors: ["The TorqueBox Team"]
|
8
8
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-07-13 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -50,6 +50,9 @@ files:
|
|
50
50
|
- lib/gem_hook.rb
|
51
51
|
- lib/action_controller/session/torque_box_store.rb
|
52
52
|
- lib/action_dispatch/session/torque_box_store.rb
|
53
|
+
- lib/generators/websockets_client/USAGE
|
54
|
+
- lib/generators/websockets_client/websockets_client_generator.rb
|
55
|
+
- lib/generators/websockets_client/templates/torquebox_ws_client.js
|
53
56
|
- lib/torquebox/session/servlet_store.rb
|
54
57
|
has_rdoc: true
|
55
58
|
homepage: http://www.torquebox.org/gem-parent/torquebox-web/
|