0001: /*
0002: * This file is part of the QuickServer library
0003: * Copyright (C) QuickServer.org
0004: *
0005: * Use, modification, copying and distribution of this software is subject to
0006: * the terms and conditions of the GNU Lesser General Public License.
0007: * You should have received a copy of the GNU LGP License along with this
0008: * library; if not, you can download a copy from <http://www.quickserver.org/>.
0009: *
0010: * For questions, suggestions, bug-reports, enhancement-requests etc.
0011: * visit http://www.quickserver.org
0012: *
0013: */
0014:
0015: package org.quickserver.net.server;
0016:
0017: import java.io.*;
0018: import java.net.*;
0019:
0020: import org.quickserver.net.*; //v1.1
0021: import org.quickserver.net.qsadmin.*; //v1.2
0022: import java.util.logging.*; //v1.3
0023: import org.quickserver.util.pool.*;
0024: import org.quickserver.util.pool.thread.*;
0025: import org.apache.commons.pool.*;
0026: import org.quickserver.util.xmlreader.*;
0027: import org.quickserver.sql.*; //v1.3.1
0028: import java.util.*; //v1.3.2
0029: import org.quickserver.util.*;
0030: import java.util.regex.*; //v1.3.3
0031: import org.quickserver.security.*; //v1.4.0
0032: import javax.net.ssl.*;
0033: import javax.net.*;
0034: import java.security.*;
0035: import java.security.cert.*;
0036: import org.quickserver.util.io.*; //v1.4.5
0037: import java.nio.*;
0038: import java.nio.channels.*;
0039: import org.quickserver.net.server.impl.*;
0040:
0041: /**
0042: * Main class of QuickServer library. This class is used to create
0043: * multi client servers quickly.
0044: * <p>
0045: * Ones a client is connected, it creates {@link ClientHandler} object,
0046: * which is run using any thread available from the pool of threads
0047: * maintained by {@link org.quickserver.util.pool.thread.ClientPool}, which
0048: * handles the client. <br/>
0049: * QuickServer divides the application logic of its developer over eight
0050: * class, <br>
0051: * <ul>
0052: * <li>ClientEventHandler<br>
0053: * Handles client events [Optional Class].
0054: * <li>ClientCommandHandler [#]<br>
0055: * Handles client character/string commands.
0056: * <li>ClientObjectHandler [#]<br>
0057: * Handles client interaction - Object commands.
0058: * <li>ClientBinaryHandler [#]<br>
0059: * Handles client interaction - binary data.
0060: * <li>ClientWriteHandler [Optional Class]<br>
0061: * Handles client interaction - writing data (Only used in non-blocking mode).
0062: * <li>ClientAuthenticationHandler [Optional Class]<br>
0063: * Used to Authencatet a client.
0064: * <li>ClientData [Optional Class]<br>
0065: * Client data carrier (support class)
0066: * <li>ClientExtendedEventHandler [Optional Class]<br>
0067: * Handles extended client events.
0068: * </ul>
0069: *
0070: * [#] = Any one of these have to be set based on default DataMode for input.
0071: * The default DataMode for input is String so if not changes you will
0072: * have to set ClientCommandHandler.
0073: * </p>
0074: * <p>
0075: * Eg:
0076: * <code><BLOCKQUOTE><pre>
0077: package echoserver;
0078:
0079: import org.quickserver.net.*;
0080: import org.quickserver.net.server.*;
0081:
0082: import java.io.*;
0083:
0084: public class EchoServer {
0085: public static void main(String args[]) {
0086: String cmdHandle = "echoserver.EchoCommandHandler";
0087:
0088: QuickServer myServer = new QuickServer();
0089: myServer.setClientCommandHandler(cmdHandle);
0090: myServer.setPort(4123);
0091: myServer.setName(Echo Server v1.0");
0092: try {
0093: myServer.startServer();
0094: } catch(AppException e) {
0095: System.err.println("Error in server : "+e);
0096: e.printStackTrace();
0097: }
0098: }
0099: }
0100: </pre></BLOCKQUOTE></code></p>
0101: *
0102: * @version 1.4.7
0103: * @author Akshathkumar Shetty
0104: */
0105: public class QuickServer implements Runnable, Service, Cloneable,
0106: Serializable {
0107: //Some variable are not initialised to any value because the
0108: //default java value was desired initial value.
0109:
0110: //'dev ' = development build not yet final
0111: //'beta' = test build all features
0112: private final static String VER = "1.4.7";//change also in QSAdminMain
0113: private final static String NEW_LINE = "\r\n";
0114:
0115: static {
0116: System.out.print("Loading QuickServer v" + getVersion() + " ");
0117: }
0118:
0119: private String serverBanner;
0120:
0121: private String clientAuthenticationHandlerString; //v1.4.6
0122: private String clientEventHandlerString; //v1.4.6
0123: private String clientExtendedEventHandlerString; //v1.4.6
0124: private String clientCommandHandlerString;
0125: private String clientObjectHandlerString; //v1.2
0126: private String clientBinaryHandlerString; //v1.4
0127: private String clientWriteHandlerString; //v1.4.5
0128: private String clientDataString;
0129:
0130: private Authenticator authenticator;
0131: private ClientAuthenticationHandler clientAuthenticationHandler; //v1.4.6
0132: private ClientEventHandler clientEventHandler; //v1.4.6
0133: private ClientExtendedEventHandler clientExtendedEventHandler; //v1.4.6
0134: private ClientCommandHandler clientCommandHandler;
0135: private ClientObjectHandler clientObjectHandler; //v1.2
0136: private ClientBinaryHandler clientBinaryHandler; //v1.4
0137: private ClientWriteHandler clientWriteHandler; //v1.4.5
0138: private ClientData clientData;
0139: protected Class clientDataClass;
0140:
0141: private int serverPort = 9876;
0142: private Thread t; //Main thread
0143: private ServerSocket server;
0144: private String serverName = "QuickServer";
0145: private long maxConnection = -1;
0146: private int socketTimeout = 60 * 1000; //1 min socket timeout
0147: private String maxConnectionMsg = "-ERR Server Busy. Max Connection Reached";
0148: private String timeoutMsg = "-ERR Timeout";
0149: private String maxAuthTryMsg = "-ERR Max Auth Try Reached";
0150: private int maxAuthTry = 5; //v1.2
0151:
0152: static {
0153: System.out.print(".");
0154: }
0155:
0156: //--v1.1
0157: private InetAddress ipAddr;
0158: private boolean stopServer;
0159: private Object[] storeObjects;
0160: private QSAdminServer adminServer;
0161:
0162: //--v1.2
0163: //Logger for QuickServer
0164: private static final Logger logger = Logger
0165: .getLogger(QuickServer.class.getName());
0166: //Logger for the application using this QuickServer
0167: private Logger appLogger;
0168:
0169: //for Service interface
0170: private long suspendMaxConnection; //backup
0171: private String suspendMaxConnectionMsg; //backup
0172: private int serviceState = Service.UNKNOWN;
0173:
0174: static {
0175: System.out.print(".");
0176: }
0177:
0178: //--v1.3
0179: private QuickServerConfig config = new QuickServerConfig();
0180: private String consoleLoggingformatter;
0181: private String consoleLoggingLevel = "INFO";
0182: private ClientPool pool;
0183: private ObjectPool clientHandlerPool;
0184: private ObjectPool clientDataPool;
0185: private DBPoolUtil dBPoolUtil;
0186:
0187: //--v1.3.1
0188: private String loggingLevel = "INFO";
0189:
0190: //--v1.3.2
0191: private boolean skipValidation = false;
0192: private boolean communicationLogging = true;
0193:
0194: //--v1.3.3
0195: private String securityManagerClass;
0196: private AccessConstraintConfig accessConstraintConfig;
0197: private ClassLoader classLoader;
0198: private String applicationJarPath;
0199: private ServerHooks serverHooks;
0200: private ArrayList listOfServerHooks;
0201:
0202: static {
0203: System.out.print(".");
0204: }
0205:
0206: //--v1.4.0
0207: private Secure secure;
0208: private BasicServerConfig basicConfig = config;
0209: private SSLContext sslc;
0210: private KeyManager km[] = null;
0211: private TrustManager tm[] = null;
0212: private boolean runningSecure = false;
0213: private SecureStoreManager secureStoreManager = null;
0214:
0215: private Exception exceptionInRun = null;
0216:
0217: //--v1.4.5
0218: private ServerSocketChannel serverSocketChannel;
0219: private Selector selector;
0220: private boolean blockingMode = true;
0221: private ObjectPool byteBufferPool;
0222: private java.util.Date lastStartTime;
0223: private ClientIdentifier clientIdentifier;
0224: private GhostSocketReaper ghostSocketReaper;
0225: private PoolManager poolManager;
0226: private QSObjectPoolMaker qsObjectPoolMaker;
0227:
0228: //--v1.4.6
0229: private DataMode defaultDataModeIN = DataMode.STRING;
0230: private DataMode defaultDataModeOUT = DataMode.STRING;
0231:
0232: //-v1.4.7
0233: private Throwable serviceError;
0234: private Map registerChannelRequestMap;
0235:
0236: static {
0237: System.out.println(" Done");
0238: //should be commented if not a patch release
0239: //System.out.println("[Includes patch(#): t=152&p=532]");
0240: //should be commented if not a dev release
0241: //System.out.println("[Dev Build Date: Saturday, October 29, 2005]");
0242: }
0243:
0244: /** Returns the version of the library. */
0245: public static final String getVersion() {
0246: return VER;
0247: }
0248:
0249: /**
0250: * Returns the numerical version of the library.
0251: * @since 1.2
0252: */
0253: public static final float getVersionNo() {
0254: return getVersionNo(VER);
0255: }
0256:
0257: /**
0258: * Returns the numerical version of the library.
0259: * @since 1.4.5
0260: */
0261: public static final float getVersionNo(String ver) {
0262: //String ver = getVersion();
0263: float version = 0;
0264: int i = ver.indexOf(" "); //check if beta
0265: if (i == -1)
0266: i = ver.length();
0267: ver = ver.substring(0, i);
0268:
0269: i = ver.indexOf("."); //check for sub version
0270: if (i != -1) {
0271: int j = ver.indexOf(".", i);
0272: if (j != -1) {
0273: ver = ver.substring(0, i)
0274: + "."
0275: + MyString.replaceAll(ver.substring(i + 1),
0276: ".", "");
0277: }
0278: }
0279:
0280: try {
0281: version = Float.parseFloat(ver);
0282: } catch (NumberFormatException e) {
0283: throw new RuntimeException("Corrupt QuickServer");
0284: }
0285: return version;
0286: }
0287:
0288: /**
0289: * Returns the new line string used by QuickServer.
0290: * @since 1.2
0291: */
0292: public static String getNewLine() {
0293: return NEW_LINE;
0294: }
0295:
0296: /**
0297: * Returns the Server name : port of the QuickServer.
0298: */
0299: public String toString() {
0300: return serverName + " : " + getPort();
0301: }
0302:
0303: /**
0304: * Creates a new server without any configuration.
0305: * Make sure you configure the QuickServer, before
0306: * calling startServer()
0307: * @see org.quickserver.net.server.ClientEventHandler
0308: * @see org.quickserver.net.server.ClientCommandHandler
0309: * @see org.quickserver.net.server.ClientObjectHandler
0310: * @see org.quickserver.net.server.ClientBinaryHandler
0311: * @see org.quickserver.net.server.ClientWriteHandler
0312: * @see org.quickserver.net.server.ClientAuthenticationHandler
0313: * @see org.quickserver.net.server.ClientHandler
0314: * @see #configQuickServer
0315: * @see #initService
0316: * @see #setPort
0317: * @see #setClientCommandHandler
0318: * @since 1.2
0319: */
0320: public QuickServer() {
0321: }
0322:
0323: /**
0324: * Creates a new server with the specified
0325: * <code>commandHandler</code> has it {@link ClientCommandHandler}.
0326: * @param commandHandler the fully qualified name of the
0327: * desired class that implements {@link ClientCommandHandler}
0328: *
0329: * @see org.quickserver.net.server.ClientCommandHandler
0330: * @see org.quickserver.net.server.ClientAuthenticationHandler
0331: * @see org.quickserver.net.server.ClientHandler
0332: * @see #setPort
0333: */
0334: public QuickServer(String commandHandler) {
0335: setClientCommandHandler(commandHandler);
0336: }
0337:
0338: /**
0339: * Creates a new server at <code>port</code> with the specified
0340: * <code>commandHandler</code> has it {@link ClientCommandHandler}.
0341: *
0342: * @param commandHandler fully qualified name of the class that
0343: * implements {@link ClientCommandHandler}
0344: * @param port to listen on.
0345: *
0346: * @see org.quickserver.net.server.ClientCommandHandler
0347: * @see org.quickserver.net.server.ClientAuthenticationHandler
0348: * @see org.quickserver.net.server.ClientHandler
0349: */
0350: public QuickServer(String commandHandler, int port) {
0351: this (commandHandler); //send to another constructor
0352: setPort(port);
0353: }
0354:
0355: /**
0356: * Starts the QuickServer.
0357: *
0358: * @exception org.quickserver.net.AppException
0359: * if Server already running or if it could not load the classes
0360: * [ClientCommandHandler, ClientAuthenticationHandler, ClientData].
0361: * @see #startService
0362: */
0363: public void startServer() throws AppException {
0364: logger.fine("Starting " + getName());
0365:
0366: if (isClosed() == false) {
0367: logger.warning("Server " + getName() + " already running.");
0368: throw new AppException("Server " + getName()
0369: + " already running.");
0370: }
0371:
0372: if (serverBanner == null) {
0373: serverBanner = "\n-------------------------------"
0374: + "\n Name : " + getName() + "\n Port : "
0375: + getPort() + "\n-------------------------------\n";
0376: logger.finest("Default Server Banner Generated");
0377: }
0378: try {
0379: loadApplicationClasses();
0380:
0381: //load class from Advanced Settings
0382: Class clientIdentifierClass = getClass(getBasicConfig()
0383: .getAdvancedSettings().getClientIdentifier(), true);
0384: clientIdentifier = (ClientIdentifier) clientIdentifierClass
0385: .newInstance();
0386: clientIdentifier.setQuickServer(QuickServer.this );
0387:
0388: //load class from ObjectPoolConfig
0389: Class poolManagerClass = getClass(getBasicConfig()
0390: .getObjectPoolConfig().getPoolManager(), true);
0391: poolManager = (PoolManager) poolManagerClass.newInstance();
0392:
0393: //load class QSObjectPoolMaker
0394: Class qsObjectPoolMakerClass = getClass(getBasicConfig()
0395: .getAdvancedSettings().getQSObjectPoolMaker(), true);
0396: qsObjectPoolMaker = (QSObjectPoolMaker) qsObjectPoolMakerClass
0397: .newInstance();
0398:
0399: loadServerHooksClasses();
0400: processServerHooks(ServerHook.PRE_STARTUP);
0401:
0402: if (getSecure().isLoad() == true)
0403: loadSSLContext(); //v1.4.0
0404:
0405: loadBusinessLogic();
0406: } catch (ClassNotFoundException e) {
0407: logger.severe("Could not load class/s : " + e.getMessage());
0408: throw new AppException("Could not load class/s : "
0409: + e.getMessage());
0410: } catch (InstantiationException e) {
0411: logger.severe("Could not instantiate class/s : "
0412: + e.getMessage());
0413: throw new AppException("Could not instantiate class/s : "
0414: + e.getMessage());
0415: } catch (IllegalAccessException e) {
0416: logger.severe("Illegal access to class/s : "
0417: + e.getMessage());
0418: throw new AppException("Illegal access to class/s : "
0419: + e.getMessage());
0420: } catch (IOException e) {
0421: logger.severe("IOException : " + e.getMessage());
0422: logger.fine("StackTrace:\n" + MyString.getStackTrace(e));
0423: throw new AppException("IOException : " + e.getMessage());
0424: } catch (Exception e) {
0425: logger.severe("Exception : " + e.getMessage());
0426: logger.fine("StackTrace:\n" + MyString.getStackTrace(e));
0427: throw new AppException("Exception : " + e);
0428: }
0429:
0430: //v1.3.3
0431: if (getSecurityManagerClass() != null) {
0432: System.setSecurityManager(getSecurityManager());
0433: }
0434:
0435: blockingMode = getBasicConfig().getServerMode().getBlocking();
0436:
0437: setServiceState(Service.INIT);
0438: t = new Thread(this , "QuickServer - " + getName());
0439: t.start();
0440:
0441: do {
0442: Thread.yield();
0443: } while (getServiceState() == Service.INIT);
0444:
0445: if (getServiceState() != Service.RUNNING) {
0446: if (exceptionInRun != null)
0447: throw new AppException("Could not start server "
0448: + getName() + "! Details: " + exceptionInRun);
0449: else
0450: throw new AppException("Could not start server "
0451: + getName());
0452: }
0453: lastStartTime = new java.util.Date();
0454: logger
0455: .fine("Started " + getName() + ", Date: "
0456: + lastStartTime);
0457: }
0458:
0459: /**
0460: * Stops the QuickServer.
0461: *
0462: * @exception org.quickserver.net.AppException
0463: * if could not stop server
0464: * @since 1.1
0465: * @see #stopService
0466: */
0467: public void stopServer() throws AppException {
0468: processServerHooks(ServerHook.PRE_SHUTDOWN);
0469: logger.warning("Stopping " + getName());
0470: stopServer = true;
0471: Socket death = null;
0472: if (isClosed() == true) {
0473: logger.warning("Server " + getName() + " is not running!");
0474: throw new AppException("Server " + getName()
0475: + " is not running!");
0476: }
0477: try {
0478: if (getBlockingMode() == true) {
0479: if (getSecure().isEnable() == false) {
0480: death = new Socket(server.getInetAddress(), server
0481: .getLocalPort());
0482: death.getInputStream().read();
0483: death.close();
0484: } else {
0485: death = getSSLSocketFactory().createSocket(
0486: server.getInetAddress(),
0487: server.getLocalPort());
0488: Thread.currentThread().sleep(100);
0489: death.close();
0490: }
0491: }
0492:
0493: if (serverSocketChannel != null) {
0494: serverSocketChannel.close();
0495: }
0496:
0497: } catch (IOException e) {
0498: logger.fine("IOError stopping " + getName() + ": " + e);
0499: } catch (Exception e) {
0500: logger.warning("Error stopping " + getName() + ": " + e);
0501: throw new AppException("Error in stopServer " + getName()
0502: + ": " + e);
0503: }
0504:
0505: for (int i = 0; getServiceState() != Service.STOPPED; i++) {
0506: try {
0507: Thread.sleep(60);
0508: } catch (Exception e) {
0509: logger.warning("Error waiting for " + getName()
0510: + " to fully stop. Error: " + e);
0511: }
0512: if (i > 1000) {
0513: logger
0514: .severe("Server was not stopped even after 10sec.. will terminate now.");
0515: System.exit(-1);
0516: }
0517: }
0518: if (adminServer == null
0519: || getQSAdminServer().getServer() != this ) {
0520: //so this is not qsadmin
0521: setClassLoader(null);
0522: }
0523: logger.info("Stopped " + getName());
0524: }
0525:
0526: /**
0527: * Restarts the QuickServer.
0528: *
0529: * @exception org.quickserver.net.AppException
0530: * if could not stop server or if it could not start the server.
0531: * @since 1.2
0532: */
0533: public void restartServer() throws AppException {
0534: stopServer();
0535: startServer();
0536: }
0537:
0538: /**
0539: * Returns the name of the QuickServer. Default is 'QuickServer'.
0540: * @see #setName
0541: */
0542: public String getName() {
0543: return serverName;
0544: }
0545:
0546: /**
0547: * Sets the name for the QuickServer
0548: * @param name for the QuickServer
0549: * @see #getName
0550: */
0551: public void setName(String name) {
0552: serverName = name;
0553: logger.finest("Set to : " + name);
0554: }
0555:
0556: /**
0557: * Returns the Server Banner of the QuickServer
0558: * @see #setServerBanner
0559: */
0560: public String getServerBanner() {
0561: return serverBanner;
0562: }
0563:
0564: /**
0565: * Sets the serverBanner for the QuickServer
0566: * that will be displayed on the standard output [console]
0567: * when server starts. <br> <br>
0568: * To set welcome message to your client
0569: * {@link ClientEventHandler#gotConnected}
0570: * @param banner for the QuickServer
0571: * @see #getServerBanner
0572: */
0573: public void setServerBanner(String banner) {
0574: serverBanner = banner;
0575: logger.finest("Set to : " + banner);
0576: }
0577:
0578: /**
0579: * Sets the port for the QuickServer to listen on.
0580: * If not set, it will run on Port 9876
0581: * @param port to listen on.
0582: * @see #getPort
0583: */
0584: public void setPort(int port) {
0585: if (port < 0) {
0586: throw new IllegalArgumentException(
0587: "Port number can not be less than 0!");
0588: }
0589: serverPort = port;
0590: logger.finest("Set to " + port);
0591: }
0592:
0593: /**
0594: * Returns the port for the QuickServer.
0595: * @see #setPort
0596: */
0597: public int getPort() {
0598: if (isClosed() == false) {
0599: return server.getLocalPort();
0600: }
0601:
0602: if (getSecure().isEnable() == false) {
0603: return serverPort;
0604: } else {
0605: int _port = getSecure().getPort();
0606: if (_port == -1)
0607: return serverPort;
0608: else
0609: return _port;
0610: }
0611: }
0612:
0613: /**
0614: * Sets the ClientCommandHandler class that interacts with
0615: * client sockets.
0616: * @param handler the fully qualified name of the class that
0617: * implements {@link ClientCommandHandler}
0618: * @see #getClientCommandHandler
0619: */
0620: public void setClientCommandHandler(String handler) {
0621: clientCommandHandlerString = handler;
0622: logger.finest("Set to " + handler);
0623: }
0624:
0625: /**
0626: * Returns the ClientCommandHandler class that interacts with
0627: * client sockets.
0628: * @see #setClientCommandHandler
0629: * @since 1.1
0630: */
0631: public String getClientCommandHandler() {
0632: return clientCommandHandlerString;
0633: }
0634:
0635: /**
0636: * Sets the ClientAuthenticationHandler class that
0637: * handles the authentication of a client.
0638: * @param authenticator the fully qualified name of the class
0639: * that implements {@link ClientAuthenticationHandler}.
0640: * @see #getClientAuthenticationHandler
0641: * @since 1.4.6
0642: */
0643: public void setClientAuthenticationHandler(String authenticator) {
0644: clientAuthenticationHandlerString = authenticator;
0645: logger.finest("Set to " + authenticator);
0646: }
0647:
0648: /**
0649: * Returns the ClientAuthenticationHandler class that
0650: * handles the authentication of a client.
0651: * @see #setClientAuthenticationHandler
0652: * @since 1.4.6
0653: */
0654: public String getClientAuthenticationHandler() {
0655: return clientAuthenticationHandlerString;
0656: }
0657:
0658: /**
0659: * Sets the Authenticator class that
0660: * handles the authentication of a client.
0661: * @param authenticator the fully qualified name of the class
0662: * that implements {@link Authenticator} or {@link ClientAuthenticationHandler}.
0663: * @see #getAuthenticator
0664: * @deprecated since 1.4.6 use setClientAuthenticationHandler
0665: * @since 1.3
0666: */
0667: public void setAuthenticator(String authenticator) {
0668: clientAuthenticationHandlerString = authenticator;
0669: logger.finest("Set to " + authenticator);
0670: }
0671:
0672: /**
0673: * Returns the Authenticator class that
0674: * handles the authentication of a client.
0675: * @see #setAuthenticator
0676: * @deprecated since 1.4.6 use getClientAuthenticationHandler
0677: * @since 1.3
0678: */
0679: public String getAuthenticator() {
0680: return clientAuthenticationHandlerString;
0681: }
0682:
0683: /**
0684: * Sets the ClientData class that carries client data.
0685: * @param data the fully qualified name of the class that
0686: * extends {@link ClientData}.
0687: * @see #getClientData
0688: */
0689: public void setClientData(String data) {
0690: this .clientDataString = data;
0691: logger.finest("Set to " + data);
0692: }
0693:
0694: /**
0695: * Returns the ClientData class string that carries client data
0696: * @return the fully qualified name of the class that
0697: * implements {@link ClientData}.
0698: * @see #setClientData
0699: */
0700: public String getClientData() {
0701: return clientDataString;
0702: }
0703:
0704: /**
0705: * Sets the client socket's timeout.
0706: * @param time client socket timeout in milliseconds.
0707: * @see #getTimeout
0708: */
0709: public void setTimeout(int time) {
0710: if (time > 0)
0711: socketTimeout = time;
0712: else
0713: socketTimeout = 0;
0714: logger.finest("Set to " + socketTimeout);
0715: }
0716:
0717: /**
0718: * Returns the Client socket timeout in milliseconds.
0719: * @see #setTimeout
0720: */
0721: public int getTimeout() {
0722: return socketTimeout;
0723: }
0724:
0725: /**
0726: * Sets max allowed login attempts.
0727: * @since 1.2
0728: * @see #getMaxAuthTry
0729: */
0730: public void setMaxAuthTry(int authTry) {
0731: maxAuthTry = authTry;
0732: logger.finest("Set to " + authTry);
0733: }
0734:
0735: /**
0736: * Returns max allowed login attempts. Default is <code>5</code>.
0737: * @since 1.2
0738: * @see #setMaxAuthTry
0739: */
0740: public int getMaxAuthTry() {
0741: return maxAuthTry;
0742: }
0743:
0744: /**
0745: * Sets message to be displayed when maximum allowed login
0746: * attempts has reached.
0747: * Default is : -ERR Max Auth Try Reached
0748: * @see #getMaxAuthTryMsg
0749: */
0750: public void setMaxAuthTryMsg(String msg) {
0751: maxAuthTryMsg = msg;
0752: logger.finest("Set to " + msg);
0753: }
0754:
0755: /**
0756: * Returns message to be displayed when maximum allowed login
0757: * attempts has reached.
0758: * @see #getMaxAuthTryMsg
0759: */
0760: public String getMaxAuthTryMsg() {
0761: return maxAuthTryMsg;
0762: }
0763:
0764: /**
0765: * Sets timeout message.
0766: * Default is : -ERR Timeout
0767: * @see #getTimeoutMsg
0768: */
0769: public void setTimeoutMsg(String msg) {
0770: timeoutMsg = msg;
0771: logger.finest("Set to " + msg);
0772: }
0773:
0774: /**
0775: * Returns timeout message.
0776: * @see #setTimeoutMsg
0777: */
0778: public String getTimeoutMsg() {
0779: return timeoutMsg;
0780: }
0781:
0782: private TheClient initTheClient() {
0783: TheClient theClient = new TheClient();
0784: theClient.setServer(QuickServer.this );
0785: theClient.setTimeoutMsg(getTimeoutMsg());
0786: theClient.setMaxAuthTry(getMaxAuthTry()); //v1.2
0787: theClient.setMaxAuthTryMsg(getMaxAuthTryMsg());
0788:
0789: theClient.setClientEventHandler(clientEventHandler);
0790: theClient
0791: .setClientExtendedEventHandler(clientExtendedEventHandler); //v1.4.6
0792: theClient.setClientCommandHandler(clientCommandHandler);
0793: theClient.setClientObjectHandler(clientObjectHandler); //v1.2
0794: theClient.setClientBinaryHandler(clientBinaryHandler); //v1.4
0795: theClient.setClientWriteHandler(clientWriteHandler); //v1.4.5
0796: theClient.setAuthenticator(authenticator); //v1.3
0797: theClient
0798: .setClientAuthenticationHandler(clientAuthenticationHandler); //v1.4.6
0799: theClient.setTimeout(socketTimeout);
0800: theClient.setMaxConnectionMsg(maxConnectionMsg);
0801: theClient.setCommunicationLogging(getCommunicationLogging()); //v1.3.2
0802: return theClient;
0803: }
0804:
0805: public void run() {
0806: exceptionInRun = null;
0807: TheClient theClient = initTheClient();
0808: try {
0809: stopServer = false;
0810:
0811: closeAllPools();
0812: initAllPools();
0813:
0814: makeServerSocket();
0815: System.out.println(serverBanner); //print banner
0816: setServiceState(Service.RUNNING); //v1.2
0817:
0818: processServerHooks(ServerHook.POST_STARTUP); //v1.3.3
0819: if (getBlockingMode() == false) {
0820: runNonBlocking(theClient);
0821: if (stopServer == true) {
0822: logger.finest("Closing selector for " + getName());
0823: selector.close();
0824: }
0825: return;
0826: } else {
0827: runBlocking(theClient);
0828: }
0829: } catch (BindException e) {
0830: exceptionInRun = e;
0831: logger.severe(getName() + " BindException for Port "
0832: + getPort() + " @ "
0833: + getBindAddr().getHostAddress() + " : "
0834: + e.getMessage());
0835: } catch (javax.net.ssl.SSLException e) {
0836: exceptionInRun = e;
0837: logger.severe("SSLException " + e);
0838: logger.fine("StackTrace:\n" + MyString.getStackTrace(e));
0839: } catch (IOException e) {
0840: exceptionInRun = e;
0841: logger.severe("IOError " + e);
0842: logger.fine("StackTrace:\n" + MyString.getStackTrace(e));
0843: } catch (Exception e) {
0844: exceptionInRun = e;
0845: logger.severe("Error " + e);
0846: logger.fine("StackTrace:\n" + MyString.getStackTrace(e));
0847: } finally {
0848: if (getBlockingMode() == true) {
0849: logger.warning("Closing " + getName());
0850: try {
0851: if (isClosed() == false) {
0852: server.close();
0853: }
0854: } catch (Exception e) {
0855: throw new RuntimeException(e);
0856: }
0857: server = null;
0858: serverSocketChannel = null;
0859:
0860: setServiceState(Service.STOPPED);
0861: logger.warning("Closed " + getName());
0862:
0863: processServerHooks(ServerHook.POST_SHUTDOWN);
0864: } else if (getBlockingMode() == false
0865: && exceptionInRun != null) {
0866: logger.warning("Closing " + getName()
0867: + " - Had Error: " + exceptionInRun);
0868: try {
0869: if (isClosed() == false) {
0870: if (serverSocketChannel != null)
0871: serverSocketChannel.close();
0872: if (server != null)
0873: server.close();
0874: }
0875: } catch (Exception e) {
0876: throw new RuntimeException(e);
0877: }
0878:
0879: server = null;
0880: serverSocketChannel = null;
0881:
0882: setServiceState(Service.STOPPED);
0883: logger.warning("Closed " + getName());
0884:
0885: processServerHooks(ServerHook.POST_SHUTDOWN);
0886: }
0887: }
0888: } //end of run
0889:
0890: /**
0891: * Sets the maximum number of client connection allowed.
0892: * @since 1.1
0893: * @see #getMaxConnection
0894: */
0895: public void setMaxConnection(long maxConnection) {
0896: if (getServiceState() == Service.SUSPENDED)
0897: suspendMaxConnection = maxConnection;
0898: else
0899: this .maxConnection = maxConnection;
0900: logger.finest("Set to " + maxConnection);
0901: }
0902:
0903: /**
0904: * Returns the maximum number of client connection allowed.
0905: * @since 1.1
0906: * @see #setMaxConnection
0907: */
0908: public long getMaxConnection() {
0909: return maxConnection;
0910: }
0911:
0912: /**
0913: * Returns number of clients connected.
0914: * @since 1.1
0915: */
0916: public long getClientCount() {
0917: if (clientHandlerPool != null) {
0918: try {
0919: return getClientHandlerPool().getNumActive();
0920: } catch (Exception e) {
0921: return 0;
0922: }
0923: }
0924: return 0;
0925: }
0926:
0927: /**
0928: * Sets the message to be sent to any new client connected after
0929: * maximum client connection has reached.
0930: * Default is : <code>-ERR Server Busy. Max Connection Reached</code>
0931: * @since 1.1
0932: * @see #getMaxConnectionMsg
0933: */
0934: public void setMaxConnectionMsg(String maxConnectionMsg) {
0935: if (getServiceState() == Service.SUSPENDED)
0936: suspendMaxConnectionMsg = maxConnectionMsg;
0937: else
0938: this .maxConnectionMsg = maxConnectionMsg;
0939: logger.finest("Set to " + maxConnectionMsg);
0940: }
0941:
0942: /**
0943: * Returns the message to be sent to any new client connected
0944: * after maximum client connection has reached.
0945: * @since 1.1
0946: * @see #setMaxConnectionMsg
0947: */
0948: public String getMaxConnectionMsg() {
0949: return maxConnectionMsg;
0950: }
0951:
0952: /**
0953: * Sets the Ip address to bind to.
0954: * @param bindAddr argument can be used on a multi-homed host for a
0955: * QuickServer that will only accept connect requests to one
0956: * of its addresses. If not set, it will default accepting
0957: * connections on any/all local addresses.
0958: * @exception java.net.UnknownHostException if no IP address for
0959: * the host could be found
0960: * @since 1.1
0961: * @see #getBindAddr
0962: */
0963: public void setBindAddr(String bindAddr)
0964: throws UnknownHostException {
0965: ipAddr = InetAddress.getByName(bindAddr);
0966: logger.finest("Set to " + bindAddr);
0967: }
0968:
0969: /**
0970: * Returns the IP address binding to.
0971: * @since 1.1
0972: * @see #setBindAddr
0973: */
0974: public InetAddress getBindAddr() {
0975: if (ipAddr == null) {
0976: try {
0977: ipAddr = InetAddress.getByName("0.0.0.0");
0978: } catch (Exception e) {
0979: logger
0980: .warning("Unable to create default ip(0.0.0.0) : "
0981: + e);
0982: throw new RuntimeException(
0983: "Error: Unable to find servers own ip : " + e);
0984: }
0985: }
0986: return ipAddr;
0987: }
0988:
0989: /**
0990: * Sets the store of objects to QuickServer, it is an array of objects
0991: * that main program or the class that created QuickServer passes to
0992: * the QuickServer.
0993: * @param storeObjects array of objects
0994: * @see #getStoreObjects
0995: * @since 1.1
0996: */
0997: public void setStoreObjects(Object[] storeObjects) {
0998: this .storeObjects = storeObjects;
0999: }
1000:
1001: /**
1002: * Returns store of objects from QuickServer, if nothing was set will
1003: * return <code>null</code>.
1004: * @see #setStoreObjects
1005: * @since 1.1
1006: */
1007: public Object[] getStoreObjects() {
1008: return storeObjects;
1009: }
1010:
1011: /**
1012: * Set the port to run QSAdminServer on.
1013: * @since 1.2
1014: */
1015: public void setQSAdminServerPort(int port) {
1016: getQSAdminServer().getServer().setPort(port);
1017: }
1018:
1019: /**
1020: * Returns the port to run QSAdminServer on.
1021: * @since 1.2
1022: */
1023: public int getQSAdminServerPort() {
1024: return getQSAdminServer().getServer().getPort();
1025: }
1026:
1027: /**
1028: * Set the ClientAuthenticationHandler class of
1029: * QSAdminServer that handles the authentication of a client.
1030: * @since 1.2
1031: */
1032: public void setQSAdminServerAuthenticator(String authenticator) {
1033: getQSAdminServer().getServer().setClientAuthenticationHandler(
1034: authenticator);
1035: }
1036:
1037: /**
1038: * Returns the Authenticator or ClientAuthenticationHandler class of
1039: * QSAdminServer that handles the authentication of a client.
1040: * @since 1.2
1041: */
1042: public String getQSAdminServerAuthenticator() {
1043: return getQSAdminServer().getServer().getAuthenticator();
1044: }
1045:
1046: /**
1047: * Starts QSAdminServer for this QuickServer.
1048: * @see org.quickserver.net.qsadmin.QSAdminServer
1049: * @param authenticator sets the ClientAuthenticationHandler class that
1050: * handles the authentication of a client,
1051: * if null uses {@link org.quickserver.net.qsadmin.Authenticator}.
1052: * @param port to run QSAdminServer on
1053: * @exception org.quickserver.net.AppException
1054: * if Server already running or if it could not load the classes
1055: * [ClientCommandHandler, ClientAuthenticationHandler, ClientData].
1056: * @since 1.1
1057: */
1058: public void startQSAdminServer(int port, String authenticator)
1059: throws AppException {
1060: getQSAdminServer()
1061: .setClientAuthenticationHandler(authenticator);
1062: getQSAdminServer().startServer(port);
1063: }
1064:
1065: /**
1066: * Starts QSAdminServer for this QuickServer.
1067: * @see org.quickserver.net.qsadmin.QSAdminServer
1068: * @since 1.2
1069: */
1070: public void startQSAdminServer() throws AppException {
1071: getQSAdminServer().startServer();
1072: }
1073:
1074: /**
1075: * Returns {@link QSAdminServer} associated with this QuickServer
1076: * @since 1.1
1077: */
1078: public QSAdminServer getQSAdminServer() {
1079: if (adminServer == null)
1080: adminServer = new QSAdminServer(QuickServer.this );
1081: return adminServer;
1082: }
1083:
1084: /**
1085: * Sets {@link QSAdminServer} associated with this QuickServer
1086: * @since 1.3.3
1087: */
1088: public void setQSAdminServer(QSAdminServer adminServer) {
1089: if (adminServer == null)
1090: this .adminServer = adminServer;
1091: }
1092:
1093: /**
1094: * Returns the closed state of the QuickServer Socket.
1095: * @since 1.1
1096: */
1097: public boolean isClosed() {
1098: if (server == null)
1099: return true;
1100: return server.isClosed();
1101: }
1102:
1103: /**
1104: * Returns the application logger associated with QuickServer.
1105: * If it was not set will return QuickServer's own logger.
1106: * @since 1.2
1107: */
1108: public Logger getAppLogger() {
1109: if (appLogger != null)
1110: return appLogger;
1111: return logger;
1112: }
1113:
1114: /**
1115: * Sets the application logger associated with QuickServer
1116: * @since 1.2
1117: */
1118: public void setAppLogger(Logger appLogger) {
1119: this .appLogger = appLogger;
1120: }
1121:
1122: /**
1123: * Sets the ClientObjectHandler class that interacts with
1124: * client sockets to handle java objects.
1125: * @param handler object the fully qualified name of the class that
1126: * implements {@link ClientObjectHandler}
1127: * @see #getClientObjectHandler
1128: * @since 1.2
1129: */
1130: public void setClientObjectHandler(String handler) {
1131: clientObjectHandlerString = handler;
1132: logger.finest("Set to " + handler);
1133: }
1134:
1135: /**
1136: * Returns the ClientObjectHandler class that interacts with
1137: * client sockets.
1138: * @see #setClientObjectHandler
1139: * @since 1.2
1140: */
1141: public String getClientObjectHandler() {
1142: return clientObjectHandlerString;
1143: }
1144:
1145: /**
1146: * Sets the console log handler formatter.
1147: * @param formatter fully qualified name of the class that implements
1148: * {@link java.util.logging.Formatter}
1149: * @since 1.2
1150: */
1151: public void setConsoleLoggingFormatter(String formatter)
1152: throws ClassNotFoundException, InstantiationException,
1153: IllegalAccessException {
1154: if (formatter == null)
1155: return;
1156: consoleLoggingformatter = formatter;
1157:
1158: Formatter conformatter = (Formatter) getClass(formatter, true)
1159: .newInstance();
1160: Logger jdkLogger = Logger.getLogger("");
1161: Handler[] handlers = jdkLogger.getHandlers();
1162: for (int index = 0; index < handlers.length; index++) {
1163: if (ConsoleHandler.class.isInstance(handlers[index])) {
1164: handlers[index].setFormatter(conformatter);
1165: }
1166: }
1167: logger.finest("Set to " + formatter);
1168: }
1169:
1170: /**
1171: * Gets the console log handler formatter.
1172: * @since 1.3
1173: */
1174: public String getConsoleLoggingFormatter() {
1175: return consoleLoggingformatter;
1176: }
1177:
1178: /**
1179: * Sets the console log handler formater to
1180: * {@link org.quickserver.util.logging.MiniFormatter}
1181: * @since 1.2
1182: */
1183: public void setConsoleLoggingToMini() {
1184: try {
1185: setConsoleLoggingFormatter("org.quickserver.util.logging.MiniFormatter");
1186: } catch (Exception e) {
1187: logger.warning("Setting to logging.MiniFormatter : " + e);
1188: }
1189: }
1190:
1191: /**
1192: * Sets the console log handler formater to
1193: * {@link org.quickserver.util.logging.MicroFormatter}
1194: * @since 1.2
1195: */
1196: public void setConsoleLoggingToMicro() {
1197: try {
1198: setConsoleLoggingFormatter("org.quickserver.util.logging.MicroFormatter");
1199: } catch (Exception e) {
1200: logger.warning("Setting to MicroFormatter : " + e);
1201: }
1202: }
1203:
1204: /**
1205: * Sets the console log handler level.
1206: * @since 1.2
1207: */
1208: public void setConsoleLoggingLevel(Level level) {
1209: Logger rlogger = Logger.getLogger("");
1210: Handler[] handlers = rlogger.getHandlers();
1211: for (int index = 0; index < handlers.length; index++) {
1212: if (ConsoleHandler.class.isInstance(handlers[index])) {
1213: handlers[index].setLevel(level);
1214: }
1215: }
1216: if (level == Level.SEVERE)
1217: consoleLoggingLevel = "SEVERE";
1218: else if (level == Level.WARNING)
1219: consoleLoggingLevel = "WARNING";
1220: else if (level == Level.INFO)
1221: consoleLoggingLevel = "INFO";
1222: else if (level == Level.CONFIG)
1223: consoleLoggingLevel = "CONFIG";
1224: else if (level == Level.FINE)
1225: consoleLoggingLevel = "FINE";
1226: else if (level == Level.FINER)
1227: consoleLoggingLevel = "FINER";
1228: else if (level == Level.FINEST)
1229: consoleLoggingLevel = "FINEST";
1230: else
1231: consoleLoggingLevel = "UNKNOWN";
1232:
1233: logger.fine("Set to " + level);
1234: }
1235:
1236: /**
1237: * Gets the console log handler level.
1238: * @since 1.3
1239: */
1240: public String getConsoleLoggingLevel() {
1241: return consoleLoggingLevel;
1242: }
1243:
1244: /**
1245: * Sets the level for all log handlers.
1246: * @since 1.3.1
1247: */
1248: public void setLoggingLevel(Level level) {
1249: Logger rlogger = Logger.getLogger("");
1250: Handler[] handlers = rlogger.getHandlers();
1251: for (int index = 0; index < handlers.length; index++) {
1252: handlers[index].setLevel(level);
1253: }
1254:
1255: if (level == Level.SEVERE)
1256: loggingLevel = "SEVERE";
1257: else if (level == Level.WARNING)
1258: loggingLevel = "WARNING";
1259: else if (level == Level.INFO)
1260: loggingLevel = "INFO";
1261: else if (level == Level.CONFIG)
1262: loggingLevel = "CONFIG";
1263: else if (level == Level.FINE)
1264: loggingLevel = "FINE";
1265: else if (level == Level.FINER)
1266: loggingLevel = "FINER";
1267: else if (level == Level.FINEST)
1268: loggingLevel = "FINEST";
1269: else
1270: loggingLevel = "UNKNOWN";
1271:
1272: consoleLoggingLevel = loggingLevel;
1273:
1274: logger.fine("Set to " + level);
1275: }
1276:
1277: //*** Start of Service interface methods
1278: /**
1279: * Returns service error if any.
1280: * @since 1.4.7
1281: */
1282: public Throwable getServiceError() {
1283: return serviceError;
1284: }
1285:
1286: /**
1287: * Initialise and create the service.
1288: * @param param of the xml configuration file.
1289: * @since 1.2
1290: */
1291: public synchronized boolean initService(Object param[]) {
1292: serviceError = null;
1293: try {
1294: initServer(param);
1295: } catch (Exception e) {
1296: serviceError = e;
1297: return false;
1298: }
1299: return true;
1300: }
1301:
1302: /**
1303: * Initialise and create the service.
1304: * @param qsConfig QuickServerConfig object.
1305: * @since 1.4.6
1306: */
1307: public synchronized boolean initService(QuickServerConfig qsConfig) {
1308: serviceError = null;
1309: try {
1310: initServer(qsConfig);
1311: } catch (Exception e) {
1312: serviceError = e;
1313: return false;
1314: }
1315: return true;
1316: }
1317:
1318: /**
1319: * Start the service.
1320: * @return true if serivce was stopped from Running state.
1321: * @since 1.2
1322: */
1323: public boolean startService() {
1324: serviceError = null;
1325: if (getServiceState() == Service.RUNNING)
1326: return false;
1327: try {
1328: startServer();
1329: } catch (AppException e) {
1330: serviceError = e;
1331: return false;
1332: }
1333: return true;
1334: }
1335:
1336: /**
1337: * Stop the service.
1338: * @return true if serivce was stopped from Running state.
1339: * @since 1.2
1340: */
1341: public boolean stopService() {
1342: serviceError = null;
1343: if (getServiceState() == Service.STOPPED)
1344: return false;
1345: try {
1346: stopServer();
1347: clearAllPools();
1348: } catch (AppException e) {
1349: serviceError = e;
1350: return false;
1351: } catch (Exception e) {
1352: serviceError = e;
1353: return false;
1354: }
1355: return true;
1356: }
1357:
1358: /**
1359: * Suspends the service.
1360: * @return true if service was suspended from resumed state.
1361: * @since 1.2
1362: */
1363: public boolean suspendService() {
1364: serviceError = null;
1365: if (getServiceState() == Service.RUNNING) {
1366: suspendMaxConnection = maxConnection;
1367: suspendMaxConnectionMsg = maxConnectionMsg;
1368: maxConnection = 0;
1369: maxConnectionMsg = "Service is suspended.";
1370: setServiceState(Service.SUSPENDED);
1371: logger.info("Service " + getName() + " is suspended.");
1372: return true;
1373: }
1374: return false;
1375: }
1376:
1377: /**
1378: * Resume the service.
1379: * @return true if service was resumed from suspended state.
1380: * @since 1.2
1381: */
1382: public boolean resumeService() {
1383: serviceError = null;
1384: if (getServiceState() == Service.SUSPENDED) {
1385: maxConnection = suspendMaxConnection;
1386: maxConnectionMsg = suspendMaxConnectionMsg;
1387: setServiceState(Service.RUNNING);
1388: logger.info("Service " + getName() + " resumed.");
1389: return true;
1390: }
1391: return false;
1392: }
1393:
1394: /**
1395: * Information about the service.
1396: * @since 1.2
1397: */
1398: public String info() {
1399: serviceError = null;
1400: StringBuffer buf = new StringBuffer();
1401: buf.append(getName() + "\n");
1402: buf.append(getBindAddr().getHostAddress() + " " + getPort()
1403: + "\n");
1404: return buf.toString();
1405: }
1406:
1407: // *** End of Service interface methods
1408:
1409: /**
1410: * Initialise and create the server.
1411: * @param param of the xml configuration file.
1412: * @exception AppException if QuickServerConfig creation failed from the xml config file.
1413: * @since 1.4.7
1414: */
1415: public synchronized void initServer(Object param[])
1416: throws AppException {
1417: QuickServerConfig qsConfig = null;
1418: try {
1419: qsConfig = ConfigReader.read((String) param[0]);
1420: } catch (Exception e) {
1421: logger.severe("Could not init server from xml file "
1422: + (new File((String) param[0]).getAbsolutePath())
1423: + " : " + e);
1424: throw new AppException(
1425: "Could not init server from xml file", e);
1426: }
1427: initServer(qsConfig);
1428: }
1429:
1430: /**
1431: * Initialise and create the service.
1432: * @param qsConfig QuickServerConfig object.
1433: * @since 1.4.7
1434: */
1435: public synchronized void initServer(QuickServerConfig qsConfig)
1436: throws AppException {
1437: setConfig(qsConfig);
1438: try {
1439: configQuickServer();
1440:
1441: loadApplicationClasses();
1442:
1443: //start InitServerHooks
1444: InitServerHooks ish = getConfig().getInitServerHooks();
1445: if (ish != null) {
1446: Iterator iterator = ish.iterator();
1447: String initServerHookClassName = null;
1448: Class initServerHookClass = null;
1449: InitServerHook initServerHook = null;
1450: while (iterator.hasNext()) {
1451: initServerHookClassName = (String) iterator.next();
1452: initServerHookClass = getClass(
1453: initServerHookClassName, true);
1454: initServerHook = (InitServerHook) initServerHookClass
1455: .newInstance();
1456:
1457: logger.info("Loaded init server hook: "
1458: + initServerHookClassName);
1459: logger.fine("Init server hook info: "
1460: + initServerHook.info());
1461: initServerHook.handleInit(QuickServer.this );
1462: }
1463: }
1464: } catch (Exception e) {
1465: logger.severe("Could not load init server hook: " + e);
1466: logger.warning("StackTrace:\n" + MyString.getStackTrace(e));
1467: throw new AppException("Could not load init server hook", e);
1468: }
1469: setServiceState(Service.INIT);
1470: logger.finest("\r\n" + MyString.getSystemInfo(getVersion()));
1471: }
1472:
1473: /**
1474: * Returns the state of the process
1475: * As any constant of {@link Service} interface.
1476: * @since 1.2
1477: */
1478: public int getServiceState() {
1479: return serviceState;
1480: }
1481:
1482: /**
1483: * Sets the state of the process
1484: * As any constant of {@link Service} interface.
1485: * @since 1.2
1486: */
1487: public void setServiceState(int state) {
1488: serviceState = state;
1489: }
1490:
1491: private void configConsoleLoggingLevel(QuickServer qs, String temp) {
1492: if (temp.equals("SEVERE"))
1493: qs.setConsoleLoggingLevel(Level.SEVERE);
1494: else if (temp.equals("WARNING"))
1495: qs.setConsoleLoggingLevel(Level.WARNING);
1496: else if (temp.equals("INFO"))
1497: qs.setConsoleLoggingLevel(Level.INFO);
1498: else if (temp.equals("CONFIG"))
1499: qs.setConsoleLoggingLevel(Level.CONFIG);
1500: else if (temp.equals("FINE"))
1501: qs.setConsoleLoggingLevel(Level.FINE);
1502: else if (temp.equals("FINER"))
1503: qs.setConsoleLoggingLevel(Level.FINER);
1504: else if (temp.equals("FINEST"))
1505: qs.setConsoleLoggingLevel(Level.FINEST);
1506: else
1507: logger.warning("unknown level " + temp);
1508: }
1509:
1510: /**
1511: * Configures QuickServer based on the passed QuickServerConfig object.
1512: * @since 1.2
1513: */
1514: public void configQuickServer(QuickServerConfig config)
1515: throws Exception {
1516: QuickServer qs = QuickServer.this ;
1517: qs.setConfig(config); //v1.3
1518: qs.setBasicConfig(config);
1519: String temp = config.getConsoleLoggingLevel();
1520: configConsoleLoggingLevel(qs, temp);
1521: temp = null;
1522:
1523: qs.setConsoleLoggingFormatter(config
1524: .getConsoleLoggingFormatter());
1525:
1526: qs.setName(config.getName());
1527: qs.setPort(config.getPort());
1528: qs.setClientEventHandler(config.getClientEventHandler());
1529: qs.setClientCommandHandler(config.getClientCommandHandler());
1530: if (config.getAuthenticator() != null)
1531: qs.setAuthenticator(config.getAuthenticator()); //v1.3
1532: else if (config.getClientAuthenticationHandler() != null)
1533: qs.setClientAuthenticationHandler(config
1534: .getClientAuthenticationHandler()); //v1.4.6
1535: qs.setClientObjectHandler(config.getClientObjectHandler());
1536: qs.setClientBinaryHandler(config.getClientBinaryHandler());//v1.4
1537: qs.setClientWriteHandler(config.getClientWriteHandler());//v1.4.5
1538: qs.setClientData(config.getClientData());
1539: qs.setClientExtendedEventHandler(config
1540: .getClientExtendedEventHandler());
1541: qs.setDefaultDataMode(config.getDefaultDataMode());//v1.4.6
1542: qs.setServerBanner(config.getServerBanner());
1543: qs.setTimeout(config.getTimeout());
1544: qs.setMaxAuthTry(config.getMaxAuthTry());
1545: qs.setMaxAuthTryMsg(config.getMaxAuthTryMsg());
1546: qs.setTimeoutMsg(config.getTimeoutMsg());
1547: qs.setMaxConnection(config.getMaxConnection());
1548: qs.setMaxConnectionMsg(config.getMaxConnectionMsg());
1549: qs.setBindAddr(config.getBindAddr());
1550: //v1.3.2
1551: qs.setCommunicationLogging(config.getCommunicationLogging());
1552: //v1.3.3
1553: qs.setSecurityManagerClass(config.getSecurityManagerClass());
1554: qs
1555: .setAccessConstraintConfig(config
1556: .getAccessConstraintConfig());
1557: temp = config.getApplicationJarPath();
1558: if (temp != null) {
1559: File ajp = new File(temp);
1560: if (ajp.isAbsolute() == false) {
1561: temp = config.getConfigFile();
1562: ajp = new File(temp);
1563: temp = ajp.getParent() + File.separatorChar
1564: + config.getApplicationJarPath();
1565: config.setApplicationJarPath(temp);
1566: temp = null;
1567: }
1568: qs.setApplicationJarPath(config.getApplicationJarPath());
1569: //set path also to QSAdmin
1570: if (config.getQSAdminServerConfig() != null) {
1571: getQSAdminServer().getServer().setApplicationJarPath(
1572: config.getApplicationJarPath());
1573: }
1574: }
1575: qs.setServerHooks(config.getServerHooks());
1576: qs.setSecure(config.getSecure());
1577: }
1578:
1579: /**
1580: * Configures QSAdminServer based on the passed QuickServerConfig object.
1581: * @since 1.2
1582: */
1583: public void configQuickServer(QSAdminServerConfig config)
1584: throws Exception {
1585: QuickServer qs = getQSAdminServer().getServer();
1586: qs.setBasicConfig(config);
1587:
1588: //set the Logging Level to same as main QS
1589: String temp = getConsoleLoggingLevel();//config.getConsoleLoggingLevel();
1590: configConsoleLoggingLevel(qs, temp);
1591:
1592: //set the Logging Formatter to same as main QS
1593: //qs.setConsoleLoggingFormatter(config.getConsoleLoggingFormatter());
1594: qs.setConsoleLoggingFormatter(getConsoleLoggingFormatter());
1595:
1596: qs.setClientEventHandler(config.getClientEventHandler());//v1.4.6
1597: qs.setClientCommandHandler(config.getClientCommandHandler());
1598: qs.setName(config.getName());
1599: qs.setPort(config.getPort());
1600: if (config.getAuthenticator() != null)
1601: qs.setAuthenticator(config.getAuthenticator()); //v1.3
1602: else if (config.getClientAuthenticationHandler() != null)
1603: qs.setClientAuthenticationHandler(config
1604: .getClientAuthenticationHandler()); //v1.4.6
1605: qs.setClientObjectHandler(config.getClientObjectHandler());
1606: qs.setClientBinaryHandler(config.getClientBinaryHandler());//v1.4
1607: qs.setClientWriteHandler(config.getClientWriteHandler());//v1.4.5
1608: qs.setClientData(config.getClientData());
1609: qs.setClientExtendedEventHandler(config
1610: .getClientExtendedEventHandler());//v1.4.6
1611: qs.setDefaultDataMode(config.getDefaultDataMode());//v1.4.6
1612: qs.setServerBanner(config.getServerBanner());
1613: qs.setTimeout(config.getTimeout());
1614: qs.setMaxAuthTry(config.getMaxAuthTry());
1615: qs.setMaxAuthTryMsg(config.getMaxAuthTryMsg());
1616: qs.setTimeoutMsg(config.getTimeoutMsg());
1617: qs.setMaxConnection(config.getMaxConnection());
1618: qs.setMaxConnectionMsg(config.getMaxConnectionMsg());
1619: qs.setBindAddr(config.getBindAddr());
1620: //v1.3.2
1621: qs.setCommunicationLogging(config.getCommunicationLogging());
1622: getQSAdminServer().setCommandPlugin(config.getCommandPlugin());
1623: //v1.3.2
1624: if (config.getCommandShellEnable().equals("true"))
1625: getQSAdminServer().setShellEnable(true);
1626: getQSAdminServer().setPromptName(
1627: config.getCommandShellPromptName());
1628: //v1.3.3
1629: qs
1630: .setAccessConstraintConfig(config
1631: .getAccessConstraintConfig());
1632: qs.setServerHooks(config.getServerHooks());
1633: qs.setSecure(config.getSecure());
1634: }
1635:
1636: /**
1637: * Configures QSAdminServer and QuickServer based on the
1638: * internal QuickServerConfig object.
1639: * @since 1.3
1640: */
1641: public void configQuickServer() throws Exception {
1642: configQuickServer(getConfig());
1643: if (getConfig().getQSAdminServerConfig() != null) {
1644: configQuickServer(getConfig().getQSAdminServerConfig());
1645: }
1646: }
1647:
1648: /**
1649: * Usage: QuickServer [-options]<br/>
1650: * Where options include:<br/>
1651: * -about Opens About Dialogbox<br/>
1652: * -load <xml_config_file> [options] Loads the server from xml file.
1653: * where options include:
1654: * -fullXML2File <new_file_name>
1655: */
1656: public static void main(String args[]) {
1657: try {
1658: if (args.length >= 1) {
1659: if (args[0].equals("-about")) {
1660: org.quickserver.net.server.gui.About.main(null);
1661: } else if (args[0].equals("-load") && args.length >= 2) {
1662: QuickServer qs = QuickServer.load(args[1]);
1663: if (qs != null)
1664: handleOptions(args, qs);
1665: } else {
1666: System.out.println(printUsage());
1667: }
1668: } else {
1669: System.out.println(printUsage());
1670: org.quickserver.net.server.gui.About.showAbout();
1671: }
1672: } catch (Exception e) {
1673: e.printStackTrace();
1674: }
1675: }
1676:
1677: /**
1678: * Loads the server from the xml file name passed.
1679: * @since 1.4.7
1680: */
1681: public static QuickServer load(String xml) throws AppException {
1682: QuickServer qs = new QuickServer();
1683: Object config[] = new Object[] { xml };
1684: qs.initServer(config);
1685: qs.startServer();
1686: if (qs.getConfig().getQSAdminServerConfig() != null) {
1687: qs.startQSAdminServer();
1688: }
1689: return qs;
1690: }
1691:
1692: /** Prints usage */
1693: private static String printUsage() {
1694: StringBuffer sb = new StringBuffer();
1695: sb
1696: .append("QuickServer - Java library/framework for creating robust multi-client TCP servers.\n");
1697: sb.append("Copyright (C) QuickServer.org\n\n");
1698: sb.append("Usage: QuickServer [-options]\n");
1699: sb.append("Where options include:\n");
1700: sb.append(" -about\t" + "Opens About Dialog box\n");
1701: sb.append(" -load <xml_config_file> [load-options]\t"
1702: + "Loads the server from xml file.\n");
1703: sb.append(" Where load-options include:\n");
1704: sb
1705: .append(" -fullXML2File <file_name>\t"
1706: + "Dumps the Full XML configuration of the QuickServer loaded.\n");
1707: return sb.toString();
1708: }
1709:
1710: private static void handleOptions(String args[],
1711: QuickServer quickserver) {
1712: if (args.length < 3)
1713: return;
1714:
1715: if (args[2].equals("-fullXML2File") && args.length >= 4) {
1716: File file = new File(args[3]);
1717: logger.info("Writing full xml configuration to file: "
1718: + file.getAbsolutePath());
1719: try {
1720: TextFile.write(file, quickserver.getConfig()
1721: .toXML(null));
1722: } catch (Exception e) {
1723: logger.warning("Error writing full xml configuration: "
1724: + e);
1725: }
1726: }
1727: }
1728:
1729: /**
1730: * Cleans all Object and Thread pools
1731: * @since 1.3
1732: */
1733: public void clearAllPools() throws Exception {
1734: try {
1735: if (pool != null)
1736: getClientPool().clear();
1737: if (clientHandlerPool != null)
1738: getClientHandlerPool().clear();
1739: if (getClientDataPool() != null)
1740: getClientDataPool().clear();
1741: if (getDBPoolUtil() != null)
1742: getDBPoolUtil().clean();
1743: if (byteBufferPool != null)
1744: getByteBufferPool().clear();
1745: } catch (Exception e) {
1746: logger.warning("Error: " + e);
1747: throw e;
1748: }
1749: }
1750:
1751: /**
1752: * Closes all Object and Thread pools
1753: * @since 1.3
1754: */
1755: public void closeAllPools() throws Exception {
1756: if (pool == null && clientHandlerPool == null
1757: && getClientDataPool() == null
1758: && getDBPoolUtil() == null && byteBufferPool == null) {
1759: return;
1760: }
1761: logger.fine("Closing pools for " + getName());
1762: try {
1763: if (pool != null
1764: && PoolHelper.isPoolOpen(getClientPool()
1765: .getObjectPool())) {
1766: logger.finer("Closing ClientThread pool.");
1767: getClientPool().close();
1768: }
1769: if (clientHandlerPool != null
1770: && PoolHelper.isPoolOpen(getClientHandlerPool())) {
1771: logger.finer("Closing ClientHandler pool.");
1772: getClientHandlerPool().close();
1773: }
1774: if (getClientDataPool() != null
1775: && PoolHelper.isPoolOpen(getClientDataPool())) {
1776: logger.finer("Closing ClientData pool.");
1777: getClientDataPool().close();
1778: }
1779: if (getDBPoolUtil() != null) {
1780: logger.finer("Closing DB pool.");
1781: getDBPoolUtil().clean();
1782: }
1783: if (byteBufferPool != null
1784: && PoolHelper.isPoolOpen(getByteBufferPool())) {
1785: logger.finer("Closing ByteBuffer pool.");
1786: getByteBufferPool().close();
1787: }
1788: logger.fine("Closed pools for " + getName());
1789: } catch (Exception e) {
1790: logger.warning("Error closing pools for " + getName()
1791: + ": " + e);
1792: throw e;
1793: }
1794: }
1795:
1796: /**
1797: * Initialise all Object and Thread pools.
1798: * @since 1.3
1799: */
1800: public void initAllPools() throws Exception {
1801: logger.fine("Creating pools");
1802: if (getBlockingMode() == false) {
1803: makeByteBufferPool(getBasicConfig().getObjectPoolConfig()
1804: .getByteBufferObjectPoolConfig());
1805: }
1806:
1807: makeClientPool(getBasicConfig().getObjectPoolConfig()
1808: .getThreadObjectPoolConfig());
1809:
1810: makeClientHandlerPool(getBasicConfig().getObjectPoolConfig()
1811: .getClientHandlerObjectPoolConfig());
1812:
1813: //check if client data is poolable
1814: if (clientDataClass != null) {
1815: try {
1816: clientData = (ClientData) clientDataClass.newInstance();
1817: if (PoolableObject.class.isInstance(clientData) == true) {
1818: PoolableObject po = (PoolableObject) clientData;
1819: if (po.isPoolable() == true) {
1820: makeClientDataPool(
1821: po.getPoolableObjectFactory(),
1822: getBasicConfig()
1823: .getObjectPoolConfig()
1824: .getClientDataObjectPoolConfig());
1825: } else {
1826: clientDataPool = null;
1827: logger.fine("ClientData is not poolable!");
1828: }
1829: }
1830: } catch (Exception e) {
1831: logger.warning("Error: " + e);
1832: throw e;
1833: }
1834: }
1835:
1836: try {
1837: makeDBObjectPool();
1838: } catch (Exception e) {
1839: logger.warning("Error in makeDBObjectPool() : " + e);
1840: logger.fine("StackTrace:\n" + MyString.getStackTrace(e));
1841: throw e;
1842: }
1843: logger.fine("Created pools");
1844: }
1845:
1846: /**
1847: * Returns {@link org.quickserver.util.pool.thread.ClientPool} class that
1848: * managing the pool of threads for handling clients.
1849: * @exception IllegalStateException if pool is not created yet.
1850: * @since 1.3
1851: */
1852: public ClientPool getClientPool() {
1853: if (pool == null)
1854: throw new IllegalStateException(
1855: "No ClientPool available yet!");
1856: return pool;
1857: }
1858:
1859: /**
1860: * Makes the pool of ClientHandler
1861: * @since 1.3
1862: */
1863: private void makeClientHandlerPool(PoolConfig opConfig)
1864: throws Exception {
1865: logger.finer("Creating ClientHandler pool");
1866: PoolableObjectFactory factory = new ClientHandlerObjectFactory(
1867: getBlockingMode());
1868: clientHandlerPool = poolManager.makeClientHandlerPool(factory,
1869: opConfig);
1870: poolManager.initPool(clientHandlerPool, opConfig);
1871: clientHandlerPool = makeQSObjectPool(clientHandlerPool);
1872: clientIdentifier
1873: .setClientHandlerPool((QSObjectPool) clientHandlerPool);
1874: }
1875:
1876: /**
1877: * Returns ObjectPool of {@link org.quickserver.net.server.ClientHandler}
1878: * class.
1879: * @exception IllegalStateException if pool is not created yet.
1880: * @since 1.3
1881: */
1882: public ObjectPool getClientHandlerPool() {
1883: if (clientHandlerPool == null)
1884: throw new IllegalStateException(
1885: "No ClientHandler Pool available yet!");
1886: return clientHandlerPool;
1887: }
1888:
1889: /**
1890: * Sets the confiuration of the QuickServer.
1891: * @since 1.3
1892: */
1893: public void setConfig(QuickServerConfig config) {
1894: this .config = config;
1895: }
1896:
1897: /**
1898: * Returns the confiuration of the QuickServer.
1899: * @since 1.3
1900: */
1901: public QuickServerConfig getConfig() {
1902: return config;
1903: }
1904:
1905: /**
1906: * Makes the pool of ClientData
1907: * @since 1.3
1908: */
1909: private void makeClientDataPool(PoolableObjectFactory factory,
1910: PoolConfig opConfig) throws Exception {
1911: logger.finer("Creating ClientData pool");
1912: clientDataPool = poolManager.makeClientDataPool(factory,
1913: opConfig);
1914: poolManager.initPool(clientDataPool, opConfig);
1915: clientDataPool = makeQSObjectPool(clientDataPool);
1916: }
1917:
1918: /**
1919: * Returns ObjectPool of {@link org.quickserver.net.server.ClientData}
1920: * class. If ClientData was not poolable will return null.
1921: * @since 1.3
1922: */
1923: public ObjectPool getClientDataPool() {
1924: return clientDataPool;
1925: }
1926:
1927: /**
1928: * Returns {@link org.quickserver.sql.DBPoolUtil} object if
1929: * {@link org.quickserver.util.xmlreader.DBObjectPoolConfig} was set.
1930: * @return DBPoolUtil object if object could be loaded, else will return <code>null</code>
1931: * @since 1.3
1932: */
1933: public DBPoolUtil getDBPoolUtil() {
1934: return dBPoolUtil;
1935: }
1936:
1937: /**
1938: * Sets {@link org.quickserver.util.xmlreader.DBObjectPoolConfig}
1939: * @since 1.3
1940: */
1941: public void setDBObjectPoolConfig(
1942: DBObjectPoolConfig dBObjectPoolConfig) {
1943: getConfig().setDBObjectPoolConfig(dBObjectPoolConfig);
1944: }
1945:
1946: /**
1947: * Makes the pool of Database Objects
1948: * @since 1.3
1949: */
1950: private void makeDBObjectPool() throws Exception {
1951: if (getConfig().getDBObjectPoolConfig() != null) {
1952: logger.fine("Creating DBObject Pool");
1953: //logger.finest("Got:\n"+getConfig().getDBObjectPoolConfig().toXML(null));
1954: Class dbPoolUtilClass = getClass(getConfig()
1955: .getDBObjectPoolConfig().getDbPoolUtil(), true);
1956: dBPoolUtil = (DBPoolUtil) dbPoolUtilClass.newInstance();
1957: dBPoolUtil.setDatabaseConnections(getConfig()
1958: .getDBObjectPoolConfig().getDatabaseConnectionSet()
1959: .iterator());
1960: dBPoolUtil.initPool();
1961: }
1962: }
1963:
1964: /**
1965: * Tries to find the Client by the Id passed.
1966: * <p>
1967: * Note: This command is an expensive so do use it limitedly and
1968: * cache the returned object. But before you start sending message to the
1969: * cached object do validate that ClientHandler with you is currently
1970: * connected and is pointing to the same clinet has it was before.
1971: * This can be done as follows. <pre>
1972: foundClientHandler.isConnected(); //this method will through SocketException if not connected
1973: Date newTime = foundClientHandler.getClientConnectedTime();
1974: if(oldCachedTime!=newTime) {
1975: //Client had disconnected and ClientHandler was reused for
1976: //someother client, so write code to again find ur client
1977: foundClientHandler = handler.getServer().findFirstClientById("friendsid");
1978: ...
1979: }</pre>
1980: * </p>
1981: * @see ClientIdentifiable
1982: * @return ClientHandler object if client was found else <code>null</code>
1983: * @since 1.3.1
1984: */
1985: public ClientHandler findFirstClientById(String id) {
1986: return clientIdentifier.findFirstClientById(id);
1987: }
1988:
1989: /**
1990: * Returns an iterator containing all the
1991: * {@link org.quickserver.net.server.ClientHandler} that
1992: * are currently handling clients.
1993: * It is recommended not to change the collection under an iterator.
1994: *
1995: * It is imperative that the user manually synchronize on the returned collection
1996: * when iterating over it:
1997: * <code><pre>
1998: Eg:
1999:
2000: ClientData foundClientData = null;
2001: Object syncObj = quickserver.getClientIdentifier().getObjectToSynchronize();
2002: synchronized(syncObj) {
2003: Iterator iterator = quickserver.findAllClient();
2004: while(iterator.hasNext()) {
2005: foundClientHandler = (ClientHandler) iterator.next();
2006: ....
2007: }
2008: }
2009:
2010: //OR
2011:
2012: ClientData foundClientData = null;
2013: ClientIdentifier clientIdentifier = quickserver.getClientIdentifier();
2014: synchronized(clientIdentifier.getObjectToSynchronize()) {
2015: Iterator iterator = clientIdentifier.findAllClient();
2016: while(iterator.hasNext()) {
2017: foundClientHandler = (ClientHandler) iterator.next();
2018: ....
2019: }
2020: }
2021: </code></pre>
2022: * @since 1.3.1
2023: */
2024: public Iterator findAllClient() {
2025: return clientIdentifier.findAllClient();
2026: }
2027:
2028: /**
2029: * Tries to find the Client by the matching pattern passed to the Id.
2030: * <p>
2031: * Note: This command is an expensive so do use it limitedly and
2032: * cache the returned object. But before you start sending message to the
2033: * cached object do validate that ClientHandler with you is currently
2034: * connected and is pointing to the same clinet has it was before.
2035: * This can be done as follows. <pre>
2036: foundClientHandler.isConnected(); //this method will through SocketException if not connected
2037: Date newTime = foundClientHandler.getClientConnectedTime();
2038: if(oldCachedTime!=newTime) {
2039: //Client had disconnected and ClientHandler was reused for
2040: //someother client, so write code to again find ur client
2041: foundClientHandler = handler.getServer().findFirstClientById("friendsid");
2042: ...
2043: }</pre>
2044: * </p>
2045: * @see ClientIdentifiable
2046: * @return ClientHandler object if client was found else <code>null</code>
2047: * @since 1.3.2
2048: */
2049: public Iterator findAllClientById(String pattern) {
2050: return clientIdentifier.findAllClientById(pattern);
2051: }
2052:
2053: /**
2054: * Tries to find the Client by the Key passed.
2055: * <p>
2056: * Note: This command is an expensive so do use it limitedly and
2057: * cache the returned object. But before you start sending message to the
2058: * cached object do validate that ClientHandler with you is currently
2059: * connected and is pointing to the same clinet has it was before.
2060: * This can be done as follows. <pre>
2061: foundClientHandler.isConnected(); //this method will through SocketException if not connected
2062: Date newTime = foundClientHandler.getClientConnectedTime();
2063: if(oldCachedTime!=newTime) {
2064: //Client had disconnected and ClientHandler was reused for
2065: //someother client, so write code to again find ur client
2066: foundClientHandler = handler.getServer().findClientByKey("friendskey");
2067: ...
2068: }</pre>
2069: * </p>
2070: * @see ClientIdentifiable
2071: * @return ClientHandler object if client was found else <code>null</code>
2072: * @since 1.3.1
2073: */
2074: public ClientHandler findClientByKey(String key) {
2075: return clientIdentifier.findClientByKey(key);
2076: }
2077:
2078: /**
2079: * Tries to find the Client by the matching pattern passed to the key.
2080: * <p>
2081: * Note: This command is an expensive so do use it limitedly and
2082: * cache the returned object. But before you start sending message to the
2083: * cached object do validate that ClientHandler with you is currently
2084: * connected and is pointing to the same clinet has it was before.
2085: * This can be done as follows. <pre>
2086: foundClientHandler.isConnected(); //this method will through SocketException if not connected
2087: Date newTime = foundClientHandler.getClientConnectedTime();
2088: if(oldCachedTime!=newTime) {
2089: //Client had disconnected and ClientHandler was reused for
2090: //some other client, so write code to again find ur client
2091: foundClientHandler = handler.getServer().findFirstClientByKey("friendsid");
2092: ...
2093: }</pre>
2094: * </p>
2095: * @see ClientIdentifiable
2096: * @return ClientHandler object if client was found else <code>null</code>
2097: * @since 1.4
2098: */
2099: public Iterator findAllClientByKey(String pattern) {
2100: return clientIdentifier.findAllClientByKey(pattern);
2101: }
2102:
2103: /**
2104: * Sets next client has a trusted client.
2105: * <p>This will skip any authentication and will not set any timout.</p>
2106: * @since 1.3.2
2107: */
2108: public void nextClientIsTrusted() {
2109: setSkipValidation(true);
2110: }
2111:
2112: /**
2113: * @since 1.3.2
2114: */
2115: private boolean getSkipValidation() {
2116: return skipValidation;
2117: }
2118:
2119: /**
2120: * @since 1.3.2
2121: */
2122: private synchronized void setSkipValidation(boolean validation) {
2123: skipValidation = validation;
2124: }
2125:
2126: /**
2127: * Sets the communication logging flag.
2128: * @see #getCommunicationLogging
2129: * @since 1.3.2
2130: */
2131: public void setCommunicationLogging(boolean communicationLogging) {
2132: this .communicationLogging = communicationLogging;
2133: }
2134:
2135: /**
2136: * Returns the communication logging flag.
2137: * @see #setCommunicationLogging
2138: * @since 1.3.2
2139: */
2140: public boolean getCommunicationLogging() {
2141: return communicationLogging;
2142: }
2143:
2144: /**
2145: * Sets the SecurityManager class
2146: * @param securityManagerClass the fully qualified name of the class
2147: * that extends {@link java.lang.SecurityManager}.
2148: * @see #getSecurityManagerClass
2149: * @since 1.3.3
2150: */
2151: public void setSecurityManagerClass(String securityManagerClass) {
2152: if (securityManagerClass != null)
2153: this .securityManagerClass = securityManagerClass;
2154: }
2155:
2156: /**
2157: * Returns the SecurityManager class
2158: * @see #setSecurityManagerClass
2159: * @since 1.3.3
2160: */
2161: public String getSecurityManagerClass() {
2162: return securityManagerClass;
2163: }
2164:
2165: public SecurityManager getSecurityManager() throws AppException {
2166: if (getSecurityManagerClass() == null)
2167: return null;
2168: SecurityManager sm = null;
2169: try {
2170: sm = (SecurityManager) getClass(getSecurityManagerClass(),
2171: true).newInstance();
2172: } catch (ClassNotFoundException e) {
2173: throw new AppException(e.getMessage());
2174: } catch (InstantiationException e) {
2175: throw new AppException(e.getMessage());
2176: } catch (IllegalAccessException e) {
2177: throw new AppException(e.getMessage());
2178: }
2179: return sm;
2180: }
2181:
2182: /**
2183: * Sets the Access constraints
2184: * @since 1.3.3
2185: */
2186: public void setAccessConstraintConfig(
2187: AccessConstraintConfig accessConstraintConfig) {
2188: this .accessConstraintConfig = accessConstraintConfig;
2189: }
2190:
2191: /**
2192: * Returns Access constraints if present else <code>null</code>.
2193: * @since 1.3.3
2194: */
2195: public AccessConstraintConfig getAccessConstraintConfig() {
2196: return accessConstraintConfig;
2197: }
2198:
2199: /**
2200: * Sets the classloader to be used to load the dynamicaly resolved
2201: * classes
2202: * @since 1.3.3
2203: */
2204: public void setClassLoader(ClassLoader classLoader) {
2205: this .classLoader = classLoader;
2206: Thread.currentThread().setContextClassLoader(classLoader);
2207: }
2208:
2209: /**
2210: * Gets the classloader used to load the dynamicaly resolved
2211: * classes.
2212: * @since 1.4.6
2213: */
2214: public ClassLoader getClassLoader() {
2215: return classLoader;
2216: }
2217:
2218: /**
2219: * Utility method to load a class
2220: * @since 1.3.3
2221: */
2222: public Class getClass(String name, boolean reload)
2223: throws ClassNotFoundException {
2224: if (name == null)
2225: throw new IllegalArgumentException(
2226: "Class name can't be null!");
2227: logger.finest("Class: " + name + ", reload: " + reload);
2228: if (reload == true && classLoader != null) {
2229: return classLoader.loadClass(name);
2230: } else if (reload == true && classLoader == null
2231: && this .getClass().getClassLoader() != null) {
2232: return this .getClass().getClassLoader().loadClass(name);
2233: } else if (reload == false && classLoader != null) {
2234: return Class.forName(name, true, classLoader);
2235: } else /*if(reload==false && classLoader==null)*/{
2236: return Class.forName(name, true, this .getClass()
2237: .getClassLoader());
2238: }
2239: }
2240:
2241: /**
2242: * Sets the applications jar/s path. This can be either absolute or
2243: * relative(to config file) path to the jar file or the directory containing
2244: * the jars needed by the application.
2245: * @see #getApplicationJarPath
2246: * @since 1.3.3
2247: */
2248: protected void setApplicationJarPath(String applicationJarPath) {
2249: this .applicationJarPath = applicationJarPath;
2250: }
2251:
2252: /**
2253: * Returns the applications jar/s path. This can be either absolute or
2254: * relative(to config file) path to the jar file or the directory containing the
2255: * jars needed by the application.
2256: * @see #setApplicationJarPath
2257: * @since 1.3.3
2258: */
2259: public String getApplicationJarPath() {
2260: return applicationJarPath;
2261: }
2262:
2263: /**
2264: * Sets the ServerHooks
2265: * @since 1.3.3
2266: */
2267: public void setServerHooks(ServerHooks serverHooks) {
2268: this .serverHooks = serverHooks;
2269: }
2270:
2271: /**
2272: * Returns ServerHooks if present else <code>null</code>.
2273: * @since 1.3.3
2274: */
2275: public ServerHooks getServerHooks() {
2276: if (serverHooks == null)
2277: serverHooks = new ServerHooks();
2278: return serverHooks;
2279: }
2280:
2281: /**
2282: * @since 1.3.3
2283: */
2284: private void loadServerHooksClasses() {
2285: if (getServerHooks() == null)
2286: return;
2287: listOfServerHooks = new ArrayList();
2288: ServerHook serverHook = null;
2289: String serverHookClassName = null;
2290: Class serverHookClass = null;
2291:
2292: //add system hooks
2293: serverHook = new GhostSocketReaper();
2294: serverHook.initHook(QuickServer.this );
2295: listOfServerHooks.add(serverHook);
2296: ghostSocketReaper = (GhostSocketReaper) serverHook;
2297:
2298: //add user hooks if any
2299: Iterator iterator = getServerHooks().iterator();
2300: while (iterator.hasNext()) {
2301: serverHookClassName = (String) iterator.next();
2302: try {
2303: serverHookClass = getClass(serverHookClassName, true);
2304: serverHook = (ServerHook) serverHookClass.newInstance();
2305: serverHook.initHook(QuickServer.this );
2306: listOfServerHooks.add(serverHook);
2307: logger.info("Loaded server hook: "
2308: + serverHookClassName);
2309: logger.fine("Server hook info: " + serverHook.info());
2310: } catch (Exception e) {
2311: logger.warning("Could not load server hook ["
2312: + serverHookClassName + "]: " + e);
2313: logger
2314: .fine("StackTrace:\n"
2315: + MyString.getStackTrace(e));
2316: }
2317: }//end of while
2318: }
2319:
2320: /**
2321: * @since 1.3.3
2322: */
2323: private void processServerHooks(int event) {
2324: if (listOfServerHooks == null) {
2325: logger.warning("listOfServerHooks was null!");
2326: return;
2327: }
2328: ServerHook serverHook = null;
2329: boolean result = false;
2330: Iterator iterator = listOfServerHooks.iterator();
2331:
2332: String hooktype = "UNKNOWN";
2333: switch (event) {
2334: case ServerHook.PRE_STARTUP:
2335: hooktype = "PRE_STARTUP";
2336: break;
2337: case ServerHook.POST_STARTUP:
2338: hooktype = "POST_STARTUP";
2339: break;
2340: case ServerHook.PRE_SHUTDOWN:
2341: hooktype = "PRE_SHUTDOWN";
2342: break;
2343: case ServerHook.POST_SHUTDOWN:
2344: hooktype = "POST_SHUTDOWN";
2345: break;
2346: }
2347:
2348: while (iterator.hasNext()) {
2349: serverHook = (ServerHook) iterator.next();
2350: try {
2351: result = serverHook.handleEvent(event);
2352: } catch (Exception e) {
2353: result = false;
2354: logger.warning("Error invoking " + hooktype + " hook ["
2355: + serverHook.getClass().getName() + "]: "
2356: + e.getMessage());
2357: }
2358: logger.fine("Invoked " + hooktype + " hook ["
2359: + serverHook.getClass().getName() + "] was: "
2360: + result);
2361: }
2362: }
2363:
2364: /**
2365: * Creates and returns a copy of this object.
2366: * @since 1.3.3
2367: */
2368: public Object clone() {
2369: Object object = null;
2370: try {
2371: object = super .clone();
2372: QuickServer _qs = (QuickServer) object;
2373: _qs.setQSAdminServer(new QSAdminServer(_qs));
2374: } catch (CloneNotSupportedException e) {
2375: logger.warning("Error cloning : " + e);//should not happ
2376: }
2377: return object;
2378: }
2379:
2380: /**
2381: * Sets the Secure setting for QuickServer
2382: * @since 1.4.0
2383: */
2384: public void setSecure(Secure secure) {
2385: this .secure = secure;
2386: }
2387:
2388: /**
2389: * Returns Secure setting for QuickServer
2390: * @since 1.4.0
2391: */
2392: public Secure getSecure() {
2393: if (secure == null)
2394: secure = new Secure();
2395: return secure;
2396: }
2397:
2398: /**
2399: * <p>Returns if the server is running in Secure mode [SSL or TLS].</p>
2400: * @since 1.4.0
2401: */
2402: public boolean isRunningSecure() {
2403: return runningSecure;
2404: }
2405:
2406: /**
2407: * <p>Sets the server mode if its running in Secure mode [SSL or TLS].</p>
2408: * @since 1.4.0
2409: */
2410: public void setRunningSecure(boolean runningSecure) {
2411: this .runningSecure = runningSecure;
2412: }
2413:
2414: private File makeAbsoluteToConfig(String fileName) {
2415: Assertion.affirm(fileName != null, "FileName can't be null");
2416: return ConfigReader.makeAbsoluteToConfig(fileName, getConfig());
2417: }
2418:
2419: /**
2420: * Returns a ServerSocket object to be used for listening.
2421: * @since 1.4.0
2422: */
2423: protected void makeServerSocket() throws BindException, IOException {
2424: server = null;
2425: logger.finest("Binding " + getName() + " to IP: "
2426: + getBindAddr());
2427: InetSocketAddress bindAddress = new InetSocketAddress(
2428: getBindAddr(), getPort());
2429:
2430: try {
2431: NetworkInterface ni = NetworkInterface
2432: .getByInetAddress(getBindAddr());
2433: if (ni != null) {
2434: logger.fine("NetworkInterface: " + ni);
2435: }
2436: } catch (Exception igrnore) {/*ignore*/
2437: } catch (Error igrnore) {/*ignore*/
2438: }
2439:
2440: if (getSecure().isEnable() == false) {
2441: logger
2442: .fine("Making a normal ServerSocket for "
2443: + getName());
2444: setRunningSecure(false);
2445:
2446: if (getBlockingMode() == false) {
2447: //for non-blocking
2448: serverSocketChannel = ServerSocketChannel.open();
2449: server = serverSocketChannel.socket();
2450: server.bind(bindAddress, getBasicConfig()
2451: .getAdvancedSettings().getBacklog());
2452: } else {
2453: //for blocking
2454: server = new ServerSocket(getPort(), getBasicConfig()
2455: .getAdvancedSettings().getBacklog(),
2456: getBindAddr());
2457: }
2458: } else {
2459: logger
2460: .fine("Making a secure ServerSocket for "
2461: + getName());
2462: try {
2463: ServerSocketFactory ssf = getSSLContext()
2464: .getServerSocketFactory();
2465: SSLServerSocket serversocket = (SSLServerSocket) ssf
2466: .createServerSocket(getPort(), getBasicConfig()
2467: .getAdvancedSettings().getBacklog(),
2468: getBindAddr());
2469: serversocket.setNeedClientAuth(secure
2470: .isClientAuthEnable());
2471: setRunningSecure(true);
2472:
2473: secureStoreManager.logSSLServerSocketInfo(serversocket);
2474:
2475: server = serversocket;
2476: serverSocketChannel = server.getChannel();
2477: if (serverSocketChannel == null
2478: && getBlockingMode() == false) {
2479: logger
2480: .warning("Secure Server does not support Channel! So will run in blocking mode.");
2481: blockingMode = true;
2482: }
2483: } catch (NoSuchAlgorithmException e) {
2484: logger.warning("NoSuchAlgorithmException : " + e);
2485: throw new IOException("Error creating secure socket : "
2486: + e.getMessage());
2487: } catch (KeyManagementException e) {
2488: logger.warning("KeyManagementException : " + e);
2489: throw new IOException("Error creating secure socket : "
2490: + e.getMessage());
2491: }
2492: }
2493:
2494: server.setReuseAddress(true);
2495:
2496: if (getBlockingMode() == false) {
2497: logger.fine("Server Mode " + getName() + " - Non Blocking");
2498: if (selector == null || selector.isOpen() == false) {
2499: logger.finest("Opening new selector");
2500: selector = Selector.open();
2501: } else {
2502: logger.finest("Reusing selector: " + selector);
2503: }
2504: serverSocketChannel.configureBlocking(false);
2505: serverSocketChannel.register(selector,
2506: SelectionKey.OP_ACCEPT);
2507: selector.wakeup();
2508: } else {
2509: logger.fine("Server Mode " + getName() + " - Blocking");
2510: }
2511: }
2512:
2513: /**
2514: * Sets the basic confiuration of the QuickServer.
2515: * @since 1.4.0
2516: */
2517: public void setBasicConfig(BasicServerConfig basicConfig)
2518: throws Exception {
2519: Assertion.affirm(basicConfig != null,
2520: "BasicServerConfig can't be null");
2521: this .basicConfig = basicConfig;
2522: }
2523:
2524: /**
2525: * Returns the basic confiuration of the QuickServer.
2526: * @since 1.4.0
2527: */
2528: public BasicServerConfig getBasicConfig() {
2529: return basicConfig;
2530: }
2531:
2532: /**
2533: * Loads the <code>SSLContext</code> from Secure configuring if set.
2534: * @see #setSecure
2535: * @since 1.4.0
2536: */
2537: public void loadSSLContext() throws IOException {
2538: if (getSecure().isLoad() == false) {
2539: throw new IllegalStateException(
2540: "Secure setting is not yet enabled for loading!");
2541: }
2542: logger.info("Loading Secure Context..");
2543: km = null;
2544: tm = null;
2545: try {
2546: String ssManager = "org.quickserver.security.SecureStoreManager";
2547: if (getSecure().getSecureStore() != null)
2548: ssManager = getSecure().getSecureStore()
2549: .getSecureStoreManager();
2550:
2551: Class secureStoreManagerClass = getClass(ssManager, true);
2552:
2553: secureStoreManager = (SecureStoreManager) secureStoreManagerClass
2554: .newInstance();
2555:
2556: km = secureStoreManager.loadKeyManagers(getConfig());
2557: logger.fine("KeyManager got");
2558:
2559: tm = secureStoreManager.loadTrustManagers(getConfig());
2560: logger.fine("TrustManager got");
2561:
2562: sslc = secureStoreManager.getSSLContext(getConfig()
2563: .getSecure().getProtocol());
2564: sslc.init(km, tm, null);
2565: logger.fine("SSLContext loaded");
2566: } catch (KeyStoreException e) {
2567: logger.warning("KeyStoreException : " + e);
2568: throw new IOException("Error creating secure socket : "
2569: + e.getMessage());
2570: } catch (NoSuchAlgorithmException e) {
2571: logger.warning("NoSuchAlgorithmException : " + e);
2572: throw new IOException("Error creating secure socket : "
2573: + e.getMessage());
2574: } catch (NoSuchProviderException e) {
2575: logger.warning("NoSuchProviderException : " + e);
2576: throw new IOException("Error creating secure socket : "
2577: + e.getMessage());
2578: } catch (UnrecoverableKeyException e) {
2579: logger.warning("UnrecoverableKeyException : " + e);
2580: throw new IOException("Error creating secure socket : "
2581: + e.getMessage());
2582: } catch (CertificateException e) {
2583: logger.warning("CertificateException : " + e);
2584: throw new IOException("Error creating secure socket : "
2585: + e.getMessage());
2586: } catch (KeyManagementException e) {
2587: logger.warning("KeyManagementException : " + e);
2588: throw new IOException("Error creating secure socket : "
2589: + e.getMessage());
2590: } catch (GeneralSecurityException e) {
2591: logger.warning("GeneralSecurityException : " + e);
2592: throw new IOException("Error creating secure socket : "
2593: + e.getMessage());
2594: } catch (ClassNotFoundException e) {
2595: logger.warning("ClassNotFoundException : " + e);
2596: throw new IOException("Error creating secure socket : "
2597: + e.getMessage());
2598: } catch (InstantiationException e) {
2599: logger.warning("InstantiationException : " + e);
2600: throw new IOException("Error creating secure socket : "
2601: + e.getMessage());
2602: } catch (IllegalAccessException e) {
2603: logger.warning("IllegalAccessException : " + e);
2604: throw new IOException("Error creating secure socket : "
2605: + e.getMessage());
2606: }
2607: }
2608:
2609: /**
2610: * Returns the <code>SSLContext</code> from Secure configuring.
2611: * @see #loadSSLContext
2612: * @since 1.4.0
2613: */
2614: public SSLContext getSSLContext() throws IOException,
2615: NoSuchAlgorithmException, KeyManagementException {
2616: return getSSLContext(null);
2617: }
2618:
2619: /**
2620: * Returns the <code>SSLContext</code> object that implements the specified
2621: * secure socket protocol from Secure configuring.
2622: * @see #loadSSLContext
2623: * @param protocol the standard name of the requested protocol. If <code>null</code> will use the protocol set in secure configuration of the server.
2624: * @throws IOException
2625: * @throws NoSuchAlgorithmException
2626: * @throws KeyManagementException
2627: * @since 1.4.0
2628: */
2629: public SSLContext getSSLContext(String protocol)
2630: throws IOException, NoSuchAlgorithmException,
2631: KeyManagementException {
2632: if (sslc == null)
2633: loadSSLContext();
2634: if (protocol != null && secureStoreManager != null) {
2635: SSLContext _sslc = secureStoreManager
2636: .getSSLContext(protocol);
2637: _sslc.init(km, tm, null);
2638: return _sslc;
2639: }
2640: return sslc;
2641: }
2642:
2643: /**
2644: * Returns a SSLSocketFactory object to be used for creating SSLSockets.
2645: * Secure socket protocol will be picked from the Secure configuring.
2646: * @see #setSecure
2647: * @throws IOException
2648: * @throws NoSuchAlgorithmException
2649: * @throws KeyManagementException
2650: * @since 1.4.0
2651: */
2652: public SSLSocketFactory getSSLSocketFactory() throws IOException,
2653: NoSuchAlgorithmException, KeyManagementException {
2654: if (sslc == null)
2655: loadSSLContext();
2656: return secureStoreManager.getSocketFactory(getSSLContext());
2657: }
2658:
2659: /**
2660: * Returns a SSLSocketFactory object to be used for creating SSLSockets.
2661: * @see #setSecure
2662: * @param protocol the standard name of the requested protocol. If
2663: * <code>null</code> will use the protocol set in secure configuration
2664: * of the server.
2665: * @throws IOException
2666: * @throws NoSuchAlgorithmException
2667: * @throws KeyManagementException
2668: * @since 1.4.0
2669: */
2670: public SSLSocketFactory getSSLSocketFactory(String protocol)
2671: throws IOException, NoSuchAlgorithmException,
2672: KeyManagementException {
2673: if (sslc == null)
2674: loadSSLContext();
2675: return secureStoreManager
2676: .getSocketFactory(getSSLContext(protocol));
2677: }
2678:
2679: /**
2680: * Sets the ClientBinaryHandler class that interacts with
2681: * client sockets to handle binary data.
2682: * @param handler object the fully qualified name of the class that
2683: * implements {@link ClientBinaryHandler}
2684: * @see #getClientBinaryHandler
2685: * @since 1.4
2686: */
2687: public void setClientBinaryHandler(String handler) {
2688: clientBinaryHandlerString = handler;
2689: logger.finest("Set to " + handler);
2690: }
2691:
2692: /**
2693: * Returns the ClientBinaryHandler class that interacts with
2694: * client sockets.
2695: * @see #setClientBinaryHandler
2696: * @since 1.4
2697: */
2698: public String getClientBinaryHandler() {
2699: return clientBinaryHandlerString;
2700: }
2701:
2702: /**
2703: * Sets the Selector (NIO).
2704: * @since 1.4.5
2705: */
2706: public void setSelector(Selector selector) {
2707: this .selector = selector;
2708: }
2709:
2710: /**
2711: * Returns the Selector (NIO),if any.
2712: * @since 1.4.5
2713: */
2714: public Selector getSelector() {
2715: return selector;
2716: }
2717:
2718: /**
2719: * Starts server in blocking mode.
2720: * @since 1.4.5
2721: */
2722: private void runBlocking(TheClient theClient) throws Exception {
2723: Socket client = null;
2724: ClientHandler _chPolled = null;
2725: int linger = getBasicConfig().getAdvancedSettings()
2726: .getSocketLinger();
2727:
2728: //long stime = System.currentTimeMillis();
2729: //long etime = System.currentTimeMillis();
2730: while (true) {
2731: //etime = System.currentTimeMillis();
2732: //System.out.println("Time Taken: "+(etime-stime));
2733: client = server.accept();
2734: //stime = System.currentTimeMillis();
2735:
2736: if (linger < 0) {
2737: client.setSoLinger(false, 0);
2738: } else {
2739: client.setSoLinger(true, linger);
2740: }
2741:
2742: if (stopServer) {
2743: //Client connected when server was about to be shutdown.
2744: try {
2745: client.close();
2746: } catch (Exception e) {
2747: }
2748: break;
2749: }
2750:
2751: if (checkAccessConstraint(client) == false) {
2752: continue;
2753: }
2754:
2755: //Check if max connection has reached
2756: if (getSkipValidation() != true
2757: && maxConnection != -1
2758: && getClientHandlerPool().getNumActive() >= maxConnection) {
2759: theClient.setClientEvent(ClientEvent.MAX_CON_BLOCKING);
2760: } else {
2761: theClient.setClientEvent(ClientEvent.RUN_BLOCKING);
2762: }
2763:
2764: theClient.setTrusted(getSkipValidation());
2765: theClient.setSocket(client);
2766: theClient.setSocketChannel(client.getChannel()); //mostly null
2767:
2768: if (clientDataClass != null) {
2769: if (getClientDataPool() == null) {
2770: clientData = (ClientData) clientDataClass
2771: .newInstance();
2772: } else {
2773: clientData = (ClientData) getClientDataPool()
2774: .borrowObject();
2775: }
2776: theClient.setClientData(clientData);
2777: }
2778:
2779: try {
2780: _chPolled = (ClientHandler) getClientHandlerPool()
2781: .borrowObject();
2782: _chPolled.handleClient(theClient);
2783: } catch (java.util.NoSuchElementException nsee) {
2784: logger
2785: .warning("Could not borrow ClientHandler from pool. Error: "
2786: + nsee);
2787: logger.warning("Closing Socket [" + client
2788: + "] since no ClientHandler available.");
2789: client.close();
2790: }
2791:
2792: if (_chPolled != null) {
2793: try {
2794: getClientPool().addClient(_chPolled, true);
2795: } catch (java.util.NoSuchElementException nsee) {
2796: logger
2797: .warning("Could not borrow Thread from pool. Error: "
2798: + nsee);
2799: //logger.warning("Closing Socket ["+client+"] since no Thread available.");
2800: //client.close();
2801: //returnClientHandlerToPool(_chPolled);
2802: }
2803: _chPolled = null;
2804: }
2805: client = null;
2806:
2807: //reset it back
2808: setSkipValidation(false);
2809: }//end of loop
2810: }
2811:
2812: /**
2813: * Starts server in non-blocking mode.
2814: * @since 1.4.5
2815: */
2816: private void runNonBlocking(TheClient theClient) throws Exception {
2817: int selectCount = 0;
2818: Iterator iterator = null;
2819: SelectionKey key = null;
2820: ServerSocketChannel serverChannel = null;
2821: SocketChannel socketChannel = null;
2822: Socket client = null;
2823: ClientHandler _chPolled = null;
2824: boolean stopServerProcessed = false;
2825: int linger = getBasicConfig().getAdvancedSettings()
2826: .getSocketLinger();
2827: registerChannelRequestMap = new HashMap();
2828:
2829: while (true) {
2830: selectCount = selector.select(500);
2831: //selectCount = selector.select();//for testing
2832:
2833: //check for any pending registerChannel req.
2834: synchronized (registerChannelRequestMap) {
2835: if (registerChannelRequestMap.size() > 0) {
2836: RegisterChannelRequest req = null;
2837: Object hashkey = null;
2838: iterator = registerChannelRequestMap.keySet()
2839: .iterator();
2840: while (iterator.hasNext()) {
2841: hashkey = iterator.next();
2842: req = (RegisterChannelRequest) registerChannelRequestMap
2843: .get(hashkey);
2844: req.register(getSelector());
2845: }
2846: iterator = null;
2847: registerChannelRequestMap.clear();
2848: }//if
2849: }//sync
2850:
2851: if (stopServer == true && stopServerProcessed == false) {
2852: logger.warning("Closing " + getName());
2853: serverSocketChannel.close();
2854: stopServerProcessed = true;
2855:
2856: server = null;
2857: serverSocketChannel = null;
2858:
2859: setServiceState(Service.STOPPED);
2860: logger.warning("Closed " + getName());
2861:
2862: processServerHooks(ServerHook.POST_SHUTDOWN);
2863: }
2864:
2865: if (stopServer == false && stopServerProcessed == true) {
2866: logger
2867: .finest("Server must have re-started.. will break");
2868: break;
2869: }
2870:
2871: if (selectCount == 0 && stopServerProcessed == true) {
2872: java.util.Set keyset = selector.keys();
2873: if (keyset.isEmpty() == true && getClientCount() <= 0) {
2874: break;
2875: } else {
2876: continue;
2877: }
2878: } else if (selectCount == 0) {
2879: continue;
2880: }
2881:
2882: iterator = selector.selectedKeys().iterator();
2883: while (iterator.hasNext()) {
2884: key = (SelectionKey) iterator.next();
2885:
2886: if (key.isValid() == false) {
2887: iterator.remove();
2888: continue;
2889: }
2890:
2891: if (key.isAcceptable() && stopServer == false) {
2892: logger.finest("Key is Acceptable");
2893: serverChannel = (ServerSocketChannel) key.channel();
2894: socketChannel = serverChannel.accept();
2895:
2896: if (socketChannel == null) {
2897: iterator.remove();
2898: continue;
2899: }
2900:
2901: client = socketChannel.socket();
2902:
2903: if (linger < 0) {
2904: client.setSoLinger(false, 0);
2905: } else {
2906: client.setSoLinger(true, linger);
2907: }
2908:
2909: if (checkAccessConstraint(client) == false) {
2910: iterator.remove();
2911: continue;
2912: }
2913:
2914: socketChannel.configureBlocking(false);
2915: theClient.setTrusted(getSkipValidation());
2916: theClient.setSocket(socketChannel.socket());
2917: theClient.setSocketChannel(socketChannel);
2918:
2919: if (clientDataClass != null) {
2920: if (getClientDataPool() == null) {
2921: clientData = (ClientData) clientDataClass
2922: .newInstance();
2923: } else {
2924: //borrow a object from pool
2925: clientData = (ClientData) getClientDataPool()
2926: .borrowObject();
2927: }
2928: theClient.setClientData(clientData);
2929: }
2930:
2931: //Check if max connection has reached
2932: if (getSkipValidation() != true
2933: && maxConnection != -1
2934: && getClientHandlerPool().getNumActive() >= maxConnection) {
2935: theClient.setClientEvent(ClientEvent.MAX_CON);
2936: } else {
2937: theClient.setClientEvent(ClientEvent.ACCEPT);
2938: }
2939:
2940: try {
2941: _chPolled = (ClientHandler) getClientHandlerPool()
2942: .borrowObject();
2943: logger.finest("Asking " + _chPolled.getName()
2944: + " to handle.");
2945: _chPolled.handleClient(theClient);
2946: } catch (java.util.NoSuchElementException nsee) {
2947: logger
2948: .warning("Could not borrow ClientHandler Object from pool. Error: "
2949: + nsee);
2950: logger
2951: .warning("Closing SocketChannel ["
2952: + serverChannel.socket()
2953: + "] since no ClientHandler available.");
2954: socketChannel.close();
2955: }
2956:
2957: if (_chPolled != null) {
2958: try {
2959: getClientPool().addClient(_chPolled, true);
2960: } catch (java.util.NoSuchElementException nsee) {
2961: logger
2962: .warning("Could not borrow Thread from pool. Error: "
2963: + nsee);
2964: //logger.warning("Closing SocketChannel ["+serverChannel.socket()+"] since no Thread available.");
2965: //socketChannel.close();
2966: //returnClientHandlerToPool(_chPolled);
2967: }
2968: _chPolled = null;
2969: }
2970: socketChannel = null;
2971: client = null;
2972:
2973: setSkipValidation(false);//reset it back
2974: } else if (key.isValid() && key.isReadable()) {
2975: boolean addedEvent = false;
2976: ClientHandler _ch = null;
2977: try {
2978: _ch = (ClientHandler) key.attachment();
2979: logger
2980: .finest("Key is Readable, removing OP_READ from interestOps for "
2981: + _ch.getName());
2982: key.interestOps(key.interestOps()
2983: & (~SelectionKey.OP_READ));
2984: _ch.addEvent(ClientEvent.READ);
2985: addedEvent = true;
2986: //_ch.setSelectionKey(key);
2987: getClientPool().addClient(_ch);
2988: } catch (CancelledKeyException cke) {
2989: logger
2990: .fine("Ignored Error - Key was Cancelled: "
2991: + cke);
2992: } catch (java.util.NoSuchElementException nsee) {
2993: logger
2994: .finest("NoSuchElementException: "
2995: + nsee);
2996: if (addedEvent)
2997: _ch.removeEvent(ClientEvent.READ);
2998: continue;//no need to remove the key
2999: }
3000: _ch = null;
3001: } else if (key.isValid() && key.isWritable()) {
3002: if (getClientPool().shouldNioWriteHappen() == false) {
3003: continue; //no need to remove the key
3004: }
3005: boolean addedEvent = false;
3006: ClientHandler _ch = null;
3007: try {
3008: _ch = (ClientHandler) key.attachment();
3009: logger
3010: .finest("Key is Writable, removing OP_WRITE from interestOps for "
3011: + _ch.getName());
3012: //remove OP_WRITE from interest set
3013: key.interestOps(key.interestOps()
3014: & (~SelectionKey.OP_WRITE));
3015: _ch.addEvent(ClientEvent.WRITE);
3016: addedEvent = true;
3017: //_ch.setSelectionKey(key);
3018: getClientPool().addClient(_ch);
3019: } catch (CancelledKeyException cke) {
3020: logger
3021: .fine("Ignored Error - Key was Cancelled: "
3022: + cke);
3023: } catch (java.util.NoSuchElementException nsee) {
3024: logger
3025: .finest("NoSuchElementException: "
3026: + nsee);
3027: if (addedEvent)
3028: _ch.removeEvent(ClientEvent.WRITE);
3029: continue;//no need to remove the key
3030: }
3031: _ch = null;
3032: } else if (stopServer == true && key.isAcceptable()) {
3033: //we will not accept this key
3034: setSkipValidation(false);//reset it back
3035: } else {
3036: logger.warning("Unknown key got in SelectionKey: "
3037: + key);
3038: }
3039: iterator.remove(); //Remove key
3040:
3041: Thread.yield();
3042: } //end of iterator
3043: iterator = null;
3044: }//end of loop
3045: }
3046:
3047: private boolean checkAccessConstraint(Socket socket) {
3048: try {
3049: if (getAccessConstraintConfig() != null) {
3050: getAccessConstraintConfig().checkAccept(socket);
3051: }
3052: return true;
3053: } catch (SecurityException se) {
3054: logger
3055: .warning("SecurityException occurred accepting connection : "
3056: + se.getMessage());
3057: return false;
3058: }
3059: }
3060:
3061: /**
3062: * Register the given channel for the given operations. This adds the request
3063: * to a list and will be processed after selector select wakes up.
3064: * @return boolean flag to indicate if new entry was added to the list to register.
3065: * @since 1.4.5
3066: */
3067: public boolean registerChannel(SocketChannel channel, int ops,
3068: Object att) throws IOException, ClosedChannelException {
3069: if (getSelector() == null) {
3070: throw new IllegalStateException("Selector is not open!");
3071: }
3072: if (channel == null) {
3073: throw new IllegalArgumentException(
3074: "Can't register a null channel!");
3075: }
3076:
3077: if (channel.isConnected() == false) {
3078: throw new ClosedChannelException();
3079: }
3080:
3081: RegisterChannelRequest req = new RegisterChannelRequest(
3082: channel, ops, att);
3083: RegisterChannelRequest reqOld = null;
3084: synchronized (registerChannelRequestMap) {
3085: reqOld = (RegisterChannelRequest) registerChannelRequestMap
3086: .get(channel);
3087: if (reqOld == null) {
3088: registerChannelRequestMap.put(channel, req);
3089: getSelector().wakeup();
3090: return true;
3091: } else {
3092: if (reqOld.equals(req) == false) {
3093: reqOld.setOps(reqOld.getOps() | req.getOps());
3094: reqOld.setAtt(req.getAtt());
3095: return true;
3096: }
3097: return false;
3098: }
3099: }
3100: /*
3101: logger.warning("Before register...");
3102: channel.register(getSelector(), ops, att);
3103: logger.warning("Before wakeup and after register...");
3104: getSelector().wakeup();
3105: logger.warning("After wakeup...");
3106: */
3107: }
3108:
3109: /**
3110: * Makes the pool of ByteBuffer
3111: * @since 1.4.5
3112: */
3113: private void makeByteBufferPool(PoolConfig opConfig) {
3114: logger.finer("Creating ByteBufferPool pool");
3115:
3116: int bufferSize = getBasicConfig().getAdvancedSettings()
3117: .getByteBufferSize();
3118: boolean useDirectByteBuffer = getBasicConfig()
3119: .getAdvancedSettings().getUseDirectByteBuffer();
3120: PoolableObjectFactory factory = new ByteBufferObjectFactory(
3121: bufferSize, useDirectByteBuffer);
3122:
3123: byteBufferPool = poolManager.makeByteBufferPool(factory,
3124: opConfig);
3125: poolManager.initPool(byteBufferPool, opConfig);
3126: }
3127:
3128: /**
3129: * Returns ObjectPool of java.nio.ByteBuffer class.
3130: * @since 1.4.5
3131: */
3132: public ObjectPool getByteBufferPool() {
3133: return byteBufferPool;
3134: }
3135:
3136: /**
3137: * Makes the pool of ByteBuffer
3138: * @since 1.4.5
3139: */
3140: private void makeClientPool(PoolConfig opConfig) throws Exception {
3141: logger.finer("Creating ClientThread pool");
3142: ThreadObjectFactory factory = new ThreadObjectFactory();
3143: ObjectPool objectPool = poolManager.makeClientPool(factory,
3144: opConfig);
3145: pool = new ClientPool(makeQSObjectPool(objectPool), opConfig);
3146: factory.setClientPool(pool);
3147: pool.setMaxThreadsForNioWrite(getBasicConfig()
3148: .getAdvancedSettings().getMaxThreadsForNioWrite());
3149: poolManager.initPool(objectPool, opConfig);
3150: }
3151:
3152: /**
3153: * Sets the ClientWriteHandler class that interacts with
3154: * client sockets to handle data write (only used in non-blocking mode).
3155: * @param handler object the fully qualified name of the class that
3156: * implements {@link ClientWriteHandler}
3157: * @see #getClientWriteHandler
3158: * @since 1.4.5
3159: */
3160: public void setClientWriteHandler(String handler) {
3161: clientWriteHandlerString = handler;
3162: logger.finest("Set to " + handler);
3163: }
3164:
3165: /**
3166: * Returns the ClientWriteHandler class that interacts with
3167: * client sockets (only used in non-blocking mode).
3168: * @see #setClientWriteHandler
3169: * @since 1.4.5
3170: */
3171: public String getClientWriteHandler() {
3172: return clientWriteHandlerString;
3173: }
3174:
3175: /**
3176: * Returns the date/time when the server was last started.
3177: * @return last started time. Will be <code>null</code> if never started.
3178: * @since 1.4.5
3179: */
3180: public java.util.Date getLastStartTime() {
3181: return lastStartTime;
3182: }
3183:
3184: /**
3185: * Sets the debug flag to ByteBufferOutputStream and
3186: * ByteBufferInputStream class that are used in non-blcking mode
3187: * @since 1.4.5
3188: */
3189: public static void setDebugNonBlockingMode(boolean flag) {
3190: org.quickserver.util.io.ByteBufferOutputStream.setDebug(flag);
3191: org.quickserver.util.io.ByteBufferInputStream.setDebug(flag);
3192: }
3193:
3194: /**
3195: * Returns the implementation that is used to do Client Identification.
3196: * @since 1.4.5
3197: */
3198: public ClientIdentifier getClientIdentifier() {
3199: return clientIdentifier;
3200: }
3201:
3202: /**
3203: * Makes QSObjectPool from ObjectPool
3204: * @since 1.4.5
3205: */
3206: private QSObjectPool makeQSObjectPool(ObjectPool objectPool)
3207: throws Exception {
3208: return (QSObjectPool) qsObjectPoolMaker
3209: .getQSObjectPool(objectPool);
3210: }
3211:
3212: /**
3213: * Returns the current blocking mode of the server.
3214: * @since 1.4.6
3215: */
3216: public boolean getBlockingMode() {
3217: return blockingMode;
3218: }
3219:
3220: /**
3221: * Loads all the Business Logic class
3222: * @since 1.4.6
3223: */
3224: protected void loadBusinessLogic() throws Exception {
3225: if (clientCommandHandlerString == null
3226: && clientEventHandlerString == null) {
3227: logger
3228: .severe("ClientCommandHandler AND ClientEventHandler was not set.");
3229: throw new AppException(
3230: "ClientCommandHandler AND ClientEventHandler was not set.");
3231: }
3232:
3233: clientCommandHandler = null;
3234: if (clientCommandHandlerString != null) {
3235: logger.finest("Loading ClientCommandHandler class..");
3236: Class clientCommandHandlerClass = getClass(
3237: clientCommandHandlerString, true);
3238: clientCommandHandler = (ClientCommandHandler) clientCommandHandlerClass
3239: .newInstance();
3240: }
3241:
3242: boolean setClientCommandHandlerLookup = false;
3243: clientEventHandler = null;
3244: if (clientEventHandlerString == null) {
3245: clientEventHandlerString = "org.quickserver.net.server.impl.DefaultClientEventHandler";
3246: setClientCommandHandlerLookup = true;
3247: }
3248: logger.finest("Loading ClientEventHandler class..");
3249: if (clientEventHandlerString.equals(clientCommandHandlerString)
3250: && ClientEventHandler.class
3251: .isInstance(clientCommandHandler)) {
3252: clientEventHandler = (ClientEventHandler) clientCommandHandler;
3253: } else {
3254: clientEventHandler = (ClientEventHandler) getClass(
3255: clientEventHandlerString, true).newInstance();
3256: if (setClientCommandHandlerLookup) {
3257: ((DefaultClientEventHandler) clientEventHandler)
3258: .setClientCommandHandler(clientCommandHandler);
3259: }
3260: }
3261:
3262: clientExtendedEventHandler = null;
3263: if (clientExtendedEventHandlerString != null) {
3264: logger.finest("Loading ClientExtendedEventHandler class..");
3265: if (clientExtendedEventHandlerString
3266: .equals(clientCommandHandlerString)
3267: && ClientExtendedEventHandler.class
3268: .isInstance(clientCommandHandler)) {
3269: clientExtendedEventHandler = (ClientExtendedEventHandler) clientCommandHandler;
3270: } else if (clientExtendedEventHandlerString
3271: .equals(clientEventHandlerString)
3272: && ClientExtendedEventHandler.class
3273: .isInstance(clientEventHandler)) {
3274: clientExtendedEventHandler = (ClientExtendedEventHandler) clientEventHandler;
3275: } else {
3276: Class clientExtendedEventHandlerClass = getClass(
3277: clientExtendedEventHandlerString, true);
3278: clientExtendedEventHandler = (ClientExtendedEventHandler) clientExtendedEventHandlerClass
3279: .newInstance();
3280: }
3281: }
3282:
3283: clientObjectHandler = null;
3284: if (clientObjectHandlerString != null) {
3285: logger.finest("Loading ClientObjectHandler class..");
3286: if (clientObjectHandlerString
3287: .equals(clientCommandHandlerString)
3288: && ClientObjectHandler.class
3289: .isInstance(clientCommandHandler)) {
3290: clientObjectHandler = (ClientObjectHandler) clientCommandHandler;
3291: } else if (clientObjectHandlerString
3292: .equals(clientEventHandlerString)
3293: && ClientObjectHandler.class
3294: .isInstance(clientEventHandler)) {
3295: clientObjectHandler = (ClientObjectHandler) clientEventHandler;
3296: } else if (clientObjectHandlerString
3297: .equals(clientExtendedEventHandlerString)
3298: && ClientObjectHandler.class
3299: .isInstance(clientExtendedEventHandler)) {
3300: clientObjectHandler = (ClientObjectHandler) clientExtendedEventHandler;
3301: } else {
3302: clientObjectHandler = (ClientObjectHandler) getClass(
3303: clientObjectHandlerString, true).newInstance();
3304: }
3305: } //end of != null
3306:
3307: clientBinaryHandler = null;
3308: if (clientBinaryHandlerString != null) {
3309: logger.finest("Loading ClientBinaryHandler class..");
3310: if (clientBinaryHandlerString
3311: .equals(clientCommandHandlerString)
3312: && ClientBinaryHandler.class
3313: .isInstance(clientCommandHandler)) {
3314: clientBinaryHandler = (ClientBinaryHandler) clientCommandHandler;
3315: } else if (clientBinaryHandlerString
3316: .equals(clientEventHandlerString)
3317: && ClientBinaryHandler.class
3318: .isInstance(clientEventHandler)) {
3319: clientBinaryHandler = (ClientBinaryHandler) clientEventHandler;
3320: } else if (clientBinaryHandlerString
3321: .equals(clientExtendedEventHandlerString)
3322: && ClientBinaryHandler.class
3323: .isInstance(clientExtendedEventHandler)) {
3324: clientBinaryHandler = (ClientBinaryHandler) clientExtendedEventHandler;
3325: } else if (clientBinaryHandlerString
3326: .equals(clientObjectHandlerString)
3327: && ClientBinaryHandler.class
3328: .isInstance(clientObjectHandler)) {
3329: clientBinaryHandler = (ClientBinaryHandler) clientObjectHandler;
3330: } else {
3331: clientBinaryHandler = (ClientBinaryHandler) getClass(
3332: clientBinaryHandlerString, true).newInstance();
3333: }
3334: } //end of != null
3335:
3336: clientWriteHandler = null;
3337: if (clientWriteHandlerString != null) {
3338: logger.finest("Loading ClientWriteHandler class..");
3339: if (clientWriteHandlerString
3340: .equals(clientCommandHandlerString)
3341: && ClientWriteHandler.class
3342: .isInstance(clientCommandHandler)) {
3343: clientWriteHandler = (ClientWriteHandler) clientCommandHandler;
3344: } else if (clientWriteHandlerString
3345: .equals(clientEventHandlerString)
3346: && ClientWriteHandler.class
3347: .isInstance(clientEventHandler)) {
3348: clientWriteHandler = (ClientWriteHandler) clientEventHandler;
3349: } else if (clientWriteHandlerString
3350: .equals(clientExtendedEventHandlerString)
3351: && ClientWriteHandler.class
3352: .isInstance(clientExtendedEventHandler)) {
3353: clientWriteHandler = (ClientWriteHandler) clientExtendedEventHandler;
3354: } else if (clientWriteHandlerString
3355: .equals(clientObjectHandlerString)
3356: && ClientWriteHandler.class
3357: .isInstance(clientObjectHandler)) {
3358: clientWriteHandler = (ClientWriteHandler) clientObjectHandler;
3359: } else if (clientWriteHandlerString
3360: .equals(clientBinaryHandlerString)
3361: && ClientWriteHandler.class
3362: .isInstance(clientBinaryHandler)) {
3363: clientWriteHandler = (ClientWriteHandler) clientBinaryHandler;
3364: } else {
3365: clientWriteHandler = (ClientWriteHandler) getClass(
3366: clientWriteHandlerString, true).newInstance();
3367: }
3368: } //end of != null
3369:
3370: Class authenticatorClass = null;
3371: if (clientAuthenticationHandlerString != null) {
3372: logger
3373: .finest("Loading ClientAuthenticationHandler class..");
3374: authenticatorClass = getClass(
3375: clientAuthenticationHandlerString, true);
3376: }
3377:
3378: if (authenticatorClass != null) {
3379: Object obj = authenticatorClass.newInstance();
3380:
3381: if (ClientAuthenticationHandler.class.isInstance(obj))
3382: clientAuthenticationHandler = (ClientAuthenticationHandler) obj;
3383: else
3384: authenticator = (Authenticator) obj;
3385: }
3386:
3387: clientDataClass = null;
3388: if (clientDataString != null) {
3389: logger.finest("Loading ClientData class..");
3390: clientDataClass = getClass(clientDataString, true);
3391: }
3392:
3393: Assertion.affirm(clientEventHandler != null,
3394: "ClientEventHandler was not loaded!");
3395: }
3396:
3397: /**
3398: * Sets the ClientEventHandler class that gets notified of
3399: * client events.
3400: * @param handler the fully qualified name of the class that
3401: * implements {@link ClientEventHandler}
3402: * @see #getClientEventHandler
3403: * @since 1.4.6
3404: */
3405: public void setClientEventHandler(String handler) {
3406: clientEventHandlerString = handler;
3407: logger.finest("Set to " + handler);
3408: }
3409:
3410: /**
3411: * Returns the ClientEventHandler class that gets notified of
3412: * client events.
3413: * @see #setClientEventHandler
3414: * @since 1.4.6
3415: */
3416: public String getClientEventHandler() {
3417: return clientEventHandlerString;
3418: }
3419:
3420: /**
3421: * Sets the default {@link DataMode} for the ClientHandler
3422: * @since 1.4.6
3423: */
3424: public void setDefaultDataMode(DataMode dataMode, DataType dataType)
3425: throws IOException {
3426: if (dataType == DataType.IN)
3427: this .defaultDataModeIN = dataMode;
3428: if (dataType == DataType.OUT)
3429: this .defaultDataModeOUT = dataMode;
3430: }
3431:
3432: /**
3433: * Sets the default {@link DataMode} for the ClientHandler
3434: * @since 1.4.6
3435: */
3436: public void setDefaultDataMode(DefaultDataMode defaultDataMode)
3437: throws IOException {
3438: defaultDataModeIN = defaultDataMode.getDataMode(DataType.IN);
3439: defaultDataModeOUT = defaultDataMode.getDataMode(DataType.OUT);
3440: ;
3441: }
3442:
3443: /**
3444: * Returns the default {@link DataMode} for the ClientHandler
3445: * @since 1.4.6
3446: */
3447: public DataMode getDefaultDataMode(DataType dataType) {
3448: if (dataType == DataType.IN)
3449: return defaultDataModeIN;
3450: if (dataType == DataType.OUT)
3451: return defaultDataModeOUT;
3452: else
3453: throw new IllegalArgumentException("Unknown DataType: "
3454: + dataType);
3455: }
3456:
3457: /**
3458: * Sets the ClientExtendedEventHandler class that gets notified of
3459: * extended client events.
3460: * @param handler the fully qualified name of the class that
3461: * implements {@link ClientExtendedEventHandler}
3462: * @see #getClientExtendedEventHandler
3463: * @since 1.4.6
3464: */
3465: public void setClientExtendedEventHandler(String handler) {
3466: clientExtendedEventHandlerString = handler;
3467: logger.finest("Set to " + handler);
3468: }
3469:
3470: /**
3471: * Returns the ClientExtendedEventHandler class that gets notified of
3472: * extended client events.
3473: * @see #setClientExtendedEventHandler
3474: * @since 1.4.6
3475: */
3476: public String getClientExtendedEventHandler() {
3477: return clientExtendedEventHandlerString;
3478: }
3479:
3480: /**
3481: * If Application Jar Path was set, load the jars
3482: * @since 1.4.6
3483: */
3484: private void loadApplicationClasses() throws Exception {
3485: if (getApplicationJarPath() != null && getClassLoader() == null) {
3486: setClassLoader(ClassUtil
3487: .getClassLoader(getApplicationJarPath()));
3488: //update qsadmin to use the same
3489: if (adminServer != null) {
3490: adminServer.getServer()
3491: .setClassLoader(getClassLoader());
3492: }
3493: }
3494: }
3495: }
|