1 /************************************************************
2 * Copyright *
3 * Portions of this software are Copyright (c) 1993 - 2002, *
4 * Chad Z. Hower (Kudzu) and the Indy Pit Crew *
5 * - http://www.nevrona.com/Indy/ *
6 ************************************************************/
7 package org.indy;
8
9 import java.beans.Beans;
10
11 import java.io.IOException;
12
13 import java.net.InetAddress;
14 import java.net.ServerSocket;
15
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Vector;
22
23 import org.indy.io.IndyIOException;
24 import org.indy.io.ServerIOHandler;
25 import org.indy.io.ServerIOHandlerSocket;
26
27 import org.indy.util.IndyUtilities;
28
29
30 /***
31 * Description of the Class
32 *
33 *@author owen
34 *@created 26 September 2002
35 */
36 public class TCPServer extends IndyComponent {
37 private final List bindings = new ArrayList();
38 private final CommandHandlers commandHandlers = new CommandHandlers(this);
39 private final ServerListenerList listenerList = new ServerListenerList();
40 private final List listenerThreadList = new ArrayList();
41 private final List threadList = Collections.synchronizedList(new ArrayList());
42 private volatile boolean commandHandlersEnabled;
43 private boolean commandHandlersInitialized;
44 private int defaultPort = 6666;
45
46 //Execution listener is unicast
47 private TCPServerExecuteListener executor;
48 private RFCReply greeting;
49 private boolean implicitIOHandler;
50 private boolean implicitThreadManager;
51 private ServerIOHandler ioHandler;
52 private boolean active = false;
53 private int listenQueue;
54 private ListenerThread listenThread;
55 private RFCReply maxConnectionReply;
56 private int maxConnections;
57 private RFCReplies relpyTexts = new RFCReplies();
58 private RFCReply replyUnknownCommand;
59 private int terminateWaitTime;
60 private PeerThreadManager threadManager = new DefaultPeerThreadManager();
61 transient private Vector TCPServerListeners;
62
63 /***
64 * Constructor for the TCPServer object
65 */
66 public TCPServer() {
67 }
68
69 /***
70 * Description of the Method
71 *
72 *@param thread Description of the Parameter
73 */
74 protected void doAfterCommandHandler(PeerThread thread) {
75 TCPServerListener[] l = listenerList.getArray();
76
77 for (int i = 0; i < l.length; i++) {
78 l[i].onAfterCommandHandler(this, thread);
79 }
80 }
81
82 /***
83 * Description of the Method
84 *
85 *@param thread Description of the Parameter
86 *@param line Description of the Parameter
87 */
88 protected void doBeforeCommandHandler(PeerThread thread, String line) {
89 TCPServerListener[] l = listenerList.getArray();
90
91 for (int i = 0; i < l.length; i++) {
92 l[i].onBeforeCommandHandler(this, thread, line);
93 }
94 }
95
96 /***
97 * Description of the Method
98 *
99 *@param thread Description of the Parameter
100 */
101 protected void doConnect(PeerThread thread) {
102 TCPServerListener[] listeners = listenerList.getArray();
103
104 for (int i = 0; i < listeners.length; i++) {
105 listeners[i].onConnect(thread);
106 }
107 }
108
109 /***
110 * Description of the Method
111 *
112 *@param thread Description of the Parameter
113 */
114 protected void doDisconnect(PeerThread thread) {
115 TCPServerListener[] l = listenerList.getArray();
116
117 for (int i = 0; i < l.length; i++) {
118 l[i].onDisconnect(thread);
119 }
120 }
121
122 /***
123 * Description of the Method
124 *
125 *@param thread Description of the Parameter
126 *@param exception Description of the Parameter
127 */
128 protected void doException(PeerThread thread, IndyException exception) {
129 if (listenerList.isEmpty()) {
130 System.err.println("No Server Listener Available:");
131 exception.printStackTrace();
132
133 return;
134 }
135
136 TCPServerListener[] listeners = listenerList.getArray();
137
138 for (int i = 0; i < listeners.length; i++) {
139 listeners[i].onException(thread, exception);
140 }
141 }
142
143 /***
144 * Description of the Method
145 *
146 *@param thread Description of the Parameter
147 *@return Description of the Return Value
148 *@throws IndyException Description of the Exception
149 */
150 protected boolean doExecute(PeerThread thread) throws IndyException {
151 if (commandHandlersEnabled && (commandHandlers.size() > 0)) {
152 String line = thread.getConnection().readLine();
153
154 if (line.length() > 0) {
155 doBeforeCommandHandler(thread, line);
156
157 try {
158 for (int i = 0, n = commandHandlers.size(); i < n; i++) {
159 CommandHandler ch = commandHandlers.getCommandHandler(i);
160
161 if (ch.isEnabled()) {
162 if (ch.check(line, thread)) {
163 break;
164 }
165 }
166
167 if (i == (n - 1)) {
168 doNoCommandHandler(thread, line);
169 }
170 }
171 }
172 finally {
173 doAfterCommandHandler(thread);
174
175 return true;
176 }
177 }
178 }
179 else {
180 if (executor != null) {
181 executor.onExecute(this, thread.getConnection());
182
183 return true;
184 }
185 }
186
187 return false;
188 }
189
190 /***
191 * Description of the Method
192 *
193 *@param thread Description of the Parameter
194 *@param exception Description of the Parameter
195 */
196 protected void doListenException(ListenerThread thread,
197 IndyException exception) {
198 if (listenerList.isEmpty()) {
199 //just do a stack trace and bail
200 System.err.println("LISTEN EXCEPTION");
201 exception.printStackTrace();
202
203 return;
204 }
205
206 TCPServerListener[] listeners = listenerList.getArray();
207
208 for (int i = 0; i < listeners.length; i++) {
209 listeners[i].onListenException(thread, exception);
210 }
211 }
212
213 /***
214 * Description of the Method
215 *
216 *@param thread Description of the Parameter
217 *@param data Description of the Parameter
218 *@exception TCPServerException Description of the Exception
219 *@throws IdTCPServerError Description of the Exception
220 */
221 protected void doNoCommandHandler(PeerThread thread, String data)
222 throws TCPServerException {
223 if (!commandHandlers.isEmpty()) {
224 TCPServerListener[] listeners = listenerList.getArray();
225
226 for (int i = 0; i < listeners.length; i++) {
227 listeners[i].onNoCommandHandler(this, thread, data);
228 }
229 }
230
231 else if (replyUnknownCommand.replyExists()) {
232 try {
233 thread.getConnection().writeRFCReply(replyUnknownCommand);
234 }
235 catch (IndyException ide) {
236 throw new TCPServerException(ide.getMessage());
237 }
238 }
239
240 else {
241 throw new TCPServerException(IndyUtilities.getResourceString(
242 "RSNoCommandHandlerFound"));
243 }
244 }
245
246 /***
247 * DOCUMENT ME!
248 *
249 * @param b DOCUMENT ME!
250 */
251 public void addBinding(TCPServerBinding b) {
252 bindings.add(b);
253 }
254
255 /***
256 * Adds a feature to the CommandHandlerListener attribute of the IdTCPServer
257 * object
258 *
259 *@param l The feature to be added to the CommandHandlerListener attribute
260 */
261 public void removeBinding(TCPServerBinding b) {
262 bindings.remove(b);
263 }
264
265 /***
266 * Description of the Method
267 *
268 *@param l Description of the Parameter
269 */
270 /***
271 * Sets the active attribute of the IdTCPServer object
272 *
273 *@param active The new active value
274 *@exception IndyIOException Description of the Exception
275 */
276 public void setActive(boolean makeActive) throws IndyIOException {
277 if (!Beans.isDesignTime() && makeActive && (makeActive != active)) {
278 try {
279 ioHandler = new ServerIOHandlerSocket();
280 ioHandler.init();
281
282 if (bindings.isEmpty()) {
283 bindings.add(new TCPServerBinding(null, defaultPort));
284 }
285
286 for (int i = 0, n = bindings.size(); i < n; i++) {
287 TCPServerBinding binding = (TCPServerBinding) bindings.get(i);
288 ServerSocket ss = null;
289
290 int port = binding.getPort();
291
292 if (binding.getHost() != null) {
293 InetAddress addr = InetAddress.getByName(binding.getHost());
294
295 ss = new ServerSocket(port, listenQueue, addr);
296 }
297 else {
298 ss = new ServerSocket(port, listenQueue);
299 }
300
301 ListenerThread listener = new ListenerThread(this, ss);
302
303 listenerThreadList.add(listener);
304 listener.start();
305 }
306 }
307 catch (IOException ioe) {
308 throw new IndyIOException(ioe);
309 }
310 }
311 else {
312 try {
313 System.err.println("Here");
314
315 threadManager.terminateThreads();
316 System.err.println("There");
317
318 for (int i = 0, n = listenerThreadList.size(); i < n; i++) {
319 ListenerThread listener = (ListenerThread) listenerThreadList.get(i);
320
321 listener.terminateAndWait();
322 }
323
324 listenerThreadList.clear();
325 }
326 catch (InterruptedException ie) {
327 ie.printStackTrace();
328 }
329 }
330
331 active = makeActive;
332 }
333
334 /***
335 * Sets the port attribute of the IdTCPServer object
336 *
337 *@param newPort The new port value
338 */
339 public void setDefaultPort(int newPort) {
340 this.defaultPort = newPort;
341 }
342
343 /***
344 * Sets the executionListener attribute of the IdTCPServer object
345 *
346 *@param e The new executionListener value
347 */
348 public void addServerExecuteListener(TCPServerExecuteListener e) { //throws TooManyListenersException{
349
350 // if(executor == null){
351 executor = e;
352
353 // }
354 // else {
355 // throw new TooManyListenersException("Only one TCPServerExecuteListener is permitted at a time. Call removeServerExecuteListener() first");
356 // }
357 }
358
359 /***
360 * DOCUMENT ME!
361 *
362 * @param e DOCUMENT ME!
363 */
364 public void removeServerExecuteListener(TCPServerExecuteListener e) {
365 executor = null;
366 }
367
368 /***
369 * DOCUMENT ME!
370 *
371 * @param listenQueue DOCUMENT ME!
372 */
373 public void setListenQueue(int listenQueue) {
374 this.listenQueue = listenQueue;
375 }
376
377 /***
378 * Sets the threadMgr attribute of the IdTCPServer object
379 *
380 *@param threadMgr The new threadMgr value
381 */
382 public void setThreadManager(PeerThreadManager threadMgr) {
383 threadManager = threadMgr;
384 }
385
386 /***
387 * DOCUMENT ME!
388 *
389 * @param index DOCUMENT ME!
390 *
391 * @return DOCUMENT ME!
392 */
393 public TCPServerBinding getBinding(int index) {
394 return (TCPServerBinding) bindings.get(index);
395 }
396
397 /***
398 * DOCUMENT ME!
399 *
400 * @return DOCUMENT ME!
401 */
402 public TCPServerBinding[] getBindings() {
403 return (TCPServerBinding[]) bindings.toArray();
404 }
405
406 /***
407 * Gets the port attribute of the IdTCPServer object
408 *
409 *@return The port value
410 */
411 public int getDefaultPort() {
412 return defaultPort;
413 }
414
415 /***
416 * Gets the iOHandler attribute of the IdTCPServer object
417 *
418 *@return The iOHandler value
419 */
420 public ServerIOHandler getIOHandler() {
421 return ioHandler;
422 }
423
424 /***
425 * DOCUMENT ME!
426 *
427 * @return DOCUMENT ME!
428 */
429 public int getListenQueue() {
430 return listenQueue;
431 }
432
433 /***
434 * Gets the maxConnectionReply attribute of the IdTCPServer object
435 *
436 *@return The maxConnectionReply value
437 */
438 public RFCReply getMaxConnectionReply() {
439 return maxConnectionReply;
440 }
441
442 /***
443 * Gets the maxConnections attribute of the IdTCPServer object
444 *
445 *@return The maxConnections value
446 */
447 public int getMaxConnections() {
448 return maxConnections;
449 }
450
451 /***
452 * Gets the replyTexts attribute of the IdTCPServer object
453 *
454 *@return The replyTexts value
455 */
456 public RFCReplies getReplyTexts() {
457 return relpyTexts;
458 }
459
460 /***
461 * Gets the threadList attribute of the IdTCPServer object
462 *
463 *@return The threadList value
464 */
465 public List getThreadList() {
466 return threadList;
467 }
468
469 /***
470 * Gets the threadMgr attribute of the IdTCPServer object
471 *
472 *@return The threadMgr value
473 */
474 public PeerThreadManager getThreadManager() {
475 return threadManager;
476 }
477
478 /***
479 * DOCUMENT ME!
480 *
481 * @return DOCUMENT ME!
482 */
483 public boolean isActive() {
484 return active;
485 }
486
487 /***
488 * DOCUMENT ME!
489 *
490 * @param l DOCUMENT ME!
491 */
492 public synchronized void removeTCPServerListener(TCPServerListener l) {
493 if ((TCPServerListeners != null) && TCPServerListeners.contains(l)) {
494 Vector v = (Vector) TCPServerListeners.clone();
495
496 v.removeElement(l);
497 TCPServerListeners = v;
498 }
499 }
500
501 /***
502 * DOCUMENT ME!
503 *
504 * @param l DOCUMENT ME!
505 */
506 public synchronized void addTCPServerListener(TCPServerListener l) {
507 Vector v = (TCPServerListeners == null)
508 ? new Vector(2) : (Vector) TCPServerListeners.clone();
509
510 if (!v.contains(l)) {
511 v.addElement(l);
512 TCPServerListeners = v;
513 }
514 }
515
516 /***
517 * Collection for server listeners that handles syncing on the listener list
518 * on a request by request basis to reduce contention on the list at higher
519 * traffic volumes.
520 *
521 *@author Owen Green
522 *@created 26 September 2002
523 */
524 private class ServerListenerList {
525 private final Collection listenerList = Collections.synchronizedCollection(
526 new HashSet());
527
528 public void add(TCPServerListener l) {
529 listenerList.add(l);
530 }
531
532 public void remove(TCPServerListener l) {
533 listenerList.remove(l);
534 }
535
536 public TCPServerListener[] getArray() {
537 return (TCPServerListener[]) listenerList.toArray(
538 new TCPServerListener[listenerList.size()]);
539 }
540
541 public boolean isEmpty() {
542 return listenerList.isEmpty();
543 }
544 }
545 }
This page was automatically generated by Maven