1 //
2 package server;
3 import java.net.*;
4 import java.io.*;
5 import java.util.*;
6 import dx.protocol.*;
7 
8 public abstract class DXThread extends Thread
9 {
10     protected Socket clientSocket = null;
11     protected Vector actions;
12 
13     private BufferedReader is;
14     private PrintStream os;
15     private Vector msg_queue;
16 
17     //
18     // Failure status
19     //
20     private boolean failed = false;
setFailed()21     protected void setFailed()
22     {
23         failed = true;
24     }
25 
isFailed()26     protected boolean isFailed()
27     {
28         return failed;
29     }
30 
31     //
32     // debug status
33     //
34     private boolean debug = false;
isDebug()35     protected boolean isDebug()
36     {
37         return debug;
38     }
39 
cleanUp()40     public void cleanUp()
41     { }
42 
43 
DXThread( Socket client )44     protected DXThread ( Socket client )
45     {
46         clientSocket = client;
47 
48         try {
49             is = new BufferedReader( new InputStreamReader( clientSocket.getInputStream() ) );
50             os = new PrintStream( clientSocket.getOutputStream(), false );
51         }
52 
53         catch ( Exception e ) {
54             e.printStackTrace();
55             is = null;
56             os = null;
57         }
58 
59         actions = new Vector( 20 );
60         msg_queue = new Vector( 10 );
61 
62         String debug_option_string = getClass().getName() + ".debug";
63         String dbgmsgs = System.getProperty( debug_option_string );
64 
65         if ( dbgmsgs != null ) debug = true;
66         else debug = false;
67 
68         failed = false;
69     }
70 
getNextString()71     protected String getNextString() throws IOException
72     {
73         String retval = null;
74 
75         synchronized ( msg_queue ) {
76             if ( getQueueSize() > 0 ) {
77                 String msg = ( String ) msg_queue.firstElement();
78                 msg_queue.removeElementAt( 0 );
79                 retval = msg;
80             }
81 
82             else
83                 retval = is.readLine();
84         }
85 
86         return retval;
87     }
88 
getQueueSize()89     protected int getQueueSize() throws IOException
90     {
91         int qsize = 0;
92 
93         synchronized ( msg_queue ) {
94             while ( is.ready() ) {
95                 String inputLine = is.readLine();
96                 msg_queue.addElement( ( Object ) inputLine );
97             }
98 
99             qsize = msg_queue.size();
100         }
101 
102         return qsize;
103     }
104 
run()105     public final void run()
106     {
107         String inputLine = null;
108 
109         try {
110             while ( ( failed == false ) && ( ( inputLine = getNextString() ) != null ) ) {
111                 if ( debug )
112                     System.out.println ( getName() + ": " + inputLine );
113 
114                 Enumeration enum1 = actions.elements();
115 
116                 boolean executed = false;
117 
118                 while ( enum1.hasMoreElements() ) {
119                     DXThreadCommand stc = ( DXThreadCommand ) enum1.nextElement();
120 
121                     if ( inputLine.startsWith( stc.getCommandString() ) ) {
122                         executed = stc.execute( inputLine );
123 
124                         if ( executed ) break;
125                     }
126                 }
127 
128                 if ( !executed )
129                     System.out.println ( getName() + ": Unrecognized: " +
130                                          inputLine );
131             }
132         }
133 
134     catch ( SocketException se ) {}
135         catch ( Exception e ) {
136             e.printStackTrace();
137             setFailed();
138         }
139 
140         disconnect();
141     }
142 
transmit( threadMsg msg )143     protected void transmit( threadMsg msg )
144     {
145         if ( isDebug() ) {
146             System.out.println ( "                                       " +
147                                  getName() + ": " + msg.toString() );
148         }
149 
150         os.println ( msg.toString() );
151         os.flush();
152     }
153 
154     //
155     // There's a problem here I don't understand.  The thread is generally sitting
156     // in getNextString() waiting for input from the browser.  If DXServer decides
157     // it's time to shutdown, then he wants to call disconnect() for every running
158     // thread.  The problem with that is that the call to close a socket blocks.
159     // I don't know why - must have something to do with having a thread inside
160     // readLine.  The book says these methods aren't synchronized but apparently
161     // something is synchronized inside there.  So, I wrote virtual cleanUp()
162     // so that DXServer can call run clean-up type work before shutting down.
163     // That's important because we need a change to erase image files.
164     //
disconnect( threadMsg msg )165     protected boolean disconnect( threadMsg msg )
166     {
167         cleanUp();
168 
169         try {
170             clientSocket.close();
171         }
172 
173         catch ( Exception e ) { }
174 
175         try {
176             is.close();
177         }
178 
179         catch ( Exception e ) { }
180 
181         try {
182             os.close();
183         }
184 
185         catch ( Exception e ) { }
186 
187         return true;
188     }
189 
disconnect()190     protected boolean disconnect()
191     {
192         return disconnect( null );
193     }
194 
peekQueue( String cmd, boolean remove )195     protected String peekQueue( String cmd, boolean remove ) throws IOException
196     {
197         String retval = null;
198 
199         synchronized ( msg_queue ) {
200             if ( getQueueSize() > 0 ) {
201                 Enumeration enum1 = msg_queue.elements();
202 
203                 while ( enum1.hasMoreElements() ) {
204                     String msg = ( String ) enum1.nextElement();
205 
206                     if ( msg.startsWith( cmd ) ) {
207                         retval = msg;
208                         break;
209                     }
210                 }
211 
212                 if ( remove )
213                     msg_queue.removeElement( retval );
214             }
215         }
216 
217         return retval;
218     }
219 
220 
221 } // end DXThread
222