ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/conient/uk/org/iscream/cms/conient/ConnectionHandler.java
Revision: 1.20
Committed: Tue Feb 27 23:31:32 2001 UTC (23 years, 3 months ago) by ajm
Branch: MAIN
Changes since 1.19: +62 -6 lines
Log Message:
added support for 1.1 PROTOCOL
initial support for using it, though the configuration
of the actually host list is in GUI form, it currently doesn't work.
The option boxes of "discover" and "use host list" do though.
The configuration options for the list (if you want to hand edit) are:
hostList and knownHostList

File Contents

# User Rev Content
1 ajm 1.6 //---PACKAGE DECLARATION---
2 ajm 1.10 package uk.ac.ukc.iscream.conient;
3 ajm 1.6
4     //---IMPORTS---
5 ajm 1.1 import uk.ac.ukc.iscream.util.*;
6 ajm 1.2 import java.io.*;
7 ajm 1.1 import java.net.*;
8 ajm 1.2 import javax.swing.JOptionPane;
9 ajm 1.1
10 ajm 1.6 /**
11     * This is the main thread for the client.
12     * Once started i continually checks it actionQueue
13     * for actions that other areas of the system have placed
14     * there, it then performs those actions.
15     *
16     * Currently this is the main thread where all non-GUI events
17     * are dispatched to.
18     *
19 ajm 1.11 * @author $Author: ajm4 $
20 ajm 1.20 * @version $Id: ConnectionHandler.java,v 1.19 2001/02/27 03:09:58 ajm4 Exp $
21 ajm 1.6 */
22 ajm 1.1 public class ConnectionHandler extends Thread {
23 ajm 1.2
24 ajm 1.6 //---FINAL ATTRIBUTES---
25    
26     /**
27     * The current CVS revision of this class
28     */
29 ajm 1.20 public final String REVISION = "$Revision: 1.19 $";
30 ajm 1.6
31 tdb 1.7
32     /**
33     * The hardcoded protocol version that we are using.
34     * Used when handshaking with the server
35     */
36 ajm 1.20 public final double PROTOCOL_VERSION = 1.1;
37 ajm 1.2
38 tdb 1.7 /**
39     * Thread action DONOTHING.
40     * This is an invalid action, but here for completeness
41     * if anything sends this action it will warn appropriately
42     * but do what it says, ie, nothing ;)
43     */
44 ajm 1.1 public static final int DONOTHING = 0;
45 tdb 1.7
46     /**
47     * Thread action CONNECT.
48     * Opens the control link to the i-scream server.
49     */
50 ajm 1.1 public static final int CONNECT = 1;
51 tdb 1.7
52     /**
53     * Thread action STARTDATA.
54     * Opens the data link to the i-scream server
55     * and prepares all gui data components for data
56     * it then starts all relavant threads going.
57     */
58 ajm 1.2 public static final int STARTDATA = 2;
59 tdb 1.7
60     /**
61     * Thread action STOPDATA.
62     * Closes the data link and shuts down all components
63     * that update gui for various things.
64     */
65 ajm 1.2 public static final int STOPDATA = 3;
66 tdb 1.7
67     /**
68     * Thread action DISCONNECT.
69     * Checks to see if STOPDATA has been called if not,
70     * it will add STOPDATA and then DISCONNECT to
71     * the action queue and return. If STOPDATA has been
72     * called it closes down the Control Link and tidies up
73     * all relevant threads
74     */
75 ajm 1.2 public static final int DISCONNECT = 4;
76 tdb 1.7
77     /**
78     * Thread action QUIT.
79     * Checks the status of the two links, if either
80     * are still up, it queues the appropriate commands
81     * to close them down. It then System.exit(0)'s!
82     */
83 ajm 1.4 public static final int QUIT = 5;
84 ajm 1.6
85 ajm 1.12 /**
86 ajm 1.14 * Thread action GETCONFIGURATION
87     * Starts the command to obtain the configuration
88     * from the server.
89     * It then passes the IO to the Configuration object
90     * so it can obtain any specific configuration
91     */
92     public static final int GETCONFIGURATION = 6;
93    
94     /**
95 ajm 1.12 * This is the time in seconds that this class
96     * should wait on the DataReader class to fully
97     * shutdown after calling shutdown() before
98     * forcing a shutdown
99     */
100     public static final int DATAREADER_SHUTDOWN_TIMEOUT = 5;
101    
102 ajm 1.13 /**
103     * The default local server to connect to when a
104     * firewall is in use if one is not specified in the server
105     */
106     public static final String DEFAULT_FIREWALL_SERVER = "localhost";
107    
108     /**
109     * The default time in seconds to wait for the
110     * firewall setup command to execute
111     */
112     public static final int DEFAULT_FIREWALL_COMMANDWAIT = 5;
113    
114 ajm 1.6 //---STATIC METHODS---
115    
116     //---CONSTRUCTORS---
117    
118 tdb 1.7 /**
119     * Constructs new data handler.
120     * Needs a reference to the data panel so that
121     * it can set it processing inBound data
122     * Also gets a reference to the queue that will be
123     * used by other areas of the system to send it actions
124     *
125     * @param data the DataPanel in use
126     * @param actionQueue the actionQueue for this class
127     */
128 ajm 1.1 public ConnectionHandler(DataPanel data, Queue actionQueue) {
129     _data = data;
130     _actionQueue = actionQueue;
131     _myQueue = _actionQueue.getQueue();
132     }
133    
134 ajm 1.6 //---PUBLIC METHODS---
135    
136 tdb 1.7
137     /**
138     * Starts this ConnectionHandler running.
139     * This basically runs until told to stop, it gets "actions"
140     * from its actionQueue and switch's on them do determine
141     * what it should do it then carries out the action
142     *
143     * For details on what each action does see the action
144     * types.
145     */
146 ajm 1.1 public void run() {
147 ajm 1.20 if(_configuration.getProperty("control.onstartconnect").equals("1")) {
148 ajm 1.13 _actionQueue.add(new Integer(CONNECT));
149     }
150 ajm 1.20 if(_configuration.getProperty("data.onstartconnect").equals("1")) {
151 ajm 1.13 _actionQueue.add(new Integer(STARTDATA));
152     }
153 tdb 1.7 while(_running) {
154 ajm 1.1 // we wait for a call...
155     int action = 0;
156     try {
157     action = ((Integer) _actionQueue.get(_myQueue)).intValue();
158     } catch (InvalidQueueException e) {
159 ajm 1.12 // we 're never going to get this
160     // but if we do we should do something nasty
161     throw new RuntimeException("unable to retrieve events from actionQueue!");
162 ajm 1.1 }
163    
164     // examine our action...
165     // if it was to connect...then we connect...
166 ajm 1.2 switch(action) {
167     case CONNECT:
168 ajm 1.12 if (_controlLink == null) {
169 ajm 1.13 try {
170     // get the server name from the config
171     _configuredServer = _configuration.getProperty("control.server");
172    
173     if (_configuredServer == null) {
174     throw new IOException("no i-scream server in current configuration");
175     }
176    
177     // open the socket to the server and bind the IO
178     // get the port from the config
179     String portString = _configuration.getProperty("control.port");
180     if (portString == null) {
181     throw new IOException("no i-scream server port in current configuration");
182     }
183     int port = 0;
184 ajm 1.12 try {
185 ajm 1.13 port = Integer.parseInt(portString);
186     } catch (NumberFormatException e) {
187     throw new IOException("no valid i-scream server port in current configuration");
188     }
189    
190     // start firewall if needed
191     _server = handleFirewall(_configuredServer, port, _controlFirewallProcess);
192    
193     Conient.setControlStatus("Connecting to - " + _server);
194     _controlLink = new Socket(_server, port);
195     _inBound = new BufferedReader(new InputStreamReader(_controlLink.getInputStream()));
196     _outBound = new PrintWriter(_controlLink.getOutputStream());
197     Conient.setControlStatus("Connection Established - " + _server);
198    
199     String response;
200     response = _inBound.readLine();
201    
202     // check the servers Protocol Identity against our own
203     // we SHOULD be backwards compatible, so we can continue if
204     // they are using a newer protocol, anything else then we die
205     if (!(Double.parseDouble(response.substring(10, response.length())) > PROTOCOL_VERSION)) {
206     Conient.addMessage("WARNING{control link}: server is using a newer protocol (" + response + "), please update your client, continuing with old protocol (PROTOCOL " + PROTOCOL_VERSION + ")" );
207     } else if (!(Double.parseDouble(response.substring(10, response.length())) < PROTOCOL_VERSION)) {
208     // tidy up
209     throw new IOException("incompatible protocol version");
210     }
211    
212     // send the name of the client
213     _outBound.println(_configuration.getProperty("clientname"));
214     _outBound.flush();
215     response = _inBound.readLine();
216     if (!response.equals("OK")) {
217     // tidy up
218 ajm 1.12
219 ajm 1.13 throw new IOException("client name rejected - " + _configuration.getProperty("clientname"));
220     }
221 ajm 1.14 // get the config...we are connected now!
222 ajm 1.18 getConfigFromServer();
223 ajm 1.20 // set our host list if we know we have one we need to set
224     String hostList = _configuration.getProperty("hostList");
225     boolean hostListSet = false;
226     // send our hostList if we have
227     if (_configuration.getProperty("useHostList").equals("1")) {
228     if (hostList.equals("")) {
229     Conient.addMessage("WARNING{control link}: your host list is empty, the server will send ALL hosts");
230     }
231     hostListSet = setHostList(hostList);
232     // if not, indicate we want the lot
233     } else {
234     hostListSet = setHostList("");
235     }
236     // warn if there was a problem, it will have already error'd
237     if (!hostListSet) {
238     Conient.addMessage("WARNING{control link}: unable to set host list");
239     }
240 ajm 1.13 } catch (IOException e) {
241     // print the error and tidy up what's left
242     Conient.addMessage("ERROR{control link}: " + e);
243     _controlLink = null;
244     // and the firewall handler if there is one
245 ajm 1.16 closeFirewall(_controlFirewallProcess);
246 ajm 1.13 _actionQueue.clearQueue(_myQueue);
247     Conient.setControlStatus("Disconnected");
248 ajm 1.2 }
249 ajm 1.12 } else {
250     Conient.addMessage("WARNING{control link}: already established");
251 ajm 1.2 }
252     break;
253     case STARTDATA:
254 ajm 1.12 // as long as the data link hasn't been established
255     // we want to establish it
256     if (_dataLink == null) {
257     // check that the control link is open, if it isn't we
258     // might want to sort that problemo out
259     // we do this by simply queueing the event to occour, then
260     // this event to run again ;-)
261 tdb 1.7 if(_controlLink == null) {
262 ajm 1.12 Conient.addMessage("WARNING{data link}: control link not established - queueing start events");
263 tdb 1.7 _actionQueue.add(new Integer(CONNECT));
264     _actionQueue.add(new Integer(STARTDATA));
265 ajm 1.12 } else {
266     try {
267    
268     // ask the server to start the data link
269     String response;
270     _outBound.println("STARTDATA");
271     _outBound.flush();
272     response = _inBound.readLine();
273    
274     // see if the server suggested a good port
275     if (response.equals("ERROR")) {
276     throw new IOException("server unable to start data link at this time");
277     }
278 ajm 1.13 int port = 0;
279 ajm 1.12 try {
280 ajm 1.13 port = Integer.parseInt(response);
281 ajm 1.12 } catch (NumberFormatException e) {
282     throw new IOException("invalid data port suggested by server - " + response);
283     }
284    
285 ajm 1.13 // start firewall if needed
286     _server = handleFirewall(_configuredServer, port, _dataFirewallProcess);
287     Conient.setDataStatus("Connecting to - " + _server + ":" + response);
288    
289     _dataLink = new Socket(_server, port);
290    
291 ajm 1.12 response = _inBound.readLine();
292     if (!response.equals("OK")) {
293     throw new IOException("server reported error establishing data channel");
294     }
295    
296     // if the socket was ok, then we attack our IO hooks
297     _dataInBound = new BufferedReader(new InputStreamReader(_dataLink.getInputStream()));
298     _dataOutBound = new PrintWriter(_dataLink.getOutputStream());
299     Conient.setDataStatus("Connection Established - " + _server);
300 ajm 1.15 // now we want to start reading the data in
301     // so we start the appropriate components on their way
302     // we create a queue to give to both the reader and the
303     // displayer
304     Queue theQueue = new Queue();
305     _dataReader = new DataReader(_dataInBound, theQueue);
306     _data.setQueue(theQueue);
307     _data.cleanUpTabs();
308    
309     // start the data rocking
310     new Thread(_data).start();
311     _dataReader.start();
312     // finished for us....
313 ajm 1.12 } catch (IOException e) {
314     // print the error and tidy up what's left
315     Conient.addMessage("ERROR{data link}: " + e);
316     _dataLink = null;
317 ajm 1.16 // and the firewall handler if there is one
318     closeFirewall(_dataFirewallProcess);
319 ajm 1.13 _actionQueue.clearQueue(_myQueue);
320 ajm 1.12 Conient.setDataStatus("Disconnected");
321     }
322 ajm 1.2 }
323 ajm 1.12 } else {
324     Conient.addMessage("WARNING{data link}: already established");
325 ajm 1.2 }
326     break;
327     case STOPDATA:
328 ajm 1.12 if(_dataLink != null) {
329     try {
330     String response;
331     // shut down the data link
332     Conient.setDataStatus("Disconnecting - " + _server);
333    
334     // close the reader
335     _dataReader.shutdown();
336     // wait for it to close
337     boolean dirtyShutdown = true;
338     long startTime = System.currentTimeMillis();
339     while((System.currentTimeMillis() - startTime) < (DATAREADER_SHUTDOWN_TIMEOUT * 1000)) {
340     if (!_dataReader.isAlive()) {
341     dirtyShutdown = false;
342     break;
343     }
344     }
345     // warn if it didn't shutdown in time
346     if (dirtyShutdown) {
347     Conient.addMessage("WARNING{data link}: data reader thread did not close within timeout, killing its IO anyway!");
348     }
349    
350     // tell the server
351     _outBound.println("STOPDATA");
352     _outBound.flush();
353     response = _inBound.readLine();
354    
355     // check the server was ok with our request...
356     // even if it wasn't we will go anyway!
357     if (!response.equals("OK")) {
358     throw new IOException("server didn't OK request to stop data channel - stopping anyway");
359     }
360    
361    
362     // close the lot down
363     _dataInBound.close();
364     _dataOutBound.close();
365     _dataLink.close();
366     // get rid of the socket
367     _dataLink = null;
368 ajm 1.13
369     // and the firewall handler if there is one
370 ajm 1.16 closeFirewall(_dataFirewallProcess);
371 ajm 1.13
372 ajm 1.12 Conient.setDataStatus("Disconnected");
373     } catch (IOException e) {
374     // print the error and tidy up what's left
375     Conient.addMessage("ERROR{data link}: " + e);
376     try {
377     _dataOutBound.close();
378     _dataInBound.close();
379     _dataLink.close();
380 ajm 1.13 // and the firewall handler if there is one
381 ajm 1.16 closeFirewall(_dataFirewallProcess);
382 ajm 1.12 } catch (IOException e2) {
383     Conient.addMessage("CRITICAL{control link}: unable to close socket - " + e2);
384     }
385     _dataLink = null;
386 ajm 1.13 _actionQueue.clearQueue(_myQueue);
387 ajm 1.12 Conient.setDataStatus("Disconnected");
388 ajm 1.2 }
389 ajm 1.12 } else {
390     Conient.addMessage("WARNING{data link}: already disconnected");
391 ajm 1.2 }
392     break;
393     case DISCONNECT:
394 ajm 1.12 if (_controlLink != null) {
395 ajm 1.2 if (_dataLink != null) {
396 ajm 1.12 // we want to tell ourselves to stop it
397     Conient.addMessage("WARNING{control link}: data link not disconnected - queueing stop events");
398     _actionQueue.add(new Integer(STOPDATA));
399     _actionQueue.add(new Integer(DISCONNECT));
400     } else {
401     try {
402     // request the server to disconnect
403     String response;
404     _outBound.println("DISCONNECT");
405     _outBound.flush();
406     response = _inBound.readLine();
407    
408     // check the server was ok with our request...
409     // even if it wasn't we will go anyway!
410     if (!response.equals("OK")) {
411     throw new IOException("server didn't OK request to stop control channel - stopping anyway");
412     }
413    
414     // then lets shutdown the link
415     Conient.setControlStatus("Disconnecting - " + _server);
416     _inBound.close();
417     _outBound.close();
418     _controlLink.close();
419     // for good measure
420     _controlLink = null;
421 ajm 1.13
422     // and the firewall handler if there is one
423 ajm 1.16 closeFirewall(_controlFirewallProcess);
424 ajm 1.13
425 ajm 1.12 Conient.setControlStatus("Disconnected");
426     } catch (IOException e) {
427 ajm 1.14 Conient.addMessage("ERROR{control link}: " + e);
428 ajm 1.12 try {
429     _inBound.close();
430     _outBound.close();
431     _controlLink.close();
432 ajm 1.13 // and the firewall handler if there is one
433 ajm 1.16 closeFirewall(_controlFirewallProcess);
434 ajm 1.12 } catch (IOException e2) {
435     Conient.addMessage("CRITICAL{control link}: unable to close socket - " + e2);
436     }
437     _controlLink = null;
438 ajm 1.13 _actionQueue.clearQueue(_myQueue);
439 ajm 1.12 Conient.setControlStatus("Disconnected");
440     }
441 ajm 1.2 }
442 ajm 1.12 } else {
443     Conient.addMessage("WARNING{control link}: already disconnected");
444 ajm 1.1 }
445 ajm 1.2 break;
446 ajm 1.4 case QUIT:
447 ajm 1.12 Conient.addMessage("Exiting.");
448 ajm 1.5 try {
449     // stop data and control if data up
450     if (_dataLink != null) {
451     _actionQueue.add(new Integer(STOPDATA));
452     _actionQueue.add(new Integer(DISCONNECT));
453     _actionQueue.add(new Integer(QUIT));
454     throw new IOException();
455     }
456     // stop control
457     if (_controlLink != null) {
458     _actionQueue.add(new Integer(DISCONNECT));
459     _actionQueue.add(new Integer(QUIT));
460     throw new IOException();
461     }
462 ajm 1.11 Conient.addMessage("Finished.");
463 ajm 1.5 // go!
464     System.exit(0);
465     } catch (IOException e) {
466 ajm 1.12 Conient.addMessage("WARNING: open connections detected - queueing stop events");
467 ajm 1.4 }
468     break;
469 ajm 1.14 case GETCONFIGURATION:
470 ajm 1.18 getConfigFromServer();
471 ajm 1.14 break;
472 ajm 1.1 }
473     }
474     }
475    
476 ajm 1.12 /**
477     * This method allows other classes
478     * to shutdown this connection handler.
479     */
480     public void shutdown() {
481     _running = false;
482     }
483    
484 ajm 1.6 //---PRIVATE METHODS---
485 ajm 1.18
486     /**
487 ajm 1.20 * This method performs the SETHOSTLIST command.
488     * This is run by the CONNECT command.
489     * It tells the server which hosts we are interested
490     * in, if "" is sent, this indicates we want ALL hosts.
491     *
492     * @param hostList the list of hosts as gained from the config
493     * @return if we succeeded in setting the host list
494     */
495     private boolean setHostList(String hostList) {
496     boolean success = false;
497     // must have a control link open
498     if (_controlLink != null) {
499     // data link must be closed (according to 1.1 PROTOCOL)
500     if(_dataLink == null) {
501     try {
502     String response = null;
503     _outBound.println("SETHOSTLIST");
504     _outBound.flush();
505     response = _inBound.readLine();
506     if (!response.equals("OK")) {
507     throw new IOException("server refused - data link possibly still open?");
508     }
509     _outBound.println(hostList);
510     _outBound.flush();
511     response = _inBound.readLine();
512     if (!response.equals("OK")) {
513     throw new IOException("server had trouble with our request");
514     }
515     success = true;
516     } catch (IOException e) {
517     Conient.addMessage("ERROR{control link}: when setting hostlist - " + e);
518     }
519     }
520     }
521     return success;
522     }
523    
524    
525     /**
526 ajm 1.18 * This method performs the STARTCONFIG command on
527     * the server. this method is called after a CONNECT,
528     * and when a GETCONFIGURATION command is called.
529     */
530     private void getConfigFromServer() {
531     if(_controlLink != null) {
532     try {
533     String response = null;
534     _outBound.println("STARTCONFIG");
535     _outBound.flush();
536     response = _inBound.readLine();
537     if (!response.equals("OK")) {
538     throw new IOException("server refused (" + response + ")");
539     }
540     _configuration.readServerConfiguration(_inBound, _outBound);
541     _outBound.println("ENDCONFIG");
542     _outBound.flush();
543     response = _inBound.readLine();
544     if (!response.equals("OK")) {
545     throw new IOException("server reported error when finishing configuration");
546     }
547     } catch (IOException e) {
548     Conient.addMessage("ERROR{control link}: when getting configuration - " + e);
549     }
550     }
551     }
552 ajm 1.6
553 ajm 1.13 /**
554     * Handles opening pipes through firewalls.
555     * It checks the configuration for various entries
556     * to set up the link or not.
557     *
558     * If a link is setup it will return the name of the
559     * new server to connect to, if a link is NOT setup,
560     * it will simply return the original server name.
561     *
562     * The name of the machine that the pipe is setup on
563     * defaults to "localhost", unless the configuration
564     * specifies otherwise.
565     *
566     * Once it has run the firewall command it then waits
567     * a set period according to the config for the firewall
568     * pipe to be set up.
569     *
570     * The firewall process should be destroyed when the
571     * link is finished with.
572     *
573     * @param server the name of the server to open up the pipe to
574     * @param port the port number to open up the pipe to
575     * @param firewallProcess the holder for the new firewall process
576     * @return the server to connect to, as determined by this routine
577     */
578     private String handleFirewall(String server, int port, Process firewallProcess) {
579     String firewallCommand = _configuration.getProperty("firewall.command");
580 ajm 1.19 String useFirewall = _configuration.getProperty("useFirewall");
581 ajm 1.13 String firewallCommandWait = _configuration.getProperty("firewall.commandwait");
582     String firewallServer = _configuration.getProperty("firewall.server");
583     // if we are running firewall support...then lets start it
584 ajm 1.20 if (useFirewall.equals("1")) {
585 ajm 1.13 // clean up the command with what we want
586     firewallCommand = replaceText(firewallCommand, "%PORT%", new Integer(port).toString());
587     firewallCommand = replaceText(firewallCommand, "%SERVER%", server);
588     Conient.addMessage("WARNING{firewall}: firewall pipes requested, running pipe setup command \"" + firewallCommand + "\"");
589     try {
590     // run the command
591     firewallProcess = Runtime.getRuntime().exec(firewallCommand);
592    
593     // work out how long we should wait before carrying on
594     int time = 0;
595     try {
596     time = Integer.parseInt(firewallCommandWait);
597     } catch (NumberFormatException e) {
598     time = 0;
599     }
600     if (time == 0) {
601     time = DEFAULT_FIREWALL_COMMANDWAIT;
602     }
603     Conient.addMessage("WARNING{firewall}: waiting " + time + " seconds for command to complete!");
604     // wait for the command to finish
605     try {
606     Thread.sleep(time * 1000);
607     } catch (InterruptedException e) {
608     }
609    
610     // set the server we want to return
611     server = firewallServer;
612 ajm 1.19 if (server.equals("")) {
613 ajm 1.13 server = DEFAULT_FIREWALL_SERVER;
614     }
615     } catch (IOException e) {
616     Conient.addMessage("ERROR{firewall}: unable to start pipe to i-scream server");
617     }
618     }
619     return server;
620 ajm 1.16 }
621    
622     /**
623     * Checks to see if the given firewall process
624     * has been created. If it has it calls destroy()
625     * on it.
626     *
627     * @param firewallProcess the process to check
628     */
629     private void closeFirewall(Process firewallProcess) {
630     if (firewallProcess != null) {
631 ajm 1.17 firewallProcess.destroy();
632     firewallProcess = null;
633 ajm 1.16 Conient.addMessage("WARNING{firewall}: firewall process destroyed");
634     }
635 ajm 1.13 }
636    
637     /**
638     * Searches a string and replaces all occurences
639     * of the given search text with the given replacement
640     * text.
641     *
642     * @param text the text to search and replace in
643     * @param search the string to look for and replace
644     * @param replace the text to replace with
645     * @return the updated version of text
646     */
647     private String replaceText(String text, String search, String replace) {
648     StringBuffer textBuffer = new StringBuffer(text);
649     int currIndex = 0;
650     currIndex = text.indexOf(search, currIndex);
651     while(currIndex != -1) {
652     if (currIndex != -1) {
653     textBuffer.delete(currIndex, currIndex + search.length());
654     textBuffer.insert(currIndex, replace);
655     }
656     text = textBuffer.toString();
657     currIndex = text.indexOf(search, currIndex + search.length());
658     }
659     return new String(textBuffer);
660     }
661 ajm 1.6 //---ACCESSOR/MUTATOR METHODS---
662    
663     //---ATTRIBUTES---
664    
665 ajm 1.12 /**
666     * The state if this thread
667     */
668 ajm 1.13 private boolean _running = true;
669 ajm 1.12
670     /**
671     * A reference to the displaying class DataPanel
672     */
673 ajm 1.13 private DataPanel _data;
674 ajm 1.12
675     /**
676     * The queue that actions are added to by other parts of the system
677     */
678 ajm 1.13 private Queue _actionQueue;
679 ajm 1.12
680     /**
681     * The queue number that we are reading from on the action queue
682     */
683 ajm 1.13 private int _myQueue;
684 ajm 1.12
685     /**
686     * The control link socket
687     */
688 ajm 1.13 private Socket _controlLink;
689 ajm 1.12
690     /**
691     * The data link socket
692     */
693 ajm 1.13 private Socket _dataLink;
694 ajm 1.12
695     /**
696     * The input for the control link
697     */
698 ajm 1.13 private BufferedReader _inBound;
699 ajm 1.12
700     /**
701     * The output for the control link
702     */
703 ajm 1.13 private PrintWriter _outBound;
704 ajm 1.12
705     /**
706     * The input for the data link
707     */
708 ajm 1.13 private BufferedReader _dataInBound;
709 ajm 1.12
710     /**
711     * The output for the data link
712     */
713 ajm 1.13 private PrintWriter _dataOutBound;
714 ajm 1.12
715     /**
716     * A reference to the DataReader in use
717     */
718 ajm 1.13 private DataReader _dataReader;
719    
720     /**
721     * A reference to the system configuration component
722     */
723     private Configuration _configuration = Configuration.getInstance();
724    
725     /**
726     * The server we will be connecting to
727     */
728     private String _server = null;
729 ajm 1.12
730     /**
731 ajm 1.13 * The server that the config says we should connect to
732 ajm 1.12 */
733 ajm 1.13 private String _configuredServer = null;
734 ajm 1.6
735 ajm 1.13 /**
736     * The process used to start the firewall pipe
737     * for the control link.
738     */
739     private Process _controlFirewallProcess = null;
740    
741     /**
742     * The process used to start the firewall pipe
743     * for the data link.
744     */
745     private Process _dataFirewallProcess = null;
746    
747 ajm 1.6 //---STATIC ATTRIBUTES---
748    
749 ajm 1.1 }