KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quickserver > net > server > QuickServer


1 /*
2  * This file is part of the QuickServer library
3  * Copyright (C) QuickServer.org
4  *
5  * Use, modification, copying and distribution of this software is subject to
6  * the terms and conditions of the GNU Lesser General Public License.
7  * You should have received a copy of the GNU LGP License along with this
8  * library; if not, you can download a copy from <http://www.quickserver.org/>.
9  *
10  * For questions, suggestions, bug-reports, enhancement-requests etc.
11  * visit http://www.quickserver.org
12  *
13  */

14
15 package org.quickserver.net.server;
16
17 import java.io.*;
18 import java.net.*;
19
20 import org.quickserver.net.*;
21 //v1.1
22
import org.quickserver.net.qsadmin.*;
23 //v1.2
24
import java.util.logging.*;
25 //v1.3
26
import org.quickserver.util.pool.*;
27 import org.quickserver.util.pool.thread.*;
28 import org.apache.commons.pool.*;
29 import org.quickserver.util.xmlreader.*;
30 import org.quickserver.sql.*;
31 //v1.3.1
32
import java.util.*;
33 //v1.3.2
34
import org.quickserver.util.*;
35 import java.util.regex.*;
36 //v1.3.3
37
import org.quickserver.security.*;
38 //v1.4.0
39
import javax.net.ssl.*;
40 import javax.net.*;
41 import java.security.*;
42 import java.security.cert.*;
43 import org.quickserver.util.io.*;
44 //v1.4.5
45
import java.nio.*;
46 import java.nio.channels.*;
47 import org.quickserver.net.server.impl.*;
48
49 /**
50  * Main class of QuickServer library. This class is used to create
51  * multi client servers quickly.
52  * <p>
53  * Ones a client is connected, it creates {@link ClientHandler} object,
54  * which is run using any thread available from the pool of threads
55  * maintained by {@link org.quickserver.util.pool.thread.ClientPool}, which
56  * handles the client. <br/>
57  * QuickServer divides the application logic of its developer over eight
58  * class, <br>
59  * <ul>
60  * <li>ClientEventHandler<br>
61  * &nbsp;Handles client events [Optional Class].
62  * <li>ClientCommandHandler [#]<br>
63  * &nbsp;Handles client character/string commands.
64  * <li>ClientObjectHandler [#]<br>
65  * &nbsp;Handles client interaction - Object commands.
66  * <li>ClientBinaryHandler [#]<br>
67  * &nbsp;Handles client interaction - binary data.
68  * <li>ClientWriteHandler [Optional Class]<br>
69  * &nbsp;Handles client interaction - writing data (Only used in non-blocking mode).
70  * <li>ClientAuthenticationHandler [Optional Class]<br>
71  * &nbsp;Used to Authencatet a client.
72  * <li>ClientData [Optional Class]<br>
73  * &nbsp;Client data carrier (support class)
74  * <li>ClientExtendedEventHandler [Optional Class]<br>
75  * &nbsp;Handles extended client events.
76  * </ul>
77  *
78  * [#] = Any one of these have to be set based on default DataMode for input.
79  * The default DataMode for input is String so if not changes you will
80  * have to set ClientCommandHandler.
81  * </p>
82  * <p>
83  * Eg:
84  * <code><BLOCKQUOTE><pre>
85 package echoserver;
86
87 import org.quickserver.net.*;
88 import org.quickserver.net.server.*;
89
90 import java.io.*;
91
92 public class EchoServer {
93     public static void main(String args[]) {
94         String cmdHandle = "echoserver.EchoCommandHandler";
95     
96         QuickServer myServer = new QuickServer();
97         myServer.setClientCommandHandler(cmdHandle);
98         myServer.setPort(4123);
99         myServer.setName(Echo Server v1.0");
100         try {
101             myServer.startServer();
102         } catch(AppException e) {
103             System.err.println("Error in server : "+e);
104             e.printStackTrace();
105         }
106     }
107 }
108 </pre></BLOCKQUOTE></code></p>
109  *
110  * @version 1.4.7
111  * @author Akshathkumar Shetty
112  */

113 public class QuickServer implements Runnable JavaDoc, Service, Cloneable JavaDoc, Serializable {
114     //Some variable are not initialised to any value because the
115
//default java value was desired initial value.
116

117     //'dev ' = development build not yet final
118
//'beta' = test build all features
119
private final static String JavaDoc VER = "1.4.7";//change also in QSAdminMain
120
private final static String JavaDoc NEW_LINE = "\r\n";
121
122     static {
123         System.out.print("Loading QuickServer v"+getVersion()+" ");
124     }
125
126     private String JavaDoc serverBanner;
127
128     private String JavaDoc clientAuthenticationHandlerString; //v1.4.6
129
private String JavaDoc clientEventHandlerString; //v1.4.6
130
private String JavaDoc clientExtendedEventHandlerString; //v1.4.6
131
private String JavaDoc clientCommandHandlerString;
132     private String JavaDoc clientObjectHandlerString; //v1.2
133
private String JavaDoc clientBinaryHandlerString; //v1.4
134
private String JavaDoc clientWriteHandlerString; //v1.4.5
135
private String JavaDoc clientDataString;
136     
137     private Authenticator authenticator;
138     private ClientAuthenticationHandler clientAuthenticationHandler; //v1.4.6
139
private ClientEventHandler clientEventHandler; //v1.4.6
140
private ClientExtendedEventHandler clientExtendedEventHandler; //v1.4.6
141
private ClientCommandHandler clientCommandHandler;
142     private ClientObjectHandler clientObjectHandler; //v1.2
143
private ClientBinaryHandler clientBinaryHandler; //v1.4
144
private ClientWriteHandler clientWriteHandler; //v1.4.5
145
private ClientData clientData;
146     protected Class JavaDoc clientDataClass;
147
148     private int serverPort = 9876;
149     private Thread JavaDoc t; //Main thread
150
private ServerSocket server;
151     private String JavaDoc serverName = "QuickServer";
152     private long maxConnection = -1;
153     private int socketTimeout = 60 * 1000; //1 min socket timeout
154
private String JavaDoc maxConnectionMsg = "-ERR Server Busy. Max Connection Reached";
155     private String JavaDoc timeoutMsg = "-ERR Timeout";
156     private String JavaDoc maxAuthTryMsg = "-ERR Max Auth Try Reached";
157     private int maxAuthTry = 5; //v1.2
158

159     static {
160         System.out.print(".");
161     }
162
163     //--v1.1
164
private InetAddress ipAddr;
165     private boolean stopServer;
166     private Object JavaDoc[] storeObjects;
167     private QSAdminServer adminServer;
168
169     //--v1.2
170
//Logger for QuickServer
171
private static final Logger logger = Logger.getLogger(QuickServer.class.getName());
172     //Logger for the application using this QuickServer
173
private Logger appLogger;
174
175     //for Service interface
176
private long suspendMaxConnection; //backup
177
private String JavaDoc suspendMaxConnectionMsg; //backup
178
private int serviceState = Service.UNKNOWN;
179
180     static {
181         System.out.print(".");
182     }
183
184     //--v1.3
185
private QuickServerConfig config = new QuickServerConfig();
186     private String JavaDoc consoleLoggingformatter;
187     private String JavaDoc consoleLoggingLevel = "INFO";
188     private ClientPool pool;
189     private ObjectPool clientHandlerPool;
190     private ObjectPool clientDataPool;
191     private DBPoolUtil dBPoolUtil;
192
193     //--v1.3.1
194
private String JavaDoc loggingLevel = "INFO";
195
196     //--v1.3.2
197
private boolean skipValidation = false;
198     private boolean communicationLogging = true;
199
200     //--v1.3.3
201
private String JavaDoc securityManagerClass;
202     private AccessConstraintConfig accessConstraintConfig;
203     private ClassLoader JavaDoc classLoader;
204     private String JavaDoc applicationJarPath;
205     private ServerHooks serverHooks;
206     private ArrayList listOfServerHooks;
207
208     static {
209         System.out.print(".");
210     }
211     
212     //--v1.4.0
213
private Secure secure;
214     private BasicServerConfig basicConfig = config;
215     private SSLContext sslc;
216     private KeyManager km[] = null;
217     private TrustManager tm[] = null;
218     private boolean runningSecure = false;
219     private SecureStoreManager secureStoreManager = null;
220     
221     private Exception JavaDoc exceptionInRun = null;
222
223     //--v1.4.5
224
private ServerSocketChannel serverSocketChannel;
225     private Selector selector;
226     private boolean blockingMode = true;
227     private ObjectPool byteBufferPool;
228     private java.util.Date JavaDoc lastStartTime;
229     private ClientIdentifier clientIdentifier;
230     private GhostSocketReaper ghostSocketReaper;
231     private PoolManager poolManager;
232     private QSObjectPoolMaker qsObjectPoolMaker;
233
234     //--v1.4.6
235
private DataMode defaultDataModeIN = DataMode.STRING;
236     private DataMode defaultDataModeOUT = DataMode.STRING;
237
238     //-v1.4.7
239
private Throwable JavaDoc serviceError;
240     private Map registerChannelRequestMap;
241
242     static {
243         System.out.println(" Done");
244         //should be commented if not a patch release
245
//System.out.println("[Includes patch(#): t=152&p=532]");
246
//should be commented if not a dev release
247
//System.out.println("[Dev Build Date: Saturday, October 29, 2005]");
248
}
249     
250     /** Returns the version of the library. */
251     public static final String JavaDoc getVersion() {
252         return VER;
253     }
254
255     /**
256      * Returns the numerical version of the library.
257      * @since 1.2
258      */

259     public static final float getVersionNo() {
260         return getVersionNo(VER);
261     }
262
263     /**
264      * Returns the numerical version of the library.
265      * @since 1.4.5
266      */

267     public static final float getVersionNo(String JavaDoc ver) {
268         //String ver = getVersion();
269
float version = 0;
270         int i = ver.indexOf(" "); //check if beta
271
if(i == -1)
272             i = ver.length();
273         ver = ver.substring(0, i);
274         
275         i = ver.indexOf("."); //check for sub version
276
if(i!=-1) {
277             int j = ver.indexOf(".", i);
278             if(j!=-1) {
279                 ver = ver.substring(0, i)+"."+
280                     MyString.replaceAll(ver.substring(i+1), ".", "");
281             }
282         }
283
284         try {
285             version = Float.parseFloat(ver);
286         } catch(NumberFormatException JavaDoc e) {
287             throw new RuntimeException JavaDoc("Corrupt QuickServer");
288         }
289         return version;
290     }
291
292     /**
293      * Returns the new line string used by QuickServer.
294      * @since 1.2
295      */

296     public static String JavaDoc getNewLine() {
297         return NEW_LINE;
298     }
299
300     /**
301      * Returns the Server name : port of the QuickServer.
302      */

303     public String JavaDoc toString() {
304         return serverName + " : " + getPort();
305     }
306
307     /**
308      * Creates a new server without any configuration.
309      * Make sure you configure the QuickServer, before
310      * calling startServer()
311      * @see org.quickserver.net.server.ClientEventHandler
312      * @see org.quickserver.net.server.ClientCommandHandler
313      * @see org.quickserver.net.server.ClientObjectHandler
314      * @see org.quickserver.net.server.ClientBinaryHandler
315      * @see org.quickserver.net.server.ClientWriteHandler
316      * @see org.quickserver.net.server.ClientAuthenticationHandler
317      * @see org.quickserver.net.server.ClientHandler
318      * @see #configQuickServer
319      * @see #initService
320      * @see #setPort
321      * @see #setClientCommandHandler
322      * @since 1.2
323      */

324     public QuickServer() {
325     }
326
327     /**
328      * Creates a new server with the specified
329      * <code>commandHandler</code> has it {@link ClientCommandHandler}.
330      * @param commandHandler the fully qualified name of the
331      * desired class that implements {@link ClientCommandHandler}
332      *
333      * @see org.quickserver.net.server.ClientCommandHandler
334      * @see org.quickserver.net.server.ClientAuthenticationHandler
335      * @see org.quickserver.net.server.ClientHandler
336      * @see #setPort
337      */

338     public QuickServer(String JavaDoc commandHandler) {
339         setClientCommandHandler(commandHandler);
340     }
341
342     /**
343      * Creates a new server at <code>port</code> with the specified
344      * <code>commandHandler</code> has it {@link ClientCommandHandler}.
345      *
346      * @param commandHandler fully qualified name of the class that
347      * implements {@link ClientCommandHandler}
348      * @param port to listen on.
349      *
350      * @see org.quickserver.net.server.ClientCommandHandler
351      * @see org.quickserver.net.server.ClientAuthenticationHandler
352      * @see org.quickserver.net.server.ClientHandler
353      */

354     public QuickServer(String JavaDoc commandHandler,int port) {
355         this(commandHandler); //send to another constructor
356
setPort(port);
357     }
358
359     /**
360      * Starts the QuickServer.
361      *
362      * @exception org.quickserver.net.AppException
363      * if Server already running or if it could not load the classes
364      * [ClientCommandHandler, ClientAuthenticationHandler, ClientData].
365      * @see #startService
366      */

367     public void startServer() throws AppException {
368         logger.fine("Starting "+getName());
369
370         if(isClosed() == false) {
371             logger.warning("Server "+getName()+" already running.");
372             throw new AppException("Server "+getName()+" already running.");
373         }
374         
375         if(serverBanner == null) {
376             serverBanner = "\n-------------------------------" +
377                            "\n Name : " + getName() +
378                            "\n Port : " + getPort() +
379                            "\n-------------------------------\n";
380             logger.finest("Default Server Banner Generated");
381         }
382         try {
383             loadApplicationClasses();
384
385             //load class from Advanced Settings
386
Class JavaDoc clientIdentifierClass =
387                 getClass(getBasicConfig().getAdvancedSettings().getClientIdentifier(), true);
388             clientIdentifier = (ClientIdentifier)
389                 clientIdentifierClass.newInstance();
390             clientIdentifier.setQuickServer(QuickServer.this);
391
392             //load class from ObjectPoolConfig
393
Class JavaDoc poolManagerClass =
394                 getClass(getBasicConfig().getObjectPoolConfig().getPoolManager(), true);
395             poolManager = (PoolManager) poolManagerClass.newInstance();
396
397             //load class QSObjectPoolMaker
398
Class JavaDoc qsObjectPoolMakerClass = getClass(
399                 getBasicConfig().getAdvancedSettings().getQSObjectPoolMaker(), true);
400             qsObjectPoolMaker = (QSObjectPoolMaker) qsObjectPoolMakerClass.newInstance();
401
402             loadServerHooksClasses();
403             processServerHooks(ServerHook.PRE_STARTUP);
404             
405             if(getSecure().isLoad()==true)
406                 loadSSLContext(); //v1.4.0
407

408             loadBusinessLogic();
409         } catch(ClassNotFoundException JavaDoc e) {
410             logger.severe("Could not load class/s : " + e.getMessage());
411             throw new AppException("Could not load class/s : " + e.getMessage());
412         } catch(InstantiationException JavaDoc e) {
413             logger.severe("Could not instantiate class/s : " + e.getMessage());
414             throw new AppException("Could not instantiate class/s : "+e.getMessage());
415         } catch(IllegalAccessException JavaDoc e) {
416             logger.severe("Illegal access to class/s : " + e.getMessage());
417             throw new AppException("Illegal access to class/s : " + e.getMessage());
418         } catch(IOException e) {
419             logger.severe("IOException : " + e.getMessage());
420             logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
421             throw new AppException("IOException : " + e.getMessage());
422         } catch(Exception JavaDoc e) {
423             logger.severe("Exception : " + e.getMessage());
424             logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
425             throw new AppException("Exception : " + e);
426         }
427
428         //v1.3.3
429
if(getSecurityManagerClass()!=null) {
430             System.setSecurityManager(getSecurityManager());
431         }
432         
433         blockingMode = getBasicConfig().getServerMode().getBlocking();
434
435         setServiceState(Service.INIT);
436         t = new Thread JavaDoc(this, "QuickServer - "+getName());
437         t.start();
438
439         do {
440             Thread.yield();
441         } while(getServiceState()==Service.INIT);
442
443         if(getServiceState()!=Service.RUNNING) {
444             if(exceptionInRun!=null)
445                 throw new AppException("Could not start server "+getName()
446                     +"! Details: "+exceptionInRun);
447             else
448                 throw new AppException("Could not start server "+getName());
449         }
450         lastStartTime = new java.util.Date JavaDoc();
451         logger.fine("Started "+getName()+", Date: "+lastStartTime);
452     }
453
454     /**
455      * Stops the QuickServer.
456      *
457      * @exception org.quickserver.net.AppException
458      * if could not stop server
459      * @since 1.1
460      * @see #stopService
461      */

462     public void stopServer() throws AppException {
463         processServerHooks(ServerHook.PRE_SHUTDOWN);
464         logger.warning("Stopping "+getName());
465         stopServer = true;
466         Socket death = null;
467         if(isClosed()==true) {
468             logger.warning("Server "+getName()+" is not running!");
469             throw new AppException("Server "+getName()+" is not running!");
470         }
471         try {
472             if(getBlockingMode()==true) {
473                 if(getSecure().isEnable()==false) {
474                     death = new Socket(server.getInetAddress(),
475                         server.getLocalPort());
476                     death.getInputStream().read();
477                     death.close();
478                 } else {
479                     death = getSSLSocketFactory().createSocket(
480                         server.getInetAddress(), server.getLocalPort());
481                     Thread.currentThread().sleep(100);
482                     death.close();
483                 }
484             }
485
486             if(serverSocketChannel!=null) {
487                 serverSocketChannel.close();
488             }
489
490         } catch(IOException e){
491             logger.fine("IOError stopping "+getName()+": "+e);
492         } catch(Exception JavaDoc e){
493             logger.warning("Error stopping "+getName()+": "+e);
494             throw new AppException("Error in stopServer "+getName()+": "+e);
495         }
496
497         for(int i=0;getServiceState()!=Service.STOPPED;i++) {
498             try {
499                 Thread.sleep(60);
500             } catch(Exception JavaDoc e) {
501                 logger.warning("Error waiting for "+getName()+" to fully stop. Error: "+e);
502             }
503             if(i>1000) {
504                 logger.severe("Server was not stopped even after 10sec.. will terminate now.");
505                 System.exit(-1);
506             }
507         }
508         if(adminServer==null || getQSAdminServer().getServer()!=this) {
509             //so this is not qsadmin
510
setClassLoader(null);
511         }
512         logger.info("Stopped "+getName());
513     }
514
515     /**
516      * Restarts the QuickServer.
517      *
518      * @exception org.quickserver.net.AppException
519      * if could not stop server or if it could not start the server.
520      * @since 1.2
521      */

522     public void restartServer() throws AppException {
523         stopServer();
524         startServer();
525     }
526
527     /**
528      * Returns the name of the QuickServer. Default is 'QuickServer'.
529      * @see #setName
530      */

531     public String JavaDoc getName() {
532         return serverName;
533     }
534     /**
535      * Sets the name for the QuickServer
536      * @param name for the QuickServer
537      * @see #getName
538      */

539     public void setName(String JavaDoc name) {
540         serverName = name;
541         logger.finest("Set to : "+name);
542     }
543
544     /**
545      * Returns the Server Banner of the QuickServer
546      * @see #setServerBanner
547      */

548     public String JavaDoc getServerBanner() {
549         return serverBanner;
550     }
551     /**
552      * Sets the serverBanner for the QuickServer
553      * that will be displayed on the standard output [console]
554      * when server starts. <br>&nbsp;<br>
555      * To set welcome message to your client
556      * {@link ClientEventHandler#gotConnected}
557      * @param banner for the QuickServer
558      * @see #getServerBanner
559      */

560     public void setServerBanner(String JavaDoc banner) {
561         serverBanner = banner;
562         logger.finest("Set to : "+banner);
563     }
564
565     /**
566      * Sets the port for the QuickServer to listen on.
567      * If not set, it will run on Port 9876
568      * @param port to listen on.
569      * @see #getPort
570      */

571     public void setPort(int port) {
572         if(port<0) {
573             throw new IllegalArgumentException JavaDoc("Port number can not be less than 0!");
574         }
575         serverPort=port;
576         logger.finest("Set to "+port);
577     }
578     /**
579      * Returns the port for the QuickServer.
580      * @see #setPort
581      */

582     public int getPort() {
583         if(isClosed()==false) {
584             return server.getLocalPort();
585         }
586
587         if(getSecure().isEnable()==false) {
588             return serverPort;
589         } else {
590             int _port = getSecure().getPort();
591             if(_port == -1)
592                 return serverPort;
593             else
594                 return _port;
595         }
596     }
597
598     /**
599      * Sets the ClientCommandHandler class that interacts with
600      * client sockets.
601      * @param handler the fully qualified name of the class that
602      * implements {@link ClientCommandHandler}
603      * @see #getClientCommandHandler
604      */

605     public void setClientCommandHandler(String JavaDoc handler) {
606         clientCommandHandlerString = handler;
607         logger.finest("Set to "+handler);
608     }
609     /**
610      * Returns the ClientCommandHandler class that interacts with
611      * client sockets.
612      * @see #setClientCommandHandler
613      * @since 1.1
614      */

615     public String JavaDoc getClientCommandHandler() {
616         return clientCommandHandlerString;
617     }
618
619     /**
620      * Sets the ClientAuthenticationHandler class that
621      * handles the authentication of a client.
622      * @param authenticator the fully qualified name of the class
623      * that implements {@link ClientAuthenticationHandler}.
624      * @see #getClientAuthenticationHandler
625      * @since 1.4.6
626      */

627     public void setClientAuthenticationHandler(String JavaDoc authenticator) {
628         clientAuthenticationHandlerString = authenticator;
629         logger.finest("Set to "+authenticator);
630     }
631     /**
632      * Returns the ClientAuthenticationHandler class that
633      * handles the authentication of a client.
634      * @see #setClientAuthenticationHandler
635      * @since 1.4.6
636      */

637     public String JavaDoc getClientAuthenticationHandler() {
638         return clientAuthenticationHandlerString;
639     }
640
641     /**
642      * Sets the Authenticator class that
643      * handles the authentication of a client.
644      * @param authenticator the fully qualified name of the class
645      * that implements {@link Authenticator} or {@link ClientAuthenticationHandler}.
646      * @see #getAuthenticator
647      * @deprecated since 1.4.6 use setClientAuthenticationHandler
648      * @since 1.3
649      */

650     public void setAuthenticator(String JavaDoc authenticator) {
651         clientAuthenticationHandlerString = authenticator;
652         logger.finest("Set to "+authenticator);
653     }
654     /**
655      * Returns the Authenticator class that
656      * handles the authentication of a client.
657      * @see #setAuthenticator
658      * @deprecated since 1.4.6 use getClientAuthenticationHandler
659      * @since 1.3
660      */

661     public String JavaDoc getAuthenticator() {
662         return clientAuthenticationHandlerString;
663     }
664
665     /**
666      * Sets the ClientData class that carries client data.
667      * @param data the fully qualified name of the class that
668      * extends {@link ClientData}.
669      * @see #getClientData
670      */

671     public void setClientData(String JavaDoc data) {
672         this.clientDataString = data;
673         logger.finest("Set to "+data);
674     }
675     /**
676      * Returns the ClientData class string that carries client data
677      * @return the fully qualified name of the class that
678      * implements {@link ClientData}.
679      * @see #setClientData
680      */

681     public String JavaDoc getClientData() {
682         return clientDataString;
683     }
684
685     /**
686      * Sets the client socket's timeout.
687      * @param time client socket timeout in milliseconds.
688      * @see #getTimeout
689      */

690     public void setTimeout(int time) {
691         if(time>0)
692             socketTimeout = time;
693         else
694             socketTimeout = 0;
695         logger.finest("Set to "+socketTimeout);
696     }
697     /**
698      * Returns the Client socket timeout in milliseconds.
699      * @see #setTimeout
700      */

701     public int getTimeout() {
702         return socketTimeout;
703     }
704
705     /**
706      * Sets max allowed login attempts.
707      * @since 1.2
708      * @see #getMaxAuthTry
709      */

710     public void setMaxAuthTry(int authTry) {
711         maxAuthTry = authTry;
712         logger.finest("Set to "+authTry);
713     }
714     /**
715      * Returns max allowed login attempts. Default is <code>5</code>.
716      * @since 1.2
717      * @see #setMaxAuthTry
718      */

719     public int getMaxAuthTry() {
720         return maxAuthTry;
721     }
722
723     /**
724      * Sets message to be displayed when maximum allowed login
725      * attempts has reached.
726      * Default is : -ERR Max Auth Try Reached
727      * @see #getMaxAuthTryMsg
728      */

729     public void setMaxAuthTryMsg(String JavaDoc msg) {
730         maxAuthTryMsg = msg;
731         logger.finest("Set to "+msg);
732     }
733     /**
734      * Returns message to be displayed when maximum allowed login
735      * attempts has reached.
736      * @see #getMaxAuthTryMsg
737      */

738     public String JavaDoc getMaxAuthTryMsg() {
739         return maxAuthTryMsg;
740     }
741
742     /**
743      * Sets timeout message.
744      * Default is : -ERR Timeout
745      * @see #getTimeoutMsg
746      */

747     public void setTimeoutMsg(String JavaDoc msg) {
748         timeoutMsg = msg;
749         logger.finest("Set to "+msg);
750     }
751     /**
752      * Returns timeout message.
753      * @see #setTimeoutMsg
754      */

755     public String JavaDoc getTimeoutMsg() {
756         return timeoutMsg;
757     }
758
759     private TheClient initTheClient() {
760         TheClient theClient = new TheClient();
761         theClient.setServer(QuickServer.this);
762         theClient.setTimeoutMsg(getTimeoutMsg());
763         theClient.setMaxAuthTry(getMaxAuthTry()); //v1.2
764
theClient.setMaxAuthTryMsg(getMaxAuthTryMsg());
765         
766         theClient.setClientEventHandler(clientEventHandler);
767         theClient.setClientExtendedEventHandler(clientExtendedEventHandler); //v1.4.6
768
theClient.setClientCommandHandler(clientCommandHandler);
769         theClient.setClientObjectHandler(clientObjectHandler); //v1.2
770
theClient.setClientBinaryHandler(clientBinaryHandler); //v1.4
771
theClient.setClientWriteHandler(clientWriteHandler); //v1.4.5
772
theClient.setAuthenticator(authenticator); //v1.3
773
theClient.setClientAuthenticationHandler(clientAuthenticationHandler); //v1.4.6
774
theClient.setTimeout(socketTimeout);
775         theClient.setMaxConnectionMsg(maxConnectionMsg);
776         theClient.setCommunicationLogging(getCommunicationLogging()); //v1.3.2
777
return theClient;
778     }
779
780     public void run() {
781         exceptionInRun = null;
782         TheClient theClient = initTheClient();
783         try {
784             stopServer = false;
785
786             closeAllPools();
787             initAllPools();
788             
789             makeServerSocket();
790             System.out.println(serverBanner); //print banner
791
setServiceState(Service.RUNNING); //v1.2
792

793             processServerHooks(ServerHook.POST_STARTUP); //v1.3.3
794
if(getBlockingMode()==false) {
795                 runNonBlocking(theClient);
796                 if(stopServer==true) {
797                     logger.finest("Closing selector for "+getName());
798                     selector.close();
799                 }
800                 return;
801             } else {
802                 runBlocking(theClient);
803             }
804         } catch(BindException e) {
805             exceptionInRun = e;
806             logger.severe(getName()+" BindException for Port "+getPort()+" @ "+
807                 getBindAddr().getHostAddress()+" : "+e.getMessage());
808         } catch(javax.net.ssl.SSLException e) {
809             exceptionInRun = e;
810             logger.severe("SSLException "+e);
811             logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
812         } catch(IOException e) {
813             exceptionInRun = e;
814             logger.severe("IOError "+e);
815             logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
816         } catch(Exception JavaDoc e) {
817             exceptionInRun = e;
818             logger.severe("Error "+e);
819             logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
820         } finally {
821             if(getBlockingMode()==true) {
822                 logger.warning("Closing "+getName());
823                 try {
824                     if(isClosed()==false) {
825                         server.close();
826                     }
827                 } catch(Exception JavaDoc e){
828                     throw new RuntimeException JavaDoc(e);
829                 }
830                 server = null;
831                 serverSocketChannel = null;
832
833                 setServiceState(Service.STOPPED);
834                 logger.warning("Closed "+getName());
835
836                 processServerHooks(ServerHook.POST_SHUTDOWN);
837             } else if(getBlockingMode()==false && exceptionInRun!=null) {
838                 logger.warning("Closing "+getName()+" - Had Error: "+exceptionInRun);
839                 try {
840                     if(isClosed()==false) {
841                         if(serverSocketChannel!=null)
842                             serverSocketChannel.close();
843                         if(server!=null)
844                             server.close();
845                     }
846                 } catch(Exception JavaDoc e){
847                     throw new RuntimeException JavaDoc(e);
848                 }
849
850                 server = null;
851                 serverSocketChannel = null;
852
853                 setServiceState(Service.STOPPED);
854                 logger.warning("Closed "+getName());
855
856                 processServerHooks(ServerHook.POST_SHUTDOWN);
857             }
858         }
859     } //end of run
860

861     /**
862      * Sets the maximum number of client connection allowed.
863      * @since 1.1
864      * @see #getMaxConnection
865      */

866     public void setMaxConnection(long maxConnection) {
867         if(getServiceState()==Service.SUSPENDED)
868             suspendMaxConnection = maxConnection;
869         else
870             this.maxConnection = maxConnection;
871         logger.finest("Set to "+maxConnection);
872     }
873     /**
874      * Returns the maximum number of client connection allowed.
875      * @since 1.1
876      * @see #setMaxConnection
877      */

878     public long getMaxConnection() {
879         return maxConnection;
880     }
881
882     /**
883      * Returns number of clients connected.
884      * @since 1.1
885      */

886     public long getClientCount() {
887         if(clientHandlerPool != null) {
888             try {
889                 return getClientHandlerPool().getNumActive();
890             } catch(Exception JavaDoc e) {
891                 return 0;
892             }
893         }
894         return 0;
895     }
896
897