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