├── .gitignore
├── client.js
├── lib
└── net
│ └── sourceforge
│ └── htmlunit
│ └── htmlunit
│ ├── 2.9-SNAPSHOT
│ ├── _maven.repositories
│ ├── htmlunit-2.9-SNAPSHOT-sources.jar
│ ├── htmlunit-2.9-SNAPSHOT.jar
│ ├── htmlunit-2.9-SNAPSHOT.jar.lastUpdated
│ ├── htmlunit-2.9-SNAPSHOT.pom
│ ├── htmlunit-2.9-SNAPSHOT.pom.lastUpdated
│ ├── maven-metadata-local.xml
│ └── resolver-status.properties
│ └── maven-metadata-local.xml
├── pom.xml
├── server.js
└── src
├── main
└── java
│ └── dnode
│ ├── Callback.java
│ ├── ClientHandler.java
│ ├── Connection.java
│ ├── DNode.java
│ ├── DNodeObject.java
│ ├── Server.java
│ ├── netty
│ ├── DNodePipelineFactory.java
│ ├── DNodeServerHandler.java
│ ├── NettyConnection.java
│ └── NettyServer.java
│ ├── socketio
│ ├── SocketIOCodec.java
│ ├── SocketIOConnection.java
│ ├── SocketIOListener.java
│ └── SocketIOWebSocketHandler.java
│ └── webbit
│ ├── DNodeWebSocketHandler.java
│ ├── WebbitConnection.java
│ └── WebbitServer.java
└── test
├── java
└── dnode
│ ├── DNodeObjectTest.java
│ ├── DNodeTest.java
│ ├── socketio
│ └── SocketIOCodecTest.java
│ └── webbit
│ ├── DNodeExample.java
│ └── WebbitIntegrationTest.java
└── resources
└── dnode
└── js
├── dnode.js
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | *.ipr
3 | *.iml
4 | *.iws
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/client.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var DNode = require('dnode');
3 | var m = process.ARGV[2];
4 |
5 | var client = DNode.connect(6060, function (remote) {
6 | remote[m](function (x) {
7 | console.log(x);
8 | });
9 | });
10 |
11 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/_maven.repositories:
--------------------------------------------------------------------------------
1 | #NOTE: This is an internal implementation file, its format can be changed without prior notice.
2 | #Sun Feb 13 08:50:36 AST 2011
3 | htmlunit-2.9-SNAPSHOT.pom>=
4 | htmlunit-2.9-SNAPSHOT-sources.jar>=
5 | htmlunit-2.9-SNAPSHOT.jar>=
6 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT-sources.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslakhellesoy/dnode-java/02d5da6378a0014b8f584917f6710542573dc916/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT-sources.jar
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslakhellesoy/dnode-java/02d5da6378a0014b8f584917f6710542573dc916/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT.jar
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT.jar.lastUpdated:
--------------------------------------------------------------------------------
1 | #NOTE: This is an internal implementation file, its format can be changed without prior notice.
2 | #Sun Feb 13 08:46:51 AST 2011
3 | http\://google-gson.googlecode.com/svn/mavenrepo/.lastUpdated=1297601206938
4 | http\://google-gson.googlecode.com/svn/mavenrepo/.error=
5 | http\://oss.sonatype.org/content/repositories/releases/.error=
6 | http\://oss.sonatype.org/content/repositories/releases/.lastUpdated=1297601207232
7 | file\:///Users/ahellesoy/scm/dnode-java/dnode/lib/.error=
8 | http\://repository.jboss.org/nexus/content/groups/public/.error=
9 | http\://repository.jboss.org/nexus/content/groups/public/.lastUpdated=1297601211367
10 | file\:///Users/ahellesoy/scm/dnode-java/dnode/lib/.lastUpdated=1297601204904
11 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT.pom:
--------------------------------------------------------------------------------
1 |
4 | 4.0.0
5 | net.sourceforge.htmlunit
6 | htmlunit
7 | 2.9-SNAPSHOT
8 | HtmlUnit
9 |
10 | Gargoyle Software Inc.
11 | http://www.GargoyleSoftware.com/
12 |
13 | jar
14 | A headless browser intended for use in testing web-based applications.
15 | http://htmlunit.sourceforge.net
16 |
17 | UTF-8
18 |
19 |
23 |
24 | org.sonatype.oss
25 | oss-parent
26 | 3
27 |
28 |
29 |
30 |
31 | org.apache.maven.plugins
32 | maven-compiler-plugin
33 | 2.3
34 |
35 |
36 | 1.5
37 | 1.5
38 |
39 | **/CodeChecker.java
40 |
41 |
42 |
43 |
44 | org.apache.maven.plugins
45 | maven-checkstyle-plugin
46 | 2.4
47 |
48 | checkstyle.xml
49 | true
50 | true
51 | true
52 |
53 | checkstyle.suppressions.file=checkstyle_suppressions.xml
54 | checkstyle.header.file=LICENSE.txt
55 |
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-jar-plugin
61 | 2.3
62 |
63 |
64 |
65 | true
66 | true
67 |
68 |
69 | ${pom.url}
70 |
71 | ${svnrevision}
72 | ${label}
73 |
74 |
75 |
76 |
77 |
78 |
79 | test-jar
80 |
81 |
82 |
83 |
84 |
85 | org.apache.maven.plugins
86 | maven-site-plugin
87 | 2.2
88 |
89 | ${basedir}/src/site/maven-site.vm
90 |
91 |
92 |
93 | org.apache.maven.plugins
94 | maven-assembly-plugin
95 | 2.2-beta-4
96 |
97 |
98 | make-assembly
99 | package
100 |
101 | single
102 |
103 |
104 |
105 |
106 | false
107 |
108 | ${basedir}/src/assembly/bin-distribution.xml
109 | ${basedir}/src/assembly/src-distribution.xml
110 |
111 |
112 |
113 |
114 | org.apache.maven.plugins
115 | maven-source-plugin
116 | 2.1
117 |
118 |
119 |
120 | jar
121 |
122 |
123 |
124 |
125 |
126 | maven-antrun-plugin
127 | 1.3
128 |
129 |
130 | moveFiles
131 | package
132 |
133 | run
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | org.apache.maven.plugins
158 | maven-eclipse-plugin
159 | 2.7
160 |
161 | true
162 | true
163 |
164 |
165 |
178 |
179 |
180 |
181 |
182 | with-library-tests
183 |
184 | true
185 |
186 |
187 |
188 |
189 | org.apache.maven.plugins
190 | maven-surefire-plugin
191 | 2.7.1
192 |
193 | -Xmx512m -Xms128m
194 |
195 | maven
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | without-library-tests
204 |
205 |
206 | withoutLibs
207 |
208 |
209 |
210 |
211 |
212 | org.apache.maven.plugins
213 | maven-surefire-plugin
214 | 2.7.1
215 |
216 |
217 | **/libraries/*.java
218 |
219 | -Xmx512m -Xms128m
220 |
221 | maven
222 |
223 |
224 |
225 |
226 |
227 |
228 | src/test/resources
229 |
230 | libraries/**/*.*
231 |
232 |
233 |
234 |
235 |
236 |
237 | only-library-tests
238 |
239 |
240 | onlyLibs
241 |
242 |
243 |
244 |
245 |
246 | org.apache.maven.plugins
247 | maven-surefire-plugin
248 | 2.7.1
249 |
250 |
251 | **/libraries/*.java
252 |
253 | -Xmx512m -Xms128m
254 |
255 | maven
256 |
257 |
258 |
259 |
260 |
261 |
262 | src/test/resources
263 |
264 | libraries/**/*.*
265 |
266 |
267 |
268 |
269 |
270 |
271 | mikeCI
272 |
273 |
274 | mikeCI
275 |
276 |
277 |
278 |
279 |
280 | org.apache.maven.plugins
281 | maven-surefire-plugin
282 | 2.7.1
283 |
284 |
285 | **/H*Applet*Test.java
286 | **/HtmlFileInputTest.java
287 |
288 | -Xmx512m -Xms128m
289 |
290 | maven
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 | org.apache.maven.plugins
302 | maven-javadoc-plugin
303 | 2.7
304 |
305 | com.gargoylesoftware.htmlunit.javascript:com.gargoylesoftware.htmlunit.protocol:com.gargoylesoftware.htmlunit.ssl:com.gargoylesoftware.htmlunit.html.xpath:com.gargoylesoftware.htmlunit.html.applets:com.gargoylesoftware.htmlunit.html.impl
306 |
307 | http://java.sun.com/j2se/1.5.0/docs/api/
308 | http://commons.apache.org/logging/apidocs/
309 | http://commons.apache.org/codec/apidocs/
310 | http://hc.apache.org/httpcomponents-client/httpclient/apidocs/
311 |
312 | maven
313 |
314 |
315 |
316 | org.apache.maven.plugins
317 | maven-jxr-plugin
318 |
319 |
320 | org.apache.maven.plugins
321 | maven-pmd-plugin
322 |
323 | 1.5
324 |
325 |
326 |
327 | org.apache.maven.plugins
328 | maven-changes-plugin
329 | 2.4
330 |
331 |
332 |
333 | changes-report
334 |
335 |
336 |
337 |
338 |
339 | http://sourceforge.net/support/tracker.php?aid=%ISSUE%
340 |
341 |
342 |
343 |
344 | org.codehaus.mojo
345 | jdepend-maven-plugin
346 |
347 |
348 | org.apache.maven.plugins
349 | maven-surefire-report-plugin
350 | 2.7.1
351 |
352 | false
353 |
354 |
355 |
356 |
357 |
358 | sourceforge
359 | http://sourceforge.net/tracker/?group_id=47038
360 |
361 | 2002
362 |
363 |
364 | Apache License, Version 2.0
365 | http://www.apache.org/licenses/LICENSE-2.0.txt
366 | repo
367 |
368 |
369 |
370 | scm:svn:https://htmlunit.svn.sourceforge.net/svnroot/htmlunit/trunk/htmlunit
371 | scm:svn:https://htmlunit.svn.sourceforge.net/svnroot/htmlunit/trunk/htmlunit
372 | http://htmlunit.svn.sourceforge.net/viewvc/htmlunit
373 |
374 |
375 | Cruise Control
376 | http://build.canoo.com/htmlunit
377 |
378 |
379 |
380 | HtmlUnit Users
381 | http://lists.sourceforge.net/lists/listinfo/htmlunit-user
382 | http://lists.sourceforge.net/lists/listinfo/htmlunit-user
383 | http://lists.sourceforge.net/lists/listinfo/htmlunit-user
384 | htmlunit-user@lists.sourceforge.net
385 |
386 | http://www.nabble.com/HtmlUnit---General-f2599.html
387 | http://htmlunit.markmail.org/
388 | http://marc.info/?l=htmlunit-user
389 |
390 |
391 |
392 | HtmlUnit Developers
393 | http://lists.sourceforge.net/lists/listinfo/htmlunit-develop
394 | http://lists.sourceforge.net/lists/listinfo/htmlunit-develop
395 | http://lists.sourceforge.net/lists/listinfo/htmlunit-develop
396 | htmlunit-develop@lists.sourceforge.net
397 |
398 | http://www.nabble.com/HtmlUnit---Dev-f2598.html
399 | http://htmlunit.markmail.org/
400 | http://marc.info/?l=htmlunit-develop
401 |
402 |
403 |
404 |
405 |
406 | Mike Bowler
407 | mbowler
408 | mbowler@GargoyleSoftware.com
409 | Gargoyle Software Inc.
410 | http://www.sphericalimprovement.com/blogs/mbowler/
411 | -5
412 |
413 |
414 | David K. Taylor
415 | dktaylor
416 |
417 |
418 | Brad Clarke
419 | bradclarke
420 | bradclarke@users.sourceforge.net
421 | http://www.bradclarke.com/
422 | -6
423 |
424 |
425 | Marc Guillemot
426 | mguillem
427 | mguillem@users.sourceforge.net
428 | http://mguillem.wordpress.com/
429 | +1
430 |
431 |
432 | Chris Erskine
433 | cerskine
434 | cerskine@users.sourceforge.net
435 | -7
436 |
437 |
438 | Daniel Gredler
439 | sdanig
440 | sdanig@users.sourceforge.net
441 | http://daniel.gredler.net/
442 | -5
443 |
444 |
445 | Ahmed Ashour
446 | asashour
447 | asashour@users.sourceforge.net
448 | http://asashour.blogspot.com/
449 | +3
450 |
451 |
452 | Sudhan Moghe
453 | sudhan_moghe
454 | sudhan_moghe@users.sourceforge.net
455 | +5.5
456 |
457 |
458 | Ronald Brill
459 | rbri
460 | rbri@rbri.de
461 | http://www.wetator.org/
462 | +1
463 |
464 |
465 |
466 |
467 | Noboru Sinohara
468 |
469 |
470 | Mike J. Bresnahan
471 | gudujarlson@sf.net
472 |
473 |
474 | Dominique Broeglin
475 |
476 |
477 | Alex Nikiforoff
478 |
479 |
480 | Barnaby Court
481 |
482 |
483 | Andreas Hangler
484 |
485 |
486 | Jun Chen
487 | chen_jun@users.sourceforge.net
488 |
489 |
490 | Christian Sell
491 | cse@dynabean.de
492 |
493 |
494 | Darrell DeBoer
495 |
496 |
497 | David D. Kilzer
498 |
499 |
500 | Ben Curren
501 | bcurren@esomnie.com
502 |
503 |
504 | Mike Williams
505 |
506 |
507 | Mike Gallaher
508 |
509 |
510 | Dierk Koenig
511 |
512 |
513 | Mike Bresnahan
514 |
515 |
516 | Sergey Gorelkin
517 |
518 |
519 | Chris Eldredge
520 |
521 |
522 | Hans Donner
523 |
524 |
525 | Michael Ottati
526 |
527 |
528 | George Murnock
529 |
530 |
531 | Kent Tong
532 |
533 |
534 | Alfred Nathaniel
535 |
536 |
537 | Bruce Faulkner
538 |
539 |
540 | Ray Suliteanu
541 |
542 |
543 | Denis N. Antonioli
544 |
545 |
546 | Stefan Anzinger
547 |
548 |
549 | Lothar Märkle
550 |
551 |
552 | Ian Lovejoy
553 |
554 |
555 | Paul King
556 |
557 |
558 | Vikram Shitole
559 |
560 |
561 | Mark van Leeuwen
562 |
563 |
564 | Brad Murray
565 |
566 |
567 | Julien Henry
568 |
569 |
570 | Andre Soereng
571 |
572 |
573 | Karel Kolman
574 |
575 |
576 | Bruce Chapman
577 |
578 |
579 | Kristian Muntau
580 |
581 |
582 | Sam Hough
583 |
584 |
585 | Deryk Sinotte
586 |
587 |
588 | Martin Tamme
589 |
590 |
591 | Philip Graf
592 |
593 |
594 | Rodney Gitzel
595 |
596 |
597 | Matt Ryall
598 |
599 |
600 | Rob Di Marco
601 |
602 |
603 | Gareth Davis
604 |
605 |
606 | David Bylsma
607 |
608 |
609 | Dmitri Zoubkov
610 |
611 |
612 | Stuart Begg
613 |
614 |
615 | Rene Schwietzke
616 |
617 |
618 | Ethan Glasser-Camp
619 |
620 |
621 | Marco Cova
622 |
623 |
624 | Mike Dirolf
625 |
626 |
627 | Mirko Friedenhagen
628 |
629 |
630 | Richard Eggert
631 |
632 |
633 | Tomasz Kalkosinski
634 |
635 |
636 | Peter Faller
637 |
638 |
639 | Benoit Heinrich
640 |
641 |
642 | Amit Manjhi
643 |
644 |
645 | Nicolas Belisle
646 |
647 |
648 | Amit Khanna
649 |
650 |
651 |
652 |
653 | xalan
654 | xalan
655 | 2.7.1
656 |
657 |
658 | xerces
659 | xercesImpl
660 |
661 |
662 |
663 |
664 | commons-collections
665 | commons-collections
666 | 3.2.1
667 |
668 |
669 | commons-lang
670 | commons-lang
671 | 2.6
672 |
673 |
674 | org.apache.httpcomponents
675 | httpclient
676 | 4.1
677 |
678 |
679 | org.apache.httpcomponents
680 | httpclient
681 | 4.1
682 | test-jar
683 | test
684 |
685 |
686 | org.apache.httpcomponents
687 | httpmime
688 | 4.1
689 |
690 |
691 | commons-codec
692 | commons-codec
693 | 1.4
694 |
695 |
696 | net.sourceforge.htmlunit
697 | htmlunit-core-js
698 | 2.9-SNAPSHOT
699 |
700 |
701 |
702 | xerces
703 | xercesImpl
704 | 2.9.1
705 |
706 |
707 | net.sourceforge.nekohtml
708 | nekohtml
709 | 1.9.15-SNAPSHOT
710 |
711 |
712 | xerces
713 | xercesImpl
714 |
715 |
716 |
717 |
718 | net.sourceforge.cssparser
719 | cssparser
720 | 0.9.5
721 |
722 |
723 | commons-io
724 | commons-io
725 | 2.0
726 |
727 |
728 | commons-logging
729 | commons-logging
730 | 1.1.1
731 |
732 |
733 |
734 | junit
735 | junit
736 | 4.8.2
737 | test
738 |
739 |
740 | gsbase
741 | gsbase
742 | 2.0.1
743 | test
744 |
745 |
746 | org.easymock
747 | easymock
748 | 3.0
749 | test
750 |
751 |
752 | log4j
753 | log4j
754 | 1.2.16
755 | test
756 |
757 |
758 | commons-fileupload
759 | commons-fileupload
760 | 1.2.2
761 | test
762 |
763 |
764 | org.eclipse.jetty
765 | jetty-security
766 | 7.1.6.v20100715
767 | test
768 |
769 |
770 | org.eclipse.jetty
771 | jetty-server
772 | 7.1.6.v20100715
773 | test
774 |
775 |
776 | org.eclipse.jetty
777 | jetty-util
778 | 7.1.6.v20100715
779 |
780 |
781 | org.eclipse.jetty
782 | jetty-webapp
783 | 7.1.6.v20100715
784 | test
785 |
786 |
787 | org.eclipse.jetty
788 | jetty-websocket
789 | 7.1.6.v20100715
790 | test
791 |
792 |
793 |
794 | org.slf4j
795 | slf4j-api
796 | 1.6.1
797 | test
798 |
799 |
800 | org.slf4j
801 | slf4j-log4j12
802 | 1.6.1
803 | test
804 |
805 |
806 | jfree
807 | jfreechart
808 | 1.0.12
809 | test
810 |
811 |
812 |
813 | org.seleniumhq.selenium
814 | selenium-htmlunit-driver
815 | 2.0b1
816 | test
817 |
818 |
819 | net.sourceforge.htmlunit
820 | htmlunit
821 |
822 |
823 |
824 |
825 | org.seleniumhq.selenium
826 | selenium-ie-driver
827 | 2.0b1
828 | test
829 |
830 |
831 | org.seleniumhq.selenium
832 | selenium-firefox-driver
833 | 2.0b1
834 | test
835 |
836 |
837 |
838 |
839 | htmlunit-website
840 | HtmlUnit WebSite - Sourceforge
841 |
842 | scp://shell.sourceforge.net/home/groups/h/ht/htmlunit/htdocs/
843 |
844 |
845 |
846 | htmlunit-m2-repo
847 |
848 | sftp://web.sourceforge.net/home/groups/h/ht/htmlunit/htdocs/m2-repo
849 |
850 | HtmlUnit Maven 2 Repository
851 |
852 |
853 | htmlunit-m2-repo-snapshots
854 |
855 | sftp://web.sourceforge.net/home/groups/h/ht/htmlunit/htdocs/m2-repo-snapshots
856 |
857 | HtmlUnit Maven 2 Snapshots Repository
858 | false
859 |
860 |
861 |
862 |
863 |
864 | true
865 | always
866 |
867 |
868 | false
869 |
870 | HtmlUnitSnapshots
871 | HtmlUnit Snapshots
872 | http://htmlunit.sourceforge.net/m2-repo-snapshots
873 | default
874 |
875 |
876 |
877 | true
878 | always
879 |
880 |
881 | false
882 |
883 | NekoHTMLSnapshots
884 | NekoHTML Snapshots
885 | http://build.canoo.com/NekoHTML/artifacts/m2-repo
886 | default
887 |
888 |
889 |
890 | true
891 | always
892 |
893 |
894 | true
895 |
896 | jetty-with-staging
897 | Jetty with staging
898 | https://oss.sonatype.org/content/groups/jetty-with-staging
899 | default
900 |
901 |
902 |
903 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/htmlunit-2.9-SNAPSHOT.pom.lastUpdated:
--------------------------------------------------------------------------------
1 | #NOTE: This is an internal implementation file, its format can be changed without prior notice.
2 | #Sun Feb 13 08:46:44 AST 2011
3 | http\://google-gson.googlecode.com/svn/mavenrepo/.lastUpdated=1297601201638
4 | http\://google-gson.googlecode.com/svn/mavenrepo/.error=
5 | http\://oss.sonatype.org/content/repositories/releases/.error=
6 | http\://oss.sonatype.org/content/repositories/releases/.lastUpdated=1297601201965
7 | file\:///Users/ahellesoy/scm/dnode-java/dnode/lib/.error=
8 | http\://repository.jboss.org/nexus/content/groups/public/.error=
9 | http\://repository.jboss.org/nexus/content/groups/public/.lastUpdated=1297601204817
10 | file\:///Users/ahellesoy/scm/dnode-java/dnode/lib/.lastUpdated=1297601200181
11 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/maven-metadata-local.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | net.sourceforge.htmlunit
4 | htmlunit
5 | 2.9-SNAPSHOT
6 |
7 |
8 | true
9 |
10 | 20110213125036
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/2.9-SNAPSHOT/resolver-status.properties:
--------------------------------------------------------------------------------
1 | #NOTE: This is an internal implementation file, its format can be changed without prior notice.
2 | #Sun Feb 13 08:46:40 AST 2011
3 | maven-metadata-Sonatype.xml.lastUpdated=1297601199659
4 | maven-metadata-Local.xml.error=
5 | maven-metadata-Local.xml.lastUpdated=1297601198868
6 | maven-metadata-GSon.xml.error=
7 | maven-metadata-Sonatype.xml.error=
8 | maven-metadata-GSon.xml.lastUpdated=1297601199758
9 | maven-metadata-JBoss.xml.lastUpdated=1297601200176
10 | maven-metadata-JBoss.xml.error=
11 |
--------------------------------------------------------------------------------
/lib/net/sourceforge/htmlunit/htmlunit/maven-metadata-local.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | net.sourceforge.htmlunit
4 | htmlunit
5 |
6 |
7 | 2.9-SNAPSHOT
8 |
9 | 20110213125036
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.aslakhellesoy
5 | dnode
6 | jar
7 | 1.0-SNAPSHOT
8 | dnode
9 | http://maven.apache.org
10 |
11 |
12 | com.google.code.gson
13 | gson
14 | 1.6
15 |
16 |
17 | webbit
18 | webbit
19 | 0.0.1
20 |
21 |
22 | webbit
23 | webbit
24 | 0.0.1
25 |
26 |
27 | org.jboss.netty
28 | netty
29 | 3.2.3.Final
30 |
31 |
32 | junit
33 | junit
34 | 4.8.2
35 | test
36 |
37 |
38 | net.sourceforge.htmlunit
39 | htmlunit
40 | 2.9-SNAPSHOT
41 | test
42 |
43 |
44 | commons-codec
45 | commons-codec
46 | 1.4
47 | test
48 |
49 |
50 |
51 |
52 | Local
53 | file://${basedir}/lib/
54 |
55 | true
56 |
57 |
58 |
59 | GSon
60 | http://google-gson.googlecode.com/svn/mavenrepo/
61 |
62 |
63 | Sonatype
64 | http://oss.sonatype.org/content/repositories/releases/
65 |
66 |
67 | JBoss
68 | http://repository.jboss.org/nexus/content/groups/public/
69 |
70 |
71 |
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-compiler-plugin
76 |
77 | UTF-8
78 | 1.6
79 | 1.6
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var DNode = require('dnode');
3 | var sys = require('sys');
4 |
5 | var server = DNode({
6 | moo : function (reply) {
7 | reply(100);
8 | server.close();
9 | },
10 | boo : function (n, reply) {
11 | reply(n+1);
12 | server.close();
13 | }
14 | }).listen(6060);
15 |
--------------------------------------------------------------------------------
/src/main/java/dnode/Callback.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | public interface Callback {
4 | void call(Object... args) throws RuntimeException;
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/dnode/ClientHandler.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | public interface ClientHandler {
4 | void onConnect(T client);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/dnode/Connection.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | import com.google.gson.JsonElement;
4 |
5 | public interface Connection {
6 | void close();
7 | void write(JsonElement data);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/dnode/DNode.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | import com.google.gson.*;
4 |
5 | import java.io.IOException;
6 | import java.lang.reflect.*;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class DNode {
11 | private final List connections = new ArrayList();
12 | private final DNodeObject instance;
13 | private final ClientHandler clientHandler;
14 |
15 | public DNode(Object instance) {
16 | this(instance, null);
17 | }
18 |
19 | public DNode(Object instance, ClientHandler clientHandler) {
20 | this.instance = new DNodeObject(instance);
21 | this.clientHandler = clientHandler;
22 | }
23 |
24 | public void listen(Server server) throws IOException {
25 | server.listen(this);
26 | }
27 |
28 | private JsonElement methods() {
29 | JsonArray arguments = new JsonArray();
30 | arguments.add(instance.getSignature());
31 | return response("methods", arguments, instance.getCallbacks(), new JsonArray());
32 | }
33 |
34 | private JsonElement response(String method, JsonArray arguments, JsonObject callbacks, JsonArray links) {
35 | return response(new JsonPrimitive(method), arguments, callbacks, links);
36 | }
37 |
38 | public JsonElement response(int method, JsonArray arguments, JsonObject callbacks, JsonArray links) {
39 | return response(new JsonPrimitive(method), arguments, callbacks, links);
40 | }
41 |
42 | private JsonElement response(JsonElement method, JsonArray arguments, JsonObject callbacks, JsonArray links) {
43 | JsonObject response = new JsonObject();
44 | response.add("method", method);
45 | response.add("arguments", arguments);
46 | response.add("callbacks", callbacks);
47 | response.add("links", links);
48 | return response;
49 | }
50 |
51 | public void onOpen(Connection connection) {
52 | connections.add(connection);
53 | connection.write(methods());
54 | if(clientHandler != null) {
55 | T clientProxy = createClientProxy(connection);
56 | clientHandler.onConnect(clientProxy);
57 | }
58 | }
59 |
60 | private T createClientProxy(final Connection connection) {
61 | ParameterizedType type = (ParameterizedType) clientHandler.getClass().getGenericInterfaces()[0];
62 | Class clientType = (Class) type.getActualTypeArguments()[0];
63 | T clientProxy = (T) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{clientType}, new InvocationHandler() {
64 | @Override
65 | public Object invoke(Object target, Method method, Object[] args) throws Throwable {
66 | JsonArray arguments = transform(args);
67 | JsonObject callbacks = new JsonObject();
68 | JsonArray links = new JsonArray();
69 | connection.write(response(method.getName(), arguments, callbacks, links));
70 | return null;
71 | }
72 | });
73 | return clientProxy;
74 | }
75 |
76 | public void onMessage(Connection connection, String msg) {
77 | JsonObject json = new JsonParser().parse(msg).getAsJsonObject();
78 | JsonPrimitive method = json.getAsJsonPrimitive("method");
79 | if (method.isString() && method.getAsString().equals("methods")) {
80 | defineClientMethods(json.getAsJsonArray("arguments").get(0).getAsJsonObject());
81 | } else {
82 | instance.invoke(this, json, connection);
83 | }
84 | }
85 |
86 | public JsonArray transform(Object[] args) {
87 | JsonArray result = new JsonArray();
88 | for (Object arg : args) {
89 | result.add(toJson(arg));
90 | }
91 | return result;
92 | }
93 |
94 | private JsonElement toJson(Object o) {
95 | JsonElement e;
96 | if (o instanceof String) {
97 | e = new JsonPrimitive((String) o);
98 | } else if (o instanceof Number) {
99 | e = new JsonPrimitive((Number) o);
100 | } else {
101 | throw new RuntimeException("Unsupported type: " + o.getClass());
102 | }
103 | return e;
104 | }
105 |
106 | private void defineClientMethods(JsonObject methods) {
107 | // TODO: Verify that the client's reported methods have the same
108 | // signatures as our client proxy, and fail fast if it doesn't.
109 | }
110 |
111 | public void closeAllConnections() {
112 | for (Connection connection : connections) {
113 | connection.close();
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/dnode/DNodeObject.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | import com.google.gson.JsonArray;
4 | import com.google.gson.JsonElement;
5 | import com.google.gson.JsonObject;
6 | import com.google.gson.JsonPrimitive;
7 |
8 | import java.lang.reflect.InvocationTargetException;
9 | import java.lang.reflect.Method;
10 | import java.util.Map;
11 | import java.util.Set;
12 |
13 | public class DNodeObject {
14 | private final Object instance;
15 |
16 | public DNodeObject(Object instance) {
17 | this.instance = instance;
18 | }
19 |
20 | public JsonElement getSignature() {
21 | Class> klass = this.instance.getClass();
22 | JsonObject signature = new JsonObject();
23 | for (Method m : klass.getDeclaredMethods()) {
24 | signature.addProperty(m.getName(), "[Function]");
25 | }
26 | return signature;
27 | }
28 |
29 | public JsonObject getCallbacks() {
30 | Class> klass = this.instance.getClass();
31 | JsonObject callbacks = new JsonObject();
32 | int index = 0;
33 | for (Method m : klass.getDeclaredMethods()) {
34 | Class>[] parameterTypes = m.getParameterTypes();
35 | for (Class> parameterType : parameterTypes) {
36 | if (Callback.class.isAssignableFrom(parameterType)) {
37 | JsonArray path = new JsonArray();
38 | path.add(new JsonPrimitive("0"));
39 | path.add(new JsonPrimitive(m.getName()));
40 | callbacks.add(String.valueOf(index++), path);
41 | }
42 | }
43 | }
44 | return callbacks;
45 | }
46 |
47 | public void invoke(final DNode dNode, JsonObject invocation, final Connection connection) {
48 | try {
49 | int methodIndex = invocation.get("method").getAsInt();
50 | Set> callbacks = invocation.get("callbacks").getAsJsonObject().entrySet();
51 | for (Map.Entry callback : callbacks) {
52 | final int callbackId = Integer.parseInt(callback.getKey());
53 | JsonArray path = callback.getValue().getAsJsonArray();
54 | Callback cb = new Callback() {
55 | @Override
56 | public void call(Object... args) throws RuntimeException {
57 | JsonArray jsonArgs = dNode.transform(args);
58 | connection.write(dNode.response(callbackId, jsonArgs, new JsonObject(), new JsonArray()));
59 | }
60 | };
61 | instance.getClass().getDeclaredMethods()[methodIndex].invoke(instance, cb);
62 | }
63 | } catch (IllegalAccessException e) {
64 | e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
65 | } catch (InvocationTargetException e) {
66 | e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
67 | }
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/dnode/Server.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | import java.io.IOException;
4 |
5 | public interface Server {
6 | void listen(DNode dnode) throws IOException;
7 | void shutdown() throws IOException;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/dnode/netty/DNodePipelineFactory.java:
--------------------------------------------------------------------------------
1 | package dnode.netty;
2 |
3 | import dnode.DNode;
4 | import org.jboss.netty.channel.ChannelPipeline;
5 | import org.jboss.netty.channel.ChannelPipelineFactory;
6 | import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
7 | import org.jboss.netty.handler.codec.frame.Delimiters;
8 | import org.jboss.netty.handler.codec.string.StringDecoder;
9 | import org.jboss.netty.handler.codec.string.StringEncoder;
10 |
11 | import static org.jboss.netty.channel.Channels.pipeline;
12 |
13 | public class DNodePipelineFactory implements ChannelPipelineFactory {
14 | private final DNode dnode;
15 |
16 | public DNodePipelineFactory(DNode dnode) {
17 | this.dnode = dnode;
18 | }
19 |
20 | @Override
21 | public ChannelPipeline getPipeline() throws Exception {
22 | ChannelPipeline pipeline = pipeline();
23 | pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
24 | pipeline.addLast("decoder", new StringDecoder());
25 | pipeline.addLast("encoder", new StringEncoder());
26 | pipeline.addLast("handler", new DNodeServerHandler(dnode));
27 | return pipeline;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/dnode/netty/DNodeServerHandler.java:
--------------------------------------------------------------------------------
1 | package dnode.netty;
2 |
3 | import dnode.Connection;
4 | import dnode.DNode;
5 | import org.jboss.netty.channel.*;
6 |
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class DNodeServerHandler extends SimpleChannelUpstreamHandler {
11 | private final DNode dnode;
12 | private Map connections = new HashMap();
13 |
14 | public DNodeServerHandler(DNode dnode) {
15 | this.dnode = dnode;
16 | }
17 |
18 | @Override
19 | public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
20 | Connection connection = new NettyConnection(e.getChannel());
21 | connections.put(e.getChannel(), connection);
22 | dnode.onOpen(connection);
23 | }
24 |
25 | @Override
26 | public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
27 | String message = (String) e.getMessage();
28 | dnode.onMessage(connections.get(e.getChannel()), message);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/dnode/netty/NettyConnection.java:
--------------------------------------------------------------------------------
1 | package dnode.netty;
2 |
3 | import com.google.gson.JsonElement;
4 | import dnode.Connection;
5 | import org.jboss.netty.channel.Channel;
6 |
7 | public class NettyConnection implements Connection {
8 | private final Channel channel;
9 |
10 | public NettyConnection(Channel channel) {
11 | this.channel = channel;
12 | }
13 |
14 | @Override
15 | public void close() {
16 | channel.close();
17 | }
18 |
19 | @Override
20 | public void write(JsonElement data) {
21 | channel.write(data.toString() + "\n");
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/dnode/netty/NettyServer.java:
--------------------------------------------------------------------------------
1 | package dnode.netty;
2 |
3 | import dnode.DNode;
4 | import dnode.Server;
5 | import org.jboss.netty.bootstrap.ServerBootstrap;
6 | import org.jboss.netty.channel.Channel;
7 | import org.jboss.netty.channel.ChannelFactory;
8 | import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
9 |
10 | import java.io.IOException;
11 | import java.net.InetSocketAddress;
12 | import java.util.concurrent.Executors;
13 |
14 | public class NettyServer implements Server {
15 | private final int port;
16 | private Channel channel;
17 |
18 | public NettyServer(int port) {
19 | this.port = port;
20 | }
21 |
22 | @Override
23 | public void listen(DNode dnode) throws IOException {
24 | ChannelFactory factory = new NioServerSocketChannelFactory(
25 | Executors.newCachedThreadPool(),
26 | Executors.newCachedThreadPool());
27 |
28 | ServerBootstrap bootstrap = new ServerBootstrap(factory);
29 | bootstrap.setPipelineFactory(new DNodePipelineFactory(dnode));
30 | channel = bootstrap.bind(new InetSocketAddress(port));
31 | }
32 |
33 | @Override
34 | public void shutdown() throws IOException {
35 | if(channel != null) {
36 | channel.close();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/dnode/socketio/SocketIOCodec.java:
--------------------------------------------------------------------------------
1 | package dnode.socketio;
2 |
3 | import com.google.gson.JsonElement;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 |
9 | public class SocketIOCodec {
10 | private static final String FRAME = "~m~";
11 |
12 | public String encode(String message) {
13 | return encode(Collections.singletonList(message));
14 | }
15 |
16 | public String encode(List messages) {
17 | StringBuilder sb = new StringBuilder();
18 | for (Object message : messages) {
19 | String m = stringify(message);
20 | sb.append(FRAME).append(m.length()).append(FRAME).append(m);
21 | }
22 | return sb.toString();
23 | }
24 |
25 | private String stringify(Object message) {
26 | if (message instanceof JsonElement) {
27 | return "~j~" + message.toString();
28 | } else {
29 | return String.valueOf(message);
30 | }
31 | }
32 |
33 | public List decode(String data) {
34 | List messages = new ArrayList();
35 | do {
36 | String number = "";
37 | if (!data.substring(0, 3).equals(FRAME)) return messages;
38 | data = data.substring(3);
39 | for (int i = 0, l = data.length(); i < l; i++) {
40 | try {
41 | String sub = data.substring(i, i + 1);
42 | Integer.parseInt(sub);
43 | number += data.substring(i, i + 1);
44 | } catch (NumberFormatException e) {
45 | data = data.substring(number.length() + FRAME.length());
46 | break;
47 | }
48 | }
49 | int l = Integer.parseInt(number);
50 | messages.add(data.substring(0, l));
51 | data = data.substring(l);
52 | } while (!data.equals(""));
53 | return messages;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/dnode/socketio/SocketIOConnection.java:
--------------------------------------------------------------------------------
1 | package dnode.socketio;
2 |
3 | import webbit.HttpRequest;
4 | import webbit.WebSocketConnection;
5 |
6 | import java.util.Map;
7 | import java.util.Set;
8 | import java.util.concurrent.Executor;
9 |
10 | class SocketIOConnection implements WebSocketConnection {
11 | private final WebSocketConnection connection;
12 | private final SocketIOCodec codec;
13 |
14 | public SocketIOConnection(WebSocketConnection connection, SocketIOCodec codec) {
15 | this.connection = connection;
16 | this.codec = codec;
17 | String id = String.valueOf(System.currentTimeMillis());
18 | connection.send(codec.encode(id));
19 | }
20 |
21 | @Override
22 | public HttpRequest httpRequest() {
23 | return connection.httpRequest();
24 | }
25 |
26 | @Override
27 | public WebSocketConnection send(String message) {
28 | String encodedMessage = codec.encode(message);
29 | connection.send(encodedMessage);
30 | return this;
31 | }
32 |
33 | @Override
34 | public WebSocketConnection close() {
35 | connection.close();
36 | return this;
37 | }
38 |
39 | @Override
40 | public Map data() {
41 | return connection.data();
42 | }
43 |
44 | @Override
45 | public Object data(String key) {
46 | return connection.data(key);
47 | }
48 |
49 | @Override
50 | public WebSocketConnection data(String key, Object value) {
51 | return connection.data(key, value);
52 | }
53 |
54 | @Override
55 | public Set dataKeys() {
56 | return connection.dataKeys();
57 | }
58 |
59 | @Override
60 | public Executor handlerExecutor() {
61 | return connection.handlerExecutor();
62 | }
63 |
64 | @Override
65 | public void execute(Runnable runnable) {
66 | connection.execute(runnable);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/dnode/socketio/SocketIOListener.java:
--------------------------------------------------------------------------------
1 | package dnode.socketio;
2 |
3 | import com.google.gson.JsonElement;
4 |
5 | public interface SocketIOListener {
6 | void onClientMessage(JsonElement json, SocketIOWebSocketHandler socketIOWebSocketHandler);
7 |
8 | void onClientMessage(String message, SocketIOWebSocketHandler socketIOWebSocketHandler);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/dnode/socketio/SocketIOWebSocketHandler.java:
--------------------------------------------------------------------------------
1 | package dnode.socketio;
2 |
3 | import webbit.WebSocketConnection;
4 | import webbit.WebSocketHandler;
5 |
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | /**
11 | * Handler that wraps/unwraps messages sent with a SocketIO client.
12 | */
13 | public class SocketIOWebSocketHandler implements WebSocketHandler {
14 | private static final SocketIOCodec codec = new SocketIOCodec();
15 | private final WebSocketHandler handler;
16 | private Map socketIOConnections = new HashMap();
17 |
18 | public SocketIOWebSocketHandler(WebSocketHandler handler) {
19 | this.handler = handler;
20 | }
21 |
22 | @Override
23 | public void onOpen(WebSocketConnection connection) throws Exception {
24 | SocketIOConnection socketIOConnection = new SocketIOConnection(connection, codec);
25 | socketIOConnections.put(connection, socketIOConnection);
26 | handler.onOpen(socketIOConnection);
27 | }
28 |
29 | @Override
30 | public void onMessage(WebSocketConnection connection, String msg) throws Exception {
31 | List messages = codec.decode(msg);
32 | for (String message : messages) {
33 | String frame = message.substring(0, 3);
34 | if (frame.equals("~j~")) {
35 | // Heartbeat
36 | return;
37 | } else if (frame.equals("~j~")) {
38 | // TODO: Should we parse into JSON here? We also seem to get JSON that is *not* prefixed with ~j~ (??)
39 | message = message.substring(3);
40 | }
41 | handler.onMessage(socketIOConnections.get(connection), message);
42 | }
43 | }
44 |
45 | @Override
46 | public void onClose(WebSocketConnection connection) throws Exception {
47 | handler.onClose(socketIOConnections.remove(connection));
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/dnode/webbit/DNodeWebSocketHandler.java:
--------------------------------------------------------------------------------
1 | package dnode.webbit;
2 |
3 | import dnode.DNode;
4 | import webbit.WebSocketConnection;
5 | import webbit.WebSocketHandler;
6 |
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class DNodeWebSocketHandler implements WebSocketHandler {
11 | private final DNode dnode;
12 |
13 | private final Map connections = new HashMap();
14 |
15 | public DNodeWebSocketHandler(DNode dnode) {
16 | this.dnode = dnode;
17 | }
18 |
19 | public void onOpen(WebSocketConnection connection) throws Exception {
20 | WebbitConnection c = getFor(connection);
21 | dnode.onOpen(c);
22 | }
23 |
24 | public void onMessage(WebSocketConnection connection, String msg) throws Exception {
25 | WebbitConnection c = getFor(connection);
26 | dnode.onMessage(c, msg);
27 | }
28 |
29 | public void onClose(WebSocketConnection connection) throws Exception {
30 | connections.remove(connection);
31 | }
32 |
33 | private WebbitConnection getFor(WebSocketConnection connection) {
34 | WebbitConnection wc = connections.get(connection);
35 | if (wc == null) {
36 | wc = new WebbitConnection(connection);
37 | connections.put(connection, wc);
38 | }
39 | return wc;
40 | }
41 | }
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/java/dnode/webbit/WebbitConnection.java:
--------------------------------------------------------------------------------
1 | package dnode.webbit;
2 |
3 | import com.google.gson.JsonElement;
4 | import dnode.Connection;
5 | import webbit.WebSocketConnection;
6 |
7 | public class WebbitConnection implements Connection {
8 | private final WebSocketConnection webSocketConnection;
9 |
10 | public WebbitConnection(WebSocketConnection webSocketConnection) {
11 | if (webSocketConnection == null) {
12 | throw new NullPointerException("Where is the connection?");
13 | }
14 | this.webSocketConnection = webSocketConnection;
15 | }
16 |
17 | @Override
18 | public void write(JsonElement data) {
19 | webSocketConnection.send(data.toString() + "\n");
20 | }
21 |
22 | @Override
23 | public void close() {
24 | webSocketConnection.close();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/dnode/webbit/WebbitServer.java:
--------------------------------------------------------------------------------
1 | package dnode.webbit;
2 |
3 | import dnode.DNode;
4 | import dnode.Server;
5 | import dnode.socketio.SocketIOWebSocketHandler;
6 | import webbit.WebServer;
7 |
8 | import java.io.IOException;
9 |
10 | public class WebbitServer implements Server {
11 | private final WebServer server;
12 |
13 | public WebbitServer(WebServer server) {
14 | this.server = server;
15 | }
16 |
17 | public void listen(DNode dnode) throws IOException {
18 | server.add("/socket.io/websocket", new SocketIOWebSocketHandler(new DNodeWebSocketHandler(dnode)));
19 | }
20 |
21 | public void shutdown() throws IOException {
22 | server.stop();
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/test/java/dnode/DNodeObjectTest.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | public class DNodeObjectTest {
8 | public static class Cat {
9 | public void say(Callback callback) {
10 |
11 | }
12 |
13 | public void meow(Callback callback) {
14 |
15 | }
16 | }
17 |
18 | @Test
19 | public void shouldReportSignature() {
20 | DNodeObject dcat = new DNodeObject(new Cat());
21 | assertEquals("{\"say\":\"[Function]\",\"meow\":\"[Function]\"}", dcat.getSignature().toString());
22 | }
23 |
24 | @Test
25 | public void shouldReportCallbacks() {
26 | DNodeObject dcat = new DNodeObject(new Cat());
27 | assertEquals("{\"0\":[\"0\",\"say\"],\"1\":[\"0\",\"meow\"]}", dcat.getCallbacks().toString());
28 | }
29 | }
--------------------------------------------------------------------------------
/src/test/java/dnode/DNodeTest.java:
--------------------------------------------------------------------------------
1 | package dnode;
2 |
3 | import dnode.netty.NettyServer;
4 | import junit.framework.AssertionFailedError;
5 | import org.junit.After;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 | import java.io.InputStreamReader;
10 | import java.io.Reader;
11 |
12 | import static org.junit.Assert.assertEquals;
13 |
14 | public class DNodeTest {
15 | private DNode dNode;
16 | private final Server server = new NettyServer(6060);
17 |
18 | public class Mooer {
19 | private final int moo;
20 | public DNode dNode;
21 |
22 | public Mooer(int moo) {
23 | this.moo = moo;
24 | }
25 |
26 | public void moo(Callback cb) throws IOException {
27 | cb.call(moo);
28 | dNode.closeAllConnections();
29 | server.shutdown();
30 | }
31 |
32 | public void boo(Callback cb) throws IOException {
33 | cb.call(moo * 10);
34 | dNode.closeAllConnections();
35 | server.shutdown();
36 | }
37 | }
38 |
39 | @After
40 | public void shutdownServer() throws IOException {
41 | server.shutdown();
42 | }
43 |
44 | @Test
45 | public void shouldTalk() throws IOException, InterruptedException {
46 | createDnode(100);
47 | dNode.listen(server);
48 | assertEquals("100\n", runClient("moo"));
49 | }
50 |
51 | @Test
52 | public void shouldUseDataInInstance() throws IOException, InterruptedException {
53 | createDnode(200);
54 | dNode.listen(server);
55 | assertEquals("200\n", runClient("moo"));
56 | }
57 |
58 | @Test
59 | public void shouldCallRightMethod() throws IOException, InterruptedException {
60 | createDnode(300);
61 | dNode.listen(server);
62 | assertEquals("3000\n", runClient("boo"));
63 | }
64 |
65 | public static interface SomeClient {
66 | void hello();
67 | }
68 |
69 | @Test
70 | public void shouldBeAbleToCallClient() {
71 | Mooer mooer = new Mooer(345);
72 | dNode = new DNode(mooer, new ClientHandler() {
73 | @Override
74 | public void onConnect(SomeClient client) {
75 | System.out.println("client = " + client);
76 | client.hello();
77 | }
78 | });
79 | }
80 |
81 |
82 | private void createDnode(int moo) {
83 | Mooer instance = new Mooer(moo);
84 | dNode = new DNode(instance);
85 | instance.dNode = dNode;
86 | }
87 |
88 | private String runClient(String method) throws IOException, InterruptedException {
89 | String node = System.getProperty("node", "/usr/local/bin/node");
90 | String clientScript = System.getProperty("client", "client.js");
91 | ProcessBuilder pb = new ProcessBuilder(node, clientScript, method);
92 | pb.redirectErrorStream(true);
93 | Process client = pb.start();
94 |
95 | Reader clientStdOut = new InputStreamReader(client.getInputStream(), "UTF-8");
96 | StringBuilder result = new StringBuilder();
97 | int c;
98 | while ((c = clientStdOut.read()) != -1) {
99 | result.append((char) c);
100 | }
101 | int exit = client.waitFor();
102 | if (exit != 0)
103 | throw new AssertionFailedError("Exit value from external process was " + exit +
104 | " (with stdout/stderr: " + result + ")");
105 | return result.toString();
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/dnode/socketio/SocketIOCodecTest.java:
--------------------------------------------------------------------------------
1 | package dnode.socketio;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 | import java.util.List;
7 |
8 | import static org.junit.Assert.assertEquals;
9 |
10 | public class SocketIOCodecTest {
11 | private final SocketIOCodec codec = new SocketIOCodec();
12 |
13 | @Test
14 | public void shouldEncodeOneElement() {
15 | assertEncoding(Arrays.asList("Hello"));
16 | }
17 |
18 | @Test
19 | public void shouldEncodeTwoElements() {
20 | assertEncoding(Arrays.asList("Hello", "World"));
21 | }
22 |
23 | private void assertEncoding(List m) {
24 | String encoded = codec.encode(m);
25 | assertEquals(m, codec.decode(encoded));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/dnode/webbit/DNodeExample.java:
--------------------------------------------------------------------------------
1 | package dnode.webbit;
2 |
3 | import dnode.Callback;
4 | import dnode.ClientHandler;
5 | import dnode.DNode;
6 | import webbit.WebServer;
7 | import webbit.handler.EmbeddedResourceHandler;
8 | import webbit.netty.NettyWebServer;
9 |
10 | import java.io.IOException;
11 |
12 | import static java.util.concurrent.Executors.newFixedThreadPool;
13 |
14 | public class DNodeExample {
15 | public static class Cat {
16 | public void howAreYou(Callback cb) {
17 | cb.call("I am fine");
18 | }
19 | }
20 |
21 | public interface MyClient {
22 | void greet(String what);
23 | }
24 |
25 | public static void main(String[] args) throws IOException {
26 | WebServer server = new NettyWebServer(6061);
27 | new DNode(new Cat(), new ClientHandler() {
28 | @Override
29 | public void onConnect(MyClient client) {
30 | client.greet("How are you?");
31 | }
32 | }).listen(new WebbitServer(server));
33 | server.add("/.*", new EmbeddedResourceHandler("dnode/js", newFixedThreadPool(4)));
34 | server.start();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/dnode/webbit/WebbitIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package dnode.webbit;
2 |
3 | import com.gargoylesoftware.htmlunit.AlertHandler;
4 | import com.gargoylesoftware.htmlunit.BrowserVersion;
5 | import com.gargoylesoftware.htmlunit.Page;
6 | import com.gargoylesoftware.htmlunit.WebClient;
7 | import com.gargoylesoftware.htmlunit.html.HtmlPage;
8 | import dnode.Callback;
9 | import dnode.DNode;
10 | import org.junit.Ignore;
11 | import org.junit.Test;
12 | import webbit.WebServer;
13 | import webbit.handler.EmbeddedResourceHandler;
14 | import webbit.netty.NettyWebServer;
15 |
16 | import java.io.IOException;
17 |
18 | import static java.lang.Thread.sleep;
19 | import static java.util.concurrent.Executors.newFixedThreadPool;
20 |
21 | public class WebbitIntegrationTest {
22 | public static class Cat {
23 | public void cat(Callback cb) {
24 | System.out.println("cb = " + cb);
25 | cb.call("GROWL");
26 | }
27 | }
28 |
29 | @Test
30 | @Ignore
31 | public void should_work_with_browser() throws IOException, InterruptedException {
32 | WebServer server = new NettyWebServer(6061);
33 | new DNode(new Cat()).listen(new WebbitServer(server));
34 | server.add("/.*", new EmbeddedResourceHandler("dnode/js", newFixedThreadPool(4)));
35 | server.start();
36 |
37 | WebClient client = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
38 | client.setAlertHandler(new AlertHandler() {
39 | @Override
40 | public void handleAlert(Page page, String message) {
41 | System.out.println("alert = " + message);
42 | }
43 | });
44 | HtmlPage page = client.getPage("http://localhost:6061/");
45 |
46 | sleep(5000);
47 | // Expected to see GROWL in stdout at least, but not happening...
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/resources/dnode/js/dnode.js:
--------------------------------------------------------------------------------
1 | /** Socket.IO 0.6.1 - Built with build.js */
2 | /**
3 | * Socket.IO client
4 | *
5 | * @author Guillermo Rauch
6 | * @license The MIT license.
7 | * @copyright Copyright (c) 2010 LearnBoost
8 | */
9 |
10 | this.io = {
11 | version: '0.6.1',
12 |
13 | setPath: function(path){
14 | if (window.console && console.error) console.error('io.setPath will be removed. Please set the variable WEB_SOCKET_SWF_LOCATION pointing to WebSocketMain.swf');
15 | this.path = /\/$/.test(path) ? path : path + '/';
16 | WEB_SOCKET_SWF_LOCATION = path + 'lib/vendor/web-socket-js/WebSocketMain.swf';
17 | }
18 | };
19 |
20 | if ('jQuery' in this) jQuery.io = this.io;
21 |
22 | if (typeof window != 'undefined'){
23 | // WEB_SOCKET_SWF_LOCATION = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//cdn.socket.io/' + this.io.version + '/WebSocketMain.swf';
24 | if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined')
25 | WEB_SOCKET_SWF_LOCATION = '/socket.io/lib/vendor/web-socket-js/WebSocketMain.swf';
26 | }
27 |
28 | /**
29 | * Socket.IO client
30 | *
31 | * @author Guillermo Rauch
32 | * @license The MIT license.
33 | * @copyright Copyright (c) 2010 LearnBoost
34 | */
35 |
36 | (function(){
37 |
38 | var _pageLoaded = false;
39 |
40 | io.util = {
41 |
42 | ios: false,
43 |
44 | load: function(fn){
45 | if (/loaded|complete/.test(document.readyState) || _pageLoaded) return fn();
46 | if ('attachEvent' in window){
47 | window.attachEvent('onload', fn);
48 | } else {
49 | window.addEventListener('load', fn, false);
50 | }
51 | },
52 |
53 | inherit: function(ctor, superCtor){
54 | // no support for `instanceof` for now
55 | for (var i in superCtor.prototype){
56 | ctor.prototype[i] = superCtor.prototype[i];
57 | }
58 | },
59 |
60 | indexOf: function(arr, item, from){
61 | for (var l = arr.length, i = (from < 0) ? Math.max(0, l + from) : from || 0; i < l; i++){
62 | if (arr[i] === item) return i;
63 | }
64 | return -1;
65 | },
66 |
67 | isArray: function(obj){
68 | return Object.prototype.toString.call(obj) === '[object Array]';
69 | },
70 |
71 | merge: function(target, additional){
72 | for (var i in additional)
73 | if (additional.hasOwnProperty(i))
74 | target[i] = additional[i];
75 | }
76 |
77 | };
78 |
79 | io.util.ios = /iphone|ipad/i.test(navigator.userAgent);
80 | io.util.android = /android/i.test(navigator.userAgent);
81 | io.util.opera = /opera/i.test(navigator.userAgent);
82 |
83 | io.util.load(function(){
84 | _pageLoaded = true;
85 | });
86 |
87 | })();
88 |
89 | /**
90 | * Socket.IO client
91 | *
92 | * @author Guillermo Rauch
93 | * @license The MIT license.
94 | * @copyright Copyright (c) 2010 LearnBoost
95 | */
96 |
97 | // abstract
98 |
99 | (function(){
100 |
101 | var frame = '~m~',
102 |
103 | stringify = function(message){
104 | if (Object.prototype.toString.call(message) == '[object Object]'){
105 | if (!('JSON' in window)){
106 | if ('console' in window && console.error) console.error('Trying to encode as JSON, but JSON.stringify is missing.');
107 | return '{ "$error": "Invalid message" }';
108 | }
109 | return '~j~' + JSON.stringify(message);
110 | } else {
111 | return String(message);
112 | }
113 | };
114 |
115 | Transport = io.Transport = function(base, options){
116 | this.base = base;
117 | this.options = {
118 | timeout: 15000 // based on heartbeat interval default
119 | };
120 | io.util.merge(this.options, options);
121 | };
122 |
123 | Transport.prototype.send = function(){
124 | throw new Error('Missing send() implementation');
125 | };
126 |
127 | Transport.prototype.connect = function(){
128 | throw new Error('Missing connect() implementation');
129 | };
130 |
131 | Transport.prototype.disconnect = function(){
132 | throw new Error('Missing disconnect() implementation');
133 | };
134 |
135 | Transport.prototype._encode = function(messages){
136 | var ret = '', message,
137 | messages = io.util.isArray(messages) ? messages : [messages];
138 | for (var i = 0, l = messages.length; i < l; i++){
139 | message = messages[i] === null || messages[i] === undefined ? '' : stringify(messages[i]);
140 | ret += frame + message.length + frame + message;
141 | }
142 | return ret;
143 | };
144 |
145 | Transport.prototype._decode = function(data){
146 | var messages = [], number, n;
147 | do {
148 | if (data.substr(0, 3) !== frame) return messages;
149 | data = data.substr(3);
150 | number = '', n = '';
151 | for (var i = 0, l = data.length; i < l; i++){
152 | n = Number(data.substr(i, 1));
153 | if (data.substr(i, 1) == n){
154 | number += n;
155 | } else {
156 | data = data.substr(number.length + frame.length);
157 | number = Number(number);
158 | break;
159 | }
160 | }
161 | messages.push(data.substr(0, number)); // here
162 | data = data.substr(number);
163 | } while(data !== '');
164 | return messages;
165 | };
166 |
167 | Transport.prototype._onData = function(data){
168 | this._setTimeout();
169 | var msgs = this._decode(data);
170 | if (msgs && msgs.length){
171 | for (var i = 0, l = msgs.length; i < l; i++){
172 | this._onMessage(msgs[i]);
173 | }
174 | }
175 | };
176 |
177 | Transport.prototype._setTimeout = function(){
178 | var self = this;
179 | if (this._timeout) clearTimeout(this._timeout);
180 | this._timeout = setTimeout(function(){
181 | self._onTimeout();
182 | }, this.options.timeout);
183 | };
184 |
185 | Transport.prototype._onTimeout = function(){
186 | this._onDisconnect();
187 | };
188 |
189 | Transport.prototype._onMessage = function(message){
190 | if (!this.sessionid){
191 | this.sessionid = message;
192 | this._onConnect();
193 | } else if (message.substr(0, 3) == '~h~'){
194 | this._onHeartbeat(message.substr(3));
195 | } else if (message.substr(0, 3) == '~j~'){
196 | this.base._onMessage(JSON.parse(message.substr(3)));
197 | } else {
198 | this.base._onMessage(message);
199 | }
200 | },
201 |
202 | Transport.prototype._onHeartbeat = function(heartbeat){
203 | this.send('~h~' + heartbeat); // echo
204 | };
205 |
206 | Transport.prototype._onConnect = function(){
207 | this.connected = true;
208 | this.connecting = false;
209 | this.base._onConnect();
210 | this._setTimeout();
211 | };
212 |
213 | Transport.prototype._onDisconnect = function(){
214 | this.connecting = false;
215 | this.connected = false;
216 | this.sessionid = null;
217 | this.base._onDisconnect();
218 | };
219 |
220 | Transport.prototype._prepareUrl = function(){
221 | return (this.base.options.secure ? 'https' : 'http')
222 | + '://' + this.base.host
223 | + ':' + this.base.options.port
224 | + '/' + this.base.options.resource
225 | + '/' + this.type
226 | + (this.sessionid ? ('/' + this.sessionid) : '/');
227 | };
228 |
229 | })();
230 | /**
231 | * Socket.IO client
232 | *
233 | * @author Guillermo Rauch
234 | * @license The MIT license.
235 | * @copyright Copyright (c) 2010 LearnBoost
236 | */
237 |
238 | (function(){
239 |
240 | var empty = new Function,
241 |
242 | XMLHttpRequestCORS = (function(){
243 | if (!('XMLHttpRequest' in window)) return false;
244 | // CORS feature detection
245 | var a = new XMLHttpRequest();
246 | return a.withCredentials != undefined;
247 | })(),
248 |
249 | request = function(xdomain){
250 | if ('XDomainRequest' in window && xdomain) return new XDomainRequest();
251 | if ('XMLHttpRequest' in window && (!xdomain || XMLHttpRequestCORS)) return new XMLHttpRequest();
252 | if (!xdomain){
253 | try {
254 | var a = new ActiveXObject('MSXML2.XMLHTTP');
255 | return a;
256 | } catch(e){}
257 |
258 | try {
259 | var b = new ActiveXObject('Microsoft.XMLHTTP');
260 | return b;
261 | } catch(e){}
262 | }
263 | return false;
264 | },
265 |
266 | XHR = io.Transport.XHR = function(){
267 | io.Transport.apply(this, arguments);
268 | this._sendBuffer = [];
269 | };
270 |
271 | io.util.inherit(XHR, io.Transport);
272 |
273 | XHR.prototype.connect = function(){
274 | this._get();
275 | return this;
276 | };
277 |
278 | XHR.prototype._checkSend = function(){
279 | if (!this._posting && this._sendBuffer.length){
280 | var encoded = this._encode(this._sendBuffer);
281 | this._sendBuffer = [];
282 | this._send(encoded);
283 | }
284 | };
285 |
286 | XHR.prototype.send = function(data){
287 | if (io.util.isArray(data)){
288 | this._sendBuffer.push.apply(this._sendBuffer, data);
289 | } else {
290 | this._sendBuffer.push(data);
291 | }
292 | this._checkSend();
293 | return this;
294 | };
295 |
296 | XHR.prototype._send = function(data){
297 | var self = this;
298 | this._posting = true;
299 | this._sendXhr = this._request('send', 'POST');
300 | this._sendXhr.onreadystatechange = function(){
301 | var status;
302 | if (self._sendXhr.readyState == 4){
303 | self._sendXhr.onreadystatechange = empty;
304 | try { status = self._sendXhr.status; } catch(e){}
305 | self._posting = false;
306 | if (status == 200){
307 | self._checkSend();
308 | } else {
309 | self._onDisconnect();
310 | }
311 | }
312 | };
313 | this._sendXhr.send('data=' + encodeURIComponent(data));
314 | };
315 |
316 | XHR.prototype.disconnect = function(){
317 | // send disconnection signal
318 | this._onDisconnect();
319 | return this;
320 | };
321 |
322 | XHR.prototype._onDisconnect = function(){
323 | if (this._xhr){
324 | this._xhr.onreadystatechange = empty;
325 | try {
326 | this._xhr.abort();
327 | } catch(e){}
328 | this._xhr = null;
329 | }
330 | if (this._sendXhr){
331 | this._sendXhr.onreadystatechange = empty;
332 | try {
333 | this._sendXhr.abort();
334 | } catch(e){}
335 | this._sendXhr = null;
336 | }
337 | this._sendBuffer = [];
338 | io.Transport.prototype._onDisconnect.call(this);
339 | };
340 |
341 | XHR.prototype._request = function(url, method, multipart){
342 | var req = request(this.base._isXDomain());
343 | if (multipart) req.multipart = true;
344 | req.open(method || 'GET', this._prepareUrl() + (url ? '/' + url : ''));
345 | if (method == 'POST' && 'setRequestHeader' in req){
346 | req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
347 | }
348 | return req;
349 | };
350 |
351 | XHR.check = function(xdomain){
352 | try {
353 | if (request(xdomain)) return true;
354 | } catch(e){}
355 | return false;
356 | };
357 |
358 | XHR.xdomainCheck = function(){
359 | return XHR.check(true);
360 | };
361 |
362 | XHR.request = request;
363 |
364 | })();
365 |
366 | /**
367 | * Socket.IO client
368 | *
369 | * @author Guillermo Rauch
370 | * @license The MIT license.
371 | * @copyright Copyright (c) 2010 LearnBoost
372 | */
373 |
374 | (function(){
375 |
376 | var WS = io.Transport.websocket = function(){
377 | io.Transport.apply(this, arguments);
378 | };
379 |
380 | io.util.inherit(WS, io.Transport);
381 |
382 | WS.prototype.type = 'websocket';
383 |
384 | WS.prototype.connect = function(){
385 | var self = this;
386 | this.socket = new WebSocket(this._prepareUrl());
387 | this.socket.onmessage = function(ev){ self._onData(ev.data); };
388 | this.socket.onclose = function(ev){ self._onClose(); };
389 | this.socket.onerror = function(e){ self._onError(e); };
390 | return this;
391 | };
392 |
393 | WS.prototype.send = function(data){
394 | if (this.socket) this.socket.send(this._encode(data));
395 | return this;
396 | };
397 |
398 | WS.prototype.disconnect = function(){
399 | if (this.socket) this.socket.close();
400 | return this;
401 | };
402 |
403 | WS.prototype._onClose = function(){
404 | this._onDisconnect();
405 | return this;
406 | };
407 |
408 | WS.prototype._onError = function(e){
409 | this.base.emit('error', [e]);
410 | };
411 |
412 | WS.prototype._prepareUrl = function(){
413 | return (this.base.options.secure ? 'wss' : 'ws')
414 | + '://' + this.base.host
415 | + ':' + this.base.options.port
416 | + '/' + this.base.options.resource
417 | + '/' + this.type
418 | + (this.sessionid ? ('/' + this.sessionid) : '');
419 | };
420 |
421 | WS.check = function(){
422 | // we make sure WebSocket is not confounded with a previously loaded flash WebSocket
423 | return 'WebSocket' in window && WebSocket.prototype && ( WebSocket.prototype.send && !!WebSocket.prototype.send.toString().match(/native/i)) && typeof WebSocket !== "undefined";
424 | };
425 |
426 | WS.xdomainCheck = function(){
427 | return true;
428 | };
429 |
430 | })();
431 |
432 | /**
433 | * Socket.IO client
434 | *
435 | * @author Guillermo Rauch
436 | * @license The MIT license.
437 | * @copyright Copyright (c) 2010 LearnBoost
438 | */
439 |
440 | (function(){
441 |
442 | var Flashsocket = io.Transport.flashsocket = function(){
443 | io.Transport.websocket.apply(this, arguments);
444 | };
445 |
446 | io.util.inherit(Flashsocket, io.Transport.websocket);
447 |
448 | Flashsocket.prototype.type = 'flashsocket';
449 |
450 | Flashsocket.prototype.connect = function(){
451 | var self = this, args = arguments;
452 | WebSocket.__addTask(function(){
453 | io.Transport.websocket.prototype.connect.apply(self, args);
454 | });
455 | return this;
456 | };
457 |
458 | Flashsocket.prototype.send = function(){
459 | var self = this, args = arguments;
460 | WebSocket.__addTask(function(){
461 | io.Transport.websocket.prototype.send.apply(self, args);
462 | });
463 | return this;
464 | };
465 |
466 | Flashsocket.check = function(){
467 | if (typeof WebSocket == 'undefined' || !('__addTask' in WebSocket)) return false;
468 | if (io.util.opera) return false; // opera is buggy with this transport
469 | if ('navigator' in window && 'plugins' in navigator && navigator.plugins['Shockwave Flash']){
470 | return !!navigator.plugins['Shockwave Flash'].description;
471 | }
472 | if ('ActiveXObject' in window) {
473 | try {
474 | return !!new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
475 | } catch (e) {}
476 | }
477 | return false;
478 | };
479 |
480 | Flashsocket.xdomainCheck = function(){
481 | return true;
482 | };
483 |
484 | })();
485 | /**
486 | * Socket.IO client
487 | *
488 | * @author Guillermo Rauch
489 | * @license The MIT license.
490 | * @copyright Copyright (c) 2010 LearnBoost
491 | */
492 |
493 | (function(){
494 |
495 | var HTMLFile = io.Transport.htmlfile = function(){
496 | io.Transport.XHR.apply(this, arguments);
497 | };
498 |
499 | io.util.inherit(HTMLFile, io.Transport.XHR);
500 |
501 | HTMLFile.prototype.type = 'htmlfile';
502 |
503 | HTMLFile.prototype._get = function(){
504 | var self = this;
505 | this._open();
506 | window.attachEvent('onunload', function(){ self._destroy(); });
507 | };
508 |
509 | HTMLFile.prototype._open = function(){
510 | this._doc = new ActiveXObject('htmlfile');
511 | this._doc.open();
512 | this._doc.write('');
513 | this._doc.parentWindow.s = this;
514 | this._doc.close();
515 |
516 | var _iframeC = this._doc.createElement('div');
517 | this._doc.body.appendChild(_iframeC);
518 | this._iframe = this._doc.createElement('iframe');
519 | _iframeC.appendChild(this._iframe);
520 | this._iframe.src = this._prepareUrl() + '/' + (+ new Date);
521 | };
522 |
523 | HTMLFile.prototype._ = function(data, doc){
524 | this._onData(data);
525 | var script = doc.getElementsByTagName('script')[0];
526 | script.parentNode.removeChild(script);
527 | };
528 |
529 | HTMLFile.prototype._destroy = function(){
530 | if (this._iframe){
531 | this._iframe.src = 'about:blank';
532 | this._doc = null;
533 | CollectGarbage();
534 | }
535 | };
536 |
537 | HTMLFile.prototype.disconnect = function(){
538 | this._destroy();
539 | return io.Transport.XHR.prototype.disconnect.call(this);
540 | };
541 |
542 | HTMLFile.check = function(){
543 | if ('ActiveXObject' in window){
544 | try {
545 | var a = new ActiveXObject('htmlfile');
546 | return a && io.Transport.XHR.check();
547 | } catch(e){}
548 | }
549 | return false;
550 | };
551 |
552 | HTMLFile.xdomainCheck = function(){
553 | // we can probably do handling for sub-domains, we should test that it's cross domain but a subdomain here
554 | return false;
555 | };
556 |
557 | })();
558 | /**
559 | * Socket.IO client
560 | *
561 | * @author Guillermo Rauch
562 | * @license The MIT license.
563 | * @copyright Copyright (c) 2010 LearnBoost
564 | */
565 |
566 | (function(){
567 |
568 | var XHRMultipart = io.Transport['xhr-multipart'] = function(){
569 | io.Transport.XHR.apply(this, arguments);
570 | };
571 |
572 | io.util.inherit(XHRMultipart, io.Transport.XHR);
573 |
574 | XHRMultipart.prototype.type = 'xhr-multipart';
575 |
576 | XHRMultipart.prototype._get = function(){
577 | var self = this;
578 | this._xhr = this._request('', 'GET', true);
579 | this._xhr.onreadystatechange = function(){
580 | if (self._xhr.readyState == 3) self._onData(self._xhr.responseText);
581 | };
582 | this._xhr.send(null);
583 | };
584 |
585 | XHRMultipart.check = function(){
586 | return 'XMLHttpRequest' in window && 'prototype' in XMLHttpRequest && 'multipart' in XMLHttpRequest.prototype;
587 | };
588 |
589 | XHRMultipart.xdomainCheck = function(){
590 | return true;
591 | };
592 |
593 | })();
594 |
595 | /**
596 | * Socket.IO client
597 | *
598 | * @author Guillermo Rauch
599 | * @license The MIT license.
600 | * @copyright Copyright (c) 2010 LearnBoost
601 | */
602 |
603 | (function(){
604 |
605 | var empty = new Function(),
606 |
607 | XHRPolling = io.Transport['xhr-polling'] = function(){
608 | io.Transport.XHR.apply(this, arguments);
609 | };
610 |
611 | io.util.inherit(XHRPolling, io.Transport.XHR);
612 |
613 | XHRPolling.prototype.type = 'xhr-polling';
614 |
615 | XHRPolling.prototype.connect = function(){
616 | if (io.util.ios || io.util.android){
617 | var self = this;
618 | io.util.load(function(){
619 | setTimeout(function(){
620 | io.Transport.XHR.prototype.connect.call(self);
621 | }, 10);
622 | });
623 | } else {
624 | io.Transport.XHR.prototype.connect.call(this);
625 | }
626 | };
627 |
628 | XHRPolling.prototype._get = function(){
629 | var self = this;
630 | this._xhr = this._request(+ new Date, 'GET');
631 | this._xhr.onreadystatechange = function(){
632 | var status;
633 | if (self._xhr.readyState == 4){
634 | self._xhr.onreadystatechange = empty;
635 | try { status = self._xhr.status; } catch(e){}
636 | if (status == 200){
637 | self._onData(self._xhr.responseText);
638 | self._get();
639 | } else {
640 | self._onDisconnect();
641 | }
642 | }
643 | };
644 | this._xhr.send(null);
645 | };
646 |
647 | XHRPolling.check = function(){
648 | return io.Transport.XHR.check();
649 | };
650 |
651 | XHRPolling.xdomainCheck = function(){
652 | return io.Transport.XHR.xdomainCheck();
653 | };
654 |
655 | })();
656 |
657 | /**
658 | * Socket.IO client
659 | *
660 | * @author Guillermo Rauch
661 | * @license The MIT license.
662 | * @copyright Copyright (c) 2010 LearnBoost
663 | */
664 |
665 | io.JSONP = [];
666 |
667 | JSONPPolling = io.Transport['jsonp-polling'] = function(){
668 | io.Transport.XHR.apply(this, arguments);
669 | this._insertAt = document.getElementsByTagName('script')[0];
670 | this._index = io.JSONP.length;
671 | io.JSONP.push(this);
672 | };
673 |
674 | io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
675 |
676 | JSONPPolling.prototype.type = 'jsonp-polling';
677 |
678 | JSONPPolling.prototype._send = function(data){
679 | var self = this;
680 | if (!('_form' in this)){
681 | var form = document.createElement('FORM'),
682 | area = document.createElement('TEXTAREA'),
683 | id = this._iframeId = 'socket_io_iframe_' + this._index,
684 | iframe;
685 |
686 | form.style.position = 'absolute';
687 | form.style.top = '-1000px';
688 | form.style.left = '-1000px';
689 | form.target = id;
690 | form.method = 'POST';
691 | form.action = this._prepareUrl() + '/' + (+new Date) + '/' + this._index;
692 | area.name = 'data';
693 | form.appendChild(area);
694 | this._insertAt.parentNode.insertBefore(form, this._insertAt);
695 | document.body.appendChild(form);
696 |
697 | this._form = form;
698 | this._area = area;
699 | }
700 |
701 | function complete(){
702 | initIframe();
703 | self._posting = false;
704 | self._checkSend();
705 | };
706 |
707 | function initIframe(){
708 | if (self._iframe){
709 | self._form.removeChild(self._iframe);
710 | }
711 |
712 | try {
713 | // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
714 | iframe = document.createElement('