FreeWRL/FreeX3D  3.0.0
Browser.java
1 // Specification of the External Interface for a VRML applet browser.
2 // FreeWRL Viewer Interface - bypass netscape and go directly
3 // to the viewer.
4 
5 package vrml.external;
6 
7 import java.util.*;
8 import java.applet.*;
9 //JAS import java.awt.*;
10 import java.net.*;
11 import java.io.*;
12 //JAS import java.lang.reflect.*;
13 import vrml.external.Node;
14 //JAS import vrml.external.field.EventOut;
24 import java.lang.System;
25 //JAS - no longer using Netscape import netscape.security.*;
26 
27 public class Browser implements BrowserInterface, IBrowser
28 
29 {
30 
31  //====================================================================
32  // Threads:
33 
34  // Replies from FreeWRL.
35  static Thread FreeWRLThread; // of type EAIinThread
36 
37  // Send commands to FreeWRL.
38  static EAIoutThread EAIoutSender;
39 
40  // Handle Async communications from FreeWRL (eg, Regisered Listeners)
41  static EAIAsyncThread RL_Async;
42 
43 
44  //====================================================================
45  // Communication Paths:
46 
47  // FreeWRLThread to Browser - responses from commands to FreeWRL.
48  PrintWriter EAIinThreadtoBrowser;
49  PipedWriter EAIinThreadtoBrowserPipe = null;
50 
51  //
52  static BufferedReader BrowserfromEAI = null;
53  PipedReader BrowserfromEAIPipe = null;
54 
55 
56 
57 
58  // The following are used to send to/from the FreeWRL Browser by:
59  // - EAIinThread
60 
61  Socket EAISocket;
62  Socket sock;
63  static PrintWriter EAIout;
64 
65 
66  // The following pipe listens for replies to events sent to
67  // the FreeWRL VRML viewer via the EAI port.
68 
69 
70  private String reply = "";
71 
72 
73  // Query Number as sent to the FreeWRL Browser.
74  static int queryno = 1;
75 
76 
77  // for setDescription/ getDescription
78  private String descript = "";
79 
80  // Sending to FreeWRL needs to synchronize on an object;
81  static Object FreeWRLToken = new Object();
82 
83 
84  // Interface methods.
85  public int get_Browser_EVtype (int event)
86  {
87  //System.out.println ("get_Browser_EVtype is returning " +
88  // BrowserGlobals.EVtype[event] +
89  // " for event " + event);
90  return BrowserGlobals.EVtype[event];
91  }
92 
93  public EventOutObserver get_Browser_EVObserver (int eventno)
94  {
95  // System.out.println ("get_Browser_EVObserver is returning " +
96  // BrowserGlobals.EVObserver[eventno]);
97  return BrowserGlobals.EVObserver[eventno];
98  }
99 
100  public void Browser_RL_Async_send (String EVentreply, int eventno)
101  {
102  int EVcounter;
103  for (EVcounter=0; EVcounter<BrowserGlobals.EVno; EVcounter++) {
104  if (BrowserGlobals.EVarray[EVcounter] == eventno) {
105  break;
106  }
107  }
108  //System.out.println ("Browser_RL_Async_send sending " + EVentreply + " to number " + EVcounter);
109  RL_Async.send(EVentreply, EVcounter);
110  }
111 
112  // Associates this instance with the first embedded plugin in the current frame.
113  public Browser(Applet pApplet, int portnum) {
114  int counter;
115 
116  // Create a socket here for an EAI server on localhost
117  int incrport = -1;
118  EAISocket = null;
119 
120  counter = 1;
121  while (EAISocket == null) {
122  try {
123  EAISocket = new Socket("localhost",portnum);
124  } catch (IOException e) {
125  // wait up to 30 seconds for FreeWRL to answer.
126  counter = counter + 1;
127  if (counter == 60) {
128  System.out.println ("EAI: Java code timed out finding FreeWRL");
129  System.exit(1);
130  }
131  try {Thread.sleep (500);} catch (InterruptedException f) { }
132  }
133  }
134 
135  sock = EAISocket; //JAS - these are the same now...
136 
137 
138 
139  //===================================================================
140  // create the EAIinThread to Browser.
141 
142  // Open the pipe for EAI replies to be sent to us...
143  try {
144  EAIinThreadtoBrowserPipe = new PipedWriter();
145  BrowserfromEAIPipe = new PipedReader(EAIinThreadtoBrowserPipe);
146  } catch (IOException ie) {
147  System.out.println ("EAI: caught error in new PipedReader: " + ie);
148  }
149 
150  EAIinThreadtoBrowser = new PrintWriter(EAIinThreadtoBrowserPipe);
151  BrowserfromEAI = new BufferedReader (BrowserfromEAIPipe);
152 
153  // Start the readfrom FREEWRL thread...
154 
155 
156  //===================================================================
157  // create the EAIinThread to Browser.
158 
159  // Open the pipe for EAI replies to be sent to us...
160  try {
161  EAIinThreadtoBrowserPipe = new PipedWriter();
162  BrowserfromEAIPipe = new PipedReader(EAIinThreadtoBrowserPipe);
163  } catch (IOException ie) {
164  System.out.println ("EAI: caught error in new PipedReader: " + ie);
165  }
166 
167  EAIinThreadtoBrowser = new PrintWriter(EAIinThreadtoBrowserPipe);
168  BrowserfromEAI = new BufferedReader (BrowserfromEAIPipe);
169 
170  // Start the readfrom FREEWRL thread...
171  FreeWRLThread = new Thread ( new EAIinThread(sock, pApplet,
172  EAIinThreadtoBrowser, this));
173  FreeWRLThread.start();
174 
175 
176  //====================================================================
177  // Start the thread that allows Registered Listenered
178  // updates to come in.
179  RL_Async = new EAIAsyncThread();
180  RL_Async.start();
181 
182 
183  //====================================================================
184  // create the EAIoutThread - send data to FreeWRL.
185  try {
186  EAIout = new PrintWriter (sock.getOutputStream());
187  } catch (IOException e) {
188  System.out.print ("EAI: Problem in handshaking with Browser");
189  }
190 
191 
192  // Start the SendTo FREEWRL thread...
193  EAIoutSender = new EAIoutThread(EAIout);
194  EAIoutSender.start();
195 
196 
197 
198  //====================================================================
199  // Browser is "gotten", and is started.
200  return;
201  }
202 
203  // Associates this instance with the first embedded plugin in the current frame.
204  public Browser(Applet pApplet) {
205  int counter;
206 
207  // Create a socket here for an EAI server on localhost
208  int incrport = -1;
209  EAISocket = null;
210 
211  counter = 1;
212  while (EAISocket == null) {
213  try {
214  EAISocket = new Socket("localhost",9877);
215  } catch (IOException e) {
216  // wait up to 30 seconds for FreeWRL to answer.
217  counter = counter + 1;
218  if (counter == 60) {
219  System.out.println ("EAI: Java code timed out finding FreeWRL");
220  System.exit(1);
221  }
222  try {Thread.sleep (500);} catch (InterruptedException f) { }
223  }
224  }
225 
226  sock = EAISocket; //JAS - these are the same now...
227 
228 
229 
230  //===================================================================
231  // create the EAIinThread to Browser.
232 
233  // Open the pipe for EAI replies to be sent to us...
234  try {
235  EAIinThreadtoBrowserPipe = new PipedWriter();
236  BrowserfromEAIPipe = new PipedReader(EAIinThreadtoBrowserPipe);
237  } catch (IOException ie) {
238  System.out.println ("EAI: caught error in new PipedReader: " + ie);
239  }
240 
241  EAIinThreadtoBrowser = new PrintWriter(EAIinThreadtoBrowserPipe);
242  BrowserfromEAI = new BufferedReader (BrowserfromEAIPipe);
243 
244  // Start the readfrom FREEWRL thread...
245  FreeWRLThread = new Thread ( new EAIinThread(sock, pApplet,
246  EAIinThreadtoBrowser, this));
247  FreeWRLThread.start();
248 
249 
250  //====================================================================
251  // Start the thread that allows Registered Listenered
252  // updates to come in.
253  RL_Async = new EAIAsyncThread();
254  RL_Async.start();
255 
256 
257  //====================================================================
258  // create the EAIoutThread - send data to FreeWRL.
259  try {
260  EAIout = new PrintWriter (sock.getOutputStream());
261  } catch (IOException e) {
262  System.out.print ("EAI: Problem in handshaking with Browser");
263  }
264 
265 
266  // Start the SendTo FREEWRL thread...
267  EAIoutSender = new EAIoutThread(EAIout);
268  EAIoutSender.start();
269 
270 
271 
272  //====================================================================
273  // Browser is "gotten", and is started.
274  return;
275  }
276 
277  // construct an instance of the Browser class
278  // If frameName is NULL, current frame is assumed.
279  public Browser(Applet pApplet, String frameName, int index) {
280  System.out.println ("Browser2 Not Implemented");
281 
282  }
283 
284  // Get the browser name
285  public String getName() {
286  String retval;
287  synchronized (FreeWRLToken) {
288  EAIoutSender.send ("" + queryno + "K\n");
289  retval = getVRMLreply(queryno);
290  queryno += 1;
291  }
292  return retval;
293  }
294 
295  public String getVersion() {
296  String retval;
297  synchronized (FreeWRLToken) {
298  EAIoutSender.send ("" + queryno + "L\n");
299  retval = getVRMLreply(queryno);
300  queryno += 1;
301  }
302  return retval;
303  }
304 
305  // Get the current file type; check the specs for correct numbers.
306  public int getEncoding() {
307  String retval;
308  synchronized (FreeWRLToken) {
309  EAIoutSender.send ("" + queryno + "Y\n");
310  retval = getVRMLreply(queryno);
311  queryno += 1;
312  }
313  return Integer.valueOf(retval).intValue();
314  }
315  // Get the current velocity of the bound viewpoint in meters/sec,
316  public float getCurrentSpeed() {
317  String retval;
318  synchronized (FreeWRLToken) {
319  EAIoutSender.send ("" + queryno + "M\n");
320  retval = getVRMLreply(queryno);
321  queryno += 1;
322  }
323  return Float.valueOf(retval).floatValue();
324  }
325 
326  // Get the current frame rate of the browser, or 0.0 if not available
327  public float getCurrentFrameRate() {
328  String retval;
329  synchronized (FreeWRLToken) {
330  EAIoutSender.send ("" + queryno + "N\n");
331  retval = getVRMLreply(queryno);
332  queryno += 1;
333  }
334  return Float.valueOf(retval).floatValue();
335  }
336 
337  // Get the URL for the root of the current world, or an empty string
338  // if not available
339  public String getWorldURL() {
340  String retval;
341  synchronized (FreeWRLToken) {
342  EAIoutSender.send ("" + queryno + "O\n");
343  retval = getVRMLreply(queryno);
344  queryno += 1;
345  }
346  return retval;
347  }
348 
349  // Get rendering properties.
350  public String getRenderingProperties() {
351  String retval;
352  synchronized (FreeWRLToken) {
353  EAIoutSender.send ("" + queryno + "X\n");
354  retval = getVRMLreply(queryno);
355  queryno += 1;
356  }
357  return retval;
358  }
359 
360  // Replace the current world with the passed array of nodes
361  public void replaceWorld(Node[] nodes)
362  throws IllegalArgumentException {
363 
364  String SysString = "";
365  String retval;
366  int count;
367 
368  for (count=0; count<nodes.length; count++) {
369  SysString = SysString + " " + nodes[count].nodeptr;
370  }
371 
372  synchronized (FreeWRLToken) {
373  EAIoutSender.send ("" + queryno + "P" + SysString);
374  retval = getVRMLreply(queryno);
375  queryno += 1;
376  }
377 
378  }
379 
380 
381  // Load the given URL with the passed parameters (as described
382  // in the Anchor node)
383  public void loadURL(String[] url, String[] parameter) {
384  String SysString = "";
385  String retval;
386  int count;
387 
388  // send along sizes of the Strings
389  SysString = "" + url.length + " " + parameter.length;
390 
391  for (count=0; count<url.length; count++) {
392  SysString = SysString + " :loadURLStringBreak:" + url[count];
393  }
394 
395  for (count=0; count<parameter.length; count++) {
396  SysString = SysString + " :loadURLStringBreak:" + parameter[count];
397  }
398 
399  synchronized (FreeWRLToken) {
400  EAIoutSender.send ("" + queryno + "Q" + SysString);
401  retval = getVRMLreply(queryno);
402  queryno += 1;
403  }
404  }
405 
406  // Viewpoint code. Command "R" to FreeWRL, with "FIRST" "NEXT" "PREV" "LAST" in it
407  static void do_vp(String vp) {
408  String retval;
409 
410  synchronized (FreeWRLToken) {
411  EAIoutSender.send ("" + queryno + "R " + vp);
412  retval = getVRMLreply(queryno);
413  queryno += 1;
414  }
415  return;
416  }
417 
418  public void firstViewpoint() {do_vp("FIRST");}
419  public void lastViewpoint() {do_vp("LAST");}
420  public void nextViewpoint() {do_vp("NEXT");}
421  public void previousViewpoint() {do_vp("PREV");}
422 
423 
424 
425  // Set the description of the current world in a browser-specific
426  // manner. To clear the description, pass an empty string as argument
427  // note that FreeWRL does not display descriptions anywhere, so this
428  // command has no freewrl EAI connectivity.
429  public void setDescription(String description) {
430  descript = description;
431  return;
432  }
433 
434  public String getDescription() {
435  return descript;
436  }
437 
438 
439  // Parse STRING into a X3D scene and return the list of root
440  // nodes for the resulting scene
441  public Node[] createX3DFromString(String vrmlSyntax)
442  throws InvalidVrmlException {
443 
444  Node[] x = new Node[100];
445  StringTokenizer tokens;
446  String retval;
447  String temp;
448  int count;
449 
450  synchronized (FreeWRLToken) {
451  EAIoutSender.send ("" +queryno + "o \n"+vrmlSyntax+"\nEOT\n");
452  retval = getVRMLreply(queryno);
453 
454  //System.out.println ("Browser.java - got " + retval);
455 
456  tokens = new StringTokenizer (retval);
457 
458  // We return a (node-index C-pointer) pair, so we have to divide by two
459  x = new Node[tokens.countTokens()];
460  count = 0;
461 
462  // Lets go through the output, and temporarily store it
463  // XXX - is there a better way? ie, using a vector?
464  while (tokens.hasMoreTokens()) {
465  x[count] = new Node();
466  x[count].nodeptr = Integer.parseInt(tokens.nextToken());
467  x[count].offset = 0;
468  x[count].datasize = 4;
469  x[count].datatype = "h"; // see CFuncs/EAIServ.c for a complete desc.
470 
471  //System.out.println ("CVS - for this one, we have NODE" +
472  // " pointer:" + x[count].nodeptr + " offset:" + x[count].offset +
473  // " datasize: " + x[count].datasize + " datatype:" + x[count].datatype);
474 
475  count ++;
476  if (count == 100) {
477  count = 99;
478  System.out.println ("EAI: createX3DFromString - warning, tied to 100 nodes");
479  }
480  }
481  queryno += 1;
482  }
483  return x;
484  }
485  // Parse STRING into a VRML scene and return the list of root
486  // nodes for the resulting scene
487  public Node[] createVrmlFromString(String vrmlSyntax)
488  throws InvalidVrmlException {
489 
490  Node[] x = new Node[100];
491  StringTokenizer tokens;
492  String retval;
493  String temp;
494  int count;
495 
496  synchronized (FreeWRLToken) {
497  EAIoutSender.send ("" +queryno + "S #VRML V2.0 utf8\n"+vrmlSyntax+"\nEOT\n");
498  retval = getVRMLreply(queryno);
499 
500  //System.out.println ("Browser.java - got " + retval);
501 
502  tokens = new StringTokenizer (retval);
503 
504  // We return a (node-index C-pointer) pair, so we have to divide by two
505  x = new Node[tokens.countTokens()];
506  count = 0;
507 
508  // Lets go through the output, and temporarily store it
509  // XXX - is there a better way? ie, using a vector?
510  while (tokens.hasMoreTokens()) {
511  x[count] = new Node();
512  x[count].nodeptr = Integer.parseInt(tokens.nextToken());
513  x[count].offset = 0;
514  x[count].datasize = 4;
515  x[count].datatype = "h"; // see CFuncs/EAIServ.c for a complete desc.
516 
517  //System.out.println ("CVS - for this one, we have NODE" +
518  // " pointer:" + x[count].nodeptr + " offset:" + x[count].offset +
519  // " datasize: " + x[count].datasize + " datatype:" + x[count].datatype);
520 
521  count ++;
522  if (count == 100) {
523  count = 99;
524  System.out.println ("EAI: createVrmlFromString - warning, tied to 100 nodes");
525  }
526  }
527  queryno += 1;
528  }
529  return x;
530  }
531 
532 
533  // for SAI coding
534  public String createNode (String name) {
535  String retval;
536 
537  synchronized (FreeWRLToken) {
538  EAIoutSender.send ("" + queryno + "a" + name + "\n");
539  retval = getVRMLreply(queryno);
540  }
541  return retval;
542  }
543 
544 
545  // for SAI coding
546  public String createProto (String name) {
547  String retval;
548 
549  synchronized (FreeWRLToken) {
550  EAIoutSender.send ("" + queryno + "b" + name + "\n");
551  retval = getVRMLreply(queryno);
552  }
553  return retval;
554  }
555 
556  // for SAI coding
557  public String updateNamedNode (String name, Node node) {
558  String retval;
559 
560  synchronized (FreeWRLToken) {
561  EAIoutSender.send ("" + queryno + "c" + name + " " + node.nodeptr + "\n");
562  retval = getVRMLreply(queryno);
563  }
564  return retval;
565  }
566 
567  // for SAI coding
568  public String removeNamedNode (String name) {
569  String retval;
570 
571  synchronized (FreeWRLToken) {
572  EAIoutSender.send ("" + queryno + "d" + name + "\n");
573  retval = getVRMLreply(queryno);
574  }
575  return retval;
576  }
577 
578 
579  // for SAI coding
580  public String getProtoDeclaration (String name) {
581  String retval;
582 
583  synchronized (FreeWRLToken) {
584  EAIoutSender.send ("" + queryno + "e" + name + "\n");
585  retval = getVRMLreply(queryno);
586  }
587  return retval;
588  }
589 
590  // for SAI coding
591  public String updateProtoDeclaration (String name, String newProtoDecl) {
592  String retval;
593 
594  synchronized (FreeWRLToken) {
595  EAIoutSender.send ("" + queryno + "f" + name + " " + newProtoDecl + "\n");
596  retval = getVRMLreply(queryno);
597  }
598  return retval;
599  }
600 
601  // for SAI coding
602  public String removeProtoDeclaration (String name) {
603  String retval;
604 
605  synchronized (FreeWRLToken) {
606  EAIoutSender.send ("" + queryno + "g" + name + "\n");
607  retval = getVRMLreply(queryno);
608  }
609  return retval;
610  }
611 
612  // for SAI coding
613  public String getNodeFieldDefs (Node myn) {
614  String retval;
615  synchronized (FreeWRLToken) {
616  EAIoutSender.send ("" + queryno + "h" + myn.nodeptr + "\n");
617  retval = getVRMLreply(queryno);
618  }
619  return retval;
620  }
621 
622  // for SAI coding
623  public String getNodeDEFName (Node myn) {
624  String retval;
625 
626  synchronized (FreeWRLToken) {
627  EAIoutSender.send ("" + queryno + "i" + myn.nodeptr + "\n");
628  retval = getVRMLreply(queryno);
629  }
630  return retval;
631  }
632 
633  // for SAI coding
634  public String getRoutes () {
635  String retval;
636 
637  synchronized (FreeWRLToken) {
638  EAIoutSender.send ("" + queryno + "j\n");
639  retval = getVRMLreply(queryno);
640  }
641  return retval;
642  }
643 
644  // for SAI coding
645  public String getNodeType (Node myn) {
646  String retval;
647 
648  synchronized (FreeWRLToken) {
649  EAIoutSender.send ("" + queryno + "k " + myn.nodeptr + "\n");
650  retval = getVRMLreply(queryno);
651  }
652  return retval;
653  }
654 
655 
656 
657  // Tells the browser to load a VRML scene from the passed URL or
658  // URLs. After the scene is loaded, an event is sent to the MFNode
659  // eventIn in node NODE named by the EVENT argument
660  public void createVrmlFromURL(String[] url,
661  Node node,
662  String event) {
663 
664  EventInMFNode Evin;
665  String retval;
666  Node[] x = new Node[1];
667  StringTokenizer tokens;
668  int count;
669 
670 
671  synchronized (FreeWRLToken) {
672  EAIoutSender.send ("" + queryno + "T " + url[0] + "\n");
673 
674  retval = getVRMLreply(queryno);
675 
676  tokens = new StringTokenizer (retval);
677  count = 0;
678  x = new Node[tokens.countTokens()];
679 
680  while (tokens.hasMoreTokens()) {
681  x[count] = new Node();
682  x[count].nodeptr = Integer.parseInt(tokens.nextToken());
683  x[count].offset = 0;
684  x[count].datasize = 4;
685  x[count].datatype = "h"; // see CFuncs/EAIServ.c for a complete desc.
686  //System.out.println ("CVU - for this one, we have NODE" +
687  // " pointer:" + x[count].nodeptr + " offset:" + x[count].offset +
688  // " datasize: " + x[count].datasize + " datatype:" + x[count].datatype);
689 
690  count ++;
691  }
692  queryno += 1;
693  }
694 
695  // Now, sent the event to the event!
696  Evin = (EventInMFNode) node.getEventIn(event);
697  Evin.setValue(x);
698  }
699 
700 
701  // Add and delete, respectively, a route between the specified eventOut
702  // and eventIn of the given nodes
703  public void addRoute(Node fromNode, String fromEventOut,
704  Node toNode, String toEventIn) throws
705  IllegalArgumentException {
706  String retval;
707 
708  synchronized (FreeWRLToken) {
709  EAIoutSender.send ("" + queryno + "H " + fromNode.nodeptr + " " + fromEventOut +
710  " " + toNode.nodeptr + " " + toEventIn +"\n");
711  retval = getVRMLreply(queryno);
712  queryno += 1;
713  }
714  return;
715  }
716 
717 
718  public void deleteRoute(Node fromNode, String fromEventOut,
719  Node toNode, String toEventIn)
720  throws IllegalArgumentException {
721  String retval;
722 
723  synchronized (FreeWRLToken) {
724  EAIoutSender.send ("" + queryno + "J " + fromNode.nodeptr + " " + fromEventOut +
725  " " + toNode.nodeptr + " " + toEventIn +"\n");
726  retval = getVRMLreply(queryno);
727  queryno += 1;
728  }
729  return;
730  }
731 
732  // begin and end an update cycle
733  public void beginUpdate() {}
734  public void endUpdate() {}
735 
736  // called after the scene is loaded, before the first event is processed
737  public void initialize() {
738  System.out.println ("EAI: Initialize Not Implemented");
739 
740  }
741 
742 
743  // called just before the scene is unloaded
744  public void shutdown() {
745  System.out.println ("EAI: Shutdown Not Implemented");
746 
747  }
748 
749  // return an instance of the Browser class
750  // This returns the first embedded plugin in the current frame.
751  static public Browser getBrowser(Applet pApplet) {
752  return (new Browser(pApplet));
753  }
754 
755  static public Browser getBrowser(Applet pApplet, int portnum) {
756  return (new Browser(pApplet, portnum));
757  }
758 
759  // return an instance of the Browser class
760  // If frameName is NULL, current frame is assumed.
761  static public Browser getBrowser(Applet pApplet, String frameName, int index) {
762  // We don't have frames and indexes yet...
763  Browser x = getBrowser(pApplet);
764  System.out.println ("EAI: getBrowser possibly Not Implemented");
765 
766  return x;
767  }
768 
769 
770  // Get a DEFed node by name. Nodes given names in the root scene
771  // graph must be made available to this method. DEFed nodes in inlines,
772  // as well as DEFed nodes returned from createVrmlFromString/URL, may
773  // or may not be made available to this method, depending on the
774  // browser's implementation
775 
776  public Node getNode (String getName) throws InvalidNodeException
777  {
778  Node temp;
779  StringTokenizer tokens;
780  String retval;
781 
782  temp = new Node();
783 
784  synchronized (FreeWRLToken) {
785  EAIoutSender.send ("" + queryno + "A " + getName + "\n");
786  retval = getVRMLreply(queryno);
787  }
788 
789  tokens = new StringTokenizer (retval);
790 
791  temp.nodeptr = Integer.parseInt(tokens.nextToken());
792  queryno += 1;
793 
794  if (temp.nodeptr == 0)
795  throw new InvalidNodeException(getName + " undefined");
796 
797  return temp;
798  }
799 
800 
801 
802 
803  //
804  // Send Event to the VRML Browser. Note the different methods, depending
805  // on the parameters.
806  //
807  public static void SendChildEvent (int parent, int offset, String FieldName, int Child) {
808  String retval;
809 
810  // System.out.println ("SendChildEvent: sending to " + parent + " ofs:" +
811  // offset + " field " + FieldName + " child: " + Child);
812 
813  synchronized (FreeWRLToken) {
814  EAIoutSender.send ("" + queryno + "C " + parent + " " + offset + " " +
815  FieldName + " "+ Child + "\n");
816  retval = getVRMLreply(queryno);
817  queryno += 1;
818  }
819  return;
820  }
821 
822  // Most events don't need us to wait around for it.
823  public static void newSendEvent (EventIn node, String Value) {
824  synchronized (FreeWRLToken) {
825  EAIoutSender.send ("" + queryno + "D" + node.datatype + " " +
826  node.nodeptr + " " + node.offset + " " +node.ScriptType + " " + Value + "\n");
827  queryno += 1;
828  }
829  return;
830  }
831 
832 
833  protected static String SendNodeEAIType (int nodeptr) {
834 
835  // get a type from a particular node.
836 
837  String retval;
838 
839  synchronized (FreeWRLToken) {
840  EAIoutSender.send ("" + queryno + "B " + nodeptr + "\n");
841  retval = getVRMLreply(queryno);
842  queryno += 1;
843  }
844  return retval;
845 }
846  protected static String SendEventType (int nodeptr, String FieldName, String direction) {
847 
848  // get a type from a particular node.
849 
850  String retval;
851 
852  synchronized (FreeWRLToken) {
853  EAIoutSender.send ("" + queryno + "F " + nodeptr + " " +
854  FieldName + " " + direction + "\n");
855  retval = getVRMLreply(queryno);
856  queryno += 1;
857  }
858  return retval;
859 }
860 
861  public static String SendEventOut (int nodeptr, int offset, int datasize, String datatype,
862  String command) {
863  // get a value from a particular node.
864 
865  //System.out.println ("SendEventOut, nodeptr " + nodeptr + " datatype " + datatype);
866 
867  String retval;
868  synchronized (FreeWRLToken) {
869  EAIoutSender.send ("" + queryno + "E " + nodeptr + " " + offset + " " + datatype +
870  " " + datasize + "\n");
871 
872  retval = getVRMLreply(queryno);
873  queryno += 1;
874  }
875  //System.out.println ("SendEventOut returns " + retval);
876  return retval;
877 }
878 
879  public static void RegisterListener (EventOutObserver f, Object userData,
880  int nodeptr, int offset, String datatype, int datasize, int EventType)
881  {
882  synchronized (FreeWRLToken) {
883  //System.out.println ("Registering " + queryno + " node: " + nodeptr + " offset:"
884  // + offset + " datatype:" + datatype +
885  //" datasize:" + datasize + "\n");
886 
887  EAIoutSender.send ("" + queryno + "G " + nodeptr + " " + offset + " " + datatype +
888  " " + datasize + "\n");
889 
890  BrowserGlobals.EVarray [BrowserGlobals.EVno] = queryno;
891  BrowserGlobals.EVtype [BrowserGlobals.EVno] = EventType;
892  BrowserGlobals.EVObject[BrowserGlobals.EVno] = userData;
893  BrowserGlobals.EVObserver[BrowserGlobals.EVno] = f;
894 
895  BrowserGlobals.EVno += 1;
896 
897  getVRMLreply(queryno);
898  queryno += 1;
899  }
900  }
901 
902  public static void unRegisterListener (EventOutObserver f,
903  int nodeptr, int offset, String datatype, int datasize, int EventType)
904  {
905  synchronized (FreeWRLToken) {
906  //System.out.println ("Registering " + queryno + " node: " + nodeptr + " offset:"
907  // + offset + " datatype:" + datatype +
908  //" datasize:" + datasize + "\n");
909 
910  EAIoutSender.send ("" + queryno + "W " + nodeptr + " " + offset + " " + datatype +
911  " " + datasize + "\n");
912 
913  //BrowserGlobals.EVarray [BrowserGlobals.EVno] = queryno;
914  //BrowserGlobals.EVtype [BrowserGlobals.EVno] = EventType;
915  //BrowserGlobals.EVObject[BrowserGlobals.EVno] = userData;
916  //BrowserGlobals.EVObserver[BrowserGlobals.EVno] = f;
917 
918  //BrowserGlobals.EVno += 1;
919 
920  getVRMLreply(queryno);
921  queryno += 1;
922  }
923  }
924 
925  protected synchronized static String getVRMLreply (int queryno)
926  {
927 
928  String req = "0";
929  String rep = "";
930 
931 
932  // This waits for the correct event toe be returned. Note that
933  // sendevents dont wait, so there is the possibility that
934  // we will have to while away a bit of time waiting...
935 
936  while (queryno != Integer.parseInt(req)) {
937  try {
938  req = BrowserfromEAI.readLine();
939  } catch (IOException ie) {
940  System.out.println ("EAI: caught " + ie);
941  return rep;
942  }
943 
944  if (queryno != Integer.parseInt(req)) {
945  System.out.println ("EAI: getVRMLreply - REPLIES MIXED UP!!! Expecting "
946  + queryno +
947  " got " + req);
948  }
949 
950  try {
951  rep = BrowserfromEAI.readLine();
952  } catch (IOException ie) { System.out.println ("EAI: getVRMLreply failed"); return null; }
953 
954 
955  }
956 
957  return rep;
958  }
959  public void close() {
960  System.out.println("EAI: closing socket");
961  //JAS try {
962  System.exit(1);
963  //JAS EAIoutSender.stopThread();
964  //JAS EAISocket.close();
965  //JAS EAIfromFreeWRLStream.close();
966 
967  //JAS } catch (IOException e) {
968  //JAS }
969  }
970 }
971