adding quickserver to thirdparty

Change-Id: Icae351c09d0480bd68e09d5c8773dc5ca23f1e12
diff --git a/quickserver/README.md b/quickserver/README.md
new file mode 100644
index 0000000..ff0413b
--- /dev/null
+++ b/quickserver/README.md
@@ -0,0 +1,193 @@
+Readme for QuickServer v 2.1.0

+------------------------------

+

+Read the "install.txt" file for instructions to setup your environment

+variables to be followed after extracting or installing QuickServer.

+

+

+Introduction

+---------------------

+QuickServer is an open source Java library/framework for quick creation 

+of robust multi-client TCP server applications. With QuickServer you can 

+concentrate on just the application logic/protocol on hand.  

+

+QuickServer provides an abstraction over the ServerSocket, Socket and 

+other network and input output classes and it eases the creation of 

+powerful network servers.

+

+Example programs demonstrating the use of the library can be found 

+with the QuickServer distribution  [examples folder]. 

+Latest examples, documentation is available through the website. 

+

+

+Brief Architecture

+---------------------

+QuickServer divides the application logic of its developer over eight 

+main classes,

+ * ClientEventHandler [Optional Class]

+    Handles client events.

+ * ClientCommandHandler [#]

+    Handles client interaction - Character/String commands.

+ * ClientObjectHandler [#]

+    Handles client interaction - Java Object commands.

+ * ClientBinaryHandler [#]

+    Handles client interaction - Binary data (byte array).

+ * ClientAuthenticationHandler [Optional Class]

+    Used to authenticate a client.

+ * ClientData [Optional Class]

+    Client data carrier (support class)

+ * ClientExtendedEventHandler [Optional Class]

+    Handles extended client events.

+

+[#] = Any one of these have to be set based on default DataMode for input. 

+      The default DataMode for input is String so if not changes you will

+      have to set ClientCommandHandler.

+

+See the architecture section of Wiki for basic architecture of QuickServer.

+

+

+Major Features

+---------------------

+ * Create multi-client TCP server applications.

+ * Support for secure server creations: SSL, TLS

+ * Support for thread per client (multi-threaded) - Blocking Mode.

+ * Clear separation of server, protocol and authentication logic.

+ * Remote administration support: QsAdminServer 

+   (With support for plugable application commands)

+ * Support for command shell for local administration of server.

+ * GUI based remote administration: QsAdminGUI 

+   (With support for gui plug-ins)

+ * Restart or Suspend the server without killing connected clients.

+ * Inbuilt pools for reusing of threads and most used Objects.

+ * Full logging support [Java built in Logging].

+ * Support for sending and receiving Strings, Bytes, Binary and 

+   serialized java objects.

+ * Support for identifying and searching clients. 

+ * Support for xml configuration with ability to store application 

+   specific data in the same xml.

+ * Support for xml based JDBC mapping.

+ * Support for Service Configurator pattern.

+ * Support for restricting access to server by ip address.

+ * Support for loading/reloading application jar from xml.

+ * Ability to add process hooks into QuickServer.

+ * Ability to specify maximum number of clients allowed.

+ * Support for negotiating secure connection over normal tcp connection.

+ * Nice and easy examples come with the distribution - FTPServer, 

+   CmdServer, EchoWebServer, ChatServer, SecureEchoWebServer, XmlAdder, 

+   PipeServer, Filesrv.

+

+

+What's New in 2.1.0

+---------------------

++ Added support for uptime in Host (QuickServer Client)

++ Supports null/no banner when server starts

+# uptime formatting shortened 

+# Fixed load pattern logic RandomLoadPattern, RoundRobinLoadPattern 

+  (was using index when client key was set)

++ added getHighestActiveCount() method to Object Pools

++ Added getHighestActiveClientCount method to QuickServer object

++ Added support for setting Security provider for SSLContext

+# Defaulted SSL to TLS

+! Bug fix for ThreadPool not reducing to max ideal 

+  (stay in wait state n increase over time)

+! Bug fix for Client (HashedLoadPattern)

+- Disabled non blocking mode (no more supported) 

+

+

+System Requirements

+---------------------

+Read the "requirements.txt" file for details on system requirements.

+

+

+QuickServer Credits 

+---------------------

+Thanks to everyone who helped me in this project. Thanks to all users 

+who posted/sent their valuable comments and suggestion. 

+I would also like to thank all the people who have posted/sent bug 

+reports. Please do keep reporting any bugs that you find in QuickServer, 

+this way you will be helping in improving it. Do visit our web site for 

+full credits listing.   

+

+

+Get Support 

+---------------------

+Do post your questions, suggestions, bug-reports, enhancement-requests 

+etc. at Developers Forum. Please do not contact development team 

+directly unless you really would like to send a private message. 

+

+Note: We provide a higher level of support to individuals and companies 

+who have contributed to QuickServer project in some way.

+There is a number of ways to contribute visit www.quickserver.org for details.

+

+

+Request to Developers

+---------------------

+If you would like to contribute to the development of QuickServer 

+please do get in touch with us. We are always on the lookout for

+people who can contribute to make this library even better.

+

+If you use QuickServer in your development and if you would like to 

+share your experience with the QuickServer community, please feel 

+free to post it in the QuickServer Forums. Thanks.

+

+

+Website

+---------------------

+http://www.quickserver.org

+https://github.com/QuickServerLab/QuickServer-Main

+http://quickserver.sourceforge.net

+http://code.google.com/p/quickserver/

+

+

+License, Copyright

+---------------------

+QuickServer

+Java library/framework for creating robust multi-client TCP servers.

+Copyright (C) 2003-2017 QuickServer.org

+Website	   : http://www.quickserver.org

+

+This library is free software; you can redistribute it and/or

+modify it under the terms of the GNU Lesser General Public

+License as published by the Free Software Foundation; either

+version 2.1 of the License, or (at your option) any later version.

+

+This library is distributed in the hope that it will be useful,

+but WITHOUT ANY WARRANTY; without even the implied warranty of

+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

+Lesser General Public License for more details.

+

+You should have received a copy of the GNU Lesser General Public

+License along with this library; if not, write to the Free Software

+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

+

+Note: The GNU LGPL v2.1 is included in the file "license.txt" for 

+your convenience.

+

+

+Other Libraries/Tools Used

+--------------------------

+QuickServer uses the following third party libraries and would like

+to thank all of them for making life easier for developers.

+

+-- Included Jars/Libraries --

+Jakarta Commons:

+ This product includes software developed by the Apache Software 

+ Foundation (http://www.apache.org/). Read the "requirements.txt" 

+ file for details. 

+ Apache Software License is included in the file "apache_license.txt"

+

+Metouia Look And Feel :

+ A free pluggable look and feel for java. License : GNU LGPL 

+ http://mlf.sourceforge.net 

+

+-- Non-Included Jars/Libraries --

+JUnit :

+ A framework to write repeatable tests. 

+

+

+Date: 12 Aug 2017

+---------------------

+

+Copyright (C) 2003-2017 QuickServer.org

+http://www.quickserver.org/

+https://github.com/QuickServerLab/QuickServer-Main
\ No newline at end of file
diff --git a/quickserver/apache_license.txt b/quickserver/apache_license.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/quickserver/apache_license.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/quickserver/bin/QS.bat b/quickserver/bin/QS.bat
new file mode 100644
index 0000000..1c70e57
--- /dev/null
+++ b/quickserver/bin/QS.bat
@@ -0,0 +1,2 @@
+@rem Starts QuickServer

+@java -server -jar ..\dist\QuickServer.jar %1 %2 %3 %4
\ No newline at end of file
diff --git a/quickserver/bin/QSAdminGUI.bat b/quickserver/bin/QSAdminGUI.bat
new file mode 100644
index 0000000..05f8dcd
--- /dev/null
+++ b/quickserver/bin/QSAdminGUI.bat
@@ -0,0 +1,3 @@
+@rem Starts QSAdminGUI

+@rem Optional argument plug-in dir, default value: ./../plugin 

+@start javaw -jar ..\dist\QSAdminGUI.jar %1
\ No newline at end of file
diff --git a/quickserver/bin/QSAdminGUI.sh b/quickserver/bin/QSAdminGUI.sh
new file mode 100644
index 0000000..1ddcd18
--- /dev/null
+++ b/quickserver/bin/QSAdminGUI.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# Starts QSAdminGUI
+#  Optional argument plug-in dir, default value: ./../plugin 
+exec java -jar ../dist/QSAdminGUI.jar "$@"
\ No newline at end of file
diff --git a/quickserver/bin/QuickServer.bat b/quickserver/bin/QuickServer.bat
new file mode 100644
index 0000000..1c70e57
--- /dev/null
+++ b/quickserver/bin/QuickServer.bat
@@ -0,0 +1,2 @@
+@rem Starts QuickServer

+@java -server -jar ..\dist\QuickServer.jar %1 %2 %3 %4
\ No newline at end of file
diff --git a/quickserver/bin/QuickServer.sh b/quickserver/bin/QuickServer.sh
new file mode 100644
index 0000000..30daab9
--- /dev/null
+++ b/quickserver/bin/QuickServer.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+# Starts QuickServer
+exec java -server -jar ../dist/QuickServer.jar "$@"
\ No newline at end of file
diff --git a/quickserver/bin/qs.sh b/quickserver/bin/qs.sh
new file mode 100644
index 0000000..30daab9
--- /dev/null
+++ b/quickserver/bin/qs.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+# Starts QuickServer
+exec java -server -jar ../dist/QuickServer.jar "$@"
\ No newline at end of file
diff --git a/quickserver/build.xml b/quickserver/build.xml
new file mode 100644
index 0000000..fef50f0
--- /dev/null
+++ b/quickserver/build.xml
@@ -0,0 +1,262 @@
+<project name="QuickServer.Project" default="jar" basedir=".">

+    <property name="app.name"   value="QuickServer" />

+    <property name="main.build.dir"  value="build/mainclasses" />

+    <property name="client.build.dir"  value="build/clientclasses" />

+    <property name="qsadmingui.build.dir"  value="build/qsadminguiclasses" />

+    <property name="test.build.dir"  value="build/testcases" />

+    <property name="dist.dir"  value="dist" />

+    <property name="src.dir" value="src" />

+    <property name="app.version"  value="2.0.0" />

+

+    <property name="app.version.sub"  value="" />

+    <property name="javac.deprecation" value="off" />

+

+    <path id="project.classpath">

+        <fileset dir="./dist/">

+            <include name="*.jar"/>

+            <exclude name="QuickServer.jar"/>

+            <exclude name="QuickServerClient.jar"/>

+            <exclude name="QSAdminGUI.jar"/>

+        </fileset>

+    </path>

+

+    <target name="help">

+        <echo>

+            Build for ${app.name} ${app.version} ${app.version.sub}

+

+            Available targets:

+            clean			Cleans all dist and build dir.

+		

+            compile_main		Compiles the main source

+            compile_qsadmingui	Compiles the QsAdminGUI source

+            compile		Combines both compile_main and compile_qsadmingui

+

+            main_jar		Creates main jar file.

+            qsadmingui_jar		Creates main jar file.

+            jar			Combines both main_jar and qsadmingui_jar

+

+            compileTests		Compiles the test cases.

+            runTests		Runs all the test cases.

+

+            docs			Creates Java API docs

+            run_about		Runs with -about flag

+            run_qsadmin		Runs QSAdminGUI

+        </echo>

+    </target>

+

+    <target name="clean">

+        <delete dir="${main.build.dir}" />

+        <delete dir="${qsadmingui.build.dir}" />

+        <delete dir="${test.build.dir}" />

+        <delete file="${dist.dir}/${app.name}.jar" />

+        <delete file="${dist.dir}/QSAdminGUI.jar" />

+        <delete dir="docs" />

+    </target>

+

+    <target name="compile" depends="compile_main, compile_qsadmingui">

+        <echo>Done</echo>

+    </target>

+

+    <target name="compile_main">

+        <mkdir dir="${main.build.dir}"/>

+        <javac srcdir="${src.dir}" destdir="${main.build.dir}" 

+               debug="on" optimize="on" listfiles="off"

+               deprecation="${javac.deprecation}" includeantruntime="false" target="1.5">

+            <include name="main/**"/>

+            <exclude name="main/org/quickserver/net/client/**"/>

+            <exclude name="main/org/quickserver/net/qsadmin/gui/**"/>

+            <exclude name="main/org/quickserver/util/xmlreader/QSAdminPluginConfig.java"/>

+            <exclude name="main/org/quickserver/util/xmlreader/PluginConfigReader.java"/>

+            <classpath refid="project.classpath"/>

+        </javac>		

+    </target>

+	

+    <target name="compile_client">

+        <mkdir dir="${client.build.dir}"/>

+        <javac srcdir="${src.dir}" destdir="${client.build.dir}" 

+               debug="on" optimize="on" listfiles="off"

+               deprecation="${javac.deprecation}" includeantruntime="false"  target="1.5">

+            <include name="main/org/quickserver/net/client/**"/>

+            <classpath refid="project.classpath"/>

+        </javac>		

+    </target>

+

+    <target name="compile_qsadmingui">

+        <mkdir dir="${qsadmingui.build.dir}"/>

+

+        <javac destdir="${qsadmingui.build.dir}" debug="on" optimize="on"

+               listfiles="off" srcdir="${src.dir}"

+               deprecation="${javac.deprecation}" includeantruntime="false"  target="1.5">

+            <include name="main/org/quickserver/net/qsadmin/gui/**"/>

+            <include name="main/org/quickserver/swing/*"/>

+            <include name="main/org/quickserver/util/*"/>

+            <include name="main/org/quickserver/util/xmlreader/QSAdminPluginConfig.java"/>

+            <include name="main/org/quickserver/util/xmlreader/PluginConfigReader.java"/>

+            <include name="main/org/quickserver/util/io/*FileList.java"/>

+            <include name="main/org/quickserver/util/io/PasswordField.java"/>

+            <include name="main/org/quickserver/util/io/MaskingThread.java"/>

+            <classpath refid="project.classpath"/>

+        </javac>

+    </target>   

+

+    <target name="jar" depends="compile, compile_client, main_jar, client_jar, qsadmingui_jar">

+        <echo>Done</echo>

+    </target>

+

+    <target name="main_jar" depends="compile_main">

+        <mkdir dir="${main.build.dir}/icons"/>

+        <copy todir="${main.build.dir}/icons" overwrite="yes">

+            <fileset dir="${src.dir}/main/icons/">

+                <include name="*.gif"/>

+                <include name="*.png"/>

+            </fileset>

+        </copy>

+        <mkdir dir="${dist.dir}"/>

+

+        <copy file="README.md" todir="${main.build.dir}" overwrite="yes" />

+        <copy file="etc/quickserver_config.xsd"

+              todir="${dist.dir}" overwrite="yes" />

+        <copy file="etc/quickserver_config.dtd"

+              todir="${dist.dir}" overwrite="yes" />

+

+        <jar jarfile="${dist.dir}/${app.name}.jar"

+             basedir="${main.build.dir}" includes="**" manifest="${src.dir}/QuickServer.MF"/>

+    </target>

+	

+    <target name="client_jar" depends="compile_client">

+        <copy file="README.md" todir="${client.build.dir}" overwrite="yes" />

+        <jar jarfile="${dist.dir}/${app.name}Client.jar"

+             basedir="${client.build.dir}" includes="**" />

+    </target>

+

+    <target name="qsadmingui_jar" depends="compile_qsadmingui">

+        <copy todir="${qsadmingui.build.dir}/icons" overwrite="yes">

+            <fileset dir="${src.dir}/main/icons/">

+                <include name="*.gif"/>

+                <include name="*.png"/>

+            </fileset>

+        </copy>

+        <mkdir dir="${dist.dir}"/>

+		

+        <copy file="${src.dir}/main/org/quickserver/net/qsadmin/gui/conf/MainCommandPanel.xml"

+              todir="${qsadmingui.build.dir}/org/quickserver/net/qsadmin/gui/conf" overwrite="yes" />

+        <copy file="${src.dir}/main/org/quickserver/net/qsadmin/gui/conf/PropertieSet.xml"

+              todir="${qsadmingui.build.dir}/org/quickserver/net/qsadmin/gui/conf" overwrite="yes" />

+

+        <jar jarfile="${dist.dir}/QSAdminGUI.jar"

+             basedir="${qsadmingui.build.dir}" includes="**" manifest="${src.dir}/QSAdminGUI.MF"/>	  

+    </target>

+

+    <target name="done">

+        <tstamp>

+            <format property="TODAY_UK" pattern="d-MMMM-yyyy hh:mm:ss" locale="en"/>

+        </tstamp>

+        <echo>Time ${TODAY_UK}</echo>		

+    </target>

+

+

+    <target name="docs" depends="compile">

+        <!--

+        <exec dir="." executable="javadoc">

+            <arg line="@options @packages -source 1.6 -classpath "/>

+        </exec>

+        -->

+        <delete dir = "docs" failonerror = "false"/>  

+        <mkdir dir="docs"/>

+        <javadoc

+            use="true" 

+            splitindex="true" 

+            windowtitle="QuickServer v${app.version} API Specification" 

+            overview="src/main/overview.html" 

+            destdir="docs" 

+            author="true" 

+            version="true"           

+        >

+            <packageset dir="src/main" defaultexcludes="yes">

+				<include name="org/quickserver/net/**" />

+                <include name="org/quickserver/net/server/*" />

+				<exclude name="org/quickserver/net/server/gui/**" />

+                <include name="org/quickserver/net/server/impl/**" />

+                <include name="org/quickserver/net/client/**" />                

+				<include name="org/quickserver/net/qsadmin/gui/**" />

+                

+                <include name="org/quickserver/sql/**" />

+                <include name="org/quickserver/util/**" />

+                <include name="org/quickserver/security/**" />

+                <include name="org/quickserver/swing/**" />

+            </packageset>            

+            

+            <doctitle><![CDATA[<b>QuickServer</b><br><font size="-1">v${app.version}</font>]]></doctitle>  

+            <bottom><![CDATA[<i>Copyright &#169; 2003-2014 QuickServer.org</i>]]></bottom>

+                 

+            <group title="Core Packages" packages="org.quickserver.net:org.quickserver.net.server"/>

+            <group title="Client Packages" packages="org.quickserver.net.client:org.quickserver.net.client.loaddistribution:org.quickserver.net.client.loaddistribution.impl:org.quickserver.net.client.monitoring:org.quickserver.net.client.monitoring.impl:org.quickserver.net.client.pool*"/>

+            

+            <group title="Util Packages" packages="org.quickserver.util:org.quickserver.util.logging:org.quickserver.swing"/>

+            <group title="Thread Pool for App" packages="org.quickserver.util.pool.thread.app"/>

+            <group title="Support Packages" packages="org.quickserver.net.server.impl:org.quickserver.security:org.quickserver.net.qsadmin:org.quickserver.util.pool:org.quickserver.util.pool.thread:org.quickserver.sql:org.quickserver.util.io:org.quickserver.net.qsadmin.gui:org.quickserver.util.xmlreader"/>

+            

+            <classpath>

+				<fileset dir="./dist/">

+					<include name="*.jar"/>

+				</fileset>

+            </classpath>

+        </javadoc>

+        

+        <copy file="src/main/XMLConfiguration.xml"

+              todir="docs" overwrite="yes" />

+        <copy file="src/main/quickserver_logo.gif"

+              todir="docs" overwrite="yes" />

+    </target>

+

+    <target name="run_about" depends="main_jar">

+        <java fork="yes" classname="org.quickserver.net.server.QuickServer"

+              taskname="QuickServer" failonerror="true">

+            <arg value="-about"/>

+            <classpath>

+                <pathelement location="${dist.dir}/${app.name}.jar" />

+                <pathelement path="${java.class.path}" />

+            </classpath>

+        </java>

+    </target>

+

+    <target name="run_qsadmin" depends="qsadmingui_jar">

+        <java fork="yes" classname="org.quickserver.net.qsadmin.gui.QSAdmin"

+              taskname="QuickServer" failonerror="true">

+            <arg value="./plugin"/>

+            <classpath>

+                <pathelement location="${dist.dir}/QSAdminGUI.jar" />

+                <pathelement path="${java.class.path}" />

+            </classpath>

+        </java>

+    </target>

+

+    <!-- junit task -->

+    <target name="junit">

+        <available property="junit.present" classname="junit.framework.TestCase" />

+    </target>

+    <target name="compileTests" depends="jar, junit">

+        <mkdir dir="${test.build.dir}"/>

+        <javac srcdir="${src.dir}/test" destdir="${test.build.dir}">

+            <classpath>

+                <pathelement location="${dist.dir}/${app.name}.jar" />

+                <pathelement path="${dist.dir}/commons-logging.jar" />

+            </classpath>

+            <include name="**/*.java"/>

+        </javac>

+    </target>

+

+    <target name="runTests" depends="compileTests" if="junit.present">

+        <java fork="yes" classname="junit.textui.TestRunner"

+              taskname="junit" failonerror="true">

+            <arg value="test.org.quickserver.AllJUnitTests"/>

+            <classpath>

+                <pathelement location="${dist.dir}/${app.name}.jar" />

+                <pathelement location="${test.build.dir}" />

+                <pathelement path="" />

+                <pathelement path="${java.class.path}" />

+            </classpath>

+        </java>

+    </target>

+    <!-- junit task -->

+</project> 

diff --git a/quickserver/dist/QSAdminGUI.jar b/quickserver/dist/QSAdminGUI.jar
new file mode 100644
index 0000000..2183b89
--- /dev/null
+++ b/quickserver/dist/QSAdminGUI.jar
Binary files differ
diff --git a/quickserver/dist/QuickServer.jar b/quickserver/dist/QuickServer.jar
new file mode 100644
index 0000000..c645693
--- /dev/null
+++ b/quickserver/dist/QuickServer.jar
Binary files differ
diff --git a/quickserver/dist/QuickServerClient.jar b/quickserver/dist/QuickServerClient.jar
new file mode 100644
index 0000000..158f8ac
--- /dev/null
+++ b/quickserver/dist/QuickServerClient.jar
Binary files differ
diff --git a/quickserver/dist/commons-beanutils.jar b/quickserver/dist/commons-beanutils.jar
new file mode 100644
index 0000000..218510b
--- /dev/null
+++ b/quickserver/dist/commons-beanutils.jar
Binary files differ
diff --git a/quickserver/dist/commons-collections.jar b/quickserver/dist/commons-collections.jar
new file mode 100644
index 0000000..c35fa1f
--- /dev/null
+++ b/quickserver/dist/commons-collections.jar
Binary files differ
diff --git a/quickserver/dist/commons-digester.jar b/quickserver/dist/commons-digester.jar
new file mode 100644
index 0000000..9085d81
--- /dev/null
+++ b/quickserver/dist/commons-digester.jar
Binary files differ
diff --git a/quickserver/dist/commons-logging.jar b/quickserver/dist/commons-logging.jar
new file mode 100644
index 0000000..8758a96
--- /dev/null
+++ b/quickserver/dist/commons-logging.jar
Binary files differ
diff --git a/quickserver/dist/commons-pool.jar b/quickserver/dist/commons-pool.jar
new file mode 100644
index 0000000..ce5ff60
--- /dev/null
+++ b/quickserver/dist/commons-pool.jar
Binary files differ
diff --git a/quickserver/dist/metouia.jar b/quickserver/dist/metouia.jar
new file mode 100644
index 0000000..16afe7b
--- /dev/null
+++ b/quickserver/dist/metouia.jar
Binary files differ
diff --git a/quickserver/dist/quickserver_config.dtd b/quickserver/dist/quickserver_config.dtd
new file mode 100644
index 0000000..f715f8b
--- /dev/null
+++ b/quickserver/dist/quickserver_config.dtd
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!ELEMENT quickserver (name?, port?, bind-address?,

+	client-event-handler?, 

+	client-command-handler?, client-object-handler?, client-binary-handler?, 

+	client-authentication-handler?, authenticator?,  

+	client-data?, 

+	client-extended-event-handler?,

+	server-banner?, max-connection?, max-connection-msg?, 

+	timeout?, timeout-msg?, 

+	max-auth-try?, max-auth-try-msg?, 

+	console-logging-level?, console-logging-formatter?, 

+	object-pool?,

+	db-object-pool?, communication-logging?,

+	application-configuration?, 

+	security-manager-class?, access-constraint?, application-jar-path?,

+	server-hooks?, init-server-hooks?, secure?, qsadmin-server?,

+	server-mode?, default-data-mode?, advanced-settings?)>

+

+<!ELEMENT db-object-pool (database-connection-set?, db-pool-util)>

+<!ELEMENT database-connection-set (database-connection*)>

+<!ELEMENT database-connection (id, driver, url, username?, password?)>

+

+<!ELEMENT qsadmin-server 

+	(name?, port?, bind-address?,

+	client-event-handler?, 

+	client-command-handler?, client-object-handler?, 

+	client-authentication-handler?, authenticator?, 

+	client-data?, 

+	client-extended-event-handler?,

+	server-banner?, max-connection?, max-connection-msg?, 

+	timeout?, timeout-msg?, 

+	max-auth-try?, max-auth-try-msg?, 

+	console-logging-level?, console-logging-formatter?, 

+	object-pool?,

+	command-plugin?,command-shell?,communication-logging?,

+	access-constraint?, server-hooks?, server-mode?, 

+	default-data-mode?, advanced-settings?)>

+

+<!ELEMENT object-pool (max-active, max-idle, init-size, thread-object-pool?, 

+	client-handler-object-pool?, byte-buffer-object-pool?, 

+	client-data-object-pool?, pool-manager?)>

+<!ELEMENT command-shell (enable, prompt-name?)>

+<!ELEMENT communication-logging (enable)>

+

+<!ELEMENT application-configuration (property*, prompt-type?)>

+<!ELEMENT property (property-name, property-value)>

+

+<!ELEMENT access-constraint (ip-filter)>

+<!ELEMENT ip-filter (enable, allow-access, ip-collection)>

+<!ELEMENT ip-collection (client-ip-address*)>

+

+<!ELEMENT server-hooks (class-name*)>

+<!ELEMENT init-server-hooks (class-name*)>

+<!ELEMENT secure (enable?, load?, port?, protocol?, client-auth-enable?, secure-store)>

+<!ELEMENT secure-store (type?, algorithm?, provider?, key-store-info, trust-store-info?, secure-store-manager?)>

+<!ELEMENT key-store-info (store-file, store-password, key-password)>

+<!ELEMENT trust-store-info (store-file, store-password, type?,  provider?)>

+

+

+<!ELEMENT server-mode (blocking)>

+<!ELEMENT advanced-settings (charset?, use-direct-byte-buffer?, 

+	byte-buffer-size?, backlog?, socket-linger?, debug-non-blocking-mode?,

+	client-identifier?, qsobject-pool-maker?)>

+<!ELEMENT thread-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT client-handler-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT byte-buffer-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT client-data-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT default-data-mode (data-type-in, data-type-out)>

+

+

+<!ELEMENT client-command-handler (#PCDATA)>

+<!ELEMENT client-object-handler (#PCDATA)>

+<!-- for v1.2 and below -->

+<!-- for v1.3 and above -->

+<!ELEMENT authenticator (#PCDATA)>

+<!ELEMENT client-data (#PCDATA)>

+

+<!ELEMENT server-banner (#PCDATA)>

+<!ELEMENT name (#PCDATA)>

+<!ELEMENT port (#PCDATA)>

+<!ELEMENT bind-address (#PCDATA)>

+

+<!ELEMENT max-connection (#PCDATA)>

+<!ELEMENT max-connection-msg (#PCDATA)>

+

+<!ELEMENT timeout (#PCDATA)>

+<!ELEMENT timeout-msg (#PCDATA)>

+

+<!ELEMENT max-auth-try (#PCDATA)>

+<!ELEMENT max-auth-try-msg (#PCDATA)>

+

+<!ELEMENT console-logging-level (#PCDATA)>

+<!ELEMENT console-logging-formatter (#PCDATA)>

+

+<!ELEMENT command-plugin (#PCDATA)>

+

+<!ELEMENT id (#PCDATA)>

+<!ELEMENT driver (#PCDATA)>

+<!ELEMENT url (#PCDATA)>

+<!ELEMENT username (#PCDATA)>

+<!ELEMENT password (#PCDATA)>

+<!ELEMENT db-pool-util (#PCDATA)>

+

+<!ELEMENT max-active (#PCDATA)>

+<!ELEMENT max-idle (#PCDATA)>

+<!ELEMENT init-size (#PCDATA)>

+

+<!-- for v1.3.2 and above -->

+<!ELEMENT enable (#PCDATA)>

+<!ELEMENT prompt-name (#PCDATA)>

+

+<!ELEMENT property-name (#PCDATA)>

+<!ELEMENT property-value (#PCDATA)>

+

+<!-- for v1.3.3 and above -->

+<!ELEMENT security-manager-class (#PCDATA)>

+<!ELEMENT allow-access (#PCDATA)>

+<!ELEMENT client-ip-address (#PCDATA)>

+<!ELEMENT application-jar-path (#PCDATA)>

+<!ELEMENT class-name (#PCDATA)>

+

+<!-- for v1.4.0 and above -->

+<!ELEMENT load (#PCDATA)>

+<!ELEMENT protocol (#PCDATA)>

+<!ELEMENT client-auth-enable (#PCDATA)>

+<!ELEMENT type (#PCDATA)>

+<!ELEMENT algorithm (#PCDATA)>

+<!ELEMENT provider (#PCDATA)>

+<!ELEMENT store-file (#PCDATA)>

+<!ELEMENT store-password (#PCDATA)>

+<!ELEMENT key-password (#PCDATA)>

+<!ELEMENT client-binary-handler (#PCDATA)>

+<!ELEMENT secure-store-manager (#PCDATA)>

+

+<!-- for v1.4.5 and above -->

+<!ELEMENT blocking (#PCDATA)>

+<!ELEMENT charset (#PCDATA)>

+<!ELEMENT use-direct-byte-buffer (#PCDATA)>

+<!ELEMENT byte-buffer-size (#PCDATA)>

+<!ELEMENT backlog (#PCDATA)>

+<!ELEMENT socket-linger (#PCDATA)>

+<!ELEMENT debug-non-blocking-mode (#PCDATA)>

+<!ELEMENT prompt-type (#PCDATA)>

+<!ELEMENT client-identifier (#PCDATA)>

+<!ELEMENT pool-manager (#PCDATA)>

+<!ELEMENT qsobject-pool-maker (#PCDATA)>

+

+<!ELEMENT client-event-handler (#PCDATA)>

+<!ELEMENT data-type-in (#PCDATA)>

+<!ELEMENT data-type-out (#PCDATA)>

+<!ELEMENT client-extended-event-handler (#PCDATA)>

+<!ELEMENT client-authentication-handler (#PCDATA)>

diff --git a/quickserver/dist/quickserver_config.xsd b/quickserver/dist/quickserver_config.xsd
new file mode 100644
index 0000000..0bf29e8
--- /dev/null
+++ b/quickserver/dist/quickserver_config.xsd
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--  http://www.quickserver.org/xml/quickserver_config.xsd -->

+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

+	<xsd:annotation>

+		<xsd:documentation xml:lang="en">QuickServer v 1.4 config schema for QuickServer.org</xsd:documentation>

+	</xsd:annotation>

+	<xsd:element name="quickserver" type="QuickserverType"/>

+	<xsd:element name="qsadmin-server" type="QSAdminServerType"/>

+	<xsd:complexType name="QuickserverType">

+		<xsd:sequence>

+			<xsd:element name="namer" type="xsd:string"/>

+			<xsd:element name="port" type="xsd:unsignedInt" default="9876" minOccurs="0"/>

+			<xsd:element name="bind-address" type="xsd:string" default="0.0.0.0" minOccurs="0"/>

+			<!-- start logic class -->

+			<xsd:element name="client-event-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-command-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-object-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-binary-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:choice minOccurs="0">

+				<!-- for v1.4.6 and above -->

+				<xsd:element name="client-authentication-handler" type="xsd:string" minOccurs="0"/>

+				<!-- Deprecated -->

+				<xsd:element name="authenticator" type="xsd:string" minOccurs="0"/>

+			</xsd:choice>

+			<xsd:element name="client-data" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-extended-event-handler" type="xsd:string" minOccurs="0"/>

+			<!-- end logic class-->

+			<xsd:element name="server-banner" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-level" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-formatter" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="object-pool" type="ObjectPoolType" minOccurs="0"/>

+			<xsd:element name="db-object-pool" type="DbObjectPoolType" minOccurs="0"/>

+			<xsd:element name="communication-logging" type="CommunicationLoggingType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="access-constraint" type="AccessConstraintType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="security-manager-class" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="application-jar-path" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="server-hooks" type="ServerHooksType" minOccurs="0"/>

+			<xsd:element name="init-server-hooks" type="InitServerHooksType" minOccurs="0"/>

+			<xsd:element name="secure" type="SecureType" minOccurs="0"/>

+			<xsd:element name="server-mode" type="ServerModeType" minOccurs="0"/>

+			<xsd:element name="advanced-settings" type="AdvancedSettingsType" minOccurs="0"/>

+			<xsd:element name="default-data-mode" type="DefaultDataModeType" minOccurs="0"/>

+			<!-- qsadmin server -->

+			<xsd:element name="qsadmin-server" type="QSAdminServerType" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ObjectPoolType">

+		<xsd:sequence>

+			<xsd:element name="max-active" type="xsd:integer"/>

+			<xsd:element name="max-idle" type="xsd:integer"/>

+			<xsd:element name="init-size" type="xsd:integer"/>

+			<xsd:element name="thread-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="client-handler-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="byte-buffer-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="client-data-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="pool-manager" type="xsd:string"  minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="DbObjectPoolType">

+		<xsd:sequence>

+			<xsd:element name="database-connection-set" type="DatabaseConnectionSet" minOccurs="0"/>

+			<xsd:element name="db-pool-util" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="DatabaseConnectionSet">

+		<xsd:sequence>

+			<xsd:element name="database-connection" type="DatabaseConnection" minOccurs="0" maxOccurs="unbounded"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="DatabaseConnection">

+		<xsd:sequence>

+			<xsd:element name="id" type="xsd:string"/>

+			<xsd:element name="driver" type="xsd:string"/>

+			<xsd:element name="url" type="xsd:string"/>

+			<xsd:element name="username" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="password" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="CommunicationLoggingType">

+		<xsd:sequence>

+			<xsd:element name="enable" type="xsd:boolean"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ApplicationConfigurationType">

+		<xsd:sequence>

+			<xsd:element name="property" type="PropertyType" minOccurs="0"/>

+			<xsd:element name="prompt-type" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="PropertyType">

+		<xsd:sequence>

+			<xsd:element name="property-name" type="xsd:string"/>

+			<xsd:element name="property-value" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="AccessConstraintType">

+		<xsd:sequence>

+			<xsd:element name="ip-filter" type="IpFilterType" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="IpFilterType">

+		<xsd:sequence>

+			<xsd:element name="enable" type="xsd:boolean"/>

+			<xsd:element name="allow-access" type="xsd:boolean"/>

+			<xsd:element name="ip-collection" type="IpCollectionnType"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="IpCollectionnType">

+		<xsd:sequence>

+			<xsd:element name="client-ip-address" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ServerHooksType">

+		<xsd:sequence>

+			<xsd:element name="class-name" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="InitServerHooksType">

+		<xsd:sequence>

+			<xsd:element name="class-name" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="SecureType">

+		<xsd:sequence>

+			<xsd:element name="enable" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="load" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="port" type="xsd:unsignedInt" minOccurs="0"/>

+			<xsd:element name="protocol" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-auth-enable" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="secure-store" type="SecureStoreType"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="SecureStoreType">

+		<xsd:sequence>

+			<xsd:element name="type" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="algorithm" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="provider" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="key-store-info" type="KeyStoreInfoType"/>

+			<xsd:element name="trust-store-info" type="TrustStoreInfoType" minOccurs="0"/>

+			<xsd:element name="secure-store-manager" type="xsd:string" default="org.quickserver.security.SecureStoreManager" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="KeyStoreInfoType">

+		<xsd:sequence>

+			<xsd:element name="store-file" type="xsd:string"/>

+			<xsd:element name="store-password" type="xsd:string"/>

+			<xsd:element name="key-password" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="TrustStoreInfoType">

+		<xsd:sequence>

+			<xsd:element name="store-file" type="xsd:string"/>

+			<xsd:element name="store-password" type="xsd:string"/>

+			<xsd:element name="type" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="provider" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="QSAdminServerType">

+		<xsd:sequence>

+			<xsd:element name="namer" type="xsd:string"/>

+			<xsd:element name="port" type="xsd:unsignedInt" default="9876" minOccurs="0"/>

+			<xsd:element name="bind-address" type="xsd:string" default="0.0.0.0" minOccurs="0"/>

+			<!-- start logic class -->

+			<xsd:element name="client-event-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-command-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-object-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-binary-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:choice minOccurs="0">

+				<!-- for v1.4.6 and above -->

+				<xsd:element name="client-authentication-handler" type="xsd:string" minOccurs="0"/>

+				<!-- Deprecated -->

+				<xsd:element name="authenticator" type="xsd:string" minOccurs="0"/>

+			</xsd:choice>

+			<xsd:element name="client-data" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="command-plugin" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-extended-event-handler" type="xsd:string" minOccurs="0"/>

+			<!-- end logic class-->

+			<xsd:element name="server-banner" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-level" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-formatter" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="object-pool" type="ObjectPoolType" minOccurs="0"/>

+			<xsd:element name="db-object-pool" type="DbObjectPoolType" minOccurs="0"/>

+			<xsd:element name="communication-logging" type="CommunicationLoggingType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="access-constraint" type="AccessConstraintType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="security-manager-class" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="application-jar-path" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="server-hooks" type="ServerHooksType" minOccurs="0"/>

+			<xsd:element name="init-server-hooks" type="InitServerHooksType" minOccurs="0"/>

+			<xsd:element name="secure" type="SecureType" minOccurs="0"/>

+			<xsd:element name="server-mode" type="ServerModeType" minOccurs="0"/>

+			<xsd:element name="advanced-settings" type="AdvancedSettingsType" minOccurs="0"/>

+			<xsd:element name="default-data-mode" type="DefaultDataModeType" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ServerModeType">

+		<xsd:sequence>

+			<xsd:element name="blocking" type="xsd:boolean" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="AdvancedSettingsType">

+		<xsd:sequence>

+			<xsd:element name="charset" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="use-direct-byte-buffer" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="byte-buffer-size" type="xsd:integer" minOccurs="0"/>

+			<xsd:element name="backlog" type="xsd:integer" minOccurs="0"/>

+			<xsd:element name="socket-linger" type="xsd:integer" minOccurs="0"/>

+			<xsd:element name="debug-non-blocking-mode" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="client-identifier" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="qsobject-pool-maker" type="xsd:string" minOccurs="0"/>			

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="GenricObjectPoolType">

+		<xsd:sequence>

+			<xsd:element name="max-active" type="xsd:integer"/>

+			<xsd:element name="max-idle" type="xsd:integer"/>

+			<xsd:element name="init-size" type="xsd:integer"/>

+		</xsd:sequence>

+	</xsd:complexType>

+

+	<xsd:complexType name="DefaultDataModeType">

+		<xsd:sequence>

+			<xsd:element name="data-type-in" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="data-type-in" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+</xsd:schema>

diff --git a/quickserver/etc/quickserver_config.dtd b/quickserver/etc/quickserver_config.dtd
new file mode 100644
index 0000000..f715f8b
--- /dev/null
+++ b/quickserver/etc/quickserver_config.dtd
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!ELEMENT quickserver (name?, port?, bind-address?,

+	client-event-handler?, 

+	client-command-handler?, client-object-handler?, client-binary-handler?, 

+	client-authentication-handler?, authenticator?,  

+	client-data?, 

+	client-extended-event-handler?,

+	server-banner?, max-connection?, max-connection-msg?, 

+	timeout?, timeout-msg?, 

+	max-auth-try?, max-auth-try-msg?, 

+	console-logging-level?, console-logging-formatter?, 

+	object-pool?,

+	db-object-pool?, communication-logging?,

+	application-configuration?, 

+	security-manager-class?, access-constraint?, application-jar-path?,

+	server-hooks?, init-server-hooks?, secure?, qsadmin-server?,

+	server-mode?, default-data-mode?, advanced-settings?)>

+

+<!ELEMENT db-object-pool (database-connection-set?, db-pool-util)>

+<!ELEMENT database-connection-set (database-connection*)>

+<!ELEMENT database-connection (id, driver, url, username?, password?)>

+

+<!ELEMENT qsadmin-server 

+	(name?, port?, bind-address?,

+	client-event-handler?, 

+	client-command-handler?, client-object-handler?, 

+	client-authentication-handler?, authenticator?, 

+	client-data?, 

+	client-extended-event-handler?,

+	server-banner?, max-connection?, max-connection-msg?, 

+	timeout?, timeout-msg?, 

+	max-auth-try?, max-auth-try-msg?, 

+	console-logging-level?, console-logging-formatter?, 

+	object-pool?,

+	command-plugin?,command-shell?,communication-logging?,

+	access-constraint?, server-hooks?, server-mode?, 

+	default-data-mode?, advanced-settings?)>

+

+<!ELEMENT object-pool (max-active, max-idle, init-size, thread-object-pool?, 

+	client-handler-object-pool?, byte-buffer-object-pool?, 

+	client-data-object-pool?, pool-manager?)>

+<!ELEMENT command-shell (enable, prompt-name?)>

+<!ELEMENT communication-logging (enable)>

+

+<!ELEMENT application-configuration (property*, prompt-type?)>

+<!ELEMENT property (property-name, property-value)>

+

+<!ELEMENT access-constraint (ip-filter)>

+<!ELEMENT ip-filter (enable, allow-access, ip-collection)>

+<!ELEMENT ip-collection (client-ip-address*)>

+

+<!ELEMENT server-hooks (class-name*)>

+<!ELEMENT init-server-hooks (class-name*)>

+<!ELEMENT secure (enable?, load?, port?, protocol?, client-auth-enable?, secure-store)>

+<!ELEMENT secure-store (type?, algorithm?, provider?, key-store-info, trust-store-info?, secure-store-manager?)>

+<!ELEMENT key-store-info (store-file, store-password, key-password)>

+<!ELEMENT trust-store-info (store-file, store-password, type?,  provider?)>

+

+

+<!ELEMENT server-mode (blocking)>

+<!ELEMENT advanced-settings (charset?, use-direct-byte-buffer?, 

+	byte-buffer-size?, backlog?, socket-linger?, debug-non-blocking-mode?,

+	client-identifier?, qsobject-pool-maker?)>

+<!ELEMENT thread-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT client-handler-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT byte-buffer-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT client-data-object-pool (max-active, max-idle, init-size)>

+<!ELEMENT default-data-mode (data-type-in, data-type-out)>

+

+

+<!ELEMENT client-command-handler (#PCDATA)>

+<!ELEMENT client-object-handler (#PCDATA)>

+<!-- for v1.2 and below -->

+<!-- for v1.3 and above -->

+<!ELEMENT authenticator (#PCDATA)>

+<!ELEMENT client-data (#PCDATA)>

+

+<!ELEMENT server-banner (#PCDATA)>

+<!ELEMENT name (#PCDATA)>

+<!ELEMENT port (#PCDATA)>

+<!ELEMENT bind-address (#PCDATA)>

+

+<!ELEMENT max-connection (#PCDATA)>

+<!ELEMENT max-connection-msg (#PCDATA)>

+

+<!ELEMENT timeout (#PCDATA)>

+<!ELEMENT timeout-msg (#PCDATA)>

+

+<!ELEMENT max-auth-try (#PCDATA)>

+<!ELEMENT max-auth-try-msg (#PCDATA)>

+

+<!ELEMENT console-logging-level (#PCDATA)>

+<!ELEMENT console-logging-formatter (#PCDATA)>

+

+<!ELEMENT command-plugin (#PCDATA)>

+

+<!ELEMENT id (#PCDATA)>

+<!ELEMENT driver (#PCDATA)>

+<!ELEMENT url (#PCDATA)>

+<!ELEMENT username (#PCDATA)>

+<!ELEMENT password (#PCDATA)>

+<!ELEMENT db-pool-util (#PCDATA)>

+

+<!ELEMENT max-active (#PCDATA)>

+<!ELEMENT max-idle (#PCDATA)>

+<!ELEMENT init-size (#PCDATA)>

+

+<!-- for v1.3.2 and above -->

+<!ELEMENT enable (#PCDATA)>

+<!ELEMENT prompt-name (#PCDATA)>

+

+<!ELEMENT property-name (#PCDATA)>

+<!ELEMENT property-value (#PCDATA)>

+

+<!-- for v1.3.3 and above -->

+<!ELEMENT security-manager-class (#PCDATA)>

+<!ELEMENT allow-access (#PCDATA)>

+<!ELEMENT client-ip-address (#PCDATA)>

+<!ELEMENT application-jar-path (#PCDATA)>

+<!ELEMENT class-name (#PCDATA)>

+

+<!-- for v1.4.0 and above -->

+<!ELEMENT load (#PCDATA)>

+<!ELEMENT protocol (#PCDATA)>

+<!ELEMENT client-auth-enable (#PCDATA)>

+<!ELEMENT type (#PCDATA)>

+<!ELEMENT algorithm (#PCDATA)>

+<!ELEMENT provider (#PCDATA)>

+<!ELEMENT store-file (#PCDATA)>

+<!ELEMENT store-password (#PCDATA)>

+<!ELEMENT key-password (#PCDATA)>

+<!ELEMENT client-binary-handler (#PCDATA)>

+<!ELEMENT secure-store-manager (#PCDATA)>

+

+<!-- for v1.4.5 and above -->

+<!ELEMENT blocking (#PCDATA)>

+<!ELEMENT charset (#PCDATA)>

+<!ELEMENT use-direct-byte-buffer (#PCDATA)>

+<!ELEMENT byte-buffer-size (#PCDATA)>

+<!ELEMENT backlog (#PCDATA)>

+<!ELEMENT socket-linger (#PCDATA)>

+<!ELEMENT debug-non-blocking-mode (#PCDATA)>

+<!ELEMENT prompt-type (#PCDATA)>

+<!ELEMENT client-identifier (#PCDATA)>

+<!ELEMENT pool-manager (#PCDATA)>

+<!ELEMENT qsobject-pool-maker (#PCDATA)>

+

+<!ELEMENT client-event-handler (#PCDATA)>

+<!ELEMENT data-type-in (#PCDATA)>

+<!ELEMENT data-type-out (#PCDATA)>

+<!ELEMENT client-extended-event-handler (#PCDATA)>

+<!ELEMENT client-authentication-handler (#PCDATA)>

diff --git a/quickserver/etc/quickserver_config.xsd b/quickserver/etc/quickserver_config.xsd
new file mode 100644
index 0000000..0bf29e8
--- /dev/null
+++ b/quickserver/etc/quickserver_config.xsd
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--  http://www.quickserver.org/xml/quickserver_config.xsd -->

+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

+	<xsd:annotation>

+		<xsd:documentation xml:lang="en">QuickServer v 1.4 config schema for QuickServer.org</xsd:documentation>

+	</xsd:annotation>

+	<xsd:element name="quickserver" type="QuickserverType"/>

+	<xsd:element name="qsadmin-server" type="QSAdminServerType"/>

+	<xsd:complexType name="QuickserverType">

+		<xsd:sequence>

+			<xsd:element name="namer" type="xsd:string"/>

+			<xsd:element name="port" type="xsd:unsignedInt" default="9876" minOccurs="0"/>

+			<xsd:element name="bind-address" type="xsd:string" default="0.0.0.0" minOccurs="0"/>

+			<!-- start logic class -->

+			<xsd:element name="client-event-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-command-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-object-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-binary-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:choice minOccurs="0">

+				<!-- for v1.4.6 and above -->

+				<xsd:element name="client-authentication-handler" type="xsd:string" minOccurs="0"/>

+				<!-- Deprecated -->

+				<xsd:element name="authenticator" type="xsd:string" minOccurs="0"/>

+			</xsd:choice>

+			<xsd:element name="client-data" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-extended-event-handler" type="xsd:string" minOccurs="0"/>

+			<!-- end logic class-->

+			<xsd:element name="server-banner" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-level" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-formatter" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="object-pool" type="ObjectPoolType" minOccurs="0"/>

+			<xsd:element name="db-object-pool" type="DbObjectPoolType" minOccurs="0"/>

+			<xsd:element name="communication-logging" type="CommunicationLoggingType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="access-constraint" type="AccessConstraintType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="security-manager-class" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="application-jar-path" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="server-hooks" type="ServerHooksType" minOccurs="0"/>

+			<xsd:element name="init-server-hooks" type="InitServerHooksType" minOccurs="0"/>

+			<xsd:element name="secure" type="SecureType" minOccurs="0"/>

+			<xsd:element name="server-mode" type="ServerModeType" minOccurs="0"/>

+			<xsd:element name="advanced-settings" type="AdvancedSettingsType" minOccurs="0"/>

+			<xsd:element name="default-data-mode" type="DefaultDataModeType" minOccurs="0"/>

+			<!-- qsadmin server -->

+			<xsd:element name="qsadmin-server" type="QSAdminServerType" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ObjectPoolType">

+		<xsd:sequence>

+			<xsd:element name="max-active" type="xsd:integer"/>

+			<xsd:element name="max-idle" type="xsd:integer"/>

+			<xsd:element name="init-size" type="xsd:integer"/>

+			<xsd:element name="thread-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="client-handler-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="byte-buffer-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="client-data-object-pool" type="GenricObjectPoolType" minOccurs="0"/>

+			<xsd:element name="pool-manager" type="xsd:string"  minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="DbObjectPoolType">

+		<xsd:sequence>

+			<xsd:element name="database-connection-set" type="DatabaseConnectionSet" minOccurs="0"/>

+			<xsd:element name="db-pool-util" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="DatabaseConnectionSet">

+		<xsd:sequence>

+			<xsd:element name="database-connection" type="DatabaseConnection" minOccurs="0" maxOccurs="unbounded"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="DatabaseConnection">

+		<xsd:sequence>

+			<xsd:element name="id" type="xsd:string"/>

+			<xsd:element name="driver" type="xsd:string"/>

+			<xsd:element name="url" type="xsd:string"/>

+			<xsd:element name="username" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="password" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="CommunicationLoggingType">

+		<xsd:sequence>

+			<xsd:element name="enable" type="xsd:boolean"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ApplicationConfigurationType">

+		<xsd:sequence>

+			<xsd:element name="property" type="PropertyType" minOccurs="0"/>

+			<xsd:element name="prompt-type" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="PropertyType">

+		<xsd:sequence>

+			<xsd:element name="property-name" type="xsd:string"/>

+			<xsd:element name="property-value" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="AccessConstraintType">

+		<xsd:sequence>

+			<xsd:element name="ip-filter" type="IpFilterType" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="IpFilterType">

+		<xsd:sequence>

+			<xsd:element name="enable" type="xsd:boolean"/>

+			<xsd:element name="allow-access" type="xsd:boolean"/>

+			<xsd:element name="ip-collection" type="IpCollectionnType"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="IpCollectionnType">

+		<xsd:sequence>

+			<xsd:element name="client-ip-address" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ServerHooksType">

+		<xsd:sequence>

+			<xsd:element name="class-name" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="InitServerHooksType">

+		<xsd:sequence>

+			<xsd:element name="class-name" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="SecureType">

+		<xsd:sequence>

+			<xsd:element name="enable" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="load" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="port" type="xsd:unsignedInt" minOccurs="0"/>

+			<xsd:element name="protocol" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-auth-enable" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="secure-store" type="SecureStoreType"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="SecureStoreType">

+		<xsd:sequence>

+			<xsd:element name="type" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="algorithm" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="provider" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="key-store-info" type="KeyStoreInfoType"/>

+			<xsd:element name="trust-store-info" type="TrustStoreInfoType" minOccurs="0"/>

+			<xsd:element name="secure-store-manager" type="xsd:string" default="org.quickserver.security.SecureStoreManager" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="KeyStoreInfoType">

+		<xsd:sequence>

+			<xsd:element name="store-file" type="xsd:string"/>

+			<xsd:element name="store-password" type="xsd:string"/>

+			<xsd:element name="key-password" type="xsd:string"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="TrustStoreInfoType">

+		<xsd:sequence>

+			<xsd:element name="store-file" type="xsd:string"/>

+			<xsd:element name="store-password" type="xsd:string"/>

+			<xsd:element name="type" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="provider" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="QSAdminServerType">

+		<xsd:sequence>

+			<xsd:element name="namer" type="xsd:string"/>

+			<xsd:element name="port" type="xsd:unsignedInt" default="9876" minOccurs="0"/>

+			<xsd:element name="bind-address" type="xsd:string" default="0.0.0.0" minOccurs="0"/>

+			<!-- start logic class -->

+			<xsd:element name="client-event-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-command-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-object-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-binary-handler" type="xsd:string" minOccurs="0"/>

+			<xsd:choice minOccurs="0">

+				<!-- for v1.4.6 and above -->

+				<xsd:element name="client-authentication-handler" type="xsd:string" minOccurs="0"/>

+				<!-- Deprecated -->

+				<xsd:element name="authenticator" type="xsd:string" minOccurs="0"/>

+			</xsd:choice>

+			<xsd:element name="client-data" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="command-plugin" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="client-extended-event-handler" type="xsd:string" minOccurs="0"/>

+			<!-- end logic class-->

+			<xsd:element name="server-banner" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-connection-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="timeout-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="max-auth-try-msg" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-level" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="console-logging-formatter" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="object-pool" type="ObjectPoolType" minOccurs="0"/>

+			<xsd:element name="db-object-pool" type="DbObjectPoolType" minOccurs="0"/>

+			<xsd:element name="communication-logging" type="CommunicationLoggingType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="access-constraint" type="AccessConstraintType" minOccurs="0"/>

+			<xsd:element name="application-configuration" type="ApplicationConfigurationType" minOccurs="0"/>

+			<xsd:element name="security-manager-class" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="application-jar-path" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="server-hooks" type="ServerHooksType" minOccurs="0"/>

+			<xsd:element name="init-server-hooks" type="InitServerHooksType" minOccurs="0"/>

+			<xsd:element name="secure" type="SecureType" minOccurs="0"/>

+			<xsd:element name="server-mode" type="ServerModeType" minOccurs="0"/>

+			<xsd:element name="advanced-settings" type="AdvancedSettingsType" minOccurs="0"/>

+			<xsd:element name="default-data-mode" type="DefaultDataModeType" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="ServerModeType">

+		<xsd:sequence>

+			<xsd:element name="blocking" type="xsd:boolean" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="AdvancedSettingsType">

+		<xsd:sequence>

+			<xsd:element name="charset" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="use-direct-byte-buffer" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="byte-buffer-size" type="xsd:integer" minOccurs="0"/>

+			<xsd:element name="backlog" type="xsd:integer" minOccurs="0"/>

+			<xsd:element name="socket-linger" type="xsd:integer" minOccurs="0"/>

+			<xsd:element name="debug-non-blocking-mode" type="xsd:boolean" minOccurs="0"/>

+			<xsd:element name="client-identifier" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="qsobject-pool-maker" type="xsd:string" minOccurs="0"/>			

+		</xsd:sequence>

+	</xsd:complexType>

+	<xsd:complexType name="GenricObjectPoolType">

+		<xsd:sequence>

+			<xsd:element name="max-active" type="xsd:integer"/>

+			<xsd:element name="max-idle" type="xsd:integer"/>

+			<xsd:element name="init-size" type="xsd:integer"/>

+		</xsd:sequence>

+	</xsd:complexType>

+

+	<xsd:complexType name="DefaultDataModeType">

+		<xsd:sequence>

+			<xsd:element name="data-type-in" type="xsd:string" minOccurs="0"/>

+			<xsd:element name="data-type-in" type="xsd:string" minOccurs="0"/>

+		</xsd:sequence>

+	</xsd:complexType>

+</xsd:schema>

diff --git a/quickserver/install.txt b/quickserver/install.txt
new file mode 100644
index 0000000..3f14bdc
--- /dev/null
+++ b/quickserver/install.txt
@@ -0,0 +1,24 @@
+
+The setup has extracted the library files into $INSTALL_PATH directory.
+
+On Windows
+Do add "$INSTALL_PATH\dist\QuickServer.jar" file to the CLASSPATH
+Do add "$INSTALL_PATH\bin" to the PATH
+
+On Unix
+Do add "$INSTALL_PATH/dist/QuickServer.jar" file to the CLASSPATH
+Do add "$INSTALL_PATH/bin" to the PATH
+
+
+Note: You need not add commons-collections.jar, commons-beanutils.jar,
+commons-digester.jar, commons-logging.jar, commons-pool.jar since 
+QuickServer.jar will directly use it from its directory.
+
+
+
+When deploying or running your server application on a production system do 
+use the -server option while invoking java command.
+
+Eg:
+
+java -server -jar dist/QuickServer.jar -load conf/SomeServer.xml
\ No newline at end of file
diff --git a/quickserver/license.txt b/quickserver/license.txt
new file mode 100644
index 0000000..5c8c81b
--- /dev/null
+++ b/quickserver/license.txt
@@ -0,0 +1,149 @@
+GNU Lesser General Public License
+Version 2.1, February 1999
+
+Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+as the successor of the GNU Library Public License, version 2, hence
+the version number 2.1.]
+
+Preamble
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. 
+
+This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. 
+
+When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
+
+To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. 
+
+For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. 
+
+We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. 
+
+To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. 
+
+Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. 
+
+Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. 
+
+When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. 
+
+We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. 
+
+For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. 
+
+In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. 
+
+Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. 
+
+The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. 
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
+
+A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. 
+
+The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) 
+
+"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 
+
+1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. 
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 
+
+2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: 
+
+a) The modified work must itself be a software library. 
+
+b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+
+c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. 
+
+d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. 
+
+(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) 
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. 
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. 
+
+In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 
+
+3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. 
+
+Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. 
+
+This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 
+
+4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. 
+
+If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. 
+
+However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. 
+
+When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. 
+
+If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) 
+
+Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 
+
+6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. 
+
+You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: 
+
+a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) 
+
+b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. 
+
+c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. 
+
+d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. 
+
+e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
+
+For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. 
+
+It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 
+
+7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: 
+
+a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. 
+
+b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 
+
+9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 
+
+10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 
+
+11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. 
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. 
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. 
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 
+
+12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 
+
+13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 
+
+14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. 
+
+NO WARRANTY 
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/quickserver/nbproject/genfiles.properties b/quickserver/nbproject/genfiles.properties
new file mode 100644
index 0000000..4f7859c
--- /dev/null
+++ b/quickserver/nbproject/genfiles.properties
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.

+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.

+nbproject/jdk.xml.data.CRC32=39bfe33e

+nbproject/jdk.xml.script.CRC32=5342cb35

+nbproject/jdk.xml.stylesheet.CRC32=c45af3dc@1.24.1

diff --git a/quickserver/nbproject/jdk.xml b/quickserver/nbproject/jdk.xml
new file mode 100644
index 0000000..3d29141
--- /dev/null
+++ b/quickserver/nbproject/jdk.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?><project name="jdk" basedir=".">

+

+    

+    <description>

+        Permits selection of a JDK to use when building and running project.

+        See: http://www.netbeans.org/issues/show_bug.cgi?id=64160

+    </description>

+

+    <target name="-jdk-pre-preinit">

+        <condition property="nbjdk.active-or-nbjdk.home">

+            <or>

+                <and>

+                    <isset property="nbjdk.active"/>

+                    <not>

+                        <equals arg1="${nbjdk.active}" arg2="default_platform"/>

+                    </not>

+                </and>

+                <and>

+                    <isset property="nbjdk.home"/>

+                    <not>

+                        <isset property="nbjdk.home.defaulted"/>

+                    </not>

+                </and>

+            </or>

+        </condition>

+    </target>

+

+    <target xmlns:common="http://java.netbeans.org/freeform/jdk.xml" name="-jdk-preinit" depends="-jdk-pre-preinit" if="nbjdk.active-or-nbjdk.home">

+        <macrodef name="property" uri="http://java.netbeans.org/freeform/jdk.xml">

+            <attribute name="name"/>

+            <attribute name="value"/>

+            <sequential>

+                <property name="@{name}" value="${@{value}}"/>

+            </sequential>

+        </macrodef>

+        <common:property name="nbjdk.home" value="platforms.${nbjdk.active}.home"/>

+        <common:property name="nbjdk.javac.tmp" value="platforms.${nbjdk.active}.javac"/>

+        <condition property=".exe" value=".exe">

+            <os family="windows"/> 

+        </condition>

+        <property name=".exe" value=""/>

+        <condition property="nbjdk.javac" value="${nbjdk.home}/bin/javac${.exe}">

+            <equals arg1="${nbjdk.javac.tmp}" arg2="$${platforms.${nbjdk.active}.javac}"/>

+        </condition>

+        <property name="nbjdk.javac" value="${nbjdk.javac.tmp}"/>

+        <common:property name="nbjdk.java.tmp" value="platforms.${nbjdk.active}.java"/>

+        <condition property="nbjdk.java" value="${nbjdk.home}/bin/java${.exe}">

+            <equals arg1="${nbjdk.java.tmp}" arg2="$${platforms.${nbjdk.active}.java}"/>

+        </condition>

+        <property name="nbjdk.java" value="${nbjdk.java.tmp}"/>

+        <common:property name="nbjdk.javadoc.tmp" value="platforms.${nbjdk.active}.javadoc"/>

+        <condition property="nbjdk.javadoc" value="${nbjdk.home}/bin/javadoc${.exe}">

+            <equals arg1="${nbjdk.javadoc.tmp}" arg2="$${platforms.${nbjdk.active}.javadoc}"/>

+        </condition>

+        <property name="nbjdk.javadoc" value="${nbjdk.javadoc.tmp}"/>

+        <common:property name="nbjdk.bootclasspath.tmp" value="platforms.${nbjdk.active}.bootclasspath"/>

+        <condition property="nbjdk.bootclasspath" value="${nbjdk.home}/jre/lib/rt.jar">

+            <equals arg1="${nbjdk.bootclasspath.tmp}" arg2="$${platforms.${nbjdk.active}.bootclasspath}"/>

+        </condition>

+        <property name="nbjdk.bootclasspath" value="${nbjdk.bootclasspath.tmp}"/>

+        <condition property="nbjdk.valid">

+            <and>

+                <available file="${nbjdk.home}" type="dir"/>

+                <available file="${nbjdk.javac}" type="file"/>

+                <available file="${nbjdk.java}" type="file"/>

+                <available file="${nbjdk.javadoc}" type="file"/>

+                

+            </and>

+        </condition>

+        <echo level="verbose">nbjdk.active=${nbjdk.active} nbjdk.home=${nbjdk.home} nbjdk.java=${nbjdk.java} nbjdk.javac=${nbjdk.javac} nbjdk.javadoc=${nbjdk.javadoc} nbjdk.bootclasspath=${nbjdk.bootclasspath} nbjdk.valid=${nbjdk.valid} have-jdk-1.4=${have-jdk-1.4} have-jdk-1.5=${have-jdk-1.5}</echo>

+    </target>

+

+    <target name="-jdk-warn" depends="-jdk-preinit" if="nbjdk.active-or-nbjdk.home" unless="nbjdk.valid">

+        <property name="jdkhome.presumed" location="${java.home}/.."/>

+        <echo level="warning">Warning: nbjdk.active=${nbjdk.active} or nbjdk.home=${nbjdk.home} is an invalid Java platform; ignoring and using ${jdkhome.presumed}</echo>

+    </target>

+

+    <target name="-jdk-presetdef-basic" depends="-jdk-preinit" if="nbjdk.valid" unless="nbjdk.presetdef.basic.done">

+        

+        

+        <macrodef name="javac-presetdef">

+            <attribute name="javacval"/>

+            <sequential>

+                <presetdef name="javac">

+                    <javac fork="yes" executable="@{javacval}"/>

+                </presetdef>

+            </sequential>

+        </macrodef>

+        <javac-presetdef javacval="${nbjdk.javac}"/>

+        <macrodef name="java-presetdef">

+            <attribute name="javaval"/>

+            <sequential>

+                <presetdef name="java">

+                    <java fork="yes" jvm="@{javaval}"/>

+                </presetdef>

+            </sequential>

+        </macrodef>

+        <java-presetdef javaval="${nbjdk.java}"/>

+        <macrodef name="javadoc-presetdef">

+            <attribute name="javadocval"/>

+            <sequential>

+                <presetdef name="javadoc">

+                    <javadoc executable="@{javadocval}"/>

+                </presetdef>

+            </sequential>

+        </macrodef>

+        <javadoc-presetdef javadocval="${nbjdk.javadoc}"/>

+        <macrodef name="junit-presetdef">

+            <attribute name="javaval"/>

+            <sequential>

+                <presetdef name="junit">

+                    <junit fork="yes" jvm="@{javaval}"/>

+                </presetdef>

+            </sequential>

+        </macrodef>

+        <junit-presetdef javaval="${nbjdk.java}"/>

+        <property name="nbjdk.presetdef.basic.done" value="true"/>

+    </target>

+

+    <target name="-jdk-presetdef-nbjpdastart" depends="-jdk-preinit" if="nbjdk.valid" unless="nbjdk.presetdef.nbjpdastart.done">

+        <macrodef name="nbjpdastart-presetdef">

+            <attribute name="bootcpval"/>

+            <sequential>

+                <presetdef name="nbjpdastart">

+                    <nbjpdastart>

+                        <bootclasspath>

+                            <path path="@{bootcpval}"/>

+                        </bootclasspath>

+                    </nbjpdastart>

+                </presetdef>

+            </sequential>

+        </macrodef>

+        <nbjpdastart-presetdef bootcpval="${nbjdk.bootclasspath}"/>

+        <property name="nbjdk.presetdef.nbjpdastart.done" value="true"/>

+    </target>

+

+    <target name="-jdk-default" unless="nbjdk.active-or-nbjdk.home">

+        

+        <property name="java.home.parent" location="${java.home}/.."/>

+        <condition property="nbjdk.home" value="${java.home.parent}">

+            <available file="${java.home.parent}/lib/tools.jar" type="file"/>

+        </condition>

+        <condition property="nbjdk.home" value="${java.home}">

+            <available file="${java.home}/lib/tools.jar" type="file"/>

+        </condition>

+        

+        <condition property="nbjdk.home" value="/Library/Java/Home">

+            <available file="/Library/Java/Home" type="dir"/>

+        </condition>

+        

+        <property name="nbjdk.home" location="${java.home.parent}"/>

+        <property name="nbjdk.home.defaulted" value="true"/>

+    </target>

+

+    <target name="-jdk-init" depends="-jdk-preinit,-jdk-warn,-jdk-presetdef-basic,-jdk-default"/>

+

+</project>
\ No newline at end of file
diff --git a/quickserver/nbproject/nbjdk.properties b/quickserver/nbproject/nbjdk.properties
new file mode 100644
index 0000000..4edb460
--- /dev/null
+++ b/quickserver/nbproject/nbjdk.properties
@@ -0,0 +1 @@
+nbjdk.active=JDK_1.5

diff --git a/quickserver/nbproject/nbjdk.xml b/quickserver/nbproject/nbjdk.xml
new file mode 100644
index 0000000..11ad4dd
--- /dev/null
+++ b/quickserver/nbproject/nbjdk.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<project basedir=".." name="QuickServer">

+    <property file="nbproject/nbjdk.properties"/>

+    <property location="${netbeans.user}/build.properties" name="user.properties.file"/>

+    <property file="${user.properties.file}"/>

+    <import file="jdk.xml"/>

+    <target depends="-jdk-init" name="jar">

+        <ant inheritall="false" target="jar"/>

+    </target>

+    <target depends="-jdk-init" name="clean">

+        <ant inheritall="false" target="clean"/>

+    </target>

+    <target depends="-jdk-init" name="docs">

+        <ant inheritall="false" target="docs"/>

+    </target>

+    <target depends="-jdk-init" name="run_qsadmin">

+        <ant inheritall="false" target="run_qsadmin"/>

+    </target>

+    <target depends="-jdk-init" name="runTests">

+        <ant inheritall="false" target="runTests"/>

+    </target>

+</project>

diff --git a/quickserver/nbproject/private/private.xml b/quickserver/nbproject/private/private.xml
new file mode 100644
index 0000000..9f31be4
--- /dev/null
+++ b/quickserver/nbproject/private/private.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
+    <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
+    <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
+    <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
+        <group>
+            <file>file:/Users/ashetty/Dropbox/development/QuickServer/git/QuickServer-Main/src/main/org/quickserver/util/pool/thread/ClientThread.java</file>
+            <file>file:/Users/ashetty/Dropbox/development/QuickServer/git/QuickServer-Main/src/main/org/quickserver/util/pool/thread/ClientPool.java</file>
+        </group>
+    </open-files>
+</project-private>
diff --git a/quickserver/nbproject/project.xml b/quickserver/nbproject/project.xml
new file mode 100644
index 0000000..6641bf6
--- /dev/null
+++ b/quickserver/nbproject/project.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.ant.freeform</type>
+    <configuration>
+        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1">
+            <name>QuickServer</name>
+        </general-data>
+        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/2">
+            <!-- Do not use Project Properties customizer when editing this file manually. -->
+            <name>QuickServer</name>
+            <properties/>
+            <folders>
+                <source-folder>
+                    <label>QuickServer</label>
+                    <location>.</location>
+                    <encoding>UTF-8</encoding>
+                </source-folder>
+                <source-folder>
+                    <label>src/main</label>
+                    <type>java</type>
+                    <location>src/main</location>
+                    <encoding>UTF-8</encoding>
+                </source-folder>
+                <source-folder>
+                    <label>src/test</label>
+                    <type>java</type>
+                    <location>src/test</location>
+                    <encoding>UTF-8</encoding>
+                </source-folder>
+            </folders>
+            <ide-actions>
+                <action name="build">
+                    <script>nbproject/nbjdk.xml</script>
+                    <target>jar</target>
+                </action>
+                <action name="clean">
+                    <script>nbproject/nbjdk.xml</script>
+                    <target>clean</target>
+                </action>
+                <action name="javadoc">
+                    <script>nbproject/nbjdk.xml</script>
+                    <target>docs</target>
+                </action>
+                <action name="run">
+                    <script>nbproject/nbjdk.xml</script>
+                    <target>run_qsadmin</target>
+                </action>
+                <action name="test">
+                    <script>nbproject/nbjdk.xml</script>
+                    <target>runTests</target>
+                </action>
+                <action name="rebuild">
+                    <script>nbproject/nbjdk.xml</script>
+                    <target>clean</target>
+                    <target>jar</target>
+                </action>
+            </ide-actions>
+            <view>
+                <items>
+                    <source-folder style="packages">
+                        <label>src/main</label>
+                        <location>src/main</location>
+                    </source-folder>
+                    <source-folder style="packages">
+                        <label>src/test</label>
+                        <location>src/test</location>
+                    </source-folder>
+                    <source-file>
+                        <location>build.xml</location>
+                    </source-file>
+                </items>
+                <context-menu>
+                    <ide-action name="build"/>
+                    <ide-action name="rebuild"/>
+                    <ide-action name="clean"/>
+                    <ide-action name="javadoc"/>
+                    <ide-action name="run"/>
+                    <ide-action name="test"/>
+                </context-menu>
+            </view>
+            <subprojects/>
+        </general-data>
+        <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3">
+            <compilation-unit>
+                <package-root>src/main</package-root>
+                <classpath mode="compile">dist/commons-beanutils.jar:dist/commons-collections.jar:dist/commons-digester.jar:dist/commons-logging.jar:dist/commons-pool.jar:dist/metouia.jar</classpath>
+                <source-level>1.6</source-level>
+            </compilation-unit>
+            <compilation-unit>
+                <package-root>src/test</package-root>
+                <unit-tests/>
+                <classpath mode="compile">dist/QSAdminGUI.jar:dist/QuickServer.jar</classpath>
+                <source-level>1.6</source-level>
+            </compilation-unit>
+        </java-data>
+    </configuration>
+</project>
diff --git a/quickserver/options b/quickserver/options
new file mode 100644
index 0000000..3de9a6a
--- /dev/null
+++ b/quickserver/options
@@ -0,0 +1,17 @@
+-d docs

+     -use 

+     -splitindex

+     -windowtitle 'QuickServer v2.1.0 API Specification'

+     -doctitle 'QuickServer v2.1.0 API Specification'

+     -header '<b>QuickServer</b><br><font size="-1">v2.1.0</font>'

+     -bottom 'Copyright &copy; 2003-2017 QuickServer.org

+     -exclude java:javax

+     -sourcepath .\src\main\

+     -author 

+     -group "Core Packages" "org.quickserver.net.server:org.quickserver.net:org.quickserver.util.xmlreader"

+     -group "Client Packages" "org.quickserver.net.client:org.quickserver.net.client.loaddistribution:org.quickserver.net.client.loaddistribution.impl:org.quickserver.net.client.monitoring:org.quickserver.net.client.monitoring.impl:org.quickserver.net.client.pool"

+     -overview src\main\overview.html

+     -group "Util Packages" "org.quickserver.net.qsadmin.gui:org.quickserver.util.logging:org.quickserver.swing"

+     -group "Thread Pool for App" "org.quickserver.util.pool.thread.app"

+     -group "Support Packages" "org.quickserver.net.server.impl:org.quickserver.security:org.quickserver.net.qsadmin:org.quickserver.util.pool:org.quickserver.util.pool.thread:org.quickserver.sql:org.quickserver.util.io"     

+    
\ No newline at end of file
diff --git a/quickserver/origdirlist.txt b/quickserver/origdirlist.txt
new file mode 100644
index 0000000..1b56758
--- /dev/null
+++ b/quickserver/origdirlist.txt
@@ -0,0 +1,57 @@
+.
+./dist
+./bin
+./etc
+./src
+./src/test
+./src/test/org
+./src/test/org/quickserver
+./src/test/org/quickserver/net
+./src/test/org/quickserver/net/server
+./src/test/org/quickserver/net/client
+./src/main
+./src/main/org
+./src/main/org/quickserver
+./src/main/org/quickserver/security
+./src/main/org/quickserver/net
+./src/main/org/quickserver/net/server
+./src/main/org/quickserver/net/server/impl
+./src/main/org/quickserver/net/server/gui
+./src/main/org/quickserver/net/qsadmin
+./src/main/org/quickserver/net/qsadmin/gui
+./src/main/org/quickserver/net/qsadmin/gui/conf
+./src/main/org/quickserver/net/client
+./src/main/org/quickserver/net/client/monitoring
+./src/main/org/quickserver/net/client/monitoring/impl
+./src/main/org/quickserver/net/client/loaddistribution
+./src/main/org/quickserver/net/client/loaddistribution/impl
+./src/main/org/quickserver/net/client/pool
+./src/main/org/quickserver/sql
+./src/main/org/quickserver/swing
+./src/main/org/quickserver/util
+./src/main/org/quickserver/util/io
+./src/main/org/quickserver/util/pool
+./src/main/org/quickserver/util/pool/thread
+./src/main/org/quickserver/util/pool/thread/app
+./src/main/org/quickserver/util/logging
+./src/main/org/quickserver/util/xmlreader
+./src/main/icons
+./.git
+./.git/hooks
+./.git/logs
+./.git/logs/refs
+./.git/logs/refs/heads
+./.git/logs/refs/remotes
+./.git/logs/refs/remotes/origin
+./.git/info
+./.git/objects
+./.git/objects/info
+./.git/objects/pack
+./.git/branches
+./.git/refs
+./.git/refs/heads
+./.git/refs/tags
+./.git/refs/remotes
+./.git/refs/remotes/origin
+./nbproject
+./nbproject/private
diff --git a/quickserver/origlist.txt b/quickserver/origlist.txt
new file mode 100644
index 0000000..18e3784
--- /dev/null
+++ b/quickserver/origlist.txt
@@ -0,0 +1,263 @@
+./apache_license.txt
+./dist/commons-collections.jar
+./dist/quickserver_config.dtd
+./dist/commons-pool.jar
+./dist/metouia.jar
+./dist/QuickServer.jar
+./dist/QSAdminGUI.jar
+./dist/commons-logging.jar
+./dist/QuickServerClient.jar
+./dist/quickserver_config.xsd
+./dist/commons-beanutils.jar
+./dist/commons-digester.jar
+./origlist.txt
+./README.md
+./version.txt
+./setDocsCP.sh
+./bin/QS.bat
+./bin/qs.sh
+./bin/QSAdminGUI.sh
+./bin/QSAdminGUI.bat
+./bin/QuickServer.bat
+./bin/QuickServer.sh
+./todo.txt
+./etc/quickserver_config.dtd
+./etc/quickserver_config.xsd
+./src/test/org/quickserver/SkeletonTest.java
+./src/test/org/quickserver/net/server/UDPEchoServer.java
+./src/test/org/quickserver/net/server/TestEventHandler.java
+./src/test/org/quickserver/net/server/SimpleServerBlockTest.java
+./src/test/org/quickserver/net/server/TestCommandHandler.java
+./src/test/org/quickserver/net/server/QuickServerTest.java
+./src/test/org/quickserver/net/server/SimpleServerNBlockTest.java
+./src/test/org/quickserver/net/client/BlockingUDPClientTest.java
+./src/test/org/quickserver/AllJUnitTests.java
+./src/QSAdminGUI.MF
+./src/QuickServer.MF
+./src/main/XMLConfiguration.xml
+./src/main/overview.html
+./src/main/quickserver_logo.gif
+./src/main/org/quickserver/security/AccessManager.java
+./src/main/org/quickserver/security/SecureStoreManager.java
+./src/main/org/quickserver/security/package.html
+./src/main/org/quickserver/net/server/DataMode.java
+./src/main/org/quickserver/net/server/QuickAuthenticationHandler.java
+./src/main/org/quickserver/net/server/TheClient.java
+./src/main/org/quickserver/net/server/QuickServer.java
+./src/main/org/quickserver/net/server/ClientAuthenticationHandler.java
+./src/main/org/quickserver/net/server/ClientEventHandler.java
+./src/main/org/quickserver/net/server/PoolManager.java
+./src/main/org/quickserver/net/server/ClientEvent.java
+./src/main/org/quickserver/net/server/ClientBinaryHandler.java
+./src/main/org/quickserver/net/server/GhostSocketReaper.java
+./src/main/org/quickserver/net/server/impl/DefaultClientEventHandler.java
+./src/main/org/quickserver/net/server/impl/BlockingClientHandler.java
+./src/main/org/quickserver/net/server/impl/BasicPoolManager.java
+./src/main/org/quickserver/net/server/impl/BasicClientIdentifier.java
+./src/main/org/quickserver/net/server/impl/SyncClientIdentifier.java
+./src/main/org/quickserver/net/server/impl/NonBlockingClientHandler.java
+./src/main/org/quickserver/net/server/impl/BasicClientHandler.java
+./src/main/org/quickserver/net/server/impl/OptimisticClientIdentifier.java
+./src/main/org/quickserver/net/server/impl/RegisterChannelRequest.java
+./src/main/org/quickserver/net/server/impl/package.html
+./src/main/org/quickserver/net/server/ClientObjectHandler.java
+./src/main/org/quickserver/net/server/AuthStatus.java
+./src/main/org/quickserver/net/server/ClientHandler.java
+./src/main/org/quickserver/net/server/QuickAuthenticator.java
+./src/main/org/quickserver/net/server/QuickServerDebugHelper.java
+./src/main/org/quickserver/net/server/Authenticator.java
+./src/main/org/quickserver/net/server/ClientIdentifier.java
+./src/main/org/quickserver/net/server/ClientExtendedEventHandler.java
+./src/main/org/quickserver/net/server/ClientData.java
+./src/main/org/quickserver/net/server/ClientCommandHandler.java
+./src/main/org/quickserver/net/server/DataType.java
+./src/main/org/quickserver/net/server/package.html
+./src/main/org/quickserver/net/server/ClientIdentifiable.java
+./src/main/org/quickserver/net/server/ClientWriteHandler.java
+./src/main/org/quickserver/net/server/gui/About.java
+./src/main/org/quickserver/net/server/gui/package.html
+./src/main/org/quickserver/net/qsadmin/CommandHandler.java
+./src/main/org/quickserver/net/qsadmin/QSAdminShell.java
+./src/main/org/quickserver/net/qsadmin/Data.java
+./src/main/org/quickserver/net/qsadmin/Authenticator.java
+./src/main/org/quickserver/net/qsadmin/QSAdminAPI.java
+./src/main/org/quickserver/net/qsadmin/CommandPlugin.java
+./src/main/org/quickserver/net/qsadmin/package.html
+./src/main/org/quickserver/net/qsadmin/QSAdminServer.java
+./src/main/org/quickserver/net/qsadmin/gui/MainCommandPanel.java
+./src/main/org/quickserver/net/qsadmin/gui/PluginPanel.java
+./src/main/org/quickserver/net/qsadmin/gui/PropertieSet.java
+./src/main/org/quickserver/net/qsadmin/gui/SimpleCommandSet.java
+./src/main/org/quickserver/net/qsadmin/gui/SplashScreen.java
+./src/main/org/quickserver/net/qsadmin/gui/HeaderPanel.java
+./src/main/org/quickserver/net/qsadmin/gui/PropertiePanel.java
+./src/main/org/quickserver/net/qsadmin/gui/conf/MainCommandPanel.xml
+./src/main/org/quickserver/net/qsadmin/gui/conf/PropertieSet.xml
+./src/main/org/quickserver/net/qsadmin/gui/SimpleActionListener.java
+./src/main/org/quickserver/net/qsadmin/gui/SimpleCommand.java
+./src/main/org/quickserver/net/qsadmin/gui/CmdConsole.java
+./src/main/org/quickserver/net/qsadmin/gui/Propertie.java
+./src/main/org/quickserver/net/qsadmin/gui/QSAdminGUI.java
+./src/main/org/quickserver/net/qsadmin/gui/QSAdmin.java
+./src/main/org/quickserver/net/qsadmin/gui/LoginDialog.java
+./src/main/org/quickserver/net/qsadmin/gui/SaveActionListener.java
+./src/main/org/quickserver/net/qsadmin/gui/EditFieldDocumentListener.java
+./src/main/org/quickserver/net/qsadmin/gui/QSAdminMain.java
+./src/main/org/quickserver/net/qsadmin/gui/package.html
+./src/main/org/quickserver/net/ConnectionLostException.java
+./src/main/org/quickserver/net/AppException.java
+./src/main/org/quickserver/net/InitServerHook.java
+./src/main/org/quickserver/net/ServerHook.java
+./src/main/org/quickserver/net/Service.java
+./src/main/org/quickserver/net/client/HttpHost.java
+./src/main/org/quickserver/net/client/monitoring/HostMonitor.java
+./src/main/org/quickserver/net/client/monitoring/HostMonitoringService.java
+./src/main/org/quickserver/net/client/monitoring/impl/PingMonitor.java
+./src/main/org/quickserver/net/client/monitoring/impl/HttpMonitor.java
+./src/main/org/quickserver/net/client/monitoring/impl/UDPMonitor.java
+./src/main/org/quickserver/net/client/monitoring/impl/SocketMonitor.java
+./src/main/org/quickserver/net/client/monitoring/impl/package.html
+./src/main/org/quickserver/net/client/monitoring/HostStateListener.java
+./src/main/org/quickserver/net/client/monitoring/package.html
+./src/main/org/quickserver/net/client/ClientService.java
+./src/main/org/quickserver/net/client/loaddistribution/LoadPattern.java
+./src/main/org/quickserver/net/client/loaddistribution/LoadDistributor.java
+./src/main/org/quickserver/net/client/loaddistribution/impl/RoundRobinLoadPattern.java
+./src/main/org/quickserver/net/client/loaddistribution/impl/HashedLoadPattern.java
+./src/main/org/quickserver/net/client/loaddistribution/impl/RandomLoadPattern.java
+./src/main/org/quickserver/net/client/loaddistribution/impl/FirstActiveLoadPattern.java
+./src/main/org/quickserver/net/client/loaddistribution/impl/package.html
+./src/main/org/quickserver/net/client/loaddistribution/package.html
+./src/main/org/quickserver/net/client/pool/PooledBlockingClient.java
+./src/main/org/quickserver/net/client/pool/PoolableBlockingClient.java
+./src/main/org/quickserver/net/client/pool/BlockingClientPool.java
+./src/main/org/quickserver/net/client/pool/package.html
+./src/main/org/quickserver/net/client/SocketBasedHost.java
+./src/main/org/quickserver/net/client/DummyTrustManager.java
+./src/main/org/quickserver/net/client/BlockingClient.java
+./src/main/org/quickserver/net/client/HostList.java
+./src/main/org/quickserver/net/client/Host.java
+./src/main/org/quickserver/net/client/ClientInfo.java
+./src/main/org/quickserver/net/client/package.html
+./src/main/org/quickserver/net/client/BlockingUDPClient.java
+./src/main/org/quickserver/net/package.html
+./src/main/org/quickserver/sql/DBPoolUtil.java
+./src/main/org/quickserver/sql/package.html
+./src/main/org/quickserver/swing/SensitiveInput.java
+./src/main/org/quickserver/swing/JFrameUtilities.java
+./src/main/org/quickserver/swing/package.html
+./src/main/org/quickserver/util/io/ByteBufferInputStream.java
+./src/main/org/quickserver/util/io/JarFileList.java
+./src/main/org/quickserver/util/io/ByteBufferOutputStream.java
+./src/main/org/quickserver/util/io/MaskingThread.java
+./src/main/org/quickserver/util/io/PasswordField.java
+./src/main/org/quickserver/util/io/DirFileList.java
+./src/main/org/quickserver/util/io/package.html
+./src/main/org/quickserver/util/FileChangeListener.java
+./src/main/org/quickserver/util/MyString.java
+./src/main/org/quickserver/util/Assertion.java
+./src/main/org/quickserver/util/pool/PoolableObject.java
+./src/main/org/quickserver/util/pool/thread/ClientThread.java
+./src/main/org/quickserver/util/pool/thread/ClientPool.java
+./src/main/org/quickserver/util/pool/thread/ThreadObjectFactory.java
+./src/main/org/quickserver/util/pool/thread/app/AppThreadPool.java
+./src/main/org/quickserver/util/pool/thread/app/QSUncaughtExceptionHandler.java
+./src/main/org/quickserver/util/pool/thread/app/NamedThreadFactory.java
+./src/main/org/quickserver/util/pool/thread/app/package.html
+./src/main/org/quickserver/util/pool/thread/package.html
+./src/main/org/quickserver/util/pool/ByteBufferObjectFactory.java
+./src/main/org/quickserver/util/pool/QSObjectPool.java
+./src/main/org/quickserver/util/pool/BasicObjectPool.java
+./src/main/org/quickserver/util/pool/ClientHandlerObjectFactory.java
+./src/main/org/quickserver/util/pool/PoolHelper.java
+./src/main/org/quickserver/util/pool/MakeQSObjectPool.java
+./src/main/org/quickserver/util/pool/QSObjectPoolMaker.java
+./src/main/org/quickserver/util/pool/package.html
+./src/main/org/quickserver/util/ClassUtil.java
+./src/main/org/quickserver/util/FileChangeMonitor.java
+./src/main/org/quickserver/util/TextFile.java
+./src/main/org/quickserver/util/logging/SimpleTextFormatter.java
+./src/main/org/quickserver/util/logging/SimpleJDKLoggingHook.java
+./src/main/org/quickserver/util/logging/MicroFormatter.java
+./src/main/org/quickserver/util/logging/MiniFormatter.java
+./src/main/org/quickserver/util/logging/SimpleConsoleFormatter.java
+./src/main/org/quickserver/util/logging/AsyncHandler.java
+./src/main/org/quickserver/util/logging/SimpleConsoleWithThreadFormatter.java
+./src/main/org/quickserver/util/logging/package.html
+./src/main/org/quickserver/util/JvmUtil.java
+./src/main/org/quickserver/util/xmlreader/QSAdminServerConfig.java
+./src/main/org/quickserver/util/xmlreader/DBObjectPoolConfig.java
+./src/main/org/quickserver/util/xmlreader/TrustStoreInfo.java
+./src/main/org/quickserver/util/xmlreader/IpFilterConfig.java
+./src/main/org/quickserver/util/xmlreader/QSAdminPluginConfig.java
+./src/main/org/quickserver/util/xmlreader/AccessConstraintConfig.java
+./src/main/org/quickserver/util/xmlreader/SecureStore.java
+./src/main/org/quickserver/util/xmlreader/Property.java
+./src/main/org/quickserver/util/xmlreader/InitServerHooks.java
+./src/main/org/quickserver/util/xmlreader/DatabaseConnectionConfig.java
+./src/main/org/quickserver/util/xmlreader/ClientHandlerObjectPoolConfig.java
+./src/main/org/quickserver/util/xmlreader/BasicServerConfig.java
+./src/main/org/quickserver/util/xmlreader/AdvancedSettings.java
+./src/main/org/quickserver/util/xmlreader/ApplicationConfiguration.java
+./src/main/org/quickserver/util/xmlreader/Secure.java
+./src/main/org/quickserver/util/xmlreader/KeyStoreInfo.java
+./src/main/org/quickserver/util/xmlreader/ConfigReader.java
+./src/main/org/quickserver/util/xmlreader/ByteBufferObjectPoolConfig.java
+./src/main/org/quickserver/util/xmlreader/PluginConfigReader.java
+./src/main/org/quickserver/util/xmlreader/ObjectPoolConfig.java
+./src/main/org/quickserver/util/xmlreader/ServerHooks.java
+./src/main/org/quickserver/util/xmlreader/ThreadObjectPoolConfig.java
+./src/main/org/quickserver/util/xmlreader/ServerMode.java
+./src/main/org/quickserver/util/xmlreader/ClientDataObjectPoolConfig.java
+./src/main/org/quickserver/util/xmlreader/DefaultDataMode.java
+./src/main/org/quickserver/util/xmlreader/PoolConfig.java
+./src/main/org/quickserver/util/xmlreader/DatabaseConnectionSet.java
+./src/main/org/quickserver/util/xmlreader/package.html
+./src/main/org/quickserver/util/xmlreader/QuickServerConfig.java
+./src/main/org/quickserver/util/package.html
+./src/main/icons/ball.gif
+./src/main/icons/logo.png
+./src/main/icons/logo.gif
+./src/main/XMLConfiguration.html
+./license.txt
+./.gitignore
+./.gitattributes
+./setDocsCP.bat
+./.git/hooks/pre-applypatch.sample
+./.git/hooks/push-to-checkout.sample
+./.git/hooks/pre-rebase.sample
+./.git/hooks/pre-commit.sample
+./.git/hooks/pre-push.sample
+./.git/hooks/commit-msg.sample
+./.git/hooks/applypatch-msg.sample
+./.git/hooks/fsmonitor-watchman.sample
+./.git/hooks/pre-receive.sample
+./.git/hooks/prepare-commit-msg.sample
+./.git/hooks/post-update.sample
+./.git/hooks/update.sample
+./.git/hooks/pre-merge-commit.sample
+./.git/HEAD
+./.git/index
+./.git/logs/HEAD
+./.git/logs/refs/heads/master
+./.git/logs/refs/remotes/origin/HEAD
+./.git/config
+./.git/packed-refs
+./.git/info/exclude
+./.git/FETCH_HEAD
+./.git/description
+./.git/objects/pack/pack-7fb301ea867f4119e8019bec7bf1fec2905032dc.pack
+./.git/objects/pack/pack-7fb301ea867f4119e8019bec7bf1fec2905032dc.idx
+./.git/refs/heads/master
+./.git/refs/remotes/origin/HEAD
+./options
+./packages
+./requirements.txt
+./nbproject/project.xml
+./nbproject/private/private.xml
+./nbproject/nbjdk.xml
+./nbproject/jdk.xml
+./nbproject/genfiles.properties
+./nbproject/nbjdk.properties
+./build.xml
+./install.txt
diff --git a/quickserver/packages b/quickserver/packages
new file mode 100644
index 0000000..fdee46a
--- /dev/null
+++ b/quickserver/packages
@@ -0,0 +1,22 @@
+org.quickserver.net.server

+org.quickserver.net.server.impl

+org.quickserver.net.qsadmin

+org.quickserver.net

+org.quickserver.sql

+org.quickserver.util

+org.quickserver.util.pool

+org.quickserver.util.pool.thread

+org.quickserver.util.pool.thread.app

+org.quickserver.util.logging

+org.quickserver.util.xmlreader

+org.quickserver.net.qsadmin.gui

+org.quickserver.security

+org.quickserver.swing

+org.quickserver.util.io

+

+org.quickserver.net.client

+org.quickserver.net.client.loaddistribution

+org.quickserver.net.client.loaddistribution.impl

+org.quickserver.net.client.monitoring

+org.quickserver.net.client.monitoring.impl

+org.quickserver.net.client.pool
\ No newline at end of file
diff --git a/quickserver/requirements.txt b/quickserver/requirements.txt
new file mode 100644
index 0000000..fa925a1
--- /dev/null
+++ b/quickserver/requirements.txt
@@ -0,0 +1,19 @@
++++++++++++++++++++++++++++++
+|     QuickServer v 2.1.0   |
+|    System  Requirements   |
++++++++++++++++++++++++++++++
+
+For QuickServer v 2.0.0 and above
+---------------------
+ * Minimum JVM     : v1.7
+ * Recommended JVM : Latest stable jvm version like 1.8
+ * Jakarta Commons Components {Digester, Pool} 
+	This product includes software developed by the Apache Software 
+	Foundation  (http://www.apache.org/). Jar files are shipped with
+	library along with BeanUtils, Collections, Logging.
+	[http://jakarta.apache.org/commons/components.html]
+	Apache Software License is included in the file 
+	"apache_license.txt" for your convenience.
+ * JUnit
+	A framework to write repeatable tests. This library is only
+	needed if are planning to test and new test cases to QuickServer.
diff --git a/quickserver/setDocsCP.bat b/quickserver/setDocsCP.bat
new file mode 100644
index 0000000..3b2eb76
--- /dev/null
+++ b/quickserver/setDocsCP.bat
@@ -0,0 +1 @@
+set CLASSPATH=%CLASSPATH%;.\dist\commons-beanutils.jar;.\dist\commons-collections.jar;.\dist\commons-pool.jar;.\dist\commons-digester.jar;.\dist\commons-logging.jar
\ No newline at end of file
diff --git a/quickserver/setDocsCP.sh b/quickserver/setDocsCP.sh
new file mode 100644
index 0000000..f4c0ec0
--- /dev/null
+++ b/quickserver/setDocsCP.sh
@@ -0,0 +1 @@
+set CLASSPATH=$CLASSPATH:./dist/commons-beanutils.jar:./dist/commons-collections.jar:./dist/commons-pool.jar:./dist/commons-digester.jar:./dist/commons-logging.jar
\ No newline at end of file
diff --git a/quickserver/src/QSAdminGUI.MF b/quickserver/src/QSAdminGUI.MF
new file mode 100644
index 0000000..54afff3
--- /dev/null
+++ b/quickserver/src/QSAdminGUI.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0

+Main-Class: org.quickserver.net.qsadmin.gui.QSAdmin

+Class-Path: metouia.jar commons-digester.jar commons-collections.jar commons-logging.jar commons-beanutils.jar

+Specification-Title: QuickServer

+Specification-Version: 2.0

+Implementation-Version: 2.1.0

+Library-Author: Akshathkumar Shetty

+Library-Author-EMail: akshath@quickserver.org

+Library-Copyrigth: QuickServer.org

+Library-HomePage: http://www.quickserver.org

diff --git a/quickserver/src/QuickServer.MF b/quickserver/src/QuickServer.MF
new file mode 100644
index 0000000..ffb1336
--- /dev/null
+++ b/quickserver/src/QuickServer.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0

+Main-Class: org.quickserver.net.server.QuickServer

+Class-Path: commons-digester.jar commons-collections.jar commons-beanutils.jar commons-logging.jar commons-pool.jar

+Specification-Title: QuickServer

+Specification-Version: 2.0

+Implementation-Version: 2.1.0

+Library-Author: Akshathkumar Shetty

+Library-Author-EMail: akshath@quickserver.org

+Library-Copyrigth: QuickServer.org

+Library-HomePage: http://www.quickserver.org

diff --git a/quickserver/src/main/XMLConfiguration.html b/quickserver/src/main/XMLConfiguration.html
new file mode 100644
index 0000000..c91b8fd
--- /dev/null
+++ b/quickserver/src/main/XMLConfiguration.html
Binary files differ
diff --git a/quickserver/src/main/XMLConfiguration.xml b/quickserver/src/main/XMLConfiguration.xml
new file mode 100644
index 0000000..1e8a58b
--- /dev/null
+++ b/quickserver/src/main/XMLConfiguration.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0"?>

+<quickserver>

+	<name>EchoServer v 1.2</name>

+	<port>4123</port>

+	<bind-address>0.0.0.0</bind-address>

+

+	<!-- business logic classes -->

+	<client-event-handler>

+		echoserver.EchoCommandHandler

+	</client-event-handler>

+	<client-command-handler>

+		echoserver.EchoCommandHandler

+	</client-command-handler>

+	<client-authentication-handler>

+		echoserver.EchoAuthenticatorHandler

+	</client-authentication-handler>

+	<client-data>

+		echoserver.Data

+	</client-data>

+	<!-- business logic classes -->

+

+

+	<!-- in milliseconds -->

+	<timeout>60000</timeout>

+

+	<timeout-msg>-ERR Timeout</timeout-msg>

+	<max-auth-try>5</max-auth-try>

+	<max-auth-try-msg>-ERR Max Auth Try Reached</max-auth-try-msg>

+	<max-connection>-1</max-connection>

+	<max-connection-msg>Server Busy\nMax Connection Reached</max-connection-msg>

+

+	<console-logging-level>INFO</console-logging-level>

+	<console-logging-formatter>

+		org.quickserver.util.logging.SimpleConsoleFormatter

+	</console-logging-formatter>

+

+	<object-pool>

+		<max-active>-1</max-active>

+		<max-idle>50</max-idle>

+

+		<thread-object-pool>

+			<max-active>200</max-active>

+			<max-idle>50</max-idle>

+		</thread-object-pool>

+

+		<client-handler-object-pool>

+			<max-active>-1</max-active>

+			<max-idle>50</max-idle>

+		</client-handler-object-pool>

+

+		<byte-buffer-object-pool>

+			<max-active>500</max-active>

+			<max-idle>50</max-idle>

+		</byte-buffer-object-pool>

+

+		<client-data-object-pool>

+			<max-active>-1</max-active>

+			<max-idle>50</max-idle>

+		</client-data-object-pool>

+	</object-pool>

+

+	<communication-logging>

+		<enable>true</enable>

+	</communication-logging>

+

+	<qsadmin-server>

+		<port>4124</port>

+		<bind-address>127.0.0.1</bind-address>

+

+		<command-shell>

+			<enable>true</enable>

+		</command-shell>

+

+		<communication-logging>

+			<enable>false</enable>

+		</communication-logging>

+

+		<access-constraint>

+		  <ip-filter> 

+			<enable>false</enable>

+			<allow-access>true</allow-access>

+			<!-- <allow-access>false<allow-access> -->

+			<ip-collection>

+			  <client-ip-address>127.0.0.1</client-ip-address> 

+			  <!--<client-ip-address>192.168.1.100</client-ip-address> -->

+			</ip-collection>

+		  </ip-filter> 

+		</access-constraint> 

+	</qsadmin-server>

+

+	<db-object-pool>

+		<database-connection-set>

+			<database-connection>

+				<id>TestDB1</id>

+				<driver>sun.jdbc.odbc.JdbcOdbcDriver</driver>

+				<url>jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=c:\\QuickServer\\examples\\db\\echoAuth.mdb</url>

+				<username></username>

+				<password></password>

+			</database-connection>

+		</database-connection-set>

+		<db-pool-util>echoserver.DBPoolUtil</db-pool-util>

+	</db-object-pool>

+

+	<application-configuration>

+		<prompt-type>gui</prompt-type>

+		<!--<prompt-type>console</prompt-type>-->

+		<!--

+		<property>

+			<property-name>APP_PARAM1</property-name>

+			<property-value>test value</property-value>

+		</property>

+		<property>

+			<property-name>APP_SECRET1</property-name>

+		</property>

+		-->

+	</application-configuration>

+

+

+	<!--

+	<security-manager-class>

+		org.quickserver.net.security.AccessManager

+	</security-manager-class>

+	-->

+

+	<access-constraint>

+	  <ip-filter> 

+	    <enable>false</enable>

+	    <allow-access>false</allow-access>

+	    <ip-collection>

+		  <client-ip-address>127.0.0.1</client-ip-address> 

+	    </ip-collection>

+	  </ip-filter> 

+	</access-constraint>

+

+	<application-jar-path>../dist/EchoServer.jar</application-jar-path>

+

+	<server-hooks>

+		<!--

+		<class-name>org.quickserver.net.server.ObjectCleaner</class-name>

+		-->

+	</server-hooks>

+		

+	<init-server-hooks>

+		<class-name>echoserver.SetupLoggingHook</class-name>

+	</init-server-hooks>

+

+	<advanced-settings>		

+		<charset>ISO-8859-1</charset>

+		<backlog>1024</backlog>		

+		<socket-linger>-1</socket-linger>

+	</advanced-settings>

+</quickserver>

diff --git a/quickserver/src/main/icons/ball.gif b/quickserver/src/main/icons/ball.gif
new file mode 100644
index 0000000..d4c5cde
--- /dev/null
+++ b/quickserver/src/main/icons/ball.gif
Binary files differ
diff --git a/quickserver/src/main/icons/logo.gif b/quickserver/src/main/icons/logo.gif
new file mode 100644
index 0000000..05d5b09
--- /dev/null
+++ b/quickserver/src/main/icons/logo.gif
Binary files differ
diff --git a/quickserver/src/main/icons/logo.png b/quickserver/src/main/icons/logo.png
new file mode 100644
index 0000000..79bac2e
--- /dev/null
+++ b/quickserver/src/main/icons/logo.png
Binary files differ
diff --git a/quickserver/src/main/org/quickserver/net/AppException.java b/quickserver/src/main/org/quickserver/net/AppException.java
new file mode 100644
index 0000000..663caae
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/AppException.java
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net;
+
+/**
+ * Generic Application Exception used by 
+ * {@link org.quickserver.net.server.QuickServer} and its support Classes.
+ * @author Akshathkumar Shetty
+ */
+public class AppException extends Exception {
+
+	/**
+	 * @since 1.4
+	 */
+	public AppException() {
+		super();
+	}
+
+	public AppException(String s) {
+		super(s);
+	}
+
+	public AppException(String s, Exception ex) {
+		super(s,ex);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/ConnectionLostException.java b/quickserver/src/main/org/quickserver/net/ConnectionLostException.java
new file mode 100644
index 0000000..7758aef
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/ConnectionLostException.java
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net;
+
+/**
+ * Generic ConnectionLostException used by 
+ * {@link org.quickserver.net.server.QuickServer} and its support classes.
+ * @since 1.4
+ * @author Akshathkumar Shetty
+ */
+public class ConnectionLostException extends java.io.IOException {
+
+	public ConnectionLostException() {
+		super();
+	}
+
+	public ConnectionLostException(String s) {
+		super(s);
+	}
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/InitServerHook.java b/quickserver/src/main/org/quickserver/net/InitServerHook.java
new file mode 100644
index 0000000..9eb2e6c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/InitServerHook.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net;
+
+import org.quickserver.net.server.QuickServer;
+
+/**
+ * This interface is for any class that would like to become
+ * a onetime on init server hook. Called just after server 
+ * loads the xml configuration file. Can be using to set up loggers.
+ * These classes should have a default constructor.
+ * @see org.quickserver.util.xmlreader.InitServerHooks
+ * @see org.quickserver.net.ServerHook
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public interface InitServerHook {
+	/** 
+	 * Information about the server hook.
+	 */
+	public String info();
+
+	/** 
+	 * Method called to perform any initialisation
+	 * @param quickserver is the server to which hook belongs to.
+	 */
+	public void handleInit(QuickServer quickserver) throws Exception;
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/ServerHook.java b/quickserver/src/main/org/quickserver/net/ServerHook.java
new file mode 100644
index 0000000..ec6f441
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/ServerHook.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net;
+
+import org.quickserver.net.server.QuickServer;
+
+/**
+ * This interface is for any class that would like to become
+ * a server hook. These are event listeners to the QuickServer.
+ * <p>Following types of Server hooks are currently supported.
+ * pre-startup, post-startup, pre-shutdown, post-shutdown.
+ * These classes should have a default constructor. </p>
+ * @see org.quickserver.util.xmlreader.ServerHooks
+ * @see org.quickserver.net.InitServerHook
+ * @author Akshathkumar Shetty
+ * @since 1.3.3
+ */
+public interface ServerHook {
+	//--types of hooks supported
+	public final static int PRE_STARTUP = 100;
+	public final static int POST_STARTUP = 101;
+	public final static int PRE_SHUTDOWN = 201;
+	public final static int POST_SHUTDOWN = 202;
+
+	/** 
+	 * Information about the server hook.
+	 */
+	public String info();
+
+	/** 
+	 * Method called to perform any initialisation
+	 * @param quickserver is the server to which hook belongs to.
+	 */
+	public void initHook(QuickServer quickserver);
+
+	/** 
+	 * Invoked pre/post server event. If the hook is doing some 
+	 * action for the even passed it should return true indicating the same.
+	 * @see #PRE_STARTUP
+	 * @see #POST_STARTUP
+	 * @see #PRE_SHUTDOWN
+	 * @see #POST_SHUTDOWN
+	 */
+	public boolean handleEvent(int event);
+}
diff --git a/quickserver/src/main/org/quickserver/net/Service.java b/quickserver/src/main/org/quickserver/net/Service.java
new file mode 100644
index 0000000..a67a7e7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/Service.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net;
+/**
+ * This interface is for any class that would like to follow
+ * Service Configurator Pattern.
+ * <p>
+ * Thanks to Markus Elfring for his email.
+ * </p>
+ * @author Akshathkumar Shetty
+ * @since 1.2
+ */
+public interface Service {
+	/** Un initialised or unknown */
+	public static int UNKNOWN  =  -1; 
+	public static int STOPPED  =  0;
+	public static int INIT =  1;
+	public static int SUSPENDED  =  2;
+	public static int RUNNING =  5;
+	
+	/** Initialise and create the service */
+	public boolean initService(Object config[]);
+	/**Start the service */
+	public boolean startService();
+	/** Stop the service */
+	public boolean stopService();
+	/** Suspend the service  */
+	public boolean suspendService();  //Sets max_client =0;
+	/** Resume the service */ 
+	public boolean resumeService(); //Set max_client back to its value
+
+	/** 
+	 * Information about the service, recommended format given below.
+	 * <p><code>
+	 * &lt;&lt;ServiceName&gt;&gt; v&lt;&lt;Version_No&gt;&gt;\n<br>
+	 * &lt;&lt;IP_ADDRESS&gt;&gt; &lt;&lt;PORT_NO&gt;&gt;\n<br>
+	 * &lt;&lt;ANY OTHET INFORMATION&gt;&gt;
+	 * </code></p>
+	 */
+	public String info();
+	/** 
+	 * Returns the state of the process 
+	 * As any constant of {@link Service} interface.
+	 */
+	public int getServiceState();
+
+	/**
+	 * Returns service error if any.
+	 * @since 1.4.7
+	 */
+	public Throwable getServiceError();
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/BlockingClient.java b/quickserver/src/main/org/quickserver/net/client/BlockingClient.java
new file mode 100644
index 0000000..fcbb3b5
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/BlockingClient.java
@@ -0,0 +1,507 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.client;
+
+import java.io.*;
+import java.net.*;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.util.logging.*;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+/**
+ * Blocking Client socket.
+ * @author Akshathkumar Shetty
+ * @since 1.4.7
+ */
+public class BlockingClient implements ClientService {
+	private static final Logger logger = Logger.getLogger(BlockingClient.class.getName());
+	private static String charset = "ISO-8859-1";
+	private static boolean debug = false;
+	private static final int _CR = 13;  
+	private static final int _LF = 10;
+        
+        private static String providerForSSLContext;
+	
+	public static boolean isDebug() {
+		return debug;
+	}
+
+	public static void setDebug(boolean aDebug) {
+		debug = aDebug;
+	}
+
+    /**
+     * @return the providerForSSLContext
+     */
+    public static String getProviderForSSLContext() {
+        return providerForSSLContext;
+    }
+
+    /**
+     * @param aProviderForSSLContext the providerForSSLContext to set
+     */
+    public static void setProviderForSSLContext(String aProviderForSSLContext) {
+        providerForSSLContext = aProviderForSSLContext;
+    }
+
+	private String host = "localhost";
+	private int port = 0;	
+
+	private Socket socket;
+	
+	private boolean secure;
+	private boolean useDummyTrustManager;
+	private TrustManager[] trustManager;
+	private SSLContext sslContext;
+	private SSLSocketFactory sslSocketFactory;
+	private InputStream clientAuthKeystoreInputStream;
+	private char[] clientAuthKeystorePassword;
+	private char[] clientAuthKeyPassword;
+	
+	private OutputStream out;
+	private BufferedOutputStream b_out;
+	private ObjectOutputStream o_out;
+
+	private InputStream in;
+	private BufferedInputStream b_in;
+	private BufferedReader br;
+	private ObjectInputStream o_in;
+        
+
+	public void setCharset(String c) {
+		charset = c;
+	}
+	public String getCharset() {
+		return charset;
+	}	
+
+	public int getMode() {
+		return ClientService.BLOCKING;
+	}
+
+	public void connect(String host, int port) throws Exception {
+		this.host = host;
+		this.port = port;
+
+		if(isDebug()) logger.finest("Connecting to "+host+":"+port);
+		
+		if(isSecure()) {
+			makeSSLSocketFactory();
+			socket = getSslSocketFactory().createSocket(host, port);
+		} else {
+			socket = new Socket(host, port);
+		}
+
+		in = socket.getInputStream();
+		out = socket.getOutputStream();
+		if(isDebug()) logger.fine("Connected");
+	}
+
+	public boolean isConnected() {
+		if(socket==null) return false;
+		return socket.isConnected();
+	}
+
+	public void close() throws IOException {
+		if(isDebug()) logger.fine("Closing");
+		
+		if(out!=null) {
+			if(isDebug()) logger.finest("Closing output streams");
+			try {
+				out.flush();
+			} catch(IOException ioe) {
+				logger.log(Level.FINEST, "Flushing output streams failed: {0}", ioe);
+			}
+			/*
+			if(socket!=null && isSecure()==false) {
+				socket.shutdownOutput();
+			}
+			 */
+
+			try {
+				if(o_out != null) {
+					o_out.close();
+				}
+			} catch(IOException ioe) {
+				logger.log(Level.FINEST, "o_out stream close failed: {0}", ioe);
+			}
+
+			try {
+				if(b_out != null) {
+					b_out.close();
+				}
+			} catch(IOException ioe) {
+				logger.log(Level.FINEST, "b_out stream close failed: {0}", ioe);
+			}
+
+			try {
+				out.close();
+			} catch(IOException ioe) {
+				logger.log(Level.FINEST, "out stream close failed: {0}", ioe);
+			}
+		}
+
+		if(in!=null) {
+			if(isDebug()) logger.finest("Closing input streams");
+			/*
+			if(socket!=null && isSecure()==false) {
+				socket.shutdownInput();
+			}
+			 */
+
+			if(o_in != null) {
+				try {
+					o_in.close();
+				} catch(IOException ioe) {
+					logger.log(Level.FINEST, "o_in stream close failed: {0}", ioe);
+				}
+			} 
+			if(b_in != null) {
+				try {
+					b_in.close();
+				} catch(IOException ioe) {
+					logger.log(Level.FINEST, "b_in stream close failed: {0}", ioe);
+				}
+			}	
+			if(br != null) {
+				try {
+					br.close();
+				} catch(IOException ioe) {
+					logger.log(Level.FINEST, "b_in stream close failed: {0}", ioe);
+				}
+			}
+			try {
+				in.close();
+			} catch(IOException ioe) {
+				logger.log(Level.FINEST, "in stream close failed: {0}", ioe);
+			}
+		}
+
+		if(socket!=null) {
+			socket.close();
+			socket = null;
+		}
+	}
+	
+	public void sendByte(int data) throws IOException {
+		if(isDebug()) logger.fine("Sending byte");
+		checkBufferedOutputStream();
+		b_out.write(data);
+		b_out.flush();
+	}
+
+	public void sendBytes(byte[] data) throws IOException {
+		if(isDebug()) logger.log(Level.FINE, "Sending bytes: {0}", data.length);
+		checkBufferedOutputStream();
+		b_out.write(data);
+		b_out.flush();
+	}
+
+	public void sendBytes(String data, String _charset) throws IOException {
+		if(isDebug()) logger.log(Level.FINE, "Sending: {0}", data);
+		checkBufferedOutputStream();
+		if(_charset==null) _charset = charset;
+		byte d[] = data.getBytes(_charset);
+		b_out.write(d, 0 , d.length);
+		b_out.flush();
+	}
+
+	public void sendLine(String data, String _charset) throws IOException {
+		if(isDebug()) logger.log(Level.FINE, "Sending: {0}", data);
+		checkBufferedOutputStream();
+		if(_charset==null) _charset = charset;
+		byte d[] = data.getBytes(_charset);
+		b_out.write(d, 0 , d.length);
+		d = "\r\n".getBytes(_charset);
+		b_out.write(d, 0 , d.length);
+		b_out.flush();
+	}
+
+	public void sendObject(Object data) throws IOException {
+		checkObjectOutputStream();
+		o_out.writeObject(data);
+		o_out.flush();
+	}
+	
+	public int readByte() throws IOException {
+		checkBufferedInputStream();
+		return b_in.read();
+	}
+
+	public byte[] readBytes() throws IOException {
+		checkBufferedInputStream();
+		return readInputStream(b_in);
+	}
+	
+	public byte[] readBytes(int countToRead) throws IOException {
+		checkBufferedInputStream();
+		return readInputStream(b_in, countToRead);
+	}
+
+	public String readBytes(String _charset) throws IOException {
+		byte data[] = readBytes();
+		if(data==null) return null;
+		if(_charset==null) _charset = charset;
+		return new String(data, _charset);
+	}
+	
+	public String readBytes(String _charset, int countToRead) throws IOException {
+		byte data[] = readInputStream(b_in, countToRead);
+		if(data==null) return null;
+		if(_charset==null) _charset = charset;
+		return new String(data, _charset);
+	}
+
+	public String readLine() throws IOException {
+		checkBufferedReader();
+		return br.readLine();
+	}
+	
+	 public String readCRLFLine() throws IOException { 
+		checkBufferedInputStream();
+		
+		StringBuilder sb = new StringBuilder();  
+		int _ch = -1;
+		do {
+			_ch = b_in.read();
+			if(_ch==-1) {
+				return null;
+			}
+			if(_ch==_CR) {
+				_ch = b_in.read();
+				if(_ch==_LF) {
+					break;
+				} else {
+					sb.append((char) _CR);  
+					sb.append((char) _ch);
+				}
+			} else {
+				sb.append((char) _ch);  
+			}
+		} while(true);		
+		
+		return(new String(sb));  
+   } 
+
+	public Object readObject() throws IOException, ClassNotFoundException {
+		checkObjectInputStream();
+		return o_in.readObject();
+	}
+
+	public Socket getSocket() {
+		return socket;
+	}
+
+	private void checkObjectOutputStream() throws IOException {
+		if(o_out==null) {
+			b_out = null;
+			o_out = new ObjectOutputStream(out);
+			o_out.flush();
+		}
+	}
+	private void checkBufferedOutputStream() throws IOException {
+		if(b_out==null) {
+			o_out = null;
+			b_out = new BufferedOutputStream(out);
+		}
+	}
+
+	private void checkBufferedInputStream() throws IOException {
+		if(b_in==null) {
+			br = null;
+			o_in = null;
+			b_in = new BufferedInputStream(in);
+		}
+	}
+	private void checkBufferedReader() throws IOException {
+		if(br==null) {
+			b_in = null;
+			o_in = null;
+			br = new BufferedReader(new InputStreamReader(in, charset));
+		}
+	}
+	private void checkObjectInputStream() throws IOException {
+		if(o_in==null) {
+			b_in = null;
+			br = null;
+			o_in = new ObjectInputStream(in);
+		}
+	}
+	
+	public static byte[] readInputStream(InputStream _in, int countToRead) 
+			throws IOException {
+		byte data[] = new byte[countToRead];
+		if(_in==null) {
+			throw new IOException("InputStream can't be null!");
+		}
+		
+		int count = 0;
+		int dataRead = 0;
+		int dataLeftToRead = countToRead - dataRead;
+		
+		while(true) {
+			count = _in.read(data, dataRead, dataLeftToRead);
+			if(count==-1) {
+				if(dataRead==countToRead) {
+					break;
+				} else {
+					throw new IOException("we have eof!");
+				}
+			} else {
+				dataRead = dataRead + count;
+				dataLeftToRead = countToRead - dataRead;
+			}
+			
+			if(dataRead>=countToRead) {
+				break;
+			}			
+		}//while
+		return data;
+	}
+
+	public static byte[] readInputStream(InputStream _in) throws IOException {
+		byte data[] = null;
+		if(_in==null)
+			throw new IOException("InputStream can't be null!");
+		
+		int s = _in.read();
+		if(s==-1) {
+			return null; //Connection lost
+		}
+		int alength = _in.available();
+		if(alength > 0) {
+			data = new byte[alength+1];	
+			data[0] = (byte) s;
+			int len = _in.read(data, 1, alength);
+			if(len < alength) {
+				data = copyOf(data, len+1);
+			}
+		} else {
+			data = new byte[1];
+			data[0] = (byte) s;
+		}
+		return data;
+	}
+	
+	private static byte[] copyOf(byte data[], int len) {
+		byte newdate[] = new byte[len];
+		System.arraycopy(data, 0, newdate, 0, len);
+		return newdate;
+	}
+	
+	public boolean isSecure() {
+		return secure;
+	}
+
+	public void setSecure(boolean secure) {
+		this.secure = secure;
+	}
+
+	public boolean isUseDummyTrustManager() {
+		return useDummyTrustManager;
+	}
+
+	public void setUseDummyTrustManager(boolean useDummyTrustManager) {
+		this.useDummyTrustManager = useDummyTrustManager;
+	}
+
+	public TrustManager[] getTrustManager() {
+		return trustManager;
+	}
+
+	public void setTrustManager(TrustManager[] trustManager) {
+		this.trustManager = trustManager;
+	}
+
+	public SSLContext getSslContext() {
+		return sslContext;
+	}
+
+	public void setSslContext(SSLContext sslContext) {
+		this.sslContext = sslContext;
+	}
+	
+	public SSLSocketFactory getSslSocketFactory() {
+		return sslSocketFactory;
+	}
+
+	public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
+		this.sslSocketFactory = sslSocketFactory;
+	}
+
+	public void makeSSLSocketFactory() throws Exception {
+		if(getSslContext()==null && getSslSocketFactory()==null) {
+			SSLContext context = null;
+                        
+                        if(getProviderForSSLContext()!=null) {
+                            context = SSLContext.getInstance("TLS", getProviderForSSLContext());
+                        } else {
+                            context = SSLContext.getInstance("TLS");
+                        }
+                        
+			if(getTrustManager()==null && isUseDummyTrustManager()) {
+				setTrustManager(new TrustManager[]{DummyTrustManager.getInstance()});
+			}
+			
+			KeyManager km[] = null;
+			if(getClientAuthKeystoreInputStream()!=null) {
+				KeyStore keyStore = KeyStore.getInstance("JKS");
+				keyStore.load(getClientAuthKeystoreInputStream(), getClientAuthKeystorePassword());
+				KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+				kmf.init(keyStore, getClientAuthKeyPassword());
+				km = kmf.getKeyManagers();
+			} else {
+				km = new KeyManager[0];
+			}
+
+			context.init(km, getTrustManager(), new SecureRandom());
+			setSslContext(context);
+		}
+		
+		if(getSslSocketFactory()==null) {
+			SSLSocketFactory factory = getSslContext().getSocketFactory();
+			setSslSocketFactory(factory);
+		}
+	}
+
+	public InputStream getClientAuthKeystoreInputStream() {
+		return clientAuthKeystoreInputStream;
+	}
+
+	public void setClientAuthKeystoreInputStream(InputStream clientAuthKeystoreInputStream) {
+		this.clientAuthKeystoreInputStream = clientAuthKeystoreInputStream;
+	}
+
+	public char[] getClientAuthKeystorePassword() {
+		return clientAuthKeystorePassword;
+	}
+
+	public void setClientAuthKeystorePassword(char clientAuthKeystorePassword[]) {
+		this.clientAuthKeystorePassword = clientAuthKeystorePassword;
+	}
+
+	public char[] getClientAuthKeyPassword() {
+		return clientAuthKeyPassword;
+	}
+
+	public void setClientAuthKeyPassword(char[] clientAuthKeyPassword) {
+		this.clientAuthKeyPassword = clientAuthKeyPassword;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/BlockingUDPClient.java b/quickserver/src/main/org/quickserver/net/client/BlockingUDPClient.java
new file mode 100644
index 0000000..cadcb96
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/BlockingUDPClient.java
@@ -0,0 +1,211 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author mukundan
+ */
+public class BlockingUDPClient implements ClientService {	
+	private static final Logger logger = Logger.getLogger(BlockingClient.class.getName());
+
+	private SocketAddress address;
+	private DatagramSocket socket;
+	private DatagramPacket incoming;
+	private DatagramPacket outgoing;
+	
+	private static int timeoutInSeconds = 5;
+	private static String charset = "ISO-8859-1";
+	private static boolean debug = false;
+	
+	private StringBuilder readLineBuffer = new StringBuilder();	
+
+	public static int getTimeoutInSeconds() {
+		return timeoutInSeconds;
+	}
+
+	public static void setTimeoutInSeconds(int aTimeoutInSeconds) {
+		timeoutInSeconds = aTimeoutInSeconds;
+	}
+
+	public static boolean isDebug() {
+		return debug;
+	}
+
+	public static void setDebug(boolean aDebug) {
+		debug = aDebug;
+	}
+
+	public int getMode() {
+		return ClientService.BLOCKING;
+	}
+	
+	public void connect(String host, int port) throws Exception {
+		socket = new DatagramSocket();
+		address = new InetSocketAddress(host, port);
+		socket.setSoTimeout(getTimeoutInSeconds()*1000);
+	}
+
+	public boolean isConnected() {
+		return socket.isConnected();
+	}
+
+	public void close() throws IOException {
+		if (null != socket){
+			socket.close();
+			socket = null;
+		}
+	}
+
+	public void sendBytes(byte[] data) throws IOException {
+		if(isDebug()) logger.log(Level.FINE, "Sending bytes: {0}", data.length);
+		
+		outgoing = new DatagramPacket(data, data.length, address);
+		if (null == socket){
+			throw new IOException("socket is null");
+		}
+		socket.send(outgoing);
+	}
+
+	public void sendBytes(String data, String charset) throws IOException {
+		if (null == data || "".equals(data)) {
+			throw new IOException("data is null or blank");
+		}
+		sendBytes(data.getBytes(charset));
+	}
+
+	public void sendLine(String data, String charset) throws IOException {
+		String outData = data + "\r\n";
+		sendBytes(outData, charset);
+	}
+
+	public void sendObject(Object data) throws IOException {
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		ObjectOutputStream oos = new ObjectOutputStream(bos);
+		oos.writeObject(data);
+		oos.flush();
+		sendBytes(bos.toByteArray());
+	}
+
+	private byte[] readBinary() throws IOException {
+		byte[] buf = new byte[8192]; //TODO - need to check the size
+		
+		incoming = new DatagramPacket(buf, buf.length);
+		socket.receive(incoming);
+		
+		if (null == incoming.getData()){
+			return null;
+		}
+		int incomingLen = incoming.getLength();
+		byte [] inData = new byte[incomingLen];
+		System.arraycopy(incoming.getData(), 0, inData, 0, incomingLen);
+		return inData;
+	}
+
+	public byte[] readBytes() throws IOException {
+		byte [] inData = readBinary();
+		if (null == inData){
+			return null;
+		}
+		return inData;
+	}
+
+	public String readBytes(String charset) throws IOException {
+		return new String(readBytes(), charset);
+	}
+	
+	public String readLine() throws IOException {
+		int idx = -1;
+		do {
+			idx = readLineBuffer.indexOf("\r\n");
+			if (idx == -1) {
+				byte [] inData = readBinary();
+				readLineBuffer.append(new String(inData, charset));
+			} else {
+				break;
+			}
+		} while(true);
+		
+		String data = readLineBuffer.substring(0, idx);
+		readLineBuffer.delete(0, idx+2);	
+		
+		return data;
+	}
+
+	public Object readObject() throws IOException, ClassNotFoundException {
+		byte[] inData = readBinary();
+		ObjectInputStream oos = null;
+		Object obj = null;
+		if (null != inData){
+			oos = new ObjectInputStream(new ByteArrayInputStream(inData));
+			obj = oos.readObject();
+		}
+		return obj;
+	}
+
+	public Socket getSocket() {
+		//TODO - remove this method from the interface (ClientService)
+		throw new UnsupportedOperationException("Not supported for UDP");
+	}
+	
+	public byte[] sendAndReceiveBinary(String host, int port, byte[] data) throws Exception{
+		connect(host, port);
+		sendBytes(data);
+		byte[] response = readBinary();
+		return response;
+	}
+	
+	public String sendAndReceiveBytes(String host, int port, String data) throws Exception{
+		connect(host, port);
+		sendBytes(data, charset);
+		byte[] respBytes = readBytes();
+		String response = new String(respBytes);
+		return response;
+	}
+	
+	public String sendAndReceiveLine(String host, int port, String data) throws Exception{
+		connect(host, port);
+		sendLine(data, charset);
+		String response = readLine();
+		return response;
+	}
+	
+	public Object sendAndReceiveObject(String host, int port, Object data) throws Exception{
+		connect(host, port);
+		sendObject(data);
+		Object response = readObject();
+		return response;
+	}
+
+	public int readByte() throws IOException {
+		throw new UnsupportedOperationException("Not supported yet.");
+	}
+	
+	public void sendByte(int data) throws IOException {
+		throw new UnsupportedOperationException("Not supported yet.");
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/ClientInfo.java b/quickserver/src/main/org/quickserver/net/client/ClientInfo.java
new file mode 100644
index 0000000..0dc6418
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/ClientInfo.java
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.net.InetAddress;
+import java.util.Map;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class ClientInfo {
+	private InetAddress inetAddress;
+	private int port;
+	
+	private Object clientKey;
+	private String hostName;
+	
+	private Map sessionInfoGot;
+	private Map sessionInfoToSet;
+
+	public InetAddress getInetAddress() {
+		return inetAddress;
+	}
+
+	public void setInetAddress(InetAddress inetAddress) {
+		this.inetAddress = inetAddress;
+	}
+
+	public int getPort() {
+		return port;
+	}
+
+	public void setPort(int port) {
+		this.port = port;
+	}
+
+	public Map getSessionInfoGot() {
+		return sessionInfoGot;
+	}
+
+	public void setSessionInfoGot(Map sessionInfoGot) {
+		this.sessionInfoGot = sessionInfoGot;
+	}
+
+	public Map getSessionInfoToSet() {
+		return sessionInfoToSet;
+	}
+
+	public void setSessionInfoToSet(Map sessionInfoToSet) {
+		this.sessionInfoToSet = sessionInfoToSet;
+	}
+
+	public Object getClientKey() {
+		return clientKey;
+	}
+
+	public void setClientKey(Object clientKey) {
+		this.clientKey = clientKey;
+	}
+
+	public String getHostName() {
+		return hostName;
+	}
+
+	public void setHostName(String hostName) {
+		this.hostName = hostName;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/ClientService.java b/quickserver/src/main/org/quickserver/net/client/ClientService.java
new file mode 100644
index 0000000..4cf7f78
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/ClientService.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.client;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * Interface that represents client socket services.
+ * @author Akshathkumar Shetty
+ * @since 1.4.7
+ */
+public interface ClientService  {
+	//modes
+	public static final int BLOCKING = 1;
+	public static final int NON_BLOCKING = 2;
+
+	/** 
+	 * Returns the client mode.
+	 */
+	public int getMode();
+
+	/** Connects this socket to the server. */
+	public void connect(String host, int port) throws Exception;
+	/** Returns the connection state of the socket. */
+	public boolean isConnected();
+	/** Closes this socket.*/
+	public void close() throws IOException;
+
+	
+	/** Send binary data */
+	public void sendByte(int data) throws IOException;
+	/** Send binary data */
+	public void sendBytes(byte[] data) throws IOException;
+	/** Send bytes (String) */
+	public void sendBytes(String data, String charset) throws IOException;
+	/** Send String appended with \r\n */
+	public void sendLine(String data, String charset) throws IOException;
+	/** Send object */
+	public void sendObject(Object data) throws IOException;
+
+	/** Read next byte */
+	public int readByte() throws IOException;
+	/** Read binary data */
+	public byte[] readBytes() throws IOException;
+	/** Read bytes (String) */
+	public String readBytes(String charset) throws IOException;
+	/** Read String appended with \r\n */
+	public String readLine() throws IOException;
+	/** Read String appended */
+	public Object readObject() throws IOException, ClassNotFoundException;
+
+	/** Returns the Socket class that is used to communicate .*/
+	public Socket getSocket();
+
+}
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/net/client/DummyTrustManager.java b/quickserver/src/main/org/quickserver/net/client/DummyTrustManager.java
new file mode 100644
index 0000000..fb9d915
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/DummyTrustManager.java
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.security.KeyStore;
+import javax.net.ssl.*;
+import java.security.cert.*;
+
+/**
+ *
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class DummyTrustManager implements X509TrustManager {
+
+	private static DummyTrustManager instance;
+
+	static {
+		try {
+			instance = new DummyTrustManager();
+		} catch (Throwable e) {
+		}
+	}
+	private X509TrustManager sunJSSEX509TrustManager;
+
+	public static DummyTrustManager getInstance() {
+		return instance;
+	}
+
+	public DummyTrustManager() throws Exception {
+		TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+
+		KeyStore ks = null;
+		tmf.init((KeyStore) null);
+
+		TrustManager tms[] = tmf.getTrustManagers();
+
+		/*
+		 * Iterate over the returned trustmanagers, look
+		 * for an instance of X509TrustManager.  If found,
+		 * use that as our "default" trust manager.
+		 */
+		for (int i = 0; i < tms.length; i++) {
+			if (tms[i] instanceof X509TrustManager) {
+				sunJSSEX509TrustManager = (X509TrustManager) tms[i];
+				break;
+			}
+		}
+		if (sunJSSEX509TrustManager == null) {
+			throw new Exception("Couldn't initialize");
+		}
+	}
+
+	/*
+	 * The default X509TrustManager returned by SunX509.  We'll delegate
+	 * decisions to it, and fall back to the logic in this class if the
+	 * default X509TrustManager doesn't trust it.
+	 */
+
+	/*
+	 * Delegate to the default trust manager.
+	 */
+	public void checkClientTrusted(X509Certificate[] chain, String authType)
+			throws CertificateException {
+		try {
+			sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
+		} catch (CertificateException excep) {
+			// do any special handling here, or rethrow exception.
+			throw excep;
+		}
+	}
+
+	/*
+	 * Delegate to the default trust manager.
+	 */
+	public void checkServerTrusted(X509Certificate[] chain, String authType)
+			throws CertificateException {
+		try {
+			sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
+		} catch (CertificateException excep) {
+			/*
+			 * Possibly pop up a dialog box asking whether to trust the
+			 * cert chain.
+			 */
+		}
+	}
+
+	/*
+	 * Merely pass this through.
+	 */
+	public X509Certificate[] getAcceptedIssuers() {
+		// return sunJSSEX509TrustManager.getAcceptedIssuers();
+		if (sunJSSEX509TrustManager == null) {
+			return null;
+		}
+
+		return sunJSSEX509TrustManager.getAcceptedIssuers();
+
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/Host.java b/quickserver/src/main/org/quickserver/net/client/Host.java
new file mode 100644
index 0000000..8527cc1
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/Host.java
@@ -0,0 +1,173 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Date;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class Host {
+	public static final char UNKNOWN = 'U';
+	public static final char ACTIVE = 'A';
+	public static final char DOWN = 'D';
+	public static final char ERROR = 'E';
+	public static final char MAINTENANCE = 'M';
+	
+	private InetAddress inetAddress;
+	private char status = Host.UNKNOWN;
+	private int timeout = 10000;//10sec	
+	private Date lastCheckedOn;
+	private Date nextCheckOn;
+	private String name;
+	
+	private Date lastActiveTime;
+	
+	public Host() {		
+	}
+	
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		if(getName()!=null)sb.append(getName());
+		sb.append("[");
+		sb.append("Host:");
+		sb.append(getInetAddress());
+		sb.append("; Status:");
+		sb.append(getStatus());
+		sb.append("]");
+		return sb.toString();
+	}
+	
+	public Host(String ip) throws UnknownHostException {
+		setInetAddress(ip);
+	}
+	
+	public Host(InetAddress inetAddress) {
+		setInetAddress(inetAddress);
+	}
+
+	public InetAddress getInetAddress() {
+		return inetAddress;
+	}
+	
+	public void setInetAddress(String ip) throws UnknownHostException  {
+		this.inetAddress = InetAddress.getByName(ip);
+	}
+
+	public void setInetAddress(InetAddress inetAddress) {
+		this.inetAddress = inetAddress;
+	}
+
+	public char getStatus() {
+		return status;
+	}
+
+	public void setStatus(char status) {		
+		if(status==Host.ACTIVE && this.status != status) {
+			lastActiveTime = new Date();
+		}
+		this.status = status;
+	}
+
+	public Date getLastCheckedOn() {
+		return lastCheckedOn;
+	}
+
+	public void setLastCheckedOn(Date lastCheckedOn) {
+		this.lastCheckedOn = lastCheckedOn;
+	}
+
+	public Date getNextCheckOn() {
+		return nextCheckOn;
+	}
+
+	public void setNextCheckOn(Date nextCheckOn) {
+		this.nextCheckOn = nextCheckOn;
+	}
+
+	public int getTimeout() {
+		return timeout;
+	}
+
+	/**
+	 * 
+	 * @param timeout in mili seconds
+	 */
+	public void setTimeout(int timeout) {
+		this.timeout = timeout;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the lastActiveTime
+	 */
+	public Date getLastActiveTime() {
+		return lastActiveTime;
+	}
+
+	/**
+	 * @param lastActiveTime the lastActiveTime to set
+	 */
+	public void setLastActiveTime(Date lastActiveTime) {
+		this.lastActiveTime = lastActiveTime;
+	}
+	
+	private static final int SECOND = 1000;
+	private static final int MINUTE = 60 * SECOND;
+	private static final int HOUR = 60 * MINUTE;
+	private static final int DAY = 24 * HOUR;
+	public String getUptime() {
+		if(getStatus()!=Host.ACTIVE) {
+			return "NA";
+		}
+		
+		Date lst = getLastActiveTime();
+		StringBuilder sb = new StringBuilder();
+		
+		if(lst==null) {
+			sb.append("N/A");
+		} else {
+			long ms = System.currentTimeMillis() - lst.getTime();
+			if (ms > DAY) {
+				sb.append(ms / DAY).append("d ");
+				ms %= DAY;
+			}
+			if (ms > HOUR) {
+				sb.append(ms / HOUR).append("h ");
+				ms %= HOUR;
+			}
+			if (ms > MINUTE) {
+				sb.append(ms / MINUTE).append("m ");
+				ms %= MINUTE;
+			}
+			if (ms > SECOND) {
+				sb.append(ms / SECOND).append("s");
+				ms %= SECOND;
+			}
+			//sb.append(ms).append("ms");
+		}
+		
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/HostList.java b/quickserver/src/main/org/quickserver/net/client/HostList.java
new file mode 100644
index 0000000..e3f220e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/HostList.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class HostList {
+	//private static final Logger logger = Logger.getLogger(HostList.class.getName());
+	
+	private String name;
+	private List<Host> fullList;
+	private volatile List<Host> activeList;
+	private Map<String,Host> nameMap = new ConcurrentHashMap<String,Host>();
+	
+	public HostList(String name) {
+		setName(name);
+		setFullList(new ArrayList<Host>());
+		setActiveList(new ArrayList<Host>());
+	}
+	
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		
+		sb.append("HostList {");
+		sb.append("activeList [").append(activeList).append("]");
+		sb.append("nameMap [").append(nameMap).append("]");
+		sb.append("fullList [").append(fullList).append("]");
+		sb.append("}");
+		
+		return sb.toString();
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public List<Host> getFullList() {
+		return fullList;
+	}
+
+	public void setFullList(List<Host> fullList) {
+		this.fullList = fullList;
+	}
+
+	public List<Host> getActiveList() {
+		return activeList;
+	}
+
+	public void setActiveList(List<Host> activeList) {
+		this.activeList = activeList;
+	}
+	
+	public void add(Host host) {
+		getFullList().add(host);
+		if(host.getName()!=null) nameMap.put(host.getName(), host);
+	}
+	public void addDefault(Host host) {
+		getFullList().add(0, host);
+		if(host.getName()!=null) nameMap.put(host.getName(), host);
+	}
+	public void remove(Host host) {
+		getFullList().remove(host);
+		if(host.getName()!=null) nameMap.remove(host.getName());
+	}
+	
+	public Host getHostByName(String name) {
+		return nameMap.get(name);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/HttpHost.java b/quickserver/src/main/org/quickserver/net/client/HttpHost.java
new file mode 100644
index 0000000..0710c0a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/HttpHost.java
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class HttpHost extends SocketBasedHost {
+	private String uri = "/";
+	private URL url;
+	private List<String> httpStatusCodeList;
+	
+	public HttpHost() {}
+	
+	public HttpHost(String url) throws Exception {
+		this(new URL(url));
+	}
+	
+	public void setUrl(URL url) throws UnknownHostException {
+		int port = url.getPort();
+		this.url = url;
+		
+		if("https".equals(url.getProtocol())) {
+			setSecure(true);
+		}
+		setUri(url.getPath());
+		if(url.getQuery()!=null) {
+			setUri(getUri()+"?"+url.getQuery());
+		}
+		
+		if(port==-1) {
+			if(isSecure()) {
+				port = 443;
+			} else {
+				port = 80;
+			}
+		}
+		
+		setInetSocketAddress(url.getHost(), port);
+	}
+	
+	public HttpHost(URL url) throws UnknownHostException {		
+		setUrl(url);
+	}
+	
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		if(getName()!=null)sb.append(getName());
+		sb.append("[");
+		if(isSecure()) {
+			sb.append("https://");
+		} else {
+			sb.append("http://");
+		}
+		sb.append(getInetSocketAddress());
+		sb.append(getUri());
+		sb.append("; Status:");
+		sb.append(getStatus());
+		sb.append("]");
+		return sb.toString();
+	}
+
+	public String getUri() {
+		return uri;
+	}
+
+	public void setUri(String uri) {		
+		this.uri = uri;
+	}
+
+	public String getHttpStatusCode() {
+		if(httpStatusCodeList==null) {
+			return "200";
+		} else if(httpStatusCodeList.size()==1) {
+			return httpStatusCodeList.get(0);
+		} else {
+			return httpStatusCodeList.toString();
+		}
+	}
+
+	public void setHttpStatusCode(String httpStatusCode) {
+		if(httpStatusCode!=null) {
+			if(httpStatusCode.indexOf(",")==-1) {
+				addHttpStatusCode(httpStatusCode.trim());
+			} else {
+				String array[] = httpStatusCode.split(",");
+				for(int i=0;i<array.length;i++) {
+					if(array[i].length()!=0) {
+						addHttpStatusCode(array[i].trim());
+					}
+				}
+			}
+		}
+	}
+	
+	public boolean isValidHttpStatusCode(String sc) {
+		if(httpStatusCodeList != null) {
+			return httpStatusCodeList.contains(sc);
+		} else {
+			return "200".equals(sc);//not set.. default
+		}
+	}
+	
+	public void addHttpStatusCode(String httpStatusCode) {
+		if(httpStatusCodeList==null) {
+			httpStatusCodeList = new ArrayList<String>();
+		}
+		httpStatusCodeList.add(httpStatusCode);
+	}
+	
+
+	public URL getUrl() {
+		return url;
+	}	
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/SocketBasedHost.java b/quickserver/src/main/org/quickserver/net/client/SocketBasedHost.java
new file mode 100644
index 0000000..aabb3b7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/SocketBasedHost.java
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client;
+
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class SocketBasedHost extends Host {
+	private InetSocketAddress inetSocketAddress;
+	private String textToExpect;
+	private boolean secure;
+	
+	private String requestText;
+	private String responseTextToExpect;
+	
+	
+	public SocketBasedHost() {
+		
+	}
+	
+	public SocketBasedHost(String host, int port) throws Exception {
+		setInetSocketAddress(host, port);
+	}
+	
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		if(getName()!=null)sb.append(getName());
+		sb.append("[");
+		sb.append("Host:");
+		sb.append(getInetSocketAddress());
+		sb.append("; Status:");
+		sb.append(getStatus());
+		sb.append("]");
+		return sb.toString();
+	}
+
+	public InetSocketAddress getInetSocketAddress() {
+		return inetSocketAddress;
+	}
+	
+	public void setInetSocketAddress(String host, int port) throws UnknownHostException {
+		setInetSocketAddress(InetSocketAddress.createUnresolved(host, port));		
+	}
+
+	public void setInetSocketAddress(InetSocketAddress inetSocketAddress) throws UnknownHostException {
+		this.inetSocketAddress = inetSocketAddress;
+		setInetAddress(inetSocketAddress.getHostName());
+	}
+
+	public String getTextToExpect() {
+		return textToExpect;
+	}
+
+	public void setTextToExpect(String textToExpect) {
+		this.textToExpect = textToExpect;
+	}
+
+	public boolean isSecure() {
+		return secure;
+	}
+
+	public void setSecure(boolean secure) {
+		this.secure = secure;
+	}
+
+	public String getRequestText() {
+		return requestText;
+	}
+
+	public void setRequestText(String requestText) {
+		this.requestText = requestText;
+	}
+
+	public String getResponseTextToExpect() {
+		return responseTextToExpect;
+	}
+
+	public void setResponseTextToExpect(String responseTextToExpect) {
+		this.responseTextToExpect = responseTextToExpect;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/LoadDistributor.java b/quickserver/src/main/org/quickserver/net/client/loaddistribution/LoadDistributor.java
new file mode 100644
index 0000000..a83bd0e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/LoadDistributor.java
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.loaddistribution;
+
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public class LoadDistributor {
+	private HostList hostList;
+	private LoadPattern loadPattern;
+	
+	public LoadDistributor(HostList hostList) {
+		setHostList(hostList);
+	}
+	
+	public Host getHost(ClientInfo clientInfo) {
+		return getLoadPattern().getHost(clientInfo);
+	}
+
+	public HostList getHostList() {
+		return hostList;
+	}
+
+	public void setHostList(HostList hostList) {
+		this.hostList = hostList;
+	}
+
+	public LoadPattern getLoadPattern() {
+		return loadPattern;
+	}
+
+	public void setLoadPattern(LoadPattern loadPattern) {
+		this.loadPattern = loadPattern;
+		this.loadPattern.setHostList(hostList);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/LoadPattern.java b/quickserver/src/main/org/quickserver/net/client/loaddistribution/LoadPattern.java
new file mode 100644
index 0000000..e1cc89c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/LoadPattern.java
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.loaddistribution;
+
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public interface LoadPattern {
+	public Host getHost(ClientInfo clientInfo);
+	public void setHostList(HostList hostList);
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/FirstActiveLoadPattern.java b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/FirstActiveLoadPattern.java
new file mode 100644
index 0000000..809b568
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/FirstActiveLoadPattern.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.loaddistribution.impl;
+
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.loaddistribution.LoadPattern;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public class FirstActiveLoadPattern implements LoadPattern {
+	private static final Logger logger = Logger.getLogger(FirstActiveLoadPattern.class.getName());
+	
+	private HostList hostList;
+	
+	public FirstActiveLoadPattern() {
+
+	}
+	
+	public HostList getHostList() {
+		return hostList;
+	}
+	public void setHostList(HostList hostList) {
+		this.hostList = hostList;
+	}
+
+	public Host getHost(ClientInfo clientInfo) {
+		List activeList = getHostList().getActiveList();
+		
+		if(activeList==null || activeList.isEmpty()) {
+			logger.warning("No active list available to service requests");
+			return null;
+		}
+		
+		if(clientInfo!=null) {
+			if(clientInfo.getHostName()!=null) {
+				Host host = hostList.getHostByName(clientInfo.getHostName());
+				if(host==null) {
+					logger.log(Level.WARNING, "Host will name [{0}] not in hostlist!{1}", 
+						new Object[]{clientInfo.getHostName(), hostList});
+				} else {
+					if(host.getStatus()==Host.ACTIVE) {
+						return host;
+					}
+				}				
+			}
+		}
+		
+		//always return firstActive from List
+		return (Host) activeList.get(0);
+	}
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/HashedLoadPattern.java b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/HashedLoadPattern.java
new file mode 100644
index 0000000..0d13617
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/HashedLoadPattern.java
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.loaddistribution.impl;
+
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.loaddistribution.LoadPattern;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public class HashedLoadPattern implements LoadPattern {
+	private static final Logger logger = Logger.getLogger(HashedLoadPattern.class.getName());
+	
+	private HostList hostList;	
+	
+	public HashedLoadPattern() {
+		
+	}
+	
+	public HostList getHostList() {
+		return hostList;
+	}
+	public void setHostList(HostList hostList) {
+		this.hostList = hostList;
+	}
+
+	public Host getHost(ClientInfo clientInfo) {
+		List activeList = getHostList().getActiveList();
+		
+		if(activeList==null || activeList.isEmpty()) {
+			logger.warning("No active list available to service requests");
+			return null;
+		}
+		int size = activeList.size();
+                
+                int hash =  -1;
+		
+		if(clientInfo!=null) {
+			if(clientInfo.getHostName()!=null) {
+                            Host host = hostList.getHostByName(clientInfo.getHostName());
+                            if(host==null) {
+                                logger.log(Level.WARNING, "Host will name [{0}] not in hostlist!{1}", 
+                                        new Object[]{clientInfo.getHostName(), hostList});
+                                //pass through
+                            } else {
+                                if(host.getStatus()==Host.ACTIVE) {
+                                    return host;
+                                } else {
+                                    //pass through
+                                }
+                            }		
+			} else if(clientInfo.getClientKey()==null) {
+                            throw new NullPointerException("ClientKey was null!");
+			} else {
+                            //pass though
+                        }
+		} else {
+                    throw new NullPointerException("clientInfo was null!");
+		}
+                
+                if(clientInfo.getClientKey()!=null) {
+                    hash = clientInfo.getClientKey().hashCode();
+                } else {
+                    hash = clientInfo.getHostName().hashCode();
+                }
+                
+		int mod = hash % size;
+		if(mod<0) mod = mod*-1;
+		
+		return (Host) activeList.get(mod);
+	}
+	
+}
+
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/RandomLoadPattern.java b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/RandomLoadPattern.java
new file mode 100644
index 0000000..60579f6
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/RandomLoadPattern.java
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.loaddistribution.impl;
+
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.loaddistribution.LoadPattern;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public class RandomLoadPattern implements LoadPattern {
+	private static final Logger logger = Logger.getLogger(RandomLoadPattern.class.getName());
+	
+	private HostList hostList;
+	private Random random;
+	
+	public RandomLoadPattern() {
+		random = new Random();
+	}
+	
+	public HostList getHostList() {
+		return hostList;
+	}
+	public void setHostList(HostList hostList) {
+		this.hostList = hostList;
+	}
+
+	public Host getHost(ClientInfo clientInfo) {
+		List activeList = getHostList().getActiveList();
+		
+		if(activeList==null || activeList.isEmpty()) {
+			logger.warning("No active list available to service requests");
+			return null;
+		}
+		
+		if(clientInfo!=null) {
+			if(clientInfo.getHostName()!=null) {
+				Host host = hostList.getHostByName(clientInfo.getHostName());
+				if(host==null) {
+					logger.log(Level.WARNING, "Host will name [{0}] not in hostlist!{1}", 
+						new Object[]{clientInfo.getHostName(), hostList});
+				} else {
+					if(host.getStatus()==Host.ACTIVE) {
+						return host;
+					}
+				}
+			}
+		}
+		
+		int size = activeList.size();
+		int pos = random.nextInt(size);
+		return (Host) activeList.get(pos);
+	}
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/RoundRobinLoadPattern.java b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/RoundRobinLoadPattern.java
new file mode 100644
index 0000000..73d5221
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/RoundRobinLoadPattern.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.loaddistribution.impl;
+
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.loaddistribution.LoadPattern;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public class RoundRobinLoadPattern implements LoadPattern {
+	private static final Logger logger = Logger.getLogger(RoundRobinLoadPattern.class.getName());
+	
+	private HostList hostList;
+	private int pos;	
+	
+	private final Object lock = new Object();
+	
+	public RoundRobinLoadPattern() {
+		pos = -1;
+	}
+	
+	public HostList getHostList() {
+		return hostList;
+	}
+	public void setHostList(HostList hostList) {
+		this.hostList = hostList;
+	}
+
+	public Host getHost(ClientInfo clientInfo) {
+		List activeList = getHostList().getActiveList();
+		
+		if(activeList==null || activeList.isEmpty()) {
+			logger.log(Level.WARNING, "No active list available to service requests {0}", activeList);
+			return null;
+		}
+		
+		if(clientInfo!=null) {
+			if(clientInfo.getHostName()!=null) {
+				Host host = hostList.getHostByName(clientInfo.getHostName());
+				if(host==null) {
+					logger.log(Level.WARNING, "Host will name [{0}] not in hostlist!{1}", 
+						new Object[]{clientInfo.getHostName(), hostList});
+				} else {
+					if(host.getStatus()==Host.ACTIVE) {
+						return host;
+					}
+				}				
+			}
+		}
+		
+		int size = activeList.size();
+		
+		int mypos;
+		synchronized(lock) {
+			pos++;
+			if(pos>=size) {
+				pos = 0;
+			}
+			mypos = pos;
+		}
+		return (Host) activeList.get(mypos);
+	}
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/package.html b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/package.html
new file mode 100644
index 0000000..b2c30ff
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/impl/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Load Distributor implementation classes of QuickServer Client. 

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/client/loaddistribution/package.html b/quickserver/src/main/org/quickserver/net/client/loaddistribution/package.html
new file mode 100644
index 0000000..3bffe93
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/loaddistribution/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Load Distributor classes of QuickServer Client.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/HostMonitor.java b/quickserver/src/main/org/quickserver/net/client/monitoring/HostMonitor.java
new file mode 100644
index 0000000..a8ca148
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/HostMonitor.java
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring;
+
+import org.quickserver.net.client.Host;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public interface HostMonitor {
+	public char monitor(Host host);
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/HostMonitoringService.java b/quickserver/src/main/org/quickserver/net/client/monitoring/HostMonitoringService.java
new file mode 100644
index 0000000..5eed9c8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/HostMonitoringService.java
@@ -0,0 +1,311 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring;
+
+import org.quickserver.net.client.HostList;
+import org.quickserver.net.client.Host;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class HostMonitoringService {
+	private static final Logger logger = Logger.getLogger(HostMonitoringService.class.getName());
+	private static long monitorInterval = 1000;
+	
+	private static final List listToMonitor = Collections.synchronizedList(new ArrayList());
+	
+	private HostList hostList;
+	private HostMonitor hostMonitor;
+	private int intervalInSec;
+	private List listnersList;
+	private Date lastCheckedOn;
+	private Date nextCheckOn;
+	
+	public static int getSize() {
+		return listToMonitor.size();
+	}
+	
+	public static void add(HostList hostList, HostMonitor hostMonitor, 
+			int intervalInSec, List listnersList) {
+		HostMonitoringService hms = new HostMonitoringService();
+		hms.setHostList(hostList);
+		hms.setHostMonitor(hostMonitor);
+		hms.setIntervalInSec(intervalInSec);
+		hms.setListnersList(listnersList);
+		
+		add(hms);
+	}
+	
+	public static void add(HostMonitoringService hms) {
+		if(listToMonitor.contains(hms)) {
+			listToMonitor.remove(hms);
+		}
+		listToMonitor.add(hms);
+	}
+	
+	public static boolean remove(HostMonitoringService hms) {
+		return listToMonitor.remove(hms);
+	}	
+	
+	public static void clear() {
+		listToMonitor.clear();
+	}
+	
+	public static void monitor() {
+		monitor(false, null, null);
+	}
+	
+	public static void monitor(boolean forceCheck) {
+		monitor(forceCheck, null, null);
+	}
+	
+	public static void monitor(boolean forceCheck, HostMonitoringService passedHms) {
+		monitor(forceCheck, null, passedHms);
+	}
+	
+	public static void monitor(String hostName) {
+		monitor(false, hostName);
+	}
+	
+	public static void monitor(boolean forceCheck, String hostName) {
+		monitor(forceCheck, hostName, null);
+	}
+	
+	public static void monitor(boolean forceCheck, String hostName, 
+			HostMonitoringService passedHms) {
+		HostMonitoringService hms = null;
+		List fullList = null;
+		Host host = null;
+		char newStatus = 'U';
+		try {
+			List list = new ArrayList(listToMonitor);
+			Iterator iterator = list.iterator();							
+			
+			while(iterator.hasNext()) {
+				hms = (HostMonitoringService) iterator.next();
+				
+				if(passedHms!=null) {
+					if(passedHms!=hms) {//we r only intrested in what is passed
+						continue;
+					}
+				}
+				
+				Date now = new Date();			
+				if(hms.getNextCheckOn()!=null && hms.getNextCheckOn().after(now)) {
+					if(forceCheck==false) continue;
+				}
+				
+				fullList = hms.getHostList().getFullList();
+				List<Host> activeList = new ArrayList<Host>();
+				
+				Iterator hostIterator = fullList.iterator();
+				
+				if(hostName==null) {
+					hms.setLastCheckedOn(now);
+					long nextTime = hms.getLastCheckedOn().getTime() + 
+							(hms.getIntervalInSec()/2)*1000;
+					hms.setNextCheckOn(new Date(nextTime));
+				}
+							
+				while(hostIterator.hasNext()) {
+					host = (Host) hostIterator.next();	
+					
+					if(hostName!=null) {
+						if(hostName.equals(host.getName())==false) {							
+							logger.log(Level.INFO, "hostName[{0}] does not match with [{1}]", 
+								new Object[]{hostName, host.getName()});
+							if(host.getStatus()==Host.ACTIVE) {
+								activeList.add(host);
+							}
+							continue;
+						} else {
+							logger.log(Level.INFO, "hostName[{0}] is a match with [{1}]", 
+								new Object[]{hostName, host.getName()});
+						}
+					}
+					
+					if(forceCheck==true || host.getNextCheckOn()==null || 
+							host.getNextCheckOn().before(now)) {
+						char oldStatus = host.getStatus();
+						if(host.getStatus()!=Host.MAINTENANCE) {
+							try {
+								newStatus = hms.getHostMonitor().monitor(host);
+							} catch (Exception er) {
+								logger.log(Level.WARNING, "Error in HostMonitor1: "+er, er);
+								er.printStackTrace();
+								newStatus = Host.ERROR;
+							}							
+						} else {
+							newStatus = host.getStatus();
+						}
+						host.setStatus(newStatus);
+						
+						if(newStatus==Host.ACTIVE) {
+							activeList.add(host);
+						} else if(host.getStatus()!=Host.MAINTENANCE) {
+							//try again..
+							try {
+								newStatus = hms.getHostMonitor().monitor(host);
+							} catch (Exception er) {
+								logger.log(Level.WARNING, "Error in HostMonitor2: "+er, er);
+								er.printStackTrace();
+								newStatus = Host.ERROR;
+							}
+							if(newStatus==Host.ACTIVE) {
+								activeList.add(host);
+							}
+							host.setStatus(newStatus);
+						}
+						
+						if(newStatus != oldStatus) {
+							List myListnersList = hms.getListnersList();
+							if(myListnersList!=null) {
+								Iterator listnersIterator = myListnersList.iterator();
+								HostStateListener listener = null;
+								while(listnersIterator.hasNext()) {
+									listener = (HostStateListener) listnersIterator.next();
+									if(listener!=null) {
+										listener.stateChanged(host, oldStatus, newStatus);
+									} else {
+										logger.warning("listener was null!");
+									}
+								}
+							} else {
+								logger.log(Level.WARNING, 
+									"No listners set {0}; old status: {1};new status:{2}", 
+									new Object[]{host, oldStatus, newStatus});
+							}
+						}
+						if(host.getLastCheckedOn()!=null) {
+							long newTime = host.getLastCheckedOn().getTime() +
+									hms.getIntervalInSec()*1000;
+							host.setNextCheckOn(new Date(newTime));
+						} else if(host.getStatus()!=Host.MAINTENANCE) {
+							logger.log(Level.WARNING, "host.getLastCheckedOn() was null {0}", host);
+						}
+						
+					} else {
+						//last monitored status is good for use
+						if(host.getStatus()==Host.ACTIVE) {
+							activeList.add(host);
+						}
+					}
+					
+					
+					now = new Date();//update
+				}//host list		
+				hms.getHostList().setActiveList(Collections.synchronizedList(activeList));//update back
+			}//hms list
+		} catch (Throwable e) {
+			logger.log(Level.SEVERE, "Error: "+e, e);
+		}
+	}
+	
+	static {
+		Thread t = new Thread() {
+			public void run() {
+				logger.fine("Started..");
+				while(true) {
+					try {
+						HostMonitoringService.monitor();
+					} catch(Throwable e) {
+						logger.log(Level.SEVERE, "Bug in monitor method! "+e, e);
+					}
+					try {
+						Thread.sleep(monitorInterval);
+					} catch (InterruptedException ex) {
+						logger.log(Level.SEVERE, "Interrupted.. will return : "+ ex);
+						break;
+					}
+				}
+			}
+		};
+		t.setName("HostMonitoringService-Thread");
+		t.setDaemon(true);
+		t.start();
+		
+	}
+
+	public HostList getHostList() {
+		return hostList;
+	}
+
+	public void setHostList(HostList hostList) {
+		this.hostList = hostList;
+	}
+
+	public HostMonitor getHostMonitor() {
+		return hostMonitor;
+	}
+
+	public void setHostMonitor(HostMonitor hostMonitor) {
+		this.hostMonitor = hostMonitor;
+	}
+
+	public int getIntervalInSec() {
+		return intervalInSec;
+	}
+
+	public void setIntervalInSec(int intervalInSec) {
+		this.intervalInSec = intervalInSec;
+	}
+
+	public List getListnersList() {
+		return listnersList;
+	}
+
+	public void setListnersList(List listnersList) {
+		this.listnersList = listnersList;
+	}
+	
+	public void addHostStateListner(HostStateListener listener) {
+		if(listnersList==null) {
+			listnersList = new ArrayList();
+		}
+		listnersList.add(listener);
+	}
+	
+	public void removeHostStateListner(HostStateListener listener) {
+		if(listnersList==null) {
+			listnersList = new ArrayList();
+		} else {
+			listnersList.remove(listener);
+		}
+	}
+
+	public Date getLastCheckedOn() {
+		return lastCheckedOn;
+	}
+
+	public void setLastCheckedOn(Date lastCheckedOn) {
+		this.lastCheckedOn = lastCheckedOn;
+	}
+
+	public Date getNextCheckOn() {
+		return nextCheckOn;
+	}
+
+	public void setNextCheckOn(Date nextCheckOn) {
+		this.nextCheckOn = nextCheckOn;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/HostStateListener.java b/quickserver/src/main/org/quickserver/net/client/monitoring/HostStateListener.java
new file mode 100644
index 0000000..6d6b1ea
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/HostStateListener.java
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring;
+
+import org.quickserver.net.client.Host;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public interface HostStateListener {
+	public void stateChanged(Host host, char oldStatus, char newStatus);
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/impl/HttpMonitor.java b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/HttpMonitor.java
new file mode 100644
index 0000000..2f2af01
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/HttpMonitor.java
@@ -0,0 +1,194 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring.impl;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.SecureRandom;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import org.quickserver.net.client.BlockingClient;
+import org.quickserver.net.client.DummyTrustManager;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.monitoring.HostMonitor;
+import org.quickserver.net.client.HttpHost;
+
+/**
+ *
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class HttpMonitor implements HostMonitor {
+	private static final Logger logger = Logger.getLogger(HttpMonitor.class.getName());
+        
+        private static String providerForSSLContext;
+
+    /**
+     * @return the providerForSSLContext
+     */
+    public static String getProviderForSSLContext() {
+        return providerForSSLContext;
+    }
+
+    /**
+     * @param aProviderForSSLContext the providerForSSLContext to set
+     */
+    public static void setProviderForSSLContext(String aProviderForSSLContext) {
+        providerForSSLContext = aProviderForSSLContext;
+    }
+	
+	private SSLSocketFactory sslSocketFactory;
+
+	private TrustManager[] trustManager;
+	private SSLContext sslContext;
+
+	public char monitor(Host host) {
+		HttpHost httpHost = (HttpHost) host;
+		HttpURLConnection http = null;
+		BufferedInputStream bis = null;
+		URL url = null;
+		try {
+			String urlString = null;
+
+			if (httpHost.isSecure()) {
+				urlString = "https://";
+			} else {
+				urlString = "http://";
+			}
+			urlString = urlString + httpHost.getInetAddress().getHostName()
+					+ ":" + httpHost.getInetSocketAddress().getPort() + httpHost.getUri();
+			
+			url = new URL(urlString);			
+			
+			http = (HttpURLConnection) url.openConnection();
+			if (httpHost.isSecure()) {
+				HttpsURLConnection https = (HttpsURLConnection) http;
+
+				makeSSLSocketFactory();
+
+				https.setSSLSocketFactory(sslSocketFactory);
+				https.setHostnameVerifier(vf);
+			}
+			http.setRequestMethod("GET");
+			http.setDoOutput(true);
+			http.setReadTimeout(httpHost.getTimeout());
+			http.setInstanceFollowRedirects(false);
+
+			http.connect();
+
+			String httpResponseCode = "" + http.getResponseCode();
+
+			if(httpHost.isValidHttpStatusCode(httpResponseCode)==false) {
+				logger.log(Level.FINE, "StatusCode does not match.. got {0}, expected: {1} for host {2}", 
+					new Object[]{httpResponseCode, httpHost.getHttpStatusCode(), 
+						httpHost.getInetAddress().getHostName()});
+				
+				return Host.DOWN;
+			}
+
+			if (httpHost.getTextToExpect() != null) {		
+				InputStream is = http.getErrorStream();
+				if(is==null) {
+					is = http.getInputStream();
+				}
+				bis = new BufferedInputStream(is);
+
+				byte data[] = BlockingClient.readInputStream(bis);
+				String textGot = null;
+
+				if(data!=null) textGot = new String(data, "utf-8");
+
+				if (textGot.indexOf(httpHost.getTextToExpect()) != -1) {
+					return Host.ACTIVE;
+				} else {
+					logger.log(Level.FINE, "{0} Error: Text [{1}] Not found! Got: {2} for host {3}", 
+						new Object[]{httpHost, httpHost.getTextToExpect(), textGot, 
+							httpHost.getInetAddress().getHostName()});
+					logger.log(Level.FINEST, "Got Data: {0}", textGot);
+					return Host.DOWN;
+				}
+			} else {
+				return Host.ACTIVE;
+			}
+		} catch (IOException e) {			
+			logger.log(Level.FINE, "url {0}", new Object[]{url});
+			logger.log(Level.FINE, httpHost+ " IOError: "+e, e);
+			return Host.DOWN;
+		} catch (Exception e) {
+			logger.log(Level.WARNING, httpHost+" Error: "+e, e);
+			return Host.ERROR;
+		} finally {
+			if(bis!=null) {
+				try {
+					bis.close();
+				} catch (IOException ex) {
+					Logger.getLogger(HttpMonitor.class.getName()).log(Level.SEVERE, null, ex);
+				}
+			}
+			if (http != null) {
+				http.disconnect();
+				
+			}
+			host.setLastCheckedOn(new Date());
+		}
+	}
+
+	public void makeSSLSocketFactory() throws Exception {
+		if (sslContext == null && getSslSocketFactory() == null) {
+                        if(getProviderForSSLContext()!=null) {
+                            sslContext = SSLContext.getInstance("TLS", getProviderForSSLContext());
+                        } else {
+                            sslContext = SSLContext.getInstance("TLS");
+                        }
+			if (trustManager == null) {
+				trustManager = new TrustManager[]{DummyTrustManager.getInstance()};
+			}
+
+			sslContext.init(new KeyManager[0], trustManager, new SecureRandom());
+		}
+
+		if (getSslSocketFactory() == null) {
+			sslSocketFactory = sslContext.getSocketFactory();
+		}
+	}
+	static HostnameVerifier vf = new HostnameVerifier() {
+
+		public boolean verify(String hostName, SSLSession session) {
+			//logger.warning("WARNING: hostname may not match the certificate host name :" + hostName);
+			return true;
+		}
+	};
+	
+	
+
+	
+	public SSLSocketFactory getSslSocketFactory() {
+		return sslSocketFactory;
+	}
+
+	public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
+		this.sslSocketFactory = sslSocketFactory;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/impl/PingMonitor.java b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/PingMonitor.java
new file mode 100644
index 0000000..bd435be
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/PingMonitor.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring.impl;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.logging.Logger;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.monitoring.HostMonitor;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class PingMonitor implements HostMonitor {
+	private static final Logger logger = Logger.getLogger(PingMonitor.class.getName());
+
+	public char monitor(Host host) {
+		try {
+			boolean flag = host.getInetAddress().isReachable(host.getTimeout());
+			if(flag) {
+				return Host.ACTIVE;
+			} else {
+				return Host.DOWN;
+			}
+		} catch (IOException e) {
+			logger.fine(host+" Error: "+e);
+			return Host.DOWN;
+		} catch (Exception e) {
+			logger.warning(host+" Error: "+e);
+			e.printStackTrace();
+			return Host.ERROR;
+		} finally {
+			host.setLastCheckedOn(new Date());
+		}
+	}
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/impl/SocketMonitor.java b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/SocketMonitor.java
new file mode 100644
index 0000000..a6a41be
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/SocketMonitor.java
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring.impl;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.net.ssl.SSLSocketFactory;
+import org.quickserver.net.client.BlockingClient;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.monitoring.HostMonitor;
+import org.quickserver.net.client.SocketBasedHost;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class SocketMonitor implements HostMonitor {
+	private static final Logger logger = Logger.getLogger(SocketMonitor.class.getName());
+	
+	private boolean useDummyTrustManager;
+	private SSLSocketFactory sslSocketFactory;
+	private int closeDelayMiliSec = 0;
+	
+
+	public char monitor(Host host) {		
+		SocketBasedHost socketBasedHost = (SocketBasedHost) host;
+		BlockingClient client = new BlockingClient();
+		try {		
+			client.setSecure(socketBasedHost.isSecure());
+			client.setUseDummyTrustManager(isUseDummyTrustManager());
+			
+			if(getSslSocketFactory()!=null) {
+				client.setSslSocketFactory(getSslSocketFactory());
+			}
+			
+			client.connect(socketBasedHost.getInetAddress().getHostAddress(), 
+					socketBasedHost.getInetSocketAddress().getPort());
+			
+			if(socketBasedHost.getTextToExpect()!=null) {
+				int minLenToRead = socketBasedHost.getTextToExpect().length();
+				StringBuilder sb = new StringBuilder();
+				String temp = null;
+				while(true) {
+					temp = client.readBytes(null);
+					if(temp==null) break;
+					
+					sb.append(temp);
+					if(sb.length()>=minLenToRead) {
+						break;
+					}
+				}
+				
+				String textGot = sb.toString();
+				if(textGot.indexOf(socketBasedHost.getTextToExpect())!=-1) {
+					return Host.ACTIVE;
+				} else {
+					logger.log(Level.WARNING, "{0} Error: Text [{1}]Not found! Got: {2}", 
+						new Object[]{socketBasedHost, socketBasedHost.getTextToExpect(), textGot});
+					return Host.DOWN;
+				}
+			} 
+			
+			if(socketBasedHost.getRequestText()!=null) {
+				client.sendBytes(socketBasedHost.getRequestText(), null);
+				if(socketBasedHost.getResponseTextToExpect()!=null) {
+					int minLenToRead = socketBasedHost.getResponseTextToExpect().length();
+
+					StringBuilder sb = new StringBuilder();
+					String temp = null;
+					while(true) {
+						temp = client.readBytes(null);
+						if(temp==null) break;
+
+						sb.append(temp);
+						if(sb.length()>=minLenToRead) {
+							break;
+						}
+					}
+
+					String textGot = sb.toString();
+
+					if(textGot!=null && textGot.indexOf(socketBasedHost.getResponseTextToExpect())!=-1) {
+						return Host.ACTIVE;
+					} else {
+						logger.log(Level.WARNING, "{0} Error: Text [{1}]Not found! Got: {2}", 
+							new Object[]{socketBasedHost, socketBasedHost.getResponseTextToExpect(), textGot});
+						return Host.DOWN;
+					}
+				} else {
+					logger.log(Level.WARNING, "ResponseTextToExpect was null! for {0}", socketBasedHost);
+				}
+			}
+			
+			if(getCloseDelayMiliSec()>0) {
+				Thread.sleep(getCloseDelayMiliSec());
+			}
+			return Host.ACTIVE;
+			
+		} catch (IOException e) {
+			logger.log(Level.FINE, "{0} IOError: {1}", new Object[]{socketBasedHost, e});
+			return Host.DOWN;
+		} catch (Exception e) {
+			logger.log(Level.WARNING, "{0} Error: {1}", new Object[]{socketBasedHost, e});
+			e.printStackTrace();
+			return Host.ERROR;
+		} finally {
+			if(client!=null) {
+				try {
+					client.close();
+				} catch (IOException ex) {
+					Logger.getLogger(SocketMonitor.class.getName()).log(Level.FINE, "Error", ex);
+				}
+			}
+			host.setLastCheckedOn(new Date());
+		}		
+	}
+	
+	public boolean isUseDummyTrustManager() {
+		return useDummyTrustManager;
+	}
+
+	public void setUseDummyTrustManager(boolean useDummyTrustManager) {
+		this.useDummyTrustManager = useDummyTrustManager;
+	}
+	
+	public SSLSocketFactory getSslSocketFactory() {
+		return sslSocketFactory;
+	}
+
+	public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
+		this.sslSocketFactory = sslSocketFactory;
+	}
+
+	public int getCloseDelayMiliSec() {
+		return closeDelayMiliSec;
+	}
+
+	/**
+	 * May be used to set delay when TextToExpect is null and we want some delay before 
+	 * closing of sockets (to allow SSL handshake to complete).
+	 * 
+	 * @param closeDelayMiliSec 
+	 */
+	public void setCloseDelayMiliSec(int closeDelayMiliSec) {
+		this.closeDelayMiliSec = closeDelayMiliSec;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/impl/UDPMonitor.java b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/UDPMonitor.java
new file mode 100644
index 0000000..0ac9a6b
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/UDPMonitor.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.client.monitoring.impl;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.BlockingUDPClient;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.SocketBasedHost;
+import org.quickserver.net.client.monitoring.HostMonitor;
+
+/**
+ *
+ * @author mukundan
+ */
+public class UDPMonitor implements HostMonitor {
+	private static final Logger logger = Logger.getLogger(UDPMonitor.class.getName());
+
+	public char monitor(Host host) {
+		char result = 'U';
+		BlockingUDPClient udpClient = new BlockingUDPClient();
+		try {
+			SocketBasedHost udpHost = (SocketBasedHost) host;			
+
+			String hostName = udpHost.getInetSocketAddress().getHostName();
+			int port = udpHost.getInetSocketAddress().getPort();
+
+			//TODO - am sending test string as UDP doesn't have any connection
+			//UDP can be monitored only by sending data and checking for response
+			//and not by just making a connection
+
+			String dataToSend = "test";
+			if (null != udpHost.getRequestText() && "".equals(udpHost.getRequestText().trim()) == false) {
+				dataToSend = udpHost.getRequestText();
+			} else {
+				logger.log(Level.SEVERE, "RequestText not configured for UDPHost{0}", hostName);
+			}
+
+			String response = null;
+			if (null != udpHost.getResponseTextToExpect()
+					&& "".equals(udpHost.getResponseTextToExpect().trim()) == false) {
+
+				response = new String(udpClient.sendAndReceiveBinary(hostName, port, dataToSend.getBytes()));
+				if (null != response && response.contains(udpHost.getResponseTextToExpect())) {
+					result = Host.ACTIVE;
+				} else {
+					logger.log(Level.FINE, "{0} Error: Text [{1}]Not found! Got: {2}",
+							new Object[]{udpHost, udpHost.getResponseTextToExpect(), response});
+					result = Host.DOWN;
+				}
+			} else {
+				logger.log(Level.SEVERE, "ResponseTextToExpect not configured for UDPHost{0}",
+						hostName);
+				result = Host.UNKNOWN;
+			}
+		} catch (IOException ioe) {
+			logger.log(Level.SEVERE, "IOException", ioe);
+			result = Host.DOWN;
+		} catch (Throwable ex) {
+			logger.log(Level.SEVERE, "Exception", ex);
+			result = Host.ERROR;
+		} finally {
+			host.setLastCheckedOn(new Date());
+			try {
+				udpClient.close();
+			} catch (IOException ex) {
+				Logger.getLogger(UDPMonitor.class.getName()).log(Level.SEVERE, null, ex);
+			}
+		}
+		return result;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/impl/package.html b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/package.html
new file mode 100644
index 0000000..d07dc3b
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/impl/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Monitoring implementation classes of QuickServer Client.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/client/monitoring/package.html b/quickserver/src/main/org/quickserver/net/client/monitoring/package.html
new file mode 100644
index 0000000..d5fe03b
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/monitoring/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Monitoring classes of QuickServer Client.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/client/package.html b/quickserver/src/main/org/quickserver/net/client/package.html
new file mode 100644
index 0000000..bd2d827
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Main classes of QuickServer Client.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/client/pool/BlockingClientPool.java b/quickserver/src/main/org/quickserver/net/client/pool/BlockingClientPool.java
new file mode 100644
index 0000000..6bec800
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/pool/BlockingClientPool.java
@@ -0,0 +1,846 @@
+package org.quickserver.net.client.pool;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.BlockingClient;
+import org.quickserver.net.client.ClientInfo;
+import org.quickserver.net.client.Host;
+import org.quickserver.net.client.HostList;
+import org.quickserver.net.client.SocketBasedHost;
+import org.quickserver.net.client.loaddistribution.LoadDistributor;
+import org.quickserver.net.client.loaddistribution.impl.RoundRobinLoadPattern;
+import org.quickserver.net.client.monitoring.HostMonitor;
+import org.quickserver.net.client.monitoring.HostMonitoringService;
+import org.quickserver.net.client.monitoring.HostStateListener;
+import org.quickserver.net.client.monitoring.impl.HttpMonitor;
+
+/**
+ * A generic Socket Pool implementation using BlockingClient of QuickServer Client API
+ * 
+ * @author Akshathkumar Shetty
+ */
+public class BlockingClientPool {
+	private static final Logger logger = Logger.getLogger(BlockingClientPool.class.getName());
+	
+	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	
+	private static int maxTimeToLockInSec = 5;
+	
+	private PoolableBlockingClient poolableBlockingClient;
+	private String name;
+	
+	private int minPoolSize;
+	private int maxPoolSize;
+	private int idlePoolSize;
+	
+	private Map <SocketBasedHost,ConcurrentLinkedQueue <PooledBlockingClient>> pool = 
+		new ConcurrentHashMap<SocketBasedHost, ConcurrentLinkedQueue<PooledBlockingClient>>();
+	
+	private Map <SocketBasedHost,ConcurrentLinkedQueue <PooledBlockingClient>> inUsePool = 
+		new ConcurrentHashMap<SocketBasedHost, ConcurrentLinkedQueue<PooledBlockingClient>>();
+	
+	private HostMonitoringService hostMonitoringService = new HostMonitoringService();
+	
+	private Thread noopThread;	
+	private boolean debug = false;
+	private int logPoolStatsTimeInMinute = 0;
+	private Thread logPoolStats;	
+	
+	public boolean isDebug() {
+		return debug;
+	}
+	public void setDebug(boolean aDebug) {
+		debug = aDebug;
+	}
+	
+	public static void test() {
+		HostList hostList = new HostList("myservers");
+		//hostList.add(host);
+		
+		final HostMonitor hm = new HttpMonitor();
+		final LoadDistributor ld = new LoadDistributor(hostList);
+		ld.setLoadPattern(new RoundRobinLoadPattern());
+		
+		PoolableBlockingClient poolableBlockingClient = new PoolableBlockingClient() {
+			public HostMonitor getHostMonitor() {
+				return hm;
+			}
+
+			public LoadDistributor getLoadDistributor() {
+				return ld;
+			}
+
+			public BlockingClient createBlockingClient(SocketBasedHost host) {
+				throw new UnsupportedOperationException("Not supported yet.");
+			}
+
+			public boolean closeBlockingClient(BlockingClient blockingClient) {
+				throw new UnsupportedOperationException("Not supported yet.");
+			}
+
+			public boolean sendNoOp(BlockingClient blockingClient) {
+				throw new UnsupportedOperationException("Not supported yet.");
+			}
+
+			public long getNoOpTimeIntervalMiliSec() {
+				throw new UnsupportedOperationException("Not supported yet.");
+			}
+
+			public int getHostMonitoringIntervalInSec() {
+				throw new UnsupportedOperationException("Not supported yet.");
+			}
+
+			public boolean isBlockWhenEmpty() {
+				return false;
+			}
+			
+			public int getMaxIntervalForBorrowInSec() {
+				return 30;
+			}
+		};
+	}
+	
+	public BlockingClientPool(String name, PoolableBlockingClient poolableBlockingClient) {
+		this.name = name;
+		this.poolableBlockingClient = poolableBlockingClient;
+	}
+	
+	public void init() {
+		logger.log(Level.FINEST, "Started with {0}", name);
+		
+		logger.log(Level.FINEST, "HostMonitoringIntervalInSec: {0}", 
+			poolableBlockingClient.getHostMonitoringIntervalInSec());
+		logger.log(Level.FINEST, "MaxIntervalForBorrowInSec: {0}", 
+			poolableBlockingClient.getMaxIntervalForBorrowInSec());
+		logger.log(Level.FINEST, "NoOpTimeIntervalMiliSec: {0}", 
+			poolableBlockingClient.getNoOpTimeIntervalMiliSec());
+		logger.log(Level.FINEST, "MinPoolSize: {0}", getMinPoolSize());
+		logger.log(Level.FINEST, "IdlePoolSize: {0}", getIdlePoolSize());
+		logger.log(Level.FINEST, "MaxPoolSize: {0}", getMaxPoolSize());
+		
+		
+		LoadDistributor ld = getPoolableBlockingClient().getLoadDistributor();
+		if(ld==null) throw new NullPointerException("Load Distributor is not set!");
+		
+		HostMonitor hm = getPoolableBlockingClient().getHostMonitor();
+		if(hm==null) throw new NullPointerException("Host Monitor is not set!");
+		
+		
+		getHostMonitoringService().setHostList(ld.getHostList());
+		getHostMonitoringService().setHostMonitor(hm);
+		getHostMonitoringService().setIntervalInSec(
+			getPoolableBlockingClient().getHostMonitoringIntervalInSec());
+		
+		HostStateListener hsl = new HostStateListener() {
+			public void stateChanged(Host host, char oldstatus, char newstatus) {
+				if(oldstatus!=Host.UNKNOWN) {
+					logger.log(Level.WARNING, "State changed: {0}; old state: {1};new state: {2}", 
+						new Object[]{host, oldstatus, newstatus});
+					
+					SocketBasedHost shost = (SocketBasedHost) host;
+					ConcurrentLinkedQueue poolForHost = pool.get(shost);
+					if(newstatus==Host.ACTIVE) {						
+						increaseSize(shost, poolForHost);
+					} else {
+						cleanPool(shost);
+					}
+				} else {
+					logger.log(Level.INFO, "State changed: {0}; old state: {1};new state: {2}", 
+						new Object[]{host, oldstatus, newstatus});
+				}
+			}
+		};
+		getHostMonitoringService().addHostStateListner(hsl);
+		HostMonitoringService.add(getHostMonitoringService());
+		HostMonitoringService.monitor(true, getHostMonitoringService());//make first call this hms
+		
+		HostList hostlist = ld.getHostList();
+		
+		List fullHostList = hostlist.getFullList();
+		Iterator iterator = fullHostList.iterator();
+		
+		SocketBasedHost host = null;
+		ConcurrentLinkedQueue poolForHost = null;
+		ConcurrentLinkedQueue poolForInUseHost = null;
+		
+		if(noopThread!=null) {
+			noopThread.interrupt();
+			noopThread = null;
+		}
+		
+
+		
+		lock.writeLock().lock();
+		try {
+			while(iterator.hasNext()) {
+				host = (SocketBasedHost) iterator.next();
+				poolForHost = pool.get(host);
+				if(poolForHost!=null) {
+					cleanPool(host);
+				} else {
+					poolForHost = new ConcurrentLinkedQueue<PooledBlockingClient>();
+					pool.put(host, poolForHost);
+
+					poolForInUseHost = new ConcurrentLinkedQueue<PooledBlockingClient>();
+					inUsePool.put(host, poolForInUseHost);
+				}
+				int _poolSize = 0;
+
+				if(host.getStatus()==Host.ACTIVE) {
+					PooledBlockingClient pooledBlockingClient = null;
+					while( _poolSize++ < getMinPoolSize() ) {
+						pooledBlockingClient = getNewPooledBlockingClient(host);
+						if(pooledBlockingClient==null) {
+							_poolSize--;
+							break;
+						}
+						poolForHost.add(pooledBlockingClient);
+					}			
+				}
+			}
+		} finally {
+			lock.writeLock().unlock();
+		}
+		
+		noopThread = new Thread() {
+			public void run() {
+				long stime = 0;
+				long timeTaken = 0;
+				
+				long timeToSlepp = 0;
+				while(true) {
+					timeToSlepp = (poolableBlockingClient.getNoOpTimeIntervalMiliSec()/2) - timeTaken;
+					if(timeToSlepp>0) {
+						try {
+							sleep(timeToSlepp);
+						} catch (InterruptedException ex) {
+							logger.log(Level.FINEST, "closing noop: {0}", ex);
+							break;
+						}
+					}
+					
+					stime = System.currentTimeMillis();
+					try {
+						sendNoOp();
+					} catch (Throwable ex) {
+						Logger.getLogger(BlockingClientPool.class.getName()).log(Level.SEVERE, 
+							"Error: "+ex, ex);
+					}
+					timeTaken = System.currentTimeMillis() - stime;
+				}
+			}
+		};
+		noopThread.setName(name+"-SendNOOP-Thread");
+		noopThread.setDaemon(true);
+		noopThread.start();
+		
+		
+		if(logPoolStats!=null) {
+			logPoolStats.interrupt();
+			logPoolStats = null;
+		}
+		if(getLogPoolStatsTimeInMinute()>0) {
+			logPoolStats = new Thread() {
+				public void run() {
+					while(true) {
+						try {
+							sleep( getLogPoolStatsTimeInMinute()*60*1000);
+						} catch (InterruptedException ex) {
+							Logger.getLogger(BlockingClientPool.class.getName()).log(Level.WARNING, 
+								"Error: "+ex, ex);
+							break;
+						}
+						
+						try {
+							logger.log(Level.INFO, "Stats: \r\n{0}", getStats());
+						} catch (Exception ex) {
+							logger.log(Level.WARNING, "Error: "+ex, ex);
+						}
+					}
+				}
+			};
+			logPoolStats.setName(name+"-LogPoolStats-Thread");
+			logPoolStats.setDaemon(true);
+			logPoolStats.start();
+		}
+		
+		logger.log(Level.FINEST, "Done with {0}", name);
+	}
+	
+	public PooledBlockingClient getBlockingClient() {
+		return getBlockingClient((ClientInfo)null);
+	}
+	
+	public void checkAllNodes() {
+		HostMonitoringService.monitor();
+	}
+	
+	/**
+	 * 
+	 * @param host
+	 * @return -1 if read lock failed!
+	 */
+	public int getPoolSize(SocketBasedHost host) {
+		ConcurrentLinkedQueue poolForHost = pool.get(host);
+		ConcurrentLinkedQueue poolToHost = inUsePool.get(host);
+		if(poolForHost==null || poolToHost==null) 
+			throw new IllegalStateException("pool for host was null!");
+		
+		if(poolForHost.isEmpty() && poolToHost.isEmpty()) return 0;
+		
+		int size = 0;
+		try {
+			if(lock.readLock().tryLock(maxTimeToLockInSec, TimeUnit.SECONDS)) {
+				try {
+					size = poolForHost.size() + poolToHost.size();
+				} finally {
+					lock.readLock().unlock();
+				}
+			} else {
+				return -1;
+			}
+		} catch (InterruptedException ex) {
+			logger.log(Level.WARNING, "Error: "+ex);
+			return -1;
+		}
+		return size;
+	}
+	
+	public PooledBlockingClient[] getOneBlockingClientForAllActiveHosts() {	
+		List<PooledBlockingClient> allClients = new ArrayList<PooledBlockingClient>();
+		
+		List<Host> listOfActiveHost = hostMonitoringService.getHostList().getActiveList();
+		Iterator<Host> iterator = listOfActiveHost.iterator();
+		
+		PooledBlockingClient pooledBlockingClient = null;	
+		Host host = null;
+		while(iterator.hasNext()) {
+			host = iterator.next();
+			pooledBlockingClient = getBlockingClientByHost((SocketBasedHost) host);
+			if(pooledBlockingClient==null) {
+				logger.warning("Error getting client from "+host);
+				continue;
+			}
+			allClients.add(pooledBlockingClient);
+		}
+		
+		return allClients.toArray(new PooledBlockingClient[0]);
+	}
+	
+	public PooledBlockingClient getBlockingClient(ClientInfo clientInfo) {		
+		SocketBasedHost host = (SocketBasedHost) 
+			getPoolableBlockingClient().getLoadDistributor().getHost(clientInfo);
+		if(host==null) {
+			logger.log(Level.WARNING, "LoadDistributor.. gave null host!");
+			return null;
+		}
+		
+		if(host.getStatus()!=Host.ACTIVE && host.getStatus()!=Host.UNKNOWN) {
+			logger.log(Level.WARNING, "host is not up! sending null host!");
+			return null;
+		}
+		
+		return getBlockingClientByHost(host);
+	}
+		
+	private PooledBlockingClient getBlockingClientByHost(SocketBasedHost host) {
+		ConcurrentLinkedQueue poolForHost = pool.get(host);
+		ConcurrentLinkedQueue poolForInUseHost = inUsePool.get(host);
+		if(poolForHost==null || poolForInUseHost==null) 
+			throw new IllegalStateException("pool for host was null!");		
+				
+		PooledBlockingClient pooledBlockingClient = null;		
+		
+		if(poolForHost.isEmpty()) {		
+			try {
+				int poolsize = poolForHost.size() + poolForInUseHost.size();
+				if(poolsize < getMaxPoolSize()) {
+					try {
+						if(lock.readLock().tryLock(maxTimeToLockInSec, TimeUnit.SECONDS)) {
+							try {
+								poolsize = poolForHost.size() + poolForInUseHost.size();
+								if(poolsize < getMaxPoolSize()) {
+									pooledBlockingClient = getNewPooledBlockingClient(host);
+									return pooledBlockingClient;
+								}
+							} finally {
+								lock.readLock().unlock();
+							}
+						} else {
+							logger.log(Level.WARNING, "not able to get read lock..");
+							return null;
+						}
+					} catch (InterruptedException ex) {
+						logger.log(Level.WARNING, "not able to get read lock..{0}", ex);
+						return null;
+					}
+				} else if(getPoolableBlockingClient().isBlockWhenEmpty()) {
+					for(int i=0;poolForHost.isEmpty() && i<10;i++) {
+						if(isDebug()) logger.log(Level.FINE, "Socket pool empty.. will wait {0}", i);
+						synchronized(poolForHost) {
+							try {
+								poolForHost.wait();				
+							} catch (InterruptedException e) {
+								logger.warning( "Interrupted while sleeping"+ e );
+							}
+							pooledBlockingClient = (PooledBlockingClient) poolForHost.poll();
+						}
+						if(pooledBlockingClient!=null) break;
+					}
+				}
+				return pooledBlockingClient;
+			} finally {
+				if(pooledBlockingClient!=null) {
+					pooledBlockingClient.setHandedOut(true);
+					pooledBlockingClient.setPoolToReturn(poolForHost);
+					pooledBlockingClient.setLastActionTime(System.currentTimeMillis());	
+
+					poolForInUseHost.add(pooledBlockingClient);
+				}
+			}
+		} else {
+			lock.writeLock().lock();
+			try {
+				pooledBlockingClient = (PooledBlockingClient) poolForHost.poll();
+				if(pooledBlockingClient!=null) {
+					pooledBlockingClient.setHandedOut(true);
+					pooledBlockingClient.setPoolToReturn(poolForHost);
+					pooledBlockingClient.setLastActionTime(System.currentTimeMillis());	
+
+					poolForInUseHost.add(pooledBlockingClient);
+				}
+			} finally {
+				lock.writeLock().unlock();
+			}
+			return pooledBlockingClient;			
+		}
+	}
+	
+	private PooledBlockingClient getNewPooledBlockingClient(SocketBasedHost host) {
+		if(host.getStatus()==Host.ACTIVE) {
+			return new PooledBlockingClient(getPoolableBlockingClient(), host);
+		} else {
+			int size = getPoolSize(host);
+			if(size>0) {
+				logger.log(Level.FINEST, "Host is not UP {0}; size: {1}", new Object[]{host, size});
+				cleanPool(host);
+				logger.log(Level.FINEST, "Done {0}; size: {1}", new Object[]{host, getPoolSize(host)});
+			}
+			return null;
+		}		
+	}
+	
+	public void returnBlockingClient(PooledBlockingClient pooledBlockingClient) {	
+		if(pooledBlockingClient==null) return;
+		if(pooledBlockingClient.getSocketBasedHost()==null) return;
+		
+		ConcurrentLinkedQueue poolForInUseHost = inUsePool.get(pooledBlockingClient.getSocketBasedHost());
+		
+		if(pooledBlockingClient.getBlockingClient()==null) {
+			poolForInUseHost.remove(pooledBlockingClient);
+			return;
+		} else if(pooledBlockingClient.getBlockingClient().isConnected()==false) {	
+			try {
+				pooledBlockingClient.getBlockingClient().close();
+			} catch (IOException ex) {
+				Logger.getLogger(BlockingClientPool.class.getName()).log(Level.WARNING, "Error: "+ex, ex);
+			}
+			poolForInUseHost.remove(pooledBlockingClient);
+			return;
+		}
+		
+		if(pooledBlockingClient.getLastActionTime()!=0) {		
+			long timepassed = System.currentTimeMillis()  - pooledBlockingClient.getLastActionTime();
+
+			if(timepassed<1000) {
+				pooledBlockingClient.returnToPool(poolForInUseHost, lock);
+				return;
+			}
+
+			if((timepassed/1000) < poolableBlockingClient.getHostMonitoringIntervalInSec()) {
+				pooledBlockingClient.returnToPool(poolForInUseHost, lock);
+				return;
+			}
+		}
+		
+		boolean flag = getPoolableBlockingClient().sendNoOp(
+			pooledBlockingClient.getBlockingClient());
+		if(isDebug()) {
+			logger.log(Level.FINEST, "noop for {0} was {1}", 
+				new Object[]{pooledBlockingClient, flag});
+		}
+		if(flag) {
+			pooledBlockingClient.returnToPool(poolForInUseHost, lock);
+		} else {
+			poolForInUseHost.remove(pooledBlockingClient);	
+			
+			if(pooledBlockingClient.replaceBlockingClient()) {
+				pooledBlockingClient.returnToPool(null, lock);
+			}
+		}
+	}
+	
+	public String getStats() {
+		SocketBasedHost socketBasedHost = null;
+		StringBuilder sb = new StringBuilder();
+		String stat = null;
+		try {
+			if(lock.readLock().tryLock(maxTimeToLockInSec, TimeUnit.SECONDS)) {
+				try {			
+					Iterator<SocketBasedHost> iterator = pool.keySet().iterator();
+					while(iterator.hasNext()) {
+						socketBasedHost = iterator.next();
+						stat = getStats(socketBasedHost);
+						sb.append(stat).append("\r\n");
+					}	
+				} finally {
+					lock.readLock().unlock();
+				}
+			} else {
+				sb.append("N/A").append("\r\n");
+			}
+		} catch (InterruptedException ex) {
+			logger.log(Level.FINE, "InterruptedException{0}", ex);
+			sb.append("N/A Er").append("\r\n");
+		}
+		return sb.toString();
+	}
+	
+	public String getStats(SocketBasedHost host) throws InterruptedException {
+		ConcurrentLinkedQueue poolForHost = pool.get(host);
+		ConcurrentLinkedQueue poolToHost = inUsePool.get(host);
+		
+		int freeSize = 0;
+		int inuseSize = 0;
+		
+		if(lock.readLock().tryLock(maxTimeToLockInSec, TimeUnit.SECONDS)) {
+			try {			
+				freeSize = poolForHost.size();
+				inuseSize = poolToHost.size();
+			} finally {
+				lock.readLock().unlock();
+			}
+		}
+		
+		StringBuilder sb = new StringBuilder();
+		sb.append(host).append(", ");
+		sb.append("FreeSize, ").append(freeSize).append(", ");
+		sb.append("InUseSize, ").append(inuseSize);		
+		return sb.toString();
+	}
+	
+	public void close() {
+		if(noopThread!=null) {
+			noopThread.interrupt();
+			noopThread = null;
+		}
+		
+		SocketBasedHost socketBasedHost = null;
+		lock.writeLock().lock();
+		try {			
+			Iterator<SocketBasedHost> iterator = pool.keySet().iterator();
+			while(iterator.hasNext()) {
+				socketBasedHost = iterator.next();
+				cleanPool(socketBasedHost);
+			}
+
+			pool.clear();
+			inUsePool.clear();		
+		} finally {
+			lock.writeLock().unlock();
+		}
+	}
+	
+	public void sendNoOp() {
+		SocketBasedHost socketBasedHost = null;
+		ConcurrentLinkedQueue <PooledBlockingClient> mypool = null;
+		
+		Iterator<SocketBasedHost> iterator = pool.keySet().iterator();
+		while(iterator.hasNext()) {
+			socketBasedHost = iterator.next();
+			mypool = pool.get(socketBasedHost);
+			
+			if(socketBasedHost.getStatus()==Host.ACTIVE) {			
+				if(isDebug()) logger.log(Level.FINEST, "Starting NOOP {0}; size: {1}", 
+					new Object[]{socketBasedHost, mypool.size()});
+				sendNoOp(socketBasedHost);
+				if(isDebug()) logger.log(Level.FINEST, "Done NOOP {0}; size: {1}", 
+					new Object[]{socketBasedHost, mypool.size()});
+			} else {
+				int size = getPoolSize(socketBasedHost);
+				if(size>0) {
+					logger.log(Level.FINEST, "Host is not UP {0}; size: {1}", 
+						new Object[]{socketBasedHost, size});
+					cleanPool(socketBasedHost);
+					size = getPoolSize(socketBasedHost);
+					logger.log(Level.FINEST, "Done {0}; size: {1}", 
+						new Object[]{socketBasedHost, size});
+				} else {
+					if(isDebug()) logger.log(Level.FINEST, "Host is not UP {0}", 
+						new Object[]{socketBasedHost});
+				}
+			}
+			
+			if(socketBasedHost.getStatus()==Host.ACTIVE) {	
+				int size = getPoolSize(socketBasedHost);
+				if(size!=-1) {
+					if(size > idlePoolSize) {
+						reduceSize(socketBasedHost, mypool);
+					} else if(size < minPoolSize) {				
+						increaseSize(socketBasedHost, mypool);			
+					}
+				}
+			}
+			
+			checkForLeak(socketBasedHost);			
+		}		
+	}
+	
+	private void reduceSize(SocketBasedHost host, ConcurrentLinkedQueue<PooledBlockingClient> poolForHost) {	
+		PooledBlockingClient pooledBlockingClient = null;		
+			
+		int size = getPoolSize(host);	
+		logger.log(Level.FINEST, 
+			"Start: Pool {0}; size is more then ideal size {1}; free size: {2}; fullsize: {3}", 
+			new Object[]{host, idlePoolSize, poolForHost.size(), size});
+		
+		if(size==-1) return;
+		
+		for(int i=0;size > idlePoolSize && i < maxPoolSize;i++) {			
+			pooledBlockingClient = poolForHost.poll();
+			if(pooledBlockingClient==null) break;
+			try {
+				pooledBlockingClient.getBlockingClient().close();
+			} catch (IOException ex) {
+				Logger.getLogger(BlockingClientPool.class.getName()).log(
+					Level.SEVERE, "Error closing: "+ex, ex);
+			}
+			
+			returnBlockingClient(pooledBlockingClient);//will in-turn drop it from pool
+			pooledBlockingClient = null;
+			
+			size = getPoolSize(host);
+			if(size==-1) break;
+		}
+		
+		logger.log(Level.FINEST, 
+			"End: Pool {0}; size was more then ideal size {1}; free size: {2}; fullsize: {3}", 
+			new Object[]{host, idlePoolSize, poolForHost.size(), size});
+	}
+	
+	private void increaseSize(SocketBasedHost host, ConcurrentLinkedQueue<PooledBlockingClient> poolForHost) {	
+		PooledBlockingClient pooledBlockingClient = null;		
+			
+		int size = getPoolSize(host);		
+		logger.log(Level.FINEST, 
+			"Start: Pool {0}; size is less then min size {1}; free size: {2}; fullsize: {3}", 
+				new Object[]{host, minPoolSize, poolForHost.size(), size});
+		if(size==-1) return;
+		
+		for(int i=0;size < minPoolSize && i < maxPoolSize;i++) {
+			pooledBlockingClient = getNewPooledBlockingClient(host);
+			if(pooledBlockingClient==null) {
+				break;
+			}
+			poolForHost.add(pooledBlockingClient);			
+			
+			size = getPoolSize(host);
+			if(size==-1) break;
+		}
+		
+		logger.log(Level.FINEST, 
+			"End: Pool {0}; size was less then min size {1}; free size: {2}; fullsize: {3}", 
+			new Object[]{host, minPoolSize, poolForHost.size(), size});
+	}
+	
+	private void checkForLeak(SocketBasedHost host) {
+		ConcurrentLinkedQueue poolForInUseHost = inUsePool.get(host);
+		PooledBlockingClient pooledBlockingClient = null;		
+		
+		if(inUsePool.isEmpty()) return;
+		
+		Iterator iterator = poolForInUseHost.iterator();
+		long timedef = 0;
+		List listToRemove = new ArrayList();
+		while(iterator.hasNext()) {
+			pooledBlockingClient = (PooledBlockingClient) iterator.next();
+			if(pooledBlockingClient==null) continue;
+			timedef = System.currentTimeMillis() - pooledBlockingClient.getLastActionTime();
+			if(timedef<1000) continue;
+			
+			timedef = timedef / 1000;
+			
+			if(timedef > getPoolableBlockingClient().getMaxIntervalForBorrowInSec()) {
+				logger.log(Level.WARNING, "There looks to be a leak {0}.. closing", pooledBlockingClient);
+				listToRemove.add(pooledBlockingClient);
+				pooledBlockingClient.close();
+			}
+		}
+		if(listToRemove.isEmpty()==false) {
+			logger.log(Level.WARNING, "Total number of leaks {0}", listToRemove.size());
+			try {
+				if(lock.writeLock().tryLock(maxTimeToLockInSec, TimeUnit.SECONDS)) {
+					try {
+						poolForInUseHost.removeAll(listToRemove);
+					} finally {
+						lock.writeLock().unlock();
+					}
+				} else {
+					logger.fine("unbale to remove leaks.. will try next time..");
+				}
+			} catch (InterruptedException ex) {
+				logger.log(Level.FINE, "unbale to remove leaks.. will try next time..", ex);
+			}
+		}
+	}
+	
+	private void sendNoOp(SocketBasedHost host) {	
+		ConcurrentLinkedQueue<PooledBlockingClient> poolForHost = pool.get(host);
+		ConcurrentLinkedQueue<PooledBlockingClient> poolForInUseHost = inUsePool.get(host);
+		if(poolForHost==null || poolForInUseHost==null) {
+			throw new IllegalStateException("pool for host was null!");
+		}	
+		
+		int size = poolForHost.size();
+		
+		PooledBlockingClient pooledBlockingClient = null;		
+		for(int i=0; i<size; i++) {
+			lock.writeLock().lock();
+			try {
+				pooledBlockingClient = (PooledBlockingClient) poolForHost.poll();
+				if(pooledBlockingClient!=null) {
+					pooledBlockingClient.setHandedOut(true);
+					pooledBlockingClient.setPoolToReturn(poolForHost);
+					//pooledBlockingClient.setLastActionTime(System.currentTimeMillis());	
+
+					poolForInUseHost.add(pooledBlockingClient);
+				} else {
+					break;
+				}
+			} finally {
+				lock.writeLock().unlock();
+			}
+			
+			if(pooledBlockingClient!=null) {			
+				returnBlockingClient(pooledBlockingClient);//will in-turn send noop	
+				pooledBlockingClient = null;
+			}
+		}
+	}
+
+	private boolean cleanPool(SocketBasedHost host) {
+		ConcurrentLinkedQueue poolForHost = pool.get(host);
+		ConcurrentLinkedQueue poolForInUseHost = inUsePool.get(host);
+		if(poolForHost==null || poolForInUseHost==null) {
+			throw new IllegalStateException("pool for host was null! "+host);
+		}	
+		
+		Iterator iterator = poolForInUseHost.iterator();
+		PooledBlockingClient pooledBlockingClient = null;
+		
+		logger.log(Level.FINEST, "Start: Clean Pool {0};  {1}; free size: {2}; fullsize: {3}", 
+			new Object[]{host, minPoolSize, poolForHost.size(), poolForInUseHost.size()});
+		try {
+			if(lock.writeLock().tryLock(maxTimeToLockInSec, TimeUnit.SECONDS)) {		
+				try {
+					while(iterator.hasNext()) {
+						pooledBlockingClient = (PooledBlockingClient) iterator.next();
+						if(pooledBlockingClient==null) continue;
+						pooledBlockingClient.setPoolToReturn(null);
+						pooledBlockingClient.close();
+					}
+					poolForInUseHost.clear();
+
+					iterator = poolForHost.iterator();
+					pooledBlockingClient = null;
+					while(iterator.hasNext()) {
+						pooledBlockingClient = (PooledBlockingClient) iterator.next();
+						if(pooledBlockingClient==null) continue;
+						pooledBlockingClient.close();
+					}
+					poolForHost.clear();
+				} finally {
+					lock.writeLock().unlock();
+				}
+			
+				logger.log(Level.FINEST, "End: Clean Pool {0};  {1}; free size: {2}; fullsize: {3}", 
+					new Object[]{host, minPoolSize, poolForHost.size(), poolForInUseHost.size()});
+				return true;
+			} else {
+				return false;
+			}
+		} catch (InterruptedException ex) {
+			logger.log(Level.FINE, "Error: {0}", ex);
+			return false;
+		}
+	}
+
+	public PoolableBlockingClient getPoolableBlockingClient() {
+		return poolableBlockingClient;
+	}
+
+	public void setPoolableBlockingClient(PoolableBlockingClient poolableBlockingClient) {
+		this.poolableBlockingClient = poolableBlockingClient;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public int getMinPoolSize() {
+		return minPoolSize;
+	}
+
+	public void setMinPoolSize(int minPoolSize) {
+		this.minPoolSize = minPoolSize;
+	}
+
+	public int getMaxPoolSize() {
+		return maxPoolSize;
+	}
+
+	public void setMaxPoolSize(int maxPoolSize) {
+		this.maxPoolSize = maxPoolSize;
+	}
+
+	public int getIdlePoolSize() {
+		return idlePoolSize;
+	}
+
+	public void setIdlePoolSize(int idlePoolSize) {
+		this.idlePoolSize = idlePoolSize;
+	}
+
+	public HostMonitoringService getHostMonitoringService() {
+		return hostMonitoringService;
+	}
+
+	private void setHostMonitoringService(HostMonitoringService hostMonitoringService) {
+		this.hostMonitoringService = hostMonitoringService;
+	}
+
+	public int getLogPoolStatsTimeInMinute() {
+		return logPoolStatsTimeInMinute;
+	}
+
+	public void setLogPoolStatsTimeInMinute(int logPoolStatsTimeInMinute) {
+		this.logPoolStatsTimeInMinute = logPoolStatsTimeInMinute;
+	}
+
+	public String toStirng() {
+		return getStats();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/pool/PoolableBlockingClient.java b/quickserver/src/main/org/quickserver/net/client/pool/PoolableBlockingClient.java
new file mode 100644
index 0000000..332b5d8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/pool/PoolableBlockingClient.java
@@ -0,0 +1,26 @@
+package org.quickserver.net.client.pool;
+
+import org.quickserver.net.client.BlockingClient;
+import org.quickserver.net.client.SocketBasedHost;
+import org.quickserver.net.client.loaddistribution.LoadDistributor;
+import org.quickserver.net.client.monitoring.HostMonitor;
+
+/**
+ *
+ * @author akshath
+ */
+public interface PoolableBlockingClient {
+	public BlockingClient createBlockingClient(SocketBasedHost host);
+	public boolean closeBlockingClient(BlockingClient blockingClient);
+	
+	public boolean isBlockWhenEmpty();
+		
+	public boolean sendNoOp(BlockingClient blockingClient);
+	public long getNoOpTimeIntervalMiliSec();
+	public int getHostMonitoringIntervalInSec();
+	public int getMaxIntervalForBorrowInSec();
+	
+	public HostMonitor getHostMonitor();
+	public LoadDistributor getLoadDistributor();
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/pool/PooledBlockingClient.java b/quickserver/src/main/org/quickserver/net/client/pool/PooledBlockingClient.java
new file mode 100644
index 0000000..23dbc87
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/pool/PooledBlockingClient.java
@@ -0,0 +1,190 @@
+package org.quickserver.net.client.pool;
+
+import java.io.IOException;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.quickserver.net.client.BlockingClient;
+import org.quickserver.net.client.SocketBasedHost;
+
+/**
+ *
+ * @author akshath
+ */
+public class PooledBlockingClient {
+	private BlockingClient blockingClient;
+	
+	private long connectedTime;
+	
+	private int handedOutCount;
+	private long handedOutSince;
+	
+	private long lastActionTime;
+	
+	private boolean handedOut;
+	
+	private ConcurrentLinkedQueue poolToReturn;
+	
+	private PoolableBlockingClient poolableBlockingClient;
+	private SocketBasedHost socketBasedHost;
+	
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("PooledBlockingClient{");
+		sb.append("socketBasedHost:").append(socketBasedHost).append(';');
+		sb.append("blockingClient:").append(blockingClient).append(';');
+		sb.append("}");
+		return sb.toString();
+	}
+	
+	public PooledBlockingClient(PoolableBlockingClient poolableBlockingClient, 
+			SocketBasedHost socketBasedHost) {
+		this.poolableBlockingClient = poolableBlockingClient;
+		this.socketBasedHost = socketBasedHost;
+		
+		blockingClient = poolableBlockingClient.createBlockingClient(socketBasedHost);
+		connectedTime = System.currentTimeMillis();
+		handedOutCount = 0;
+		handedOutSince = -1;
+		handedOut = false;
+	}
+	
+	public void close() {
+		if(getBlockingClient()!=null) {
+			try {
+				getBlockingClient().close();
+			} catch (IOException ex) {
+				Logger.getLogger(BlockingClientPool.class.getName()).log(
+					Level.WARNING, "Error closeing: "+ex, ex);
+			}
+		}
+		blockingClient = null;
+		poolToReturn = null;
+		poolableBlockingClient = null;
+	}
+	
+	protected boolean replaceBlockingClient() {
+		if(blockingClient!=null) {
+			try {
+				blockingClient.close();
+			} catch (IOException ex) {
+				Logger.getLogger(PooledBlockingClient.class.getName()).log(
+					Level.WARNING, "Error closing : "+ex, ex);
+			}
+		}
+		
+		if(poolableBlockingClient!=null) {
+			blockingClient = poolableBlockingClient.createBlockingClient(getSocketBasedHost());
+			return blockingClient!=null;
+		} else {
+			return false;
+		}
+	}
+	
+	protected void returnToPool(ConcurrentLinkedQueue poolForInUseHost, ReentrantReadWriteLock lock) {
+		if(poolToReturn!=null) {
+			setLastActionTime(System.currentTimeMillis());	
+			
+			Object objToLock = null;
+			if(poolableBlockingClient.isBlockWhenEmpty()) {
+				objToLock = poolToReturn;
+			}
+			
+			lock.writeLock().lock();
+			try {
+				if(poolForInUseHost!=null) poolForInUseHost.remove(this);
+				setHandedOut(false);
+				poolToReturn.add(this);
+				poolToReturn = null;
+			} finally {
+				lock.writeLock().unlock();
+			}			
+			
+			if(poolableBlockingClient.isBlockWhenEmpty()) {
+				synchronized(objToLock) {
+					objToLock.notify();
+				}
+			}
+		} else {
+			Logger.getLogger(PooledBlockingClient.class.getName()).log(Level.WARNING, 
+				"poolToReturn was null.. will close");
+			try {
+				getBlockingClient().close();
+			} catch (IOException ex) {
+				Logger.getLogger(PooledBlockingClient.class.getName()).log(Level.WARNING, "Error "+ex, ex);
+			}
+		}
+	}
+
+	public BlockingClient getBlockingClient() {
+		return blockingClient;
+	}
+
+	public void setBlockingClient(BlockingClient blockingClient) {
+		this.blockingClient = blockingClient;
+	}
+
+	public long getConnectedTime() {
+		return connectedTime;
+	}
+
+	public void setConnectedTime(long connectedTime) {
+		this.connectedTime = connectedTime;
+	}
+
+	public int getHandedOutCount() {
+		return handedOutCount;
+	}
+
+	public void setHandedOutCount(int handedOutCount) {
+		this.handedOutCount = handedOutCount;
+	}
+
+	public long getHandedOutSince() {
+		return handedOutSince;
+	}
+
+	public void setHandedOutSince(long handedOutSince) {
+		this.handedOutSince = handedOutSince;
+	}
+
+	public boolean isHandedOut() {
+		return handedOut;
+	}
+
+	public void setHandedOut(boolean handedOut) {
+		this.handedOut = handedOut;
+		if(handedOut) {
+			handedOutCount++;
+			handedOutSince = System.currentTimeMillis();			
+		} else {
+			handedOutSince = -1;
+		}
+	}
+
+	public ConcurrentLinkedQueue getPoolToReturn() {
+		return poolToReturn;
+	}
+
+	public void setPoolToReturn(ConcurrentLinkedQueue poolToReturn) {
+		this.poolToReturn = poolToReturn;
+	}
+
+	public SocketBasedHost getSocketBasedHost() {
+		return socketBasedHost;
+	}
+
+	public void setSocketBasedHost(SocketBasedHost socketBasedHost) {
+		this.socketBasedHost = socketBasedHost;
+	}
+
+	public long getLastActionTime() {
+		return lastActionTime;
+	}
+
+	public void setLastActionTime(long lastActionTime) {
+		this.lastActionTime = lastActionTime;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/client/pool/package.html b/quickserver/src/main/org/quickserver/net/client/pool/package.html
new file mode 100644
index 0000000..49cf653
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/client/pool/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Socket Pool classes of QuickServer Client.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/package.html b/quickserver/src/main/org/quickserver/net/package.html
new file mode 100644
index 0000000..80ddf2e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Support classes and exceptions.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/Authenticator.java b/quickserver/src/main/org/quickserver/net/qsadmin/Authenticator.java
new file mode 100644
index 0000000..785755a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/Authenticator.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import org.quickserver.net.server.*;
+import org.quickserver.net.AppException;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Default QSAdminServer ServerAuthenticator.
+ * <p>
+ * Username : Admin<br>
+ * Password : QsAdm1n
+ * </p>
+ * @since 1.1
+ */
+public class Authenticator extends QuickAuthenticationHandler {
+
+	public AuthStatus askAuthentication(ClientHandler handler) 
+			throws IOException, AppException {
+		Data data = (Data) handler.getClientData();
+		data.setLastAsked("U");
+		handler.sendClientMsg("+OK Username required");
+		return null;
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, String command) 
+			throws IOException, AppException {
+		Data data = (Data)handler.getClientData();
+
+		if(data.getLastAsked().equals("U")) {
+			data.setUsername(command);
+			data.setLastAsked("P");
+			handler.sendClientMsg("+OK Password required");
+		} else if(data.getLastAsked().equals("P")) {
+			data.setPassword(command.getBytes());
+			
+			if(Authenticator.validate(data.getUsername(), data.getPassword())) {
+				handler.sendClientMsg("+OK Logged in");
+				data.setPassword(null);
+				return AuthStatus.SUCCESS;
+			} else {
+				handler.sendClientMsg("-ERR Authorisation Failed");
+				data.setPassword(null);
+				return AuthStatus.FAILURE;
+			}
+		} else {
+			throw new AppException("Unknown LastAsked!");
+		}
+
+		return null;
+	}
+
+	/**
+	 * This function is used to validate username and password.
+	 * May be overridden to change username and/or password.
+	 */ 
+	protected static boolean validate(String username, byte[] password) {
+		return username.equals("Admin") && 
+			Arrays.equals(password,"QsAdm1n".getBytes());
+	}
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/CommandHandler.java b/quickserver/src/main/org/quickserver/net/qsadmin/CommandHandler.java
new file mode 100644
index 0000000..8d9366d
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/CommandHandler.java
@@ -0,0 +1,1026 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import java.net.*;
+import java.io.*;
+import java.text.Format;
+import java.text.SimpleDateFormat;
+import java.util.StringTokenizer;
+
+import org.quickserver.net.server.ClientCommandHandler;
+import org.quickserver.net.server.ClientEventHandler;
+import org.quickserver.net.server.ClientHandler;
+import org.quickserver.net.server.QuickServer;
+import org.quickserver.net.AppException;
+
+import java.util.logging.*;
+
+import org.quickserver.util.*;
+import org.quickserver.util.pool.thread.*;
+import java.util.*;
+import org.quickserver.util.pool.*;
+import org.apache.commons.pool.ObjectPool;
+import org.quickserver.net.server.ClientIdentifier;
+
+/**
+ * ClientCommandHandler for QSAdminServer.
+ * <p>
+ * = Protocol =<br>
+ * Each response starts with a status.
+ * <ul>
+ *  <li>+OK = Success
+ *  <li>-ERR = Failed
+ * </ul>
+ * If response if one lined then it follows the status.
+ * Else You will get "info follows" as the first line
+ * followed by with many lines of response ending by a 
+ * dot in a line by itself. i.e.,  &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;<br>
+ * Command supported are give below .. [ Note: &lt;&lt;target&gt;&gt; = server|self ]
+ * <br>&nbsp;<br>
+ * <table align="center" border=1>
+ * <tr><th>Command</th><th>Param</th><th>Effect</th></tr>
+ * <tr><td>start</td><td>&lt;&lt;target&gt;&gt;</td><td>Starts target.</td></tr>
+ * <tr><td>stop</td><td>&lt;&lt;target&gt;&gt;</td><td>Stops target.</td></tr>
+ * <tr><td>restart</td><td>&lt;&lt;target&gt;&gt;</td><td>=stop+start command</td></tr>
+ * <tr><td>shutdown</td><td>&nbsp;</td><td>Stops server and self. </td></tr>
+ * <tr><td>kill or exit</td><td>&nbsp;</td><td>Stops server and self and kill all threads. </td></tr>
+ * <tr><td>info</td><td>&lt;&lt;target&gt;&gt;</td><td>Information about target.</td></tr>
+ * <tr><td>noclient</td><td>&lt;&lt;target&gt;&gt;</td><td>No Client connected to the target.</td></tr>
+ * <tr><td>running</td><td>&lt;&lt;target&gt;&gt;</td><td>Checks if target is running.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; maxClient</td><td>Gets max no of client for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; port</td><td>Gets port for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; maxAuthTryMsg</td><td>Gets maxAuthTryMsg for the target. </td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientCommandHandler</td><td>Gets ClientCommandHandler class for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientAuthenticationHandler</td><td>Gets ClientAuthenticationHandler class for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientData</td><td>Gets ClientData class for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; timeout</td><td>Gets timeout set for clients for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; maxClient &lt;&lt;value&gt;&gt;</td><td>Sets max no of client for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; port &lt;&lt;value&gt;&gt;</td><td>Sets port for the target.*</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; maxAuthTryMsg &lt;&lt;value&gt;&gt;</td><td>Sets maxAuthTryMsg for the target. *</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientCommandHandler &lt;&lt;value&gt;&gt;</td><td>Sets ClientCommandHandler class for the target. *</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientAuthenticationHandler &lt;&lt;value&gt;&gt;</td><td>Sets ClientAuthenticationHandler class for the target. *</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientData &lt;&lt;value&gt;&gt;</td><td>Sets ClientData class for the target. *</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; timeout &lt;&lt;value&gt;&gt;</td><td>Sets timeout set for clients for the target. *</td></tr>
+ * <tr><td>version</td><td>&nbsp;</td><td>Gets the version of the QuickServer library used.</td></tr>
+ * <tr><td>quit</td><td>&nbsp;</td><td>Close session.</td></tr>
+ * <tr><td colspan=3>New Command in v1.2 </td></tr>
+ * <tr><td>get</td><td>self plugin</td><td>Gets pluggable command handler for QsAdminServer. *</td></tr>
+ * <tr><td>set</td><td>self plugin &lt;&lt;full class name&gt;&gt;</td><td>Sets Pluggable command handler for QsAdminServer. *</td></tr>
+ * <tr><td colspan=3>New Command in v1.3 </td></tr>
+ * <tr><td>suspendService</td><td>&lt;&lt;target&gt;&gt;</td><td>Suspends target.</td></tr>
+ * <tr><td>resumeService</td><td>&lt;&lt;target&gt;&gt;</td><td>Resume target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; maxAuthTry</td><td>Gets maxAuthTry for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; maxAuthTry</td><td>Sets maxAuthTry for the target.*</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientObjectHandler</td><td>Gets ClientObjectHandler class for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientObjectHandler</td><td>Sets ClientObjectHandler class for the target.*</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; timeoutMsg</td><td>Gets timeout Message for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; timeoutMsg</td><td>Sets timeout Message for the target.*</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; serviceState</td><td>Gets Service State for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; consoleLoggingFormatter</td><td>Sets consoleLoggingFormatter for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; consoleLoggingFormatter</td><td>Sets consoleLoggingFormatter for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; consoleLoggingLevel</td><td>Sets consoleLoggingLevel for the target. <br>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; consoleLoggingLevel</td><td>Sets consoleLoggingLevel for the target. <br>
+ * [<code>SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST<code>]</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; maxClientMsg</td><td>Sets maxClientMsg for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; maxClientMsg</td><td>Gets maxClientMsg for the target.</td></tr>
+ * <tr><td colspan=3>New Command in v1.3.1 </td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; loggingLevel</td><td>Sets LoggingLevel for the target. <br>
+ * [<code>SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST<code>]</td></tr>
+ * <tr><td colspan=3>New Command in v1.3.2 </td></tr>
+ * <tr><td>memoryInfo</td><td>&nbsp;</td><td>Memory Information {Total:Used:Max}</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; communicationLogging</td><td>Sets communication logging flag for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; communicationLogging</td><td>Gets communication logging flag for the target.</td></tr>
+
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; objectPoolConfig-maxActive</td><td>Sets maxActive of objectPoolConfig for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; objectPoolConfig-maxActive</td><td>Gets maxActive of objectPoolConfig for the target.</td></tr>
+
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; objectPoolConfig-maxIdle</td><td>Sets maxIdle of objectPoolConfig for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; objectPoolConfig-maxIdle</td><td>Gets maxIdle of objectPoolConfig for the target.</td></tr>
+ *
+ * <tr><td colspan=3>New Command in v1.4.5 </td></tr>
+ * <tr><td>all-pool-info</td><td>&lt;&lt;target&gt;&gt;</td><td>Gives stats of all pools for the target.</td></tr>
+ * <tr><td>client-thread-pool-dump</td><td>&lt;&lt;target&gt;&gt;</td><td>Gives dump of all threads in pool for the target.</td></tr>
+ * <tr><td>start</td><td>&lt;&lt;console&gt;&gt;</td><td>Starts console shell.</td></tr>
+ * <tr><td>stop</td><td>&lt;&lt;console&gt;&gt;</td><td>Stops console shell.</td></tr>
+ *
+ * <tr><td colspan=3>New Command in v1.4.6 </td></tr>
+ * <tr><td>client-handler-pool-dump</td><td>&lt;&lt;target&gt;&gt;</td><td>Gives dump of all ClientHandler in pool for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientEventHandler</td><td>Gets ClientEventHandler class for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientEventHandler &lt;&lt;value&gt;&gt;</td><td>Sets ClientEventHandler class for the target. *</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientWriteHandler</td><td>Gets ClientWriteHandler class for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientWriteHandler &lt;&lt;value&gt;&gt;</td><td>Sets ClientWriteHandler class for the target. *</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; clientExtendedEventHandler</td><td>Gets ClientExtendedEventHandler class for the target.</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; clientExtendedEventHandler &lt;&lt;value&gt;&gt;</td><td>Sets ClientExtendedEventHandler class for the target. *</td></tr>
+ * <tr><td>set</td><td>&lt;&lt;target&gt;&gt; objectPoolConfig-initSize</td><td>Sets initSize of objectPoolConfig for the target.</td></tr>
+ * <tr><td>get</td><td>&lt;&lt;target&gt;&gt; objectPoolConfig-initSize</td><td>Gets initSize of objectPoolConfig for the target.</td></tr>
+ * <tr><td colspan=3>New Command in v2.0.0 </td></tr>
+ * <tr><td>kill-clients-all</td><td>&lt;&lt;target&gt;&gt;</td><td>Kill all ClientHandler/Client in pool for the target.</td></tr>
+ * <tr><td>kill-client-with</td><td>&lt;&lt;target&gt;&gt; &lt;&lt;search term&gt;&gt;</td><td>Kill all ClientHandler/Client in pool for the target which has the search term n toString (check client-handler-pool-dump command for the format).</td></tr>
+ * 
+ * <tr><td>jvm</td><td>dumpJmapHisto file</td><td>Dump JMAP to file</td></tr>
+ * <tr><td>jvm</td><td>dumpJmapHisto log</td><td>Dump JMAP to jdk log</td></tr>
+ * <tr><td>jvm</td><td>dumpJStack file</td><td>Dump JStack to file</td></tr>
+ * <tr><td>jvm</td><td>dumpJStack log</td><td>Dump JStack to jdk log</td></tr>
+ * <tr><td>jvm</td><td>threadDump file</td><td>Take thread dump to file</td></tr>
+ * <tr><td>jvm</td><td>threadDump log</td><td>Take thread dump to jdk log</td></tr>
+ * <tr><td>jvm</td><td>dumpHeap</td><td>Dump Heap to file</td></tr>
+ *
+ * <tr><td colspan=3>* = Take effect after a restart command.<br>
+ *      value if set null then key will be set to <code>null</code>
+ *     </td></tr>
+ * </table>
+ * <br>Note: 
+ * <ul>
+ * <li>Stopping the QuickServer will not disconnect any client connect to it, since 
+ * client connections are handled by different thread.
+ * <li><code>restart</code> and <code>start</code> response just indicate only 
+ * if command was sent. Do check the state of the target using 
+ * <code>running</code> command to see if server was started successful.
+ * <li>Demo code examples\EchoServer shows the use of QsAdminServer to control itself.
+ * </ul>
+ * Eg: <br>
+ * <BLOCKQUOTE>
+ *  noClient server<br>
+ *  noClient self<br>
+ *  get server maxClient<br>
+ *  set server maxClient 10
+ * </BLOCKQUOTE>
+ * </p>
+ * @since 1.1
+ */
+public class CommandHandler implements ClientCommandHandler, ClientEventHandler {
+	private static Logger logger = Logger.getLogger(CommandHandler.class.getName());
+	
+	private static Format formatter = new SimpleDateFormat("yyyyMMdd_HHmmss");
+	
+	private static File getFile(String name, String ext) {
+		StringBuilder sb = new StringBuilder("./");
+		
+		File logDir = new File("./log/");
+		if(logDir.exists()==false) {
+			logDir.mkdirs();
+		}
+		if(logDir.canWrite()) {
+			sb.append("log/");
+		}
+		
+		sb.append(name);		
+		sb.append("_");
+		sb.append(formatter.format(new Date()));
+		
+		sb.append(ext);
+		
+		return new File(sb.toString());
+	}
+
+	private CommandPlugin plugin;
+	private Runtime runtime;
+	StringBuilder temp = new StringBuilder();
+
+	//-- ClientEventHandler
+	public void gotConnected(ClientHandler handler)
+		throws SocketTimeoutException, IOException {
+		logger.log(Level.FINE, "Connection opened : {0}", handler.getHostAddress());
+
+		handler.sendClientMsg("+OK +++++++++++++++++++++++++++++++++");
+		handler.sendClientMsg("+OK   Welcome to QsAdminServer v 1.0 ");
+		handler.sendClientMsg("+OK +++++++++++++++++++++++++++++++++");
+
+		//v.2
+		if(plugin==null || runtime==null) {
+			plugin = (CommandPlugin)
+				handler.getServer().getStoreObjects()[1];
+			//v1.3.2
+			runtime = Runtime.getRuntime();
+		}
+	}
+
+	public void lostConnection(ClientHandler handler) 
+			throws IOException {
+		logger.log(Level.FINE, "Connection lost : {0}", handler.getHostAddress());
+	}
+	public void closingConnection(ClientHandler handler) 
+			throws IOException {
+		logger.log(Level.FINE, "Connection closing : {0}", handler.getHostAddress());
+	}
+	//-- ClientEventHandler
+
+	public void handleCommand(ClientHandler handler, String command)
+			throws SocketTimeoutException, IOException {
+		if(command==null || command.trim().equals("")) {
+			handler.sendClientMsg("-ERR No command");
+			return;
+		}
+		
+		//v1.2 - plugin
+		if( plugin != null && plugin.handleCommand(handler,command) ) {
+			logger.fine("Handled by plugin.");
+			return;
+		}
+		QSAdminServer adminServer = (QSAdminServer)
+			handler.getServer().getStoreObjects()[2];
+
+		StringTokenizer st = new StringTokenizer(command," ");
+		String cmd = null;
+		cmd = st.nextToken().toLowerCase();
+		String param[] = new String[st.countTokens()];
+		
+		QuickServer target = null;		
+		for (int i=0;st.hasMoreTokens();i++) {
+			param[i] = st.nextToken();
+		}
+
+		if(command.equals("start console")) { /*v1.4.5*/
+			QSAdminShell.getInstance(
+				(QuickServer) handler.getServer().getStoreObjects()[0], null);
+			handler.sendClientMsg("+OK QSAdminShell is started.");
+			return;
+		} else if(command.equals("stop console")) { /*v1.4.5*/
+			QSAdminShell shell = QSAdminShell.getInstance(null, null);
+			if(shell!=null) {
+				try {
+					shell.stopShell();
+				} catch(Exception err) {
+					handler.sendClientMsg("-ERR Error stopping QSAdminShell: "+err);
+				}				
+				handler.sendClientMsg("+OK QSAdminShell is stopped.");
+			} else {
+				handler.sendClientMsg("-ERR QSAdminShell is not running.");
+			}
+			return;
+		} else if(cmd.equals("jvm")) {/*2.0.0*/
+			/*
+				jvm dumpHeap
+				jvm dumpJmapHisto file
+				jvm dumpJmapHisto log
+				jvm threadDump file
+				jvm threadDump log
+				jvm dumpJStack file
+				jvm dumpJStack log
+			 */
+			
+			if(param.length==0) {
+				handler.sendClientMsg("-ERR "+"Use jvm help");
+				return;
+			}			
+			
+			if(param[0].equals("dumpHeap")) {
+				File file = getFile("dumpHeap", ".bin");
+				JvmUtil.dumpHeap(file.getAbsolutePath(), true);
+				handler.sendClientMsg("+OK File "+file.getAbsolutePath());
+			} else if(param[0].equals("dumpJmapHisto")) {
+				if(param.length < 2)/*dumpJmapHisto file*/ {
+					handler.sendClientMsg("-ERR "+"insufficient param");
+					return;
+				}
+				
+				if(param[1].equals("file")) {
+					File file = getFile("dumpJmapHisto", ".txt");
+					
+					handler.sendClientMsg("+OK info follows");					
+					handler.sendClientMsg("Starting.. ");
+					
+					JvmUtil.dumpJmapHisto(file.getAbsolutePath());
+					
+					handler.sendClientMsg("Done - File "+file.getAbsolutePath());					
+					handler.sendClientMsg(".");
+				} else if(param[1].equals("log")) {
+					handler.sendClientMsg("+OK info follows");					
+					handler.sendClientMsg("Starting.. ");
+					
+					JvmUtil.dumpJmapHistoToLog();
+					
+					handler.sendClientMsg("Done - Dumped to jdk log file");
+					handler.sendClientMsg(".");
+				} else {
+					handler.sendClientMsg("-ERR "+"bad param");
+					return;
+				}
+			} else if(param[0].equals("threadDump")) {
+				if(param.length < 2)/*threadDump file*/ {
+					handler.sendClientMsg("-ERR "+"insufficient param");
+					return;
+				}
+				
+				if(param[1].equals("file")) {
+					File file = getFile("threadDump", ".txt");
+					
+					handler.sendClientMsg("+OK info follows");					
+					handler.sendClientMsg("Starting.. ");
+					
+					JvmUtil.threadDump(file.getAbsolutePath());
+					
+					handler.sendClientMsg("Done - File "+file.getAbsolutePath());
+					handler.sendClientMsg(".");
+				} else if(param[1].equals("log")) {
+					handler.sendClientMsg("+OK info follows");					
+					handler.sendClientMsg("Starting.. ");
+					
+					JvmUtil.threadDumpToLog();
+					
+					handler.sendClientMsg("Done - Dumped to jdk log file");
+					handler.sendClientMsg(".");
+				} else {
+					handler.sendClientMsg("-ERR "+"bad param");
+					return;
+				}
+			} else if(param[0].equals("dumpJStack")) {
+				if(param.length < 2)/*dumpJStack file*/ {
+					handler.sendClientMsg("-ERR "+"insufficient param");
+					return;
+				}
+				
+				if(param[1].equals("file")) {
+					File file = getFile("dumpJStack", ".txt");
+					
+					handler.sendClientMsg("+OK info follows");					
+					handler.sendClientMsg("Starting.. ");
+					
+					JvmUtil.dumpJStack(file.getAbsolutePath());
+					
+					handler.sendClientMsg("Done - File "+file.getAbsolutePath());
+					handler.sendClientMsg(".");
+				} else if(param[1].equals("log")) {
+					handler.sendClientMsg("+OK info follows");					
+					handler.sendClientMsg("Starting.. ");
+					
+					JvmUtil.dumpJStackToLog();
+					
+					handler.sendClientMsg("Done - Dumped to jdk log file");
+					handler.sendClientMsg(".");
+				} else {
+					handler.sendClientMsg("-ERR "+"bad param");
+					return;
+				}
+			} else if(param[0].equals("help")) {
+				handler.sendClientMsg("+OK info follows");
+				
+				handler.sendClientMsg("jvm dumpJmapHisto file");
+				handler.sendClientMsg("jvm dumpJStack file");
+				
+				handler.sendClientMsg(" ");
+				
+				handler.sendClientMsg("jvm threadDump file");
+				handler.sendClientMsg("jvm dumpHeap");
+				
+				handler.sendClientMsg(" ");
+				
+				handler.sendClientMsg("jvm threadDump log");				
+				handler.sendClientMsg("jvm dumpJmapHisto log");				
+				handler.sendClientMsg("jvm dumpJStack log");
+				
+				handler.sendClientMsg(".");
+				return;				
+			} else {				
+				handler.sendClientMsg("-ERR "+"bad param use jvm help");
+			}
+			return;
+		}
+
+		if(param.length > 0) {
+			if( param[0].equals("server") )
+				target = (QuickServer) handler.getServer().getStoreObjects()[0];
+			else if( param[0].equals("self") )
+				target = handler.getServer();
+			else {
+				handler.sendClientMsg("-ERR Bad <<target>> : "+param[0]);
+				return;
+			}
+		}
+ 
+		if(cmd.equals("help")) {
+			handler.sendClientMsg("+OK info follows"+"\r\n"+
+				"Refer Api Docs for org.quickserver.net.qsadmin.CommandHandler");
+			handler.sendClientMsg(".");
+			return;
+		} else if(cmd.equals("quit")) {
+			handler.sendClientMsg("+OK Bye ;-)");
+			handler.closeConnection();
+			return;
+		} else if(cmd.equals("shutdown")) {
+			try	{
+				QuickServer controlServer = 
+					(QuickServer) handler.getServer().getStoreObjects()[0];
+				if(controlServer!=null && controlServer.isClosed()==false) {
+					controlServer.stopServer();
+				}
+				if(handler.getServer()!=null && handler.getServer().isClosed()==false) {
+					handler.getServer().stopServer();
+				}
+
+				QSAdminShell shell = QSAdminShell.getInstance(null, null);
+				if(shell!=null) {
+					try {
+						shell.stopShell();
+					} catch(Exception err) {
+						logger.warning("Error stoping shell: "+err);
+					}				
+				}
+
+				handler.sendClientMsg("+OK Done");
+			} catch (AppException e) {
+				handler.sendClientMsg("-ERR "+e);
+			}
+			return;
+		} else if(cmd.equals("version")) {
+			handler.sendClientMsg("+OK "+QuickServer.getVersion());
+			return;
+		} else if(cmd.equals("kill") || cmd.equals("exit")) /*v1.3,v1.3.2*/{
+			StringBuilder errBuf = new StringBuilder();
+			QuickServer controlServer = 
+				(QuickServer) handler.getServer().getStoreObjects()[0];
+			int exitCode = 0;
+
+			if(param.length!=0) {
+				try {
+					exitCode = Integer.parseInt(param[0]);
+				} catch(Exception nfe) {/*ignore*/}				
+			}
+
+			try	{				
+				if(controlServer!=null && controlServer.isClosed()==false) {
+					try {
+						controlServer.stopServer();
+					} catch(AppException ae) {
+						errBuf.append(ae.toString());
+					}
+				}
+				if(handler.getServer()!=null  && handler.getServer().isClosed()==false) {
+					try {
+						handler.getServer().stopServer();
+					} catch(AppException ae) {
+						errBuf.append(ae.toString());
+					}					
+				}
+
+				QSAdminShell shell = QSAdminShell.getInstance(null, null);
+				if(shell!=null) {
+					try {
+						shell.stopShell();
+					} catch(Exception err) {
+						errBuf.append(err.toString());
+					}				
+				}
+
+				if(errBuf.length()==0)
+					handler.sendClientMsg("+OK Done");
+				else
+					handler.sendClientMsg("+OK Done, Errors: "+errBuf.toString());
+			} catch (Exception e) {
+				handler.sendClientMsg("-ERR Exception : "+e+"\r\n"+errBuf.toString());
+				if(exitCode==0) exitCode = 1;
+			} finally {
+				try {
+					if(controlServer!=null)
+						controlServer.closeAllPools();
+					if(handler.getServer()!=null)
+						handler.getServer().closeAllPools();
+				} catch(Exception er) {
+					logger.warning("Error closing pools: "+er);
+				}
+				System.exit(exitCode);
+			}
+			return;
+		} else if(cmd.equals("memoryinfo")) { /*v1.3.2*/
+			//Padding : Total:Used:Max
+			float totalMemory = (float) runtime.totalMemory();
+			float usedMemory = totalMemory - (float) runtime.freeMemory();			        
+			float maxMemory = (float) runtime.maxMemory();
+			handler.sendClientMsg("+OK "+totalMemory+":"+usedMemory+":"+maxMemory);
+			return;
+		} else if(cmd.equals("systeminfo")) { /*v1.4.5*/
+			handler.sendClientMsg("+OK info follows");
+			handler.sendClientMsg(MyString.getSystemInfo(target.getVersion()));			
+			handler.sendClientMsg(".");
+			return;
+		} else if(param.length==0) {
+			handler.sendClientMsg("-ERR Bad Command or No Param : ->"+cmd+"<-");
+			return;
+		}
+		
+		if(cmd.equals("start")) {
+			try	{
+				target.startServer();
+				handler.sendClientMsg("+OK Server Started");
+			} catch (AppException e) {
+				handler.sendClientMsg("-ERR "+e);
+			}
+			return;
+		} else if(cmd.equals("stop")) {
+			try	{
+				target.stopServer();
+				handler.sendClientMsg("+OK Server Stopped");
+			} catch (AppException e) {
+				handler.sendClientMsg("-ERR "+e);
+			}
+			return;
+		} else if(cmd.equals("restart")) {
+			try	{
+				target.stopServer();
+				target.startServer();
+				handler.sendClientMsg("+OK Server Restarted");
+			} catch (AppException e) {
+				handler.sendClientMsg("-ERR "+e);
+			}
+			return;
+		} else if(cmd.equals("info")) {
+			handler.sendClientMsg("+OK info follows");
+			handler.sendClientMsg(""+target);
+			handler.sendClientMsg("Running : "+!target.isClosed());
+			handler.sendClientMsg("PID : "+QuickServer.getPID());
+			handler.sendClientMsg("Max Client Allowed  : "+target.getMaxConnection() );
+			handler.sendClientMsg("No Client Connected : "+target.getClientCount() );
+			if(target.isRunningSecure()==true) {
+				handler.sendClientMsg("Running in secure mode : "+
+					target.getSecure().getProtocol() );
+			} else {
+				handler.sendClientMsg("Running in non-secure mode");
+			}
+			handler.sendClientMsg("Server Mode : "+target.getBasicConfig().getServerMode());
+			handler.sendClientMsg("QuickServer v : "+QuickServer.getVersion());
+			handler.sendClientMsg("Uptime : "+target.getUptime());
+			handler.sendClientMsg(".");
+			return;
+		} else if(cmd.equals("noclient")) {
+			handler.sendClientMsg("+OK "+target.getClientCount() );
+			return;
+		} else if(cmd.equals("running")) {
+			handler.sendClientMsg("+OK "+!target.isClosed() );
+			return;
+		} else if(cmd.equals("suspendservice")) {
+			handler.sendClientMsg("+OK "+target.suspendService() );
+			return;
+		} else if(cmd.equals("resumeservice")) {
+			handler.sendClientMsg("+OK "+target.resumeService() );
+			return;
+		} else if(cmd.equals("client-thread-pool-info")) /*v1.3.2*/{
+			temp.setLength(0);//used:idle
+			if(PoolHelper.isPoolOpen(target.getClientPool().getObjectPool())==true) {
+				temp.append(target.getClientPool().getNumActive());
+				temp.append(':');
+				temp.append(target.getClientPool().getNumIdle());
+			} else {
+				temp.append("0:0");
+			}
+			handler.sendClientMsg("+OK "+temp.toString() );
+			return;
+		} else if(cmd.equals("client-thread-pool-dump")) /*v1.4.5*/{
+			if(PoolHelper.isPoolOpen(target.getClientPool().getObjectPool())==true) {
+				handler.sendClientMsg("+OK info follows");
+				ClientThread ct = null;
+				synchronized(target.getClientPool().getObjectToSynchronize()) {
+					Iterator iterator = target.getClientPool().getAllClientThread();
+					while(iterator.hasNext()) {
+						ct = (ClientThread)iterator.next();
+						handler.sendClientMsg(ct.toString());
+					}
+				}
+				handler.sendClientMsg(".");
+			} else {
+				handler.sendClientMsg("-ERR Pool Closed");
+			}
+			return;
+		} else if(cmd.equals("client-handler-pool-dump")) /*v1.4.6*/{
+			
+			ObjectPool objectPool = target.getClientHandlerPool();
+
+			if(PoolHelper.isPoolOpen(objectPool)==true) {
+				if(QSObjectPool.class.isInstance(objectPool)==false) {
+					handler.sendClientMsg("-ERR System Error!");
+				}
+
+				ClientIdentifier clientIdentifier = target.getClientIdentifier();
+				ClientHandler foundClientHandler = null;
+				synchronized(clientIdentifier.getObjectToSynchronize()) {	
+					Iterator iterator = clientIdentifier.findAllClient();
+					handler.sendClientMsg("+OK info follows");
+					while(iterator.hasNext()) {
+						foundClientHandler = (ClientHandler) iterator.next();
+						handler.sendClientMsg(foundClientHandler.info());
+					}
+				}
+				handler.sendClientMsg(".");
+			} else {
+				handler.sendClientMsg("-ERR Pool Closed");
+			}
+			return;
+		} else if(cmd.equals("client-data-pool-info")) /*v1.3.2*/{
+			temp.setLength(0);//used:idle
+			if(target.getClientDataPool()!=null) {
+				if(PoolHelper.isPoolOpen(target.getClientDataPool())==true) {
+					temp.append(target.getClientDataPool().getNumActive());
+					temp.append(':');
+					temp.append(target.getClientDataPool().getNumIdle());
+					handler.sendClientMsg("+OK "+temp.toString() );
+				} else {
+					handler.sendClientMsg("-ERR Client Data Pool Closed");
+				}
+			} else {
+				handler.sendClientMsg("-ERR No Client Data Pool");
+			}
+			return;
+		} else if(cmd.equals("byte-buffer-pool-info")) /*v1.4.6*/{
+			temp.setLength(0);//used:idle
+			if(target.getByteBufferPool()!=null) {
+				if(PoolHelper.isPoolOpen(target.getByteBufferPool())==true) {
+					temp.append(target.getByteBufferPool().getNumActive());
+					temp.append(':');
+					temp.append(target.getByteBufferPool().getNumIdle());
+					handler.sendClientMsg("+OK "+temp.toString() );
+				} else {
+					handler.sendClientMsg("-ERR ByteBuffer Pool Closed");
+				}
+			} else {
+				handler.sendClientMsg("-ERR No ByteBuffer Pool");
+			}
+			return;
+		} else if(cmd.equals("all-pool-info")) /*v1.4.5*/{
+			handler.sendClientMsg("+OK info follows");
+			temp.setLength(0);//used:idle
+			
+			if(PoolHelper.isPoolOpen(target.getClientPool().getObjectPool())==true) {
+				temp.append("Client Thread Pool - ");
+				temp.append("Num Active: ");
+				temp.append(target.getClientPool().getNumActive());
+				temp.append(", Num Idle: ");
+				temp.append(target.getClientPool().getNumIdle());
+				temp.append(", Max Idle: ");
+				temp.append(target.getClientPool().getPoolConfig().getMaxIdle());
+				temp.append(", Max Active: ");
+				temp.append(target.getClientPool().getPoolConfig().getMaxActive());				
+			} else {
+				temp.append("Byte Buffer Pool - Closed");
+			}
+			handler.sendClientMsg(temp.toString());
+			temp.setLength(0);
+
+			if(PoolHelper.isPoolOpen(target.getClientHandlerPool())==true) {
+				temp.append("Client Handler Pool - ");
+				temp.append("Num Active: ");
+				temp.append(target.getClientHandlerPool().getNumActive());
+				temp.append(", Num Idle: ");
+				temp.append(target.getClientHandlerPool().getNumIdle());
+				temp.append(", Max Idle: ");
+				temp.append(target.getBasicConfig().getObjectPoolConfig().getClientHandlerObjectPoolConfig().getMaxIdle());
+				temp.append(", Max Active: ");
+				temp.append(target.getBasicConfig().getObjectPoolConfig().getClientHandlerObjectPoolConfig().getMaxActive());
+			} else {
+				temp.append("Client Handler Pool - Closed");
+			}
+			handler.sendClientMsg(temp.toString());
+			temp.setLength(0);
+
+			if(target.getByteBufferPool()!=null) {
+				if(PoolHelper.isPoolOpen(target.getByteBufferPool())==true) {
+					temp.append("ByteBuffer Pool - ");
+					temp.append("Num Active: ");
+					temp.append(target.getByteBufferPool().getNumActive());
+					temp.append(", Num Idle: ");
+					temp.append(target.getByteBufferPool().getNumIdle());
+					temp.append(", Max Idle: ");
+					temp.append(target.getBasicConfig().getObjectPoolConfig().getByteBufferObjectPoolConfig().getMaxIdle());
+					temp.append(", Max Active: ");
+					temp.append(target.getBasicConfig().getObjectPoolConfig().getByteBufferObjectPoolConfig().getMaxActive());
+				} else {
+					temp.append("Byte Buffer Pool - Closed");
+				}
+			} else {
+				temp.append("Byte Buffer Pool - Not Used");
+			}
+			handler.sendClientMsg(temp.toString());
+			temp.setLength(0);
+
+			if(target.getClientDataPool()!=null) {
+				if(PoolHelper.isPoolOpen(target.getClientDataPool())==true) {
+					temp.append("Client Data Pool - ");
+					temp.append("Num Active: ");
+					temp.append(target.getClientDataPool().getNumActive());
+					temp.append(", Num Idle: ");
+					temp.append(target.getClientDataPool().getNumIdle());				
+					temp.append(", Max Idle: ");
+					temp.append(target.getBasicConfig().getObjectPoolConfig().getClientDataObjectPoolConfig().getMaxIdle());
+					temp.append(", Max Active: ");
+					temp.append(target.getBasicConfig().getObjectPoolConfig().getClientDataObjectPoolConfig().getMaxActive());
+				} else {
+					temp.append("Client Data Pool - Closed");
+				}
+			} else {
+				temp.append("Client Data Pool - Not Used");
+			}
+			handler.sendClientMsg(temp.toString());
+			temp.setLength(0);			
+
+			handler.sendClientMsg(".");
+			return;
+		} else if(cmd.equals("set")) {
+			if(param.length < 3)/*target,key,value*/ {
+				handler.sendClientMsg("-ERR "+"insufficient param");
+				return;
+			}
+			if(param[2].equals("null"))
+				param[2]=null;
+			try	{
+				if(param[1].equals("maxClient")) {
+					long no = Long.parseLong(param[2]);
+					target.setMaxConnection(no);
+				} else if(param[1].equals("maxClientMsg")) {
+					target.setMaxConnectionMsg(param[2]);
+				} else if(param[1].equals("port")) {
+					long no = Long.parseLong(param[2]);
+					target.setPort((int)no);
+				} else if(param[1].equals("port")) {
+					long no = Long.parseLong(param[2]);
+					target.setPort((int)no);
+				} else if(param[1].equals("maxAuthTry")) {
+					int no = Integer.parseInt(param[2]);
+					target.setMaxAuthTry(no);
+				} else if(param[1].equals("maxAuthTryMsg")) {
+					target.setMaxAuthTryMsg(param[2]);
+				} else if(param[1].equals("clientEventHandler")) { /*v1.4.6*/
+					target.setClientEventHandler(param[2]);
+				} else if(param[1].equals("clientCommandHandler")) {
+					target.setClientCommandHandler(param[2]);
+				} else if(param[1].equals("clientWriteHandler")) { /*v1.4.6*/
+					target.setClientWriteHandler(param[2]);
+				} else if(param[1].equals("clientObjectHandler")) {
+					target.setClientObjectHandler(param[2]); /*v1.3*/
+				} else if(param[1].equals("clientAuthenticationHandler")) {
+					target.setClientAuthenticationHandler(param[2]);
+				} else if(param[1].equals("clientData")) {
+					target.setClientData(param[2]);
+				} else if(param[1].equals("clientExtendedEventHandler")) { /*v1.4.6*/
+					target.setClientExtendedEventHandler(param[2]);
+				} else if(param[1].equals("timeout")) {
+					long no = Long.parseLong(param[2]);
+					target.setTimeout((int)no);
+				} else if(param[1].equals("timeoutMsg")) {
+					target.setTimeoutMsg(param[2]); /* v1.3 */
+				} else if(param[1].equals("plugin")) /* v1.2*/{
+					if(param[0].equals("self")) {
+						try {							
+							adminServer.setCommandPlugin(param[2]);
+						} catch(Exception e) {
+							handler.sendClientMsg("-ERR not set : "+e);
+							return;
+						}
+					} else {
+						handler.sendClientMsg("-ERR Bad target : "+param[0]+" self is only allowed.");
+						return;
+					}
+				} else if(param[1].equals("consoleLoggingFormatter")) {
+					target.setConsoleLoggingFormatter(param[2]); /* v1.3 */
+				} else if(param[1].equals("consoleLoggingLevel")) { /* v1.3 */
+					if(param[2].endsWith("SEVERE"))
+						target.setConsoleLoggingLevel(Level.SEVERE); 
+					else if(param[2].endsWith("WARNING"))
+						target.setConsoleLoggingLevel(Level.WARNING); 
+					else if(param[2].endsWith("INFO"))
+						target.setConsoleLoggingLevel(Level.INFO); 
+					else if(param[2].endsWith("CONFIG"))
+						target.setConsoleLoggingLevel(Level.CONFIG);
+					else if(param[2].endsWith("FINE"))
+						target.setConsoleLoggingLevel(Level.FINE);
+					else if(param[2].endsWith("FINER"))
+						target.setConsoleLoggingLevel(Level.FINER); 
+					else if(param[2].endsWith("FINEST"))
+						target.setConsoleLoggingLevel(Level.FINEST);
+					else if(param[2].endsWith("ALL"))
+						target.setConsoleLoggingLevel(Level.ALL);
+					else if(param[2].endsWith("OFF"))
+						target.setConsoleLoggingLevel(Level.OFF);
+					else {
+						handler.sendClientMsg("-ERR Bad Level "+param[2]);	
+						return;
+					}
+				} else if(param[1].equals("loggingLevel")) { /* v1.3.1 */
+					if(param[2].endsWith("SEVERE"))
+						target.setLoggingLevel(Level.SEVERE); 
+					else if(param[2].endsWith("WARNING"))
+						target.setLoggingLevel(Level.WARNING); 
+					else if(param[2].endsWith("INFO"))
+						target.setLoggingLevel(Level.INFO); 
+					else if(param[2].endsWith("CONFIG"))
+						target.setLoggingLevel(Level.CONFIG);
+					else if(param[2].endsWith("FINE"))
+						target.setLoggingLevel(Level.FINE);
+					else if(param[2].endsWith("FINER"))
+						target.setLoggingLevel(Level.FINER); 
+					else if(param[2].endsWith("FINEST"))
+						target.setLoggingLevel(Level.FINEST);
+					else if(param[2].endsWith("ALL"))
+						target.setLoggingLevel(Level.ALL);
+					else if(param[2].endsWith("OFF"))
+						target.setLoggingLevel(Level.OFF);
+					else {
+						handler.sendClientMsg("-ERR Bad Level "+param[2]);	
+						return;
+					}
+				} else if(param[1].equals("communicationLogging")) {
+					if(param[2].equals("true"))/* v1.3.2 */
+						target.setCommunicationLogging(true);
+					else
+						target.setCommunicationLogging(false);
+				} else if(param[1].equals("objectPoolConfig-maxActive")) {
+					int no = Integer.parseInt(param[2]);
+					target.getConfig().getObjectPoolConfig().setMaxActive(no);
+				} else if(param[1].equals("objectPoolConfig-maxIdle")) {
+					int no = Integer.parseInt(param[2]);
+					target.getConfig().getObjectPoolConfig().setMaxIdle(no);
+				} else if(param[1].equals("objectPoolConfig-initSize")) {
+					int no = Integer.parseInt(param[2]);
+					target.getConfig().getObjectPoolConfig().setInitSize(no);
+				} else {
+					handler.sendClientMsg("-ERR Bad Set Key : "+param[1]);	
+					return;
+				}
+				handler.sendClientMsg("+OK Set");				
+			} catch(Exception e) {
+				handler.sendClientMsg("-ERR "+e);
+			}
+			return;
+		} else if(cmd.equals("get")) {
+			if(param.length < 2)/*target,key*/ {
+				handler.sendClientMsg("-ERR "+"insufficient param");
+				return;
+			}
+			try	{
+				if(param[1].equals("maxClient")) {
+					long no = target.getMaxConnection();
+					handler.sendClientMsg("+OK "+no);
+				} else if(param[1].equals("maxClientMsg")) {
+					String msg = target.getMaxConnectionMsg();
+					msg = MyString.replaceAll(msg, "\n", "\\n");
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("port")) {
+					long no = target.getPort();
+					handler.sendClientMsg("+OK "+no);
+				} else if(param[1].equals("maxAuthTry")) {
+					int no = target.getMaxAuthTry();
+					handler.sendClientMsg("+OK "+no);
+				} else if(param[1].equals("maxAuthTryMsg")) {
+					String msg=target.getMaxAuthTryMsg();
+					msg = MyString.replaceAll(msg, "\n", "\\n");
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientEventHandler")) { /*v1.4.6*/
+					String msg=target.getClientEventHandler();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientCommandHandler")) {
+					String msg=target.getClientCommandHandler();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientWriteHandler")) { /*v1.4.6*/
+					String msg=target.getClientWriteHandler();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientObjectHandler")) {
+					String msg=target.getClientObjectHandler();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientAuthenticationHandler")) {
+					String msg=target.getClientAuthenticationHandler();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientData")) {
+					String msg=target.getClientData();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("clientExtendedEventHandler")) { /*v1.4.6*/
+					String msg=target.getClientExtendedEventHandler();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("timeout")) {
+					String msg=""+target.getTimeout();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("timeoutMsg")) {
+					String msg=""+target.getTimeoutMsg();
+					msg = MyString.replaceAll(msg, "\n", "\\n");
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("plugin")) /* v1.2*/{
+					if(param[0].equals("self")) {
+						String msg = adminServer.getCommandPlugin();
+						handler.sendClientMsg("+OK "+msg);			
+					} else {
+						handler.sendClientMsg("-ERR Bad target : "+param[0]+" self is only allowed.");
+					}
+				} else if(param[1].equals("consoleLoggingFormatter")) {
+					String msg=""+target.getConsoleLoggingFormatter(); /* v1.3 */
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("consoleLoggingLevel")) { /* v1.3 */
+					String msg=""+target.getConsoleLoggingLevel();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("serviceState")) {
+					int state=target.getServiceState(); /*v1.3*/
+					if(state==org.quickserver.net.Service.INIT)
+						handler.sendClientMsg("+OK INIT");
+					else if(state==org.quickserver.net.Service.RUNNING)
+						handler.sendClientMsg("+OK RUNNING");
+					else if(state==org.quickserver.net.Service.STOPPED)
+						handler.sendClientMsg("+OK STOPPED");
+					else if(state==org.quickserver.net.Service.SUSPENDED)
+						handler.sendClientMsg("+OK SUSPENDED");
+					else
+						handler.sendClientMsg("+OK UNKNOWN");
+				} else if(param[1].equals("communicationLogging")) {
+					String msg=""+target.getCommunicationLogging();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("objectPoolConfig-maxActive")) {
+					String msg=""+target.getConfig().getObjectPoolConfig().getMaxActive();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("objectPoolConfig-maxIdle")) {
+					String msg=""+target.getConfig().getObjectPoolConfig().getMaxIdle();
+					handler.sendClientMsg("+OK "+msg);
+				} else if(param[1].equals("objectPoolConfig-initSize")) {
+					String msg=""+target.getConfig().getObjectPoolConfig().getInitSize();
+					handler.sendClientMsg("+OK "+msg);
+				} else {
+					handler.sendClientMsg("-ERR Bad Get Key : "+param[1]);	
+				}			
+			} catch(Exception e) {
+				handler.sendClientMsg("-ERR "+e);
+			}
+			return;
+		} else if(cmd.equals("kill-clients-all")) /*v2.0.0*/{
+			
+			ObjectPool objectPool = target.getClientHandlerPool();
+
+			if(PoolHelper.isPoolOpen(objectPool)==true) {
+				if(QSObjectPool.class.isInstance(objectPool)==false) {
+					handler.sendClientMsg("-ERR System Error!");
+				}
+
+				ClientIdentifier clientIdentifier = target.getClientIdentifier();
+				ClientHandler foundClientHandler = null;
+				synchronized(clientIdentifier.getObjectToSynchronize()) {	
+					Iterator iterator = clientIdentifier.findAllClient();
+					handler.sendClientMsg("+OK closing");
+					int count = 0;
+					int found = 0;
+					while(iterator.hasNext()) {
+						foundClientHandler = (ClientHandler) iterator.next();
+						found++;
+						if(foundClientHandler.isClosed()==false) {
+							foundClientHandler.closeConnection();
+							count ++;
+						}
+					}
+					handler.sendClientMsg("Count Found: "+found);
+					handler.sendClientMsg("Count Closed: "+count);
+				}
+				handler.sendClientMsg(".");
+			} else {
+				handler.sendClientMsg("-ERR Closing");
+			}
+			return;
+		} else if(cmd.equals("kill-client-with")) /*v2.0.0*/{
+			
+			if(param.length < 2)/*target,search*/ {
+				handler.sendClientMsg("-ERR "+"insufficient param");
+				return;
+			}
+			String search = param[1];
+			
+			ObjectPool objectPool = target.getClientHandlerPool();
+
+			if(PoolHelper.isPoolOpen(objectPool)==true) {
+				if(QSObjectPool.class.isInstance(objectPool)==false) {
+					handler.sendClientMsg("-ERR System Error!");
+				}
+
+				ClientIdentifier clientIdentifier = target.getClientIdentifier();
+				ClientHandler foundClientHandler = null;
+				synchronized(clientIdentifier.getObjectToSynchronize()) {	
+					Iterator iterator = clientIdentifier.findAllClient();
+					handler.sendClientMsg("+OK closing");
+					int count = 0;
+					int found = 0;
+					while(iterator.hasNext()) {
+						foundClientHandler = (ClientHandler) iterator.next();
+						if(foundClientHandler.toString().indexOf(search)!=-1) {
+							found++;
+							if(foundClientHandler.isClosed()==false) {
+								foundClientHandler.closeConnection();
+								count ++;
+							}
+						}						
+					}
+					handler.sendClientMsg("Count Found: "+found);
+					handler.sendClientMsg("Count Closed: "+count);
+				}
+				handler.sendClientMsg(".");
+			} else {
+				handler.sendClientMsg("-ERR Closing");
+			}
+			return;
+		} else {
+			handler.sendClientMsg("-ERR Bad Command : "+cmd);
+		}
+		return;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/CommandPlugin.java b/quickserver/src/main/org/quickserver/net/qsadmin/CommandPlugin.java
new file mode 100644
index 0000000..513fd3e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/CommandPlugin.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import org.quickserver.net.server.*;
+
+/**
+ * This interface defines the methods that should be implemented by 
+ * any class that wants to override default protocol of QsAdminServer 
+ * or add new command specific to your application.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientCommandHandler
+ * <ul>
+ * <li>Should be thread safe.
+ * <li>It should not store any client data that may be needed in the 
+ * implementation.
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * <li>Should have a default constructor - If QsAdminSupport is needed. 
+ * </ul>
+ * If you need to access the QuickServer you can use the code given below<br/>
+ * <code>QuickServer myserver = (QuickServer) handler.getServer().getStoreObjects()[0];</code>
+ * </p>
+ * @see QSAdminServer#startServer()
+ * @author Akshathkumar Shetty 
+ */
+public interface CommandPlugin {
+	/**
+	 * Method called every time client sends a command to QsAdminServer.
+	 * Should be used to handle the command sent and send any 
+	 * requested data. 
+	 * If the comand is handled by the plugin it should
+	 * return <code>true</code> else it should return <code>false</code>
+	 * indicating <code>qsadmin.CommandHandler</code> to take any 
+	 * default action for the command.
+	 * This method can be used to override default protocol of 
+	 * QsAdminServer or add new command specific to your application.
+	 *
+	 * @exception java.net.SocketTimeoutException if socket times out
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public boolean handleCommand(ClientHandler handler,	String command)
+		throws SocketTimeoutException, IOException;
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/Data.java b/quickserver/src/main/org/quickserver/net/qsadmin/Data.java
new file mode 100644
index 0000000..f5036eb
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/Data.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import org.quickserver.net.*;
+import org.quickserver.net.server.*;
+
+import java.io.*;
+
+public class Data implements ClientData {
+	private String lastAsked = null;
+	private String username = null;
+	private byte password[] = null;
+
+	public void setLastAsked(String lastAsked) {
+		this.lastAsked = lastAsked;
+	}
+	public String getLastAsked() {
+		return lastAsked;
+	}
+
+	public void setUsername(String username) {
+		this.username = username;
+	}
+	public String getUsername() {
+		return username;
+	}
+
+	public void setPassword(byte[] password) {
+		this.password = password;
+	}
+	public byte[] getPassword() {
+		return password;
+	}
+}
+
+
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminAPI.java b/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminAPI.java
new file mode 100644
index 0000000..afe03c3
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminAPI.java
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import java.io.*;
+import java.net.*;
+import java.util.logging.*;
+
+/**
+ * QSAdminAPI class to communicate to QsAdmin from java applications.
+ * <p>
+ *  Eg:
+ * <code><BLOCKQUOTE><pre>
+	QSAdminAPI qsAdminApi = new QSAdminAPI("127.0.0.1", 9080);
+	if(qsAdminApi.logon()) {
+		System.out.println("Logged in");
+		String info = qsAdminApi.sendCommand("info server");
+		System.out.println("Info on Server :\n"+info);
+		qsAdminApi.logoff();
+	} else {
+		System.out.println("Bad Login");
+		qsAdminApi.close();
+	}
+</pre></BLOCKQUOTE></code></p>
+ * @see QSAdminServer
+ * @since 1.4
+ * @author Akshathkumar Shetty
+ */
+public class QSAdminAPI {
+	private static final Logger logger = Logger.getLogger(QSAdminAPI.class.getName());
+
+	private String username = "Admin";
+	private String password = "QsAdm1n";
+
+	private String host = "localhost";
+	private int port = 9877;
+
+	private Socket socket;
+	private InputStream in;
+	private OutputStream out;
+	private BufferedReader br;
+	private BufferedWriter bw;
+ 
+	/**
+	 * Creates QSAdminAPI object that will communicate with the 
+	 * passed host and port.
+	 */
+	public QSAdminAPI(String host, int port) {
+		this.host = host;
+		this.port = port;		
+	}
+ 
+	/**
+	 * Will attempt to connect and logon to the remote QsAdminServer.
+	 */
+	public boolean logon() throws IOException {
+		return logon(username, password);
+	}
+
+	/**
+	 * Will attempt to connect and logon to the remote QsAdminServer.
+	 */
+	public boolean logon(String username, String password) 
+			throws IOException {
+		this.username = username;
+		this.password = password;
+
+		logger.fine("Connecting to "+host+":"+port);
+		socket = new Socket(host, port);
+		in = socket.getInputStream();
+		out = socket.getOutputStream();
+		br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+		bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
+		logger.fine("Got : "+br.readLine());
+		logger.fine("Got : "+br.readLine());
+		logger.fine("Got : "+br.readLine());
+
+		logger.fine("Got : "+br.readLine());
+		logger.fine("Sending username");
+		bw.write(username+"\r\n");
+		bw.flush();
+		logger.fine("Got : "+br.readLine());
+
+		logger.fine("Sending password");
+		bw.write(password+"\r\n");
+		bw.flush();
+
+		String temp = br.readLine();
+		logger.fine("Got : "+temp);
+		return temp.startsWith("+OK ");  
+	}
+ 
+	/**
+	 * Sends the given command to QSAdmin and gives the response back.
+	 */
+	public String sendCommand(String data) throws IOException  {
+		logger.fine("Sending command : "+data);
+		bw.write(data+"\r\n");
+		bw.flush();
+		String temp = readResponse();
+		logger.fine("Got : "+temp);
+		return temp;
+	}
+
+	private String readResponse() throws IOException {
+		StringBuilder command = new StringBuilder();
+		String res = br.readLine();
+		if(res!=null && res.equals("+OK info follows")==false)
+			return res;
+		while(res!=null && res.equals(".")==false) {
+			command.append(res + "\r\n");
+			res = br.readLine();
+		}
+		return command.toString();
+	}
+ 
+	/**
+	 * Logoff the QSAdminServer and closed the socket associated.
+	 */
+	public void logoff() throws IOException  {
+		logger.fine("Logging off");
+		logger.fine("Sending command : quit");
+		bw.write("quit"+"\r\n");
+		bw.flush();
+		logger.fine("Got : "+br.readLine());
+		close();
+	}
+
+	/**
+	 * Closes the socket associated.
+	 */
+	public void close() throws IOException  {
+		logger.fine("Closing");
+		socket.close();
+		socket = null;
+	}
+ 
+	public static void main(String[] args) throws Exception {
+		QSAdminAPI qsAdminApi = new QSAdminAPI("127.0.0.1", 9080);
+		if(qsAdminApi.logon()) {
+			logger.info("Logged in");
+			String info = qsAdminApi.sendCommand("info server");
+			logger.info("Info on Server :\n"+info);
+			qsAdminApi.logoff();
+		} else {
+			logger.warning("Bad Login!");
+			qsAdminApi.close();
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminServer.java b/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminServer.java
new file mode 100644
index 0000000..710fdba
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminServer.java
@@ -0,0 +1,246 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import org.quickserver.net.*;
+import org.quickserver.net.server.*;
+
+import java.io.*;
+//v1.2
+import java.util.logging.*;
+
+/**
+ * QSAdminServer Main class.
+ * <p>
+ *	This is can be used to setup a admin server to a 
+ *  {@link org.quickserver.net.server.QuickServer}, it is implemented
+ *  as a QuickServer. {@link org.quickserver.net.server.QuickServer} 
+ *  comes with a very use full method
+ *  {@link org.quickserver.net.server.QuickServer#startQSAdminServer} that
+ *  creates  QSAdminServer associated with itself and starts it at 
+ *  the specified port or the default port 9877.
+ * </p>
+ * @see #startServer()
+ * @since 1.1
+ */
+public class QSAdminServer {
+	private static Logger logger = Logger.getLogger(
+			QSAdminServer.class.getName());
+	private final static String VER = "2.0";
+
+	private QuickServer controlServer;
+	private QuickServer adminServer; //this server
+	private int port = 9877;
+
+	private String cmdHandle = "org.quickserver.net.qsadmin.CommandHandler";
+	private String auth = "org.quickserver.net.qsadmin.Authenticator";
+	private String data = "org.quickserver.net.qsadmin.Data";
+	
+	//v1.2	
+	private String pluginClass;
+	private CommandPlugin plugin;
+
+	//v1.3.2
+	private boolean shellEnable;
+	private String promptName;
+
+	/**
+	 * Creates QSAdminServer with default settings.
+	 * By default it has been set to allow only 1 client 
+	 * connection to it and binds to <code>127.0.0.1</code>.
+	 * @param controlServer QuickServer to control.
+	 */
+	public QSAdminServer(QuickServer controlServer) {
+		this.controlServer = controlServer;
+		adminServer = new QuickServer();
+
+		adminServer.setClientEventHandler(cmdHandle);
+		adminServer.setClientCommandHandler(cmdHandle);
+		adminServer.setClientAuthenticationHandler(auth);
+		adminServer.setClientData(data);
+		adminServer.setPort(port);	
+
+		adminServer.setAppLogger(logger); //v1.2
+		adminServer.setName("QSAdminServer v "+VER);
+		adminServer.setMaxConnection(1);
+		adminServer.getBasicConfig().getServerMode().setBlocking(true);
+
+		try	{
+			adminServer.setBindAddr("127.0.0.1");
+		} catch(java.net.UnknownHostException e) {
+			logger.warning("Could not bind to 127.0.0.1");
+			throw new RuntimeException("Could not bind to 127.0.0.1 : "+e);
+		}
+		adminServer.setQSAdminServer(this);//lets set to self
+	}	
+
+	/**
+     * Sets the Authenticator class that handles the 
+	 * authentication of a client, if null uses default 
+	 * {@link Authenticator}.
+	 * @param authenticator full class name of the class that 
+	 * implements {@link org.quickserver.net.server.Authenticator}.
+	 * @since 1.3
+	 * @deprecated since 1.4.6 use setClientAuthenticationHandler
+     */
+	public void setAuthenticator(String authenticator) {
+		if(authenticator != null)
+			adminServer.setClientAuthenticationHandler(authenticator);
+	}
+
+	/**
+     * Sets the ClientAuthenticationHandler class that handles the 
+	 * authentication of a client, if null uses default 
+	 * {@link Authenticator}.
+	 * @param authenticator full class name of the class that 
+	 * implements {@link org.quickserver.net.server.ClientAuthenticationHandler}.
+	 * @since 1.4.6
+     */
+	public void setClientAuthenticationHandler(String authenticator) {
+		if(authenticator != null)
+			adminServer.setClientAuthenticationHandler(authenticator);
+	}
+
+	/**
+	 * Starts the QSAdminServer.
+	 * @param port to run QSAdminServer on
+	 */
+	public void startServer(int port) throws AppException {
+		adminServer.setPort(port);
+		startServer();
+	}
+
+	/**
+	 * Starts the QSAdminServer.
+	 * This method also sets the 'Store Objects' of QSAdminServer's
+	 * QuickServer to the following <PRE>
+		POS 0 = QuickServer that is controled.
+		POS 1 = Command Plugin if present for QSAdminServer's CommandHandler
+		POS 3 = QSAdminServer own reference object. </PRE> 
+	 * @since 1.2
+	 */
+	public void startServer() throws AppException {
+		//v1.2 -  plugin stored in pos = 1, 
+		//        QSAdminServer stored at pos = 2
+
+		prepareCommandPlugin();
+		Object[] store = new Object[]{(Object) getControlServer(), 
+			(Object) plugin, (Object) QSAdminServer.this };
+		adminServer.setStoreObjects(store);
+
+		if(getControlServer()==null)
+			throw new NullPointerException("control Server was null"); 
+		try	{
+			adminServer.startServer();
+			if(isShellEnable()==true) {
+				QSAdminShell.getInstance(getControlServer(), getPromptName());
+			}
+		} catch(AppException e) {
+			logger.warning("AppError : "+e);
+			throw e;
+		}
+	}
+
+	/**
+     * Returns the QuickServer object that created it.
+     */
+	public QuickServer getServer() {
+		return adminServer;
+	}
+
+	/**
+     * Returns the QuickServer object that is being 
+	 * controled by this QSAdminServer.
+     */
+	public QuickServer getControlServer() {
+		return controlServer;
+	}
+
+	private void prepareCommandPlugin() {
+		String _pluginClass = getCommandPlugin();
+		if(_pluginClass==null) return;
+		try {
+			Class cl = getControlServer().getClass(pluginClass, true);
+			plugin = (CommandPlugin) cl.newInstance();
+		} catch(Exception e) {
+			logger.warning("Error loading plugin : " + e);
+		}
+	}	 
+
+	/**
+	 * Sets the {@link CommandPlugin} class which plugs into
+	 * {@link CommandHandler} of QsAdminServer. It should be set 
+	 * before QSAdminServer is started. Or QSAdminServer must be 
+	 * restarted.
+	 * @param pluginClass the fully qualified name of the 
+	 *  desired class that implements {@link CommandPlugin}
+	 * @exception if could not load the class
+	 * @since 1.2
+	 */	 
+	public void setCommandPlugin(String pluginClass) 
+			throws Exception {
+		if(pluginClass==null)
+			return;
+		this.pluginClass = pluginClass;	
+	}
+	
+
+	/**
+	 * Returns the {@link CommandPlugin} class which plugs into
+	 * {@link CommandHandler} of QsAdminServer,it will be null if not set.
+	 * @since 1.2
+	 */
+	public String getCommandPlugin() {
+		return pluginClass;
+	}
+
+	public static String getVersion() {
+		return VER;
+	}
+
+
+	/**
+	 * Returns flag indicated if command shell is enabled. 
+	 * @since 1.3.2
+	 */
+	public boolean isShellEnable() {
+		return shellEnable;
+	}
+
+	/**
+	 * Sets the flag indicated if command shell is enabled. 
+	 * @since 1.3.2
+	 */
+	public void setShellEnable(boolean flag) {
+		shellEnable = flag;
+	}
+
+	/** 
+	 * Set the prompt name for QSAdminShell
+	 * Default values = <code>QSAdmin</code>
+	 * @since 1.3.2
+	 */
+	public void setPromptName(String promptName) {
+		if(promptName!=null && promptName.equals("")==false)
+			this.promptName = promptName;
+	}
+	/** 
+	 * Gets the prompt name for QSAdminShell
+	 * @since 1.3.2
+	 */
+	public String getPromptName() {
+		return promptName;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminShell.java b/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminShell.java
new file mode 100644
index 0000000..5be8afc
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/QSAdminShell.java
@@ -0,0 +1,374 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin;
+
+import java.io.*;
+import java.util.*;
+import java.net.*;
+import org.quickserver.net.server.QuickServer;
+import org.quickserver.util.xmlreader.*;
+import org.quickserver.util.MyString;
+import java.util.logging.*;
+
+/**
+ * QSAdmin Command Shell.
+ * This class will auto increase the maxClient by 1 if for QSAdminServer 
+ * maxClient is not equals to -1 and 0 (no other client except shell is allowed).
+ * @author Akshathkumar Shetty
+ * @since 1.3.2
+ */
+public class QSAdminShell extends Thread {
+	private static Logger logger = Logger.getLogger(
+			QSAdminShell.class.getName());
+	
+	private String promptName = "QSAdmin";
+	private String promptPostFix = ":> ";
+	private String prompt = promptName+promptPostFix;
+
+	private String error = "Error: ";
+
+	private BufferedReader in;
+	private String command = "";
+
+	private Socket clientSocket = null;
+	private QuickServer server;
+
+	private InputStream s_in;
+	private OutputStream s_out;
+	private BufferedReader s_br;
+	private BufferedOutputStream s_bo;
+
+	private boolean gotResponse;
+	private boolean multilineResponse;
+	private boolean stop = false;
+
+	private static QSAdminShell qsAdminShell;
+	private static long oldMaxClient = -1;
+	
+
+	public static QSAdminShell getInstance(QuickServer server, String promptName) {
+		if(qsAdminShell==null) {
+			if(server!=null) {
+				qsAdminShell = new QSAdminShell(server, promptName);
+				qsAdminShell.start();
+			} else {
+				return null;
+			}
+		} else {
+			if(server!=null) 
+				qsAdminShell.server = server;
+			if(promptName!=null) 
+				qsAdminShell.promptName = promptName;
+			qsAdminShell.stop = false;
+		}
+		return qsAdminShell;
+	}
+
+	private QSAdminShell(QuickServer server, String promptName) {
+		super("GUIAdminShell");
+		setDaemon(true);
+		this.server = server;
+		if(promptName!=null)
+			setPromptName(promptName);
+		
+		boolean isConsole = true;
+		try {
+			if(System.console()==null) {
+				isConsole = false;
+			}
+		} catch(Throwable e) {
+			//ignore..
+		}
+		
+		if(isConsole) {
+			try {
+				in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+			} catch(UnsupportedEncodingException e) {
+				logger.warning("UTF-8 was not supported: "+e);
+				in = new BufferedReader(new InputStreamReader(System.in));
+			}
+			
+			logger.fine("Starting QSAdmin Shell");
+		} else {
+			System.out.println("QuickServer: System does not have console so not starting QSAdmin Shell!");
+		}
+	}
+
+	public void setPromptName(String name) {
+		if(name==null) return;
+		promptName = name;
+		prompt = promptName+promptPostFix;
+	}
+
+	public String getPromptName() {
+		return promptName; 
+	}
+
+	public void stopShell() throws IOException {
+		stop = true;
+		clientSocket.close();
+	}
+
+	public void run() {
+		if(in==null) {
+			logger.warning("We do not have System.in.. So stopping QSAdminShell.");
+			return;
+		}
+
+		try	{
+			for(int i=0;i<3;i++) {
+				sleep(500);
+				if(server.getQSAdminServer().getServer().isClosed()==false) {
+					connect();
+					break;
+				} 
+				if(i==3) {
+					logger.warning(error+"QSAdminServer is not running!! So stopping QSAdminShell.");
+					return;
+				}
+			}
+		} catch(Exception e) {
+			logger.fine(error+e.getMessage());
+		}
+		while(stop==false) {
+			try	{				
+				print(prompt);
+				command = in.readLine();
+				
+				if(stop) {
+					if(command.trim().equals("")==false)
+						System.out.println("Command ignored since shell was closed.");
+					break;
+				}
+
+				if(command==null) {
+					System.out.println("");
+					logger.severe("User must have forced an exit at shell!");
+					continue;
+				}
+
+				if(command.equals("FullThreadDump")) {
+					tryFullThreadDump();
+					continue;
+				}
+
+				/*
+				if(command.toLowerCase().startsWith("shellto")) {
+					try	{
+						StringTokenizer st = 
+							new StringTokenizer(command, " ");
+						if(st.countTokens()!=3) {
+							throw new Exception("Bad param sent to shellto command!");
+						}
+
+						clientSocket.close();
+						clientSocket = null;
+						st.nextToken();
+						connect(st.nextToken(), 
+							Integer.parseInt(st.nextToken()));
+						continue;
+					} catch(Exception e) {
+						logger.fine(error+e.getMessage());
+					}						
+				} else */
+				if(command.toLowerCase().startsWith("disconnect")) {
+					try	{
+						clientSocket.close();
+						s_bo.close();
+						s_br.close();
+					} catch(Exception er) {
+						println("-ERR "+er);
+					}
+					break;
+				}
+
+				if(command.trim().equals("")==false) {
+					if(clientSocket==null) {
+						if(connect()==false)
+							continue;
+					}
+					sendCommand(command);
+				} else {
+					if(clientSocket==null) {
+						connect();
+					}
+				}
+			} catch(Exception e) {
+				println("-ERR "+e);
+			}
+		}//end while
+		qsAdminShell = null;
+	}
+
+	private void print(String text) {
+		System.out.print(text);
+	}
+
+	private void println(String text) {
+		System.out.println(text);
+	}
+
+	private boolean connect() throws IOException {
+		try {
+			server.getQSAdminServer().getServer().nextClientIsTrusted();
+			int port = server.getQSAdminServer().getServer().getPort();
+			String host = 
+				server.getQSAdminServer().getServer().getBindAddr().getHostAddress();
+			connect(host, port);
+			return true;
+		} catch(Exception e) {
+			println(error+e.getMessage());
+			logger.warning(MyString.getStackTrace(e));
+			if(clientSocket!=null) {
+				try {
+					clientSocket.close();
+				} catch(Exception ignore) {/*ignore*/}
+				clientSocket = null;
+			}
+			return false;
+		}
+	}
+
+	private void connect(String host, int port) throws IOException {
+		clientSocket = new Socket(host, port);
+		clientSocket.setSoTimeout(0);
+		s_in = clientSocket.getInputStream();
+		s_out = clientSocket.getOutputStream();
+		s_br = new BufferedReader(new InputStreamReader(s_in, "UTF-8"));
+		s_bo = new BufferedOutputStream(s_out);
+
+		String temp = null;
+		//skip header
+		temp = s_br.readLine();
+		temp = s_br.readLine();
+		temp = s_br.readLine();
+
+		if(oldMaxClient==-1) {
+			//increase maxClient for self by 1
+			try	{
+				long maxC = -1;
+				sendCommand("get self maxClient", false);
+				temp = s_br.readLine();
+				maxC = Long.parseLong(temp.substring(4));
+				if(maxC!=-1 && maxC!=0) {
+					oldMaxClient = maxC;
+					maxC++;
+					sendCommand("set self maxClient "+maxC, false);
+					temp = s_br.readLine();
+					if(temp.startsWith("+OK")==false) {
+						println(error+"Could not increase max client from QSAdmin : "+s_br);
+					}
+				}
+			} catch(IOException ioe)	{
+				throw ioe;
+			} catch(Exception ignoreEx)	{
+				println(error+ignoreEx.getMessage());
+			}
+		}
+		startSocketListener();
+	}
+
+	private synchronized void sendCommand(String command) throws IOException {
+		sendCommand(command, true);
+	}
+
+	private synchronized void sendCommand(String command, boolean wait) 
+			throws IOException {
+		if(clientSocket==null)
+			println(error+"Not connected yet");
+		command += QuickServer.getNewLine();
+		gotResponse = false;
+		byte d[] = command.getBytes();
+		s_bo.write(d, 0, d.length);
+		s_bo.flush();
+		
+		try	{
+			while(wait==true && gotResponse==false)
+				sleep(100);
+		} catch(InterruptedException e)	{
+			logger.fine(error+e.getMessage());
+		}		
+	}
+
+	public void startSocketListener() {
+		final String pad = "";
+		Thread t = new Thread() {
+			public void run() {
+				String rec = "";
+				while(true) {
+					try {
+						rec =  s_br.readLine();
+					} catch(IOException e) {
+						logger.info("Shell Closed! "+e.getMessage());						
+						break;
+					}
+					if(rec==null) {
+						clientSocket=null;
+						break;
+					}
+
+					if(rec.equals("+OK info follows"))
+						multilineResponse = true;
+					
+					println(pad+rec);
+
+					if(multilineResponse==false)
+						gotResponse=true;
+					else {
+						if(rec.equals(".")) {
+							gotResponse=true;
+							multilineResponse=false;
+						}
+					}
+				} //end of while
+				try	{
+					clientSocket.close();
+					clientSocket = null;	
+				} catch(Exception e) {
+					logger.fine(error+e.getMessage());
+				}
+			}
+		};
+		t.setDaemon(true);
+		t.setName("GUIAdminShell-SocketListener");
+		t.start();
+	}
+
+	public static void tryFullThreadDump() {
+		System.out.println("Trying to get Full Thread Dump @ "+new java.util.Date());
+		String os = System.getProperty("os.name");
+		if(os!=null && os.toLowerCase().startsWith("windows")) {						
+			try {
+				java.awt.Robot robot = new java.awt.Robot();
+				robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
+				robot.keyPress(java.awt.event.KeyEvent.VK_CANCEL);
+				robot.keyRelease(java.awt.event.KeyEvent.VK_CANCEL);
+				robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
+			} catch(Exception ignore) {
+				logger.warning("Could not press: Ctrl+Break"); 
+			}
+		} else {
+			try {
+				java.awt.Robot robot = new java.awt.Robot();
+				robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
+				robot.keyPress(java.awt.event.KeyEvent.VK_BACK_SLASH);
+				robot.keyRelease(java.awt.event.KeyEvent.VK_BACK_SLASH);
+				robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
+			} catch(Exception ignore) {
+				logger.warning("Could not press: Ctrl+\\"); 
+			}
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/CmdConsole.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/CmdConsole.java
new file mode 100644
index 0000000..efc77ec
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/CmdConsole.java
@@ -0,0 +1,251 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import java.io.*;
+
+/**
+ * Command Console
+ * @author Akshathkumar Shetty
+ */
+public class CmdConsole extends JPanel {
+	private static final String NEW_LINE = "\r\n";
+	private QSAdminMain qsadminMain;
+
+	private JPanel centerPanel;
+	private JPanel textPanel;
+	private JPanel sendPanel;
+	private JPanel buttonPanel;
+
+	private JLabel convLabel = new JLabel("Conversation with host");
+	private Border connectedBorder = BorderFactory.createTitledBorder(
+		new EtchedBorder(), "Connected To < NONE >");
+	private JTextArea messagesField = new JTextArea();
+	
+	private JLabel sendLabel = new JLabel("Message");
+	private JTextField sendField = new JTextField();
+	
+	private JButton sendButton = new JButton("Send");
+	private JButton saveButton = new JButton("Save");
+	private JButton clearButton = new JButton("Clear");
+	
+	private GridBagConstraints gbc = new GridBagConstraints();
+
+	public CmdConsole(QSAdminMain qsadminMain) {
+		Container cp = this;
+		this.qsadminMain = qsadminMain;
+
+		textPanel = new JPanel();
+		textPanel.setLayout(new BorderLayout(0,5));
+		textPanel.add(convLabel,BorderLayout.NORTH);
+		messagesField.setEditable(false);
+		messagesField.setBackground(Color.BLACK);
+		messagesField.setForeground(Color.GREEN);
+		JScrollPane jsp = new JScrollPane(messagesField);
+		textPanel.add(jsp);
+		textPanel.setBorder(BorderFactory.createEmptyBorder(3,3,0,3));
+
+		sendPanel = new JPanel();
+		sendPanel.setLayout(new GridBagLayout());
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.EAST;
+		gbc.fill = GridBagConstraints.NONE;
+		sendPanel.add(sendLabel, gbc);
+		gbc.gridx = 1;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		sendField.setEditable(false);
+		sendPanel.add(sendField, gbc);
+		gbc.gridx = 2;
+		gbc.weightx = 0.0;
+		gbc.fill = GridBagConstraints.NONE;
+		sendButton.setEnabled(false);
+		sendButton.setToolTipText("Send text to host");
+		ActionListener sendListener = new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				String msg = sendField.getText();
+				if(!msg.equals(""))
+					sendMessage(msg);
+				else {
+					int value = JOptionPane.showConfirmDialog(
+						CmdConsole.this,  "Send Blank Line ?",
+						"Send Data To Server",
+						JOptionPane.YES_NO_OPTION);
+					if (value == JOptionPane.YES_OPTION)
+						sendMessage(msg);
+				}
+			}
+		};
+		sendButton.addActionListener(sendListener);
+		sendField.addActionListener(sendListener);
+		sendPanel.add(sendButton, gbc);
+		sendPanel.setBorder(
+			new CompoundBorder(
+				BorderFactory.createEmptyBorder(0,0,0,3),
+				BorderFactory.createTitledBorder("Send")));
+
+		buttonPanel = new JPanel();
+		buttonPanel.setLayout(new GridBagLayout());
+		gbc.weighty = 0.0;
+		gbc.weightx = 1.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridheight = 2;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.EAST;
+		gbc.fill = GridBagConstraints.BOTH;
+		buttonPanel.add(sendPanel, gbc);
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridx = 1;
+		gbc.gridheight = 1;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		saveButton.setToolTipText("Save conversation with host to a file");
+		saveButton.setMnemonic('S');
+		ActionListener saveListener = new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				String text = messagesField.getText();
+				if(text.equals("")) {
+					error("Nothing to save","Save to file");
+					return;
+				}
+				String fileName="";
+				JFileChooser chooser = new JFileChooser();
+				chooser.setCurrentDirectory(new File("."));
+				int returnVal = chooser.showSaveDialog(CmdConsole.this);
+				if(returnVal == JFileChooser.APPROVE_OPTION) {
+				   fileName=chooser.getSelectedFile().getAbsolutePath();
+				   try {
+						writeFile(fileName,text);	
+				   }
+				   catch (Exception ioe) {
+					   JOptionPane.showMessageDialog(CmdConsole.this,
+						   ""+ioe.getMessage(),
+						   "Error saving to file..",
+						   JOptionPane.ERROR_MESSAGE);
+				   }				   
+				}				
+			}
+		};
+		saveButton.addActionListener(saveListener);
+		buttonPanel.add(saveButton, gbc);
+		gbc.gridy = 1;
+		clearButton.setToolTipText("Clear conversation with host");
+		clearButton.setMnemonic('C');
+		ActionListener clearListener = new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				messagesField.setText("");
+			}
+		};
+		clearButton.addActionListener(clearListener);
+		buttonPanel.add(clearButton, gbc);
+		buttonPanel.setBorder(BorderFactory.createEmptyBorder(3,0,0,3));
+
+		centerPanel = new JPanel();
+		centerPanel.setLayout(new BorderLayout(0,0));
+		centerPanel.add(buttonPanel,BorderLayout.SOUTH);
+		centerPanel.add(textPanel,BorderLayout.CENTER);
+
+		CompoundBorder cb=new CompoundBorder(
+			BorderFactory.createEmptyBorder(5,10,10,10),
+			connectedBorder);
+		centerPanel.setBorder(cb);
+
+		cp.setLayout(new BorderLayout());
+		cp.add(centerPanel,BorderLayout.CENTER);
+	}
+
+	public void append(String msg) {
+		setSendEdit(qsadminMain.isConnected());
+		messagesField.append(msg+NEW_LINE);
+		messagesField.setCaretPosition(messagesField.getText().length());
+	}
+
+	public void sendMessage(String s) {
+		setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		try	{
+			qsadminMain.sendCommand(s, true);
+			sendField.setText("");
+			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+		} catch (Exception e) {
+			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+			JOptionPane.showMessageDialog(CmdConsole.this,
+				e.getMessage(),"Error Sending Message", 
+				JOptionPane.ERROR_MESSAGE);
+		}
+	}
+
+	private void changeBorder(String ip) {
+		if(ip==null || ip.equals(""))
+			connectedBorder = BorderFactory.createTitledBorder(
+				new EtchedBorder(), "Connected To < NONE >");
+		else
+			connectedBorder = BorderFactory.createTitledBorder(
+				new EtchedBorder(), "Connected To < "+ip+" >");
+		CompoundBorder cb=new CompoundBorder(
+			BorderFactory.createEmptyBorder(5,10,10,10),
+			connectedBorder);
+		centerPanel.setBorder(cb);
+		invalidate();
+		repaint();
+	}
+
+	public void error(String error) {
+		error(error, null);
+	}
+	public void error(String error, String heading) {
+		if(error==null || error.equals(""))
+			return;
+		if(heading==null)
+			heading = "Error";
+		JOptionPane.showMessageDialog(CmdConsole.this,
+			   error, heading, JOptionPane.ERROR_MESSAGE);
+	}
+	
+	public static void writeFile(String fileName, String text) 
+		throws IOException {
+		PrintWriter out = null;
+		try {
+			out = new PrintWriter(
+				new BufferedWriter(new FileWriter(fileName)));
+			out.print(text);	
+		} finally {
+			if(out!=null) out.close();
+		}
+	}
+
+	public void setSendEdit(boolean flag) {
+		sendButton.setEnabled(flag);
+		sendField.setEditable(flag);
+	}
+
+	public void updateConnectionStatus(boolean connected) {
+		if(connected==false) {
+			changeBorder(null);
+		} else {
+			changeBorder(qsadminMain.getIpAddress());
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/EditFieldDocumentListener.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/EditFieldDocumentListener.java
new file mode 100644
index 0000000..c5b631f
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/EditFieldDocumentListener.java
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.event.*;
+import javax.swing.event.*;
+import javax.swing.*;
+
+public class EditFieldDocumentListener implements DocumentListener {
+	JButton saveButton;
+
+	public EditFieldDocumentListener(JButton saveButton) {
+		this.saveButton = saveButton;
+	}
+
+	public void insertUpdate(DocumentEvent e) {
+		if(saveButton!=null) saveButton.setEnabled(true);
+	}
+	public void removeUpdate(DocumentEvent e) {
+		if(saveButton!=null) saveButton.setEnabled(true);
+	}
+	public void changedUpdate(DocumentEvent e) {
+		//System.out.println(">>Change Update");
+		//if(saveButton!=null) saveButton.setEnabled(true);
+	}
+}    
+
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/HeaderPanel.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/HeaderPanel.java
new file mode 100644
index 0000000..17f70c1
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/HeaderPanel.java
@@ -0,0 +1,199 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import java.io.IOException;
+
+import org.quickserver.util.TextFile;
+import org.quickserver.swing.JFrameUtilities;
+import java.util.logging.*;
+
+/**
+ * Control Panel - Header for 
+ * QuickServer Admin GUI - QSAdminGUI
+ * @author Akshathkumar Shetty
+ */
+public class HeaderPanel extends JPanel /*JFrame*/{
+	private static Logger logger = 
+			Logger.getLogger(HeaderPanel.class.getName());
+	private ClassLoader classLoader = getClass().getClassLoader();
+	public ImageIcon logo = new ImageIcon(
+		classLoader.getResource("icons/logo.gif"));
+	public ImageIcon logoAbout = new ImageIcon(
+		classLoader.getResource("icons/logo.png"));
+
+	private JLabel logoLabel;
+	private JPanel leftPanel;
+	private JPanel rightPanel;
+
+	private JLabel productName;
+	private JLabel status;
+	private JButton login;
+
+	private String statusTxt1 = "<html><font style=\"font-size:10pt;color:#535353\"><b> Status : ";
+	private String statusTxt2 = "</b></font>";
+	private String statusMsg = "Not Connected";
+	private GridBagConstraints gbc;
+
+	//--
+	private LoginDialog loginDialog;
+	private final JFrame parentFrame;
+	private QSAdminMain qsadminMain;
+
+	public HeaderPanel(QSAdminMain qsadminMain, JFrame parentFrame) {
+		this.parentFrame = parentFrame;
+		this.qsadminMain = qsadminMain;
+
+		gbc = new GridBagConstraints();
+		logoLabel = new JLabel(logoAbout, JLabel.CENTER);
+		productName = new JLabel("<html><font "+
+			"style=\"font-size:20pt;color:#535353\">"+
+			" <b>QSAdmin GUI</b></font>",JLabel.LEFT);
+		status = new JLabel(statusTxt1+statusMsg+statusTxt2);
+		login = new JButton("<html><font style=\"font-size:10pt;color:#535353\">"+
+			"<b>Login</b>"+"</font>");
+		login.setMnemonic('L');
+		
+		Container cp = this;
+
+		login.addActionListener( new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				handleLoginLogout();
+			}
+		});
+
+		//--- Left Panel
+		leftPanel = new JPanel();
+		leftPanel.setLayout(new GridBagLayout());
+		gbc.insets = new Insets( 2, 2, 2, 2 );
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		leftPanel.add(productName, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.weightx = 0.7;
+		gbc.weighty = 0.7;
+		gbc.gridheight = 1;
+		gbc.anchor = GridBagConstraints.EAST;
+		gbc.fill = GridBagConstraints.BOTH;
+		leftPanel.add(status, gbc);
+
+
+	
+		
+		//--- Right Panel
+		rightPanel = new JPanel();
+		rightPanel.setLayout(new GridBagLayout());
+		gbc.insets = new Insets( 0, 0, 0, 0 );
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.fill = GridBagConstraints.NONE;
+		rightPanel.add(logoLabel, gbc);
+
+		gbc.gridy = 1;
+		gbc.gridx = 0;
+		gbc.weightx = 0.8;
+		gbc.weighty = 0.8;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets( 1, 1, 1, 1 );
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.fill = GridBagConstraints.BOTH;
+		rightPanel.add(login, gbc);
+
+		cp.setLayout(new BorderLayout(0,10));
+		cp.add(rightPanel,BorderLayout.EAST);
+		cp.add(leftPanel,BorderLayout.CENTER);
+	}
+
+	public void setStatus(String msg) {
+		statusMsg = msg;
+		status.setText(statusTxt1+statusMsg+statusTxt2);
+	}
+
+	public String getStatus() {
+		return statusMsg;
+	}
+
+	public void setLoginText() {
+		login.setText("<html><font style=\"font-size:10pt;color:#535353\">"+
+			"<b>Login</b>"+"</font>");
+	}
+	public void setLogoutText() {
+		login.setText("<html><font style=\"font-size:10pt;color:#535353\">"+
+			"<b>Logout</b>"+"</font>");
+	}
+
+	public void handleLoginLogout() {
+		if(qsadminMain.isConnected()==false) {
+			if(loginDialog==null) {
+				loginDialog = new LoginDialog(parentFrame);
+			}
+			loginDialog.show();
+			if(loginDialog.isOk()==true) {
+				Thread performer = new Thread(new Runnable() {
+					public void run() {
+						String r[] = loginDialog.getValues();
+						try {
+							boolean flag = qsadminMain.doLogin(r[0], 
+								Integer.parseInt(r[1]), r[2], r[3]);
+							if(flag==true) {
+								setLogoutText();
+							} else {
+								setLoginText();
+								//recall the login dialog
+								handleLoginLogout();
+							}
+						} catch(Exception ex) {
+							logger.warning("Error logging in : "+ex);
+							setLoginText();
+						}
+					}
+				}, "QsAdminGUI-LoginThread");
+				performer.start();
+			}
+		} else {
+			Thread performer = new Thread(new Runnable() {
+				public void run() {
+					try {
+						qsadminMain.doLogout();
+						setLoginText();
+					} catch(Exception ex) {
+						logger.warning("Error logging in : "+ex);
+					}
+				}
+			}, "QsAdminGUI-LogoutThread");
+			performer.start();
+		}
+	}
+}
+
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/LoginDialog.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/LoginDialog.java
new file mode 100644
index 0000000..8cd16a9
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/LoginDialog.java
@@ -0,0 +1,287 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import java.io.IOException;
+
+import org.quickserver.util.TextFile;
+import org.quickserver.swing.JFrameUtilities;
+
+/**
+ * Login Dialog
+ * QuickServer Admin GUI - QSAdminGUI
+ * @author Akshathkumar Shetty
+ */
+public class LoginDialog extends JDialog /*JFrame*/{
+	private JPanel topPanel;
+	private JPanel ipPanel;
+	private JPanel authPanel;
+	private JPanel buttonPanel;
+
+	private JLabel productName;
+	private JLabel ipLabel;
+	private JTextField ipField;
+	private JLabel portLabel;
+	private JTextField portField;
+	private JLabel loginLabel;
+	private JTextField loginField;
+	private JLabel passwordLabel;
+	private JPasswordField passwordField;
+	private JButton loginButton;
+	private JButton cancelButton;
+
+	private String statusTxt1 = "<html><font style=\"font-size:15pt;color:#535353\"><b>";
+	private String statusTxt2 = "</b></font>";
+	private GridBagConstraints gbc;
+
+	//for storing the values
+	private String values[] = new String[4];
+	private boolean isOk = false;
+
+	public LoginDialog(Frame parent) {
+		super(parent, "QSAdmin Login");
+		gbc = new GridBagConstraints();
+		productName = new JLabel(statusTxt1+
+			"QSAdmin Login"+statusTxt2,JLabel.CENTER);
+
+		ipLabel = new JLabel("IP Address");
+		ipField = new JTextField("127.0.0.1");
+		portLabel = new JLabel("Port");
+		portField = new JTextField("9876");
+
+		loginLabel = new JLabel("Login");
+		loginField = new JTextField("Admin");
+		passwordLabel = new JLabel("Password");
+		passwordField = new JPasswordField("QsAdm1n");
+
+		loginButton = new JButton("<html><font style=\"font-size:10pt;color:#535353\">"+
+			"<b>Login</b>"+"</font>");
+		loginButton.setMnemonic('L');
+		cancelButton = new JButton("<html><font style=\"font-size:10pt;color:#535353\">"+
+			"<b>Cancel</b>"+"</font>");
+		cancelButton.setMnemonic('C');
+		cancelButton.addActionListener( new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				hide();
+			}
+		});
+		
+		//--- Action
+		ipField.addActionListener(new ActionListener() {
+				public void actionPerformed(ActionEvent e) {
+					portField.requestFocus();
+				}
+			});
+		portField.addActionListener(new ActionListener() {
+				public void actionPerformed(ActionEvent e) {
+					loginField.requestFocus();
+				}
+			});
+		loginField.addActionListener(new ActionListener() {
+				public void actionPerformed(ActionEvent e) {
+					passwordField.requestFocus();
+				}
+			});
+
+		ActionListener loginAl = new ActionListener() {
+			public void actionPerformed(ActionEvent e) {		
+				isOk = false;
+				if(ipField.getText().equals("")) {
+					showError("Blank IP Address");
+					return;
+				}
+				if(portField.getText().equals("")) {
+					showError("Blank Port Number");
+					return;
+				} else {
+					try {
+						Integer.parseInt(portField.getText());
+					} catch(Exception ex) {
+						showError("Bad Port Number.");
+						return;
+					}
+				}
+				if(loginField.getText().equals("")) {
+					showError("Blank Login");
+					return;
+				}
+				char p[] = passwordField.getPassword();
+				if(p==null || p.length==0) {
+					showError("Blank password");
+					return;
+				}
+				p = null;
+				hide();
+				isOk = true;					
+			}
+		};
+
+		loginButton.addActionListener(loginAl);
+		passwordField.addActionListener(loginAl);
+
+		cancelButton.addActionListener( new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				hide();
+				isOk = false;
+			}
+		});
+		//---- Action
+
+		Container cp = getContentPane();
+
+		//--- Top Panel
+		topPanel = new JPanel();
+		topPanel.setLayout(new GridBagLayout());
+		gbc.insets = new Insets( 2, 2, 2, 2 );
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.fill = GridBagConstraints.NONE;
+		topPanel.add(productName, gbc);
+
+		//-- IP Panel
+		ipPanel = new JPanel();
+		ipPanel.setLayout(new GridBagLayout());
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		ipPanel.add(ipLabel, gbc);
+
+		gbc.gridx = 1;
+		gbc.gridy = 0;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.BOTH;
+		ipPanel.add(ipField, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.weightx = 0.0;
+		gbc.fill = GridBagConstraints.NONE;
+		ipPanel.add(portLabel, gbc);
+
+		gbc.gridx = 1;
+		gbc.gridy = 1;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.BOTH;
+		ipPanel.add(portField, gbc);
+		ipPanel.setBorder(BorderFactory.createTitledBorder(
+			new EtchedBorder(),"Location"));
+
+		//-- Login Panel
+		authPanel = new JPanel();
+		authPanel.setLayout(new GridBagLayout());
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		authPanel.add(loginLabel, gbc);
+
+		gbc.gridx = 1;
+		gbc.gridy = 0;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.BOTH;
+		authPanel.add(loginField, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.weightx = 0.0;
+		gbc.fill = GridBagConstraints.NONE;
+		authPanel.add(passwordLabel, gbc);
+
+		gbc.gridx = 1;
+		gbc.gridy = 1;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.BOTH;
+		authPanel.add(passwordField, gbc);
+		authPanel.setBorder(BorderFactory.createTitledBorder(
+			new EtchedBorder(),"Authentication"));
+
+		//-- buttonPanel
+		buttonPanel = new JPanel();
+		buttonPanel.setLayout(new GridBagLayout());
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.fill = GridBagConstraints.NONE;
+		buttonPanel.add(loginButton, gbc);
+
+		gbc.gridx = 1;
+		buttonPanel.add(cancelButton, gbc);
+
+		cp.setLayout(new GridBagLayout());
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.weightx = 1.0;
+		gbc.weighty = 1.0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		cp.add(topPanel,gbc);
+		gbc.fill = GridBagConstraints.BOTH;
+		gbc.gridy = 1;
+		cp.add(ipPanel,gbc);
+		gbc.fill = GridBagConstraints.BOTH;
+		gbc.gridy = 2;
+		cp.add(authPanel,gbc);
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		gbc.gridy = 3;
+		cp.add(buttonPanel,gbc);
+		pack();
+		setSize(240,250);
+		setResizable(false);
+		setModal(true);
+		JFrameUtilities.centerWindow(this);
+	}
+
+	private void showError(String msg) {
+		JOptionPane.showMessageDialog(LoginDialog.this,
+			msg, "Error", JOptionPane.ERROR_MESSAGE);
+	}
+
+	public String[] getValues(){
+		values[0] = ipField.getText();
+		values[1] = portField.getText();
+		values[2] = loginField.getText();
+		values[3] = new String(passwordField.getPassword());
+		return values;
+	}
+
+	public boolean isOk(){
+		return isOk;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/MainCommandPanel.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/MainCommandPanel.java
new file mode 100644
index 0000000..fe99ebc
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/MainCommandPanel.java
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.*;
+
+/**
+ * Main CommandPanel fro
+ * QuickServer Admin GUI - QSAdminGUI
+ * @author Akshathkumar Shetty
+ */
+public class MainCommandPanel extends JPanel {
+	private QSAdminMain qsadminMain;
+	private JPanel targetPanel;
+	private JPanel commandPanel;
+
+	private JLabel targetLabel;
+	private JRadioButton serverButton, selfButton;
+
+	//---
+	private String target = "server";
+	private SimpleCommandSet sms;
+
+	private GridBagConstraints gbc;
+
+	public MainCommandPanel(final QSAdminMain qsadminMain) {
+		Container cp = this;
+		this.qsadminMain = qsadminMain;
+		//target panel
+		targetPanel = new JPanel();
+		targetLabel = new JLabel("<html><font "+
+			"style=\"font-size:10pt;color:#535353\">"+
+			" <b>Target : </b></font>",JLabel.LEFT);
+		serverButton = new JRadioButton("Server");
+		serverButton.setMnemonic(KeyEvent.VK_S);
+		serverButton.setActionCommand("server");
+		serverButton.setSelected(true);
+
+		selfButton = new JRadioButton("Admin Server");
+		selfButton.setMnemonic(KeyEvent.VK_A);
+		selfButton.setActionCommand("self");
+		
+		ButtonGroup group = new ButtonGroup();
+		group.add(serverButton);
+		group.add(selfButton);
+		class RadioListener implements ActionListener{
+			public void actionPerformed(ActionEvent e) {
+				setTarget(e.getActionCommand());
+			}
+		}
+
+		RadioListener rListener = new RadioListener();
+		serverButton.addActionListener(rListener);
+		selfButton.addActionListener(rListener);
+
+		targetPanel.add(targetLabel);
+		targetPanel.add(serverButton);
+		targetPanel.add(selfButton);
+		
+
+		sms = SimpleCommandSet.getSimpleCommands();
+		java.util.List list = sms.getList();
+		//Map map = sms.getMap();
+		commandPanel = new JPanel();
+		commandPanel.setLayout(new GridLayout((int)list.size(), 1,2,2));
+		Iterator cmdIt = list.iterator();
+		SimpleCommand sm = null;
+		JButton cmdButton = null;
+		while(cmdIt.hasNext()) {
+			sm = (SimpleCommand)cmdIt.next();
+			StringBuilder sf  = new StringBuilder(sm.getName());
+			if(sf.length()<15) {
+				sf.append(' ');
+				sf.insert(0, ' ');
+			}
+			cmdButton = new JButton("<html><font style=\"font-size:10pt;color:#008080\"><b>"+
+			sf.toString()+"</b></font>");
+			cmdButton.setToolTipText(sm.getDesc());
+			cmdButton.addActionListener(getSimpleAction(sm));
+			commandPanel.add(cmdButton);
+		} //end of while
+
+		//--- layout main panel
+		cp.setLayout(new BorderLayout(0,10));
+		cp.add(targetPanel,BorderLayout.NORTH);
+		JScrollPane commandScrollPane = new JScrollPane(commandPanel);
+		cp.add(commandScrollPane,BorderLayout.CENTER);
+
+		/*setBorder(new CompoundBorder(
+			BorderFactory.createEmptyBorder(1,1,1,1),
+			BorderFactory.createTitledBorder("Simple Commands")
+			));
+		*/
+		//setPreferredSize(new java.awt.Dimension(100,200));
+	}
+
+	public String getTarget() {
+		return target;
+	}
+	private void setTarget(String target) {
+		this.target = target;
+	}
+
+	private ActionListener getSimpleAction(SimpleCommand cm) {
+		return new SimpleActionListener(qsadminMain, cm, 
+			MainCommandPanel.this);
+	}
+
+	public void updateConnectionStatus(boolean connected) {
+		serverButton.setEnabled(connected);
+		selfButton.setEnabled(connected);
+		commandPanel.setEnabled(connected);
+	}
+}
+
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/PluginPanel.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/PluginPanel.java
new file mode 100644
index 0000000..bc74651
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/PluginPanel.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+/**
+ * PluginPanel is a template class for plug-ins written for
+ * QuickServer Admin GUI - QSAdminGUI.
+ * <p>
+ * The plug-in class implementing this interface must also extend 
+ * <code>javax.swing.JPanel</code>
+ * class. The plug-in class must be made into a jar and plugin.xml needs to be 
+ * written that describing the plug-in to QSAdminGUI. A sample xml is below 
+ * <br>&nbsp;<br><b><code>
+<font color="#808080">&nbsp;</font><font color="#000000">&lt;qsadmin-plugin&gt;</font><br>
+
+<font color="#808080">&nbsp;</font><font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">&lt;name&gt;Stats&lt;/name&gt;</font><br>
+
+<font color="#808080">&nbsp;</font><font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">&lt;desc&gt;Server&nbsp;Status&nbsp;Panel&lt;/desc&gt;</font><br>
+
+<font color="#808080">&nbsp;</font><font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">&lt;type&gt;javax.swing.JPanel&lt;/type&gt;</font><br>
+
+<font color="#808080">&nbsp;</font><font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">&lt;main-class</font><font color="#000000">&gt;org.quickserver.net.qsadmin.plugin.stats.StatsPanel&lt;/main-class</font><font color="#000000">&gt;</font><br>
+
+<font color="#808080">&nbsp;</font><font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">&lt;active&gt;yes&lt;/active&gt;</font><br>
+
+<font color="#808080">&nbsp;</font><font color="#000000">&lt;/qsadmin-plugin&gt;</font>
+</code>
+ * </b><br>&nbsp;<br> Now both the jar and the plugin.xml file needs to be places in a 
+ * directory by the name of the plug-in and placed in the plugin folder of
+ * QuickServer installation.
+ * </p>
+ * @see org.quickserver.util.xmlreader.QSAdminPluginConfig
+ * @author Akshathkumar Shetty
+ */
+public interface PluginPanel {
+	/** This method is the first method called after plugin is instanced. */
+	public void setQSAdminMain(final QSAdminMain qsAdminMain);
+	/** This method is called before it is added to QSAdminGUI. */
+	public void init();
+
+	/** This method is called when connection status changes in QSAdminGUI. */
+	public void updateConnectionStatus(boolean connected);
+
+	/** This method is called when the tab where plugin is loaded is activated */
+	public void activated();
+
+	/** This method is called when the tab where plugin is loaded is deactivated */
+	public void deactivated();
+
+	/** This method indicate if the plugin is in active or non-active state */
+	public boolean isActivated();
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/Propertie.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/Propertie.java
new file mode 100644
index 0000000..b3b116d
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/Propertie.java
@@ -0,0 +1,345 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.*;
+import org.quickserver.util.MyString;
+
+/**
+ * A Simple class that Stores information about QSAdmin Properties
+ * @author Akshathkumar Shetty
+ */
+public class Propertie {
+	private String name;
+	private String target = "server";
+	private String command;
+	private boolean get = false;
+	private boolean set = false;
+	private String type = "edit";
+	private String select;
+	private String desc;
+	private String targetNeeded = "yes";
+	private String version = "1.3";//when AdminUI was added
+	
+	//gui components
+	private JLabel namelabel;
+	private JTextField editField;
+	private JComboBox selectList;
+	private JButton saveButton;
+
+	public String getGetCommand() {
+		if(targetNeeded.equals("yes"))
+			return "get "+target+" "+command;
+		else
+			return "get "+command;
+	}
+	public String getSetCommand(String value) {
+		if(targetNeeded.equals("yes"))
+			return "set "+target+" "+command+" "+value;
+		else
+			return "set "+command+" "+value;
+
+	}
+
+	public String getName(){
+		return name;
+	}
+	public void setName(String name) {
+		if(name!=null && name.equals("")==false)
+			this.name = name;
+	}
+
+	public String getTarget() {
+		return target;
+	}
+	public void setTarget(String target) {
+		if(target!=null && target.equals("")==false)
+			this.target = target;
+	}
+
+	public String getCommand() {
+		return command;
+	}
+	public void setCommand(String command) {
+		if(command!=null && command.equals("")==false)
+			this.command = command;
+	}
+
+	public void setGet(String getValue) {
+		if(getValue!=null && getValue.toLowerCase().equals("yes"))
+			get = true;
+		else
+			get = false;
+	}
+	public boolean isGet() {
+		return get;
+	}
+
+	public void setSet(String setValue) {
+		if(setValue!=null && setValue.toLowerCase().equals("yes"))
+			set = true;
+		else
+			set = false;
+	}
+	public boolean isSet() {
+		return set;
+	}
+	
+	public String getType() {
+		return type;
+	}
+	public void setType(String type) {
+		if(type!=null && type.equals("")==false)
+			this.type = type;
+	}
+
+	public String getDesc() {
+		return desc;
+	}
+	public void setDesc(String desc) {
+		if(desc!=null && desc.equals("")==false)
+			this.desc = desc;
+	}
+
+	public String getSelect() {
+		return select;
+	}
+	public void setSelect(String select) {
+		if(select!=null && select.equals("")==false)
+			this.select = select;
+	}
+
+	public String getTargetNeeded() {
+		return targetNeeded;
+	}
+	public void setTargetNeeded(String targetNeeded) {
+		this.targetNeeded = targetNeeded.toLowerCase();
+	}
+
+	public String getVersion() {
+		return version;
+	}
+	public float getVersionNo() {
+		String ver = version;
+		float version = 0;
+		int i = ver.indexOf(" "); //check if beta
+		if(i == -1)
+			i = ver.length();
+		ver = ver.substring(0, i);
+
+		i = ver.indexOf("."); //check for sub versions
+		if(i!=-1) {
+			int j = ver.indexOf(".", i);
+			if(j!=-1) {
+				ver = ver.substring(0, i)+"."+
+					MyString.replaceAll(ver.substring(i+1), ".", "");
+			}
+		}
+
+		try	{
+			version = Float.parseFloat(ver);	
+		} catch(NumberFormatException e) {
+			//ignoring
+		}		
+		return version;
+	}
+	public void setVersion(String version) {
+		if(version!=null && version.equals("")==false)
+			this.version = version.toLowerCase();
+	}
+
+	public String toXML() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("<propertie>\n");
+		sb.append("\t<name>").append(name).append("</name>\n");
+		sb.append("\t<command>").append(command).append("</command>\n");
+		if(get==true)
+			sb.append("\t<get>yes</get>\n");
+		else
+			sb.append("\t<get>no</get>\n");
+		if(set==true)
+			sb.append("\t<set>yes</set>\n");
+		else
+			sb.append("\t<set>no</set>\n");
+		sb.append("\t<type>").append(type).append("</type>\n");
+		if(select!=null)
+			sb.append("\t<select>").append(select).append("</select>\n");
+		if(desc!=null)
+			sb.append("\t<desc>").append(desc).append("</desc>\n");
+		sb.append("\t<version>").append(version).append("</version>\n");
+		if(targetNeeded!=null && targetNeeded.equals("yes"))
+			sb.append("\t<target-needed>yes</target-needed>\n");
+		else
+			sb.append("\t<target-needed>no</target-needed>\n");
+		sb.append("</propertie>\n");
+		return sb.toString();
+	}
+
+	//--- gui methods---
+	public void load(PropertiePanel pp, QSAdminMain qsadminMain) {
+		setTarget(pp.getTarget());
+		String temp = null;
+		if(isGet()==false) {
+			temp = "+OK  ";
+		} else {
+			try {
+				temp = qsadminMain.sendCommunicationSilent(getGetCommand(), 
+					false, false);
+			} catch(Exception e) {
+				temp = "Could not get parameter : "+e.getMessage();
+			}
+		}
+
+		if(temp==null) return;
+		
+		boolean got = false;
+		if(temp.startsWith("+OK"))
+			got = true;
+		temp = temp.substring(temp.indexOf(" ")+1);
+		//temp = temp.trim();
+
+		if(getType().equals("edit")) {
+			editField.setText(temp);
+			if(got==true) {
+				editField.setEnabled(true);
+				editField.setEditable(isSet());
+			}
+		} else if(getType().equals("select")) {
+			selectList.setSelectedItem(temp);
+			if(got==true) {
+				selectList.setEnabled(true);
+			}
+		}
+	}
+
+	public void addToPanel(Container cp, GridBagConstraints gbc, 
+			PropertiePanel pp, QSAdminMain qsadminMain) {
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridy++;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 1;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		
+		String temp = getType().toLowerCase();
+		if(temp==null) temp = "edit";
+
+		//space
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		cp.add(Box.createRigidArea(new Dimension(10,10)), gbc);
+
+		//label
+		gbc.gridx++;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		namelabel = new JLabel(getName());
+		namelabel.setToolTipText(getDesc());
+		cp.add(namelabel, gbc);
+
+		//space
+		gbc.gridx++;
+		gbc.weightx = 0.0;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		cp.add(Box.createRigidArea(new Dimension(10,10)), gbc);
+		
+
+		//value
+		gbc.gridx++;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		if(temp.equals("edit")) {
+			editField = new JTextField();
+			editField.setEnabled(false);
+			editField.setToolTipText(getDesc());
+			cp.add(editField, gbc);
+		} else if(temp.equals("select")) {
+			temp = getSelect();
+			StringTokenizer st = new StringTokenizer(temp,"|");
+			String[] valStrings = new String[st.countTokens()];
+			for(int i=0;st.hasMoreTokens();i++) {
+				valStrings[i]=st.nextToken();
+			}
+			selectList = new JComboBox(valStrings);
+			selectList.setMaximumRowCount(3);
+			selectList.setEditable(false);
+			selectList.setEnabled(false);
+			cp.add(selectList, gbc);
+		}
+		
+		//space
+		gbc.weightx = 0.0;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		gbc.gridx++;
+		cp.add(Box.createRigidArea(new Dimension(10,10)), gbc);
+
+		//control
+		gbc.gridx++;
+		gbc.weightx = 0.5;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		if(isSet()==true) {
+			saveButton = new JButton("Save");
+			saveButton.setEnabled(false);
+			saveButton.addActionListener(
+				getSaveAction(qsadminMain, Propertie.this));
+			cp.add(saveButton, gbc);
+		} else {
+			cp.add(new JLabel(), gbc);
+		}
+
+		//extra space
+		gbc.gridx++;
+		gbc.weightx = 0.0;
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.NONE;
+		cp.add(Box.createRigidArea(new Dimension(10,10)), gbc);
+
+		if(temp.equals("edit")) {
+			editField.getDocument().addDocumentListener(
+				new EditFieldDocumentListener(saveButton));
+		} else {
+			selectList.addItemListener(new ItemListener() {
+				public void itemStateChanged(ItemEvent e) {
+					saveButton.setEnabled(true);
+				}
+			});
+		}
+	}
+
+	public JTextField getEditField() {
+		return editField;
+	}
+
+	public JComboBox getComboBox() {
+		return selectList;
+	}
+
+	public JButton getSaveButton() {
+		return saveButton;
+	}
+
+	private ActionListener getSaveAction(QSAdminMain qsadminMain, 
+		Propertie propertie) {
+		return new SaveActionListener(qsadminMain, propertie);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/PropertiePanel.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/PropertiePanel.java
new file mode 100644
index 0000000..1c55271
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/PropertiePanel.java
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import java.util.*;
+
+import org.quickserver.util.TextFile;
+import org.quickserver.swing.JFrameUtilities;
+
+/**
+ * PropertiePanel for
+ * QuickServer Admin GUI - QSAdminGUI
+ * @author Akshathkumar Shetty
+ */
+public class PropertiePanel extends JPanel {
+	private QSAdminMain qsadminMain;
+	private JPanel targetPanel;
+	private JPanel commandPanel;
+
+	private JLabel targetLabel;
+	private JRadioButton serverButton, selfButton;
+	private JButton reloadButton;
+	private ButtonGroup group;
+
+	private PropertieSet propertieSet;
+
+	//---
+	private String target = "server";
+
+	private GridBagConstraints gbc;
+
+	public PropertiePanel(final QSAdminMain qsadminMain) {
+		Container cp = this;
+		this.qsadminMain = qsadminMain;
+		//target panel
+		targetPanel = new JPanel();
+		targetLabel = new JLabel("<html><font "+
+			"style=\"font-size:10pt;color:#535353\">"+
+			" <b>Target : </b></font>",JLabel.LEFT);
+		serverButton = new JRadioButton("Server");
+		serverButton.setMnemonic(KeyEvent.VK_S);
+		serverButton.setActionCommand("server");
+		serverButton.setSelected(true);
+
+		selfButton = new JRadioButton("Admin Server");
+		selfButton.setMnemonic(KeyEvent.VK_A);
+		selfButton.setActionCommand("self");
+		
+		group = new ButtonGroup();
+		group.add(serverButton);
+		group.add(selfButton);
+		class RadioListener implements ActionListener{
+			public void actionPerformed(ActionEvent e) {
+				setTarget(e.getActionCommand());
+			}
+		}
+
+		RadioListener rListener = new RadioListener();
+		serverButton.addActionListener(rListener);
+		selfButton.addActionListener(rListener);
+
+		propertieSet = PropertieSet.getPropertieSet();
+		final java.util.List list = propertieSet.getList();
+		//Map map = sms.getMap();
+
+		reloadButton = new JButton("Reload Properties For the Target");
+		class ReloadListener implements ActionListener{
+			public void actionPerformed(ActionEvent e) {
+				Thread performer = new Thread(new Runnable() {
+					public void run() {
+						Iterator cmdIt = list.iterator();
+						Propertie propertie = null;
+						while(cmdIt.hasNext()) {
+							propertie = (Propertie)cmdIt.next();
+							propertie.load(PropertiePanel.this, qsadminMain);
+						} //end of while
+						updateConnectionStatus(true);
+					}
+				}, "QsAdminGUI-ReloadThread");
+				performer.start();
+			}
+		}
+		ReloadListener reloadListener = new ReloadListener();
+		reloadButton.addActionListener(reloadListener);
+
+		targetPanel.add(targetLabel);
+		targetPanel.add(serverButton);
+		targetPanel.add(selfButton);
+		targetPanel.add(reloadButton);
+		
+		
+		commandPanel = new JPanel();
+		GridBagConstraints gbc = new GridBagConstraints();
+		commandPanel.setLayout(new GridBagLayout());
+		gbc.insets = new Insets( 0, 0, 0, 0 );
+		Iterator cmdIt = list.iterator();
+		Propertie propertie = null;
+		while(cmdIt.hasNext()) {
+			propertie = (Propertie)cmdIt.next();
+			propertie.addToPanel(commandPanel, gbc, this, qsadminMain);
+		} //end of while
+
+
+		//--- layout main panel
+		cp.setLayout(new BorderLayout(0,10));
+		cp.add(targetPanel,BorderLayout.NORTH);
+		cp.add(commandPanel,BorderLayout.CENTER);
+
+	}
+
+	public String getTarget() {
+		return target;
+	}
+	private void setTarget(String target) {
+		this.target = target;
+	}
+
+	public void updateConnectionStatus(boolean connected) {
+		java.util.List list = propertieSet.getList();
+		Iterator cmdIt = list.iterator();
+		Propertie propertie = null;
+		while(cmdIt.hasNext()) {
+			propertie = (Propertie)cmdIt.next();
+			/*
+			if(qsadminMain.isConnected()==false) {
+				//remove all values
+				if(propertie.getType().equals("edit")) {
+					propertie.getEditField().setText("");
+					propertie.getEditField().setEnabled(false);
+				} else if(propertie.getType().equals("edit")) {
+					propertie.getComboBox().setSelectedItem("");
+					propertie.getComboBox().setEnabled(false);
+				}
+			}
+			*/
+			if(propertie.getSaveButton()!=null)
+				propertie.getSaveButton().setEnabled(false);
+		}//end of while
+				
+		reloadButton.setEnabled(connected);
+		serverButton.setEnabled(connected);
+		selfButton.setEnabled(connected);
+	}
+}
+
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/PropertieSet.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/PropertieSet.java
new file mode 100644
index 0000000..7f1bf1e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/PropertieSet.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.util.*;
+import java.net.URL;
+import java.io.InputStream;
+import org.quickserver.util.MyString;
+import java.util.logging.*;
+import org.apache.commons.digester3.Digester;
+
+/**
+ * A Simple class that Stores PropertieSet
+ * @author Akshathkumar Shetty
+ */
+public class PropertieSet {
+	private static Logger logger = Logger.getLogger(
+			PropertieSet.class.getName());
+
+	//stores commands from xml file
+	private List list;
+	private Map map;
+
+	public PropertieSet() {
+		list = new ArrayList();
+		map = new HashMap();
+	}
+
+	public List getList() {
+		return list;
+	}
+	public Map getMap() {
+		return map;
+	}
+	
+	public void addCommand(Propertie p) {
+		list.add(p);
+		map.put(p.getCommand(), p);
+	}
+
+	/* Returns SimpleCommandSet containing simple commands */
+	public static PropertieSet getPropertieSet() {
+		PropertieSet ps = null;
+		try {
+	        Digester digester = new Digester();
+		    digester.setValidating(false);
+			//digester.setNamespaceAware(true);
+			//String xsd = "" + new File("quickserver_config.xsd").toURI();
+			//digester.setSchema(xsd);
+
+			//nested QSAdminServer tag
+			String mainTag = "propertie-set";
+			String subTag = "propertie";
+			digester.addObjectCreate(mainTag, PropertieSet.class);
+			digester.addObjectCreate(mainTag+"/"+subTag, Propertie.class);
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/name");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/command");
+			digester.addCallMethod(mainTag+"/"+subTag+"/get", "setGet",0);
+			digester.addCallMethod(mainTag+"/"+subTag+"/set", "setSet",0);
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/type");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/desc");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/select");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/target-needed", "targetNeeded");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/version");
+			digester.addSetNext(mainTag+"/"+subTag,"addCommand");
+
+			URL configFile = 
+				PropertieSet.class.getResource("/org/quickserver/net/qsadmin/gui/conf/PropertieSet.xml");
+			if(configFile==null)
+				throw new RuntimeException("XML File not found : "+"PropertieSet.xml");
+
+			InputStream input = configFile.openStream();			
+			logger.fine("Loading command config from xml file : " + input);
+			ps = (PropertieSet) digester.parse(input);			
+		} catch(Exception e) {
+			logger.severe("Could not init from xml file : " +e);
+			logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
+		}
+		return ps;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdmin.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdmin.java
new file mode 100644
index 0000000..aac2f88
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdmin.java
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+public class QSAdmin {
+	public static void main(final String args[]) {
+		SplashScreen splash = new SplashScreen();
+
+		if(args!=null && args.length==1)
+			QSAdminGUI.setPluginDir(args[0]);
+		
+		QSAdminGUI.showGUI(args, splash);			
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdminGUI.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdminGUI.java
new file mode 100644
index 0000000..ebfbc30
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdminGUI.java
@@ -0,0 +1,328 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import java.io.IOException;
+
+import org.quickserver.util.*;
+import java.util.logging.*;
+import org.quickserver.swing.JFrameUtilities;
+//--v1.3.2
+import java.io.*;
+import java.util.*;
+import org.quickserver.util.io.*;
+import org.quickserver.util.*;
+import org.quickserver.util.xmlreader.QSAdminPluginConfig;
+import org.quickserver.util.xmlreader.PluginConfigReader;
+
+
+/**
+ * QSAdminGUI - Control Panel for 
+ * QuickServer Admin GUI - QSAdminGUI
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class QSAdminGUI extends JPanel /*JFrame*/{
+	private static Logger logger = Logger.getLogger(
+			QSAdminGUI.class.getName());
+
+	private static QSAdminMain qsadminMain = null;
+	private static String pluginDir = "./../plugin";
+
+	private ClassLoader classLoader = getClass().getClassLoader();
+	public ImageIcon logo = new ImageIcon(
+		classLoader.getResource("icons/logo.gif"));
+	public ImageIcon logoAbout = new ImageIcon(
+		classLoader.getResource("icons/logo.png"));
+	public ImageIcon ball = new ImageIcon(
+		classLoader.getResource("icons/ball.gif"));
+
+	private HeaderPanel headerPanel;
+	private MainCommandPanel mainCommandPanel;
+	private CmdConsole cmdConsole;
+	private PropertiePanel propertiePanel;
+	//private StatsPanel statsPanel;
+
+	private JTabbedPane tabbedPane;
+	private JFrame parentFrame;
+
+	final HashMap pluginPanelMap = new HashMap();
+
+	//--v1.3.2
+	private ArrayList plugins = new ArrayList();
+
+	private JMenu mainMenu, helpMenu;
+    private JMenuBar jMenuBar;
+	private JMenuItem loginMenuItem, exitMenuItem,  aboutMenuItem;
+	
+
+	/**
+	 * Logs the interaction,
+	 * Type can be 
+	 *	S - Server Sent
+	 *	C - Client Sent
+	 */
+	public void logComand(String command, char type) {
+		logger.info("For["+type+"] "+command);
+	}
+
+	/**
+	 * Displays the QSAdminGUi with in a JFrame.
+	 */
+	public static void showGUI(String args[], final SplashScreen splash) {		
+		java.awt.EventQueue.invokeLater(new Runnable() {
+            public void run() {
+				try {
+					UIManager.setLookAndFeel(
+						"net.sourceforge.mlf.metouia.MetouiaLookAndFeel");
+				} catch(Exception e) {
+					try {
+						UIManager.setLookAndFeel(
+							UIManager.getSystemLookAndFeelClassName());
+					} catch(Exception ee) {}
+				}
+
+				qsadminMain = new QSAdminMain();
+
+				JFrame frame = new JFrame("QSAdmin GUI");
+				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+				QSAdminGUI qsAdminGUI = new QSAdminGUI(qsadminMain, frame);
+				qsAdminGUI.updateConnectionStatus(false);
+				frame.getContentPane().add(qsAdminGUI);
+				frame.pack();
+				frame.setSize(700, 450);
+				frame.setIconImage(qsAdminGUI.logo.getImage());
+				JFrameUtilities.centerWindow(frame);
+				frame.setVisible(true);
+				if(splash!=null) splash.kill();				
+			}
+		});
+	}
+
+	public QSAdminGUI(QSAdminMain qsadminMain, JFrame parentFrame) {
+		this.parentFrame = parentFrame;
+		Container cp = this;
+		qsadminMain.setGUI(this);
+		cp.setLayout(new BorderLayout(5,5));
+		headerPanel = new HeaderPanel(qsadminMain, parentFrame);
+		mainCommandPanel = new MainCommandPanel(qsadminMain);
+		cmdConsole = new CmdConsole(qsadminMain);
+		propertiePanel = new PropertiePanel(qsadminMain);
+
+		if(headerPanel==null || mainCommandPanel==null ||
+			cmdConsole==null || propertiePanel==null) {
+			throw new RuntimeException("Loading of one of gui component failed.");
+		}
+		
+		headerPanel.setBorder(BorderFactory.createEmptyBorder(0,5,0,5));
+		cp.add(headerPanel, BorderLayout.NORTH);
+		JScrollPane propertieScrollPane = new JScrollPane(propertiePanel);
+		//JScrollPane commandScrollPane = new JScrollPane(mainCommandPanel);
+		JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 
+				true, mainCommandPanel, cmdConsole);
+		splitPane.setOneTouchExpandable(false);
+		splitPane.setDividerLocation(250);
+		//splitPane.setDividerLocation(0.70);
+
+		tabbedPane = new JTabbedPane(JTabbedPane.TOP);
+		tabbedPane.addTab("Main", ball, splitPane, "Main Commands");
+		tabbedPane.addTab("Get/Set", ball, propertieScrollPane, "Properties Panel");
+
+		QSAdminPluginConfig qsAdminPluginConfig = null;
+		PluginPanel pluginPanel = null;
+		//-- start of loadPlugins
+		try	{
+			File xmlFile = null;
+			ClassLoader classLoader = null;
+			Class mainClass = null;
+
+			File file = new File(pluginDir);			
+			File dirs[] = null;
+			
+			if(file.canRead())
+				dirs = file.listFiles(new DirFileList());
+
+			for(int i=0;dirs!=null && i<dirs.length;i++) {
+				xmlFile = new File(dirs[i].getAbsolutePath()+
+					File.separator+"plugin.xml");
+				if(xmlFile.canRead()) {
+					qsAdminPluginConfig = PluginConfigReader.read(xmlFile);
+					if(qsAdminPluginConfig.getActive().equals("yes") &&
+							qsAdminPluginConfig.getType().equals("javax.swing.JPanel")) {
+						classLoader = ClassUtil.getClassLoaderFromJars( dirs[i].getAbsolutePath() );
+						mainClass = classLoader.loadClass(qsAdminPluginConfig.getMainClass());
+						logger.fine("Got PluginMainClass "+mainClass);
+						pluginPanel = (PluginPanel) mainClass.newInstance();
+						if( JPanel.class.isInstance(pluginPanel)==true ) {
+							logger.info("Loading plugin : "+qsAdminPluginConfig.getName());
+							pluginPanelMap.put(""+(2+i), pluginPanel);
+							plugins.add(pluginPanel);
+							tabbedPane.addTab(qsAdminPluginConfig.getName(), 
+								ball, (JPanel)pluginPanel, qsAdminPluginConfig.getDesc());
+							pluginPanel.setQSAdminMain(qsadminMain);
+							pluginPanel.init();							
+						}
+					} else {
+						logger.info("Plugin "+dirs[i]+" is disabled so skipping "+qsAdminPluginConfig.getActive()+":"+qsAdminPluginConfig.getType());
+					}
+				} else {
+					logger.info("No plugin configuration found in "+xmlFile+" so skipping");
+				}
+			}
+		} catch(Exception e) {
+			logger.warning("Error loading plugin : "+e);
+			logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
+		}
+		//-- end of loadPlugins
+
+		tabbedPane.addChangeListener(new ChangeListener() {
+			int selected = -1;
+			int oldSelected = -1;
+			public void stateChanged(ChangeEvent e) {
+				//if plugin
+				selected = tabbedPane.getSelectedIndex();
+				if(selected>=2) {
+					( (PluginPanel)pluginPanelMap.get(""+selected) ).activated();
+				} 
+				if(oldSelected>=2) {
+					( (PluginPanel)pluginPanelMap.get(""+oldSelected) ).deactivated();
+				}				
+				oldSelected = selected;
+			}
+		});
+
+		//tabbedPane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		cp.add(tabbedPane, BorderLayout.CENTER);
+		
+		buildMenu();
+	}
+
+	public void setStatus(String msg) {
+		headerPanel.setStatus(msg);
+	}
+
+	public void setResponse(String res) {
+		int msgType = JOptionPane.PLAIN_MESSAGE ;
+		if(res.startsWith("+OK"))
+			msgType = JOptionPane.INFORMATION_MESSAGE;
+		if(res.startsWith("-ERR"))
+			msgType = JOptionPane.ERROR_MESSAGE;
+		JOptionPane.showMessageDialog(QSAdminGUI.this,
+			res.substring(res.indexOf(" ")+1), "Response", msgType);
+	}
+
+	public void appendToConsole(String msg) {
+		cmdConsole.append(msg);
+	}
+
+	public void setConsoleSend(boolean flag) {
+		cmdConsole.setSendEdit(flag);
+	}
+	
+	public void updateConnectionStatus(boolean connected) {
+		if(connected==true) {
+			headerPanel.setLogoutText();
+			loginMenuItem.setText("Logout");
+		} else {
+			headerPanel.setLoginText();
+			loginMenuItem.setText("Login...");
+		}
+		mainCommandPanel.updateConnectionStatus(connected);
+		propertiePanel.updateConnectionStatus(connected);
+		cmdConsole.updateConnectionStatus(connected);
+		Iterator iterator = plugins.iterator();
+		PluginPanel updatePluginPanel = null;
+		while(iterator.hasNext()) {
+			updatePluginPanel = (PluginPanel)iterator.next();
+			updatePluginPanel.updateConnectionStatus(connected);
+		}
+		
+		if(connected==true) {
+			int selected = tabbedPane.getSelectedIndex();
+			if(selected>=2) {
+				( (PluginPanel)pluginPanelMap.get(""+selected) ).activated();
+			} 
+		}
+	}
+
+	//--v1.3.2
+	public static void setPluginDir(String dir) {
+		pluginDir = dir;
+	}
+	public static String getPluginDir() {
+		return pluginDir;
+	}
+
+	private void buildMenu() {
+		jMenuBar = new javax.swing.JMenuBar();
+        mainMenu = new javax.swing.JMenu();
+		mainMenu.setText("Main");
+
+		loginMenuItem = new JMenuItem("Login...");
+        loginMenuItem.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                headerPanel.handleLoginLogout();
+            }
+        });
+
+        mainMenu.add(loginMenuItem);
+
+		exitMenuItem = new JMenuItem("Exit");
+        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+				if(qsadminMain.isConnected()==true) {
+					headerPanel.handleLoginLogout();
+				}
+                System.exit(0);
+            }
+        });
+        mainMenu.add(exitMenuItem);
+        
+        helpMenu = new javax.swing.JMenu();
+		helpMenu.setText("Help");
+
+		aboutMenuItem = new JMenuItem("About...");
+        aboutMenuItem.setEnabled(true);
+        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                about();
+            }
+        });
+        helpMenu.add(aboutMenuItem);
+
+        jMenuBar.add(mainMenu);
+		jMenuBar.add(helpMenu);
+
+		parentFrame.setJMenuBar(jMenuBar);
+	}
+
+	private void about() {
+		JOptionPane.showMessageDialog(this,
+			"QSAdminGUI\n\n"+
+			"GUI Client for QSAdminServer of QuickServer.\n"+
+			"This is compliant with QuickServer v"+QSAdminMain.VERSION_OF_SERVER+" release.\n\n"+
+			"Copyright (C) QuickServer.org\n"+
+			"http://www.quickserver.org",
+			"About QSAdminGUI",
+			JOptionPane.INFORMATION_MESSAGE,
+			logoAbout);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdminMain.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdminMain.java
new file mode 100644
index 0000000..ed98b17
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/QSAdminMain.java
@@ -0,0 +1,429 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.net.*;
+import java.io.*;
+import java.util.LinkedList;
+
+import org.quickserver.util.*;
+import org.quickserver.swing.JFrameUtilities;
+
+import java.util.logging.*;
+
+/**
+ * Main Class of QSAdminGUI
+ * QuickServer Admin GUI - QSAdminGUI
+ * @author Akshathkumar Shetty
+ */
+public class QSAdminMain {
+	private static Logger logger = Logger.getLogger(QSAdminMain.class.getName());
+	private final static String NEW_LINE;
+
+	static {
+		if(System.getProperty("org.quickserver.useOSLineSeparator")!=null && 
+			System.getProperty("org.quickserver.useOSLineSeparator").equals("true")) {
+			NEW_LINE = System.getProperty("line.separator");
+		} else {
+			NEW_LINE = "\r\n";
+		}
+	}
+
+	private Socket socket;
+	private InputStream in;
+	private OutputStream out;
+	private BufferedReader br;
+	private BufferedWriter bw;
+
+	private boolean connected = false;
+	//v1.3.2
+	private boolean loggedIn = false;
+	private boolean appendToConsole = true;
+
+	private QSAdminGUI gui;
+
+	private LinkedList receivedMsg;
+
+	public static String VERSION_OF_SERVER = "1.4.9"; //QuickServer.getVersion();
+
+	public QSAdminMain() {
+		
+	}
+
+	public boolean doLogin(String ipAddress, int port,
+			String username, String password) throws IOException {
+		connected = false;
+		loggedIn = false;
+		String backupVersionOfServer = VERSION_OF_SERVER;
+		VERSION_OF_SERVER = null;
+		logger.fine("Logging in to " + ipAddress + ":"+port);
+		try	{
+			socket = new Socket(ipAddress, port);
+			connected = true;
+			in = socket.getInputStream();
+			out = socket.getOutputStream();
+			br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+			bw = new BufferedWriter(new OutputStreamWriter(out,  "UTF-8"));
+			getGUI().setStatus("Connected");
+			startSocketListener();
+
+			String res = null;
+			res = sendCommunicationSilent(null, false, true);
+			if(res.startsWith("+OK")==false)
+				throw new IOException(res.substring(4));
+			res = sendCommunicationSilent(null, false, true);
+			if(res.startsWith("+OK")==false)
+				throw new IOException(res.substring(4));
+			res = sendCommunicationSilent(null, false, true);
+			if(res.startsWith("+OK")==false)
+				throw new IOException(res.substring(4));
+			//gui.setResponse(res);
+
+			//try to login
+			res = sendCommunicationSilent(null, false, true);
+			res = sendCommunicationSilent(username, false, true);
+			if(res.startsWith("+OK")) { //+OK Password required
+				getGUI().setStatus("Authorising..");
+			} else if(res.startsWith("-ERR")) {
+				getGUI().setStatus("Error: "+res.substring(4));
+				throw new IOException("Bad QSAdmin Username! Server reply: "+res);
+			} else {
+				getGUI().setStatus("Protocol Error: "+res);
+				throw new IOException("Bad QSAdmin Username! Server reply: "+res);
+			}
+
+			//password
+			StringBuilder buffer = new StringBuilder();
+			for(int i=0;i<password.length();i++)
+				buffer.append('*');
+			getGUI().appendToConsole(buffer.toString());
+			res = sendCommunicationSilent(password, false, false);
+			
+			if(res.startsWith("+OK")) {
+				getGUI().setStatus("Authorised");
+				loggedIn = true;
+			} else {
+				getGUI().setStatus("Error : "+res.substring(4));
+				throw new IOException(res.substring(4));
+			}
+			getGUI().setConsoleSend(true);
+			getGUI().updateConnectionStatus(true);
+
+			getGUI().appendToConsole("Checking version at host..");
+			VERSION_OF_SERVER = sendCommunicationSilent("version", false, true);
+			if(VERSION_OF_SERVER!=null && VERSION_OF_SERVER.startsWith("+OK "))
+				VERSION_OF_SERVER = VERSION_OF_SERVER.substring(4);
+			return true;
+		} catch(UnknownHostException e) {
+			if(socket!=null) socket.close();
+			logger.warning("Error "+e);
+			connected = false;
+			loggedIn = false;
+			socket = null;
+			in = null;
+			out = null;
+			br = null;
+			bw = null;
+			gui.setResponse("-ERR Unknown Host : "+e.getMessage());
+			gui.setConsoleSend(false);
+			VERSION_OF_SERVER = backupVersionOfServer;
+			return false;
+		} catch(IOException e) {
+			if(socket!=null) socket.close();
+			logger.warning("Error "+e);
+			connected = false;
+			socket = null;
+			in = null;
+			out = null;
+			br = null;
+			bw = null;
+			gui.setResponse("-ERR "+e.getMessage());
+			gui.setConsoleSend(false);
+			VERSION_OF_SERVER = backupVersionOfServer;
+			return false;
+		}
+	}
+
+	public void doLogout() throws IOException {
+		if(socket==null)
+			throw new IllegalStateException("Not connected");
+		String res = sendCommunicationSilent("quit", false, true);
+		if(res.startsWith("+OK"))
+			gui.setStatus("Disconnecting");
+		else {
+			gui.setStatus("Error : "+res.substring(4));
+		}
+		clean();		
+	}
+
+	private void clean() {
+		if(socket!=null) {
+			try {
+				socket.close();	
+			} catch(Exception e) {
+				logger.warning("Error : "+e);
+			}
+			socket = null;
+		}
+		in = null;
+		out = null;
+		br = null;
+		bw = null;
+		connected = false;
+		loggedIn = false;
+		gui.setConsoleSend(false);
+		gui.setStatus("Disconnected");
+		gui.updateConnectionStatus(false);
+		setAppendToConsole(true);
+	}
+
+	public void sendCommand(String command, boolean echo) {
+		logger.fine("Got command : "+command);
+		if(isConnected()==false) {
+			gui.setResponse("-ERR Not connected yet.");
+			return;
+		}
+		if(command!=null && command.equals("")==false) {
+			if(socket==null)
+				throw new IllegalStateException("Not connected");
+			if(echo==true)
+				gui.appendToConsole(command);
+			command += NEW_LINE;
+			try {
+				bw.write(command, 0, command.length());
+				bw.flush();				
+			} catch(Exception e) {
+				gui.setResponse("-ERR "+e.getMessage());
+			}
+		}
+	}
+
+	public String readResponse(boolean multiLineResponse) {
+		StringBuilder command = new StringBuilder();
+		try {
+			if(multiLineResponse==true) {
+				String res = getReceivedMsg();
+				//check if is single line
+				if(res!=null && res.equals("+OK info follows")==false)
+					return res;
+
+				if(res!=null && res.equals("+OK info follows")==true) {
+					command.append("+OK ");
+					res = getReceivedMsg();
+				}
+				while(res!=null && res.equals(".")==false) {
+					logger.fine(res);
+					command.append(res + NEW_LINE);
+					res = getReceivedMsg();
+				}
+			} else {
+				command.append(getReceivedMsg());
+			}
+		} catch(Exception e) {
+			command.append("-ERR "+e.getMessage());
+		}
+		return command.toString();
+	}
+
+	public synchronized String sendCommunication(String command, 
+			boolean multiLineResponse, boolean echo) {
+		logger.fine("Got command : "+command);
+		if(isConnected()==false) {
+			gui.setResponse("-ERR Not connected yet.");
+			return "-ERR Not connected yet";
+		}
+		if(command!=null && command.equals("")==false) {
+			if(socket==null)
+				throw new IllegalStateException("Not connected");
+			if(echo==true)
+				gui.appendToConsole(command);
+			command += NEW_LINE;
+			emptyReceivedMsg();
+			try {
+				bw.write(command, 0, command.length());
+				bw.flush();				
+			} catch(Exception e) {
+				gui.setResponse("-ERR "+e.getMessage());
+				return null;
+			}
+		}
+		command = readResponse(multiLineResponse);
+		gui.setResponse(command);
+		return command;
+	}
+
+
+	public synchronized String sendCommunicationSilent(String command, 
+			boolean multiLineResponse, boolean echo) throws IOException {
+		logger.fine("Got command : "+command);
+		if(isConnected()==false)
+			return "-ERR Not connected yet";
+		if(socket==null)
+			throw new IllegalStateException("Not connected");
+		if(command!=null && command.equals("")==false) {
+			if(echo==true)
+				gui.appendToConsole(command);
+			command += NEW_LINE;
+			emptyReceivedMsg();
+			bw.write(command, 0, command.length());
+			bw.flush();
+		} 
+		return readResponse(multiLineResponse);
+	}
+
+	public synchronized String sendCommunicationNoEcho(String command, 
+			boolean multiLineResponse) throws IOException {
+		try	{
+			setAppendToConsole(false);
+			logger.fine("Got command : "+command);
+			if(isConnected()==false)
+				return "-ERR Not connected yet";
+			if(socket==null)
+				throw new IllegalStateException("Not connected");
+			if(command!=null && command.equals("")==false) {
+				command += NEW_LINE;
+				emptyReceivedMsg();
+				bw.write(command, 0, command.length());
+				bw.flush();
+			} 
+			command = readResponse(multiLineResponse);			
+		} catch(IllegalStateException e) {
+			throw e;
+		} catch(Exception e) {
+			throw new IOException("Exception Got : "+ e);
+		} finally {
+			setAppendToConsole(true);
+		}
+		return command;
+	}
+
+	public String toString() {
+		if(socket==null) {
+			return "Not connected";
+		}
+		StringBuilder info = new StringBuilder("Connected to ");
+		info.append(socket.getInetAddress().getHostName());
+		return info.toString();
+	}
+
+	public boolean isConnected(){
+		return  connected;
+	}
+
+	public boolean isLoggedIn(){
+		return loggedIn;
+	}
+
+	public void setGUI(QSAdminGUI gui) {
+		this.gui = gui;
+	}
+	public QSAdminGUI getGUI(){
+		return gui;
+	}
+
+	public void startSocketListener() {
+		receivedMsg = new LinkedList();
+		Thread t = new Thread() {
+			public void run() {
+				String rec = null;
+				logger.info("Started");
+				while(true) {
+					try {
+						rec =  br.readLine();
+					} catch(IOException e) {
+						logger.warning("Error : "+e);
+						if(isConnected()==true) clean();
+						break;
+					}
+					if(rec==null) {
+						if(isConnected()==true) clean();
+						break;
+					}
+					receivedMsg.add(rec);
+					if(getAppendToConsole()==true)
+						gui.appendToConsole(rec);
+				}
+				logger.info("Finished");
+			}
+		};
+		t.setPriority(Thread.NORM_PRIORITY);
+		t.start();
+	}
+
+	public String getReceivedMsg() {
+		while(receivedMsg.size()==0 && isConnected()==true) {
+			try {
+				Thread.currentThread().sleep(50);
+			} catch(InterruptedException e) {
+				logger.warning("Error : "+e);
+			}
+		}
+		if(receivedMsg.size()!=0)
+			return (String)receivedMsg.removeFirst();
+		else
+			return null;
+	}
+
+	public void emptyReceivedMsg() {
+		receivedMsg.clear();
+	}
+
+	/** 
+	 * Returns the numerical version of the server connected to.
+	 */
+	public float getServerVersionNo() {
+		String ver = VERSION_OF_SERVER;
+		if(ver==null) {
+			gui.setResponse("-ERR Not connected yet");
+			return 0;
+		}
+
+		float version = 0;
+		int i = ver.indexOf(" "); //check if beta
+		if(i == -1)
+			i = ver.length();
+		ver = ver.substring(0, i);
+
+		i = ver.indexOf("."); //check for sub version
+		if(i!=-1) {
+			int j = ver.indexOf(".", i);
+			if(j!=-1) {
+				ver = ver.substring(0, i)+"."+
+					MyString.replaceAll(ver.substring(i+1), ".", "");
+			}
+		}
+
+		try	{
+			version = Float.parseFloat(ver);	
+		} catch(NumberFormatException e) {
+			logger.warning("Error : "+e);
+			gui.setResponse("-ERR Corrupt QuickServer running @ host :"+e.getMessage());
+		}	
+		return version;
+	}
+
+	public String getIpAddress() {
+		if(socket==null) return null;
+		return socket.getInetAddress().getHostName();
+	}
+
+
+	public boolean getAppendToConsole() {
+		return appendToConsole;
+	}
+	public void setAppendToConsole(boolean appendToConsole) {
+		this.appendToConsole = appendToConsole;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/SaveActionListener.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SaveActionListener.java
new file mode 100644
index 0000000..6e69a80
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SaveActionListener.java
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+public class SaveActionListener implements ActionListener {
+	private Propertie propertie;
+	private QSAdminMain qsadminMain;
+
+	public SaveActionListener(QSAdminMain qsadminMain, Propertie propertie) {
+		this.qsadminMain = qsadminMain;
+		this.propertie = propertie;
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		Thread performer = new Thread(new Runnable() {
+			public void run() {
+				String temp = null;
+				if(propertie.getType().equals("edit")) {
+					temp = propertie.getEditField().getText();
+				} else if(propertie.getType().equals("select")) {
+					temp = (String)propertie.getComboBox().getSelectedItem();
+				}
+
+
+				if(qsadminMain.getServerVersionNo() < propertie.getVersionNo()) {
+					qsadminMain.getGUI().setResponse("-ERR "+"Host does not support this command"); 
+					return;
+				}		
+
+				try {
+					temp = qsadminMain.sendCommunicationSilent(
+						propertie.getSetCommand(temp), false, true);
+					propertie.getSaveButton().setEnabled(false);
+				} catch(Exception ex) {
+					temp = "-ERR Could not set parameter : "+ex.getMessage();
+				}
+				if(temp==null) return;
+				
+				if(temp.indexOf(" ")==-1) {
+					qsadminMain.getGUI().setResponse("-ERR "+temp);
+					return;
+				}
+				qsadminMain.getGUI().setResponse(temp);
+			}
+		}, "QsAdminGUI-SaveThread");
+		performer.start();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleActionListener.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleActionListener.java
new file mode 100644
index 0000000..e48a823
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleActionListener.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+public class SimpleActionListener implements ActionListener {
+	private SimpleCommand sm;
+	private MainCommandPanel mcp;
+	private QSAdminMain qsadminMain;
+
+	public SimpleActionListener(QSAdminMain qsadminMain, SimpleCommand sm, 
+			MainCommandPanel mcp) {
+		this.qsadminMain = qsadminMain;
+		this.sm = sm;
+		this.mcp = mcp;
+	}
+	public void actionPerformed(ActionEvent e) {
+		Thread performer = new Thread(new Runnable() {
+			public void run() {
+				sm.setTarget(mcp.getTarget());
+				boolean multiLine = sm.getMultiLineResponse().equals("yes");
+				if(qsadminMain.getServerVersionNo()>=sm.getVersionNo()) {
+					qsadminMain.sendCommunication(sm.getSimpleCommand(), 
+						multiLine, true);
+				} else {
+					qsadminMain.getGUI().setResponse("-ERR "+"Host does not support this command"); 
+				}
+			}
+		}, "QsAdminGUI-SimpleThread");
+		performer.start();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleCommand.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleCommand.java
new file mode 100644
index 0000000..b822e7a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleCommand.java
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import org.quickserver.util.MyString;
+
+/**
+ * A Simple class that Stores information about QSAdmin Command
+ * that are common to any <code>target</code>
+ * @author Akshathkumar Shetty
+ */
+public class SimpleCommand {
+	private String name;
+	private String target = "server";
+	private String command;
+	private String desc;
+	private String targetNeeded = "yes";
+	private String multiLineResponse = "no";
+	private String version = "1.3"; //when AdminUI was added
+
+	public String getSimpleCommand() {
+		if(targetNeeded.equals("yes"))
+			return command+" "+target;
+		else
+			return command;
+	}
+
+	public String getName(){
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getTarget() {
+		return target;
+	}
+	public void setTarget(String target) {
+		this.target = target;
+	}
+
+	public String getCommand() {
+		return command;
+	}
+	public void setCommand(String command) {
+		this.command = command;
+	}
+
+	public String getDesc() {
+		return desc;
+	}
+	public void setDesc(String desc) {
+		this.desc = desc;
+	}
+
+	public String getTargetNeeded() {
+		return targetNeeded;
+	}
+	public void setTargetNeeded(String targetNeeded) {
+		this.targetNeeded = targetNeeded.toLowerCase();
+	}
+
+	public String getMultiLineResponse() {
+		return multiLineResponse;
+	}
+	public void setMultiLineResponse(String multiLineResponse) {
+		this.multiLineResponse = multiLineResponse.toLowerCase();
+	}
+
+	public String getVersion() {
+		return version;
+	}
+	public float getVersionNo() {
+		return getVersionNo(version);
+	}
+	public void setVersion(String version) {
+		if(version!=null && version.equals("")==false)
+			this.version = version.toLowerCase();
+	}
+
+	public String toXML() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("<simple-command>\n");
+		sb.append("\t<name>").append(name).append("</name>\n");
+		sb.append("\t<command>").append(command).append("</command>\n");
+		if(multiLineResponse!=null && multiLineResponse.equals("yes"))
+			sb.append("\t<multi-line-response>yes</multi-line-response>\n");
+		else
+			sb.append("\t<multi-line-response>no</multi-line-response>\n");
+		if(desc!=null)
+			sb.append("\t<desc>").append(desc).append("</desc>\n");
+		sb.append("\t<version>").append(version).append("</version>\n");
+		if(targetNeeded!=null && targetNeeded.equals("yes"))
+			sb.append("\t<target-needed>yes</target-needed>\n");
+		else
+			sb.append("\t<target-needed>no</target-needed>\n");
+		sb.append("</simple-command>\n");
+		return sb.toString();
+	}
+
+	private static final float getVersionNo(String ver) {
+		//String ver = getVersion();
+		float version = 0;
+		int i = ver.indexOf(" "); //check if beta
+		if(i == -1)
+			i = ver.length();
+		ver = ver.substring(0, i);
+		
+		i = ver.indexOf("."); //check for sub version
+		if(i!=-1) {
+			int j = ver.indexOf(".", i);
+			if(j!=-1) {
+				ver = ver.substring(0, i)+"."+
+					MyString.replaceAll(ver.substring(i+1), ".", "");
+			}
+		}
+
+		try	{
+			version = Float.parseFloat(ver);	
+		} catch(NumberFormatException e) {
+			throw new RuntimeException("Corrupt QuickServer");
+		}
+		return version;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleCommandSet.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleCommandSet.java
new file mode 100644
index 0000000..98fda9b
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SimpleCommandSet.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.util.*;
+import java.net.URL;
+import java.io.InputStream;
+import java.util.logging.*;
+import org.apache.commons.digester3.Digester;
+import org.quickserver.util.MyString;
+
+/**
+ * A Simple class that Stores SimpleCommands for QSAdmin GUI
+ * @author Akshathkumar Shetty
+ */
+public class SimpleCommandSet {
+	private static Logger logger = Logger.getLogger(SimpleCommandSet.class.getName());
+
+	//stores commands from xml file
+	private List list;
+	private Map map;
+
+	public SimpleCommandSet() {
+		list = new ArrayList();
+		map = new HashMap();
+	}
+
+	public List getList() {
+		return list;
+	}
+	public Map getMap() {
+		return map;
+	}
+	
+	public void addCommand(SimpleCommand sm) {
+		list.add(sm);
+		map.put(sm.getCommand(), sm);
+	}
+
+	/* Returns SimpleCommandSet containing simple commands */
+	public static SimpleCommandSet getSimpleCommands() {
+		SimpleCommandSet sms = null;
+		try {
+	        Digester digester = new Digester();
+		    digester.setValidating(false);
+			//digester.setNamespaceAware(true);
+			//String xsd = "" + new File("quickserver_config.xsd").toURI();
+			//digester.setSchema(xsd);
+
+			//nested QSAdminServer tag
+			String mainTag = "simple-command-set";
+			String subTag = "simple-command";
+			digester.addObjectCreate(mainTag, SimpleCommandSet.class);
+			digester.addObjectCreate(mainTag+"/"+subTag, SimpleCommand.class);
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/name");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/command");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/desc");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/target-needed", "targetNeeded");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/multi-line-response", "multiLineResponse");
+			digester.addBeanPropertySetter(mainTag+"/"+subTag+"/version");
+			digester.addSetNext(mainTag+"/"+subTag,"addCommand");
+			URL configFile = 
+				SimpleCommandSet.class.getResource("/org/quickserver/net/qsadmin/gui/conf/MainCommandPanel.xml");
+			if(configFile==null)
+				throw new RuntimeException("XML File not found : "+"MainCommandPanel.xml");
+
+			InputStream input = configFile.openStream();
+			logger.fine("Loading command config from xml file : " + input);
+			sms = (SimpleCommandSet) digester.parse(input);			
+		} catch(Exception e) {
+			logger.severe("Could not init from xml file : " +e);
+			logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
+		}
+		return sms;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/SplashScreen.java b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SplashScreen.java
new file mode 100644
index 0000000..16669b5
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/SplashScreen.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.qsadmin.gui;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.event.*;
+import org.quickserver.swing.JFrameUtilities;
+
+public class SplashScreen extends JWindow {	
+	protected ImageIcon logo;
+	protected JLabel productName;
+
+	public SplashScreen() {
+		logo = new ImageIcon(getClass().getClassLoader().getResource("icons/logo.png"));
+		productName = new JLabel("<html><font face=\"Verdana\" size=\"3\"> Loading..</font><br>"+
+			"<font face=\"Verdana\" size=\"5\">QSAdminGUI</font>",logo,JLabel.CENTER);
+		productName.setBackground(new Color(238,238,230,255));//Color.white);
+		productName.setOpaque(true);
+		
+		productName.setBorder(BorderFactory.createCompoundBorder(
+			BorderFactory.createEmptyBorder(10,10,10,10),
+			BorderFactory.createLineBorder(Color.black) ));
+		getContentPane().add(productName);
+		Dimension dim=productName.getPreferredSize();
+		dim.setSize(dim.getWidth()+10,dim.getHeight()+10);
+		setSize(dim);
+		JFrameUtilities.centerWindow(this);
+		setVisible(true);	
+	}
+	
+	public void kill() {
+		dispose();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/conf/MainCommandPanel.xml b/quickserver/src/main/org/quickserver/net/qsadmin/gui/conf/MainCommandPanel.xml
new file mode 100644
index 0000000..a2e9ab9
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/conf/MainCommandPanel.xml
@@ -0,0 +1,132 @@
+<simple-command-set>
+	<simple-command>
+		<name>Information</name>
+		<command>info</command>
+		<desc>Information about the server</desc>
+		<multi-line-response>yes</multi-line-response>
+	</simple-command>
+	<simple-command>
+		<name>Start</name>
+		<command>start</command>
+		<desc>Starts the server</desc>
+	</simple-command>
+	<simple-command>
+		<name>Stop</name>
+		<command>stop</command>
+		<desc>Stops the server</desc>
+	</simple-command>
+	<simple-command>
+		<name>Restart</name>
+		<command>restart</command>
+		<desc>Restarts the server</desc>
+	</simple-command>
+	<simple-command>
+		<name>Stutdown</name>
+		<command>shutdown</command>
+		<desc>Stutdown the server</desc>
+		<target-needed>no</target-needed>
+	</simple-command>	
+	<simple-command>
+		<name>Is Running</name>
+		<command>running</command>
+		<desc>Checks if target is running</desc>
+	</simple-command>
+	<simple-command>
+		<name>Version</name>
+		<command>version</command>
+		<target-needed>no</target-needed>
+		<desc>Gets the version of the QuickServer library used</desc>
+	</simple-command>
+	<simple-command>
+		<name>Suspend Service</name>
+		<command>suspendservice</command>
+		<desc>Suspend the server</desc>
+		<version>1.3</version>
+	</simple-command>
+	<simple-command>
+		<name>Resume Service</name>
+		<command>resumeservice</command>
+		<desc>Resume the server</desc>
+		<version>1.3</version>
+	</simple-command>
+	<simple-command>
+		<name>Kill Service</name>
+		<command>kill</command>
+		<desc>Kills the server</desc>
+		<version>1.3</version>
+	</simple-command>
+
+	<simple-command>
+		<name>Client Count</name>
+		<command>noclient</command>
+		<desc>No Client connected</desc>
+	</simple-command>
+
+	<simple-command>
+		<name>All Pool Information</name>
+		<command>all-pool-info</command>
+		<desc>Information on all pool in use</desc>
+		<multi-line-response>yes</multi-line-response>
+		<version>1.4.5</version>
+	</simple-command>
+	<simple-command>
+		<name>Client Thread Pool Dump</name>
+		<command>client-thread-pool-dump</command>
+		<desc>Dump of Client Threads active in pool</desc>
+		<multi-line-response>yes</multi-line-response>
+		<version>1.4.5</version>
+	</simple-command>
+	<simple-command>
+		<name>Client Handler Pool Dump</name>
+		<command>client-handler-pool-dump</command>
+		<desc>Dump of ClientHandler active in pool</desc>
+		<multi-line-response>yes</multi-line-response>
+		<version>1.4.6</version>
+	</simple-command>
+	
+	
+	<simple-command>
+		<name>System Information</name>
+		<command>systeminfo</command>
+		<desc>Information on System</desc>
+		<multi-line-response>yes</multi-line-response>
+		<target-needed>no</target-needed>
+		<version>1.4.5</version>
+	</simple-command>
+
+	<simple-command>
+		<name>Start Console</name>
+		<command>start console</command>
+		<desc>Starts Command Console</desc>
+		<multi-line-response>no</multi-line-response>
+		<target-needed>no</target-needed>
+		<version>1.4.5</version>
+	</simple-command>
+	<simple-command>
+		<name>Stop Console</name>
+		<command>stop console</command>
+		<desc>Stops Command Console</desc>
+		<multi-line-response>no</multi-line-response>
+		<target-needed>no</target-needed>
+		<version>1.4.5</version>
+	</simple-command>
+	
+	<simple-command>
+		<name>JStack > File</name>
+		<command>jvm dumpJStack file</command>
+		<desc>Take JStack to file</desc>
+		<multi-line-response>yes</multi-line-response>
+		<target-needed>no</target-needed>
+		<version>2.0.0</version>
+	</simple-command>
+	
+	<simple-command>
+		<name>JMap > File</name>
+		<command>jvm dumpJmapHisto file</command>
+		<desc>Take JMap Histo to file</desc>
+		<multi-line-response>yes</multi-line-response>
+		<target-needed>no</target-needed>
+		<version>2.0.0</version>
+	</simple-command>
+	
+</simple-command-set>
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/conf/PropertieSet.xml b/quickserver/src/main/org/quickserver/net/qsadmin/gui/conf/PropertieSet.xml
new file mode 100644
index 0000000..2edbccf
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/conf/PropertieSet.xml
@@ -0,0 +1,211 @@
+<propertie-set>

+	<propertie>

+		<name>ClientEventHandler</name>

+		<command>clientEventHandler</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientEventHandler class</desc>

+		<version>1.4.6</version>

+	</propertie>

+	<propertie>

+		<name>ClientCommandHandler</name>

+		<command>clientCommandHandler</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientCommandHandler class</desc>

+	</propertie>

+	<propertie>

+		<name>ClientWriteHandler</name>

+		<command>clientWriteHandler</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientWriteHandler class</desc>

+		<version>1.4.6</version>

+	</propertie>

+	<propertie>

+		<name>ClientObjectHandler</name>

+		<command>clientObjectHandler</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientObjectHandler class</desc>

+		<version>1.3</version>

+	</propertie>

+	<propertie>

+		<name>ClientAuthenticationHandler</name>

+		<command>clientAuthenticationHandler</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientAuthenticationHandler class</desc>

+	</propertie>

+	<propertie>

+		<name>ClientData</name>

+		<command>clientData</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientData class</desc>

+	</propertie>

+	<propertie>

+		<name>ClientExtendedEventHandler</name>

+		<command>clientExtendedEventHandler</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>ClientExtendedEventHandler class</desc>

+		<version>1.4.6</version>

+	</propertie>

+

+	<propertie>

+		<name>Max. Client</name>

+		<command>maxClient</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>maximum no. of clients</desc>

+	</propertie>

+	<propertie>

+		<name>Max. Client Messsage</name>

+		<command>maxClientMsg</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Message for excess clients</desc>

+		<version>1.3</version>

+	</propertie>

+	<propertie>

+		<name>Listening Port</name>

+		<command>port</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>port to listen on</desc>

+	</propertie>

+	<propertie>

+		<name>Max. AuthTry</name>

+		<command>maxAuthTry</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Max AuthTry</desc>

+		<version>1.3</version>

+	</propertie>

+	<propertie>

+		<name>Max. AuthTry Message</name>

+		<command>maxAuthTryMsg</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Max AuthTry Message</desc>

+	</propertie>

+	<propertie>

+		<name>Timeout</name>

+		<command>timeout</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>timeout set for clients</desc>

+	</propertie>

+	<propertie>

+		<name>Timeout Message</name>

+		<command>timeoutMsg</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>timeout message</desc>

+		<version>1.3</version>

+	</propertie>

+

+	

+

+	

+	<propertie>

+		<name>QSAdmin Plugin</name>

+		<command>self plugin</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>pluggable command handler for QsAdminServer</desc>

+		<target-needed>no</target-needed>

+		<version>1.2</version>

+	</propertie>

+	<propertie>

+		<name>Service State</name>

+		<command>serviceState</command>

+		<get>yes</get>

+		<set>no</set>

+		<type>edit</type>

+		<desc>ServiceState</desc>

+		<version>1.2</version>

+	</propertie>

+	<propertie>

+		<name>Console Logging Formatter</name>

+		<command>consoleLoggingFormatter</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Console Logging Formatter</desc>

+		<version>1.3</version>

+	</propertie>

+	<propertie>

+		<name>Console Logging Level</name>

+		<command>consoleLoggingLevel</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>select</type>

+		<desc>Console Logging Formatter</desc>

+		<version>1.3</version>

+		<select>ALL|SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST|OFF</select>

+	</propertie>

+	<propertie>

+		<name>All Logging Level</name>

+		<command>loggingLevel</command>

+		<get>no</get>

+		<set>yes</set>

+		<type>select</type>

+		<desc>Console Logging Formatter</desc>

+		<version>1.3.1</version>

+		<select>ALL|SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST|OFF</select>

+	</propertie>

+	<propertie>

+		<name>Communication Logging</name>

+		<command>communicationLogging</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Communication logging flag</desc>

+		<version>1.3.2</version>

+	</propertie>	

+	<propertie>

+		<name>Max Objects Active in Pool</name>

+		<command>objectPoolConfig-maxActive</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Max number of objects active in pool</desc>

+		<version>1.3.2</version>

+	</propertie>

+	<propertie>

+		<name>Max Objects Idle in Pool</name>

+		<command>objectPoolConfig-maxIdle</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Max number of objects idle in pool</desc>

+		<version>1.3.2</version>

+	</propertie>

+	<propertie>

+		<name>Init Size Objects of Pool</name>

+		<command>objectPoolConfig-initSize</command>

+		<get>yes</get>

+		<set>yes</set>

+		<type>edit</type>

+		<desc>Init Size Objects of Pool</desc>

+		<version>1.4.6</version>

+	</propertie>

+

+</propertie-set>

diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/gui/package.html b/quickserver/src/main/org/quickserver/net/qsadmin/gui/package.html
new file mode 100644
index 0000000..878b2dd
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/gui/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+GUI components and classes.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/qsadmin/package.html b/quickserver/src/main/org/quickserver/net/qsadmin/package.html
new file mode 100644
index 0000000..1caecda
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/qsadmin/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Contains all of the classes for creating QSAdminServer.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/server/AuthStatus.java b/quickserver/src/main/org/quickserver/net/server/AuthStatus.java
new file mode 100644
index 0000000..4be2c13
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/AuthStatus.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+/**
+ * This class defines the state of authentication.
+ * @since 1.4.6
+ * @author Akshathkumar Shetty
+ */
+public class AuthStatus {
+	private int status;
+	private String desc;
+
+	private AuthStatus(int status) {
+		this.status = status;
+		if(status==1) {
+			desc = "Success";
+		} else {
+			desc = "Failure";
+		}
+	}
+
+	public String toString() {
+		return desc;
+	}
+
+	public static final AuthStatus FAILURE = new AuthStatus(0);
+	public static final AuthStatus SUCCESS = new AuthStatus(1);
+}
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/net/server/Authenticator.java b/quickserver/src/main/org/quickserver/net/server/Authenticator.java
new file mode 100644
index 0000000..659f341
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/Authenticator.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+import org.quickserver.net.AppException;
+
+
+/**
+ * This interface defines a class that can be used by 
+ * QuickServer to authenticate a client when new connection is
+ * made to QuickServer. Should have a default constructor. 
+ * @author Akshathkumar Shetty
+ * @deprecated As of 1.4.6 use {@link ClientAuthenticationHandler}
+ */
+public interface Authenticator {
+
+	/**
+	 *  This method is called by {@link QuickServer} 
+	 *  if Authenticator was set, to authenticate any client
+	 *  connection.
+	 *  @return result of authentication.
+	 *	@exception org.quickserver.net.AppException 
+	 *		if ServerAuthenticator wants QuickServer to close the 
+	 *        client connection. <br>
+	 *        Can be used for exiting on Timeouts<br>
+	 *        Can be used when Quit commands is received when 
+	 *          Authenticating.
+	 * @exception java.io.IOException if there is socket error
+	 */
+	public boolean askAuthorisation(ClientHandler clientHandler) 
+		throws IOException, AppException;
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientAuthenticationHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientAuthenticationHandler.java
new file mode 100644
index 0000000..e7035d7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientAuthenticationHandler.java
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import org.quickserver.net.AppException;
+
+/**
+ * This interface defines a class that can be used by 
+ * QuickServer to authenticate a client when new connection is
+ * made to QuickServer. 
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientAuthenticationHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any data that may is associated with a particular client. 
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+package echoserver;
+
+import java.net.*;
+import java.io.*;
+import org.quickserver.net.server.ClientAuthenticationHandler;
+import org.quickserver.net.server.ClientHandler;
+
+public class EchoAuthenticationHandler 
+		implements ClientAuthenticationHandler {
+
+	public AuthStatus askAuthentication(ClientHandler handler) 
+		throws IOException, AppException {
+		handler.sendClientMsg("Password :");
+		return null;
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, String data) 
+			throws IOException, AppException {
+		if(data.equals("password"))
+			return AuthStatus.SUCCESS;
+		else
+			return AuthStatus.FAILURE;
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, Object data) 
+			throws IOException, AppException {
+		if(true) throw new IOException("Object mode not implemented!");
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, byte data[]) 
+			throws IOException {
+		if(true) throw new IOException("Byte mode not implemented!");
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * @author Akshathkumar Shetty
+ * @since 1.4.6
+ */
+public interface ClientAuthenticationHandler {
+	/**
+	 * Method called first time after gotConnected() method is caled on
+	 * ClientEventHandler, if Authenticator is set.
+	 * Should be used to initate a authorisation process, like asking for username.
+	 * @exception java.io.IOException if io error in socket
+	 * @exception AppException if client socket needs to be closed.
+	 * @return AuthStatus that indicates if authorisation states, if null it 
+	 * is treated as authentication not yet finished.
+	 */
+	public AuthStatus askAuthentication(ClientHandler handler) 
+			throws IOException, AppException;
+
+	/**
+	 * Method called when ever a client sends character/string data
+	 * before authentication.
+	 * @exception java.io.IOException if io error in socket
+	 * @exception AppException if client socket needs to be closed.
+	 * @return AuthStatus that indicates if authorisation states, if null it 
+	 * is treated as authentication not yet finished.
+	 */
+	public AuthStatus handleAuthentication(ClientHandler handler, String data) 
+			throws IOException, AppException;
+
+	/**
+	 * Method called when ever a client sends Object data
+	 * before authentication.
+	 * @exception java.io.IOException if io error in socket
+	 * @exception AppException if client socket needs to be closed.
+	 * @return AuthStatus that indicates if authorisation states, if null it 
+	 * is treated as authentication not yet finished.
+	 */
+	public AuthStatus handleAuthentication(ClientHandler handler, Object data) 
+			throws IOException, AppException;
+
+	/**
+	 * Method called when ever a client sends binary data
+	 * before authentication.
+	 * @exception java.io.IOException if io error in socket
+	 * @exception AppException if client socket needs to be closed.
+	 * @return AuthStatus that indicates if authorisation states, if null it 
+	 * is treated as authentication not yet finished.
+	 */
+	public AuthStatus handleAuthentication(ClientHandler handler, byte data[]) 
+			throws IOException, AppException;
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientBinaryHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientBinaryHandler.java
new file mode 100644
index 0000000..2e8b5c9
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientBinaryHandler.java
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+/**
+ * This interface defines the methods 
+ * that should be implemented by any class that
+ * wants to handle java Objects from a client.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientBinaryHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any data that may is associated with a particular client. 
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+package dateserver;
+
+import java.net.*;
+import java.io.*;
+import java.util.Date;
+import org.quickserver.net.server.*;
+
+public class BinaryHandler implements ClientBinaryHandler {
+
+	public void handleBinary(ClientHandler handler, byte command[]))
+			throws SocketTimeoutException, IOException {
+		handler.sendSystemMsg("Got Binary : " + new String(command));
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public interface ClientBinaryHandler {
+
+	/**
+	 * Method called every time client sends an binary data.
+	 * Should be used to handle the binary data sent.
+	 * @exception java.net.SocketTimeoutException if socket times out
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public void handleBinary(ClientHandler handler, byte command[])
+		throws SocketTimeoutException, IOException;
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientCommandHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientCommandHandler.java
new file mode 100644
index 0000000..a214b43
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientCommandHandler.java
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+/**
+ * This interface defines the methods that should be implemented by any 
+ * class that wants to handle character/string data from client.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientCommandHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any data that may is associated with a particular client. 
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+package echoserver;
+
+import java.net.*;
+import java.io.*;
+import org.quickserver.net.server.ClientCommandHandler;
+import org.quickserver.net.server.ClientHandler;
+
+public class EchoCommandHandler implements ClientCommandHandler {
+
+	public void handleCommand(ClientHandler handler, String command)
+			throws SocketTimeoutException, IOException {
+		if(command.toLowerCase().equals("quit")) {
+			handler.sendClientMsg("Bye ;-)");
+			handler.closeConnection();
+		} else {
+			handler.sendClientMsg("Echo : " + command);
+		}
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * @author Akshathkumar Shetty
+ */
+public interface ClientCommandHandler {
+	/**
+	 * Method called every time client sends character/string data.
+	 * Should be used to handle the command sent and send any 
+	 * requested data.
+	 * @exception java.net.SocketTimeoutException if socket times out
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public void handleCommand(ClientHandler handler, String command)
+		throws SocketTimeoutException, IOException;
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientData.java b/quickserver/src/main/org/quickserver/net/server/ClientData.java
new file mode 100644
index 0000000..a752e68
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientData.java
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+/**
+ * This is a marker interface, which a class can implement to
+ * act has a client data carrier. 
+ * 
+ * This class stores any data associated a client during its 
+ * session with the QuickServer. This class can be used by 
+ * {@link ClientCommandHandler} class to store any data about 
+ * the client it may need in the next call to 
+ * {@link ClientCommandHandler#handleCommand} from the same client.
+ * 
+ * Note: It is recommended the ClientData implementation also 
+ * implement {@link org.quickserver.util.pool.PoolableObject} so that
+ * QuickServer can create a pool of objects and reuse objects from 
+ * that pool, instead of creating an new instance for every client.
+ */
+public interface ClientData extends java.io.Serializable {
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientEvent.java b/quickserver/src/main/org/quickserver/net/server/ClientEvent.java
new file mode 100644
index 0000000..33ad5ba
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientEvent.java
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+
+/**
+ * Encapsulates client event.
+ * @since 1.4.5
+ * @author Akshathkumar Shetty
+ */
+public class ClientEvent {
+	public static final ClientEvent RUN_BLOCKING = new ClientEvent("Run Blocking");	
+	public static final ClientEvent ACCEPT = new ClientEvent("Accept");
+	public static final ClientEvent READ = new ClientEvent("Read");
+	public static final ClientEvent WRITE = new ClientEvent("Write");
+
+	public static final ClientEvent MAX_CON = new ClientEvent("Max Connection");
+	public static final ClientEvent MAX_CON_BLOCKING = new ClientEvent("Max Connection Blocking");
+
+	public static final ClientEvent LOST_CON = new ClientEvent("Lost Connection");
+	public static final ClientEvent CLOSE_CON = new ClientEvent("Close Connection");
+
+	private String event;
+	private ClientEvent(String eventName) {
+		event = "(ClientEvent-"+eventName+")";
+	}
+
+	public String toString() {
+		return event;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientEventHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientEventHandler.java
new file mode 100644
index 0000000..c8856d8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientEventHandler.java
@@ -0,0 +1,105 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+/**
+ * This interface defines the methods that should be implemented by any 
+ * class that wants to handle client events.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientEventHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any data that may is associated with a particular client. 
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * <p>If not ClientEventHandler is set for QuickServer then a 
+ * default implementation {@link org.quickserver.net.server.impl.DefaultClientEventHandler} is used.
+ * </p>
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+package echoserver;
+
+import java.net.*;
+import java.io.*;
+import org.quickserver.net.server.ClientEventHandler;
+import org.quickserver.net.server.ClientHandler;
+
+public class EchoEventHandler implements ClientEventHandler {
+
+	public void gotConnected(ClientHandler handler)
+		throws SocketTimeoutException, IOException {
+		handler.sendSystemMsg("Connection opened : "+
+			handler.getSocket().getInetAddress());
+
+		handler.sendClientMsg("Welcome to EchoServer v1.0 ");
+		handler.sendClientMsg("Note: Password = Username");
+		handler.sendClientMsg("Send 'Quit' to exit");
+	}
+
+	public void lostConnection(ClientHandler handler) 
+		throws IOException {
+		handler.sendSystemMsg("Connection lost : " + 
+			handler.getSocket().getInetAddress());
+	}
+	public void closingConnection(ClientHandler handler) 
+		throws IOException {
+		handler.sendSystemMsg("Connection closing : " + 
+			handler.getSocket().getInetAddress());
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * @since 1.4.5
+ * @author Akshathkumar Shetty
+ */
+public interface ClientEventHandler {
+
+	/**
+	 * Method called when there is a new client connects
+	 * to the QuickServer.
+	 * Can be used to send welcome message to the client and logging.
+	 * @exception java.net.SocketTimeoutException if socket times out
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public void gotConnected(ClientHandler handler)
+		throws SocketTimeoutException, IOException;
+
+	/**
+	 * Method called when client connection is lost.
+	 * Don't write to the connection in this method.
+	 * Its just information, to be used at the Server end.
+	 * It can be caused due to network errors.
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public void lostConnection(ClientHandler handler) 
+		throws IOException;
+
+	/**
+	 * Method called when client connection is closed.
+	 * Don't write to the connection in this method.
+	 * Its just information, you can use to log time and ip of client closing connection.
+ 	 * @exception java.io.IOException if io error in socket
+	 */
+	public void closingConnection(ClientHandler handler) 
+		throws IOException;
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientExtendedEventHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientExtendedEventHandler.java
new file mode 100644
index 0000000..2bbbf6f
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientExtendedEventHandler.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketException;
+/**
+ * This interface defines the methods that should be implemented by any 
+ * class that wants to handle extended client events.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientExtendedEventHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any data that may is associated with a particular client. 
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+package echoserver;
+
+import java.net.*;
+import java.io.*;
+import org.quickserver.net.server.ClientExtendedEventHandler;
+import org.quickserver.net.server.ClientHandler;
+
+public class EchoExtendedEventHandler implements ClientExtendedEventHandler {
+
+	public void handleTimeout(ClientHandler handler) 
+			throws SocketException, IOException {
+		handler.sendClientMsg("-ERR Timeout");
+		if(true) throw new SocketException();
+	}
+
+	public void handleMaxAuthTry(ClientHandler handler) throws IOException {
+		handler.sendClientMsg("-ERR Max Auth Try Reached");
+	}
+
+	public boolean handleMaxConnection(ClientHandler handler) throws IOException {
+		//for now lets reject all excess clients
+		if(true) {
+			handler.sendClientMsg("Server Busy - Max Connection Reached");
+			return false;
+		}
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * @since 1.4.6
+ * @author Akshathkumar Shetty
+ */
+public interface ClientExtendedEventHandler {
+
+	/**
+	 * Method called when client timeouts.
+	 * @exception java.net.SocketException if client socket needs to be closed.
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public void handleTimeout(ClientHandler handler) throws SocketException, IOException;
+
+	/**
+	 * Method called when client has reached maximum auth tries. 
+	 * After this method call QuickServer will close the clients socket.
+	 * Should be used to give error information to the client.
+	 * @exception java.io.IOException if io error in socket
+	 */
+	public void handleMaxAuthTry(ClientHandler handler) throws IOException;
+
+	/**
+	 * Method called when maximum number of clients has been reached and
+	 * a new client connects. If this method return <code>true</code> the 
+	 * client is accepted else client connection is closed.
+ 	 * @exception java.io.IOException if io error in socket
+	 */
+	public boolean handleMaxConnection(ClientHandler handler) throws IOException;
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientHandler.java
new file mode 100644
index 0000000..37e3dc8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientHandler.java
@@ -0,0 +1,552 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.sql.Connection;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.net.ssl.SSLSocket;
+import org.quickserver.util.MyString;
+
+/**
+ * Interface that represents client handle in QuickServer.
+ * <p> This class is used by {@link QuickServer} to handle each new client 
+ * connected. This class is responsible to handle client sockets. It can operate 
+ * in both blocking mode and non-blocking mode (java nio) based on its
+ * implementation.</p>
+ * @author Akshathkumar Shetty
+ */
+public interface ClientHandler extends Runnable {
+
+    /** 
+	 * Adds the ClientEvent. 
+	 * @since 1.4.5
+	 */
+    void addEvent(ClientEvent event);
+
+	/** 
+	 * Removes the ClientEvent. 
+	 * @since 1.4.5
+	 */
+	void removeEvent(ClientEvent event);
+
+    void clean();
+
+    /** Closes client socket associated. */
+    void closeConnection();
+
+    /**
+	 * Force the closing of the client by closing the associated socket.
+	 * @since 1.3.3
+	 */
+    void forceClose() throws IOException;
+
+    /** 
+	 * Returns client SelectionKey associated, if any. 
+	 * @since 1.4.5
+	 */
+    Logger getAppLogger();
+
+    /**
+	 *Returns the {@link java.io.BufferedInputStream} associated with 
+	 * the Client being handled. Can be null if not available at the time of method call. 
+	 * @see #getBufferedOutputStream
+	 * @since 1.4.6
+	 */
+    BufferedInputStream getBufferedInputStream();
+
+    /**
+	 * Returns the {@link java.io.BufferedOutputStream} associated with 
+	 * the Client being handled. Can be null if not available at the time of method call. 
+	 * @see #getBufferedInputStream
+	 * @since 1.4.6
+	 */
+    BufferedOutputStream getBufferedOutputStream();
+
+    /**
+	 * Returns the {@link java.io.BufferedReader} associated with 
+	 * the Client being handled. Note that this is only available under blocking mode. 
+	 * @see #getBufferedWriter
+	 */
+    BufferedReader getBufferedReader();
+
+
+    /**
+     * Returns Charset to be used for String decoding and encoding..
+     * @see #setCharset
+	 * @since 1.4.5
+     */
+    String getCharset();
+
+    /**
+	 * Returns the date/time when the client socket was assigned to this
+	 * ClientHanlder. If no client is currently connected it will return
+	 * <code>null</code>
+	 * @since 1.3.1
+	 */
+    Date getClientConnectedTime();
+
+    /**
+     * Returns the ClientData object associated with this ClientHandler, 
+	 * if not set will return <code>null</code>
+	 * @see ClientData
+     */
+    ClientData getClientData();
+
+    /**
+	 * Returns the communication logging flag.
+	 * @see #setCommunicationLogging
+	 * @since 1.3.2
+	 */
+    boolean getCommunicationLogging();
+
+    /**
+	 * Returns the {@link DataMode} of the ClientHandler for the 
+	 * DataType.
+	 * @since 1.2
+	 */
+    DataMode getDataMode(DataType dataType);
+
+    /**
+	 * Returns cached socket host ip address.
+	 * @since 1.4.5
+	 */
+    String getHostAddress();
+
+    /**
+	 * Returns the {@link java.io.InputStream} associated with 
+	 * the Client being handled.
+	 */
+    InputStream getInputStream();
+
+    /**
+	 * Returns the date/time when the client socket last sent a data to this
+	 * ClientHanlder. If no client is currently connected it will return
+	 * <code>null</code>
+	 * @since 1.3.3
+	 */
+    Date getLastCommunicationTime();
+
+    /**
+	 * Returns message to be displayed to the client when maximum 
+	 * connection reaches.
+	 * @since 1.4.5
+	 */
+    String getMaxConnectionMsg();
+
+    /**
+     * Returns the ClientHandler name
+	 * @since 1.4.6
+     */
+    String getName();
+
+    /**
+	 * Returns the {@link java.io.ObjectInputStream} associated with 
+	 * the Client being handled.
+	 * It will be <code>null</code> if no {@link ClientObjectHandler} 
+	 * was set in {@link QuickServer}.
+	 * @see #getObjectOutputStream
+	 * @since 1.2
+	 */
+    ObjectInputStream getObjectInputStream();
+
+    /**
+	 * Returns the {@link java.io.ObjectOutputStream} associated with 
+	 * the Client being handled.
+	 * It will be <code>null</code> if no {@link ClientObjectHandler} 
+	 * was set in {@link QuickServer}.
+	 * @see #getObjectInputStream
+	 * @since 1.2
+	 */
+    ObjectOutputStream getObjectOutputStream();
+
+    /**
+	 * Returns the {@link java.io.OutputStream} associated with 
+	 * the Client being handled.
+	 * @see #setOutputStream
+	 */
+    OutputStream getOutputStream();
+
+    /** 
+	 * Returns client SelectionKey associated, if any. 
+	 * @since 1.4.5
+	 */
+    SelectionKey getSelectionKey();
+
+    /**
+     * Returns the QuickServer object that created it.
+     */
+    QuickServer getServer();
+
+    /** Returns client socket associated. */
+    Socket getSocket();
+
+    /** 
+	 * Returns client socket channel associated, if any. 
+	 * @since 1.4.5
+	 */
+    SocketChannel getSocketChannel();
+
+    /**
+     * Returns the Client socket timeout in milliseconds.
+	 * @see #setTimeout
+	 * @since 1.4.5
+     */
+    int getTimeout();
+
+    /**
+	 * Associates the ClientHanlder with the client encapsulated by 
+	 * <code>theClient</code>.
+	 * @param theClient object that encapsulates client socket 
+	 *  and its configuration details.
+	 */
+    void handleClient(TheClient theClient) throws Exception;
+
+    /** 
+	 * Checks if this client has the event. 
+	 * @since 1.4.5
+	 */
+    boolean hasEvent(ClientEvent event);
+
+    /**
+     * Returns the ClientHandler detailed information.
+	 * If ClientData is present and is ClientIdentifiable will return ClientInfo else
+	 * it will return Clients InetAddress and port information.
+     */
+    String info();
+
+    /**
+	 * Checks if the passed ClientEvent is the one next for 
+	 * processing if a thread is allowed through this object.
+	 * @since 1.4.6
+	 */
+    boolean isClientEventNext(ClientEvent clientEvent);
+
+    /**
+	 * Checks if the client is closed.
+	 * @since 1.4.1
+	 */
+    boolean isClosed();
+  
+
+    /**
+	 * Checks if the client is still connected.
+	 * @exception SocketException if Socket is not open.
+	 * @since 1.4.5
+	 */
+    boolean isConnected() throws SocketException;
+
+    /**
+	 * Checks if the client is still connected and if socket is open. This is same as isConnected() 
+     * but does not throw SocketException.
+	 * @since 1.4.6
+	 */
+    boolean isOpen();
+
+    /**
+	 * Returns flag indicating if the client is connected in secure mode 
+	 * (SSL or TLS).
+	 * @return secure flag
+	 * @since 1.4.0
+	 */
+    boolean isSecure();
+
+    /**
+	 * Makes current Client connection to secure protocol based on the 
+	 * secure configuration set to the server. This method will just call 
+	 * <code>makeSecure(false, false, true, null)</code>.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+    void makeSecure() throws IOException, NoSuchAlgorithmException, KeyManagementException;
+
+    /**
+	 * Makes current Client connection to secure protocol.
+	 * @param useClientMode falg if the socket should start its first handshake in "client" mode.
+	 * @param needClientAuth flag if the clients must authenticate themselves.
+	 * @param autoClose close the underlying socket when this socket is closed 
+	 * @param protocol the standard name of the requested protocol. If <code>null</code> will use the protocol set in secure configuration of the server.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+    void makeSecure(boolean useClientMode, boolean needClientAuth, boolean autoClose, String protocol) throws IOException, NoSuchAlgorithmException, KeyManagementException;
+
+    /**
+	 * Makes current Client connection to secure protocol.
+	 * This method will just call <code>makeSecure(false, false, true, protocol)</code>.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+    void makeSecure(String protocol) throws IOException, NoSuchAlgorithmException, KeyManagementException;
+
+    /**
+	 * Read the binary input. This will block till some data is
+	 * received from the stream. Allowed only when 
+	 * <code>DataType.IN</code> is in <code>DataMode.BINARY</code> mode.
+	 * @return The data as a String
+	 * @since 1.4
+	 */
+    byte[] readBinary() throws IOException;
+
+    /**
+	 * Read the byte input. This will block till some data is
+	 * received from the stream. Allowed only when 
+	 * <code>DataType.IN</code> is in <code>DataMode.BYTE</code> mode.
+	 * @return The data as a String
+	 * @since 1.3.2
+	 */
+    String readBytes() throws IOException;
+
+    /**
+	 * Register OP_READ with the SelectionKey associated with the channel. If SelectionKey is
+	 * not set then it registers the channel with the Selector.
+	 * @since 1.4.5
+	 */
+    void registerForRead() throws IOException, ClosedChannelException;
+
+    /**
+	 * Register OP_WRITE with the SelectionKey associated with the channel.
+	 * @since 1.4.5
+	 */
+    void registerForWrite() throws IOException, ClosedChannelException;
+
+    void run();
+
+    /**
+	 * Send a binary data to the connected client.
+	 * If client is not connected it will just return.
+	 * @since 1.4
+	 * @exception IOException
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+    void sendClientBinary(byte[] data) throws IOException;
+
+    /**
+	 * Send a binary data to the connected client.
+	 * If client is not connected it will just return.
+	 * @since 1.4.5
+	 * @exception IOException
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+    void sendClientBinary(byte[] data, int off, int len) throws IOException;
+
+    /**
+	 * Send a String message to the connected client as a string of bytes.
+	 * If client is not connected it will just return.
+	 * @since 1.3.1
+	 * @exception IOException
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+    void sendClientBytes(String msg) throws IOException;
+
+    /**
+	 * Send a String message to the connected client
+	 * it adds a new line{\r\n} to the end of the string.
+	 * If client is not connected it will just return.
+	 * @exception IOException 
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+    void sendClientMsg(String msg) throws IOException;
+
+    /**
+	 * Send a Object message to the connected client. The message Object
+	 * passed must be serializable. If client is not connected it 
+	 * will just return.
+	 * @exception IOException if Socket IO Error or Socket was closed 
+	 * by the client.
+	 * @exception IllegalStateException if DataType.OUT is not in 
+	 *  DataMode.OBJECT
+	 * @see #setDataMode
+	 * @since 1.2
+	 */
+    void sendClientObject(Object msg) throws IOException;
+
+    /**
+	 * Send a String message to the logger associated with 
+	 * {@link QuickServer#getAppLogger} with Level.INFO as its level.
+	 */
+    void sendSystemMsg(String msg);
+
+    /**
+	 * Send a String message to the logger associated with 
+	 * {@link QuickServer#getAppLogger}.
+	 * @since 1.2
+	 */
+    void sendSystemMsg(String msg, Level level);
+
+    /**
+     * Sets the Charset to be used for String decoding and encoding.
+	 * @param charset to be used for String decoding and encoding
+	 * @see #getCharset
+	 * @since 1.4.5
+     */
+    void setCharset(String charset);
+
+    /**
+	 * Sets the communication logging flag.
+	 * @see #getCommunicationLogging
+	 * @since 1.3.2
+	 */
+    void setCommunicationLogging(boolean communicationLogging);
+
+    /**
+	 * Sets the {@link DataMode} for the ClientHandler
+	 *
+	 * Note: When mode is DataMode.OBJECT and type is DataType.IN
+	 * this call will block until the client ObjectOutputStream has
+	 * written and flushes the header.
+	 * @since 1.2
+	 * @exception IOException if mode could not be changed.
+	 * @param dataMode mode of data exchange - String or Object.
+	 * @param dataType type of data for which mode has to be set.
+	 */
+    void setDataMode(DataMode dataMode, DataType dataType) throws IOException;
+
+    /** 
+	 * Sets message to be displayed when maximum connection reaches.
+	 * @since 1.4.5
+	 */
+    void setMaxConnectionMsg(String msg);
+
+    /**
+	 * Set the {@link java.io.OutputStream} associated with 
+	 * the Client being handled.
+	 * @since 1.1
+	 * @see #getOutputStream
+	 * @exception IOException if ObjectOutputStream could not be created.
+	 */
+    void setOutputStream(OutputStream out) throws IOException;
+
+    /**
+	 * Sets flag indicating if the client is connected in secure mode 
+	 * (SSL or TLS).
+ 	 * @param secure
+	 * @since 1.4.0
+	 */
+    void setSecure(boolean secure);
+
+    /** 
+	 * Sets client SelectionKey associated, if any. 
+	 * @since 1.4.5
+	 */
+    void setSelectionKey(SelectionKey selectionKey);
+
+    /** 
+	 * Returns client socket associated. 
+	 * @since 1.4.0
+	 * @see #updateInputOutputStreams
+	 */
+    void setSocket(Socket socket);
+
+    /** 
+	 * Sets client socket channel associated, if any. 
+	 * @since 1.4.5
+	 */
+    void setSocketChannel(SocketChannel socketChannel);
+
+    /**
+     * Sets the client socket's timeout.
+	 * @param time client socket timeout in milliseconds.
+	 * @see #getTimeout
+	 * @since 1.4.5
+     */
+    void setTimeout(int time);
+
+    /**
+     * Returns the ClientHandler information.
+	 * If ClientData is present and is ClientIdentifiable will return ClientInfo else
+	 * it will return Clients InetAddress and port information.
+     */
+    String toString();
+
+    /**
+	 * Updates the InputStream and OutputStream for the ClientHandler for the 
+	 * set Socket.
+	 * @since 1.4.0
+	 * @see #setSocket
+	 */
+    void updateInputOutputStreams() throws IOException;
+
+    /**
+	 * Updates the last communication time for this client
+	 * @since 1.3.3
+	 */
+    void updateLastCommunicationTime();
+
+	/**
+	 * Returns the {@link java.sql.Connection} object for the 
+	 * DatabaseConnection that is identified by id passed. If id passed
+	 * does not match with any connection loaded by this class it will
+	 * return <code>null</code>.
+	 * This just calls <code>getServer().getDBPoolUtil().getConnection(id)</code>
+	 * @since 1.3
+	 * @deprecated as of v1.4.5 use <code>getServer().getDBPoolUtil().getConnection(id)</code>
+	 */
+    Connection getConnection(String id) throws Exception;
+
+	 /**
+	 * Checks if the client is still connected.
+	 * @exception SocketException if Socket is not open.
+	 * @deprecated since 1.4.5 Use {@link #isConnected}
+	 */
+    boolean isConected() throws SocketException;
+
+	 /**
+	 * Send a String message to the system output stream.
+	 * @param newline indicates if new line required at the end.
+	 * @deprecated Use {@link #sendSystemMsg(java.lang.String)}, 
+	 *   since it uses Logging.
+	 */
+    void sendSystemMsg(String msg, boolean newline);
+
+	 /**
+	 * Returns the {@link java.io.BufferedWriter} associated with 
+	 * the Client being handled.
+	 * @deprecated since 1.4.5 use getOutputStream()
+	 */
+    BufferedWriter getBufferedWriter();
+	
+	int getTotalReadBytes();
+	int getTotalWrittenBytes();
+	
+	void resetTotalReadBytes();
+	void resetTotalWrittenBytes();
+	
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientIdentifiable.java b/quickserver/src/main/org/quickserver/net/server/ClientIdentifiable.java
new file mode 100644
index 0000000..0150433
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientIdentifiable.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+/**
+ * This is an interface that can be implemented by {@link ClientData}
+ * so that the client connected can be identified.
+ * One can search an client by using
+ * {@link QuickServer#findFirstClientById}, {@link QuickServer#findAllClientById}, 
+ * {@link QuickServer#findClientByKey}, {@link QuickServer#findAllClientByKey}, 
+ * {@link QuickServer#findAllClient}
+ * @since 1.3.1
+ */
+public interface ClientIdentifiable  {
+	/**
+	 * Returns string (hash code) unique for that user connected.
+	 */
+	public String getClientId();
+
+	/**
+	 * Returns string (hash code) unique for that client connected. 
+	 * used to differentiate client that share same user ids.
+	 */
+	public String getClientKey();
+
+	/**
+	 * Returns some inforamtion for that client connected. 
+	 */
+	public String getClientInfo();
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientIdentifier.java b/quickserver/src/main/org/quickserver/net/server/ClientIdentifier.java
new file mode 100644
index 0000000..6f0f05a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientIdentifier.java
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.util.*;
+import org.quickserver.util.pool.QSObjectPool;
+
+/**
+ * Client Identifier interface.
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public interface ClientIdentifier {
+	public void setQuickServer(QuickServer quickserver);
+	public void setClientHandlerPool(QSObjectPool clientHandlerPool);
+	public Object getObjectToSynchronize();
+
+	public Iterator findAllClient();
+
+	public ClientHandler findFirstClientById(String id);
+	public Iterator findAllClientById(String pattern);
+
+	public ClientHandler findClientByKey(String key);
+	public Iterator findAllClientByKey(String pattern);
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientObjectHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientObjectHandler.java
new file mode 100644
index 0000000..74584e5
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientObjectHandler.java
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+/**
+ * This interface defines the methods 
+ * that should be implemented by any class that
+ * wants to handle java Objects from a client.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientObjectHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any client data that may be needed in the 
+ * implementation.
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+package dateserver;
+
+import java.net.*;
+import java.io.*;
+import java.util.Date;
+import org.quickserver.net.server.*;
+
+public class ObjectHandler implements ClientObjectHandler {
+
+	public void handleObject(ClientHandler handler, Object command)
+			throws SocketTimeoutException, IOException {
+		handler.sendSystemMsg("Got Object : " + command.toString());
+		handler.setDataMode(DataMode.STRING);
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * @author Akshathkumar Shetty
+ */
+public interface ClientObjectHandler {
+
+	/**
+	 * Method called every time client sends an Object.
+	 * Should be used to handle the Object sent.
+	 * @exception java.net.SocketTimeoutException if socket times out
+	 * @exception java.io.IOException if io error in socket
+	 * @since v1.2
+	 */
+	public void handleObject(ClientHandler handler, Object command)
+		throws SocketTimeoutException, IOException;
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/ClientWriteHandler.java b/quickserver/src/main/org/quickserver/net/server/ClientWriteHandler.java
new file mode 100644
index 0000000..72f9f77
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/ClientWriteHandler.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+/**
+ * This interface defines the methods that should be implemented by any 
+ * class that needs to be notified when its ready to accept more data.
+ * 
+ * <p>
+ * Recommendations to be followed when implementing ClientWriteHandler
+ * <ul>
+ * <li>Should have a default constructor. 
+ * <li>Should be thread safe.
+ * <li>It should not store any data that may is associated with a particular client. 
+ * <li>If any client data is need to be saved from the client session,  
+ * it should be saved to a {@link ClientData} class, which can be retrieved 
+ * using handler.getClientData() method.
+ * </ul>
+ * </p>
+ * @since 1.4.5
+ * @author Akshathkumar Shetty
+ */
+public interface ClientWriteHandler {
+	/**
+	 * Method called every time client is ready to receive for more data.
+	 * Should be used to handle the write any requested data.
+	 * @exception java.io.IOException if io error in socket/Channel.
+	 */
+	public void handleWrite(ClientHandler handler)
+		throws IOException;
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/DataMode.java b/quickserver/src/main/org/quickserver/net/server/DataMode.java
new file mode 100644
index 0000000..622f03a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/DataMode.java
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+/**
+ * This class defines the mode(format) of data exchange between 
+ * QuickServer and client socket.
+ * <p>
+ * Contributions By: 
+ *   Martin Benns : BYTE Mode
+ * </p>
+ * @since 1.2
+ * @author Akshathkumar Shetty
+ */
+public class DataMode {
+	private String mode;
+	
+	private DataMode(String mode) {
+		this.mode = mode;
+	}
+	
+	public String toString() {
+		return mode;
+	}
+
+	/** 
+	 * String (default) data mode for {@link ClientHandler} 
+	 * - Receive data as String terminated by &lt;CR&gt;&lt;LF&gt
+	 * When {@link ClientHandler} receives any String it calls
+	 * {@link ClientCommandHandler#handleCommand} method
+	 */
+	public static final DataMode STRING = new DataMode("String");
+	
+	/** 
+	 * Object data mode for {@link ClientHandler} 
+	 * - Receive java objects.
+	 * When {@link ClientHandler} receives any Object it calls
+	 * {@link ClientObjectHandler#handleObject} method.
+	 */
+	public static final DataMode OBJECT = new DataMode("Object");
+	
+
+	/**
+	 * Byte data mode for {@link ClientHandler}
+	 * - Receive byte character data stream
+	 * When {@link ClientHandler} receives any bytes it calls
+	 * {@link ClientCommandHandler#handleCommand} method passing the 
+	 * character bytes received  has a String object. This can be used to
+	 * receive String data that are not terminated by &lt;CR&gt; and/or 
+	 * &lt;LF&gt or have &lt;CR&gt; and/or &lt;LF&gt in them.
+	 */
+	public static final DataMode BYTE = new DataMode("Byte");
+
+	/** 
+	 * Binary data mode for {@link ClientHandler} 
+	 * - Receive binary data [byte]
+	 * When {@link ClientHandler} receives any binary it calls
+	 * {@link ClientBinaryHandler#handleBinary} method.
+	 * @since 1.4
+	 */
+	public static final DataMode BINARY = new DataMode("Binary");
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/DataType.java b/quickserver/src/main/org/quickserver/net/server/DataType.java
new file mode 100644
index 0000000..542212e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/DataType.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+/**
+ * This class defines the type(direction) of  data exchanging between 
+ * QuickServer and client socket.
+ * @since 1.2
+ */
+public class DataType {
+	private String type;
+	
+	private DataType(String type) {
+		this.type = type;
+	}
+	
+	public String toString() {
+		return type;
+	}
+
+	/** 
+	 * Incoming data type for {@link ClientHandler} 
+	 */
+	public static final DataType IN = new DataType("Incoming");
+	/** 
+	 * Outgoing data type for {@link ClientHandler} 
+	 */
+	public static final DataType OUT = new DataType("Outgoing");
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/GhostSocketReaper.java b/quickserver/src/main/org/quickserver/net/server/GhostSocketReaper.java
new file mode 100644
index 0000000..9a6327f
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/GhostSocketReaper.java
@@ -0,0 +1,352 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+import org.quickserver.net.*;
+import org.quickserver.util.pool.thread.*;
+import org.quickserver.util.*;
+import org.quickserver.net.server.impl.*;
+
+import java.util.logging.*;
+
+/**
+ * Class (Server Hook) that closes any dead (ghost) sockets that are no 
+ * longer connected or communicating.
+ * <p>
+ * It runs as a daemon thread. This thread will simply return if the socket 
+ * timeout is set to &lt;= 0 in QuickServer. It will close any socket that
+ * has not sent in any communication for more than the socket timeout set, 
+ * i.e., if socket timeout is set to 1000 miliseconds then
+ * if a client socket has not communicated for more than 1 seconds then this 
+ * thread will close the socket and returns the ClientHandler to the pool.
+ * </p>
+ * @author Akshathkumar Shetty
+ * @since 1.3.3
+ */
+public class GhostSocketReaper extends Thread implements ServerHook {
+	private static final Logger logger = Logger.getLogger(GhostSocketReaper.class.getName());
+
+	
+	private QuickServer quickserver;
+	private volatile boolean stopFlag;
+
+	private long timeOut = 0;
+	private long timeOutDelay = 0;
+	private ClientIdentifier clientIdentifier = null;
+	
+	
+	public void initHook(QuickServer quickserver) {
+		this.quickserver = quickserver;
+		clientIdentifier = quickserver.getClientIdentifier();
+	}
+
+	public boolean handleEvent(int event) {
+		if(event==ServerHook.POST_STARTUP) {
+			//logger.finest("Startup Event");
+			setDaemon(true);
+			stopFlag = false;
+			setName("GhostSocketReaper-For-("+quickserver+")");
+			start();
+			return true;
+		} else if(event==ServerHook.POST_SHUTDOWN) {
+			//logger.finest("Shutdown Event");
+			stopFlag = true;
+			return true;
+		}
+		return false;
+	}
+
+	public String info() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("GhostSocketReaper - ServerHook");
+		return sb.toString();
+	}
+
+	public void run() {
+		logger.log(Level.FINE, "Starting GhostSocketReaper thread - {0}", quickserver.getName());
+		if(quickserver.getTimeout()<=0) {
+			stopFlag = true;
+			logger.log(Level.INFO, "Timeout is less than 0, so will exit - {0}", quickserver.getName());
+			return;
+		}
+		timeOut = quickserver.getTimeout();
+
+		if(quickserver.getBasicConfig().getServerMode().getBlocking()==true)
+			timeOutDelay = 1000; //so that it can use SocketTimeoutException
+
+		List ghostList = new ArrayList();
+		long searchSleepTime = timeOut/2;
+		int failCount = 0;
+		boolean flag = false;
+		while(stopFlag==false) {
+			try {
+				try {
+					sleep(searchSleepTime);
+				} catch(InterruptedException ie) {
+					logger.log(Level.WARNING, "InterruptedException : {0}", ie.getMessage());
+				}
+
+				if(failCount<4) {
+					flag = optimisticGhostSocketsFinder(ghostList);
+					if(flag==false)
+						failCount++;
+					else
+						failCount = 0;
+				} else {
+					syncGhostSocketsFinder(ghostList);
+					failCount = 0;
+				}
+				cleanGhostSockets(ghostList, true);
+				
+			} catch(Exception e) {
+				logger.fine("Exception : " + e);
+				if(Assertion.isEnabled()) {
+					logger.finest("StackTrace:\n"+MyString.getStackTrace(e));
+				}
+			}
+		}//end of while
+
+		//wait till all client have disconnected.. then clean the pool 
+		while(stopFlag==true) {
+			try {
+				try {
+					sleep(searchSleepTime);
+				} catch(InterruptedException ie) {
+					logger.warning("InterruptedException : " + ie.getMessage());
+				}
+
+				if(quickserver.isClosed()==false) {
+					break;
+				}
+
+				if(quickserver.getClientCount()<=0) {
+					try {
+						Thread.yield();
+						sleep(1000);//lets wait for objects to come back to pool
+					} catch(InterruptedException ie) {
+						logger.warning("InterruptedException : " + ie.getMessage());
+					}
+					quickserver.closeAllPools();
+					break;
+				}
+			} catch(Exception e) {
+				logger.fine("Exception : " + e);
+				if(Assertion.isEnabled()) {
+					logger.finest("StackTrace:\n"+MyString.getStackTrace(e));
+				}
+				break;
+			}
+		}
+		logger.log(Level.INFO, "Returning from GhostSocketReaper thread - {0}", quickserver.getName());
+	}
+
+	private long getCurrentTime() {
+		return new Date().getTime();
+	}
+
+	private boolean optimisticGhostSocketsFinder(List list) {
+		Iterator iterator = null;
+		ClientHandler clientHandler = null;
+		int count = 0;
+		long currentTime = getCurrentTime();
+		try {
+			iterator = clientIdentifier.findAllClient();
+			/*
+			if(iterator.hasNext()) {
+				logger.finest("ENTER");
+			}
+			*/
+
+			while(iterator.hasNext()) {
+				count++;
+				if(count==60) {
+					currentTime = getCurrentTime(); //update time
+					count = 1;
+				}
+				clientHandler = (ClientHandler)iterator.next();
+				
+				checkClientHandlerForGhostSocket(clientHandler, currentTime, list);
+
+				if(list.size()>100) {
+					logger.fine("Found about 100 ghost sockets, lets clean..");
+					break;
+				}
+			}//end of while
+		} catch(ConcurrentModificationException e) {
+			//ignore
+			return false;
+		}
+		return true;
+	}
+
+	private void syncGhostSocketsFinder(List list) {
+		Iterator iterator = null;
+		ClientHandler clientHandler = null;
+		int count = 0;
+		long currentTime = getCurrentTime();
+		synchronized(clientIdentifier.getObjectToSynchronize()) {
+			iterator = clientIdentifier.findAllClient();
+			if(iterator.hasNext())
+				logger.finest("ENTER");
+
+			while(iterator.hasNext()) {
+				count++;
+				if(count==60) {
+					currentTime = getCurrentTime(); //update time
+					count = 1;
+				}
+				clientHandler = (ClientHandler)iterator.next();
+				
+				checkClientHandlerForGhostSocket(clientHandler, currentTime, list);
+
+				if(list.size()>100) {
+					logger.fine("Found about 100 ghost sockets, lets clean..");
+					break;
+				}
+			}//end of while
+		} 
+	}
+
+	private void cleanGhostSockets(List list, boolean checkTimeout) {
+		long currentTime = getCurrentTime();
+		long commTime = 0;		
+		long diff = -1;
+		long closedCount = 0;
+		ClientHandler clientHandler = null;
+
+		int size = list.size();
+		if(size>0) {
+			logger.log(Level.INFO, "Found ghost sockets: {0}", size);
+		} else {
+			return;
+		}
+		for(int i=0;i<size;i++) {
+			try	{
+				clientHandler = (ClientHandler) list.get(i);
+				
+				if(((BasicClientHandler)clientHandler).getWillClean()==true) {
+					logger.log(Level.FINEST, "Not closing client {0}, WillClean is true", clientHandler);
+					continue;
+				}
+				
+				if(checkTimeout) {
+					timeOut = clientHandler.getTimeout()+timeOutDelay;
+					if(clientHandler.getLastCommunicationTime()!=null) {
+						commTime = clientHandler.getLastCommunicationTime().getTime();
+						diff = currentTime-commTime;
+
+						if(diff < timeOut && clientHandler.isClosed()==false) {
+							logger.log(Level.FINEST, 
+								"Not closing client {0}, must have been reassigned. CommTime(sec): {1}, Diff(sec): {2}",
+								new Object[]{clientHandler, commTime/1000, diff/1000});
+							continue;
+						}
+					}
+				}//end of if checkTimeout
+
+				if(clientHandler.isClosed()==false) {				
+					logger.log(Level.FINEST, "Closing client {0}", clientHandler.getName());
+					closedCount++;
+					
+					try {
+						if(clientHandler.hasEvent(ClientEvent.RUN_BLOCKING)==true) {
+							clientHandler.closeConnection();							
+						} else {
+							if( ((NonBlockingClientHandler)clientHandler).getThreadAccessCount()!=0 ) {
+								clientHandler.closeConnection();
+
+								Object obj = clientHandler.getInputStream();
+								if(obj!=null) {
+									synchronized(obj) {
+										clientHandler.getInputStream().notifyAll();
+									}
+								}
+							} else {
+								clientHandler.addEvent(ClientEvent.CLOSE_CON);
+								quickserver.getClientPool().addClient(clientHandler);
+							}
+						}
+					} catch(Exception er) {
+						logger.log(Level.FINE, "Error closing client {0} : {1}", 
+							new Object[]{clientHandler, er});
+						clientHandler.forceClose();
+					}
+				} else {
+					if(clientHandler.hasEvent(ClientEvent.RUN_BLOCKING)==false) {
+						logger.log(Level.FINEST, "Notifying IO of client {0}", clientHandler);
+						Object obj = clientHandler.getInputStream();
+						if(obj==null) continue;
+						synchronized(obj) {
+							clientHandler.getInputStream().notifyAll();
+						}
+					
+						logger.log(Level.FINEST, "Returning objs to pool {0}", clientHandler);
+						if(quickserver.getClientDataPool()!=null && clientHandler.getClientData()!=null)
+							quickserver.getClientDataPool().returnObject(clientHandler.getClientData());
+
+						logger.log(Level.FINEST, "{0} returning {1}", 
+							new Object[]{Thread.currentThread().getName(), getName()});
+						quickserver.getClientHandlerPool().returnObject(clientHandler);
+					} else {
+						logger.log(Level.FINEST, 
+							"Skipping closed {0} since in blocking mode.. this should clean up it self.", clientHandler);
+					}					
+				}
+			} catch(Exception ee) {
+				logger.log(Level.FINE, "Exception forcing the close : {0}", ee);
+				if(Assertion.isEnabled()) {
+					logger.log(Level.FINEST, "StackTrace:\n{0}", MyString.getStackTrace(ee));
+				}
+			} 
+		}//end of for
+		logger.log(Level.INFO, "We closed : {0}", closedCount);
+		list.clear(); 
+	}
+
+	private void checkClientHandlerForGhostSocket(ClientHandler clientHandler,
+			long currentTime, List list) {
+		if(clientHandler==null)
+			return;
+
+
+		if(clientHandler.isClosed()) {
+			logger.log(Level.FINEST, 
+				"Not connected .. so returning ClientData and ClientHandler objects for : {0}", clientHandler);
+			list.add(clientHandler);
+			return;
+		}
+		
+		if(clientHandler.getTimeout()<=0) {
+			//logger.finest("ClientHandler's timeout is <=0, so skipping.");
+			return;
+		}
+
+		if(clientHandler.getLastCommunicationTime()==null) return;
+
+		long commTime = clientHandler.getLastCommunicationTime().getTime();
+		long diff = currentTime-commTime;
+
+		long timeOutToUse = clientHandler.getTimeout()+timeOutDelay;		
+		if(diff >= timeOutToUse) {
+			logger.log(Level.FINE, "Closable client {0}, Time diff(sec) : {1}", 
+				new Object[]{clientHandler, diff/1000});
+			list.add(clientHandler);
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/PoolManager.java b/quickserver/src/main/org/quickserver/net/server/PoolManager.java
new file mode 100644
index 0000000..9dbf5ee
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/PoolManager.java
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import org.apache.commons.pool.*;
+import org.quickserver.util.pool.thread.ClientPool;
+import org.quickserver.util.xmlreader.PoolConfig;
+
+/**
+ * PoolManager interface.
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public interface PoolManager {
+	public ObjectPool makeByteBufferPool(PoolableObjectFactory factory, PoolConfig opConfig);
+	public ObjectPool makeClientPool(PoolableObjectFactory factory, PoolConfig opConfig);
+	public ObjectPool makeClientHandlerPool(PoolableObjectFactory factory, PoolConfig opConfig);
+	public ObjectPool makeClientDataPool(PoolableObjectFactory factory, PoolConfig opConfig);
+	public void initPool(ObjectPool objectPool, PoolConfig opConfig);
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/QuickAuthenticationHandler.java b/quickserver/src/main/org/quickserver/net/server/QuickAuthenticationHandler.java
new file mode 100644
index 0000000..ed275f0
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/QuickAuthenticationHandler.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+import org.quickserver.net.AppException;
+import org.quickserver.net.ConnectionLostException;
+import org.quickserver.util.io.*;
+
+/**
+ * This class is used to authenticate a client when 
+ * it connects to QuickServer. Only single instance of this class
+ * will be used per QuickServer to handle all authentication.
+ * Should have a default constructor. 
+ *
+ * @author Akshathkumar Shetty
+ * @since 1.4.6
+ */
+public abstract class QuickAuthenticationHandler 
+		implements ClientAuthenticationHandler {
+
+	public AuthStatus askAuthentication(ClientHandler handler) 
+		throws IOException, AppException {
+		return null;
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, String data) 
+			throws IOException, AppException {
+		if(true) throw new RuntimeException("String/Byte mode not implemented!");
+		return null;
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, Object data) 
+			throws IOException, AppException {
+		if(true) throw new RuntimeException("String/Byte mode not implemented!");
+		return null;
+	}
+
+	public AuthStatus handleAuthentication(ClientHandler handler, byte data[]) 
+			throws IOException {
+		if(true) throw new RuntimeException("String/Byte mode not implemented!");
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/net/server/QuickAuthenticator.java b/quickserver/src/main/org/quickserver/net/server/QuickAuthenticator.java
new file mode 100644
index 0000000..2500429
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/QuickAuthenticator.java
@@ -0,0 +1,230 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.net.SocketTimeoutException;
+import org.quickserver.net.AppException;
+import org.quickserver.net.ConnectionLostException;
+import org.quickserver.util.io.*;
+
+/**
+ * This class is used to authenticate a client when 
+ * it connects to QuickServer. Only single instance of this class
+ * will be used per QuickServer to handle all authentication.
+ * Should have a default constructor. 
+ * <p>
+ * Ex:
+ * <code><BLOCKQUOTE><pre>
+ package echoserver;
+
+import org.quickserver.net.server.*;
+import java.io.*;
+
+public class EchoServerQuickAuthenticator extends QuickAuthenticator {
+
+	public boolean askAuthorisation(ClientHandler clientHandler) 
+			throws IOException {		
+		String username = askStringInput(clientHandler, "User Name :");
+		String password = askStringInput(clientHandler, "Password :");
+
+		if(username==null || password ==null)
+			return false;
+		
+		if(username.equals(password)) {
+			sendString(clientHandler, "Auth OK");
+			return true;
+		} else {
+			sendString(clientHandler, "Auth Failed");
+			return false;
+		}
+	}
+}
+ </pre></BLOCKQUOTE></code></p>
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public abstract class QuickAuthenticator 
+		implements Authenticator {
+
+	public abstract boolean askAuthorisation(ClientHandler clientHandler) 
+		throws IOException, AppException;
+
+
+	/**
+	 * Prints the given message to the client.
+	 * @param msg Message to send.
+	 * If <code>null</code> is passed it will not send any thing.
+	 */
+	public void sendString(ClientHandler clientHandler, String msg) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.STRING)
+				clientHandler.setDataMode(DataMode.STRING, DataType.OUT);
+			clientHandler.sendClientMsg(msg);
+		}
+	}
+
+	/**
+	 * Prints the given message to the client and reads a line of input.
+	 * @return the line of input read from the client.
+	 * @param msg Message to send before reading input. If received String is 
+	 * <code>null</code> it will throw {@link ConnectionLostException}.
+	 * If <code>null</code> is passed it will not send any thing.
+	 * @exception IOException if an I/O error occurs
+	 */
+	public String askStringInput(ClientHandler clientHandler, String msg) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.STRING)
+				clientHandler.setDataMode(DataMode.STRING, DataType.OUT);
+			clientHandler.sendClientMsg(msg);
+		}
+		if(clientHandler.getDataMode(DataType.IN)!=DataMode.STRING)
+			clientHandler.setDataMode(DataMode.STRING, DataType.IN);
+
+		String data = null;
+		if(clientHandler.hasEvent(ClientEvent.RUN_BLOCKING)) {
+			data = clientHandler.getBufferedReader().readLine();
+		} else {
+			ByteBufferInputStream bbin = (ByteBufferInputStream) 
+				clientHandler.getInputStream();
+			data = bbin.readLine();
+		}
+
+		if(data!=null) 
+			return data;
+		else
+			throw new ConnectionLostException();
+	}
+
+	/**
+	 * Sends the given object to the client.
+	 * @param msg Message to send.
+	 * If <code>null</code> is passed it will not send any thing.
+	 */
+	public void sendObject(ClientHandler clientHandler, Object msg) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.OBJECT)
+				clientHandler.setDataMode(DataMode.OBJECT, DataType.OUT);
+			clientHandler.sendClientObject(msg);
+		}
+	}
+
+	/**
+	 * Prints the given message to the client and reads a Object from input.
+	 * @return the Object from input read from the client. If received Object is 
+	 * <code>null</code> it will throw {@link ConnectionLostException}.
+	 * @param msg Message to send before reading input.
+	 * If <code>null</code> is passed it will not send any thing.
+	 * @exception IOException if an I/O error occurs
+	 */
+	public Object askObjectInput(ClientHandler clientHandler, Object msg) 
+			throws IOException, ClassNotFoundException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.OBJECT)
+				clientHandler.setDataMode(DataMode.OBJECT, DataType.OUT);
+			clientHandler.sendClientObject(msg);
+		}
+		if(clientHandler.getDataMode(DataType.IN)!=DataMode.OBJECT)
+			clientHandler.setDataMode(DataMode.OBJECT, DataType.IN);
+		Object data = clientHandler.getObjectInputStream().readObject();
+		if(data!=null) 
+			return data;
+		else
+			throw new ConnectionLostException();
+	}
+
+	/**
+	 * Prints the given message to the client.
+	 * @param msg Message to send.
+	 * If <code>null</code> is passed it will not send any thing.
+	 * @since 1.3.2
+	 */
+	public void sendByte(ClientHandler clientHandler, String msg) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.BYTE)
+				clientHandler.setDataMode(DataMode.BYTE, DataType.OUT);
+			clientHandler.sendClientBytes(msg);
+		}
+	}
+
+	/**
+	 * Prints the given message to the client and reads a line of input.
+	 * @return the line of input read from the client. If received byte is 
+	 * <code>null</code> it will throw {@link ConnectionLostException}.
+	 * @param msg Message to send before reading input.
+	 * If <code>null</code> is passed it will not send any thing.
+	 * @exception IOException if an I/O error occurs
+	 * @since 1.3.2
+	 */
+	public String askByteInput(ClientHandler clientHandler, String msg) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.BYTE)
+				clientHandler.setDataMode(DataMode.BYTE, DataType.OUT);
+			clientHandler.sendClientBytes(msg);
+		}
+		if(clientHandler.getDataMode(DataType.IN)!=DataMode.BYTE)
+			clientHandler.setDataMode(DataMode.BYTE, DataType.IN);
+		String data = clientHandler.readBytes();
+		if(data!=null) 
+			return data;
+		else
+			throw new ConnectionLostException();
+	}
+
+	/**
+	 * Sends the given binary data to the client.
+	 * @param msg binary data to send.
+	 * If <code>null</code> is passed it will not send any thing.
+	 * @since 1.4
+	 */
+	public void sendBinary(ClientHandler clientHandler, byte msg[]) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.BINARY)
+				clientHandler.setDataMode(DataMode.BINARY, DataType.OUT);
+			clientHandler.sendClientBinary(msg);
+		}
+	}
+
+	/**
+	 * Sends the given binary data to the client and reads binary data input.
+	 * @return the binary data input read from the client. If received byte is 
+	 * <code>null</code> it will throw {@link ConnectionLostException}.
+	 * @param msg binary data to send before reading input.
+	 * If <code>null</code> is passed it will not send any thing.
+	 * @exception IOException if an I/O error occurs
+	 * @since 1.4
+	 */
+	public byte[] askBinaryInput(ClientHandler clientHandler, byte msg[]) 
+			throws IOException {
+		if(msg!=null) {
+			if(clientHandler.getDataMode(DataType.OUT)!=DataMode.BINARY)
+				clientHandler.setDataMode(DataMode.BINARY, DataType.OUT);
+			clientHandler.sendClientBinary(msg);
+		}
+		if(clientHandler.getDataMode(DataType.IN)!=DataMode.BINARY)
+			clientHandler.setDataMode(DataMode.BINARY, DataType.IN);
+		byte[] data = clientHandler.readBinary();
+		if(data!=null) 
+			return data;
+		else
+			throw new ConnectionLostException();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/QuickServer.java b/quickserver/src/main/org/quickserver/net/server/QuickServer.java
new file mode 100644
index 0000000..d2317da
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/QuickServer.java
@@ -0,0 +1,3416 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.io.*;
+import java.lang.management.ManagementFactory;
+import java.net.*;
+
+import org.quickserver.net.*;
+//v1.1
+import org.quickserver.net.qsadmin.*;
+//v1.2
+import java.util.logging.*;
+//v1.3
+import org.quickserver.util.pool.*;
+import org.quickserver.util.pool.thread.*;
+import org.apache.commons.pool.*;
+import org.quickserver.util.xmlreader.*;
+import org.quickserver.sql.*;
+//v1.3.1
+import java.util.logging.Formatter;
+import java.util.*;
+//v1.3.2
+import org.quickserver.util.*;
+//v1.3.3
+import org.quickserver.security.*;
+//v1.4.0
+import javax.net.ssl.*;
+import javax.net.*;
+import java.security.*;
+import java.security.cert.*;
+//v1.4.5
+import java.nio.channels.*;
+import org.quickserver.net.server.impl.*;
+
+/**
+ * Main class of QuickServer library. This class is used to create 
+ * multi client servers quickly.
+ * <p>
+ * Ones a client is connected, it creates {@link ClientHandler} object, 
+ * which is run using any thread available from the pool of threads 
+ * maintained by {@link org.quickserver.util.pool.thread.ClientPool}, which 
+ * handles the client. <br/>
+ * QuickServer divides the application logic of its developer over eight 
+ * class, <br>
+ * 	<ul>
+ *		<li>ClientEventHandler<br>
+ * 		   &nbsp;Handles client events [Optional Class].
+ * 		<li>ClientCommandHandler [#]<br>
+ * 		   &nbsp;Handles client character/string commands.
+ * 		<li>ClientObjectHandler [#]<br>
+ * 		   &nbsp;Handles client interaction - Object commands.
+ *		<li>ClientBinaryHandler [#]<br>
+ * 		   &nbsp;Handles client interaction - binary data.
+ *		<li>ClientWriteHandler [Optional Class]<br>
+ * 		   &nbsp;Handles client interaction - writing data (Only used in non-blocking mode).
+ * 		<li>ClientAuthenticationHandler [Optional Class]<br>
+ * 			&nbsp;Used to Authencatet a client.
+ * 		<li>ClientData [Optional Class]<br>
+ * 			&nbsp;Client data carrier (support class)
+ *		<li>ClientExtendedEventHandler [Optional Class]<br>
+ * 		   &nbsp;Handles extended client events.
+ * 	</ul>
+ *
+ * [#] = Any one of these have to be set based on default DataMode for input. 
+ * The default DataMode for input is String so if not changes you will
+ * have to set ClientCommandHandler.
+ * </p>
+ * <p>
+ *  Eg:
+ * <code><BLOCKQUOTE><pre>
+package echoserver;
+
+import org.quickserver.net.*;
+import org.quickserver.net.server.*;
+
+import java.io.*;
+
+public class EchoServer {
+	public static void main(String args[])	{
+		String cmdHandle = "echoserver.EchoCommandHandler";
+	
+		QuickServer myServer = new QuickServer();
+		myServer.setClientCommandHandler(cmdHandle);
+		myServer.setPort(4123);
+		myServer.setName(Echo Server v1.0");
+		try {
+			myServer.startServer();
+		} catch(AppException e) {
+			System.err.println("Error in server : "+e);
+			e.printStackTrace();
+		}
+	}
+}
+</pre></BLOCKQUOTE></code></p>
+ * 
+ * @version 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public class QuickServer implements Runnable, Service, Cloneable, Serializable {
+	//Some variable are not initialised to any value because the 
+	//default java value was desired initial value. 
+
+	//'dev ' = development build not yet final
+	//'beta' = test build all features
+	private final static String VER = "2.1.0";//change also in QSAdminMain
+	private final static String NEW_LINE;
+	private final static String pid;
+	
+
+	static {
+		if(System.getProperty("org.quickserver.useOSLineSeparator")!=null && 
+			System.getProperty("org.quickserver.useOSLineSeparator").equals("true")) {
+			NEW_LINE = System.getProperty("line.separator");
+		} else {
+			NEW_LINE = "\r\n";
+		}
+		String _pid = ManagementFactory.getRuntimeMXBean().getName();
+		int i = _pid.indexOf("@");
+		pid = _pid.substring(0, i);
+		System.out.print("Loading QuickServer v"+getVersion()+" [PID:"+pid+"]");
+	}
+
+	private String serverBanner;
+
+	private String clientAuthenticationHandlerString; //v1.4.6
+	private String clientEventHandlerString; //v1.4.6
+	private String clientExtendedEventHandlerString; //v1.4.6
+	private String clientCommandHandlerString;
+	private String clientObjectHandlerString; //v1.2
+	private String clientBinaryHandlerString; //v1.4
+	private String clientWriteHandlerString; //v1.4.5
+	private String clientDataString;
+	
+	private Authenticator authenticator;
+	private ClientAuthenticationHandler clientAuthenticationHandler; //v1.4.6
+	private ClientEventHandler clientEventHandler; //v1.4.6
+	private ClientExtendedEventHandler clientExtendedEventHandler; //v1.4.6
+	private ClientCommandHandler clientCommandHandler;
+	private ClientObjectHandler clientObjectHandler; //v1.2
+	private ClientBinaryHandler clientBinaryHandler; //v1.4
+	private ClientWriteHandler clientWriteHandler; //v1.4.5
+	private ClientData clientData;
+	protected Class clientDataClass;
+
+	private int serverPort = 9876;
+	private Thread t; //Main thread
+	protected ServerSocket server;
+	private String serverName = "QuickServer";
+	private long maxConnection = -1;
+	private int socketTimeout = 60 * 1000; //1 min socket timeout
+	private String maxConnectionMsg = "-ERR Server Busy. Max Connection Reached";	
+	private String timeoutMsg = "-ERR Timeout";
+	private String maxAuthTryMsg = "-ERR Max Auth Try Reached";
+	private int maxAuthTry = 5; //v1.2	
+
+	static {
+		System.out.print(".");
+	}
+
+	//--v1.1
+	private InetAddress ipAddr;
+	protected boolean stopServer;
+	private Object[] storeObjects;
+	private QSAdminServer adminServer;
+
+	//--v1.2
+	//Logger for QuickServer
+	private static final Logger logger = Logger.getLogger(QuickServer.class.getName());
+	//Logger for the application using this QuickServer
+	private Logger appLogger;
+
+	//for Service interface
+	private long suspendMaxConnection; //backup
+	private String suspendMaxConnectionMsg; //backup
+	private int serviceState = Service.UNKNOWN;
+
+	static {
+		System.out.print(".");
+	}
+
+	//--v1.3
+	private QuickServerConfig config = new QuickServerConfig();
+	private String consoleLoggingformatter;
+	private String consoleLoggingLevel = "INFO";
+	private ClientPool pool;
+	private ObjectPool clientHandlerPool;
+	private ObjectPool clientDataPool;
+	private DBPoolUtil dBPoolUtil;
+
+	//--v1.3.1
+	private String loggingLevel = "INFO";
+
+	//--v1.3.2
+	private boolean skipValidation = false;
+	private boolean communicationLogging = true;
+
+	//--v1.3.3
+	private String securityManagerClass;
+	private AccessConstraintConfig accessConstraintConfig;
+	private ClassLoader classLoader;
+	private String applicationJarPath;
+	private ServerHooks serverHooks;
+	private ArrayList listOfServerHooks;
+
+	static {
+		System.out.print(".");
+	}
+	
+	//--v1.4.0
+	private Secure secure;
+	private BasicServerConfig basicConfig = config;
+	private SSLContext sslc;
+	private KeyManager km[] = null;
+	private TrustManager tm[] = null;
+	private boolean runningSecure = false;
+	private SecureStoreManager secureStoreManager = null;
+	
+	private Exception exceptionInRun = null;
+
+	//--v1.4.5
+	private ServerSocketChannel serverSocketChannel;
+	private Selector selector;
+	private boolean blockingMode = true;
+	private ObjectPool byteBufferPool;
+	private java.util.Date lastStartTime;
+	private ClientIdentifier clientIdentifier;
+	private GhostSocketReaper ghostSocketReaper;
+	private PoolManager poolManager;
+	private QSObjectPoolMaker qsObjectPoolMaker;
+
+	//--v1.4.6
+	private DataMode defaultDataModeIN = DataMode.STRING;
+	private DataMode defaultDataModeOUT = DataMode.STRING;
+
+	//-v1.4.7
+	private Throwable serviceError;
+	private Map registerChannelRequestMap;
+	
+	//v-1.4.8
+	private boolean rawCommunicationLogging = false;
+	private int rawCommunicationMaxLength = 100;
+
+	static {
+		System.out.println(" Done");
+		//should be commented if not a patch release
+		//System.out.println("[Includes patch(#): t=152&p=532]");
+		//should be commented if not a dev release
+		//System.out.println("[Dev Build Date: Saturday, October 29, 2005]");
+		logger.log(Level.FINE, "PID: {0}", pid);
+	}
+	
+	/** Returns the version of the library. */
+	public static final String getVersion() {
+		return VER;
+	}
+
+	/** 
+	 * Returns the numerical version of the library.
+	 * @since 1.2
+	 */
+	public static final float getVersionNo() {
+		return getVersionNo(VER);
+	}
+
+	/** 
+	 * Returns the numerical version of the library.
+	 * @since 1.4.5
+	 */
+	public static final float getVersionNo(String ver) {
+		//String ver = getVersion();
+		float version = 0;
+		int i = ver.indexOf(" "); //check if beta
+		if(i == -1)
+			i = ver.length();
+		ver = ver.substring(0, i);
+		
+		i = ver.indexOf("."); //check for sub version
+		if(i!=-1) {
+			int j = ver.indexOf(".", i);
+			if(j!=-1) {
+				ver = ver.substring(0, i)+"."+
+					MyString.replaceAll(ver.substring(i+1), ".", "");
+			}
+		}
+
+		try	{
+			version = Float.parseFloat(ver);	
+		} catch(NumberFormatException e) {
+			throw new RuntimeException("Corrupt QuickServer");
+		}
+		return version;
+	}
+
+	/**
+	 * Returns the new line string used by QuickServer.
+	 * @since 1.2
+	 */
+	public static String getNewLine() {
+		return NEW_LINE;
+	}
+
+	/**
+     * Returns the Server name : port of the QuickServer.
+     */
+	public String toString() {
+		return serverName + " : " + getPort();
+	}
+
+	/**
+	 * Creates a new server without any configuration.
+	 * Make sure you configure the QuickServer, before 
+	 * calling startServer()
+	 * @see org.quickserver.net.server.ClientEventHandler
+	 * @see org.quickserver.net.server.ClientCommandHandler
+	 * @see org.quickserver.net.server.ClientObjectHandler
+	 * @see org.quickserver.net.server.ClientBinaryHandler
+ 	 * @see org.quickserver.net.server.ClientWriteHandler
+	 * @see org.quickserver.net.server.ClientAuthenticationHandler
+	 * @see org.quickserver.net.server.ClientHandler
+ 	 * @see #configQuickServer
+	 * @see #initService
+	 * @see #setPort
+	 * @see #setClientCommandHandler
+	 * @since 1.2
+	 */
+	public QuickServer() {
+	}
+
+	/**
+	 * Creates a new server with the specified  
+	 * <code>commandHandler</code> has it {@link ClientCommandHandler}.
+	 * @param commandHandler the fully qualified name of the 
+	 *  desired class that implements {@link ClientCommandHandler}
+	 *
+	 * @see org.quickserver.net.server.ClientCommandHandler
+	 * @see org.quickserver.net.server.ClientAuthenticationHandler
+	 * @see org.quickserver.net.server.ClientHandler
+	 * @see #setPort
+	 */
+	public QuickServer(String commandHandler) {
+		setClientCommandHandler(commandHandler);
+	}
+
+	/**
+	 * Creates a new server at <code>port</code> with the specified  
+	 * <code>commandHandler</code> has it {@link ClientCommandHandler}.
+	 *
+	 * @param commandHandler fully qualified name of the class that
+	 * implements {@link ClientCommandHandler}
+	 * @param port to listen on.
+	 *
+	 * @see org.quickserver.net.server.ClientCommandHandler
+	 * @see org.quickserver.net.server.ClientAuthenticationHandler
+	 * @see org.quickserver.net.server.ClientHandler
+	 */
+	public QuickServer(String commandHandler,int port) {
+		this(commandHandler); //send to another constructor
+		setPort(port);		
+	}
+
+	/**
+	 * Starts the QuickServer.
+	 *
+	 * @exception org.quickserver.net.AppException 
+	 *  if Server already running or if it could not load the classes
+	 *  [ClientCommandHandler, ClientAuthenticationHandler, ClientData].
+	 * @see #startService
+	 */
+	public void startServer() throws AppException {
+		logger.log(Level.FINE, "Starting {0}", getName());
+
+		if(isClosed() == false) {
+			logger.log(Level.WARNING, "Server {0} already running.", getName());
+			throw new AppException("Server "+getName()+" already running.");
+		}
+		
+		blockingMode = getBasicConfig().getServerMode().getBlocking();
+		
+		if(blockingMode==false) {
+				logger.warning("QuickServer no longer supports non-blocking mode! So will run in blocking mode.");
+				blockingMode = true;
+				getBasicConfig().getServerMode().setBlocking(blockingMode);
+		}
+		
+		if(serverBanner == null) {
+			serverBanner = "\n-------------------------------" + 
+				           "\n Name : " + getName() +
+						   "\n Port : " + getPort() + 
+						   "\n-------------------------------\n";
+			logger.finest("Default Server Banner Generated");
+		}
+		try	{
+			loadApplicationClasses();
+
+			//load class from Advanced Settings
+			Class clientIdentifierClass = 
+				getClass(getBasicConfig().getAdvancedSettings().getClientIdentifier(), true);
+			clientIdentifier = (ClientIdentifier) 
+				clientIdentifierClass.newInstance();
+			clientIdentifier.setQuickServer(QuickServer.this);
+
+			//load class from ObjectPoolConfig
+			Class poolManagerClass = 
+				getClass(getBasicConfig().getObjectPoolConfig().getPoolManager(), true);
+			poolManager = (PoolManager) poolManagerClass.newInstance();
+
+			//load class QSObjectPoolMaker
+			Class qsObjectPoolMakerClass = getClass(
+				getBasicConfig().getAdvancedSettings().getQsObjectPoolMaker(), true);
+			qsObjectPoolMaker = (QSObjectPoolMaker) qsObjectPoolMakerClass.newInstance();
+
+			loadServerHooksClasses();
+			processServerHooks(ServerHook.PRE_STARTUP);
+			
+			if(getSecure().isLoad()==true)
+				loadSSLContext(); //v1.4.0
+
+			loadBusinessLogic();
+		} catch(ClassNotFoundException e) {
+			logger.log(Level.SEVERE, "Could not load class/s: "+e, e);
+			throw new AppException("Could not load class/s : " + e);
+		} catch(InstantiationException e) {
+			logger.log(Level.SEVERE, "Could not instantiate class/s: "+e, e);
+			throw new AppException("Could not instantiate class/s: "+e);
+		} catch(IllegalAccessException e) {
+			logger.log(Level.SEVERE, "Illegal access to class/s: "+e, e);
+			throw new AppException("Illegal access to class/s: " + e);
+		} catch(IOException e) {
+			logger.log(Level.SEVERE, "IOException: "+e, e);
+			throw new AppException("IOException: " + e);
+		} catch(Exception e) {
+			logger.log(Level.SEVERE, "Exception: "+e, e);
+			logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(e));
+			throw new AppException("Exception : " + e);
+		}
+
+		//v1.3.3
+		if(getSecurityManagerClass()!=null) {
+			System.setSecurityManager(getSecurityManager());
+		}
+		
+		
+
+		setServiceState(Service.INIT);
+		t = new Thread(this, "QuickServer - "+getName());
+		t.start();
+
+		do {
+			Thread.yield();	
+		} while(getServiceState()==Service.INIT);
+
+		if(getServiceState()!=Service.RUNNING) {			
+			if(exceptionInRun!=null)
+				throw new AppException("Could not start server "+getName()
+					+"! Details: "+exceptionInRun);
+			else
+				throw new AppException("Could not start server "+getName());
+		}
+		lastStartTime = new java.util.Date();
+		logger.log(Level.FINE, "Started {0}, Date: {1}", new Object[]{getName(), lastStartTime});
+	}
+
+	/**
+	 * Stops the QuickServer.
+	 *
+	 * @exception org.quickserver.net.AppException 
+	 *  if could not stop server
+	 * @since 1.1
+	 * @see #stopService
+	 */
+	public void stopServer() throws AppException {
+		processServerHooks(ServerHook.PRE_SHUTDOWN);
+		logger.log(Level.WARNING, "Stopping {0}", getName());
+		stopServer = true;
+		Socket death = null;
+		if(isClosed()==true) {
+			logger.log(Level.WARNING, "Server {0} is not running!", getName());
+			throw new AppException("Server "+getName()+" is not running!");
+		}
+		try	{
+			if(getBlockingMode()==true) {
+				if(getSecure().isEnable()==false) {
+					death = new Socket(server.getInetAddress(), 
+						server.getLocalPort());
+					death.getInputStream().read();
+					death.close();
+				} else {
+					death = getSSLSocketFactory().createSocket(
+						server.getInetAddress(), server.getLocalPort());
+					Thread.sleep(100);
+					death.close();
+				}
+			}
+
+			if(serverSocketChannel!=null) {
+				serverSocketChannel.close();
+			}
+
+		} catch(IOException e){
+			logger.log(Level.FINE, "IOError stopping {0}: {1}", new Object[]{getName(), e});
+		} catch(Exception e){
+			logger.log(Level.WARNING, "Error stopping {0}: {1}", new Object[]{getName(), e});
+			throw new AppException("Error in stopServer "+getName()+": "+e);
+		}
+
+		for(int i=0;getServiceState()!=Service.STOPPED;i++) {
+			try {
+				Thread.sleep(60);
+			} catch(Exception e) {
+				logger.log(Level.WARNING, "Error waiting for {0} to fully stop. Error: {1}", 
+					new Object[]{getName(), e});
+			}
+			if(i>1000) {
+				logger.severe("Server was not stopped even after 10sec.. will terminate now.");
+				System.exit(-1);
+			}
+		}
+		if(adminServer==null || getQSAdminServer().getServer()!=this) {
+			//so this is not qsadmin
+			setClassLoader(null);
+		}
+		logger.log(Level.INFO, "Stopped {0}", getName());
+	}
+
+	/**
+	 * Restarts the QuickServer.
+	 *
+	 * @exception org.quickserver.net.AppException 
+	 *  if could not stop server or if it could not start the server.
+	 * @since 1.2
+	 */
+	public void restartServer() throws AppException {
+		stopServer();
+		startServer();
+	}
+
+    /**
+     * Returns the name of the QuickServer. Default is 'QuickServer'.
+     * @see #setName
+     */
+	public String getName() {
+		return serverName;
+	}
+    /**
+     * Sets the name for the QuickServer
+     * @param name for the QuickServer
+     * @see #getName
+     */
+	public void setName(String name) {
+		serverName = name;
+		logger.log(Level.FINEST, "Set to : {0}", name);
+	}
+
+	/**
+     * Returns the Server Banner of the QuickServer
+     * @see #setServerBanner
+     */
+	public String getServerBanner() {
+		return serverBanner;
+	}
+    /**
+     * Sets the serverBanner for the QuickServer
+	 * that will be displayed on the standard output [console]
+	 * when server starts. <br>&nbsp;<br>
+	 * To set welcome message to your client
+	 * {@link ClientEventHandler#gotConnected}
+     * @param banner for the QuickServer
+     * @see #getServerBanner
+     */
+	public void setServerBanner(String banner) {
+		serverBanner = banner;
+		logger.log(Level.FINEST, "Set to : {0}", banner);
+	}
+
+    /**
+     * Sets the port for the QuickServer to listen on.
+	 * If not set, it will run on Port 9876 
+	 * @param port to listen on.
+     * @see #getPort
+     */
+	public void setPort(int port) {		
+		if(port<0) {
+			throw new IllegalArgumentException("Port number can not be less than 0!");
+		}
+		serverPort=port;
+		logger.log(Level.FINEST, "Set to {0}", port);
+	}
+	/**
+     * Returns the port for the QuickServer.
+     * @see #setPort
+     */
+	public int getPort() {
+		if(isClosed()==false) {
+			return server.getLocalPort();
+		}
+
+		if(getSecure().isEnable()==false) {
+			return serverPort;
+		} else {
+			int _port = getSecure().getPort();
+			if(_port == -1) 
+				return serverPort;
+			else
+				return _port;
+		}
+	}
+
+	/**
+     * Sets the ClientCommandHandler class that interacts with 
+	 * client sockets.
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link ClientCommandHandler}
+	 * @see #getClientCommandHandler
+     */
+	public void setClientCommandHandler(String handler) {
+		clientCommandHandlerString = handler;
+		logger.log(Level.FINEST, "Set to {0}", handler);
+	}	
+	/**
+     * Returns the ClientCommandHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientCommandHandler
+	 * @since 1.1
+     */
+	public String getClientCommandHandler() {
+		return clientCommandHandlerString;
+	}
+
+	/**
+     * Sets the ClientAuthenticationHandler class that 
+	 * handles the authentication of a client.
+	 * @param authenticator the fully qualified name of the class 
+	 * that implements {@link ClientAuthenticationHandler}.
+	 * @see #getClientAuthenticationHandler
+	 * @since 1.4.6
+     */
+	public void setClientAuthenticationHandler(String authenticator) {
+		clientAuthenticationHandlerString = authenticator;
+		logger.log(Level.FINEST, "Set to {0}", authenticator);
+	}
+	/**
+     * Returns the ClientAuthenticationHandler class that 
+	 * handles the authentication of a client.
+	 * @see #setClientAuthenticationHandler
+	 * @since 1.4.6
+     */
+	public String getClientAuthenticationHandler() {
+		return clientAuthenticationHandlerString;
+	}
+
+	/**
+     * Sets the Authenticator class that 
+	 * handles the authentication of a client.
+	 * @param authenticator the fully qualified name of the class 
+	 * that implements {@link Authenticator} or {@link ClientAuthenticationHandler}.
+	 * @see #getAuthenticator
+	 * @deprecated since 1.4.6 use setClientAuthenticationHandler
+	 * @since 1.3
+     */
+	public void setAuthenticator(String authenticator) {
+		clientAuthenticationHandlerString = authenticator;
+		logger.log(Level.FINEST, "Set to {0}", authenticator);
+	}
+	/**
+     * Returns the Authenticator class that 
+	 * handles the authentication of a client.
+	 * @see #setAuthenticator
+	 * @deprecated since 1.4.6 use getClientAuthenticationHandler
+	 * @since 1.3
+     */
+	public String getAuthenticator() {
+		return clientAuthenticationHandlerString;
+	}
+
+	/**
+     * Sets the ClientData class that carries client data.
+	 * @param data the fully qualified name of the class that 
+	 * extends {@link ClientData}.
+	 * @see #getClientData
+     */
+	public void setClientData(String data) {
+		this.clientDataString = data;
+		logger.log(Level.FINEST, "Set to {0}", data);
+	}
+	/**
+     * Returns the ClientData class string that carries client data  
+	 * @return the fully qualified name of the class that 
+	 * implements {@link ClientData}.
+	 * @see #setClientData
+     */
+	public String getClientData() {
+		return clientDataString;
+	}
+
+	/**
+     * Sets the client socket's timeout.
+	 * @param time client socket timeout in milliseconds.
+	 * @see #getTimeout
+     */
+	public void setTimeout(int time) {
+		if(time>0)
+			socketTimeout = time;
+		else
+			socketTimeout = 0;
+		logger.log(Level.FINEST, "Set to {0}", socketTimeout);
+	}	
+	/**
+     * Returns the Client socket timeout in milliseconds.
+	 * @see #setTimeout
+     */
+	public int getTimeout() {
+		return socketTimeout;
+	}
+
+	/** 
+	 * Sets max allowed login attempts.
+	 * @since 1.2
+	 * @see #getMaxAuthTry
+	 */
+	public void setMaxAuthTry(int authTry) {
+		maxAuthTry = authTry;
+		logger.log(Level.FINEST, "Set to {0}", authTry);
+	}
+	/** 
+	 * Returns max allowed login attempts. Default is <code>5</code>.
+	 * @since 1.2
+	 * @see #setMaxAuthTry
+	 */
+	public int getMaxAuthTry() {
+		return maxAuthTry;
+	}
+
+	/** 
+	 * Sets message to be displayed when maximum allowed login 
+	 * attempts has reached.
+	 * Default is : -ERR Max Auth Try Reached
+	 * @see #getMaxAuthTryMsg
+	 */
+	public void setMaxAuthTryMsg(String msg) {
+		maxAuthTryMsg = msg;
+		logger.log(Level.FINEST, "Set to {0}", msg);
+	}
+	/** 
+	 * Returns message to be displayed when maximum allowed login 
+	 * attempts has reached.
+	 * @see #getMaxAuthTryMsg
+	 */
+	public String getMaxAuthTryMsg() {
+		return maxAuthTryMsg;
+	}
+
+	/**
+	 * Sets timeout message. 
+	 * Default is : -ERR Timeout
+	 * @see #getTimeoutMsg
+	 */
+	public void setTimeoutMsg(String msg) {
+		timeoutMsg = msg;
+		logger.log(Level.FINEST, "Set to {0}", msg);
+	}
+	/** 
+	 * Returns timeout message.
+	 * @see #setTimeoutMsg
+	 */
+	public String getTimeoutMsg() {
+		return timeoutMsg;
+	}
+
+	private TheClient initTheClient() {
+		TheClient theClient = new TheClient();
+		theClient.setServer(QuickServer.this);
+		theClient.setTimeoutMsg(getTimeoutMsg());
+		theClient.setMaxAuthTry(getMaxAuthTry()); //v1.2
+		theClient.setMaxAuthTryMsg(getMaxAuthTryMsg());
+		
+		theClient.setClientEventHandler(clientEventHandler);
+		theClient.setClientExtendedEventHandler(clientExtendedEventHandler); //v1.4.6
+		theClient.setClientCommandHandler(clientCommandHandler);
+		theClient.setClientObjectHandler(clientObjectHandler); //v1.2
+		theClient.setClientBinaryHandler(clientBinaryHandler); //v1.4
+		theClient.setClientWriteHandler(clientWriteHandler); //v1.4.5
+		theClient.setAuthenticator(authenticator); //v1.3
+		theClient.setClientAuthenticationHandler(clientAuthenticationHandler); //v1.4.6
+		theClient.setTimeout(socketTimeout);
+		theClient.setMaxConnectionMsg(maxConnectionMsg);
+		theClient.setCommunicationLogging(getCommunicationLogging()); //v1.3.2
+		return theClient;
+	}
+
+	public void run() {
+		exceptionInRun = null;
+		TheClient theClient = initTheClient();
+		try {
+			stopServer = false;
+
+			closeAllPools();
+			initAllPools();
+			
+			makeServerSocket();
+			
+			if(getServerBanner().length()>0) {
+				System.out.println(getServerBanner()); //print banner
+			}
+			
+			setServiceState(Service.RUNNING); //v1.2
+			
+			processServerHooks(ServerHook.POST_STARTUP); //v1.3.3
+			if(getBlockingMode()==false) {
+				runNonBlocking(theClient);
+				if(stopServer==true) {
+					logger.log(Level.FINEST, "Closing selector for {0}", getName());
+					selector.close();
+				}
+				return;
+			} else {
+				runBlocking(theClient);
+			}
+		} catch(BindException e) {
+			exceptionInRun = e;
+			logger.log(Level.SEVERE, "{0} BindException for Port {1} @ {2} : {3}", 
+				new Object[]{getName(), getPort(), getBindAddr().getHostAddress(), e.getMessage()});
+		} catch(javax.net.ssl.SSLException e) {
+			exceptionInRun = e;
+			logger.log(Level.SEVERE, "SSLException {0}", e);
+			logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(e));
+		} catch(IOException e) {
+			exceptionInRun = e;
+			logger.log(Level.SEVERE, "IOError {0}", e);
+			logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(e));
+		} catch(Exception e) {
+			exceptionInRun = e;
+			logger.log(Level.SEVERE, "Error {0}", e);
+			logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(e));
+		} finally {
+			if(getBlockingMode()==true) {
+				logger.log(Level.WARNING, "Closing {0}", getName());
+				try	{
+					if(isClosed()==false) {						
+						server.close();
+					}
+				} catch(Exception e){
+					throw new RuntimeException(e);
+				}
+				server = null;
+				serverSocketChannel = null;
+
+				setServiceState(Service.STOPPED);
+				logger.log(Level.WARNING, "Closed {0}", getName());
+
+				processServerHooks(ServerHook.POST_SHUTDOWN);
+			} else if(getBlockingMode()==false && exceptionInRun!=null) {
+				logger.log(Level.WARNING, "Closing {0} - Had Error: {1}", new Object[]{getName(), exceptionInRun});
+				try	{
+					if(isClosed()==false) {
+						if(serverSocketChannel!=null)
+							serverSocketChannel.close();
+						if(server!=null)
+							server.close();
+					}
+				} catch(Exception e){
+					throw new RuntimeException(e);
+				}		
+
+				server = null;
+				serverSocketChannel = null;
+
+				setServiceState(Service.STOPPED);
+				logger.log(Level.WARNING, "Closed {0}", getName());
+
+				processServerHooks(ServerHook.POST_SHUTDOWN);
+			}
+		}
+	} //end of run
+
+	/**
+	 * Sets the maximum number of client connection allowed.
+	 * @since 1.1
+	 * @see #getMaxConnection
+	 */
+	public void setMaxConnection(long maxConnection) {
+		if(getServiceState()==Service.SUSPENDED)
+			suspendMaxConnection = maxConnection;
+		else
+			this.maxConnection = maxConnection;
+		logger.log(Level.FINEST, "Set to {0}", maxConnection);
+	}
+	/** 
+	 * Returns the maximum number of client connection allowed.
+	 * @since 1.1
+	 * @see #setMaxConnection
+	 */
+	public long getMaxConnection() {
+		return maxConnection;
+	}
+
+	/** 
+	 * Returns number of clients connected.
+	 * @since 1.1
+	 */
+	public long getClientCount() {
+		if(clientHandlerPool != null) {
+			try {
+				return getClientHandlerPool().getNumActive();
+			} catch(Exception e) {
+				return 0;
+			}
+		}
+		return 0;
+	}
+	
+	/** 
+	 * Returns highest number of clients connected.
+	 * @since 2.1.0
+	 */
+	public long getHighestActiveClientCount() {
+		if(clientHandlerPool != null) {
+			try {
+				return ((QSObjectPool)getClientHandlerPool()).getHighestActiveCount();
+			} catch(Exception e) {
+				return 0;
+			}
+		}
+		return 0;
+	}
+
+	/**
+	 * Sets the message to be sent to any new client connected after
+	 * maximum client connection has reached. 
+	 * Default is : <code>-ERR Server Busy. Max Connection Reached</code>
+	 * @since 1.1
+	 * @see #getMaxConnectionMsg
+	 */
+	public void setMaxConnectionMsg(String maxConnectionMsg) {
+		if(getServiceState() == Service.SUSPENDED)
+			suspendMaxConnectionMsg = maxConnectionMsg;
+		else
+			this.maxConnectionMsg = maxConnectionMsg;
+		logger.log(Level.FINEST, "Set to {0}", maxConnectionMsg);
+	}
+	/**
+	 * Returns the message to be sent to any new client connected 
+	 * after maximum client connection has reached.
+	 * @since 1.1
+	 * @see #setMaxConnectionMsg
+	 */
+	public String getMaxConnectionMsg() {
+		return maxConnectionMsg;
+	}
+
+	/**
+	 * Sets the Ip address to bind to. 
+	 * @param bindAddr argument can be used on a multi-homed host for a 
+	 * QuickServer that will only accept connect requests to one 
+	 * of its addresses. If not set, it will default accepting 
+	 * connections on any/all local addresses.
+	 * @exception java.net.UnknownHostException if no IP address for 
+	 * the host could be found
+	 * @since 1.1
+	 * @see #getBindAddr
+	 */
+	public void setBindAddr(String bindAddr) 
+			throws UnknownHostException {
+		ipAddr = InetAddress.getByName(bindAddr);
+		logger.log(Level.FINEST, "Set to {0}", bindAddr);
+	}
+	/**
+	 * Returns the IP address binding to. 
+	 * @since 1.1
+	 * @see #setBindAddr
+	 */
+	public InetAddress getBindAddr() {
+		if(ipAddr==null) {
+			try	{
+				ipAddr = InetAddress.getByName("0.0.0.0");
+			} catch(Exception e){
+				logger.log(Level.WARNING, "Unable to create default ip(0.0.0.0) : {0}", e);
+				throw new RuntimeException("Error: Unable to find servers own ip : "+e);
+			}			
+		}
+		return ipAddr;
+	}
+
+	/**
+	 * Sets the store of objects to QuickServer, it is an array of objects  
+	 * that main program or the class that created QuickServer passes to 
+	 * the QuickServer. 
+	 * @param storeObjects array of objects
+	 * @see #getStoreObjects
+	 * @since 1.1
+	 */
+	public void setStoreObjects(Object[] storeObjects) {
+		this.storeObjects = storeObjects;
+	}
+
+	/**
+	 * Returns store of objects from QuickServer, if nothing was set will
+	 * return <code>null</code>.
+	 * @see #setStoreObjects
+	 * @since 1.1
+	 */
+	public Object[] getStoreObjects() {
+		return storeObjects;
+	}
+
+	/** 
+	 * Set the port to run QSAdminServer on.
+	 * @since 1.2
+	 */
+	public void setQSAdminServerPort(int port) {
+		getQSAdminServer().getServer().setPort(port);
+	}
+	/** 
+	 * Returns the port to run QSAdminServer on.
+	 * @since 1.2
+	 */
+	public int getQSAdminServerPort() {
+		return getQSAdminServer().getServer().getPort();
+	}
+
+	/** 
+	 * Set the ClientAuthenticationHandler class of 
+	 * QSAdminServer that handles the authentication of a client.
+	 * @since 1.2
+	 */
+	public void setQSAdminServerAuthenticator(String authenticator) {
+		getQSAdminServer().getServer().setClientAuthenticationHandler(authenticator);
+	}
+	/** 
+	 * Returns the Authenticator or ClientAuthenticationHandler class of 
+	 * QSAdminServer that handles the authentication of a client.
+	 * @since 1.2
+	 */
+	public String getQSAdminServerAuthenticator() {
+		return getQSAdminServer().getServer().getAuthenticator();
+	}
+
+	/**
+	 * Starts QSAdminServer for this QuickServer.
+	 * @see org.quickserver.net.qsadmin.QSAdminServer
+	 * @param authenticator sets the ClientAuthenticationHandler class that 
+	 *   handles the authentication of a client, 
+	 *   if null uses {@link org.quickserver.net.qsadmin.Authenticator}.
+	 * @param port to run QSAdminServer on
+ 	 * @exception org.quickserver.net.AppException 
+	 *  if Server already running or if it could not load the classes
+	 *  [ClientCommandHandler, ClientAuthenticationHandler, ClientData].
+	 * @since 1.1
+	 */
+	public void startQSAdminServer(int port, String authenticator) 
+			throws AppException {
+		getQSAdminServer().setClientAuthenticationHandler(authenticator);
+		getQSAdminServer().startServer(port);
+	}
+	/**
+	 * Starts QSAdminServer for this QuickServer.
+	 * @see org.quickserver.net.qsadmin.QSAdminServer
+	 * @since 1.2
+	 */
+	public void startQSAdminServer() throws AppException {
+		getQSAdminServer().startServer();
+	}
+
+	/**
+	 * Returns {@link QSAdminServer} associated with this QuickServer
+	 * @since 1.1
+	 */
+	public QSAdminServer getQSAdminServer() {
+		if(adminServer==null)
+			adminServer = new QSAdminServer(QuickServer.this);
+		return adminServer;
+	}
+
+	/**
+	 * Sets {@link QSAdminServer} associated with this QuickServer
+	 * @since 1.3.3
+	 */
+	public void setQSAdminServer(QSAdminServer adminServer) {
+		if(adminServer==null)
+			this.adminServer = adminServer;
+	}
+
+	/** 
+	 * Returns the closed state of the QuickServer Socket.
+	 * @since 1.1
+	 */
+	public boolean isClosed() {
+		if(server==null)
+			return true;
+		return server.isClosed();
+	}
+
+	/** 
+	 * Returns the application logger associated with QuickServer.
+	 * If it was not set will return QuickServer's own logger.
+	 * @since 1.2
+	 */
+	public Logger getAppLogger() {
+		if(appLogger!=null)
+			return appLogger;
+		return logger;
+	}
+	/** 
+	 * Sets the application logger associated with QuickServer
+	 * @since 1.2
+	 */
+	public void setAppLogger(Logger appLogger) {
+		this.appLogger = appLogger;
+	}
+
+	/**
+     * Sets the ClientObjectHandler class that interacts with 
+	 * client sockets to handle java objects.
+	 * @param handler object the fully qualified name of the class that 
+	 *  implements {@link ClientObjectHandler}
+	 * @see #getClientObjectHandler
+	 * @since 1.2
+     */
+	public void setClientObjectHandler(String handler) {
+		clientObjectHandlerString = handler;
+		logger.log(Level.FINEST, "Set to {0}", handler);
+	}
+	/**
+     * Returns the ClientObjectHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientObjectHandler
+	 * @since 1.2
+     */
+	public String getClientObjectHandler() {
+		return clientObjectHandlerString;
+	}
+
+	/**
+	 * Sets the console log handler formatter.
+	 * @param formatter fully qualified name of the class that implements 
+	 * {@link java.util.logging.Formatter}
+	 * @since 1.2
+	 */
+	public void setConsoleLoggingFormatter(String formatter) 
+			throws ClassNotFoundException, InstantiationException,
+				IllegalAccessException {
+		if(formatter==null)
+			return;
+		consoleLoggingformatter = formatter;
+
+		java.util.logging.Formatter conformatter = 
+			(java.util.logging.Formatter) getClass(formatter, true).newInstance();
+		Logger jdkLogger = Logger.getLogger("");
+		Handler[] handlers =  jdkLogger.getHandlers();
+		for(int index = 0; index < handlers.length; index++ ) {
+			if(ConsoleHandler.class.isInstance(handlers[index])) {
+				handlers[index].setFormatter(conformatter);
+			}
+		}
+		logger.log(Level.FINEST, "Set to {0}", formatter);
+	}
+
+	/**
+	 * Gets the console log handler formatter.
+	 * @since 1.3
+	 */
+	public String getConsoleLoggingFormatter() {
+		return consoleLoggingformatter;
+	}
+
+	/**
+	 * Sets the console log handler formater to 
+	 * {@link org.quickserver.util.logging.MiniFormatter}
+	 * @since 1.2
+	 */
+	public void setConsoleLoggingToMini() {
+		try	{
+			setConsoleLoggingFormatter("org.quickserver.util.logging.MiniFormatter");
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "Setting to logging.MiniFormatter : {0}", e);
+		}
+	}
+
+	/**
+	 * Sets the console log handler formater to 
+	 * {@link org.quickserver.util.logging.MicroFormatter}
+	 * @since 1.2
+	 */
+	public void setConsoleLoggingToMicro() {
+		try	{
+			setConsoleLoggingFormatter("org.quickserver.util.logging.MicroFormatter");	
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "Setting to MicroFormatter : {0}", e);
+		}
+	}
+
+	/**
+	 * Sets the console log handler level.
+	 * @since 1.2
+	 */
+	public void setConsoleLoggingLevel(Level level) {
+		Logger rlogger = Logger.getLogger("");
+		Handler[] handlers =  rlogger.getHandlers();
+		
+		boolean isConsole = true;
+		try {
+			if(System.console()==null) {
+				isConsole = false;
+			}
+		} catch(Throwable e) {
+			//ignore
+		}
+		
+		for(int index = 0; index < handlers.length; index++ ) {
+			if(ConsoleHandler.class.isInstance(handlers[index])) {
+				if(isConsole==false && level!=Level.OFF) {					
+					System.out.println("QuickServer: You do not have a console.. so turning console logger off..");
+					level=Level.OFF;
+				}
+				
+				if(level==Level.OFF) {
+					logger.info("QuickServer: Removing console handler.. ");
+					rlogger.removeHandler(handlers[index]);
+					
+					handlers[index].setLevel(level);
+					handlers[index].close();
+				} else {
+					handlers[index].setLevel(level);
+				}
+			}
+		}
+		if(level==Level.SEVERE)
+			consoleLoggingLevel = "SEVERE";
+		else if(level==Level.WARNING)
+			consoleLoggingLevel = "WARNING";
+		else if(level==Level.INFO)
+			consoleLoggingLevel = "INFO";
+		else if(level==Level.CONFIG)
+			consoleLoggingLevel = "CONFIG";
+		else if(level==Level.FINE)
+			consoleLoggingLevel = "FINE";
+		else if(level==Level.FINER)
+			consoleLoggingLevel = "FINER";
+		else if(level==Level.FINEST)
+			consoleLoggingLevel = "FINEST";
+		else if(level==Level.OFF)
+			consoleLoggingLevel = "OFF";
+		else
+			consoleLoggingLevel = "UNKNOWN";
+
+		logger.log(Level.FINE, "Set to {0}", level);
+	}
+
+	/**
+	 * Gets the console log handler level.
+	 * @since 1.3
+	 */
+	public String getConsoleLoggingLevel() {
+		return consoleLoggingLevel;
+	}
+
+	/**
+	 * Sets the level for all log handlers.
+	 * @since 1.3.1
+	 */
+	public void setLoggingLevel(Level level) {
+		Logger rlogger = Logger.getLogger("");
+		Handler[] handlers =  rlogger.getHandlers();
+		for(int index = 0; index < handlers.length; index++ ) {
+		  handlers[index].setLevel(level);
+		}
+
+		if(level==Level.SEVERE)
+			loggingLevel = "SEVERE";
+		else if(level==Level.WARNING)
+			loggingLevel = "WARNING";
+		else if(level==Level.INFO)
+			loggingLevel = "INFO";
+		else if(level==Level.CONFIG)
+			loggingLevel = "CONFIG";
+		else if(level==Level.FINE)
+			loggingLevel = "FINE";
+		else if(level==Level.FINER)
+			loggingLevel = "FINER";
+		else if(level==Level.FINEST)
+			loggingLevel = "FINEST";
+		else if(level==Level.OFF)
+			loggingLevel = "OFF";
+		else 
+			loggingLevel = "UNKNOWN";
+
+		consoleLoggingLevel = loggingLevel;
+
+		logger.log(Level.FINE, "Set to {0}", level);
+	}
+
+	//*** Start of Service interface methods
+	/**
+	 * Returns service error if any.
+	 * @since 1.4.7
+	 */
+	public Throwable getServiceError() {
+		return serviceError;
+	}
+
+	/**
+	 * Initialise and create the service.
+	 * @param param of the xml configuration file.
+	 * @since 1.2
+	 */
+	public synchronized boolean initService(Object param[]) {
+		serviceError = null;
+		try {
+			initServer(param);
+		} catch(Exception e) {
+			serviceError = e;
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Initialise and create the service.
+	 * @param qsConfig QuickServerConfig object.
+	 * @since 1.4.6
+	 */
+	public synchronized boolean initService(QuickServerConfig qsConfig) {
+		serviceError = null;
+		try {
+			initServer(qsConfig);			
+		} catch(Exception e) {
+			serviceError = e;
+			return false;
+		}
+		return true;
+	}
+	
+	/**
+	 * Start the service.
+	 * @return true if serivce was stopped from Running state.
+	 * @since 1.2
+	 */
+	public boolean startService() {
+		serviceError = null;
+		if(getServiceState() == Service.RUNNING)
+			return false;
+		try	{
+			startServer();
+		} catch(AppException e) {
+			serviceError = e;
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Stop the service.
+	 * @return true if service was stopped from Running state.
+	 * @since 1.2
+	 */
+	public boolean stopService() {
+		serviceError = null;
+		if(getServiceState() == Service.STOPPED)
+			return false;
+		try	{
+			stopServer();
+			clearAllPools();
+		} catch(AppException e) {
+			serviceError = e;
+			return false;
+		} catch(Exception e) {
+			serviceError = e;
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Suspends the service.
+	 * @return true if service was suspended from resumed state.
+	 * @since 1.2
+	 */
+	public boolean suspendService() {
+		serviceError = null;
+		if(getServiceState() == Service.RUNNING) {
+			suspendMaxConnection = maxConnection;
+			suspendMaxConnectionMsg = maxConnectionMsg;
+			maxConnection = 0;
+			maxConnectionMsg = "Service is suspended.";
+			setServiceState(Service.SUSPENDED);
+			logger.log(Level.INFO, "Service {0} is suspended.", getName());
+			return true;
+		}
+		return false;
+	}
+	/**
+	 * Resume the service.
+	 * @return true if service was resumed from suspended state.
+	 * @since 1.2
+	 */ 
+	public boolean resumeService() {
+		serviceError = null;
+		if(getServiceState() == Service.SUSPENDED) {
+			maxConnection = suspendMaxConnection;
+			maxConnectionMsg = suspendMaxConnectionMsg;
+			setServiceState(Service.RUNNING);
+			logger.log(Level.INFO, "Service {0} resumed.", getName());
+			return true;
+		}
+		return false;
+	}
+	/** 
+	 * Information about the service.
+	 * @since 1.2
+	 */
+	public String info() {
+		serviceError = null;
+		StringBuilder buf = new StringBuilder();
+		buf.append(getName()).append("\n");
+		buf.append(getBindAddr().getHostAddress()).append(" ");
+		buf.append(getPort()).append("\n");
+		return buf.toString();
+	}
+	// *** End of Service interface methods
+
+	/**
+	 * Initialise and create the server.
+	 * @param param of the xml configuration file.
+	 * @exception AppException if QuickServerConfig creation failed from the xml config file.
+	 * @since 1.4.7
+	 */
+	public synchronized void initServer(Object param[]) throws AppException {
+		QuickServerConfig qsConfig = null;
+		try {
+			qsConfig = ConfigReader.read( (String)param[0]);
+		} catch(Exception e) {
+			logger.log(Level.SEVERE, "Could not init server from xml file {0} : {1}", 
+				new Object[]{new File((String)param[0]).getAbsolutePath(), e});
+			throw new AppException("Could not init server from xml file",e);
+		}
+		initServer(qsConfig);
+	}
+
+	/**
+	 * Initialise and create the service.
+	 * @param qsConfig QuickServerConfig object.
+	 * @since 1.4.7
+	 */
+	public synchronized void initServer(QuickServerConfig qsConfig) throws AppException {
+		setConfig(qsConfig);
+		try {
+			configQuickServer();
+
+			loadApplicationClasses();
+
+			//start InitServerHooks
+			InitServerHooks ish = getConfig().getInitServerHooks();
+			if(ish!=null) {
+				Iterator iterator = ish.iterator();
+				String initServerHookClassName = null;
+				Class initServerHookClass = null;
+				InitServerHook initServerHook = null;
+				while(iterator.hasNext()) {
+					initServerHookClassName = (String)iterator.next();
+					initServerHookClass = getClass(initServerHookClassName, true);
+					initServerHook = (InitServerHook) initServerHookClass.newInstance();
+
+					logger.log(Level.INFO, "Loaded init server hook: {0}", initServerHookClassName);
+					logger.log(Level.FINE, "Init server hook info: {0}", initServerHook.info());
+					initServerHook.handleInit(QuickServer.this);
+				}
+			}
+		} catch(Exception e) {
+			logger.log(Level.SEVERE, "Could not load init server hook: {0}", e);
+			logger.log(Level.WARNING, "StackTrace:\n{0}", MyString.getStackTrace(e));
+			throw new AppException("Could not load init server hook",e);
+		}
+		setServiceState(Service.INIT);
+		logger.log(Level.FINEST, "\r\n{0}", MyString.getSystemInfo(getVersion()));
+	}
+
+	/** 
+	 * Returns the state of the process 
+	 * As any constant of {@link Service} interface.
+	 * @since 1.2
+	 */
+	public int getServiceState() {
+		return serviceState;
+	}
+	/** 
+	 * Sets the state of the process 
+	 * As any constant of {@link Service} interface.
+	 * @since 1.2
+	 */
+	public void setServiceState(int state) {
+		serviceState = state;
+	}
+
+	private void configConsoleLoggingLevel(QuickServer qs, String temp) {
+		if(temp.equals("SEVERE"))
+			qs.setConsoleLoggingLevel(Level.SEVERE);
+		else if(temp.equals("WARNING"))
+			qs.setConsoleLoggingLevel(Level.WARNING);
+		else if(temp.equals("INFO"))
+			qs.setConsoleLoggingLevel(Level.INFO);
+		else if(temp.equals("CONFIG"))
+			qs.setConsoleLoggingLevel(Level.CONFIG);
+		else if(temp.equals("FINE"))
+			qs.setConsoleLoggingLevel(Level.FINE);
+		else if(temp.equals("FINER"))
+			qs.setConsoleLoggingLevel(Level.FINER);
+		else if(temp.equals("FINEST"))
+			qs.setConsoleLoggingLevel(Level.FINEST);
+		else if(temp.equals("OFF"))
+			qs.setConsoleLoggingLevel(Level.OFF);
+		else 
+			logger.log(Level.WARNING, "unknown level {0}", temp);
+	}
+	
+	/**
+	 * Configures QuickServer based on the passed QuickServerConfig object.
+	 * @since 1.2
+	 */
+	public void configQuickServer(QuickServerConfig config) throws Exception {
+		QuickServer qs = QuickServer.this;
+		qs.setConfig(config); //v1.3
+		qs.setBasicConfig(config);
+		String temp = config.getConsoleLoggingLevel();
+		configConsoleLoggingLevel(qs, temp);
+		temp = null;
+		
+		qs.setConsoleLoggingFormatter(config.getConsoleLoggingFormatter());
+
+		qs.setName(config.getName());
+		qs.setPort(config.getPort());
+		qs.setClientEventHandler(config.getClientEventHandler());
+		qs.setClientCommandHandler(config.getClientCommandHandler());
+		if(config.getAuthenticator()!=null)
+			qs.setAuthenticator(config.getAuthenticator()); //v1.3
+		else if(config.getClientAuthenticationHandler()!=null)
+			qs.setClientAuthenticationHandler(config.getClientAuthenticationHandler()); //v1.4.6
+		qs.setClientObjectHandler(config.getClientObjectHandler());
+		qs.setClientBinaryHandler(config.getClientBinaryHandler());//v1.4
+		qs.setClientWriteHandler(config.getClientWriteHandler());//v1.4.5
+		qs.setClientData(config.getClientData());
+		qs.setClientExtendedEventHandler(config.getClientExtendedEventHandler());
+		qs.setDefaultDataMode(config.getDefaultDataMode());//v1.4.6
+		qs.setServerBanner(config.getServerBanner());
+		qs.setTimeout(config.getTimeout());
+		qs.setMaxAuthTry(config.getMaxAuthTry());
+		qs.setMaxAuthTryMsg(config.getMaxAuthTryMsg());
+		qs.setTimeoutMsg(config.getTimeoutMsg());
+		qs.setMaxConnection(config.getMaxConnection());
+		qs.setMaxConnectionMsg(config.getMaxConnectionMsg());
+		qs.setBindAddr(config.getBindAddr());
+		//v1.3.2
+		qs.setCommunicationLogging(config.getCommunicationLogging());
+		//v1.3.3
+		qs.setSecurityManagerClass(config.getSecurityManagerClass());
+		qs.setAccessConstraintConfig(config.getAccessConstraintConfig());
+		temp = config.getApplicationJarPath();
+		if(temp!=null) {
+			File ajp = new File(temp);
+			if(ajp.isAbsolute()==false) {
+				temp = config.getConfigFile();
+				ajp = new File(temp);
+				temp = ajp.getParent() + File.separatorChar + 
+					config.getApplicationJarPath();
+				config.setApplicationJarPath(temp);
+				temp = null;
+			}
+			qs.setApplicationJarPath(config.getApplicationJarPath());
+			//set path also to QSAdmin
+			if(config.getQSAdminServerConfig() != null ) {
+				getQSAdminServer().getServer().setApplicationJarPath(
+					config.getApplicationJarPath());
+			}
+		}
+		qs.setServerHooks(config.getServerHooks());
+		qs.setSecure(config.getSecure());
+	}
+
+	/**
+	 * Configures QSAdminServer based on the passed QuickServerConfig object.
+	 * @since 1.2
+	 */
+	public void configQuickServer(QSAdminServerConfig config) 
+			throws Exception {
+		QuickServer qs = getQSAdminServer().getServer();
+		qs.setBasicConfig(config);
+		
+		//set the Logging Level to same as main QS
+		String temp = getConsoleLoggingLevel();//config.getConsoleLoggingLevel();
+		configConsoleLoggingLevel(qs, temp);
+		
+		//set the Logging Formatter to same as main QS
+		//qs.setConsoleLoggingFormatter(config.getConsoleLoggingFormatter());
+		qs.setConsoleLoggingFormatter(getConsoleLoggingFormatter());
+		
+		qs.setClientEventHandler(config.getClientEventHandler());//v1.4.6
+		qs.setClientCommandHandler(config.getClientCommandHandler());
+		qs.setName(config.getName());
+		qs.setPort(config.getPort());
+		if(config.getAuthenticator()!=null)
+			qs.setAuthenticator(config.getAuthenticator()); //v1.3
+		else  if(config.getClientAuthenticationHandler()!=null)
+			qs.setClientAuthenticationHandler(config.getClientAuthenticationHandler()); //v1.4.6
+		qs.setClientObjectHandler(config.getClientObjectHandler());
+		qs.setClientBinaryHandler(config.getClientBinaryHandler());//v1.4
+		qs.setClientWriteHandler(config.getClientWriteHandler());//v1.4.5
+		qs.setClientData(config.getClientData());
+		qs.setClientExtendedEventHandler(config.getClientExtendedEventHandler());//v1.4.6
+		qs.setDefaultDataMode(config.getDefaultDataMode());//v1.4.6
+		qs.setServerBanner(config.getServerBanner());
+		qs.setTimeout(config.getTimeout());
+		qs.setMaxAuthTry(config.getMaxAuthTry());
+		qs.setMaxAuthTryMsg(config.getMaxAuthTryMsg());
+		qs.setTimeoutMsg(config.getTimeoutMsg());
+		qs.setMaxConnection(config.getMaxConnection());
+		qs.setMaxConnectionMsg(config.getMaxConnectionMsg());
+		qs.setBindAddr(config.getBindAddr());
+		//v1.3.2
+		qs.setCommunicationLogging(config.getCommunicationLogging());
+		getQSAdminServer().setCommandPlugin(config.getCommandPlugin());
+		//v1.3.2
+		if(config.getCommandShellEnable().equals("true"))
+			getQSAdminServer().setShellEnable(true);
+		getQSAdminServer().setPromptName(config.getCommandShellPromptName());
+		//v1.3.3
+		qs.setAccessConstraintConfig(config.getAccessConstraintConfig());
+		qs.setServerHooks(config.getServerHooks());
+		qs.setSecure(config.getSecure());
+	}
+
+	/**
+	 * Configures QSAdminServer and QuickServer based on the 
+	 * internal QuickServerConfig object.
+	 * @since 1.3
+	 */
+	public void configQuickServer() throws Exception {
+		configQuickServer(getConfig());
+		if(getConfig().getQSAdminServerConfig() != null ) {
+			configQuickServer(getConfig().getQSAdminServerConfig());
+		}
+	}
+
+	/**
+	 * Usage: QuickServer [-options]<br/>
+	 * Where options include:<br/>
+	 *   -about		Opens About Dialogbox<br/>
+	 *   -load <xml_config_file> [options]	Loads the server from xml file.
+	 * where options include:
+	 *    -fullXML2File <new_file_name>
+	 */
+	public static void main(String args[]) {
+		try {
+			if(args.length >= 1) {
+				if(args[0].equals("-about")) {
+					org.quickserver.net.server.gui.About.main(null);
+				} else if(args[0].equals("-load") && args.length>=2) {
+					QuickServer qs = QuickServer.load(args[1]);
+					if(qs!=null) handleOptions(args, qs);
+				} else {
+					System.out.println(printUsage());
+				}
+			} else {
+				System.out.println(printUsage());
+				org.quickserver.net.server.gui.About.showAbout();
+			}
+		} catch(Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Loads the server from the xml file name passed.
+	 * @since 1.4.7
+	 */
+	public static QuickServer load(String xml) throws AppException {
+		QuickServer qs = new QuickServer();
+		Object config[] = new Object[] {xml};
+		qs.initServer(config);
+		qs.startServer();
+		if(qs.getConfig().getQSAdminServerConfig()!= null) {
+			qs.startQSAdminServer();
+		}
+		return qs;
+	}
+	
+	/** Prints usage */
+	private static String printUsage() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("QuickServer - Java library/framework for creating robust multi-client TCP servers.\n");
+		sb.append("Copyright (C) QuickServer.org\n\n");
+		sb.append("Usage: QuickServer [-options]\n");
+		sb.append("Where options include:\n");
+		sb.append("  -about\t"+"Opens About Dialog box\n");
+		sb.append("  -load <xml_config_file> [load-options]\t"+"Loads the server from xml file.\n");
+		sb.append("  Where load-options include:\n");
+		sb.append("     -fullXML2File <file_name>\t"+"Dumps the Full XML configuration of the QuickServer loaded.\n");
+		return sb.toString();
+	}
+
+	private static void handleOptions(String args[], QuickServer quickserver) {
+		if(args.length<3) return;
+
+		if(args[2].equals("-fullXML2File") && args.length>=4) {
+			File file = new File(args[3]);
+			logger.log(Level.INFO, "Writing full xml configuration to file: {0}", file.getAbsolutePath());
+			try {
+				TextFile.write(file, quickserver.getConfig().toXML(null));	
+			} catch(Exception e) {
+				logger.log(Level.WARNING, "Error writing full xml configuration: {0}", e);
+			}			
+		}
+	}
+
+	/**
+	 * Cleans all Object and Thread pools
+	 * @since 1.3
+	 */
+	public void clearAllPools() throws Exception {
+		try {
+			if(pool!=null)
+				getClientPool().clear();
+			if(clientHandlerPool!=null)
+				getClientHandlerPool().clear();
+			if(getClientDataPool()!=null)
+				getClientDataPool().clear();
+			if(getDBPoolUtil()!=null)
+				getDBPoolUtil().clean();
+			if(byteBufferPool!=null)
+				getByteBufferPool().clear();
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "Error: {0}", e);
+			throw e;
+		}
+	}
+
+	/**
+	 * Closes all Object and Thread pools
+	 * @since 1.3
+	 */
+	public void closeAllPools() throws Exception {
+		if(pool==null && clientHandlerPool==null && getClientDataPool()==null &&
+				getDBPoolUtil()==null && byteBufferPool==null) {
+			return;
+		}
+		logger.log(Level.FINE, "Closing pools for {0}", getName());
+		try {
+			if(pool!=null && PoolHelper.isPoolOpen(getClientPool().getObjectPool())) {
+				logger.finer("Closing ClientThread pool.");
+				getClientPool().close();
+			}
+			if(clientHandlerPool!=null && PoolHelper.isPoolOpen(getClientHandlerPool())) {
+				logger.finer("Closing ClientHandler pool.");
+				getClientHandlerPool().close();
+			}
+			if(getClientDataPool()!=null && PoolHelper.isPoolOpen(getClientDataPool())) {
+				logger.finer("Closing ClientData pool.");
+				getClientDataPool().close();
+			}
+			if(getDBPoolUtil()!=null) {
+				logger.finer("Closing DB pool.");
+				getDBPoolUtil().clean();
+			}
+			if(byteBufferPool!=null && PoolHelper.isPoolOpen(getByteBufferPool())) {
+				logger.finer("Closing ByteBuffer pool.");
+				getByteBufferPool().close();
+			}
+			logger.log(Level.FINE, "Closed pools for {0}", getName());
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "Error closing pools for {0}: {1}", new Object[]{getName(), e});
+			throw e;
+		}		
+	}
+
+	/**
+	 * Initialise all Object and Thread pools.
+	 * @since 1.3
+	 */
+	public void initAllPools() throws Exception {
+		logger.fine("Creating pools");
+		if(getBlockingMode()==false) {			
+			makeByteBufferPool(getBasicConfig().getObjectPoolConfig().getByteBufferObjectPoolConfig());
+		}
+		
+		makeClientPool(getBasicConfig().getObjectPoolConfig().getThreadObjectPoolConfig());
+		
+		makeClientHandlerPool(
+			getBasicConfig().getObjectPoolConfig().getClientHandlerObjectPoolConfig());
+		
+		//check if client data is poolable
+		if(clientDataClass!=null) {
+			try {
+				clientData = (ClientData)clientDataClass.newInstance();
+				if(PoolableObject.class.isInstance(clientData)==true) {
+					PoolableObject po = (PoolableObject)clientData;
+					if( po.isPoolable()==true) {						
+						makeClientDataPool(po.getPoolableObjectFactory(),
+							getBasicConfig().getObjectPoolConfig().getClientDataObjectPoolConfig() );
+					} else {
+						clientDataPool = null;
+						logger.fine("ClientData is not poolable!");
+					}
+				}
+			} catch(Exception e) {
+				logger.log(Level.WARNING, "Error: {0}", e);
+				throw e;
+			}
+		}
+
+		try {
+			makeDBObjectPool();
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "Error in makeDBObjectPool() : {0}", e);
+			logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(e));
+			throw e;
+		}
+		logger.fine("Created pools");
+	}
+
+
+	/**
+	 * Returns {@link org.quickserver.util.pool.thread.ClientPool} class that 
+	 * managing the pool of threads for handling clients.
+	 * @exception IllegalStateException if pool is not created yet.
+	 * @since 1.3
+	 */
+	public ClientPool getClientPool() {
+		if(pool==null)
+			throw new IllegalStateException("No ClientPool available yet!");
+		return pool;
+	}
+
+	/** 
+	 * Makes the pool of ClientHandler
+	 * @since 1.3
+	 */
+	private void makeClientHandlerPool(PoolConfig opConfig) throws Exception {
+		logger.finer("Creating ClientHandler pool");
+		PoolableObjectFactory factory = new ClientHandlerObjectFactory(getBlockingMode());
+		clientHandlerPool = poolManager.makeClientHandlerPool(factory, opConfig);
+		poolManager.initPool(clientHandlerPool, opConfig);
+		clientHandlerPool = makeQSObjectPool(clientHandlerPool);
+		clientIdentifier.setClientHandlerPool((QSObjectPool)clientHandlerPool);
+	}
+
+	/**
+	 * Returns ObjectPool of {@link org.quickserver.net.server.ClientHandler} 
+	 * class.
+	 * @exception IllegalStateException if pool is not created yet.
+	 * @since 1.3
+	 */
+	public ObjectPool getClientHandlerPool() {
+		if(clientHandlerPool==null)
+			throw new IllegalStateException("No ClientHandler Pool available yet!");
+		return clientHandlerPool;
+	}
+
+	
+	/**
+	 * Sets the configuration of the QuickServer.
+	 * @since 1.3
+	 */
+	public void setConfig(QuickServerConfig config) {
+		this.config = config;
+	}
+
+	/**
+	 * Returns the configuration of the QuickServer.
+	 * @since 1.3
+	 */
+	public QuickServerConfig getConfig() {
+		return config;
+	}
+
+	/** 
+	 * Makes the pool of ClientData
+	 * @since 1.3
+	 */
+	private void makeClientDataPool(PoolableObjectFactory factory, 
+			PoolConfig opConfig) throws Exception {
+		logger.finer("Creating ClientData pool");
+		clientDataPool = poolManager.makeClientDataPool(factory, opConfig);
+		poolManager.initPool(clientDataPool, opConfig);
+		clientDataPool = makeQSObjectPool(clientDataPool);		
+	}
+
+	/**
+	 * Returns ObjectPool of {@link org.quickserver.net.server.ClientData} 
+	 * class. If ClientData was not poolable will return  null.
+	 * @since 1.3
+	 */
+	public ObjectPool getClientDataPool() {
+		return clientDataPool;
+	}
+
+	/**
+	 * Returns {@link org.quickserver.sql.DBPoolUtil} object if
+	 * {@link org.quickserver.util.xmlreader.DBObjectPoolConfig} was set.
+	 * @return DBPoolUtil object if object could be loaded, else will return <code>null</code>
+	 * @since 1.3
+	 */
+	public DBPoolUtil getDBPoolUtil() {
+		return dBPoolUtil;
+	}
+	/**
+	 * Sets {@link org.quickserver.util.xmlreader.DBObjectPoolConfig}
+	 * @since 1.3
+	 */
+	public void setDBObjectPoolConfig(DBObjectPoolConfig dBObjectPoolConfig) {
+		getConfig().setDBObjectPoolConfig(dBObjectPoolConfig);
+	}
+
+	/** 
+	 * Makes the pool of Database Objects
+	 * @since 1.3
+	 */
+	private void makeDBObjectPool() throws Exception {
+		if(getConfig().getDBObjectPoolConfig()!=null) {
+			logger.fine("Creating DBObject Pool");
+			//logger.finest("Got:\n"+getConfig().getDBObjectPoolConfig().toXML(null));
+			Class dbPoolUtilClass = getClass(
+				getConfig().getDBObjectPoolConfig().getDbPoolUtil(), true);
+			dBPoolUtil = (DBPoolUtil) dbPoolUtilClass.newInstance();
+			dBPoolUtil.setDatabaseConnections(
+				getConfig().getDBObjectPoolConfig().getDatabaseConnectionSet().iterator());
+			dBPoolUtil.initPool();
+		}
+	}
+
+	/**
+	 * Tries to find the Client by the Id passed.
+	 * <p>
+	 * Note: This command is an expensive so do use it limitedly and
+	 * cache the returned object. But before you start sending message to the 
+	 * cached object do validate that ClientHandler with you is currently 
+	 * connected and is pointing to the same clinet has it was before.
+	 * This can be done as follows. <pre>
+	foundClientHandler.isConnected(); //this method will through SocketException if not connected
+	Date newTime = foundClientHandler.getClientConnectedTime();
+	if(oldCachedTime!=newTime) {
+		//Client had disconnected and ClientHandler was reused for
+		//someother client, so write code to again find ur client
+		foundClientHandler = handler.getServer().findFirstClientById("friendsid");
+		...
+	}</pre>
+	 * </p>
+	 * @see ClientIdentifiable
+	 * @return ClientHandler object if client was found else <code>null</code>
+	 * @since 1.3.1
+	 */
+	public ClientHandler findFirstClientById(String id) {
+		return clientIdentifier.findFirstClientById(id);
+	}
+
+	/**
+	 * Returns an iterator containing all the 
+	 * {@link org.quickserver.net.server.ClientHandler} that
+	 * are currently handling clients. 
+	 * It is recommended not to change the collection under an iterator. 
+	 *
+	 * It is imperative that the user manually synchronize on the returned collection 
+	 * when iterating over it: 
+	 * <code><pre>
+   Eg:
+
+	ClientData foundClientData = null;
+	Object syncObj = quickserver.getClientIdentifier().getObjectToSynchronize();
+	synchronized(syncObj) {	
+		Iterator iterator = quickserver.findAllClient();
+		while(iterator.hasNext()) {
+			foundClientHandler = (ClientHandler) iterator.next();
+			....
+		}
+	}
+
+	//OR
+
+	ClientData foundClientData = null;
+	ClientIdentifier clientIdentifier = quickserver.getClientIdentifier();
+	synchronized(clientIdentifier.getObjectToSynchronize()) {	
+		Iterator iterator = clientIdentifier.findAllClient();
+		while(iterator.hasNext()) {
+			foundClientHandler = (ClientHandler) iterator.next();
+			....
+		}
+	}
+   </code></pre>
+	 * @since 1.3.1
+	 */
+	public Iterator findAllClient() {
+		return clientIdentifier.findAllClient();
+	}
+
+	/**
+	 * Tries to find the Client by the matching pattern passed to the Id.
+	 * <p>
+	 * Note: This command is an expensive so do use it limitedly and
+	 * cache the returned object. But before you start sending message to the 
+	 * cached object do validate that ClientHandler with you is currently 
+	 * connected and is pointing to the same client has it was before.
+	 * This can be done as follows. <pre>
+	foundClientHandler.isConnected(); //this method will through SocketException if not connected
+	Date newTime = foundClientHandler.getClientConnectedTime();
+	if(oldCachedTime!=newTime) {
+		//Client had disconnected and ClientHandler was reused for
+		//someother client, so write code to again find ur client
+		foundClientHandler = handler.getServer().findFirstClientById("friendsid");
+		...
+	}</pre>
+	 * </p>
+	 * @see ClientIdentifiable
+	 * @return ClientHandler object if client was found else <code>null</code>
+	 * @since 1.3.2
+	 */
+	public Iterator findAllClientById(String pattern) {
+		return clientIdentifier.findAllClientById(pattern);
+	}
+
+	/**
+	 * Tries to find the Client by the Key passed.
+	 * <p>
+	 * Note: This command is an expensive so do use it limitedly and
+	 * cache the returned object. But before you start sending message to the 
+	 * cached object do validate that ClientHandler with you is currently 
+	 * connected and is pointing to the same client has it was before.
+	 * This can be done as follows. <pre>
+	foundClientHandler.isConnected(); //this method will through SocketException if not connected
+	Date newTime = foundClientHandler.getClientConnectedTime();
+	if(oldCachedTime!=newTime) {
+		//Client had disconnected and ClientHandler was reused for
+		//someother client, so write code to again find ur client
+		foundClientHandler = handler.getServer().findClientByKey("friendskey");
+		...
+	}</pre>
+	 * </p>
+	 * @see ClientIdentifiable
+	 * @return ClientHandler object if client was found else <code>null</code>
+	 * @since 1.3.1
+	 */
+	public ClientHandler findClientByKey(String key) {
+		return clientIdentifier.findClientByKey(key);
+	}
+
+	/**
+	 * Tries to find the Client by the matching pattern passed to the key.
+	 * <p>
+	 * Note: This command is an expensive so do use it limitedly and
+	 * cache the returned object. But before you start sending message to the 
+	 * cached object do validate that ClientHandler with you is currently 
+	 * connected and is pointing to the same client has it was before.
+	 * This can be done as follows. <pre>
+	foundClientHandler.isConnected(); //this method will through SocketException if not connected
+	Date newTime = foundClientHandler.getClientConnectedTime();
+	if(oldCachedTime!=newTime) {
+		//Client had disconnected and ClientHandler was reused for
+		//some other client, so write code to again find ur client
+		foundClientHandler = handler.getServer().findFirstClientByKey("friendsid");
+		...
+	}</pre>
+	 * </p>
+	 * @see ClientIdentifiable
+	 * @return ClientHandler object if client was found else <code>null</code>
+	 * @since 1.4
+	 */
+	public Iterator findAllClientByKey(String pattern) {
+		return clientIdentifier.findAllClientByKey(pattern);
+	}
+
+	/**
+	 * Sets next client has a trusted client. 
+	 * <p>This will skip any authentication and will not set any timeout.</p>
+	 * @since 1.3.2
+	 */
+	public void nextClientIsTrusted() {
+		setSkipValidation(true);
+	}
+	/**
+	 * @since 1.3.2
+	 */
+	private synchronized boolean getSkipValidation() {
+		return skipValidation;
+	}
+	/**
+	 * @since 1.3.2
+	 */
+	private synchronized void setSkipValidation(boolean validation) {
+		skipValidation = validation;
+	}
+
+	/**
+	 * Sets the communication logging flag.
+	 * @see #getCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public void setCommunicationLogging(boolean communicationLogging) {
+		this.communicationLogging = communicationLogging;
+	}
+	/**
+	 * Returns the communication logging flag.
+	 * @see #setCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public boolean getCommunicationLogging() {
+		return communicationLogging;
+	}
+
+	/**
+	 * Sets the SecurityManager class
+	 * @param securityManagerClass the fully qualified name of the class 
+	 * that extends {@link java.lang.SecurityManager}.
+	 * @see #getSecurityManagerClass
+	 * @since 1.3.3
+	 */
+	public void setSecurityManagerClass(String securityManagerClass) {
+		if(securityManagerClass!=null)
+			this.securityManagerClass = securityManagerClass;
+	}
+	/**
+	 * Returns the SecurityManager class
+	 * @see #setSecurityManagerClass
+	 * @since 1.3.3
+	 */
+	public String getSecurityManagerClass() {
+		return securityManagerClass;
+	}
+
+	public SecurityManager getSecurityManager() throws AppException {
+		if(getSecurityManagerClass()==null)
+			return null;
+		SecurityManager sm = null;
+		try {
+			sm = (SecurityManager) 
+				getClass(getSecurityManagerClass(), true).newInstance();
+		} catch(ClassNotFoundException e) {
+			throw new AppException(e.getMessage());
+		} catch(InstantiationException e) {
+			throw new AppException(e.getMessage());
+		} catch(IllegalAccessException e) {
+			throw new AppException(e.getMessage());
+		}
+		return sm;
+	}
+
+	/**
+	 * Sets the Access constraints
+	 * @since 1.3.3
+	 */
+	public void setAccessConstraintConfig(
+			AccessConstraintConfig accessConstraintConfig) {
+		this.accessConstraintConfig = accessConstraintConfig;
+	}
+	/**
+	 * Returns Access constraints if present else <code>null</code>.
+	 * @since 1.3.3
+	 */
+	public AccessConstraintConfig getAccessConstraintConfig() {
+		return accessConstraintConfig;
+	}
+
+	/**
+	 * Sets the classloader to be used to load the dynamically resolved 
+	 * classes
+	 * @since 1.3.3
+	 */
+	public void setClassLoader(ClassLoader classLoader) {
+		this.classLoader = classLoader;
+		Thread.currentThread().setContextClassLoader(classLoader);
+	}
+
+	/**
+	 * Gets the classloader used to load the dynamically resolved 
+	 * classes.
+	 * @since 1.4.6
+	 */
+	public ClassLoader getClassLoader() {
+		return classLoader;
+	}
+
+	/**
+	 * Utility method to load a class
+	 * @since 1.3.3
+	 */
+	 public Class getClass(String name, boolean reload) 
+			throws ClassNotFoundException {
+		if(name==null) throw new IllegalArgumentException("Class name can't be null!");
+		logger.log(Level.FINEST, "Class: {0}, reload: {1}", new Object[]{name, reload});
+		if(reload==true && classLoader!=null) {
+			return classLoader.loadClass(name);
+		} else if(reload==true && classLoader==null && this.getClass().getClassLoader()!=null) {
+			return this.getClass().getClassLoader().loadClass(name);
+		} else if(reload==false && classLoader!=null) {
+			return Class.forName(name, true, classLoader);
+		} else /*if(reload==false && classLoader==null)*/ {
+			return Class.forName(name, true, this.getClass().getClassLoader());
+		}
+	 }
+
+	 /**
+	 * Sets the applications jar/s path. This can be either absolute or
+	 * relative(to config file) path to the jar file or the directory containing 
+	 * the jars needed by the application.
+	 * @see #getApplicationJarPath
+	 * @since 1.3.3
+	 */
+	protected void setApplicationJarPath(String applicationJarPath) {
+		this.applicationJarPath = applicationJarPath;
+	}
+
+	/**
+	 * Returns the applications jar/s path. This can be either absolute or
+	 * relative(to config file) path to the jar file or the directory containing the 
+	 * jars needed by the application.
+	 * @see #setApplicationJarPath
+	 * @since 1.3.3
+	 */
+	public String getApplicationJarPath() {
+		return applicationJarPath;
+	}
+
+	/**
+	 * Sets the ServerHooks
+	 * @since 1.3.3
+	 */
+	public void setServerHooks(ServerHooks serverHooks) {
+		this.serverHooks = serverHooks;
+	}
+	/**
+	 * Returns ServerHooks if present else <code>null</code>.
+	 * @since 1.3.3
+	 */
+	public ServerHooks getServerHooks() {
+		if(serverHooks==null)
+			serverHooks = new ServerHooks();
+		return serverHooks;
+	}
+
+	/**
+	 * @since 1.3.3
+	 */
+	private void loadServerHooksClasses() {
+		if(getServerHooks()==null) return;
+		listOfServerHooks = new ArrayList();
+		ServerHook serverHook = null;
+		String serverHookClassName = null;
+		Class serverHookClass = null;
+
+		//add system hooks
+		serverHook = new GhostSocketReaper();
+		serverHook.initHook(QuickServer.this);
+		listOfServerHooks.add(serverHook);
+		ghostSocketReaper = (GhostSocketReaper) serverHook;
+
+		//add user hooks if any
+		Iterator iterator = getServerHooks().iterator();
+		while(iterator.hasNext()) {
+			serverHookClassName = (String)iterator.next();
+			try	{
+				serverHookClass = getClass(serverHookClassName, true);
+				serverHook = (ServerHook)serverHookClass.newInstance();
+				serverHook.initHook(QuickServer.this);
+				listOfServerHooks.add(serverHook);
+				logger.log(Level.INFO, "Loaded server hook: {0}", serverHookClassName);
+				logger.log(Level.FINE, "Server hook info: {0}", serverHook.info());
+			} catch(Exception e) {
+				logger.log(Level.WARNING, "Could not load server hook [{0}]: {1}", new Object[]{serverHookClassName, e});
+				logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(e));
+			}
+		}//end of while
+	}
+
+	/**
+	 * @since 1.3.3
+	 */
+	protected void processServerHooks(int event) {
+		if(listOfServerHooks==null) {
+			logger.warning("listOfServerHooks was null!");
+			return;
+		}
+		ServerHook serverHook = null;
+		boolean result = false;
+		Iterator iterator = listOfServerHooks.iterator();
+
+		String hooktype = "UNKNOWN";
+		switch(event) {
+			case ServerHook.PRE_STARTUP: hooktype="PRE_STARTUP";break;
+			case ServerHook.POST_STARTUP: hooktype="POST_STARTUP";break;
+			case ServerHook.PRE_SHUTDOWN: hooktype="PRE_SHUTDOWN";break;
+			case ServerHook.POST_SHUTDOWN: hooktype="POST_SHUTDOWN";break;
+		}
+		
+		while(iterator.hasNext()) {
+			serverHook = (ServerHook)iterator.next();
+			try	{
+				result = serverHook.handleEvent(event);
+			} catch(Exception e) {
+				result = false;
+				logger.log(Level.WARNING, "Error invoking {0} hook [{1}]: {2}", 
+					new Object[]{hooktype, serverHook.getClass().getName(), e.getMessage()});
+			}
+			logger.log(Level.FINE, "Invoked {0} hook [{1}] was: {2}", 
+				new Object[]{hooktype, serverHook.getClass().getName(), result});
+		}
+	}
+
+	/**
+	 * Creates and returns a copy of this object.
+	 * @since 1.3.3
+	 */
+	public Object clone() {
+		Object object = null;
+		try {
+			object = super.clone(); 
+			QuickServer _qs = (QuickServer) object;
+			_qs.setQSAdminServer( new QSAdminServer(_qs) );
+		} catch(CloneNotSupportedException e) {
+			logger.log(Level.WARNING, "Error cloning : {0}", e);//should not happ
+		}
+		return object;
+	}
+
+	/**
+	 * Sets the Secure setting for QuickServer
+	 * @since 1.4.0
+	 */
+	public void setSecure(Secure secure) {
+		this.secure = secure;
+	}
+	/**
+	 * Returns Secure setting for QuickServer
+	 * @since 1.4.0
+	 */
+	public Secure getSecure() {
+		if(secure==null) secure = new Secure();
+		return secure;
+	}
+
+	/**
+	 * <p>Returns if the server is running in Secure mode [SSL or TLS].</p>
+	 * @since 1.4.0
+	 */
+	public boolean isRunningSecure() {
+		return runningSecure;
+	}
+
+	/**
+	 * <p>Sets the server mode if its running in Secure mode [SSL or TLS].</p>
+	 * @since 1.4.0
+	 */
+	public void setRunningSecure(boolean runningSecure) {
+		this.runningSecure = runningSecure;
+	}
+
+	private File makeAbsoluteToConfig(String fileName) {
+		Assertion.affirm(fileName!=null, "FileName can't be null");
+		return ConfigReader.makeAbsoluteToConfig(fileName, getConfig());
+	}
+
+	/**
+	 * Returns a ServerSocket object to be used for listening.
+	 * @since 1.4.0
+	 */
+	protected void makeServerSocket() 
+			throws BindException, IOException {
+		server = null;
+		logger.log(Level.FINEST, "Binding {0} to IP: {1}", new Object[]{getName(), getBindAddr()});
+		InetSocketAddress bindAddress = 
+			new InetSocketAddress(getBindAddr(), getPort());
+
+		try {
+			NetworkInterface ni = NetworkInterface.getByInetAddress(getBindAddr());
+			if(ni!=null) {
+				logger.fine("NetworkInterface: "+ni);
+			}
+		} catch(Exception igrnore) {/*ignore*/}
+		  catch(Error igrnore) {/*ignore*/}
+		
+
+		if(getSecure().isEnable()==false) {
+			logger.log(Level.FINE, "Making a normal ServerSocket for {0}", getName());
+			setRunningSecure(false);
+			
+			if(getBlockingMode()==false) {
+				//for non-blocking
+				serverSocketChannel = ServerSocketChannel.open();
+				server = serverSocketChannel.socket();
+				server.bind(bindAddress, 
+					getBasicConfig().getAdvancedSettings().getBacklog());
+			} else {
+				//for blocking
+				server = new ServerSocket(getPort(), getBasicConfig().getAdvancedSettings().getBacklog(), getBindAddr());
+			}
+		} else {
+			try	{
+				logger.log(Level.FINE, "Making a secure ServerSocket for {0}", getName());
+				getSSLContext();
+				setRunningSecure(true);
+					
+				
+				
+				if(getBlockingMode()==false) {
+					
+					logger.log(Level.FINE, "Making a secure ServerSocketChannel for {0}", getName());
+					//for non-blocking
+					serverSocketChannel = ServerSocketChannel.open();
+					server = serverSocketChannel.socket();
+					server.bind(bindAddress, 
+						getBasicConfig().getAdvancedSettings().getBacklog());
+				} else {
+					
+					ServerSocketFactory ssf = getSSLContext().getServerSocketFactory();
+					SSLServerSocket serversocket = (SSLServerSocket) 
+						ssf.createServerSocket(getPort(), 
+						getBasicConfig().getAdvancedSettings().getBacklog(), 
+						getBindAddr());
+					serversocket.setNeedClientAuth(secure.isClientAuthEnable());
+					setRunningSecure(true);
+
+					secureStoreManager.logSSLServerSocketInfo(serversocket);
+
+					server = serversocket;
+					serverSocketChannel = server.getChannel();
+					
+					if(serverSocketChannel==null && getBlockingMode()==false) {
+						logger.warning("Secure Server does not support Channel! So will run in blocking mode.");
+						blockingMode = false;
+					}
+										
+				}//blocking
+			} catch(NoSuchAlgorithmException e)	{
+				logger.log(Level.WARNING, "NoSuchAlgorithmException : {0}", e);
+				throw new IOException("Error creating secure socket : "+e.getMessage());
+			} catch(KeyManagementException e) {
+				logger.log(Level.WARNING, "KeyManagementException : {0}", e);
+				throw new IOException("Error creating secure socket : "+e.getMessage());
+			}
+		}
+
+		server.setReuseAddress(true);
+		
+		int connectionTime = 0;
+		int latency = 0;
+		int bandwidth = 0;
+		
+		connectionTime = getBasicConfig().getAdvancedSettings().getPerformancePreferencesConnectionTime();
+		latency = getBasicConfig().getAdvancedSettings().getPerformancePreferencesLatency();
+		bandwidth = getBasicConfig().getAdvancedSettings().getPerformancePreferencesBandwidth();
+
+		logger.log(Level.FINE, "getPerformancePreferencesConnectionTime : {0}", connectionTime);
+		logger.log(Level.FINE, "getPerformancePreferencesLatency : {0}", latency);
+		logger.log(Level.FINE, "getPerformancePreferencesBandwidth : {0}", bandwidth);
+		
+		server.setPerformancePreferences(connectionTime, latency, bandwidth);
+		
+		int clientSocketReceiveBufferSize = getBasicConfig().getAdvancedSettings().getClientSocketReceiveBufferSize();
+		if(clientSocketReceiveBufferSize>0) {
+			logger.log(Level.FINE, "clientSocketReceiveBufferSize: {0}", clientSocketReceiveBufferSize);
+			server.setReceiveBufferSize(clientSocketReceiveBufferSize);
+		}
+
+		if(getBlockingMode()==false) {
+			logger.log(Level.FINE, "Server Mode {0} - Non Blocking", getName());
+			if(selector==null || selector.isOpen()==false) {
+				logger.finest("Opening new selector");
+				selector = Selector.open();
+			} else {
+				logger.log(Level.FINEST, "Reusing selector: {0}", selector);
+			}
+			serverSocketChannel.configureBlocking(false);
+			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
+			selector.wakeup();
+		} else {
+			logger.log(Level.FINE, "Server Mode {0} - Blocking", getName());
+		}
+	}
+
+	/**
+	 * Sets the basic configuration of the QuickServer.
+	 * @since 1.4.0
+	 */
+	public void setBasicConfig(BasicServerConfig basicConfig) 
+			throws Exception {
+		Assertion.affirm(basicConfig!=null, "BasicServerConfig can't be null");
+		this.basicConfig = basicConfig;
+	}
+
+	/**
+	 * Returns the basic configuration of the QuickServer.
+	 * @since 1.4.0
+	 */
+	public BasicServerConfig getBasicConfig() {
+		return basicConfig;
+	}
+
+	/**
+	 * Loads the <code>SSLContext</code> from Secure configuring if set.
+	 * @see #setSecure
+	 * @since 1.4.0
+	 */
+	public void loadSSLContext() throws IOException {
+		if(getSecure().isLoad()==false) {
+			throw new IllegalStateException("Secure setting is not yet enabled for loading!");
+		}
+		logger.info("Loading Secure Context..");
+		km = null;
+		tm = null;
+		try {
+			String ssManager = "org.quickserver.security.SecureStoreManager";
+			if(getSecure().getSecureStore()!=null) {
+				ssManager = getSecure().getSecureStore().getSecureStoreManager();
+                        }
+
+			Class secureStoreManagerClass = getClass(ssManager, true);
+
+			secureStoreManager = (SecureStoreManager) secureStoreManagerClass.newInstance();
+
+			km = secureStoreManager.loadKeyManagers(getConfig());
+			logger.fine("KeyManager got");
+
+			tm = secureStoreManager.loadTrustManagers(getConfig());
+			logger.fine("TrustManager got");
+
+			sslc = secureStoreManager.getSSLContext(getConfig());
+			sslc.init(km, tm, null);
+			logger.fine("SSLContext loaded "+sslc.getProvider());
+		} catch(KeyStoreException e) {
+			logger.warning("KeyStoreException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(NoSuchAlgorithmException e) {
+			logger.warning("NoSuchAlgorithmException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(NoSuchProviderException e) {
+			logger.warning("NoSuchProviderException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(UnrecoverableKeyException e) {
+			logger.warning("UnrecoverableKeyException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(CertificateException e) {
+			logger.warning("CertificateException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(KeyManagementException e) {
+			logger.warning("KeyManagementException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(GeneralSecurityException e) {
+			logger.warning("GeneralSecurityException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(ClassNotFoundException e) {
+			logger.warning("ClassNotFoundException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(InstantiationException e) {
+			logger.warning("InstantiationException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		} catch(IllegalAccessException e) {
+			logger.warning("IllegalAccessException : "+e);
+			throw new IOException("Error creating secure socket : "+e.getMessage());
+		}
+	}
+
+	/**
+	 * Returns the <code>SSLContext</code> from Secure configuring.
+	 * @see #loadSSLContext
+	 * @since 1.4.0
+	 */
+	public SSLContext getSSLContext() 
+			throws IOException, NoSuchAlgorithmException, 
+				KeyManagementException {
+		return getSSLContext(null);
+	}
+
+	/**
+	 * Returns the <code>SSLContext</code> object that implements the specified 
+	 * secure socket protocol from Secure configuring.
+	 * @see #loadSSLContext
+	 * @param protocol the standard name of the requested protocol. If <code>null</code> will use the protocol set in secure configuration of the server.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+	public SSLContext getSSLContext(String protocol) 
+			throws IOException, NoSuchAlgorithmException, 
+				KeyManagementException {
+		if(sslc==null) {
+                    loadSSLContext();
+                }
+		
+		return sslc;
+	}
+
+	/**
+	 * Returns a SSLSocketFactory object to be used for creating SSLSockets. 
+	 * Secure socket protocol will be picked from the Secure configuring.
+	 * @see #setSecure
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+	public SSLSocketFactory getSSLSocketFactory() 
+			throws IOException, NoSuchAlgorithmException, 
+				KeyManagementException {
+		if(sslc==null) loadSSLContext();		
+		return secureStoreManager.getSocketFactory(getSSLContext());
+	}
+
+	/**
+	 * Returns a SSLSocketFactory object to be used for creating SSLSockets. 
+	 * @see #setSecure
+	 * @param protocol the standard name of the requested protocol. If 
+	 * <code>null</code> will use the protocol set in secure configuration 
+	 * of the server.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+	public SSLSocketFactory getSSLSocketFactory(String protocol) 
+			throws IOException, NoSuchAlgorithmException, KeyManagementException {
+		if(sslc==null) loadSSLContext();		
+		return secureStoreManager.getSocketFactory(getSSLContext(protocol));
+	}
+
+	/**
+     * Sets the ClientBinaryHandler class that interacts with 
+	 * client sockets to handle binary data.
+	 * @param handler object the fully qualified name of the class that 
+	 *  implements {@link ClientBinaryHandler}
+	 * @see #getClientBinaryHandler
+	 * @since 1.4
+     */
+	public void setClientBinaryHandler(String handler) {
+		clientBinaryHandlerString = handler;
+		logger.finest("Set to "+handler);
+	}
+	/**
+     * Returns the ClientBinaryHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientBinaryHandler
+	 * @since 1.4
+     */
+	public String getClientBinaryHandler() {
+		return clientBinaryHandlerString;
+	}
+
+	/**
+	 * Sets the Selector (NIO).
+	 * @since 1.4.5
+	 */
+	public void setSelector(Selector selector) {
+		this.selector = selector;
+	}
+	/**
+	 * Returns the Selector (NIO),if any.
+	 * @since 1.4.5
+	 */
+	public Selector getSelector() {
+		return selector;
+	}
+
+	/**
+	 * Starts server in blocking mode.
+	 * @since 1.4.5
+	 */
+	private void runBlocking(TheClient theClient) throws Exception {
+		Socket client = null;
+		ClientHandler _chPolled = null;
+		int linger = getBasicConfig().getAdvancedSettings().getSocketLinger();
+		
+		int socketTrafficClass = 0;
+		if(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass()!=null) {
+			socketTrafficClass = Integer.parseInt(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass());
+		}
+
+		//long stime = System.currentTimeMillis();
+		//long etime = System.currentTimeMillis();
+		while(true) {
+			//etime = System.currentTimeMillis();
+			//System.out.println("Time Taken: "+(etime-stime));
+			client = server.accept();
+			//stime = System.currentTimeMillis();
+
+			if(linger<0) {
+				client.setSoLinger(false, 0);
+			} else {
+				client.setSoLinger(true, linger);
+			}
+			
+			client.setTcpNoDelay(getBasicConfig().getAdvancedSettings().getClientSocketTcpNoDelay());
+			
+			if(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass()!=null) {
+				client.setTrafficClass(socketTrafficClass);//low delay=10
+			}
+			
+			//logger.fine("ReceiveBufferSize: "+client.getReceiveBufferSize());
+			
+			if(getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize()!=0) {
+				client.setSendBufferSize(getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize());
+				//logger.fine("SendBufferSize: "+client.getSendBufferSize());
+			}
+
+			if(stopServer) {
+				//Client connected when server was about to be shutdown.
+				try {
+					client.close();
+				} catch(Exception e) {}
+				break;
+			}
+
+			if(checkAccessConstraint(client)==false) {
+				continue;
+			}
+
+			//Check if max connection has reached
+			if(getSkipValidation()!=true && maxConnection != -1 && 
+					getClientHandlerPool().getNumActive() >= maxConnection) {
+				theClient.setClientEvent(ClientEvent.MAX_CON_BLOCKING);
+			} else {
+				theClient.setClientEvent(ClientEvent.RUN_BLOCKING);
+			}
+
+			theClient.setTrusted(getSkipValidation());
+			theClient.setSocket(client);			
+			theClient.setSocketChannel(client.getChannel()); //mostly null
+
+			if(clientDataClass != null) {
+				if(getClientDataPool()==null) {
+					clientData = (ClientData)clientDataClass.newInstance();
+				} else {
+					clientData = (ClientData)getClientDataPool().borrowObject();
+				}
+				theClient.setClientData(clientData);
+			}
+
+			try {
+				_chPolled = (ClientHandler) getClientHandlerPool().borrowObject();
+				_chPolled.handleClient(theClient);				
+			} catch(java.util.NoSuchElementException nsee) {
+				logger.warning("Could not borrow ClientHandler from pool. Error: "+nsee);
+				logger.warning("Closing Socket ["+client+"] since no ClientHandler available.");
+				client.close();
+			}
+			
+			if(_chPolled!=null) {
+				try {
+					getClientPool().addClient(_chPolled, true);
+				} catch(java.util.NoSuchElementException nsee) {
+					logger.warning("Could not borrow Thread from pool. Error: "+nsee);					
+					//logger.warning("Closing Socket ["+client+"] since no Thread available.");
+					//client.close();
+					//returnClientHandlerToPool(_chPolled);
+				}
+				_chPolled = null;
+			}
+			client = null;
+
+			//reset it back
+			setSkipValidation(false);
+		}//end of loop
+	}
+
+	/**
+	 * Starts server in non-blocking mode.
+	 * @since 1.4.5
+	 */
+	private void runNonBlocking(TheClient theClient) throws Exception {
+		int selectCount = 0;
+		Iterator iterator = null;
+		SelectionKey key = null;
+		ServerSocketChannel serverChannel = null;
+		SocketChannel socketChannel = null;
+		Socket client = null;
+		ClientHandler _chPolled = null;
+		boolean stopServerProcessed = false;
+		int linger = getBasicConfig().getAdvancedSettings().getSocketLinger();
+		registerChannelRequestMap = new HashMap();
+		
+		int socketTrafficClass = 0;
+		if(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass()!=null) {
+			socketTrafficClass = Integer.parseInt(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass());
+		}
+
+
+		while(true) {
+			selectCount = selector.select(500);
+			//selectCount = selector.select();//for testing
+			
+			//check for any pending registerChannel req.
+			synchronized(registerChannelRequestMap) {				
+				if(registerChannelRequestMap.size()>0) {
+					RegisterChannelRequest req = null;
+					Object hashkey = null;
+					iterator = registerChannelRequestMap.keySet().iterator();
+					while(iterator.hasNext()) {
+						hashkey = iterator.next();
+						req = (RegisterChannelRequest) registerChannelRequestMap.get(hashkey);
+						req.register(getSelector());
+					}
+					iterator = null;
+					registerChannelRequestMap.clear();
+				}//if
+			}//sync
+			
+			if(stopServer==true && stopServerProcessed==false) {
+				logger.warning("Closing "+getName());
+				serverSocketChannel.close();
+				stopServerProcessed = true;
+
+				server = null;
+				serverSocketChannel = null;
+
+				setServiceState(Service.STOPPED);
+				logger.warning("Closed "+getName());
+
+				processServerHooks(ServerHook.POST_SHUTDOWN);
+			}
+
+			if(stopServer==false && stopServerProcessed==true) {
+				logger.finest("Server must have re-started.. will break");
+				break;
+			}
+
+			if(selectCount==0 && stopServerProcessed==true) {
+				java.util.Set keyset = selector.keys();
+				if(keyset.isEmpty()==true && getClientCount()<=0) {
+					break;
+				} else {
+					continue;
+				}
+			} else if(selectCount==0) {
+				continue;
+			}
+
+			iterator = selector.selectedKeys().iterator();			
+			while(iterator.hasNext()) {
+				key = (SelectionKey) iterator.next();
+
+				if(key.isValid()==false) {
+					iterator.remove();
+					continue;
+				}
+				
+				if(key.isAcceptable() && stopServer==false) {
+					logger.finest("Key is Acceptable");
+					serverChannel = (ServerSocketChannel) key.channel();
+					socketChannel = serverChannel.accept();
+					
+					if(socketChannel==null) {
+						iterator.remove();
+						continue;
+					}
+
+					client = socketChannel.socket();
+
+					if(linger<0) {
+						client.setSoLinger(false, 0);
+					} else {
+						client.setSoLinger(true, linger);
+					}
+					
+					client.setTcpNoDelay(getBasicConfig().getAdvancedSettings().getClientSocketTcpNoDelay());
+			
+					if(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass()!=null) {
+						client.setTrafficClass(socketTrafficClass);//low delay=10
+					}
+
+					//logger.fine("ReceiveBufferSize: "+client.getReceiveBufferSize());
+
+					if(getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize()!=0) {
+						client.setSendBufferSize(getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize());
+						//logger.fine("SendBufferSize: "+client.getSendBufferSize());
+					}
+
+					if(checkAccessConstraint(client)==false) {
+						iterator.remove();
+						continue;
+					}					
+
+					socketChannel.configureBlocking(false);
+					theClient.setTrusted(getSkipValidation());
+					theClient.setSocket(socketChannel.socket());
+					theClient.setSocketChannel(socketChannel);
+
+					if(clientDataClass != null) {
+						if(getClientDataPool()==null) {
+							clientData = (ClientData)clientDataClass.newInstance();
+						} else {
+							//borrow a object from pool
+							clientData = (ClientData)getClientDataPool().borrowObject();
+						}
+						theClient.setClientData(clientData);
+					}
+
+					//Check if max connection has reached
+					if(getSkipValidation()!=true && maxConnection != -1 && 
+							getClientHandlerPool().getNumActive() >= maxConnection) {
+						theClient.setClientEvent(ClientEvent.MAX_CON);
+					} else {
+						theClient.setClientEvent(ClientEvent.ACCEPT);						
+					}
+
+					try {
+						_chPolled = (ClientHandler)getClientHandlerPool().borrowObject();
+						logger.finest("Asking "+_chPolled.getName()+" to handle."); 
+						_chPolled.handleClient(theClient);						
+					} catch(java.util.NoSuchElementException nsee) {
+						logger.warning("Could not borrow ClientHandler Object from pool. Error: "+nsee);
+						logger.warning("Closing SocketChannel ["+serverChannel.socket()+"] since no ClientHandler available.");
+						socketChannel.close();
+					}
+
+					if(_chPolled!=null) {
+						try {
+							getClientPool().addClient(_chPolled, true);
+						} catch(java.util.NoSuchElementException nsee) {
+							logger.warning("Could not borrow Thread from pool. Error: "+nsee);
+							//logger.warning("Closing SocketChannel ["+serverChannel.socket()+"] since no Thread available.");
+							//socketChannel.close();
+							//returnClientHandlerToPool(_chPolled);
+						}
+						_chPolled = null;
+					}
+					socketChannel = null;
+					client = null;
+					
+					setSkipValidation(false);//reset it back
+				} else if(key.isValid() && key.isReadable()) {
+					boolean addedEvent = false;
+					ClientHandler _ch = null;
+					try {
+						_ch = (ClientHandler)key.attachment();
+						logger.finest("Key is Readable, removing OP_READ from interestOps for "+_ch.getName());
+						key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
+						_ch.addEvent(ClientEvent.READ);addedEvent= true;
+						//_ch.setSelectionKey(key);
+						getClientPool().addClient(_ch);
+					} catch(CancelledKeyException cke) {
+						logger.fine("Ignored Error - Key was Cancelled: "+cke);
+					} catch(java.util.NoSuchElementException nsee) {
+						logger.finest("NoSuchElementException: "+nsee);
+						if(addedEvent) _ch.removeEvent(ClientEvent.READ);
+						continue;//no need to remove the key
+					}
+					_ch = null;
+				} else if(key.isValid() && key.isWritable()) {
+					if(getClientPool().shouldNioWriteHappen()==false) {
+						continue; //no need to remove the key
+					}
+					boolean addedEvent = false;
+					ClientHandler _ch = null;
+					try {
+						_ch = (ClientHandler)key.attachment();
+						logger.finest("Key is Writable, removing OP_WRITE from interestOps for "+_ch.getName());
+						//remove OP_WRITE from interest set
+						key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
+						_ch.addEvent(ClientEvent.WRITE);addedEvent= true;
+						//_ch.setSelectionKey(key);
+						getClientPool().addClient(_ch);
+					} catch(CancelledKeyException cke) {
+						logger.fine("Ignored Error - Key was Cancelled: "+cke);
+					} catch(java.util.NoSuchElementException nsee) {
+						logger.finest("NoSuchElementException: "+nsee);
+						if(addedEvent) _ch.removeEvent(ClientEvent.WRITE);
+						continue;//no need to remove the key
+					}
+					_ch = null;
+				} else if(stopServer==true && key.isAcceptable()) {
+					//we will not accept this key
+					setSkipValidation(false);//reset it back
+				} else {
+					logger.warning("Unknown key got in SelectionKey: "+key);
+				}
+				iterator.remove(); //Remove key
+
+				Thread.yield();
+			} //end of iterator
+			iterator = null;
+		}//end of loop
+	}
+
+	private boolean checkAccessConstraint(Socket socket) {
+		try {
+			if(getAccessConstraintConfig()!=null) {
+				getAccessConstraintConfig().checkAccept(socket);
+			}
+			return true;
+		} catch(SecurityException se) {
+			logger.warning("SecurityException occurred accepting connection : "
+				+se.getMessage());
+			return false;
+		}
+	}
+
+	/**
+	 * Register the given channel for the given operations. This adds the request
+	 * to a list and will be processed after selector select wakes up.
+	 * @return boolean flag to indicate if new entry was added to the list to register.
+	 * @since 1.4.5
+	 */
+	public boolean registerChannel(SocketChannel channel, int ops, Object att) 
+			throws IOException, ClosedChannelException {
+		if(getSelector()==null) {
+			throw new IllegalStateException("Selector is not open!");
+		}
+		if(channel==null) {
+			throw new IllegalArgumentException("Can't register a null channel!");
+		}
+
+		if(channel.isConnected()==false) {
+			throw new ClosedChannelException();
+		}
+		
+		RegisterChannelRequest req = new RegisterChannelRequest(channel, ops, att);
+		RegisterChannelRequest reqOld = null;
+		synchronized(registerChannelRequestMap) {
+			reqOld = (RegisterChannelRequest) registerChannelRequestMap.get(channel);
+			if(reqOld==null) {
+				registerChannelRequestMap.put(channel, req);
+				getSelector().wakeup();
+				return true;
+			} else {
+				if(reqOld.equals(req)==false) {
+					reqOld.setOps(reqOld.getOps() | req.getOps());
+					reqOld.setAtt(req.getAtt());
+					return true;
+				}
+				return false;
+			}
+		}
+		/*
+		logger.warning("Before register...");
+		channel.register(getSelector(), ops, att);
+		logger.warning("Before wakeup and after register...");
+		getSelector().wakeup();
+		logger.warning("After wakeup...");
+		*/		
+	}
+
+	/** 
+	 * Makes the pool of ByteBuffer
+	 * @since 1.4.5
+	 */
+	private void makeByteBufferPool(PoolConfig opConfig) {
+		logger.finer("Creating ByteBufferPool pool");
+
+		int bufferSize = getBasicConfig().getAdvancedSettings().getByteBufferSize();
+		boolean useDirectByteBuffer = getBasicConfig().getAdvancedSettings().getUseDirectByteBuffer();
+		PoolableObjectFactory factory = new ByteBufferObjectFactory(bufferSize, useDirectByteBuffer);
+
+		byteBufferPool = poolManager.makeByteBufferPool(factory, opConfig);
+		poolManager.initPool(byteBufferPool, opConfig);
+	}
+
+	/**
+	 * Returns ObjectPool of java.nio.ByteBuffer class. 
+	 * @since 1.4.5
+	 */
+	public ObjectPool getByteBufferPool() {
+		return byteBufferPool;
+	}
+
+	/** 
+	 * Makes the pool of ByteBuffer
+	 * @since 1.4.5
+	 */
+	private void makeClientPool(PoolConfig opConfig) throws Exception {
+		logger.finer("Creating ClientThread pool");
+		ThreadObjectFactory factory = new ThreadObjectFactory();
+		ObjectPool objectPool = poolManager.makeClientPool(factory, opConfig);
+		pool = new ClientPool(makeQSObjectPool(objectPool), opConfig);
+		factory.setClientPool(pool);
+		pool.setMaxThreadsForNioWrite(
+			getBasicConfig().getAdvancedSettings().getMaxThreadsForNioWrite());
+		poolManager.initPool(objectPool, opConfig);
+	}
+
+	/**
+     * Sets the ClientWriteHandler class that interacts with 
+	 * client sockets to handle data write (only used in non-blocking mode).
+	 * @param handler object the fully qualified name of the class that 
+	 *  implements {@link ClientWriteHandler}
+	 * @see #getClientWriteHandler
+	 * @since 1.4.5
+     */
+	public void setClientWriteHandler(String handler) {
+		clientWriteHandlerString = handler;
+		logger.log(Level.FINEST, "Set to {0}", handler);
+	}
+	/**
+     * Returns the ClientWriteHandler class that interacts with 
+	 * client sockets (only used in non-blocking mode).
+	 * @see #setClientWriteHandler
+	 * @since 1.4.5
+     */
+	public String getClientWriteHandler() {
+		return clientWriteHandlerString;
+	}
+
+	/**
+     * Returns the date/time when the server was last started.
+	 * @return last started time. Will be <code>null</code> if never started.
+	 * @since 1.4.5
+     */
+	public java.util.Date getLastStartTime() {
+		return lastStartTime;
+	}
+
+	/**
+	 * Sets the debug flag to ByteBufferOutputStream and
+	 * ByteBufferInputStream class that are used in non-blcking mode
+	 * @since 1.4.5
+	 */
+	public static void setDebugNonBlockingMode(boolean flag) {
+		org.quickserver.util.io.ByteBufferOutputStream.setDebug(flag);
+		org.quickserver.util.io.ByteBufferInputStream.setDebug(flag);
+	}
+
+	/**
+	 * Returns the implementation that is used to do Client Identification.
+	 * @since 1.4.5
+	 */
+	public ClientIdentifier getClientIdentifier() {
+		return clientIdentifier;
+	}
+
+	/**
+	 * Makes QSObjectPool from ObjectPool
+	 * @since 1.4.5
+	 */
+	private QSObjectPool makeQSObjectPool(ObjectPool objectPool) 
+			throws Exception {
+		return (QSObjectPool) qsObjectPoolMaker.getQSObjectPool(objectPool);
+	}
+
+	
+	/**
+	 * Returns the current blocking mode of the server.
+	 * @since 1.4.6
+	 */
+	public boolean getBlockingMode() {
+		return blockingMode;
+	}
+
+	/**
+	 * Loads all the Business Logic class
+	 * @since 1.4.6
+	 */
+	protected void loadBusinessLogic() throws Exception {
+		if(clientCommandHandlerString == null && 
+				clientEventHandlerString == null) {
+			logger.severe("ClientCommandHandler AND ClientEventHandler was not set.");
+			throw new AppException("ClientCommandHandler AND ClientEventHandler was not set.");
+		}
+
+		clientCommandHandler = null;
+		if(clientCommandHandlerString != null) {
+			logger.finest("Loading ClientCommandHandler class..");
+			Class clientCommandHandlerClass = 
+				getClass(clientCommandHandlerString, true);
+			clientCommandHandler = (ClientCommandHandler) 
+				clientCommandHandlerClass.newInstance();
+		}
+
+		boolean setClientCommandHandlerLookup = false;
+		clientEventHandler = null;
+		if(clientEventHandlerString==null) {
+			clientEventHandlerString = "org.quickserver.net.server.impl.DefaultClientEventHandler";
+			setClientCommandHandlerLookup = true;
+		}
+		logger.finest("Loading ClientEventHandler class..");
+		if(clientEventHandlerString.equals(clientCommandHandlerString) && 
+				ClientEventHandler.class.isInstance(clientCommandHandler)) {
+			clientEventHandler = (ClientEventHandler) clientCommandHandler;
+		} else {
+			clientEventHandler = (ClientEventHandler) 
+				getClass(clientEventHandlerString, true).newInstance();
+			if(setClientCommandHandlerLookup) {
+				((DefaultClientEventHandler)clientEventHandler).setClientCommandHandler(
+					clientCommandHandler);
+			}
+		}
+
+		clientExtendedEventHandler = null;
+		if(clientExtendedEventHandlerString != null) {
+			logger.finest("Loading ClientExtendedEventHandler class..");
+			if(clientExtendedEventHandlerString.equals(clientCommandHandlerString) && 
+					ClientExtendedEventHandler.class.isInstance(clientCommandHandler)) {
+				clientExtendedEventHandler = (ClientExtendedEventHandler) clientCommandHandler;
+			} else if(clientExtendedEventHandlerString.equals(clientEventHandlerString) && 
+					ClientExtendedEventHandler.class.isInstance(clientEventHandler)) {
+				clientExtendedEventHandler = (ClientExtendedEventHandler) clientEventHandler;
+			} else {
+				Class clientExtendedEventHandlerClass = 
+					getClass(clientExtendedEventHandlerString, true);
+				clientExtendedEventHandler = (ClientExtendedEventHandler) 
+					clientExtendedEventHandlerClass.newInstance();
+			}
+		}
+
+		clientObjectHandler = null;
+		if(clientObjectHandlerString != null) {
+			logger.finest("Loading ClientObjectHandler class..");
+			if(clientObjectHandlerString.equals(clientCommandHandlerString) && 
+					ClientObjectHandler.class.isInstance(clientCommandHandler)) {
+				clientObjectHandler = (ClientObjectHandler) clientCommandHandler;
+			} else if(clientObjectHandlerString.equals(clientEventHandlerString) && 
+					ClientObjectHandler.class.isInstance(clientEventHandler)) {
+				clientObjectHandler = (ClientObjectHandler) clientEventHandler;
+			} else if(clientObjectHandlerString.equals(clientExtendedEventHandlerString) && 
+					ClientObjectHandler.class.isInstance(clientExtendedEventHandler)) {
+				clientObjectHandler = (ClientObjectHandler) clientExtendedEventHandler;
+			} else {
+				clientObjectHandler = (ClientObjectHandler)
+					getClass(clientObjectHandlerString, true).newInstance();
+			}
+		} //end of != null
+
+		clientBinaryHandler = null;
+		if(clientBinaryHandlerString != null) {
+			logger.finest("Loading ClientBinaryHandler class..");
+			if(clientBinaryHandlerString.equals(clientCommandHandlerString) && 
+					ClientBinaryHandler.class.isInstance(clientCommandHandler)) {
+				clientBinaryHandler = (ClientBinaryHandler) clientCommandHandler;
+			} else if(clientBinaryHandlerString.equals(clientEventHandlerString) && 
+					ClientBinaryHandler.class.isInstance(clientEventHandler)) {
+				clientBinaryHandler = (ClientBinaryHandler) clientEventHandler;
+			} else if(clientBinaryHandlerString.equals(clientExtendedEventHandlerString) && 
+					ClientBinaryHandler.class.isInstance(clientExtendedEventHandler)) {
+				clientBinaryHandler = (ClientBinaryHandler) clientExtendedEventHandler;
+			} else if(clientBinaryHandlerString.equals(clientObjectHandlerString) && 
+					ClientBinaryHandler.class.isInstance(clientObjectHandler)) {
+				clientBinaryHandler = (ClientBinaryHandler) clientObjectHandler;
+			} else {
+				clientBinaryHandler = (ClientBinaryHandler)
+					getClass(clientBinaryHandlerString, true).newInstance();
+			}
+		} //end of != null
+
+		clientWriteHandler = null;
+		if(clientWriteHandlerString != null) {
+			logger.finest("Loading ClientWriteHandler class..");
+			if(clientWriteHandlerString.equals(clientCommandHandlerString) && 
+					ClientWriteHandler.class.isInstance(clientCommandHandler)) {
+				clientWriteHandler = (ClientWriteHandler) clientCommandHandler;
+			} else if(clientWriteHandlerString.equals(clientEventHandlerString) && 
+					ClientWriteHandler.class.isInstance(clientEventHandler)) {
+				clientWriteHandler = (ClientWriteHandler) clientEventHandler;
+			} else if(clientWriteHandlerString.equals(clientExtendedEventHandlerString) && 
+					ClientWriteHandler.class.isInstance(clientExtendedEventHandler)) {
+				clientWriteHandler = (ClientWriteHandler) clientExtendedEventHandler;
+			} else if(clientWriteHandlerString.equals(clientObjectHandlerString) && 
+					ClientWriteHandler.class.isInstance(clientObjectHandler)) {
+				clientWriteHandler = (ClientWriteHandler) clientObjectHandler;
+			} else if(clientWriteHandlerString.equals(clientBinaryHandlerString) && 
+					ClientWriteHandler.class.isInstance(clientBinaryHandler)) {
+				clientWriteHandler = (ClientWriteHandler) clientBinaryHandler;
+			} else {
+				clientWriteHandler = (ClientWriteHandler)
+					getClass(clientWriteHandlerString, true).newInstance();
+			}
+		} //end of != null
+
+		Class authenticatorClass = null;
+		if(clientAuthenticationHandlerString != null) {
+			logger.finest("Loading ClientAuthenticationHandler class..");
+			authenticatorClass = getClass(clientAuthenticationHandlerString, true);
+		}
+
+		if(authenticatorClass!=null) {
+			Object obj = authenticatorClass.newInstance();
+
+			if(ClientAuthenticationHandler.class.isInstance(obj))
+				clientAuthenticationHandler = (ClientAuthenticationHandler) obj;
+			else
+				authenticator = (Authenticator) obj;
+		}
+
+		clientDataClass = null;
+		if(clientDataString != null) {
+			logger.finest("Loading ClientData class..");
+			clientDataClass = getClass(clientDataString, true);
+		}
+
+		Assertion.affirm(clientEventHandler!=null, "ClientEventHandler was not loaded!");
+	}
+
+	/**
+     * Sets the ClientEventHandler class that gets notified of 
+	 * client events.
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link ClientEventHandler}
+	 * @see #getClientEventHandler
+	 * @since 1.4.6
+     */
+	public void setClientEventHandler(String handler) {
+		clientEventHandlerString = handler;
+		logger.finest("Set to "+handler);
+	}	
+	/**
+     * Returns the ClientEventHandler class that gets notified of 
+	 * client events.
+	 * @see #setClientEventHandler
+	 * @since 1.4.6
+     */
+	public String getClientEventHandler() {
+		return clientEventHandlerString;
+	}
+
+	/**
+	 * Sets the default {@link DataMode} for the ClientHandler
+	 * @since 1.4.6
+	 */
+	public void setDefaultDataMode(DataMode dataMode, DataType dataType) 
+			throws IOException {
+		if(dataType==DataType.IN)
+			this.defaultDataModeIN = dataMode;
+		if(dataType==DataType.OUT)
+			this.defaultDataModeOUT = dataMode;
+	}
+	/**
+	 * Sets the default {@link DataMode} for the ClientHandler
+	 * @since 1.4.6
+	 */
+	public void setDefaultDataMode(DefaultDataMode defaultDataMode) 
+			throws IOException {
+		defaultDataModeIN = defaultDataMode.getDataMode(DataType.IN);
+		defaultDataModeOUT = defaultDataMode.getDataMode(DataType.OUT);;
+	}
+	/**
+	 * Returns the default {@link DataMode} for the ClientHandler
+	 * @since 1.4.6
+	 */
+	public DataMode getDefaultDataMode(DataType dataType) {
+		if(dataType==DataType.IN)
+			return defaultDataModeIN;
+		if(dataType==DataType.OUT)
+			return defaultDataModeOUT;
+		else
+			throw new IllegalArgumentException("Unknown DataType: "+dataType);
+	}
+
+	/**
+     * Sets the ClientExtendedEventHandler class that gets notified of 
+	 * extended client events.
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link ClientExtendedEventHandler}
+	 * @see #getClientExtendedEventHandler
+	 * @since 1.4.6
+     */
+	public void setClientExtendedEventHandler(String handler) {
+		clientExtendedEventHandlerString = handler;
+		logger.finest("Set to "+handler);
+	}	
+	/**
+     * Returns the ClientExtendedEventHandler class that gets notified of 
+	 * extended client events.
+	 * @see #setClientExtendedEventHandler
+	 * @since 1.4.6
+     */
+	public String getClientExtendedEventHandler() {
+		return clientExtendedEventHandlerString;
+	}
+
+	/**
+	 * If Application Jar Path was set, load the jars
+	 * @since 1.4.6
+	 */
+	private void loadApplicationClasses() throws Exception {
+		if(getApplicationJarPath()!=null && getClassLoader()==null) {
+			setClassLoader(	
+				ClassUtil.getClassLoader(getApplicationJarPath()));
+			//update qsadmin to use the same
+			if(adminServer!=null) {
+				adminServer.getServer().setClassLoader(getClassLoader());
+			}
+		}
+	}
+	
+	/** 
+	 * Returns PID of the JVM
+	 * @return PID of the JVM
+	 * @since 1.4.8
+	 */
+	public static String getPID() {
+		return pid;
+	}
+
+	public boolean isRawCommunicationLogging() {
+		return rawCommunicationLogging;
+	}
+
+	public void setRawCommunicationLogging(boolean rawCommunicationLogging) {
+		this.rawCommunicationLogging = rawCommunicationLogging;
+	}
+
+	public int getRawCommunicationMaxLength() {
+		return rawCommunicationMaxLength;
+	}
+
+	public void setRawCommunicationMaxLength(int rawCommunicationMaxLength) {
+		this.rawCommunicationMaxLength = rawCommunicationMaxLength;
+	}
+		
+	public String getUptime() {
+		Date lst = getLastStartTime();
+		return JvmUtil.getUptime(lst);
+	}	
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/QuickServerDebugHelper.java b/quickserver/src/main/org/quickserver/net/server/QuickServerDebugHelper.java
new file mode 100644
index 0000000..768912c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/QuickServerDebugHelper.java
@@ -0,0 +1,172 @@
+package org.quickserver.net.server;
+
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.pool.ObjectPool;
+import org.quickserver.net.server.ClientHandler;
+import org.quickserver.net.server.ClientIdentifier;
+import org.quickserver.net.server.QuickServer;
+import org.quickserver.util.pool.PoolHelper;
+import org.quickserver.util.pool.QSObjectPool;
+import org.quickserver.util.pool.thread.ClientThread;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ */
+public class QuickServerDebugHelper {
+	
+	public static void logInfoServer(Logger logger, QuickServer quickserver) {
+		logger.info("+OK info follows");
+		logger.info(""+quickserver);
+		logger.info("Running : "+!quickserver.isClosed());
+		logger.info("PID : "+QuickServer.getPID());
+		logger.info("Max Client Allowed  : "+quickserver.getMaxConnection() );
+		logger.info("No Client Connected : "+quickserver.getClientCount() );
+		if(quickserver.isRunningSecure()==true) {
+			logger.info("Running in secure mode : "+
+				quickserver.getSecure().getProtocol() );
+		} else {
+			logger.info("Running in non-secure mode");
+		}
+		logger.info("Server Mode : "+quickserver.getBasicConfig().getServerMode());
+		logger.info("QuickServer v : "+QuickServer.getVersion());
+		logger.info("Uptime : "+quickserver.getUptime());
+		logger.info(".");
+	}
+	
+	public static void logClientHandlerPoolInfo(Logger logger, QuickServer quickserver) {
+		ObjectPool objectPool = quickserver.getClientHandlerPool();
+
+		logger.log(Level.INFO, "logClientHandlerPoolInfo : {0}", quickserver);
+		
+		if(PoolHelper.isPoolOpen(objectPool)==true) {
+			if(QSObjectPool.class.isInstance(objectPool)==false) {
+				logger.info("-ERR System Error! Bad pool got. Not a  QSObjectPool!");
+			}
+
+			ClientIdentifier clientIdentifier = quickserver.getClientIdentifier();
+			ClientHandler foundClientHandler = null;
+			synchronized(clientIdentifier.getObjectToSynchronize()) {	
+				Iterator iterator = clientIdentifier.findAllClient();
+				logger.info("+OK ClientHandlerPool Info follows");
+				while(iterator.hasNext()) {
+					foundClientHandler = (ClientHandler) iterator.next();
+					logger.info(foundClientHandler.info());
+				}
+			}
+			logger.info(".");
+		} else {
+			logger.info("-ERR ClientHandlerPool Pool Closed");
+		}
+	}
+	
+	public static void logClientThreadPoolInfo(Logger logger, QuickServer quickserver) {
+		logger.log(Level.INFO, "logClientThreadPoolInfo : {0}", quickserver);
+		
+		if(PoolHelper.isPoolOpen(quickserver.getClientPool().getObjectPool())==true) {
+			logger.info("NumActive: "+quickserver.getClientPool().getNumActive());
+			
+			logger.info("NumIdle: "+quickserver.getClientPool().getNumIdle());
+		} else {
+			logger.info("ClientThreadPool is closed");
+		}
+		
+			
+		if(PoolHelper.isPoolOpen(quickserver.getClientPool().getObjectPool())==true) {
+			logger.info("+OK ClientThread Pool Dump follows");
+			ClientThread ct = null;
+			synchronized(quickserver.getClientPool().getObjectToSynchronize()) {
+				Iterator iterator = quickserver.getClientPool().getAllClientThread();
+				while(iterator.hasNext()) {
+					ct = (ClientThread)iterator.next();
+					logger.info(ct.toString());
+				}
+			}
+			logger.info(".");
+		} else {
+			logger.info("-ERR ClientThread Pool Closed");
+		}
+	}
+	
+	public static void logAllPoolInfo(Logger logger, QuickServer quickserver) {
+		logger.info("+OK info follows");
+		StringBuilder temp = new StringBuilder();
+		temp.setLength(0);//used:idsle
+
+		if(PoolHelper.isPoolOpen(quickserver.getClientPool().getObjectPool())==true) {
+			temp.append("Client Thread Pool - ");
+			temp.append("Num Active: ");
+			temp.append(quickserver.getClientPool().getNumActive());
+			temp.append(", Num Idle: ");
+			temp.append(quickserver.getClientPool().getNumIdle());
+			temp.append(", Max Idle: ");
+			temp.append(quickserver.getClientPool().getPoolConfig().getMaxIdle());
+			temp.append(", Max Active: ");
+			temp.append(quickserver.getClientPool().getPoolConfig().getMaxActive());				
+		} else {
+			temp.append("Byte Buffer Pool - Closed");
+		}
+		logger.info(temp.toString());
+		temp.setLength(0);
+
+		if(PoolHelper.isPoolOpen(quickserver.getClientHandlerPool())==true) {
+			temp.append("Client Handler Pool - ");
+			temp.append("Num Active: ");
+			temp.append(quickserver.getClientHandlerPool().getNumActive());
+			temp.append(", Num Idle: ");
+			temp.append(quickserver.getClientHandlerPool().getNumIdle());
+			temp.append(", Max Idle: ");
+			temp.append(quickserver.getBasicConfig().getObjectPoolConfig().getClientHandlerObjectPoolConfig().getMaxIdle());
+			temp.append(", Max Active: ");
+			temp.append(quickserver.getBasicConfig().getObjectPoolConfig().getClientHandlerObjectPoolConfig().getMaxActive());
+		} else {
+			temp.append("Client Handler Pool - Closed");
+		}
+		logger.info(temp.toString());
+		temp.setLength(0);
+
+		if(quickserver.getByteBufferPool()!=null) {
+			if(PoolHelper.isPoolOpen(quickserver.getByteBufferPool())==true) {
+				temp.append("ByteBuffer Pool - ");
+				temp.append("Num Active: ");
+				temp.append(quickserver.getByteBufferPool().getNumActive());
+				temp.append(", Num Idle: ");
+				temp.append(quickserver.getByteBufferPool().getNumIdle());
+				temp.append(", Max Idle: ");
+				temp.append(quickserver.getBasicConfig().getObjectPoolConfig().getByteBufferObjectPoolConfig().getMaxIdle());
+				temp.append(", Max Active: ");
+				temp.append(quickserver.getBasicConfig().getObjectPoolConfig().getByteBufferObjectPoolConfig().getMaxActive());
+			} else {
+				temp.append("Byte Buffer Pool - Closed");
+			}
+		} else {
+			temp.append("Byte Buffer Pool - Not Used");
+		}
+		logger.info(temp.toString());
+		temp.setLength(0);
+
+		if(quickserver.getClientDataPool()!=null) {
+			if(PoolHelper.isPoolOpen(quickserver.getClientDataPool())==true) {
+				temp.append("Client Data Pool - ");
+				temp.append("Num Active: ");
+				temp.append(quickserver.getClientDataPool().getNumActive());
+				temp.append(", Num Idle: ");
+				temp.append(quickserver.getClientDataPool().getNumIdle());				
+				temp.append(", Max Idle: ");
+				temp.append(quickserver.getBasicConfig().getObjectPoolConfig().getClientDataObjectPoolConfig().getMaxIdle());
+				temp.append(", Max Active: ");
+				temp.append(quickserver.getBasicConfig().getObjectPoolConfig().getClientDataObjectPoolConfig().getMaxActive());
+			} else {
+				temp.append("Client Data Pool - Closed");
+			}
+		} else {
+			temp.append("Client Data Pool - Not Used");
+		}
+		logger.info(temp.toString());
+		temp.setLength(0);			
+
+		logger.info(".");
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/TheClient.java b/quickserver/src/main/org/quickserver/net/server/TheClient.java
new file mode 100644
index 0000000..9ad810e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/TheClient.java
@@ -0,0 +1,404 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server;
+
+import java.net.Socket;
+import java.nio.channels.SocketChannel;
+
+/**
+ * Encapsulates client socket and its configuration details. Used by
+ * {@link QuickServer} and {@link ClientHandler} classes.
+ * @author Akshathkumar Shetty
+ */
+public class TheClient {
+	private String timeoutMsg;
+	private String maxAuthTryMsg;
+	private int maxAuthTry;
+	private Socket socket;
+	private Authenticator authenticator;
+	private ClientAuthenticationHandler clientAuthenticationHandler; //v1.4.6
+	private ClientEventHandler eventHandler;//v1.4.6
+	private ClientExtendedEventHandler extendedEventHandler;//v1.4.6
+	private ClientCommandHandler commandHandler;
+	private ClientObjectHandler objectHandler; //v1.2
+	private ClientBinaryHandler binaryHandler; //v1.4
+	private QuickServer quickServer;
+	private ClientData clientData;
+	//--v1.3.2
+	private boolean trusted = false;
+	private boolean communicationLogging = true;
+	//--v1.4.5
+	private int socketTimeout;
+	private String maxConnectionMsg;
+	private ClientEvent event = ClientEvent.RUN_BLOCKING;
+	private SocketChannel socketChannel;
+	private ClientWriteHandler writeHandler;
+
+	/**
+     * Sets the QuickServer object associated with this Client
+     * @see #getServer
+     */
+	public void setServer(QuickServer server) {
+		this.quickServer=server;
+	}
+	/**
+     * Gets the QuickServer object associated with this Client
+     * @see #getServer
+     */
+	public QuickServer getServer() {
+		return quickServer;
+	}
+
+	/** Sets client socket associated. */
+	public void setSocket(Socket socket) {
+		this.socket = socket;
+	}
+	/** Returns client socket associated. */
+	public Socket getSocket() {
+		return socket;
+	}
+
+	/**
+     * Sets the Authenticator class that handles the 
+	 * authentication of a client.
+	 * @param authenticator object that implements {@link Authenticator}.
+	 * @see #getAuthenticator
+	 * @since 1.3
+	 * @deprecated As of 1.4.6 use {@link #setClientAuthenticationHandler}
+     */
+	public void setAuthenticator(Authenticator authenticator) {
+		this.authenticator=authenticator;
+	}
+	/**
+     * Returns the Authenticator object that handles the 
+	 * authentication of a client.
+	 * @see #setAuthenticator
+	 * @since 1.3
+	 * @deprecated As of 1.4.6 use {@link #getClientAuthenticationHandler}
+     */
+	public Authenticator getAuthenticator() {
+		return authenticator;
+	}
+
+	/**
+     * Sets the ClientAuthenticationHandler class that handles the 
+	 * authentication of a client.
+	 * @param clientAuthenticationHandler object that implements {@link ClientAuthenticationHandler}.
+	 * @see #getClientAuthenticationHandler
+	 * @since 1.4.6
+     */
+	public void setClientAuthenticationHandler(ClientAuthenticationHandler clientAuthenticationHandler) {
+		this.clientAuthenticationHandler = clientAuthenticationHandler;
+	}
+	/**
+     * Returns the ClientAuthenticationHandler object that handles the 
+	 * authentication of a client.
+	 * @see #setClientAuthenticationHandler
+	 * @since 1.4.6
+     */
+	public ClientAuthenticationHandler getClientAuthenticationHandler() {
+		return clientAuthenticationHandler;
+	}
+
+	/**
+     * Sets the ClientData object that carries client data.
+	 * @param data object of the class that 
+	 * extends {@link ClientData}.
+	 * @see #getClientData
+     */
+	public void setClientData(ClientData data) {
+		this.clientData=data;
+	}
+	/**
+     * Returns the ClientData object that carries client data.
+	 * @return object of the class that implements {@link ClientData}.
+	 * @see #setClientData
+     */
+	public ClientData getClientData() {
+		return clientData;
+	}
+
+	/** 
+	 * Sets maximum allowed login attempts.
+	 * @since 1.2
+	 */
+	public void setMaxAuthTry(int authTry) {
+		maxAuthTry = authTry;
+	}
+	/** 
+	 * Returns maximum allowed login attempts.
+	 * @since 1.2
+	 */
+	public int getMaxAuthTry() {
+		return maxAuthTry;
+	}
+
+	/** Sets message to be displayed when max login attempt reaches.*/
+	public void setMaxAuthTryMsg(String msg) {
+		maxAuthTryMsg = msg;
+	}
+	/**
+	 * Returns message to be displayed to the client when maximum 
+	 * allowed login attempts reaches.
+	 */
+	public String getMaxAuthTryMsg() {
+		return maxAuthTryMsg;
+	}
+
+	/** Sets timeout message. */
+	public void setTimeoutMsg(String msg) {
+		timeoutMsg = msg;
+	}
+	/** Returns timeout message. */
+	public String getTimeoutMsg() {
+		return timeoutMsg;
+	}
+
+	/**
+     * Sets the ClientEventHandler objects class that gets notified of 
+	 * client events.
+	 * @param handler object that 
+	 *  implements {@link ClientEventHandler}
+	 * @see #getClientEventHandler
+	 * @since 1.4.6
+     */
+	public void setClientEventHandler(ClientEventHandler handler) {
+		this.eventHandler = handler;
+	}
+	/**
+     * Returns the ClientEventHandler object that gets notified of 
+	 * client events.
+	 * @see #setClientEventHandler
+	 * @since 1.4.6
+     */
+	public ClientEventHandler getClientEventHandler() {
+		return eventHandler;
+	}
+
+	/**
+     * Sets the ClientExtendedEventHandler objects class that gets notified of 
+	 * extended client events.
+	 * @param handler object that 
+	 *  implements {@link ClientExtendedEventHandler}
+	 * @see #getClientExtendedEventHandler
+	 * @since 1.4.6
+     */
+	public void setClientExtendedEventHandler(ClientExtendedEventHandler handler) {
+		this.extendedEventHandler = handler;
+	}
+	/**
+     * Returns the ClientExtendedEventHandler object that gets notified of 
+	 * client events.
+	 * @see #setClientExtendedEventHandler
+	 * @since 1.4.6
+     */
+	public ClientExtendedEventHandler getClientExtendedEventHandler() {
+		return extendedEventHandler;
+	}
+
+	/**
+     * Sets the ClientCommandHandler objects that interacts with 
+	 * client sockets.
+	 * @param handler object that 
+	 *  implements {@link ClientCommandHandler}
+	 * @see #getClientCommandHandler
+     */
+	public void setClientCommandHandler(ClientCommandHandler handler) {
+		this.commandHandler = handler;
+	}
+	/**
+     * Returns the ClientCommandHandler object that interacts with 
+	 * client sockets.
+	 * @see #setClientCommandHandler
+     */
+	public ClientCommandHandler getClientCommandHandler() {
+		return commandHandler;
+	}
+
+	/**
+     * Sets the ClientObjectHandler object that interacts with 
+	 * client sockets.
+	 * @param handler object that 
+	 *  implements {@link ClientObjectHandler}
+	 * @see #getClientObjectHandler
+	 * @since 1.2
+     */
+	public void setClientObjectHandler(ClientObjectHandler handler) {
+		this.objectHandler = handler;
+	}
+	/**
+     * Returns the ClientObjectHandler object that interacts with 
+	 * client sockets.
+	 * @see #setClientObjectHandler
+	 * @since 1.2
+     */
+	public ClientObjectHandler getClientObjectHandler() {
+		return objectHandler;
+	}
+
+	/**
+	 * Returns flag to skip timeout setting and authentication of this client. 
+	 * @since 1.3.2
+	 */
+	public boolean getTrusted() {
+		return trusted;
+	}
+	/**
+	 * Sets flag to skip timeout setting and authentication of this client. 
+	 * @since 1.3.2
+	 */
+	public void setTrusted(boolean flag) {
+		trusted = flag;
+	}
+
+	/**
+	 * Sets the communication logging flag.
+	 * @see #getCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public void setCommunicationLogging(boolean communicationLogging) {
+		this.communicationLogging = communicationLogging;
+	}
+	/**
+	 * Returns the communication logging flag.
+	 * @see #setCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public boolean getCommunicationLogging() {
+		return communicationLogging;
+	}
+
+	/**
+     * Sets the ClientBinaryHandler object that interacts with 
+	 * client sockets.
+	 * @param handler object that 
+	 *  implements {@link ClientBinaryHandler}
+	 * @see #getClientBinaryHandler
+	 * @since 1.4
+     */
+	public void setClientBinaryHandler(ClientBinaryHandler handler) {
+		this.binaryHandler = handler;
+	}
+	/**
+     * Returns the ClientBinaryHandler object that interacts with 
+	 * client sockets.
+	 * @see #setClientBinaryHandler
+	 * @since 1.4
+     */
+	public ClientBinaryHandler getClientBinaryHandler() {
+		return binaryHandler;
+	}
+
+	/**
+     * Sets the client socket's timeout.
+	 * @param time client socket timeout in milliseconds.
+	 * @see #getTimeout
+	 * @since 1.4.5
+     */
+	public void setTimeout(int time) {
+		socketTimeout = time;
+	}	
+	/**
+     * Returns the Client socket timeout in milliseconds.
+	 * @see #setTimeout
+	 * @since 1.4.5
+     */
+	public int getTimeout() {
+		return socketTimeout;
+	}
+
+	/** 
+	 * Sets ClientEvent. 
+	 * @since 1.4.5
+	 */
+	public void setClientEvent(ClientEvent event) {
+		this.event = event;
+	}
+	/** 
+	 * Returns ClientEvent. 
+	 * @since 1.4.5
+	 */
+	public ClientEvent getClientEvent() {
+		return event;
+	}
+
+	/** 
+	 * Sets message to be displayed when maximum connection reaches.
+	 * @since 1.4.5
+	 */
+	public void setMaxConnectionMsg(String msg) {
+		maxConnectionMsg = msg;
+	}
+	/**
+	 * Returns message to be displayed to the client when maximum 
+	 * connection reaches.
+	 * @since 1.4.5
+	 */
+	public String getMaxConnectionMsg() {
+		return maxConnectionMsg;
+	}
+
+	/** 
+	 * Sets client socket channel associated, if any. 
+	 * @since 1.4.5
+	 */
+	public void setSocketChannel(SocketChannel socketChannel) {
+		this.socketChannel = socketChannel;
+	}
+	/** 
+	 * Returns client socket channel associated, if any. 
+	 * @since 1.4.5
+	 */
+	public SocketChannel getSocketChannel() {
+		return socketChannel;
+	}
+
+	/**
+     * Sets the ClientWriteHandler object that interacts with 
+	 * client sockets.
+	 * @param handler object that 
+	 *  implements {@link ClientWriteHandler}
+	 * @see #getClientWriteHandler
+	 * @since 1.4.5
+     */
+	public void setClientWriteHandler(ClientWriteHandler handler) {
+		this.writeHandler = handler;
+	}
+	/**
+     * Returns the ClientWriteHandler object that interacts with 
+	 * client sockets.
+	 * @see #setClientWriteHandler
+	 * @since 1.4.5
+     */
+	public ClientWriteHandler getClientWriteHandler() {
+		return writeHandler;
+	}
+
+	/** 
+	 * Returns client info. 
+	 * @since 1.4.5
+	 */
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("{TheClient ");
+		if(socket!=null) 
+			sb.append(socket);
+		else
+			sb.append("no socket");
+		sb.append(", Event: ").append(event);
+		sb.append('}');
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/gui/About.java b/quickserver/src/main/org/quickserver/net/server/gui/About.java
new file mode 100644
index 0000000..fd8beb7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/gui/About.java
@@ -0,0 +1,217 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import java.io.IOException;
+
+import org.quickserver.net.server.QuickServer;
+import org.quickserver.util.TextFile;
+import org.quickserver.swing.JFrameUtilities;
+
+/**
+ * About Panel for QuickServer - GUI Component
+ * @author Akshathkumar Shetty
+ */
+public class About extends JPanel /*JFrame*/{
+	private ClassLoader classLoader = getClass().getClassLoader();
+	public ImageIcon logo = new ImageIcon(
+		classLoader.getResource("icons/logo.gif"));
+	public ImageIcon logoAbout = new ImageIcon(
+		classLoader.getResource("icons/logo.png"));
+	public ImageIcon ball = new ImageIcon(
+		classLoader.getResource("icons/ball.gif"));
+
+	private JPanel centerPanel;
+	private JPanel topPanel;
+
+	private JLabel productName = new JLabel("<html><font "+
+		"style=\"font-size:35pt;color:#535353\" face=\"Verdana\">"+
+		"<b> QuickServer</b></font>",logoAbout,JLabel.CENTER);
+	private JTextArea readme = new JTextArea();
+	private JScrollPane jsp;
+
+	String html="<html><font face=\"verdana\" size=\"2\">";
+
+	private JLabel versionText = new JLabel(html+"Version",ball,JLabel.LEFT);
+	private JLabel version = new JLabel(html+": "+QuickServer.getVersion(), JLabel.LEFT);
+
+	private JLabel licenseText = new JLabel(html+"License",ball,JLabel.LEFT);
+	private JLabel license = new JLabel(html+": GNU Lesser General Public License", JLabel.LEFT);
+
+	//private JLabel authorText = new JLabel(html+"Author",ball,JLabel.LEFT);
+	//private JLabel author = new JLabel(html+": Akshathkumar Shetty", JLabel.LEFT);
+
+	private JLabel copyrightText = new JLabel(html+"Copyright &copy; QuickServer.org",ball,JLabel.LEFT);
+
+	private JLabel websiteText = new JLabel(html+"Website",ball,JLabel.LEFT);
+	private JLabel website = new JLabel(html+": http://www.quickserver.org", JLabel.LEFT);
+
+	private JLabel readmeText = new JLabel(html+"ReadMe",ball,JLabel.LEFT);
+
+	private GridBagConstraints gbc = new GridBagConstraints();
+
+	public About() {
+		//Container cp = getContentPane();
+		Container cp = this;
+
+		topPanel = new JPanel();
+		topPanel.setLayout(new GridBagLayout());
+		gbc.insets = new Insets( 2, 2, 2, 2 );
+		gbc.weighty = 0.0;
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridheight = 1;
+		gbc.gridwidth = 3;
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.fill = GridBagConstraints.NONE;
+		topPanel.add(productName, gbc);
+		/*
+		gbc.gridwidth = 1;
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(Box.createHorizontalGlue(), gbc);
+		*/
+		gbc.anchor = GridBagConstraints.WEST;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+
+		gbc.gridy++; //= 1;
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		topPanel.add(versionText, gbc);
+		gbc.gridx = 1;		
+		topPanel.add(version, gbc);
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(Box.createHorizontalGlue(), gbc);
+
+		gbc.gridy++; //= 2;
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		topPanel.add(licenseText, gbc);
+		gbc.gridx = 1;		
+		topPanel.add(license, gbc);
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;//1.0
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(new JLabel(), gbc);
+		
+		/*
+		gbc.gridy++; // = 3;
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		topPanel.add(authorText, gbc);
+		gbc.gridx = 1;		
+		topPanel.add(author, gbc);
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(Box.createHorizontalGlue(), gbc);
+		*/
+
+		gbc.gridy++; // = 4;
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		topPanel.add(websiteText, gbc);
+		gbc.gridx = 1;		
+		topPanel.add(website, gbc);
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(Box.createHorizontalGlue(), gbc);
+
+		gbc.gridy++; // = 5;
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		gbc.gridwidth = 2;
+		topPanel.add(copyrightText, gbc);
+		gbc.gridwidth = 1;
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(Box.createHorizontalGlue(), gbc);
+		
+		gbc.gridy++; // = 6;
+		gbc.gridx = 0;
+		gbc.weightx = 0.0;
+		gbc.gridwidth = 1;
+		topPanel.add(readmeText, gbc);
+		gbc.gridx = 1;		
+		topPanel.add(new JLabel(" "), gbc);
+		gbc.gridx = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		topPanel.add(Box.createHorizontalGlue(), gbc);
+		
+
+		centerPanel = new JPanel();
+		readme.setText("Loading... readme");
+		try	{
+			String cont = TextFile.read("/README.md",
+				(Object)About.this);
+			readme.setText(cont);
+		}
+		catch (IOException e){
+			System.err.println("Error reading README.md "+e);
+			readme.append("\r\nFailed : "+e.getMessage());
+		}
+		readme.setEditable(false);
+		readme.setLineWrap(true);
+		readme.setWrapStyleWord(true);
+		jsp = new JScrollPane(readme);
+		centerPanel.setLayout(new BorderLayout());
+		centerPanel.add(jsp);
+		centerPanel.setBorder(BorderFactory.createEmptyBorder(0,9,0,9));
+
+		cp.setLayout(new BorderLayout(0,10));
+		cp.add(topPanel,BorderLayout.NORTH);
+		cp.add(centerPanel,BorderLayout.CENTER);
+		setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+	}
+
+	/**
+	 * Displays the about box with in a JFrame.
+	 */
+	public static void showAbout(){
+		try {
+		  UIManager.setLookAndFeel(
+			UIManager.getSystemLookAndFeelClassName());
+		} catch(Exception e) {}
+
+		About about = new About();
+		JFrame frame = new JFrame("About QuickServer");
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.getContentPane().add(about);
+		frame.setSize(600, 500);
+		frame.setIconImage(about.logo.getImage());
+		JFrameUtilities.centerWindow(frame);
+		frame.setVisible(true);
+	}
+
+	public static void main(String args[]) {
+		java.awt.EventQueue.invokeLater(new Runnable() {
+            public void run() {
+				showAbout();
+			}
+		});
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/gui/package.html b/quickserver/src/main/org/quickserver/net/server/gui/package.html
new file mode 100644
index 0000000..878b2dd
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/gui/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+GUI components and classes.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/server/impl/BasicClientHandler.java b/quickserver/src/main/org/quickserver/net/server/impl/BasicClientHandler.java
new file mode 100644
index 0000000..0ab7f62
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/BasicClientHandler.java
@@ -0,0 +1,1443 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import java.io.*;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.InetAddress;
+import java.util.*;
+import java.util.logging.*;
+import java.security.*;
+import java.nio.channels.*;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.quickserver.net.*;
+import org.quickserver.util.*;
+import org.quickserver.net.server.*;
+import javax.net.ssl.*;
+
+/**
+ * Basic implementation of ClientHandler that handles clients for QuickServer.
+ * <p> This class is used by {@link QuickServer} to handle each new client 
+ * connected. This class is responsible to handle client sockets. It can operate 
+ * in both blocking mode and non-blocking mode (java nio).</p>
+ * <p>
+ * Contributions By: 
+ *   Martin Benns : BYTE Mode
+ * </p>
+ * @author Akshathkumar Shetty
+ * @author Martin Benns : Added BYTE mode
+ */
+public abstract class BasicClientHandler implements ClientHandler {
+	private static final Logger logger = Logger.getLogger(BasicClientHandler.class.getName());
+
+	protected static final String NEW_LINE = QuickServer.getNewLine();
+	protected static final byte NEW_LINE_BYTES[] = NEW_LINE.getBytes();
+
+	//Some variable are not initialised to any value because the 
+	//default java value was desired initial value. 
+	
+	/** Client socket */
+	protected Socket socket;
+	/** Client authorisation status */
+	protected volatile boolean authorised;
+	/** Count of client login attempts */
+	protected int counAuthTry;
+	/** max allowed login attempts */
+	protected int maxAuthTry = 5;
+	/** timeout message */
+	protected String timeoutMsg;
+	/** Message to be displayed when max login attempt reaches.*/
+	protected String maxAuthTryMsg;	
+
+	protected int socketTimeout;
+	protected volatile boolean connection; //false
+	protected boolean lost; //false
+	
+	protected QuickServer quickServer;
+	protected Authenticator authenticator; //v1.3
+	protected ClientAuthenticationHandler clientAuthenticationHandler; //v1.4.6
+	protected ClientEventHandler clientEventHandler; //v1.4.6
+	protected ClientExtendedEventHandler clientExtendedEventHandler; //v1.4.6
+	protected ClientCommandHandler clientCommandHandler;
+	protected ClientObjectHandler clientObjectHandler; //v1.2
+	protected ClientBinaryHandler clientBinaryHandler; //1.4
+	protected ClientData clientData;
+
+	protected InputStream in;
+	protected OutputStream out;
+	protected BufferedReader bufferedReader;
+	//if DataMode.OBJECT
+	protected ObjectOutputStream o_out; //v1.2
+	protected ObjectInputStream o_in; //v1.2
+	//added for BYTE mode and BINARY mode
+	protected BufferedInputStream b_in;
+	protected BufferedOutputStream b_out;
+
+	//logger for the application using this QuickServer
+	protected Logger appLogger; 
+	protected DataMode dataModeIN = null;
+	protected DataMode dataModeOUT = null;
+
+	protected boolean communicationLogging = true;
+	protected Date clientConnectedTime = null;	
+	protected Date lastCommunicationTime = null;
+	protected boolean secure = false;
+
+	//--v1.4.5
+	protected static final ThreadLocal threadEvent = new ThreadLocal();
+
+	protected String maxConnectionMsg;
+	protected final Set clientEvents = new HashSet();	
+	protected ConcurrentLinkedQueue unprocessedClientEvents = new ConcurrentLinkedQueue();
+	
+	protected volatile boolean closeOrLostNotified;
+	protected final Object lockObj = new Object();
+	protected volatile boolean willClean;
+	protected String charset;
+
+	private static Map idMap = new HashMap();
+	private int instanceCount;
+	private int id;
+	private String name;
+	private String hostAddress;
+	private int port;
+
+	protected SSLEngine sslEngine;
+	
+	protected int totalReadBytes;
+	protected int totalWrittenBytes;
+
+	static class InstanceId {
+		private int id = 0;
+		public int getNextId() {
+			return ++id;
+		}
+	};
+
+	private static int getNewId(int instanceCount) {
+		InstanceId instanceId = (InstanceId) idMap.get(""+instanceCount);
+		if(instanceId==null) {
+			instanceId = new InstanceId();
+			idMap.put(""+instanceCount, instanceId);
+		}
+		return instanceId.getNextId();
+	}
+
+	public BasicClientHandler(int instanceCount) {
+		this.instanceCount = instanceCount;
+		id = getNewId(instanceCount);
+
+		StringBuilder sb = new StringBuilder();
+		sb.append("<ClientHandler-Pool#");
+		sb.append(instanceCount);
+		sb.append("-ID:");
+		sb.append(id);
+		sb.append(">");
+		name = sb.toString();
+	}
+
+	public int getInstanceCount() {
+		return instanceCount;
+	}
+
+
+	public BasicClientHandler() {
+		this(-1);
+	}	
+	
+	public void clean() {
+		counAuthTry = 0;
+		authorised = false;
+		in = null;
+		out = null;
+		bufferedReader = null;
+		o_out = null; o_in = null;
+		b_in = null; b_out = null;
+
+		dataModeIN = null;
+		dataModeOUT = null;
+
+		lost = false;
+		clientData = null;
+		clientConnectedTime = null;
+		lastCommunicationTime = null;
+		communicationLogging = true;
+		socketTimeout = 0;
+		secure = false;
+		
+		authenticator = null;
+		clientAuthenticationHandler = null;//1.4.6
+		clientCommandHandler = null;
+		clientObjectHandler = null;
+		clientBinaryHandler = null;//1.4		
+		clientData = null;
+
+		maxConnectionMsg = null;
+		synchronized(clientEvents) {
+			clientEvents.clear();
+			unprocessedClientEvents.clear();
+		}		
+
+		closeOrLostNotified = false;
+
+		if(socket!=null) {
+			try {
+				socket.close();
+			} catch(Exception er) {
+				appLogger.log(Level.WARNING, "Error in closing socket: "+er, er);
+			}
+			socket = null;
+		}
+
+		hostAddress = null;
+		port = 0;
+
+		quickServer = null;
+		willClean  = false;
+		charset = null;
+
+		sslEngine = null;
+		
+		totalReadBytes = 0;
+		totalWrittenBytes = 0;
+	}
+
+	/**
+	 * Associates the ClientHanlder with the client encapsulated by 
+	 * <code>theClient</code>.
+	 * @param theClient object that encapsulates client socket 
+	 *  and its configuration details.
+	 */
+	public void handleClient(TheClient theClient) throws Exception {
+		setServer(theClient.getServer());
+
+		if(getServer().isRunningSecure()==true) {
+			setSecure(true);
+			sslEngine = getServer().getSSLContext().createSSLEngine();
+		}
+		setSocket(theClient.getSocket());
+
+		if(theClient.getTrusted()==false) {
+			setAuthenticator(theClient.getAuthenticator());
+			setClientAuthenticationHandler(theClient.getClientAuthenticationHandler());
+		}
+		setClientEventHandler(theClient.getClientEventHandler());
+		setClientExtendedEventHandler(theClient.getClientExtendedEventHandler());
+		setClientCommandHandler(theClient.getClientCommandHandler());
+		setClientObjectHandler(theClient.getClientObjectHandler());
+		setClientBinaryHandler(theClient.getClientBinaryHandler()); //v1.4
+		
+		setClientData(theClient.getClientData());
+		if(theClient.getTrusted()==false) {
+			socketTimeout = theClient.getTimeout();
+		}
+		timeoutMsg = theClient.getTimeoutMsg();
+		maxAuthTryMsg = theClient.getMaxAuthTryMsg();
+		maxAuthTry = theClient.getMaxAuthTry(); //v1.2
+		appLogger = quickServer.getAppLogger(); //v1.2
+		
+		setCommunicationLogging(theClient.getCommunicationLogging()); //v1.3.2
+
+		maxConnectionMsg = theClient.getMaxConnectionMsg();//1.4.5
+		addEvent(theClient.getClientEvent());//1.4.5
+	}
+
+	/**
+     * Returns the QuickServer object that created it.
+     * @see #setServer
+     */
+	public QuickServer getServer() {
+		return quickServer;
+	}
+	/**
+     * Sets the QuickServer object associated with this ClientHandler.
+     * @see #getServer
+     */
+	protected void setServer(QuickServer server) {
+		Assertion.affirm(server!=null, "QuickServer can't be null!");
+		quickServer = server;
+	}
+	
+	/**
+     * Sets the ClientData object associated with this ClientHandler
+	 * @see ClientData
+     * @see #getClientData
+     */
+	protected void setClientData(ClientData data) {
+		this.clientData = data;
+	}
+	/**
+     * Returns the ClientData object associated with this ClientHandler, 
+	 * if not set will return <code>null</code>
+	 * @see ClientData
+     * @see #setClientData
+     */
+	public ClientData getClientData() {
+		return clientData;
+	}
+
+	/**
+     * Sets the ClientAuthenticationHandler class that handles the 
+	 * authentication of a client.
+	 * @param clientAuthenticationHandler fully qualified name of the class that 
+	 * implements {@link ClientAuthenticationHandler}.
+	 * @since 1.4.6
+     */
+	protected void setClientAuthenticationHandler(ClientAuthenticationHandler clientAuthenticationHandler) {
+		this.clientAuthenticationHandler = clientAuthenticationHandler;
+	}
+
+	/**
+     * Sets the Authenticator class that handles the 
+	 * authentication of a client.
+	 * @param authenticator fully qualified name of the class that 
+	 * implements {@link Authenticator}.
+	 * @since 1.3
+     */
+	protected void setAuthenticator(Authenticator authenticator) {
+		this.authenticator = authenticator;
+	}
+
+	/**
+	 * Returns the {@link java.io.InputStream} associated with 
+	 * the Client being handled.
+	 * @see #setInputStream
+	 */
+	public InputStream getInputStream() {
+		return in;
+	}
+	/**
+	 * Sets the {@link java.io.InputStream} associated with 
+	 * the Client being handled.
+	 * @since 1.1
+	 * @see #getInputStream
+	 */
+	protected abstract void setInputStream(InputStream in) throws IOException;
+
+	/**
+	 * Returns the {@link java.io.OutputStream} associated with 
+	 * the Client being handled.
+	 * @see #setOutputStream
+	 */
+	public OutputStream getOutputStream() {
+		return out;
+	}
+	/**
+	 * Set the {@link java.io.OutputStream} associated with 
+	 * the Client being handled.
+	 * @since 1.1
+	 * @see #getOutputStream
+	 * @exception IOException if ObjectOutputStream could not be created.
+	 */
+	public void setOutputStream(OutputStream out) throws IOException {
+		this.out = out;
+		if(getDataMode(DataType.OUT) == DataMode.STRING || 
+				getDataMode(DataType.OUT) == DataMode.BYTE || 
+				getDataMode(DataType.OUT) == DataMode.BINARY) {
+			o_out = null;
+			b_out = new BufferedOutputStream(out);
+		} else if(getDataMode(DataType.OUT) == DataMode.OBJECT) {
+			b_out = null;
+			o_out = new ObjectOutputStream(out);
+			o_out.flush();
+		} else {
+			throw new IllegalStateException("Unknown DataMode " +getDataMode(DataType.OUT));
+		}
+	}
+	
+	/**
+	 * Returns the {@link java.io.BufferedReader} associated with 
+	 * the Client being handled. Note that this is only available under blocking mode. 
+	 * @see #getBufferedWriter
+	 */
+	public abstract BufferedReader getBufferedReader();
+
+	/**
+	 * Returns the {@link java.io.BufferedWriter} associated with 
+	 * the Client being handled.
+	 * @deprecated since 1.4.5 use getOutputStream()
+	 */
+	public BufferedWriter getBufferedWriter() {
+		try {
+			return new BufferedWriter(new OutputStreamWriter(b_out, charset));
+		} catch(UnsupportedEncodingException e) {
+			logger.log(Level.WARNING, "{0} was not supported : {1}", new Object[]{charset, e});
+			return new BufferedWriter(new OutputStreamWriter(b_out));
+		}		
+	}
+
+	/**
+	 * Returns the {@link java.io.ObjectOutputStream} associated with 
+	 * the Client being handled.
+	 * It will be <code>null</code> if no {@link ClientObjectHandler} 
+	 * was set in {@link QuickServer}.
+	 * @see #getObjectInputStream
+	 * @since 1.2
+	 */
+	public ObjectOutputStream getObjectOutputStream() {
+		return o_out;
+	}
+	/**
+	 * Returns the {@link java.io.ObjectInputStream} associated with 
+	 * the Client being handled.
+	 * It will be <code>null</code> if no {@link ClientObjectHandler} 
+	 * was set in {@link QuickServer}.
+	 * @see #getObjectOutputStream
+	 * @since 1.2
+	 */
+	public ObjectInputStream getObjectInputStream() {
+		return o_in;
+	}
+
+	/**
+     * Sets the ClientEventHandler class that gets notified of client events.
+	 * @since 1.4.6
+     */
+	protected void setClientEventHandler(ClientEventHandler handler) {
+		clientEventHandler=handler;
+	}
+
+	/**
+     * Sets the ClientExtendedEventHandler class that gets notified of extended client events.
+	 * @since 1.4.6
+     */
+	protected void setClientExtendedEventHandler(ClientExtendedEventHandler handler) {
+		clientExtendedEventHandler=handler;
+	}
+
+	/**
+     * Sets the ClientCommandHandler class that interacts with 
+	 * client sockets.
+     */
+	protected void setClientCommandHandler(ClientCommandHandler handler) {
+		clientCommandHandler=handler;
+	}
+
+	/**
+     * Sets the ClientObjectHandler class that interacts with 
+	 * client sockets.
+	 * @param handler fully qualified name of the class that 
+	 * implements {@link ClientObjectHandler}
+	 * @since 1.2
+     */
+	protected void setClientObjectHandler(ClientObjectHandler handler) {
+		clientObjectHandler = handler;
+	}
+
+	/** Closes client socket associated. */
+	public abstract void closeConnection();
+
+	/** Returns client socket associated. */
+	public Socket getSocket() {
+		return socket;
+	}
+
+	/** 
+	 * Returns client socket associated. 
+	 * @since 1.4.0
+	 * @see #updateInputOutputStreams
+	 */
+	public void setSocket(Socket socket) {
+		this.socket = socket;
+	}
+
+	/**
+	 * Checks if the client is still connected.
+	 * @exception SocketException if Socket is not open.
+	 * @deprecated since 1.4.5 Use {@link #isConnected}
+	 */
+	public boolean isConected() throws SocketException {
+		return isConnected();
+	}
+
+	/**
+	 * Checks if the client is still connected.
+	 * @exception SocketException if Socket is not open.
+	 * @since 1.4.5
+	 */
+	public boolean isConnected() throws SocketException {
+		if(isOpen()==false)
+			throw new SocketException("Connection is no more open!");
+		else
+			return true;
+	}
+
+	/**
+	 * Checks if the client is still connected and if socket is open. This is same as isConnected() 
+     * but does not throw SocketException.
+	 * @since 1.4.6
+	 */
+	public boolean isOpen() {
+		if(lost==true || socket==null || socket.isConnected()==false || socket.isClosed()==true)
+			return false;
+		else
+			return true;
+	}
+
+	/**
+	 * Checks if the client is closed.
+	 * @since 1.4.1
+	 */
+	public boolean isClosed() {
+		if(socket==null || socket.isClosed()==true)
+			return true;
+		else
+			return false;
+	}
+
+	/**
+	 * Send a String message to the connected client
+	 * it adds a new line{\r\n} to the end of the string.
+	 * If client is not connected it will just return.
+	 * @exception IOException 
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+	public void sendClientMsg(String msg) throws IOException {
+		isConnected();
+
+		if(dataModeOUT != DataMode.STRING)
+			throw new IllegalStateException("Can't send String :" + 
+				"DataType.OUT is not in DataMode.STRING");
+		if(getCommunicationLogging()) {
+			appLogger.log(Level.FINE, "Sending [{0}] : {1}", new Object[]{getHostAddress(), msg});
+		}
+		byte data[] = msg.getBytes(charset);
+
+		synchronized(this) {
+			b_out.write(data, 0, data.length);
+			b_out.write(NEW_LINE_BYTES, 0, NEW_LINE_BYTES.length);
+			totalWrittenBytes = totalWrittenBytes + data.length + NEW_LINE_BYTES.length;
+		}
+		b_out.flush();
+
+		updateLastCommunicationTime();
+	}
+
+	/**
+	 * Send a String message to the connected client as a string of bytes.
+	 * If client is not connected it will just return.
+	 * @since 1.3.1
+	 * @exception IOException
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+	public void sendClientBytes(String msg) throws IOException {
+		isConnected();
+
+		if (dataModeOUT != DataMode.BYTE)
+			throw new IllegalStateException("Can't send String :" + 
+				"DataType.OUT is not in DataMode.BYTE");
+		if(getCommunicationLogging()) {
+			appLogger.log(Level.FINE, "Sending [{0}] : {1}", new Object[]{getHostAddress(), msg});
+		}
+		byte data[] = msg.getBytes(charset);
+
+		synchronized(this) {
+			b_out.write(data,0,data.length);
+			totalWrittenBytes = totalWrittenBytes + data.length;
+		}
+		b_out.flush();
+
+		updateLastCommunicationTime();
+	}
+
+
+	/**
+	 * Send a Object message to the connected client. The message Object
+	 * passed must be serializable. If client is not connected it 
+	 * will just return.
+	 * @exception IOException if Socket IO Error or Socket was closed 
+	 * by the client.
+	 * @exception IllegalStateException if DataType.OUT is not in 
+	 *  DataMode.OBJECT
+	 * @see #setDataMode
+	 * @since 1.2
+	 */
+	public void sendClientObject(Object msg) throws IOException {
+		isConnected();
+
+		if(dataModeOUT != DataMode.OBJECT)
+			throw new IllegalStateException("Can't send Object : DataType.OUT is not in DataMode.OBJECT");
+		if(getCommunicationLogging()) {
+			appLogger.log(Level.FINE, "Sending [{0}] : {1}", new Object[]{getHostAddress(), msg.toString()});
+		}
+		synchronized(this) {
+			o_out.writeObject(msg);
+			
+			totalWrittenBytes = totalWrittenBytes + 1;
+		}
+		o_out.flush();
+
+		updateLastCommunicationTime();
+	}
+
+	/**
+	 * Send a String message to the logger associated with 
+	 * {@link QuickServer#getAppLogger} with Level.INFO as its level.
+	 */
+	public void sendSystemMsg(String msg) {
+		sendSystemMsg(msg, Level.INFO);
+	}
+
+	/**
+	 * Send a String message to the logger associated with 
+	 * {@link QuickServer#getAppLogger}.
+	 * @since 1.2
+	 */
+	public void sendSystemMsg(String msg, Level level) {
+		appLogger.log(level, msg);
+	}
+
+	/**
+	 * Send a String message to the system output stream.
+	 * @param newline indicates if new line required at the end.
+	 * @deprecated Use {@link #sendSystemMsg(java.lang.String)}, 
+	 *   since it uses Logging.
+	 */
+	public void sendSystemMsg(String msg, boolean newline) {
+		if(newline)
+			System.out.println(msg);
+		else
+			System.out.print(msg);
+	}
+
+	public abstract void run();
+
+	protected void prepareForRun() throws SocketException, IOException {
+		clientConnectedTime = new java.util.Date(); //v1.3.2
+		lastCommunicationTime = clientConnectedTime;//v1.3.3
+
+		setCharset(getServer().getBasicConfig().getAdvancedSettings().getCharset());//1.4.5	
+		hostAddress = getSocket().getInetAddress().getHostAddress();//1.4.5
+		port = getSocket().getPort();
+
+		if(logger.isLoggable(Level.FINEST)) {
+			StringBuilder sb = new StringBuilder();
+			sb.append(getName());
+			sb.append(" -> ");
+			sb.append(hostAddress);
+			sb.append(':');
+			sb.append(port);
+			logger.finest(sb.toString());
+		}
+
+		socket.setSoTimeout(socketTimeout);
+		connection = true;
+
+		dataModeIN = getServer().getDefaultDataMode(DataType.IN); 
+		dataModeOUT = getServer().getDefaultDataMode(DataType.OUT);
+
+		updateInputOutputStreams();
+	}
+
+	protected void processMaxConnection(ClientEvent currentEvent) throws IOException {
+		if(clientExtendedEventHandler!=null) {
+			if(clientExtendedEventHandler.handleMaxConnection(this)) {
+				removeEvent(getThreadEvent());
+				if(getThreadEvent()==ClientEvent.MAX_CON) {
+					currentEvent = ClientEvent.ACCEPT;
+				} else if(getThreadEvent()==ClientEvent.MAX_CON_BLOCKING) {
+					currentEvent = ClientEvent.RUN_BLOCKING;
+				} else {
+					throw new IllegalArgumentException("Unknown ClientEvent: "+getThreadEvent());
+				}
+				synchronized(clientEvents) {
+					clientEvents.add(currentEvent);
+				}
+				threadEvent.set(currentEvent);
+			}
+		} else if(maxConnectionMsg.length()!=0) {
+			out.write(maxConnectionMsg.getBytes(charset), 0, maxConnectionMsg.length());
+			out.write(NEW_LINE_BYTES, 0, NEW_LINE_BYTES.length);
+			out.flush();
+		}
+	}
+
+	protected AuthStatus processAuthorisation() throws SocketException, 
+			IOException, AppException {
+		logger.finest("INSIDE");
+		while(authorised==false && connection==true) {
+			isConnected();
+
+			counAuthTry++;
+
+			if(authorised == false) {
+				if(counAuthTry > maxAuthTry) {
+					processMaxAuthTry();
+				}
+			}	
+
+			try	{
+				if(clientAuthenticationHandler!=null) {
+					return clientAuthenticationHandler.askAuthentication(this);
+				} else if(authenticator!=null) {
+					authorised = authenticator.askAuthorisation(this);	
+				}
+			} catch(NullPointerException e) {
+				logger.severe("Authenticator implementation has not handled null properly."+
+					" Input from client should be checked for null!");
+				throw e;
+			} catch(SocketTimeoutException e) {
+				handleTimeout(e);
+			}
+
+			updateLastCommunicationTime();			
+		} //end of auth while
+		return AuthStatus.SUCCESS;
+	}
+
+	private void processMaxAuthTry() throws SocketException, IOException, AppException {
+		if(clientExtendedEventHandler!=null) {
+			clientExtendedEventHandler.handleMaxAuthTry(this);
+		} else {
+			String temp = maxAuthTryMsg;
+			if(dataModeOUT == DataMode.STRING)
+				temp = temp + NEW_LINE;
+			if(dataModeOUT != DataMode.OBJECT) {
+				out.write(temp.getBytes(charset));
+				out.flush();
+			}
+		}
+		appLogger.log(Level.WARNING, "Max Auth Try Reached - Client : {0}", getHostAddress());
+		if(true) throw new AppException(maxAuthTryMsg);
+	}
+
+
+	protected void notifyCloseOrLost() throws IOException {
+		synchronized(this) {
+			if(closeOrLostNotified==false) {
+				if(lost==true) {
+					clientEventHandler.lostConnection(this);				
+				} else {
+					clientEventHandler.closingConnection(this);
+				}
+				closeOrLostNotified = true;
+			}			
+		}
+	}
+
+	protected synchronized void returnClientData() {
+		if(clientData==null || getServer().getClientDataPool()==null)
+			return;
+		logger.finest("Returning ClientData to pool");
+		try	{
+			getServer().getClientDataPool().returnObject(clientData);
+			clientData = null;
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "IGNORED: Could not return ClientData to pool: "+e, e);
+		}
+	}	
+
+	protected void returnClientHandler() {
+		try	{
+			synchronized(lockObj) {
+				logger.log(Level.FINEST, "{0} returning {1}", new Object[]{Thread.currentThread().getName(), getName()});
+				getServer().getClientHandlerPool().returnObject(this);
+			}
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "IGNORED: Could not return ClientHandler to pool: "+e, e);
+		}
+	}
+
+	/**
+     * Returns the ClientHandler name
+	 * @since 1.4.6
+     */
+	public String getName() {
+		return name;
+	}
+
+	/**
+     * Returns the ClientHandler detailed information.
+	 * If ClientData is present and is ClientIdentifiable will return ClientInfo else
+	 * it will return Clients InetAddress and port information.
+     */
+	public String info() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("{");
+		sb.append(name);
+		sb.append(" - ");
+		String info = getClientIdentifiable(this);
+		if(info!=null) {
+			sb.append("[ClientInfo: ");
+			sb.append(info);
+			sb.append(']');
+		}
+
+		if(getSocket()==null || getSocket().isClosed()==true) {
+			sb.append("[non-connected;willClean:").append(getWillClean()).append("]");
+		} else if(info==null) {
+			sb.append('[');
+			sb.append(hostAddress);
+			sb.append(':');
+			sb.append(port);	
+			sb.append(']');
+		}
+		sb.append('}');
+		return sb.toString();
+	}
+
+	/**
+     * Returns the ClientHandler information.
+	 * If ClientData is present and is ClientIdentifiable will return ClientInfo else
+	 * it will return Clients InetAddress and port information.
+     */
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("{");
+		sb.append(name);
+		sb.append(" - ");
+		if(getSocket()==null || getSocket().isClosed()==true) {
+			sb.append("[non-connected;willClean:").append(getWillClean()).append("]");
+		} else if(hostAddress!=null) {
+			sb.append('[');
+			sb.append(hostAddress);
+			sb.append(':');
+			sb.append(port);
+			sb.append(']');
+		}
+		synchronized(clientEvents) {
+			if(clientEvents.isEmpty()==false) {
+				sb.append(' ');
+				sb.append(clientEvents);
+			}
+		}
+		sb.append('}');
+		return sb.toString();
+	}
+
+	protected static String getClientIdentifiable(ClientHandler foundClientHandler) {
+		if(foundClientHandler==null) return null;
+		ClientData foundClientData = null;
+		foundClientData = foundClientHandler.getClientData();
+		if(foundClientData==null)
+			return null;
+		else if(ClientIdentifiable.class.isInstance(foundClientData)==false)
+			return null;
+		else
+			return ((ClientIdentifiable)foundClientData).getClientInfo();
+	}
+
+	/**
+	 * Sets the {@link DataMode} for the ClientHandler
+	 *
+	 * Note: When mode is DataMode.OBJECT and type is DataType.IN
+	 * this call will block until the client ObjectOutputStream has
+	 * written and flushes the header.
+	 * @since 1.2
+	 * @exception IOException if mode could not be changed.
+	 * @param dataMode mode of data exchange - String or Object.
+	 * @param dataType type of data for which mode has to be set.
+	 */
+	public abstract void setDataMode(DataMode dataMode, DataType dataType) throws IOException;
+
+	protected void checkDataModeSet(DataMode dataMode, DataType dataType) {
+		if(dataMode==DataMode.STRING && dataType==DataType.IN && clientCommandHandler==null) {
+			throw new IllegalArgumentException("Can't set DataType.IN mode to STRING when ClientCommandHandler is not set!");
+		}
+
+		if(dataMode==DataMode.BYTE && dataType==DataType.IN && clientCommandHandler==null) {
+			throw new IllegalArgumentException("Can't set DataType.IN mode to BYTE when ClientCommandHandler is not set!");
+		}
+
+		if(dataMode==DataMode.OBJECT && dataType==DataType.IN && clientObjectHandler==null) {
+			throw new IllegalArgumentException("Can't set DataType.IN mode to OBJECT when ClientObjectHandler is not set!");
+		}
+
+		if(dataMode==DataMode.BINARY && dataType==DataType.IN && clientBinaryHandler==null) {
+			throw new IllegalArgumentException("Can't set DataType.IN mode to BINARY when ClientBinaryHandler is not set!");
+		}
+	}
+
+	/**
+	 * Returns the {@link DataMode} of the ClientHandler for the 
+	 * DataType.
+	 * @since 1.2
+	 */
+	public DataMode getDataMode(DataType dataType) {
+		if(dataType == DataType.IN)
+			return dataModeIN;
+		else if(dataType == DataType.OUT)
+			return dataModeOUT;
+		else
+			throw new IllegalArgumentException("Unknown DataType : " + 
+				dataType);
+	}
+
+	/**
+	 * Returns the {@link java.sql.Connection} object for the 
+	 * DatabaseConnection that is identified by id passed. If id passed
+	 * does not match with any connection loaded by this class it will
+	 * return <code>null</code>.
+	 * This just calls <code>getServer().getDBPoolUtil().getConnection(id)</code>
+	 * @since 1.3
+	 * @deprecated as of v1.4.5 use <code>getServer().getDBPoolUtil().getConnection(id)</code>
+	 */
+	public java.sql.Connection getConnection(String id) throws Exception {
+		if(getServer()==null)
+			throw new Exception("ClientHandler no longer is associated with any client! Try to use quickserver.getDBPoolUtil().getConnection("+id+")");
+		return getServer().getDBPoolUtil().getConnection(id);
+	}
+
+	/**
+	 * Returns the date/time when the client socket was assigned to this
+	 * ClientHanlder. If no client is currently connected it will return
+	 * <code>null</code>
+	 * @since 1.3.1
+	 */
+	public Date getClientConnectedTime() {
+		return clientConnectedTime;
+	}
+
+	/**
+	 * Read the byte input. This will block till some data is
+	 * received from the stream. 
+	 * @return The data as a String
+	 * @since 1.3.1
+	 */
+	protected abstract byte[] readInputStream() throws IOException;
+
+	protected static byte[] readInputStream(InputStream _in) throws IOException {
+		byte data[] = null;
+		if(_in==null)
+			throw new IOException("InputStream can't be null!");
+		
+		int s = _in.read();
+		if(s==-1) {
+			return null; //Connection lost
+		}
+		int alength = _in.available();
+		if(alength > 0) {
+			data = new byte[alength+1];	
+			data[0] = (byte) s;
+			int len = _in.read(data, 1, alength);
+			if(len < alength) {
+				data = copyOf(data, len+1);
+			}
+		} else {
+			data = new byte[1];
+			data[0] = (byte) s;
+		}
+		return data;
+	}
+	
+	private static byte[] copyOf(byte data[], int len) {
+		byte newdate[] = new byte[len];
+		System.arraycopy(data, 0, newdate, 0, len);
+		return newdate;
+	}
+
+	/**
+	 * Read the byte input. This will block till some data is
+	 * received from the stream. Allowed only when 
+	 * <code>DataType.IN</code> is in <code>DataMode.BYTE</code> mode.
+	 * @return The data as a String
+	 * @since 1.3.2
+	 */
+	public String readBytes() throws IOException {
+		if(dataModeIN != DataMode.BYTE)
+				throw new IllegalStateException("Can't read Byte: " + 
+					"DataType.IN is not in DataMode.BYTE");
+		byte data[] = readInputStream();
+		if(data!=null)
+			return new String(data, charset);
+		else
+			return null;
+	}
+
+	/**
+	 * Sets the communication logging flag.
+	 * @see #getCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public void setCommunicationLogging(boolean communicationLogging) {
+		this.communicationLogging = communicationLogging;
+	}
+	/**
+	 * Returns the communication logging flag.
+	 * @see #setCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public boolean getCommunicationLogging() {
+		return communicationLogging;
+	}
+
+	/**
+	 * Returns the date/time when the client socket last sent a data to this
+	 * ClientHanlder. If no client is currently connected it will return
+	 * <code>null</code>
+	 * @since 1.3.3
+	 */
+	public Date getLastCommunicationTime() {
+		return lastCommunicationTime;
+	}
+
+	/**
+	 * Updates the last communication time for this client
+	 * @since 1.3.3
+	 */
+	public void updateLastCommunicationTime() {
+		lastCommunicationTime = new Date();
+	}
+
+	/**
+	 * Force the closing of the client by closing the associated socket.
+	 * @since 1.3.3
+	 */
+	public synchronized void forceClose() throws IOException {
+		if(getBlockingMode()==false) {
+			if(getSelectionKey()!=null) getSelectionKey().cancel();
+			if(getSocketChannel()!=null) {
+				getSocketChannel().close();
+				setSocketChannel(null);
+			}
+		}
+		if(getSocket()!=null) {
+			getSocket().close();
+			setSocket(null);
+		}
+	}
+
+	/**
+	 * Returns flag indicating if the client is connected in secure mode 
+	 * (SSL or TLS).
+	 * @return secure flag
+	 * @since 1.4.0
+	 */ 
+	public boolean isSecure() {
+		return secure;
+	}
+
+	/**
+	 * Sets flag indicating if the client is connected in secure mode 
+	 * (SSL or TLS).
+ 	 * @param secure
+	 * @since 1.4.0
+	 */
+	public void setSecure(boolean secure) {
+		this.secure = secure;
+	}
+
+	/**
+	 * Updates the InputStream and OutputStream for the ClientHandler for the 
+	 * set Socket.
+	 * @since 1.4.0
+	 * @see #setSocket
+	 */
+	public abstract void updateInputOutputStreams() throws IOException;
+
+	/**
+	 * Makes current Client connection to secure protocol based on the 
+	 * secure configuration set to the server. This method will just call 
+	 * <code>makeSecure(false, false, true, null)</code>.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+	public void makeSecure() throws IOException, NoSuchAlgorithmException, 
+			KeyManagementException {
+		makeSecure(false, false, true, null);
+	}
+
+	/**
+	 * Makes current Client connection to secure protocol.
+	 * This method will just call <code>makeSecure(false, false, true, protocol)</code>.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+	public void makeSecure(String protocol) throws IOException, 
+			NoSuchAlgorithmException, KeyManagementException {
+		makeSecure(false, false, true, protocol);
+	}
+
+	/**
+	 * Makes current Client connection to secure protocol.
+	 * @param useClientMode falg if the socket should start its first handshake in "client" mode.
+	 * @param needClientAuth flag if the clients must authenticate themselves.
+	 * @param autoClose close the underlying socket when this socket is closed 
+	 * @param protocol the standard name of the requested protocol. If <code>null</code> will use the protocol set in secure configuration of the server.
+	 * @throws IOException
+	 * @throws NoSuchAlgorithmException
+	 * @throws KeyManagementException
+	 * @since 1.4.0
+	 */
+	public void makeSecure(boolean useClientMode, boolean needClientAuth, 
+			boolean autoClose, String protocol) throws IOException, 
+			NoSuchAlgorithmException, KeyManagementException {
+		if(isSecure()==true) {
+			throw new IllegalStateException("Client is already in secure mode!");
+		}
+		
+		appLogger.log(Level.FINE, "Making secure - Protocol: {0}, Client: [{1}]", 
+			new Object[]{protocol, getHostAddress()});
+
+		javax.net.ssl.SSLSocketFactory sslSf = getServer().getSSLSocketFactory(protocol);
+		String host = getServer().getBindAddr().getHostAddress();
+		if(host.equals("0.0.0.0")) host = InetAddress.getLocalHost().getHostAddress();
+		SSLSocket newSocket = (SSLSocket) sslSf.createSocket(
+			getSocket(), host, getServer().getPort(), autoClose);
+		newSocket.setNeedClientAuth(needClientAuth);
+		newSocket.setUseClientMode(useClientMode);
+		setSocket(newSocket);
+		setSecure(true);
+		updateInputOutputStreams();		
+	}
+
+	/**
+	 * Send a binary data to the connected client.
+	 * If client is not connected it will just return.
+	 * @since 1.4
+	 * @exception IOException
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+	public void sendClientBinary(byte data[]) throws IOException {
+		sendClientBinary(data, 0, data.length);
+	}
+
+	/**
+	 * Send a binary data to the connected client.
+	 * If client is not connected it will just return.
+	 * @since 1.4.5
+	 * @exception IOException
+	 *        if Socket IO Error or Socket was closed by the client.
+	 */
+	public void sendClientBinary(byte data[], int off, int len) throws IOException {
+		if(isConnected()) {
+			if(dataModeOUT != DataMode.BINARY)
+				throw new IllegalStateException("Can't send Binary :" + 
+					"DataType.OUT is not in DataMode.BINARY");
+			if(getCommunicationLogging()) {				
+				if(getServer().isRawCommunicationLogging()) {
+					if(getServer().getRawCommunicationMaxLength()>0 && len>getServer().getRawCommunicationMaxLength()) {
+						appLogger.log(Level.FINE, 
+							"Sending [{0}] : {1}; RAW: {2}{3}", new Object[]{
+								getHostAddress(), MyString.getMemInfo(len), new String(
+							data,0,getServer().getRawCommunicationMaxLength(),charset),"..."});
+					} else {
+						appLogger.log(Level.FINE, 
+							"Sending [{0}] : {1}; RAW: {2}", new Object[]{
+								getHostAddress(), MyString.getMemInfo(len), new String(data,charset)});
+					}
+				} else {
+					appLogger.log(Level.FINE, 
+						"Sending [{0}] : {1}", new Object[]{getHostAddress(), MyString.getMemInfo(len)});
+				}
+			}
+			synchronized(this) {
+				b_out.write(data, off, len); 
+				b_out.flush();
+				totalWrittenBytes = totalWrittenBytes + len;
+			}
+		} else {
+			logger.warning("Client not connected.");
+		}
+		updateLastCommunicationTime();
+	}
+
+	/**
+	 * Read the binary input. This will block till some data is
+	 * received from the stream. Allowed only when 
+	 * <code>DataType.IN</code> is in <code>DataMode.BINARY</code> mode.
+	 * @return The data as a String
+	 * @since 1.4
+	 */
+	public byte[] readBinary() throws IOException {
+		if(dataModeIN != DataMode.BINARY)
+				throw new IllegalStateException("Can't read Binary :" + 
+					"DataType.IN is not in DataMode.BINARY");
+		byte data[] = readInputStream();
+		return data;
+	}
+
+	/**
+     * Sets the ClientBinaryHandler class that interacts with 
+	 * client sockets.
+	 * @param handler fully qualified name of the class that 
+	 * implements {@link ClientBinaryHandler}
+	 * @since 1.4
+     */
+	protected void setClientBinaryHandler(ClientBinaryHandler handler) {
+		clientBinaryHandler=handler;
+	}
+
+	/** 
+	 * Returns client SelectionKey associated, if any. 
+	 * @since 1.4.5
+	 */
+	public Logger getAppLogger() {
+		return appLogger;
+	}
+
+	/**
+     * Sets the client socket's timeout.
+	 * @param time client socket timeout in milliseconds.
+	 * @see #getTimeout
+	 * @since 1.4.5
+     */
+	public void setTimeout(int time) {
+		socketTimeout = time;
+	}	
+	/**
+     * Returns the Client socket timeout in milliseconds.
+	 * @see #setTimeout
+	 * @since 1.4.5
+     */
+	public int getTimeout() {
+		return socketTimeout;
+	}
+
+	/** 
+	 * Checks if this client has the event. 
+	 * @since 1.4.5
+	 */
+	public boolean hasEvent(ClientEvent event) {
+		synchronized(clientEvents) {
+			return clientEvents.contains(event);
+		}
+	}
+
+	/** 
+	 * Adds the ClientEvent. 
+	 * @since 1.4.5
+	 */
+	public void addEvent(ClientEvent event) {
+		synchronized(clientEvents) {
+			unprocessedClientEvents.add(event);
+			clientEvents.add(event);
+		}
+	}
+
+	/** 
+	 * Removes the ClientEvent. 
+	 * @since 1.4.5
+	 */
+	public void removeEvent(ClientEvent event) {
+		if(event==null) return;
+
+		synchronized(clientEvents) {
+			clientEvents.remove(event);
+		}
+
+		ClientEvent _clientEvent = (ClientEvent)threadEvent.get();
+		if(_clientEvent!=null && _clientEvent==event) {
+			threadEvent.set(null);
+		}
+		
+	}
+
+	/** 
+	 * Returns threads current event for this client. 
+	 * @since 1.4.5
+	 */
+	protected ClientEvent getThreadEvent() {
+		return (ClientEvent)threadEvent.get();
+	}
+
+	/** 
+	 * Sets message to be displayed when maximum connection reaches.
+	 * @since 1.4.5
+	 */
+	public void setMaxConnectionMsg(String msg) {
+		maxConnectionMsg = msg;
+	}
+	/**
+	 * Returns message to be displayed to the client when maximum 
+	 * connection reaches.
+	 * @since 1.4.5
+	 */
+	public String getMaxConnectionMsg() {
+		return maxConnectionMsg;
+	}
+
+	/** 
+	 * Returns the current blocking mode of the server.
+	 * @since 1.4.9
+	 */
+	public abstract boolean getBlockingMode();
+
+	/** 
+	 * Sets client socket channel associated, if any. 
+	 * @since 1.4.5
+	 */
+	public abstract void setSocketChannel(SocketChannel socketChannel);
+	/** 
+	 * Returns client socket channel associated, if any. 
+	 * @since 1.4.5
+	 */
+	public abstract SocketChannel getSocketChannel();
+
+	/** 
+	 * Sets client SelectionKey associated, if any. 
+	 * @since 1.4.5
+	 */
+	public abstract void setSelectionKey(SelectionKey selectionKey);
+	/** 
+	 * Returns client SelectionKey associated, if any. 
+	 * @since 1.4.5
+	 */
+	public abstract SelectionKey getSelectionKey();
+
+	public boolean getWillClean() {
+		return willClean;
+	}
+
+	/**
+	 * Register OP_READ with the SelectionKey associated with the channel. If SelectionKey is
+	 * not set then it registers the channel with the Selector.
+	 * @since 1.4.5
+	 */
+	public abstract void registerForRead() throws IOException, 
+		ClosedChannelException;
+	
+	/**
+	 * Register OP_WRITE with the SelectionKey associated with the channel.
+	 * @since 1.4.5
+	 */
+	public abstract void registerForWrite() throws IOException, 
+		ClosedChannelException;
+
+	/**
+     * Sets the ClientWriteHandler class that interacts with 
+	 * client sockets.
+	 * @param handler fully qualified name of the class that 
+	 * implements {@link ClientWriteHandler}
+	 * @since 1.4.5
+     */
+	protected abstract void setClientWriteHandler(ClientWriteHandler handler);
+
+	/**
+     * Sets the Charset to be used for String decoding and encoding.
+	 * @param charset to be used for String decoding and encoding
+	 * @see #getCharset
+	 * @since 1.4.5
+     */
+	public void setCharset(String charset) {
+		if(charset==null || charset.trim().length()==0)
+			return;
+		this.charset = charset;
+	}
+	/**
+     * Returns Charset to be used for String decoding and encoding..
+     * @see #setCharset
+	 * @since 1.4.5
+     */
+	public String getCharset() {
+		return charset;
+	}
+
+	/**
+	 * Returns cached socket host ip address.
+	 * @since 1.4.5
+	 */
+	public String getHostAddress() {
+		return hostAddress;
+	}
+
+	protected void assertionSystemExit() {
+		logger.warning("[Assertions Was Enabled] Forcing program exit to help developer.");
+		org.quickserver.net.qsadmin.QSAdminShell.tryFullThreadDump();//it can help debug.
+		try {
+			Thread.sleep(100);	
+		} catch(InterruptedException e) {
+			logger.fine("Interrupted: "+e);
+		}		
+		System.exit(-1);
+	}
+
+	/**
+	 * Checks if the passed ClientEvent is the one next for 
+	 * processing if a thread is allowed through this object.
+	 * @since 1.4.6
+	 */
+	public boolean isClientEventNext(ClientEvent clientEvent) {
+		ClientEvent ce = null;
+		synchronized(clientEvents) {
+			ce = (ClientEvent) unprocessedClientEvents.peek();			
+		}
+		return clientEvent == ce;
+	}
+
+	/**
+	 *Returns the {@link java.io.BufferedInputStream} associated with 
+	 * the Client being handled. Can be null if not available at the time of method call. 
+	 * @see #getBufferedOutputStream
+	 * @since 1.4.6
+	 */
+	public BufferedInputStream getBufferedInputStream() {
+		return b_in;
+	}
+
+	/**
+	 * Returns the {@link java.io.BufferedOutputStream} associated with 
+	 * the Client being handled. Can be null if not available at the time of method call. 
+	 * @see #getBufferedInputStream
+	 * @since 1.4.6
+	 */
+	public BufferedOutputStream getBufferedOutputStream() {
+		return b_out;
+	}
+
+	protected void handleTimeout(SocketTimeoutException e) throws SocketException, IOException {
+		appLogger.log(Level.FINE, "Timeout - Client [{0}]", getHostAddress());
+		appLogger.log(Level.FINE, "LastCommunicationTime - {0}", getLastCommunicationTime());
+		appLogger.log(Level.FINEST, "SocketTimeoutException : {0}", e.getMessage());
+
+		String temp = null;
+		if(clientExtendedEventHandler!=null) {
+			clientExtendedEventHandler.handleTimeout(this);
+		} else {
+			temp = timeoutMsg;
+			if(dataModeOUT == DataMode.STRING)
+				temp = temp + NEW_LINE;
+			if(dataModeOUT != DataMode.OBJECT) {
+				out.write(temp.getBytes(charset));
+				out.flush();
+			}
+			if(true) throw new SocketException("Timeout");
+		}
+	}
+
+	/**
+	 * Returns SSLEngine if in secure mode.
+	 * @since 1.4.9
+	 */
+	public SSLEngine getSSLEngine() {
+		return sslEngine;
+	}
+	
+	
+	public int getTotalReadBytes() {
+		return totalReadBytes;
+	}
+	public int getTotalWrittenBytes() {
+		return totalWrittenBytes;
+	}
+	
+	public void resetTotalReadBytes() {
+		synchronized(this) {
+			totalReadBytes = 0;
+		}
+	}
+	public void resetTotalWrittenBytes() {
+		synchronized(this) {
+			totalWrittenBytes = 0;
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/BasicClientIdentifier.java b/quickserver/src/main/org/quickserver/net/server/impl/BasicClientIdentifier.java
new file mode 100644
index 0000000..d2ff1ba
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/BasicClientIdentifier.java
@@ -0,0 +1,136 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+import java.util.regex.*;
+import org.quickserver.net.server.*;
+import org.quickserver.util.pool.*;
+
+/**
+ * Client Identifier interface.
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public abstract class BasicClientIdentifier implements ClientIdentifier{
+	private static final Logger logger = Logger.getLogger(BasicClientIdentifier.class.getName());
+
+	protected QSObjectPool clientHandlerPool;
+	protected QuickServer quickserver;
+
+	public void setQuickServer(QuickServer quickserver) {
+		this.quickserver = quickserver;
+	}
+
+	public void setClientHandlerPool(QSObjectPool clientHandlerPool) {
+		this.clientHandlerPool = clientHandlerPool;
+	}
+
+	public Object getObjectToSynchronize() {
+		return clientHandlerPool.getObjectToSynchronize();
+	}
+
+	public Iterator findAllClient() {
+		return clientHandlerPool.getAllActiveObjects();
+	}
+
+	protected ClientIdentifiable getClientIdentifiable(
+			ClientHandler foundClientHandler) {
+		if(foundClientHandler==null) return null;
+		if(foundClientHandler.isOpen()==false) return null;
+		ClientData foundClientData = null;
+
+		foundClientData = foundClientHandler.getClientData();
+		if(foundClientData==null)
+			throw new IllegalStateException("No ClientData was set! Can't find a client with out it.");
+		if(ClientIdentifiable.class.isInstance(foundClientData)==false)
+			throw new IllegalStateException("ClientData does not implement ClientIdentifiable! Can't find a client with out it.");
+		return (ClientIdentifiable) foundClientData;
+	}
+
+	protected ClientHandler checkClientId(ClientHandler foundClientHandler, 
+			String id) {
+		ClientIdentifiable data = getClientIdentifiable(foundClientHandler);
+		if(data==null) return null;
+
+		String foundId = data.getClientId();
+		//logger.finest("Found id: "+foundId+", id: "+id);
+		if(foundId==null) {
+			//throw new NullPointerException("Id returned by ClientData was null!");
+			logger.finest("Id returned by ClientData was null! Client may not yet ready.. skipping");
+			return null;
+		}
+		if(foundId.equals(id)==false)
+			foundClientHandler = null;
+		return foundClientHandler;
+	}
+
+	protected ClientHandler checkClientId(ClientHandler foundClientHandler, 
+			Pattern pattern) {
+		ClientIdentifiable data = getClientIdentifiable(foundClientHandler);
+		if(data==null) return null;
+
+		String foundId = data.getClientId();
+		//logger.finest("Found id: "+foundId+", pattern: "+pattern);
+		if(foundId==null) {
+			//throw new NullPointerException("Id returned by ClientData was null!");
+			logger.finest("Id returned by ClientData was null! Client may not yet ready.. skipping");
+			return null;
+		}
+		Matcher m = pattern.matcher(foundId);
+		if(m.matches()==false)
+			foundClientHandler = null;
+		return foundClientHandler;
+	}
+
+	protected ClientHandler checkClientKey(ClientHandler foundClientHandler, 
+			String key) {
+		ClientIdentifiable data = getClientIdentifiable(foundClientHandler);
+		if(data==null) return null;
+
+		String foundKey = data.getClientKey();
+		//logger.finest("Found key: "+foundKey+", key: "+key);
+		if(foundKey==null) {
+			//throw new NullPointerException("Key returned by ClientData was null!");
+			logger.finest("Key returned by ClientData was null! Client may not yet ready.. skipping");
+			return null;
+		}
+		if(foundKey.equals(key)==false)
+			foundClientHandler = null;
+		return foundClientHandler;
+	}
+
+	protected ClientHandler checkClientKey(ClientHandler foundClientHandler, 
+			Pattern pattern) {
+		ClientIdentifiable data = getClientIdentifiable(foundClientHandler);
+		if(data==null) return null;
+
+		String foundKey = data.getClientKey();
+		//logger.finest("Found key: "+foundKey+", pattern: "+pattern);
+		if(foundKey==null) {
+			//throw new NullPointerException("Key returned by ClientData was null!");
+			logger.finest("Key returned by ClientData was null! Client may not yet ready.. skipping");
+			return null;
+		}
+		Matcher m = pattern.matcher(foundKey);
+		if(m.matches()==false)
+			foundClientHandler = null;
+		return foundClientHandler;
+	}
+
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/BasicPoolManager.java b/quickserver/src/main/org/quickserver/net/server/impl/BasicPoolManager.java
new file mode 100644
index 0000000..0ca7d69
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/BasicPoolManager.java
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import org.apache.commons.pool.*;
+import org.apache.commons.pool.impl.*;
+import org.quickserver.util.xmlreader.PoolConfig;
+import org.quickserver.net.server.PoolManager;
+import java.util.logging.*;
+
+/**
+ * BasicPoolManager class.
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public class BasicPoolManager implements PoolManager {
+	private static final Logger logger = Logger.getLogger(
+			BasicPoolManager.class.getName());
+	
+	protected GenericObjectPool.Config configurePool(PoolConfig opConfig) {
+		GenericObjectPool.Config  bconfig = new GenericObjectPool.Config();
+		bconfig.maxActive = opConfig.getMaxActive();
+		bconfig.maxIdle  =  opConfig.getMaxIdle();
+		bconfig.testOnReturn  = true;
+		
+		bconfig.timeBetweenEvictionRunsMillis = 1000*60*3;
+		bconfig.minEvictableIdleTimeMillis = 1000*60*2;
+		
+		return  bconfig;
+	}
+
+	public ObjectPool makeByteBufferPool(PoolableObjectFactory factory, 
+			PoolConfig opConfig) {
+		GenericObjectPool.Config  bconfig = configurePool(opConfig);
+		bconfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
+		return new GenericObjectPool(factory, bconfig);
+	}
+
+	public ObjectPool makeClientPool(PoolableObjectFactory factory, 
+			PoolConfig opConfig) {
+		GenericObjectPool.Config  bconfig = configurePool(opConfig);
+		bconfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
+		return new GenericObjectPool(factory, bconfig);
+	}
+
+	public ObjectPool makeClientHandlerPool(PoolableObjectFactory factory, 
+			PoolConfig opConfig) {
+		GenericObjectPool.Config  bconfig = configurePool(opConfig);	
+		bconfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
+		return new GenericObjectPool(factory, bconfig);
+	}
+
+	public ObjectPool makeClientDataPool(PoolableObjectFactory factory, 
+			PoolConfig opConfig) {
+		GenericObjectPool.Config  bconfig = configurePool(opConfig);
+		bconfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
+		return new GenericObjectPool(factory, bconfig);
+	}
+
+	public void initPool(ObjectPool objectPool, PoolConfig opConfig) {
+		int initSize = opConfig.getInitSize();
+		try {
+			while(objectPool.getNumIdle()<initSize)
+				objectPool.addObject();
+		} catch(Exception e) {
+			logger.log(Level.FINE, "Error: {0}", e);
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/BlockingClientHandler.java b/quickserver/src/main/org/quickserver/net/server/impl/BlockingClientHandler.java
new file mode 100644
index 0000000..2d2e2ad
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/BlockingClientHandler.java
@@ -0,0 +1,541 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import org.quickserver.net.server.*;
+import org.quickserver.net.*;
+import org.quickserver.util.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.logging.*;
+
+import java.nio.channels.*;
+
+public class BlockingClientHandler extends BasicClientHandler {
+	private static final Logger logger = Logger.getLogger(BlockingClientHandler.class.getName());
+
+	public BlockingClientHandler(int instanceCount) {
+		super(instanceCount);
+	}
+
+	public BlockingClientHandler() {
+		super();
+	}
+
+	public void clean() {
+		logger.log(Level.FINEST, "Starting clean - {0}", getName());
+		super.clean();
+		logger.log(Level.FINEST, "Finished clean - {0}", getName());
+	}
+
+	public void handleClient(TheClient theClient) throws Exception {
+		super.handleClient(theClient);
+	}
+
+	protected void setInputStream(InputStream in) throws IOException {
+		this.in = in;
+		if(getDataMode(DataType.IN) == DataMode.STRING) {
+			b_in = null;
+			o_in = null;
+			bufferedReader = new BufferedReader(new InputStreamReader(this.in, charset));
+		} else if(getDataMode(DataType.IN) == DataMode.OBJECT) {
+			b_in = null;
+			bufferedReader = null;
+			o_in = new ObjectInputStream(in);
+		} else if(getDataMode(DataType.IN) == DataMode.BYTE || 
+				getDataMode(DataType.IN) == DataMode.BINARY) {
+			o_in = null;
+			bufferedReader = null;
+			b_in = new BufferedInputStream(in);
+		} 
+	}
+
+	public BufferedReader getBufferedReader() {
+		return bufferedReader;
+	}
+
+	public synchronized void closeConnection() {
+		if(connection==false) return;
+		connection = false;
+		try	{
+			if(hasEvent(ClientEvent.MAX_CON_BLOCKING)==false) {				
+				notifyCloseOrLost();
+			}		
+			
+			if(out!=null) {
+				logger.finest("Closing output streams");
+				try {
+					out.flush();
+				} catch(IOException ioe) {
+					logger.log(Level.FINEST, "Flushing output streams failed: "+ioe, ioe);
+				}
+				
+				if(socket!=null && isSecure()==false) {
+					socket.shutdownOutput();
+				}
+				if(dataModeOUT == DataMode.OBJECT) {
+					o_out.close();
+				} else {
+					b_out.close();
+				}				
+				if(out!=null) out.close();
+			}
+
+			if(in!=null) {
+				logger.finest("Closing input streams");
+				//if(socket!=null) socket.shutdownInput();
+
+				if(dataModeIN == DataMode.STRING) {
+					if(bufferedReader!=null) bufferedReader.close();
+				} else if(dataModeIN == DataMode.OBJECT) {
+					o_in.close();
+				} else {
+					b_in.close();
+				}
+				if(in!=null) in.close();				
+			}			
+		} catch(IOException e) {
+			logger.log(Level.WARNING, "Error in closeConnection: {0}", e);
+			if(logger.isLoggable(Level.FINE)) {
+				logger.log(Level.FINE, "StackTrace: "+e, e);
+			}
+		} catch(NullPointerException npe) {
+			logger.log(Level.FINE, "NullPointerException: "+npe, npe);
+		} 
+	}
+
+	public void run() {
+		if(unprocessedClientEvents.isEmpty()) {
+			logger.finest("No unprocessed ClientEvents!");
+			return;
+		}
+
+		ClientEvent currentEvent = (ClientEvent) unprocessedClientEvents.poll();
+		if(currentEvent==null) {
+			threadEvent.set(null);
+			logger.finest("No unprocessed ClientEvents! pool was null");
+			return;
+		}
+		
+		if(logger.isLoggable(Level.FINEST)) {
+			StringBuilder sb = new StringBuilder();
+			sb.append("Running ").append(getName());
+			sb.append(" using ");
+			sb.append(Thread.currentThread().getName());
+			sb.append(" for ");
+
+			synchronized(clientEvents) {
+				if(clientEvents.size()>1) {
+					sb.append(currentEvent).append(", Current Events - ").append(clientEvents);
+				} else {
+					sb.append(currentEvent);
+				}
+			}
+			logger.finest(sb.toString());
+		}
+		
+		threadEvent.set(currentEvent);		
+
+		try {
+			if(socket==null)
+				throw new SocketException("Socket was null!");
+
+			prepareForRun();
+
+			if(getThreadEvent()==ClientEvent.MAX_CON_BLOCKING) {
+				processMaxConnection(currentEvent);
+			}
+
+			try {				
+				if(getThreadEvent()==ClientEvent.RUN_BLOCKING) {
+					clientEventHandler.gotConnected(this);
+				
+					if(authorised == false) {						
+						if(clientAuthenticationHandler==null && authenticator == null) {
+							authorised = true;
+						} else {
+							if(clientAuthenticationHandler!=null) {
+								AuthStatus authStatus = null;
+								do {
+									authStatus = processAuthorisation();
+								} while(authStatus==AuthStatus.FAILURE);
+
+								if(authStatus==AuthStatus.SUCCESS)
+									authorised = true;
+							} else {
+								processAuthorisation();
+							}		
+						}
+					}//end of authorised
+
+					processRead();
+				}	
+			} catch(SocketException e) {
+				appLogger.log(Level.FINEST, "SocketException - Client [{0}]: {1}", 
+					new Object[]{getHostAddress(), e});
+				lost = true;
+			} catch(AppException e) {
+				appLogger.log(Level.FINEST, "AppException {0}: {1}", new Object[]{
+					Thread.currentThread().getName(), e});		
+			} catch(javax.net.ssl.SSLException e) {
+				lost = true;
+				if(Assertion.isEnabled()) {
+					appLogger.log(Level.INFO, "SSLException - Client [{0}] {1}: {2}", 
+						new Object[]{getHostAddress(), Thread.currentThread().getName(), e});
+				} else {
+					appLogger.log(Level.WARNING, "SSLException - Client [{0}]: {1}", 
+						new Object[]{getHostAddress(), e});
+				}
+			} catch(ConnectionLostException e) {
+				lost = true;
+				if(e.getMessage()!=null)
+					appLogger.log(Level.FINEST, "Connection lost {0}: {1}", 
+						new Object[]{Thread.currentThread().getName(), e});
+				else
+					appLogger.log(Level.FINEST, "Connection lost {0}", Thread.currentThread().getName());
+			} catch(IOException e) {
+				lost = true;
+				appLogger.log(Level.FINE, "IOError {0}: {1}", new Object[]{Thread.currentThread().getName(), e});
+			} catch(AssertionError er) {
+				logger.log(Level.WARNING, "[AssertionError] {0} {1}", new Object[]{getName(), er});
+				if(logger.isLoggable(Level.FINEST)) {
+					logger.log(Level.FINEST, "StackTrace {0}: {1}", new Object[]{
+						Thread.currentThread().getName(), MyString.getStackTrace(er)});
+				}
+				assertionSystemExit();
+			} catch(RuntimeException re) {
+				logger.log(Level.WARNING, "[RuntimeException] {0}", MyString.getStackTrace(re));
+				if(Assertion.isEnabled()) {
+					assertionSystemExit();
+				}
+				lost = true;
+			} catch(Throwable er) {
+				logger.log(Level.WARNING, "[Error] {0}", er);
+				if(logger.isLoggable(Level.FINEST)) {
+					logger.log(Level.FINEST, "StackTrace {0}: {1}", 
+						new Object[]{Thread.currentThread().getName(), MyString.getStackTrace(er)});
+				}
+				if(Assertion.isEnabled()) {
+					assertionSystemExit();
+				}
+				lost = true;
+			} 
+			
+			if(getThreadEvent()!=ClientEvent.MAX_CON_BLOCKING) {
+				notifyCloseOrLost();
+			}
+			
+			if(connection) {
+				logger.log(Level.FINEST, "{0} calling closeConnection()", Thread.currentThread().getName());
+				closeConnection();
+			}
+		} catch(javax.net.ssl.SSLException se) {
+			logger.log(Level.WARNING, "SSLException {0}", se);
+		} catch(IOException ie) {
+			logger.log(Level.WARNING, "IOError - Closing Client: {0}", ie);
+		} catch(RuntimeException re) {
+			logger.log(Level.WARNING, "[RuntimeException] {0} {1}", new Object[]{
+				getName(), MyString.getStackTrace(re)});
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+		} catch(Exception e) {
+			logger.log(Level.WARNING, "Error on Event:{0} - Socket:{1} : {2}", new Object[]{getThreadEvent(), socket, e});
+			logger.log(Level.FINE, "StackTrace: {0}\n{1}", new Object[]{getName(), MyString.getStackTrace(e)});
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+		} catch(Throwable e) {
+			logger.log(Level.WARNING, "Error on - Event:{0} - Socket:{1} : {2}", new Object[]{getThreadEvent(), socket, e});
+			logger.log(Level.FINE, "StackTrace: {0}\n{1}", new Object[]{getName(), MyString.getStackTrace(e)});
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+		}
+
+		try	{				
+			if(socket!=null && socket.isClosed()==false) {
+				logger.finest("Closing Socket");
+				socket.close();
+			}	
+		} catch(Exception re) {
+			logger.log(Level.WARNING, "Error closing Socket/Channel: {0}", re);
+		}		
+
+		willClean = true;
+		returnClientData();
+
+		boolean returnClientHandler = false;
+		synchronized(lockObj) {
+			returnClientHandler = checkReturnClientHandler();
+		}
+
+		if(returnClientHandler) {
+			returnClientHandler(); //return to pool
+		}
+	}
+
+	protected boolean checkReturnClientHandler() {
+		return true;
+	}
+
+	private void processRead() throws IOException, ClassNotFoundException, AppException {
+		AuthStatus authStatus = null;
+
+		String rec = null;
+		Object recObject = null; //v1.2
+		byte[] recByte = null; //1.4
+		
+		while(connection) {
+			try {
+				if(dataModeIN == DataMode.STRING) {
+					rec = bufferedReader.readLine();
+					if(rec==null) {
+						lost = true;
+						break;
+					}
+					if(getCommunicationLogging() && authorised == true) {
+						appLogger.log(Level.FINE, "Got STRING [{0}] : {1}", 
+							new Object[]{getHostAddress(), rec});
+					}
+					totalReadBytes = totalReadBytes + rec.length() + 2;
+					
+					if(authorised == false)
+						authStatus = clientAuthenticationHandler.handleAuthentication(this, rec);
+					else
+						clientCommandHandler.handleCommand(this, rec);
+				} else if(dataModeIN == DataMode.OBJECT) {
+					recObject = o_in.readObject();
+					if(recObject==null) {
+						lost = true;
+						break;
+					}
+					
+					if(getCommunicationLogging() && authorised == true) {
+						appLogger.log(Level.FINE, "Got OBJECT [{0}] : {1}", 
+							new Object[]{getHostAddress(), recObject.toString()});
+					}
+					totalReadBytes = totalReadBytes + 1;
+					if(authorised == false)
+						authStatus = clientAuthenticationHandler.handleAuthentication(this, recObject);
+					else
+						clientObjectHandler.handleObject(this, recObject);
+				} else if(dataModeIN == DataMode.BYTE) {
+					rec = readBytes();
+					if(rec==null) {
+						lost = true;
+						break;
+					}
+					if(getCommunicationLogging() && authorised == true) {
+						appLogger.log(Level.FINE, "Got BYTE [{0}] : {1}", new Object[]{getHostAddress(), rec});
+					}
+					totalReadBytes = totalReadBytes + rec.length();
+					if(authorised == false)
+						authStatus = clientAuthenticationHandler.handleAuthentication(this, rec);
+					else
+						clientCommandHandler.handleCommand(this, rec);
+				} else if(dataModeIN == DataMode.BINARY) {
+					recByte = readBinary();
+					if(recByte==null) {
+						lost = true;
+						break;
+					}
+					if(getCommunicationLogging() && authorised == true) {
+						if(getServer().isRawCommunicationLogging()) {
+							if(getServer().getRawCommunicationMaxLength()>0 && 
+									recByte.length>getServer().getRawCommunicationMaxLength()) {
+								appLogger.log(Level.FINE, 
+									"Got BINARY [{0}] : {1}; RAW: {2}{3}", new Object[]{
+										getHostAddress(), MyString.getMemInfo(recByte.length), 
+										new String(recByte,0,getServer().getRawCommunicationMaxLength(),charset),"..."});
+							} else {
+								appLogger.log(Level.FINE, 
+									"Got BINARY [{0}] : {1}; RAW: {2}", new Object[]{
+										getHostAddress(), MyString.getMemInfo(recByte.length), 
+										new String(recByte,charset)});
+							}
+						} else {
+							appLogger.log(Level.FINE, 
+								"Got BINARY [{0}] : {1}", new Object[]{getHostAddress(), 
+									MyString.getMemInfo(recByte.length)});
+						}
+					} else if (getCommunicationLogging()) {
+						appLogger.log(Level.FINE, 
+							"Got BINARY [{0}] : {1}", new Object[]{getHostAddress(), 
+								MyString.getMemInfo(recByte.length)});
+					}
+					totalReadBytes = totalReadBytes + recByte.length;
+					if(authorised == false)
+						authStatus = clientAuthenticationHandler.handleAuthentication(this, recByte);
+					else
+						clientBinaryHandler.handleBinary(this, recByte);
+				} else {
+					throw new IllegalStateException("Incoming DataMode is not supported: "+dataModeIN);
+				}
+				updateLastCommunicationTime();
+
+				while(authStatus==AuthStatus.FAILURE)
+					authStatus = processAuthorisation();
+
+				if(authStatus==AuthStatus.SUCCESS)
+					authorised = true;
+			} catch(SocketTimeoutException e) {
+				handleTimeout(e);
+			}
+		}//end of while
+	}
+
+	protected void returnClientHandler() {
+		logger.finest(getName());
+		super.returnClientHandler();
+	}
+	
+	public void setDataMode(DataMode dataMode, DataType dataType) 
+			throws IOException {
+		if(getDataMode(dataType)==dataMode) return;
+
+		appLogger.log(Level.FINE, "Setting Type:{0}, Mode:{1}", new Object[]{dataType, dataMode});
+		super.checkDataModeSet(dataMode, dataType);
+
+		setDataModeBlocking(dataMode, dataType);
+	}
+
+	private void setDataModeBlocking(DataMode dataMode, DataType dataType) 
+			throws IOException {
+		logger.finest("ENTER");
+		if(dataMode == DataMode.STRING) {
+			if(dataType == DataType.OUT) {
+				if(dataModeOUT == DataMode.BYTE || dataModeOUT == DataMode.BINARY) {
+					dataModeOUT = dataMode;
+				} else if(dataModeOUT == DataMode.OBJECT) {
+					dataModeOUT = dataMode;
+					o_out.flush(); o_out = null;
+					b_out = new BufferedOutputStream(out);
+				} else {
+					Assertion.affirm(false, "Unknown DataType.OUT DataMode - "+dataModeOUT);
+				}
+				Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!");
+			} else if(dataType == DataType.IN) {
+				dataModeIN = dataMode;
+
+				if(o_in!=null) {
+					if(o_in.available()!=0)
+						logger.warning("Data looks to be present in ObjectInputStream");
+					o_in = null;
+				}
+				if(b_in!=null) {
+					if(b_in.available()!=0)
+						logger.warning("Data looks to be present in BufferedInputStream");
+					b_in = null;
+				}
+				bufferedReader = new BufferedReader(new InputStreamReader(in, charset));	
+				Assertion.affirm(bufferedReader!=null, "BufferedReader is still null!");
+			}
+		} else if(dataMode == DataMode.OBJECT) {
+			if(dataType == DataType.OUT) {
+				dataModeOUT = dataMode;
+				if(b_out!=null) {
+					b_out.flush();
+					b_out = null;
+				}
+				o_out = new ObjectOutputStream(out);
+				Assertion.affirm(o_out!=null, "ObjectOutputStream is still null!");
+			} else if(dataType == DataType.IN) {
+				dataModeIN = dataMode;
+				if(b_in!=null) {
+					if(b_in.available()!=0)
+						logger.warning("Data looks to be present in BufferedInputStream");
+					b_in = null;
+				}
+				bufferedReader = null;
+				o_in = new ObjectInputStream(in); //will block
+				Assertion.affirm(o_in!=null, "ObjectInputStream is still null!");
+			}
+		} else if(dataMode == DataMode.BYTE || dataMode == DataMode.BINARY) {
+			if(dataType == DataType.OUT) {
+				if(dataModeOUT == DataMode.STRING || dataModeOUT == DataMode.BYTE || 
+						dataModeOUT == DataMode.BINARY) {
+					dataModeOUT = dataMode;
+				} else if(dataModeOUT == DataMode.OBJECT) {
+					dataModeOUT = dataMode;
+					if(o_out!=null) {
+						o_out.flush();
+						o_out = null;
+					}					
+					b_out = new BufferedOutputStream(out);
+				} else {
+					Assertion.affirm(false, "Unknown DataType.OUT - DataMode: "+dataModeOUT);
+				}
+				Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!");
+			} else if(dataType == DataType.IN) {
+				dataModeIN = dataMode;
+				if(o_in!=null) {
+					if(o_in.available()!=0)
+						logger.warning("Data looks to be present in ObjectInputStream");
+					o_in = null;
+				}
+				bufferedReader = null;
+				b_in = new BufferedInputStream(in);
+				Assertion.affirm(b_in!=null, "BufferedInputStream is still null!");
+			} else {
+				throw new IllegalArgumentException("Unknown DataType : "+dataType);
+			}
+		} else {
+			throw new IllegalArgumentException("Unknown DataMode : "+dataMode);
+		}
+	}
+
+	protected byte[] readInputStream() throws IOException {
+		return readInputStream(b_in);
+	}
+
+	public void updateInputOutputStreams() throws IOException {
+		setInputStream(getSocket().getInputStream());
+		setOutputStream(getSocket().getOutputStream());
+	}
+
+	public boolean getBlockingMode() {
+		return true;
+	}
+
+	public void setSocketChannel(SocketChannel socketChannel) {
+		if(true) throw new IllegalStateException("Can't set in blocking mode!");
+	}
+	public SocketChannel getSocketChannel() {
+		if(true) throw new IllegalStateException("Can't get in blocking mode!");
+		return null;
+	}
+
+	public void setSelectionKey(SelectionKey selectionKey) {
+		if(true) throw new IllegalStateException("Can't set in blocking mode!");
+	}
+	public SelectionKey getSelectionKey() {
+		if(true) throw new IllegalStateException("Can't get in blocking mode!");
+		return null;
+	}
+
+	public void registerForRead() throws IOException, ClosedChannelException {
+		if(true) throw new IllegalStateException("Can't register in blocking mode!");
+	}
+
+	public void registerForWrite() throws IOException, ClosedChannelException {
+		if(true) throw new IllegalStateException("Can't register in blocking mode!");
+	}
+
+	protected void setClientWriteHandler(ClientWriteHandler handler) {
+		if(true) throw new IllegalStateException("Can't register in blocking mode!");
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/DefaultClientEventHandler.java b/quickserver/src/main/org/quickserver/net/server/impl/DefaultClientEventHandler.java
new file mode 100644
index 0000000..d158399
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/DefaultClientEventHandler.java
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import org.quickserver.net.server.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.io.*;
+import java.util.logging.*;
+
+/**
+ * Default ClientEventHandler implementation. 
+ * <p>This implementation will try to provide a default ClientEventHandler
+ * implementation. If a ClientCommandHandler is known to have been set then 
+ * this implementation will look for ClientEventHandler methods in that 
+ * implementation and pass the corresponding call to that method.
+ * This was done to provide backward compatibility with v1.4.5 and prior version
+ * of ClientCommandHandler.</p>
+ * @author Akshathkumar Shetty
+ * @since 1.4.6
+ */
+public class DefaultClientEventHandler implements ClientEventHandler {
+	private static Logger logger = Logger.getLogger(DefaultClientEventHandler.class.getName());
+
+	private ClientCommandHandler clientCommandHandler = null;
+	private Method gotConnectedMethod = null;
+	private Method lostConnectionMethod = null;
+	private Method closingConnectionMethod = null;
+
+	/**
+	 * Sets ClientCommandHandler that should be examined to
+	 * find any ClientEventHandler methods
+	 */
+	public void setClientCommandHandler(ClientCommandHandler handler) {
+		this.clientCommandHandler = handler;
+		if(clientCommandHandler!=null)
+			loadMethods();
+	}
+
+	public void gotConnected(ClientHandler handler)
+			throws SocketTimeoutException, IOException {
+		if(gotConnectedMethod==null)
+			handler.sendSystemMsg("Connection opened: "+handler.getHostAddress());
+		else
+			invoke(gotConnectedMethod, handler);
+	}
+
+	public void lostConnection(ClientHandler handler) 
+			throws IOException {
+		if(lostConnectionMethod==null)
+			handler.sendSystemMsg("Connection lost: "+handler.getHostAddress());
+		else
+			invoke(lostConnectionMethod, handler);
+	}
+
+	public void closingConnection(ClientHandler handler) 
+			throws IOException {
+		if(closingConnectionMethod==null)
+			handler.sendSystemMsg("Connection closing: "+handler.getHostAddress());
+		else
+			invoke(closingConnectionMethod, handler);
+	}
+
+	private void loadMethods() {
+		Class cls = clientCommandHandler.getClass();
+		try {
+			gotConnectedMethod = cls.getMethod("gotConnected", 
+				new Class[] {ClientHandler.class});
+		} catch(NoSuchMethodException ex) {
+			logger.fine("Error finding gotConnected : "+ex);
+		}
+		try {
+			lostConnectionMethod = cls.getMethod("lostConnection", 
+				new Class[] {ClientHandler.class});
+		} catch(NoSuchMethodException ex) {
+			logger.fine("Error finding lostConnection : "+ex);
+		}
+		try {
+			closingConnectionMethod = cls.getMethod("closingConnection", 
+				new Class[] {ClientHandler.class});
+		} catch(NoSuchMethodException ex) {
+			logger.fine("Error finding lostConnection : "+ex);
+		}
+	}
+
+	private void invoke(Method method, ClientHandler handler) throws SocketTimeoutException, IOException {
+		try {
+			method.invoke(clientCommandHandler, new Object[] {handler});
+		} catch(IllegalAccessException e) {
+			logger.warning("Error invoking "+method+" : "+e);
+		} catch(InvocationTargetException e) {
+			Exception cause = (Exception) e.getCause();
+			if(cause!=null) {
+				if(SocketTimeoutException.class.isInstance(cause))
+					throw (SocketTimeoutException) cause;
+				else if(IOException.class.isInstance(cause))
+					throw (IOException) cause;
+			}
+			logger.warning("Error invoking "+method+" : "+e+"\n Cause: "+cause);
+			IOException ioe = new IOException();
+			ioe.initCause(cause);
+			throw ioe;
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/NonBlockingClientHandler.java b/quickserver/src/main/org/quickserver/net/server/impl/NonBlockingClientHandler.java
new file mode 100644
index 0000000..1a8b3e6
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/NonBlockingClientHandler.java
@@ -0,0 +1,1297 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import org.quickserver.net.server.*;
+import org.quickserver.net.*;
+import org.quickserver.util.*;
+import org.quickserver.util.io.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+
+import java.nio.*;
+import java.nio.channels.*;
+import javax.net.ssl.*;
+
+public class NonBlockingClientHandler extends BasicClientHandler {
+	private static final Logger logger = Logger.getLogger(NonBlockingClientHandler.class.getName());
+
+	protected ClientWriteHandler clientWriteHandler; //v1.4.5	
+	private SocketChannel socketChannel;
+
+	protected ArrayList readByteBuffer = new ArrayList();
+	protected ArrayList writeByteBuffer = new ArrayList();
+
+	protected SelectionKey selectionKey;
+
+	protected volatile int threadAccessCount = 0;
+	protected volatile boolean willReturn;
+	protected volatile boolean waitingForFinalWrite;
+
+	private static int maxThreadAccessCount = 5; //one for each event ACCEPT, WRITE, READ
+	private static boolean wakeupSelectorAfterRegisterWrite = true;
+	private static boolean wakeupSelectorAfterRegisterRead = true;
+
+	//nio ssl
+	//private final SSLSession session;
+	private boolean initialHandshakeStatus = false;
+	private SSLEngineResult.HandshakeStatus handshakeStatus;
+	private SSLEngineResult.Status status = null;
+	private ByteBuffer dummyByteBuffer = ByteBuffer.allocate(0);
+	private ByteBuffer peerNetData = null;
+	private boolean sslShutdown = false;
+
+	/**
+	 * Sets the flag to wakeup Selector After RegisterForWrite is called.
+	 * @since 1.4.7
+	 */
+	public static void setWakeupSelectorAfterRegisterWrite(boolean flag) {
+		wakeupSelectorAfterRegisterWrite = flag;
+	}
+	/**
+	 * Returns wakeupSelectorAfterRegisterWrite the flag that controls if wakeup is called on Selector
+	 * after RegisterForWrite is called. 
+	 * @since 1.4.7
+	 */
+	public static boolean getWakeupSelectorAfterRegisterWrite() {
+		return wakeupSelectorAfterRegisterWrite;
+	}
+	
+	/**
+	 * Sets the flag to wakeup Selector After RegisterForRead is called.
+	 * @since 1.4.7
+	 */
+	public static void setWakeupSelectorAfterRegisterRead(boolean flag) {
+		wakeupSelectorAfterRegisterRead = flag;
+	}
+	/**
+	 * Returns wakeupSelectorAfterRegisterRead the flag that controls if wakeup is called on Selector
+	 * after RegisterForRead is called. 
+	 * @since 1.4.7
+	 */
+	public static boolean getWakeupSelectorAfterRegisterRead() {
+		return wakeupSelectorAfterRegisterRead;
+	}
+
+	/**
+	 * Sets the maximum count of thread allowed to run objects of this class at a time.
+	 * @since 1.4.7
+	 */
+	public static void setMaxThreadAccessCount(int count) {
+		if(count<3 && count!=-1) throw new IllegalArgumentException("Value should be >=3 or -1");
+		maxThreadAccessCount = count;
+	}
+	/**
+	 * Returns the maximum count of thread allowed to run objects of this class at a time.
+	 * @since 1.4.7
+	 */
+	public static int getMaxThreadAccessCount() {
+		return maxThreadAccessCount;
+	}
+
+	//v1.4.7
+	private ByteBufferOutputStream byteBufferOutputStream;
+
+	public NonBlockingClientHandler(int instanceCount) {
+		super(instanceCount);
+	}
+
+	public NonBlockingClientHandler() {
+		super();
+	}
+
+	public void clean() {
+		logger.log(Level.FINEST, "Starting clean - {0}", getName());
+		if(threadAccessCount!=0) {
+			logger.log(Level.WARNING, "Thread Access Count was not 0!: {0}", threadAccessCount);
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+			threadAccessCount = 0;
+		}
+				
+		while(readByteBuffer.isEmpty()==false) {
+			try {
+				getServer().getByteBufferPool().returnObject(
+					readByteBuffer.remove(0));	
+			} catch(Exception er) {
+				logger.log(Level.WARNING, "Error in returning read ByteBuffer to pool: "+er, er);
+				break;
+			}
+		}
+
+		while(writeByteBuffer.isEmpty()==false) {
+			try {
+				getServer().getByteBufferPool().returnObject(
+					writeByteBuffer.remove(0));	
+			} catch(Exception er) {
+				appLogger.log(Level.WARNING, "Error in returning write ByteBuffer to pool: "+er, er);
+				break;
+			}
+		}
+
+		if(peerNetData!=null) {
+			try {
+				getServer().getByteBufferPool().returnObject(peerNetData);
+			} catch(Exception er) {
+				appLogger.log(Level.WARNING, "Error in returning peerNetData to pool: "+er, er);
+			}
+		}
+
+		if(selectionKey!=null) {
+			selectionKey.cancel();
+			selectionKey.selector().wakeup();
+			selectionKey = null;
+		}
+		willReturn = false;	
+		waitingForFinalWrite = false;
+		socketChannel = null;
+		if(byteBufferOutputStream!=null) {
+			byteBufferOutputStream.close();
+		}
+
+		super.clean();
+
+		clientWriteHandler = null;//1.4.5		
+		byteBufferOutputStream = null;		
+
+		sslShutdown = false;
+		logger.log(Level.FINEST, "Finished clean - {0}", getName());
+	}
+
+	public void handleClient(TheClient theClient) throws Exception {
+		super.handleClient(theClient);
+		setClientWriteHandler(theClient.getClientWriteHandler()); //v1.4.5
+		setSocketChannel(theClient.getSocketChannel());//1.4.5
+	}
+
+	protected void setInputStream(InputStream in) throws IOException {
+		this.in = in;
+		if(getDataMode(DataType.IN) == DataMode.STRING) {
+			b_in = null;
+			o_in = null;
+			bufferedReader = null;
+		} else if(getDataMode(DataType.IN) == DataMode.OBJECT) {
+			b_in = null;
+			bufferedReader = null;
+			o_in = new ObjectInputStream(in);
+		} else if(getDataMode(DataType.IN) == DataMode.BYTE || 
+				getDataMode(DataType.IN) == DataMode.BINARY) {
+			o_in = null;
+			bufferedReader = null;
+			b_in = null;
+		} 
+	}
+
+	public BufferedReader getBufferedReader() {
+		throw new IllegalStateException("Access to BufferedReader in not allowed in Non-Blocking mode!");
+	}
+
+	public void closeConnection() {
+		logger.finest("inside");
+		synchronized(this) {
+			if(connection==false) return;
+			if(waitingForFinalWrite) return;
+			if(getSelectionKey()!=null && getSelectionKey().isValid() && lost == false) {
+				waitingForFinalWrite = true;
+			} else {
+				connection = false;
+			}
+		}
+
+		try	{			
+			if(getSocketChannel()!=null && socket!=null) {
+				if(waitingForFinalWrite) {
+					try {					
+						waitTillFullyWritten();	
+					} catch(Exception error) {
+						logger.warning("Error in waitingForFinalWrite : "+error);
+						if(logger.isLoggable(Level.FINE)) {
+							logger.fine("StackTrace:\n"+MyString.getStackTrace(error));
+						}
+					}
+				}//end of waitingForFinalWrite
+
+				if(isSecure()==true) {
+					sslShutdown = true;
+					if(lost == false && sslEngine.isOutboundDone()==false) {
+						logger.finest("SSL isOutboundDone is false");
+						if(byteBufferOutputStream.doShutdown()==false) {
+							return;
+						}
+					} else if(sslEngine.isOutboundDone()) {
+						logger.finest("SSL Outbound is done.");
+					}
+				} 
+			
+				doPostCloseActivity();				
+			}//if socket			
+		} catch(IOException e) {
+			logger.warning("Error in closeConnection : "+e);
+			if(logger.isLoggable(Level.FINE)) {
+				logger.fine("StackTrace:\n"+MyString.getStackTrace(e));
+			}
+		} catch(NullPointerException npe) {
+			logger.fine("NullPointerException: "+npe);
+			if(logger.isLoggable(Level.FINE)) {
+				logger.fine("StackTrace:\n"+MyString.getStackTrace(npe));
+			}
+		} 
+	}
+
+	private void doPostCloseActivity() throws IOException {
+		connection = false;
+		byteBufferOutputStream.forceNotify();
+		getSelectionKey().cancel();
+
+		if(getServer()!=null) {
+			getServer().getSelector().wakeup();
+		}		
+
+		synchronized(this) {
+			if(hasEvent(ClientEvent.MAX_CON)==false) {
+				notifyCloseOrLost();
+			}
+			if(getSocketChannel().isOpen()) {
+				logger.finest("Closing SocketChannel");
+				getSocketChannel().close();
+			}
+		}
+	}
+
+	public boolean closeIfSSLOutboundDone() {
+		if(isSecure()==false) throw new IllegalStateException("Client is not in secure mode!");
+
+		if(sslEngine.isOutboundDone()) {
+			logger.finest("SSL Outbound is done.");
+			try {
+				if(getSocketChannel().isOpen()) {
+					logger.finest("Closing SocketChannel");
+					getSocketChannel().close();
+				}
+			} catch(IOException e) {
+				logger.fine("IGNORE: Error in Closing SocketChannel: "+e);
+			}
+			return true;
+		} else {
+			logger.finest("SSL Outbound is not done.");
+			return false;
+		}		
+	}
+
+	
+	/**
+	 * waitTillFullyWritten
+	 * @since 1.4.7
+	 */
+	public void waitTillFullyWritten() {
+		Object waitLock = new Object();
+		if(byteBufferOutputStream.isDataAvailableForWrite(waitLock)) {
+			if(ByteBufferOutputStream.isLoggable(Level.FINEST)) {
+				logger.finest("Waiting "+getName());
+			}
+			try {
+				synchronized(waitLock) {
+					waitLock.wait(1000*60*2);//2 min max
+				}
+			} catch(InterruptedException ie) {
+				logger.warning("Error: "+ie);
+			}
+			if(ByteBufferOutputStream.isLoggable(Level.FINEST)) {
+				logger.finest("Done. "+getName());
+			}
+		}
+	}
+
+	public void run() {
+		if(unprocessedClientEvents.isEmpty()) {
+			logger.finest("No unprocessed ClientEvents!");
+			return;
+		}
+
+		synchronized(this) {
+			if(willReturn) {
+				return;
+			} else {
+				threadAccessCount++;
+			}
+		}
+
+		ClientEvent currentEvent = (ClientEvent) unprocessedClientEvents.poll();
+		if(currentEvent==null) {
+			threadEvent.set(null);
+			logger.finest("No unprocessed ClientEvents! pool was null");
+			return;
+		}
+
+		if(logger.isLoggable(Level.FINEST)) {
+			StringBuilder sb = new StringBuilder();
+			sb.append("Running ").append(getName());
+			sb.append(" using ");
+			sb.append(Thread.currentThread().getName());
+			sb.append(" for ");
+
+			synchronized(clientEvents) {
+				if(clientEvents.size()>1) {
+					sb.append(currentEvent+", Current Events - "+clientEvents);
+				} else {
+					sb.append(currentEvent);
+				}
+			}
+			logger.finest(sb.toString());
+		}
+
+		logger.finest("threadAccessCount: "+threadAccessCount);
+
+		threadEvent.set(currentEvent);	
+
+		try {
+			if(maxThreadAccessCount!=-1 && threadAccessCount>maxThreadAccessCount) {
+				logger.warning("ThreadAccessCount can't go beyond "+maxThreadAccessCount+": "+threadAccessCount);
+				if(Assertion.isEnabled()) {
+					throw new AssertionError("ThreadAccessCount can't go beyond "+maxThreadAccessCount+": "+threadAccessCount);
+				}
+				return;
+			}
+
+			if(socket==null)
+				throw new SocketException("Socket was null!");
+
+			if(getThreadEvent()==ClientEvent.ACCEPT || 
+					getThreadEvent()==ClientEvent.MAX_CON) {
+				prepareForRun();
+				Assertion.affirm(willReturn==false, "WillReturn has to be false!: "+willReturn);
+			}
+
+			if(getThreadEvent()==ClientEvent.MAX_CON) {
+				processMaxConnection(currentEvent);
+			}
+
+			try {
+				if(getThreadEvent()==ClientEvent.ACCEPT) {					
+					registerForRead();
+					clientEventHandler.gotConnected(this);
+
+					if(authorised == false) {						
+						if(clientAuthenticationHandler==null && authenticator == null) {
+							authorised = true;
+							logger.finest("No Authenticator "+getName()+" so return thread.");
+						} else {
+							if(clientAuthenticationHandler!=null) {
+								AuthStatus authStatus = null;
+								do {
+									authStatus = processAuthorisation();
+								} while(authStatus==AuthStatus.FAILURE);
+
+								if(authStatus==AuthStatus.SUCCESS)
+									authorised = true;
+							} else {
+								processAuthorisation();
+							}
+							if(authorised)
+								logger.finest("Authentication done "+getName()+", so return thread.");
+							else
+								logger.finest("askAuthentication() done "+getName()+", so return thread.");
+						}
+					}//end authorised
+					returnThread(); //return thread to pool
+					return;
+				}			
+				
+				if(connection && getThreadEvent()==ClientEvent.READ) {
+					if(processRead()) return;
+				}
+
+				if(connection && getThreadEvent()==ClientEvent.WRITE) {
+					if(processWrite()) return;
+				}
+
+			} catch(SocketException e) {
+				appLogger.finest("SocketException - Client [" + 
+					getHostAddress() +"]: "	+ e.getMessage());
+				//e.printStackTrace();
+				lost = true;
+			} catch(AppException e) {
+				//errors from Application
+				appLogger.finest("AppException "+Thread.currentThread().getName()+": " 
+					+ e.getMessage());		
+			} catch(javax.net.ssl.SSLException e) {
+				lost = true;
+				if(Assertion.isEnabled()) {
+					appLogger.info("SSLException - Client ["+getHostAddress()
+						+"] "+Thread.currentThread().getName()+": " + e);
+				} else {
+					appLogger.warning("SSLException - Client ["+
+						getHostAddress()+"]: "+e);
+				}
+			} catch(ConnectionLostException e) {
+				lost = true;
+				if(e.getMessage()!=null)
+					appLogger.finest("Connection lost " +
+						Thread.currentThread().getName()+": " + e.getMessage());
+				else
+					appLogger.finest("Connection lost "+Thread.currentThread().getName());
+			} catch(ClosedChannelException e) {
+				lost = true;
+				appLogger.finest("Channel closed "+Thread.currentThread().getName()+": " + e);
+			} catch(IOException e) {
+				lost = true;
+				appLogger.fine("IOError "+Thread.currentThread().getName()+": " + e);
+			} catch(AssertionError er) {
+				logger.warning("[AssertionError] "+getName()+" "+er);
+				if(logger.isLoggable(Level.FINEST)) {
+					logger.finest("StackTrace "+Thread.currentThread().getName()+": "+MyString.getStackTrace(er));
+				}
+				assertionSystemExit();
+			} catch(RuntimeException re) {
+				logger.warning("[RuntimeException] "+MyString.getStackTrace(re));
+				if(Assertion.isEnabled()) {
+					assertionSystemExit();
+				}
+				lost = true;
+			} catch(Throwable er) {
+				logger.warning("[Error] "+er);
+				if(logger.isLoggable(Level.FINEST)) {
+					logger.finest("StackTrace "+Thread.currentThread().getName()+": "+MyString.getStackTrace(er));
+				}
+				if(Assertion.isEnabled()) {
+					assertionSystemExit();
+				}
+				lost = true;
+			} 
+			
+			if(getThreadEvent()!=ClientEvent.MAX_CON) {
+				notifyCloseOrLost();
+			}
+			
+			if(connection) {
+				logger.finest(Thread.currentThread().getName()+" calling closeConnection()");
+				closeConnection();
+			} 
+			
+			if(connection==true && lost==true && waitingForFinalWrite) {
+				byteBufferOutputStream.forceNotify();
+			}
+		} catch(javax.net.ssl.SSLException se) {
+			logger.warning("SSLException "+Thread.currentThread().getName()+" - " + se);
+		} catch(IOException ie) {
+			logger.warning("IOError "+Thread.currentThread().getName()+" - Closing Client : " + ie);
+		} catch(RuntimeException re) {
+			logger.warning("[RuntimeException] "+getName()+" "+Thread.currentThread().getName()+" - "+MyString.getStackTrace(re));
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+		} catch(Exception e) {
+			logger.warning("Error "+Thread.currentThread().getName()+" - Event:"+getThreadEvent()+" - Socket:"+socket+" : "+e);
+			logger.fine("StackTrace: "+getName()+"\n"+MyString.getStackTrace(e));
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+		} catch(Throwable e) {
+			logger.warning("Error "+Thread.currentThread().getName()+" - Event:"+getThreadEvent()+" - Socket:"+socket+" : "+e);
+			logger.fine("StackTrace: "+getName()+"\n"+MyString.getStackTrace(e));
+			if(Assertion.isEnabled()) {
+				assertionSystemExit();
+			}
+		}
+
+		synchronized(this) {
+			try	{
+				if(getSelectionKey()!=null && getSelectionKey().isValid()) {
+					logger.finest("Canceling SelectionKey");
+					getSelectionKey().cancel();
+				}
+
+				if(socket!=null && socket.isClosed()==false) {
+					logger.finest("Closing Socket");
+					socket.close();
+				}
+
+				if(getSocketChannel()!=null && getSocketChannel().isOpen()) {
+					logger.finest("Closing SocketChannel");
+					socketChannel.close();
+				}				
+			} catch(Exception re) {
+				logger.warning("Error closing Socket/Channel: " +re);
+			}
+		}//end synchronized
+
+		willClean = true;
+		returnClientData();
+
+		boolean returnClientHandler = false;
+		synchronized(lockObj) {
+			returnThread();
+			returnClientHandler = checkReturnClientHandler();
+		}
+
+		if(returnClientHandler) {
+			returnClientHandler(); //return to pool
+		}
+	}
+
+	protected boolean checkReturnClientHandler() {
+		if(willReturn==false) {
+			willReturn = true;
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Process read
+	 * @return value indicates if the thread should return form run()
+	 */
+	private boolean processRead() throws Exception {
+		if(doRead()) {
+			returnThread(); //return to pool
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	private boolean doRead() throws Exception {
+		int count = 0;
+		int fullCount = 0;
+		
+		while(true) {
+			try {
+				if(peerNetData==null) {
+					peerNetData = (ByteBuffer) getServer().getByteBufferPool().borrowObject();
+				}
+
+				count = getSocketChannel().read(peerNetData);
+				if(count<0) {
+					//logger.finest("SocketChannel read was "+count+"!");
+					getServer().getByteBufferPool().returnObject(peerNetData);
+					peerNetData = null;
+					break;
+				} else {
+					fullCount += count;
+				}
+
+				peerNetData.flip(); // Make readable
+				ByteBuffer peerAppData = null;
+
+				//--
+				if(sslEngine!=null) {
+					SSLEngineResult res;
+					peerAppData = (ByteBuffer) 
+							getServer().getByteBufferPool().borrowObject();
+					do {						
+						res = sslEngine.unwrap(peerNetData, peerAppData);
+						logger.info("Unwrapping:\n" + res);
+					} while(res.getStatus() == SSLEngineResult.Status.OK &&
+							res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP &&
+							res.bytesProduced() == 0);
+
+					if(res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {
+						logger.info("HandshakeStatus.FINISHED!");
+						finishInitialHandshake();
+					}
+
+					if(peerAppData.position() == 0 && 
+							res.getStatus() == SSLEngineResult.Status.OK &&
+							peerNetData.hasRemaining()) {
+						logger.info("peerNetData hasRemaining and pos=0!");
+						res = sslEngine.unwrap(peerNetData, peerAppData);
+						logger.info("Unwrapping:\n" + res);			
+					}
+
+					/*
+					 * OK, OVERFLOW, UNDERFLOW, CLOSED
+					 */
+					status = res.getStatus();
+					handshakeStatus = res.getHandshakeStatus();
+
+					if(status != SSLEngineResult.Status.BUFFER_OVERFLOW) {
+						logger.warning("Buffer overflow: " + res.toString());
+					} else if(status == SSLEngineResult.Status.CLOSED) {
+						logger.fine("Connection is being closed by peer.");
+						lost = true;
+						System.out.println("NEdd to code for shutdow of SSL");
+						break;
+					}
+
+					peerNetData.compact();
+					peerAppData.flip();
+
+					if(handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_TASK ||
+							handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP ||
+							handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED) {
+						doHandshake();
+					}
+
+					//return peerAppData.remaining();
+					logger.fine("peerAppData.remaining(): "+peerAppData.remaining());
+				} else {
+					peerAppData = peerNetData;
+					peerNetData = null;
+				}
+				//--
+
+				readByteBuffer.add(peerAppData);
+				peerAppData = null;
+
+			} catch(Exception error) {
+				logger.finest("Error in data read: "+error);
+				if(sslEngine!=null) sslEngine.closeInbound();
+				lost = true;
+				synchronized(getInputStream()) {
+					getInputStream().notifyAll();
+				}
+				throw error;
+			} 
+
+			if(count==0) break;
+		}//end while
+
+		if(count<0) {
+			logger.finest("SocketChannel read was "+count+"!");
+			if(sslEngine!=null) sslEngine.closeInbound();
+			lost = true;
+			synchronized(getInputStream()) {
+				getInputStream().notifyAll();
+			}
+		} else {
+			logger.finest(fullCount+" bytes read");
+			if(fullCount!=0) {
+				updateLastCommunicationTime();
+				synchronized(getInputStream()) {
+					getInputStream().notify(); //if any are waiting
+				}
+				if(hasEvent(ClientEvent.ACCEPT) == false) {
+					processGotDataInBuffers();
+				}
+			}
+
+			//check if any data was read but not yet processed
+			while(getInputStream().available()>0) {
+				logger.finest("Sending again for processing...");
+				if(hasEvent(ClientEvent.ACCEPT) == false) {
+					processGotDataInBuffers();
+					break;
+				} else {
+					synchronized(getInputStream()) {
+						getInputStream().notifyAll();									
+					}
+					Thread.sleep(100);								
+				}							
+			}
+
+			if(connection) {
+				registerForRead();
+				//getSelectionKey().selector().wakeup();
+				return true;
+			}
+		}//end of else
+		logger.finest("We don't have connection, lets return all resources.");
+		return false;
+	}
+
+	/**
+	 * Process write
+	 * @return value indicates if the thread should return form run()
+	 */
+	private boolean processWrite() throws IOException {
+		if(doWrite()) {
+			returnThread(); //return to pool
+			return true;
+		} else {
+			return false;
+		}		
+	}
+
+	private boolean doWrite() throws IOException {
+		if(sslShutdown) {
+			if(byteBufferOutputStream.doShutdown()==false) {
+				return true;
+			}
+			
+			doPostCloseActivity();
+
+			logger.finest("We don't have connection, lets return all resources.");
+			return false;
+		}
+
+		updateLastCommunicationTime();
+
+		boolean flag = byteBufferOutputStream.writeAllByteBuffer();
+		
+		if(flag==false) {
+			registerWrite();
+		} else if(/*flag==true && */clientWriteHandler!=null) {
+			clientWriteHandler.handleWrite(this);
+		}
+
+		if(connection) {
+			return true;
+		} else {
+			logger.finest("We don't have connection, lets return all resources.");
+			return false;
+		}
+	}
+
+	protected void returnThread() {
+		//System.out.println("returnThread..");
+		//(new Exception()).printStackTrace();
+		threadAccessCount--;
+		Assertion.affirm(threadAccessCount>=0, "ThreadAccessCount went less the 0! Value: "+threadAccessCount);
+		//return is done at ClientThread end
+		removeEvent((ClientEvent)threadEvent.get());
+	}
+
+	protected void returnClientHandler() {
+		logger.finest(getName());
+		try {
+			for(int i=0;threadAccessCount!=0;i++) {
+				if(i==100) { 
+					logger.warning("ClientHandler must have got into a loop waiting for thread to free up! ThreadAccessCount="+threadAccessCount);
+					threadAccessCount = 0;
+					if(Assertion.isEnabled()) {
+						assertionSystemExit();
+					} else {
+						break;
+					}
+				}
+				if(threadAccessCount<=0) break;
+
+				logger.finest("Waiting for other thread of "+getName()+" to finish");
+				Thread.sleep(60);
+			}
+		} catch(InterruptedException ie) {
+			appLogger.warning("InterruptedException: "+ie);
+		}
+		super.returnClientHandler();
+	}
+
+	public void setDataMode(DataMode dataMode, DataType dataType) 
+			throws IOException {
+		if(getDataMode(dataType)==dataMode) return;
+
+		appLogger.fine("Setting Type:"+dataType+", Mode:"+dataMode);
+		super.checkDataModeSet(dataMode, dataType);
+
+		setDataModeNonBlocking(dataMode, dataType);
+	}
+
+	private void setDataModeNonBlocking(DataMode dataMode, DataType dataType) 
+			throws IOException {
+		logger.finest("ENTER");
+		if(dataMode == DataMode.STRING) {
+			if(dataType == DataType.OUT) {
+				if(dataModeOUT == DataMode.BYTE || dataModeOUT == DataMode.BINARY) {
+					dataModeOUT = dataMode;
+				} else if(dataModeOUT == DataMode.OBJECT) {
+					dataModeOUT = dataMode;
+					o_out.flush(); o_out = null;
+					b_out = new BufferedOutputStream(out);
+				} else {
+					Assertion.affirm(false, "Unknown DataType.OUT DataMode - "+dataModeOUT);
+				}
+				Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!");
+				Assertion.affirm(o_out==null, "ObjectOutputStream is still not null!");
+			} else if(dataType == DataType.IN) {
+				dataModeIN = dataMode;
+
+				if(o_in!=null) {
+					if(o_in.available()!=0)
+						logger.warning("Data looks to be present in ObjectInputStream");
+					o_in = null;
+				}
+				b_in = null;
+				bufferedReader = null;
+				//input stream will work
+				Assertion.affirm(in!=null, "InputStream is still null!");
+				Assertion.affirm(b_in==null, "BufferedInputStream is still not null!");
+				Assertion.affirm(bufferedReader==null, "BufferedReader is still not null!");
+			}
+		} else if(dataMode == DataMode.OBJECT) {
+			if(dataType == DataType.IN) {
+				//we will disable this for now
+				throw new IllegalArgumentException("Can't set DataType.IN mode to OBJECT when blocking mode is set as false!");
+			}
+
+			if(dataType == DataType.OUT) {
+				dataModeOUT = dataMode;
+				b_out = null;
+				o_out = new ObjectOutputStream(out);
+				Assertion.affirm(o_out!=null, "ObjectOutputStream is still null!");
+				o_out.flush();
+			} else if(dataType == DataType.IN) {
+				dataModeIN = dataMode;
+				b_in = null;
+				bufferedReader = null;
+				
+				registerForRead();
+				o_in = new ObjectInputStream(in); //will block	
+				Assertion.affirm(o_in!=null, "ObjectInputStream is still null!");
+			}
+		} else if(dataMode == DataMode.BYTE || dataMode == DataMode.BINARY) {
+			if(dataType == DataType.OUT) {
+				if(dataModeOUT == DataMode.STRING || 
+						dataModeOUT == DataMode.BYTE || 
+						dataModeOUT == DataMode.BINARY) {
+					dataModeOUT = dataMode;
+				} else if(dataModeOUT == DataMode.OBJECT) {
+					dataModeOUT = dataMode;
+					
+					o_out = null;
+					b_out = new BufferedOutputStream(out);
+				} else {
+					Assertion.affirm(false, "Unknown DataType.OUT - DataMode: "+dataModeOUT);
+				}
+				Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!");
+			} else if(dataType == DataType.IN) {
+				dataModeIN = dataMode;
+				o_in = null;
+				bufferedReader = null;
+				b_in = null;
+				//input stream will work
+				Assertion.affirm(in!=null, "InputStream is still null!");
+			} else {
+				throw new IllegalArgumentException("Unknown DataType : "+dataType);
+			}
+		} else {
+			throw new IllegalArgumentException("Unknown DataMode : "+dataMode);
+		}
+	}
+
+	protected byte[] readInputStream() throws IOException {
+		return readInputStream(getInputStream());
+	}
+
+	public void updateInputOutputStreams() throws IOException {
+		byteBufferOutputStream = new ByteBufferOutputStream(writeByteBuffer, this);
+		setInputStream( new ByteBufferInputStream(readByteBuffer, this, getCharset()) );
+		setOutputStream(byteBufferOutputStream);
+		
+		//logger.warning("updateInputOutputStreams: "+sslEngine);
+		if(sslEngine!=null) {
+			sslEngine.setUseClientMode(false);
+			sslEngine.beginHandshake();
+
+			handshakeStatus = sslEngine.getHandshakeStatus();
+			initialHandshakeStatus = true;
+			/*
+			try {
+				doHandshake();
+			} catch(Exception e) {
+				logger.warning("Error: "+e);
+				throw new IOException(e.toString());
+			}
+			*/
+		}
+	}
+
+	public boolean getBlockingMode() {
+		return false;
+	}
+
+	public void setSocketChannel(SocketChannel socketChannel) {
+		this.socketChannel = socketChannel;
+	}
+	public SocketChannel getSocketChannel() {
+		return socketChannel;
+	}
+
+	public void setSelectionKey(SelectionKey selectionKey) {
+		this.selectionKey = selectionKey;
+	}
+	public SelectionKey getSelectionKey() {
+		if(selectionKey==null)
+			selectionKey = getSocketChannel().keyFor(getServer().getSelector());
+		return selectionKey;
+	}
+
+	private void processGotDataInBuffers() throws AppException, 
+			ConnectionLostException, ClassNotFoundException, IOException {
+		if(getInputStream().available()==0) return;
+		
+		logger.finest("Trying to process got data.. DataMode.IN="+dataModeIN);
+		AuthStatus authStatus = null;
+		
+		//--For debug
+		((ByteBufferInputStream) getInputStream()).dumpContent();
+
+		String temp = null;
+		String rec = null;
+		Object recObject = null;
+		byte[] recByte = null;
+
+		boolean timeToCheckForNewLineMiss = false;
+		
+		do {
+			//updateLastCommunicationTime();
+
+			if(dataModeIN == DataMode.STRING) {
+				ByteBufferInputStream bbin = (ByteBufferInputStream) 
+					getInputStream();
+				timeToCheckForNewLineMiss = true;
+
+				while(bbin.isLineReady()) {
+
+					rec = bbin.readLine();
+					if(rec==null) {
+						lost = true;
+						return;
+					}
+					if(getCommunicationLogging() && authorised == true) {
+						appLogger.log(Level.FINE, "Got STRING [{0}] : {1}", new Object[]{getHostAddress(), rec});
+					}
+					
+					totalReadBytes = totalReadBytes + rec.length();
+					
+					if(authorised == false)
+						authStatus = clientAuthenticationHandler.handleAuthentication(this, rec);
+					else
+						clientCommandHandler.handleCommand(this, rec);
+
+					if(isClosed()==true) return;
+
+					while(authStatus==AuthStatus.FAILURE)
+						authStatus = processAuthorisation();
+
+					if(authStatus==AuthStatus.SUCCESS)
+						authorised = true;
+
+					if(dataModeIN != DataMode.STRING) {
+						break;
+					}
+
+					timeToCheckForNewLineMiss = false;
+				}//end of while
+
+				if(timeToCheckForNewLineMiss && bbin.availableOnlyInByteBuffer()==0) {
+					return;
+				} else {
+					timeToCheckForNewLineMiss = false;
+				}
+			} 
+			
+			//if(dataModeIN == DataMode.OBJECT) {
+			while(dataModeIN == DataMode.OBJECT && o_in!=null) {
+				//not sure if all bytes are in buffer..~ may need more read.. will get stuck..
+				recObject = o_in.readObject();
+				if(recObject==null) {
+					lost = true;
+					return;
+				}
+				if(getCommunicationLogging() && authorised == true) {
+					appLogger.log(Level.FINE, "Got OBJECT [{0}] : {1}", new Object[]{getHostAddress(), recObject.toString()});
+				}
+				
+				totalReadBytes = totalReadBytes + 1;
+
+				if(authorised == false)
+					authStatus = clientAuthenticationHandler.handleAuthentication(this, recObject);
+				else
+					clientObjectHandler.handleObject(this, recObject);
+				
+				if(isClosed()==true) return;
+
+				while(authStatus==AuthStatus.FAILURE)
+					authStatus = processAuthorisation();
+				
+				if(authStatus==AuthStatus.SUCCESS)
+					authorised = true;
+			}
+			//} 
+			
+
+			//if(dataModeIN == DataMode.BYTE) {
+			while(dataModeIN == DataMode.BYTE && getInputStream().available()!=0) {
+				rec = readBytes();
+				if(rec==null) {
+					lost = true;
+					return;
+				}
+				if(getCommunicationLogging() && authorised == true) {
+					appLogger.log(Level.FINE, "Got BYTE [{0}] : {1}", 
+						new Object[]{getHostAddress(), rec});
+				}
+				
+				totalReadBytes = totalReadBytes + rec.length();
+
+				if(authorised == false)
+					authStatus = clientAuthenticationHandler.handleAuthentication(this, rec);
+				else
+					clientCommandHandler.handleCommand(this, rec);
+
+				if(isClosed()==true) return;
+
+				while(authStatus==AuthStatus.FAILURE)
+					authStatus = processAuthorisation();
+
+				if(authStatus==AuthStatus.SUCCESS)
+					authorised = true;
+			}
+
+			//} else if(dataModeIN == DataMode.BINARY) {
+			while(dataModeIN == DataMode.BINARY && getInputStream().available()!=0) {
+				recByte = readBinary();
+				if(recByte==null) {
+					lost = true;
+					return;
+				}
+				if(getCommunicationLogging() && authorised == true) {				
+					if(getServer().isRawCommunicationLogging()) {
+						if(getServer().getRawCommunicationMaxLength()>0 && 
+									recByte.length>getServer().getRawCommunicationMaxLength()) {
+							appLogger.log(Level.FINE, 
+								"Got BINARY [{0}] : {1}; RAW: {2}{3}", new Object[]{
+									getHostAddress(), MyString.getMemInfo(recByte.length), 
+									new String(recByte,0,getServer().getRawCommunicationMaxLength(),charset),"..."});
+						} else {
+							appLogger.log(Level.FINE, 
+								"Got BINARY [{0}] : {1}; RAW: {2}", new Object[]{
+									getHostAddress(), MyString.getMemInfo(recByte.length), 
+									new String(recByte,charset)});
+						}
+					} else {
+						appLogger.log(Level.FINE, 
+							"Got BINARY [{0}] : {1}", new Object[]{getHostAddress(), 
+								MyString.getMemInfo(recByte.length)});
+					}
+				} else if (getCommunicationLogging()) {
+					appLogger.log(Level.FINE, 
+						"Got BINARY [{0}] : {1}", new Object[]{getHostAddress(), 
+							MyString.getMemInfo(recByte.length)});
+				}
+				
+				totalReadBytes = totalReadBytes + recByte.length;
+
+				if(authorised == false)
+					authStatus = clientAuthenticationHandler.handleAuthentication(this, recByte);
+				else
+					clientBinaryHandler.handleBinary(this, recByte);
+
+				if(isClosed()==true) return;
+
+				while(authStatus==AuthStatus.FAILURE)
+					authStatus = processAuthorisation();
+
+				if(authStatus==AuthStatus.SUCCESS)
+					authorised = true;
+			}
+
+			//} else {
+			if(dataModeIN != DataMode.STRING && dataModeIN != DataMode.OBJECT 
+				&& dataModeIN != DataMode.BYTE && dataModeIN != DataMode.BINARY) {
+				throw new IllegalStateException("Incoming DataMode is not supported : "+dataModeIN);
+			}
+		} while(getInputStream().available()!=0);
+	}
+
+	public void registerForRead() 
+			throws IOException, ClosedChannelException {
+		//System.out.println("registerForRead..");
+		//(new Exception()).printStackTrace();
+		try {		
+			if(getSelectionKey()==null) {
+				boolean flag = getServer().registerChannel(getSocketChannel(), 
+					SelectionKey.OP_READ, this);
+				if(flag) {
+					logger.finest("Adding OP_READ as interest Ops for "+getName());
+				} else if(ByteBufferOutputStream.isLoggable(Level.FINEST)) {
+					logger.finest("OP_READ is already present in interest Ops for "+getName());
+				}
+			} else if(getSelectionKey().isValid()) {
+				if((getSelectionKey().interestOps() & SelectionKey.OP_READ) == 0 ) {
+					logger.finest("Adding OP_READ to interest Ops for "+getName());
+					removeEvent(ClientEvent.READ);
+					getSelectionKey().interestOps(getSelectionKey().interestOps() 
+						| SelectionKey.OP_READ);
+					if(wakeupSelectorAfterRegisterRead) {
+						getServer().getSelector().wakeup();
+					}
+				} else {
+					if(ByteBufferOutputStream.isLoggable(Level.FINEST)) {
+						logger.finest("OP_READ is already present in interest Ops for "+getName());
+					}
+				}
+			} else {
+				throw new IOException("SelectionKey is invalid!");
+			}
+		} catch(CancelledKeyException e) {
+			throw new IOException("SelectionKey is cancelled!");
+		}
+	}
+
+	public void registerForWrite() 
+			throws IOException, ClosedChannelException {
+		if(hasEvent(ClientEvent.RUN_BLOCKING) || hasEvent(ClientEvent.MAX_CON_BLOCKING)) {
+			throw new IllegalStateException("This method is only allowed under Non-Blocking mode.");
+		}
+
+		if(clientWriteHandler==null) {
+			throw new IllegalStateException("ClientWriteHandler has not been set!");
+		}
+		registerWrite();
+	}
+	
+	public void registerWrite() throws IOException {
+		//System.out.println("registerWrite..");
+		//(new Exception()).printStackTrace();
+		try {
+			if(getSelectionKey()==null) {				
+				boolean flag = getServer().registerChannel(getSocketChannel(), 
+						SelectionKey.OP_WRITE, this);
+				if(flag) {
+					logger.finest("Adding OP_WRITE as interest Ops for "+getName());
+				} else if(ByteBufferOutputStream.isLoggable(Level.FINEST)) {
+					logger.finest("OP_WRITE is already present in interest Ops for "+getName());
+				}
+			} else if(getSelectionKey().isValid()) {
+				if((getSelectionKey().interestOps() & SelectionKey.OP_WRITE) == 0 ) {
+					logger.finest("Adding OP_WRITE to interest Ops for "+getName());
+					removeEvent(ClientEvent.WRITE);
+					getSelectionKey().interestOps(getSelectionKey().interestOps() 
+						| SelectionKey.OP_WRITE);
+					if(wakeupSelectorAfterRegisterWrite) {
+						getServer().getSelector().wakeup();
+					}
+				} else {
+					if(ByteBufferOutputStream.isLoggable(Level.FINEST)) {
+						logger.finest("OP_WRITE is already present in interest Ops for "+getName());
+					}
+				}
+			} else {
+				throw new IOException("SelectionKey is invalid!");
+			}
+		} catch(CancelledKeyException e) {
+			throw new IOException("SelectionKey is cancelled!");
+		}
+	}
+
+	protected void setClientWriteHandler(ClientWriteHandler handler) {
+		clientWriteHandler=handler;
+	}
+
+	/**
+	 * Returns number of thread currently in this object.
+	 * @since 1.4.6
+	 */
+	public int getThreadAccessCount() {
+		return threadAccessCount;
+	}
+
+	private void doHandshake() throws Exception {
+		while (true) {
+			SSLEngineResult res;
+			logger.fine("handshakeStatus: "+handshakeStatus);
+
+			if(handshakeStatus==SSLEngineResult.HandshakeStatus.FINISHED) {
+					if(initialHandshakeStatus) {
+						finishInitialHandshake();
+					}
+					return;
+			} else if(handshakeStatus==SSLEngineResult.HandshakeStatus.NEED_TASK) {
+					doTasks();
+					continue;
+			} else if(handshakeStatus==SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
+					/*
+					doRead();
+
+					if(initialHandshakeStatus && 
+							status == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
+						registerForRead();
+					}
+					*/
+					return;
+			} else if(handshakeStatus==SSLEngineResult.HandshakeStatus.NEED_WRAP) {
+					ByteBuffer netData = (ByteBuffer) getServer().getByteBufferPool().borrowObject();
+					//netData.clear();
+
+					res = sslEngine.wrap(dummyByteBuffer, netData);
+					logger.info("Wrapping:\n" + res);
+					assert res.bytesProduced() != 0 : "No net data produced during handshake wrap.";
+					assert res.bytesConsumed() == 0 : "App data consumed during handshake wrap.";
+					handshakeStatus = res.getHandshakeStatus();
+					
+					//netData.flip(); -- no need to flip will be done when writing to sc					
+					byteBufferOutputStream.addEncryptedByteBuffer(netData);
+
+					if (!doWrite()) {
+						return;
+					}
+					continue;//back to loop
+			} else if(handshakeStatus==SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
+					assert false : "doHandshake() should never reach the NOT_HANDSHAKING state";
+					return;
+			}//if
+		}//loop
+	}
+
+	private void doTasks() {
+		Runnable task;
+		while ((task = sslEngine.getDelegatedTask()) != null) {
+			logger.fine("Running the task.. START ");
+			task.run();
+			logger.fine("Running the task.. END");
+		}
+		handshakeStatus = sslEngine.getHandshakeStatus();
+		logger.fine("handshakeStatus: "+handshakeStatus);
+	}
+
+	private void finishInitialHandshake() throws IOException {
+		initialHandshakeStatus = false;
+	}
+
+	public boolean getInitialHandshakeStatus() {
+		return initialHandshakeStatus;
+	}
+
+	public ByteBuffer encrypt(ByteBuffer src) throws IOException {
+		if(initialHandshakeStatus) {
+			logger.fine("Writing not possible during handshake!");
+			//Exception e = new Exception();
+			//e.printStackTrace();
+			return null;
+		}
+
+		ByteBuffer dest = null;
+		boolean isException = false;
+		try {
+			src.flip();
+			dest = (ByteBuffer) getServer().getByteBufferPool().borrowObject();
+			//dest.clear();
+			SSLEngineResult res = sslEngine.wrap(src, dest);
+			logger.info("Wrapping:\n" + res);
+			//dest.flip();
+			return dest;
+		} catch(IOException e) {
+			logger.warning("IOException:" + e);
+			isException = true;
+			throw e;
+		} catch(Exception e) {
+			logger.warning("Exception:" + e);
+			isException = true;
+			throw new IOException(e.getMessage());
+		} finally {
+			if(isException==true && dest!=null) {
+				try {
+					getServer().getByteBufferPool().returnObject(dest);
+				} catch(Exception er) {
+					logger.warning("Error in returning ByteBuffer to pool: "+er);
+				}				
+			}
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/OptimisticClientIdentifier.java b/quickserver/src/main/org/quickserver/net/server/impl/OptimisticClientIdentifier.java
new file mode 100644
index 0000000..dd0c92b
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/OptimisticClientIdentifier.java
@@ -0,0 +1,153 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
+import org.quickserver.util.pool.*;
+import org.quickserver.net.server.*;
+import java.util.regex.*;
+
+/**
+ * Optimistic Client Identifier implementation.
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public class OptimisticClientIdentifier extends BasicClientIdentifier  {
+	private static final Logger logger = Logger.getLogger(OptimisticClientIdentifier.class.getName());
+	private ClientIdentifier backupClientIdentifier;
+	private static final int MAX_TRY_COUNT = 4;
+
+	public ClientHandler findFirstClientById(String id) {
+		return findFirstClientById(id, 0);
+	}
+
+	private ClientHandler findFirstClientById(String id, int callCount) {
+		ClientHandler foundClientHandler = null;
+		try {
+			Iterator iterator = findAllClient();			
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientId(
+					(ClientHandler) iterator.next(), id);
+
+				if(foundClientHandler!=null) break;
+			}//endof while
+		} catch(ConcurrentModificationException e) {
+			if(callCount<MAX_TRY_COUNT) {
+				//start over again.
+				foundClientHandler = findFirstClientById(id, ++callCount);
+			} else {
+				logger.finest("Going for backup..");
+				foundClientHandler = getBackupClientIdentifier().findFirstClientById(id);
+			}
+		}
+		return foundClientHandler;
+	}
+
+	public Iterator findAllClientById(String pattern) {
+		return findAllClientById(pattern, 0);
+	}
+	private Iterator findAllClientById(String pattern, int callCount) {
+		ArrayList list = new ArrayList();
+		Pattern p = Pattern.compile(pattern);
+		ClientHandler foundClientHandler = null;
+		
+		try {
+			Iterator iterator = findAllClient();			
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientId(
+					(ClientHandler) iterator.next(), p);
+
+				if(foundClientHandler!=null) 
+					list.add(foundClientHandler);
+			}//endof while
+		} catch(ConcurrentModificationException e) {
+			if(callCount<MAX_TRY_COUNT) {
+				//start over again.
+				list = null;
+				return findAllClientById(pattern, ++callCount);
+			} else {
+				logger.finest("Going for backup..");
+				return getBackupClientIdentifier().findAllClientById(pattern);
+			}
+		}
+		return list.iterator();
+	}
+
+	public ClientHandler findClientByKey(String key) {
+		return findClientByKey(key, 0);
+	}
+	private ClientHandler findClientByKey(String key, int callCount) {
+		ClientHandler foundClientHandler = null;
+		try {
+			Iterator iterator = findAllClient();
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientKey( 
+					(ClientHandler) iterator.next(), key);
+
+				if(foundClientHandler!=null) break;
+			}//endof while
+		} catch(ConcurrentModificationException e) {
+			if(callCount<MAX_TRY_COUNT) {
+				//start over again.
+				foundClientHandler = findClientByKey(key,  ++callCount);
+			} else {
+				logger.finest("Going for backup..");
+				foundClientHandler = getBackupClientIdentifier().findClientByKey(key);
+			}
+		}
+		return foundClientHandler;
+	}
+
+	public Iterator findAllClientByKey(String pattern) {
+		return findAllClientByKey(pattern, 0);
+	}
+	private Iterator findAllClientByKey(String pattern, int callCount) {
+		ArrayList list = new ArrayList();
+		Pattern p = Pattern.compile(pattern);
+		ClientHandler foundClientHandler = null;
+
+		try {
+			Iterator iterator = findAllClient();
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientKey( 
+					(ClientHandler) iterator.next(), p);
+			
+				if(foundClientHandler!=null) 
+					list.add(foundClientHandler);
+				foundClientHandler = null;
+			}//endof while
+		} catch(ConcurrentModificationException e) {
+			if(callCount<MAX_TRY_COUNT) {
+				//start over again.
+				list = null;
+				return findAllClientByKey(pattern, ++callCount);
+			} else {
+				logger.finest("Going for backup..");
+				return getBackupClientIdentifier().findAllClientByKey(pattern);
+			}
+		}
+		return list.iterator();
+	}
+
+	private synchronized ClientIdentifier getBackupClientIdentifier() {
+		if(backupClientIdentifier==null) {
+			backupClientIdentifier = new SyncClientIdentifier();
+			backupClientIdentifier.setClientHandlerPool(clientHandlerPool);
+		}
+		return backupClientIdentifier;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/RegisterChannelRequest.java b/quickserver/src/main/org/quickserver/net/server/impl/RegisterChannelRequest.java
new file mode 100644
index 0000000..cd5370f
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/RegisterChannelRequest.java
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import java.io.*;
+import java.util.logging.*;
+import java.nio.channels.*;
+
+/**
+ * RegisterChannel request object.
+ * @author Akshathkumar Shetty
+ * @since 1.4.7
+ */
+public class RegisterChannelRequest {
+	private static final Logger logger = Logger.getLogger(RegisterChannelRequest.class.getName());
+
+	private SelectableChannel channel;
+	private int ops;
+	private Object att;
+
+	public RegisterChannelRequest(SelectableChannel channel, int ops, Object att) {
+		this.channel = channel;
+		this.ops = ops;
+		this.att = att;
+	}
+
+	public void register(Selector selector) {
+		try {
+			channel.register(selector, ops, att);
+		} catch(ClosedChannelException cce) {
+			logger.warning("Error: "+cce);
+		}
+	}
+
+	public SelectableChannel getChannel() {
+        return channel;
+    }
+
+    public void setChannel(SelectableChannel channel) {
+        this.channel = channel;
+    }
+
+    public int getOps() {
+        return ops;
+    }
+
+    public void setOps(int ops) {
+        this.ops = ops;
+    }
+
+    public Object getAtt() {
+        return att;
+    }
+
+    public void setAtt(Object att) {
+        this.att = att;
+    }
+
+	public boolean equals(Object obj) {
+		if(obj==null) return false;
+
+		RegisterChannelRequest req = (RegisterChannelRequest) obj;
+		boolean res = req.getChannel()==getChannel();
+		if(res)	res = req.getAtt()==getAtt();
+		if(res)	res = req.getOps()==getOps();
+		return res;
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/SyncClientIdentifier.java b/quickserver/src/main/org/quickserver/net/server/impl/SyncClientIdentifier.java
new file mode 100644
index 0000000..be1cd61
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/SyncClientIdentifier.java
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.net.server.impl;
+
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
+import org.quickserver.util.pool.*;
+import org.quickserver.net.server.*;
+import java.util.regex.*;
+
+/**
+ * Synchronized Client Identifier implementation. 
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public class SyncClientIdentifier extends BasicClientIdentifier {
+	private static final Logger logger = Logger.getLogger(SyncClientIdentifier.class.getName());
+
+	public ClientHandler findFirstClientById(String id) {
+		ClientHandler foundClientHandler = null;
+
+		synchronized(getObjectToSynchronize()) {
+			Iterator iterator = findAllClient();			
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientId(
+					(ClientHandler) iterator.next(), id);
+
+				if(foundClientHandler!=null) break;
+			}//endof while
+		}
+		return foundClientHandler;
+	}
+
+	public Iterator findAllClientById(String pattern) {
+		ArrayList list = new ArrayList();
+		Pattern p = Pattern.compile(pattern);
+		ClientHandler foundClientHandler = null;
+		
+		synchronized(getObjectToSynchronize()) {
+			Iterator iterator = findAllClient();
+			
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientId(
+					(ClientHandler) iterator.next(), p);
+
+				if(foundClientHandler!=null) 
+					list.add(foundClientHandler);
+			}//endof while
+		}
+		return list.iterator();
+	}
+
+	public ClientHandler findClientByKey(String key) {
+		ClientHandler foundClientHandler = null;
+
+		synchronized(getObjectToSynchronize()) {
+			Iterator iterator = findAllClient();
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientKey( 
+					(ClientHandler) iterator.next(), key);
+
+				if(foundClientHandler!=null) break;
+			}//endof while
+		}
+		return foundClientHandler;
+	}
+
+	public Iterator findAllClientByKey(String pattern) {
+		ArrayList list = new ArrayList();
+		Pattern p = Pattern.compile(pattern);
+		ClientHandler foundClientHandler = null;
+
+		synchronized(getObjectToSynchronize()) {
+			Iterator iterator = findAllClient();
+			while(iterator.hasNext()) {
+				foundClientHandler = checkClientKey( 
+					(ClientHandler) iterator.next(), pattern);
+			
+				if(foundClientHandler!=null) 
+					list.add(foundClientHandler);
+				foundClientHandler = null;
+			}//endof while
+		}
+		return list.iterator();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/net/server/impl/package.html b/quickserver/src/main/org/quickserver/net/server/impl/package.html
new file mode 100644
index 0000000..512ef55
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/impl/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Contains all of the implementation classes for interface in server package.  

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/net/server/package.html b/quickserver/src/main/org/quickserver/net/server/package.html
new file mode 100644
index 0000000..967ae57
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/net/server/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Contains all of the classes for creating QuickServer.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/security/AccessManager.java b/quickserver/src/main/org/quickserver/security/AccessManager.java
new file mode 100644
index 0000000..4b982c3
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/security/AccessManager.java
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.security;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+
+/**
+ * This is a simple SecurityManager template.
+ * @since 1.3.3
+ */
+public class AccessManager extends SecurityManager {
+	
+	public AccessManager() {
+	}
+
+	public void checkPermission(Permission perm) {}
+	public void checkPermission(Permission perm, Object context) {}
+	public void checkPrintJobAccess() {}
+	public void checkSecurityAccess(String target) {}
+
+	public void checkCreateClassLoader() {}
+	public void checkMemberAccess(Class clazz, int which) {}
+	public void checkPackageAccess(String pkg) {}
+	public void checkPackageDefinition(String pkg) {}
+	
+	public void checkDelete(String file) {}
+	public void checkExec(String cmd) {}
+	public void checkExit(int status) {}
+
+	public void checkListen(int port ) {}
+	public void checkAccept(String host, int port) {
+		//throw new SecurityException("Accept denied from "+host+":"+port);
+	}
+	public void checkConnect(String host, int port) {}
+	public void checkConnect(String host, int port, Object context) {}
+	public void checkMulticast(InetAddress maddr) {}
+	public void checkSetFactory() {}
+	public void checkSystemClipboardAccess() {}
+ 
+	public void checkAccess(Thread t) {}
+	public void checkAccess(ThreadGroup g) {} 
+
+	public void checkRead(String str) {}
+	public void checkRead(FileDescriptor fd ) {}
+	public void checkRead(String file, Object context) {}
+	
+	public void checkWrite(FileDescriptor f){}
+	public void checkWrite(String s){}
+
+	public void checkLink(String lib ) {}
+	public void checkPropertiesAccess() {}
+	public void checkPropertyAccess (String key) {}
+
+	public void checkAwtEventQueueAccess() {};
+	public boolean checkTopLevelWindow(Object window) {
+		return true;
+	}
+
+}
diff --git a/quickserver/src/main/org/quickserver/security/SecureStoreManager.java b/quickserver/src/main/org/quickserver/security/SecureStoreManager.java
new file mode 100644
index 0000000..f6b21ba
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/security/SecureStoreManager.java
@@ -0,0 +1,304 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.security;
+
+import java.io.*;
+import java.util.logging.*;
+import org.quickserver.util.xmlreader.*;
+import org.quickserver.util.io.*;
+import javax.net.ssl.*;
+import java.security.*;
+import org.quickserver.swing.*;
+
+/**
+ * Class that loads Key Managers, Trust Managers, SSLContext and other secure
+ * objects from QuickServer configuration passed. See &lt;secure-store-manager&gt;
+ * in &lt;secure-store&gt; to set new manger to load your SecureStore. This 
+ * class can be overridden to change the way QuickServer configures the 
+ * secure mode.
+ * @see org.quickserver.util.xmlreader.SecureStore 
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public class SecureStoreManager {
+	private static Logger logger = Logger.getLogger(
+		SecureStoreManager.class.getName());
+	private SensitiveInput sensitiveInput = null;
+
+	/**
+	 * Loads KeyManagers. KeyManagers are responsible for managing 
+	 * the key material which is used to authenticate the local 
+	 * SSLSocket to its peer. Can return null.
+	 */
+	public KeyManager[] loadKeyManagers(QuickServerConfig config) 
+			throws GeneralSecurityException, IOException {
+		Secure secure = config.getSecure();
+		SecureStore secureStore = secure.getSecureStore();
+
+		if(secureStore==null) {
+			logger.fine("SecureStore configuration not set! "+
+				"So returning null for KeyManager");
+			return null;
+		}
+
+		KeyStoreInfo keyStoreInfo = secureStore.getKeyStoreInfo();
+		if(keyStoreInfo==null) {
+			logger.fine("KeyStoreInfo configuration not set! "+
+				"So returning null for KeyManager");
+			return null;
+		}
+
+		logger.finest("Loading KeyManagers");		
+		KeyStore ks = getKeyStoreForKey(secureStore.getType(),
+				secureStore.getProvider());
+                
+                logger.info("KeyManager Provider: "+ks.getProvider());		
+
+		char storepass[] = null;
+		if(keyStoreInfo.getStorePassword()!=null) {
+			logger.finest("KeyStore: Store password was present!");
+			storepass = keyStoreInfo.getStorePassword().toCharArray();
+		} else {
+			logger.finest("KeyStore: Store password was not set.. so asking!");
+			if(sensitiveInput==null) {
+				sensitiveInput = new SensitiveInput(config.getName()+" - Input Prompt");
+			}
+			storepass = sensitiveInput.getInput("Store password for KeyStore");
+			if(storepass==null) {
+				logger.finest("No password entered.. will pass null");
+			}
+		}
+
+		InputStream keyStoreStream = null;
+		try {
+			if(keyStoreInfo.getStoreFile().equalsIgnoreCase("none")==false) {
+				logger.finest("KeyStore location: "+
+					ConfigReader.makeAbsoluteToConfig(keyStoreInfo.getStoreFile(),
+					config));
+				keyStoreStream = new FileInputStream(
+					ConfigReader.makeAbsoluteToConfig(keyStoreInfo.getStoreFile(),
+					config));
+			}
+
+			ks.load(keyStoreStream, storepass);
+			logger.finest("KeyStore loaded");
+		} finally {
+			if(keyStoreStream != null) {
+				keyStoreStream.close();
+				keyStoreStream = null;
+			}
+		}
+
+		char keypass[] = null;
+		if(keyStoreInfo.getKeyPassword()!=null) {
+			logger.finest("KeyStore: key password was present!");
+			keypass = keyStoreInfo.getKeyPassword().toCharArray();
+		} else {
+			logger.finest("KeyStore: Key password was not set.. so asking!");
+			if(sensitiveInput==null) {
+				sensitiveInput = new SensitiveInput(config.getName()+" - Input Prompt");
+			}
+			keypass = sensitiveInput.getInput("Key password for KeyStore");
+			if(keypass==null) {
+				logger.finest("No password entered.. will pass blank");
+				keypass = "".toCharArray();
+			}
+		}
+
+		KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+			secureStore.getAlgorithm());
+		kmf.init(ks, keypass);
+
+		storepass = "               ".toCharArray();
+		storepass = null;
+		keypass = "               ".toCharArray();
+		keypass = null;
+
+		return kmf.getKeyManagers();
+	}
+
+	/**
+	 * Loads TrustManagers. TrustManagers are responsible for managing the 
+	 * trust material that is used when making trust decisions, and for 
+	 * deciding whether credentials presented by a peer should be accepted. 
+	 * Can return null.
+	 */
+	public TrustManager[] loadTrustManagers(QuickServerConfig config) 
+			throws GeneralSecurityException, IOException {
+		Secure secure = config.getSecure();
+		SecureStore secureStore = secure.getSecureStore();
+		TrustStoreInfo trustStoreInfo = secureStore.getTrustStoreInfo();
+
+		if(trustStoreInfo==null) {
+			return null;
+		}
+
+		logger.finest("Loading TrustManagers");
+
+		String type = null;
+		if(trustStoreInfo.getType()!=null && trustStoreInfo.getType().trim().length()!=0)
+			type = trustStoreInfo.getType();
+		else
+			type = secureStore.getType();
+
+		String provider = null;
+		if(trustStoreInfo.getProvider()!=null && trustStoreInfo.getProvider().trim().length()!=0)
+			provider = trustStoreInfo.getProvider();
+		else
+			provider = secureStore.getProvider();
+		
+		KeyStore ts = getKeyStoreForTrust(type,	provider);	
+
+		char trustpass[] = null;
+		if(trustStoreInfo.getStorePassword()!=null) {
+			logger.finest("TrustStore: Store password was present!");
+			trustpass = trustStoreInfo.getStorePassword().toCharArray();
+		} else {
+			logger.finest("TrustStore: Store password was not set.. so asking!");
+			if(sensitiveInput==null) {
+				sensitiveInput = new SensitiveInput(config.getName()+" - Input Prompt");
+			}
+			trustpass = sensitiveInput.getInput("Store password for TrustStore");
+			if(trustpass==null) {
+				logger.finest("No password entered.. will pass null");
+			}
+		}
+
+		InputStream trustStoreStream = null;
+		try {
+			if(trustStoreInfo.getStoreFile().equalsIgnoreCase("none")==false) {
+				logger.finest("TrustStore location: "+
+					ConfigReader.makeAbsoluteToConfig(
+					trustStoreInfo.getStoreFile(), config));
+				trustStoreStream = new FileInputStream(
+					ConfigReader.makeAbsoluteToConfig(
+					trustStoreInfo.getStoreFile(), config));
+			}
+
+			ts.load(trustStoreStream, trustpass);
+			logger.finest("TrustStore loaded");
+		} finally {
+			if(trustStoreStream!=null) {
+				trustStoreStream.close();
+				trustStoreStream = null;
+			}
+		}
+	
+		TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+			secureStore.getAlgorithm());
+		tmf.init(ts);
+		return tmf.getTrustManagers();
+	}
+
+	/**
+	 * Generates a SSLContext object that implements the specified secure 
+	 * socket protocol.
+	 */
+	public SSLContext getSSLContext(String protocol) 
+			throws NoSuchAlgorithmException {
+		return SSLContext.getInstance(protocol);
+	}
+        
+        public SSLContext getSSLContext(QuickServerConfig config) 
+			throws NoSuchAlgorithmException, NoSuchProviderException {
+            
+            if(config.getSecure().getSecureStore().getProvider()!=null) {
+                return SSLContext.getInstance(
+                        config.getSecure().getProtocol(),
+                        config.getSecure().getSecureStore().getProvider());
+            } else {
+                return SSLContext.getInstance(config.getSecure().getProtocol());
+            }
+		
+	}
+
+	/**
+	 * Generates a keystore object for the specified keystore type from 
+	 * the specified provider to be used for loading/storeing keys. 
+ 	 * @param type the type of keystore
+	 * @param provider the name of the provider if <code>null</code> any
+	 * provider package that implements this type of key may be given based
+	 * on the priority. 
+	 */
+	protected KeyStore getKeyStoreForKey(String type, String provider) 
+			throws KeyStoreException, NoSuchProviderException {
+		if(provider==null)
+			return KeyStore.getInstance(type);
+		return KeyStore.getInstance(type, provider);
+	}
+
+	/**
+	 * Generates a keystore object for the specified keystore type from 
+	 * the specified provider to be used for loading/storing trusted 
+	 * keys/certificates. 
+	 * @param type the type of keystore
+	 * @param provider the name of the provider if <code>null</code> any
+	 * provider package that implements this type of key may be given based
+	 * on the priority. 
+	 */
+	protected KeyStore getKeyStoreForTrust(String type, String provider) 
+			throws KeyStoreException, NoSuchProviderException {
+		if(provider==null)
+			return KeyStore.getInstance(type);
+		return KeyStore.getInstance(type, provider);
+	}
+
+	/**
+	 * Returns a SSLSocketFactory object to be used for creating SSLSockets. 
+	 */
+	public SSLSocketFactory getSocketFactory(SSLContext context) {
+		return context.getSocketFactory();
+	}
+
+	/**
+	 * Can be used to log details about the SSLServerSocket used to 
+	 * create a secure server [SSL/TLS]. This method can also be
+	 * overridden to change the enabled cipher suites and/or enabled protocols. 
+	 */
+	public void logSSLServerSocketInfo(SSLServerSocket sslServerSocket) {
+		if(logger.isLoggable(Level.FINEST)==false) {
+			return;
+		}
+		logger.finest("SecureServer Info: ClientAuth: "+
+			sslServerSocket.getNeedClientAuth());
+		logger.finest("SecureServer Info: ClientMode: "+
+			sslServerSocket.getUseClientMode());
+
+		String supportedSuites[] = sslServerSocket.getSupportedCipherSuites();
+		logger.finest("SecureServer Info: Supported Cipher Suites --------");
+		for(int i=0;i<supportedSuites.length;i++)
+			logger.finest(supportedSuites[i]);
+		logger.finest("---------------------------------------------------");
+
+		String enabledSuites[] = sslServerSocket.getEnabledCipherSuites();
+		logger.finest("SecureServer Info: Enabled Cipher Suites ----------");
+		for(int i=0;i<enabledSuites.length;i++)
+			logger.finest(enabledSuites[i]);
+		logger.finest("---------------------------------------------------");
+
+
+		String supportedProtocols[] = sslServerSocket.getSupportedProtocols();
+		logger.finest("SecureServer Info: Supported Protocols ------------");
+		for(int i=0;i<supportedProtocols.length;i++)
+			logger.finest(supportedProtocols[i]);
+		logger.finest("---------------------------------------------------");
+
+		String enabledProtocols[] = sslServerSocket.getEnabledProtocols();
+		logger.finest("SecureServer Info: Enabled Protocols --------------");
+		for(int i=0;i<enabledProtocols.length;i++)
+			logger.finest(enabledProtocols[i]);
+		logger.finest("---------------------------------------------------"); 
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/security/package.html b/quickserver/src/main/org/quickserver/security/package.html
new file mode 100644
index 0000000..4032aa5
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/security/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Classes for Security interfacing with QuickServer.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/sql/DBPoolUtil.java b/quickserver/src/main/org/quickserver/sql/DBPoolUtil.java
new file mode 100644
index 0000000..13f84e7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/sql/DBPoolUtil.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.sql;
+
+import org.quickserver.util.xmlreader.*;
+import java.sql.Connection;
+import java.util.*;
+/**
+ * This interface is used by {@link org.quickserver.net.server.QuickServer}
+ * load all db drivers.
+ * It is also used to get {@link java.sql.Connection} object by 
+ * the QuickServer when it encounters &lt;db-object-pool&gt;...&lt;/db-object-pool&gt;
+ * in its configuration file.
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public interface DBPoolUtil {
+	/**
+	 * QuickServer passes the an <code>iterator</code> containing
+	 * {@link org.quickserver.util.xmlreader.DatabaseConnectionConfig}
+	 * objects if any from the xml configuration it reads.
+	 */
+	public void setDatabaseConnections(Iterator iterator) throws Exception;
+
+	/**
+	 * This method will initilise and load all the db connection pools
+	 * that was set using {@link #setDatabaseConnections}
+	 */
+	public boolean initPool();
+
+	/**
+	 * This method will close all db connection pools
+	 * that was set using {@link #setDatabaseConnections}
+	 */
+	public boolean clean();
+
+	/**
+	 * Returns the {@link java.sql.Connection} object for the 
+	 * DatabaseConnection that is identified by id passed. If id passed
+	 * does not match with any connection loaded by this class it will
+	 * return <code>null</code>.
+	 */
+	public Connection getConnection(String id) throws Exception;
+}
diff --git a/quickserver/src/main/org/quickserver/sql/package.html b/quickserver/src/main/org/quickserver/sql/package.html
new file mode 100644
index 0000000..c1afdd0
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/sql/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Classes for SQL interfacing with QuickServer.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/swing/JFrameUtilities.java b/quickserver/src/main/org/quickserver/swing/JFrameUtilities.java
new file mode 100644
index 0000000..aa0bec2
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/swing/JFrameUtilities.java
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.swing;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.Window;
+import java.awt.Toolkit;
+import java.awt.Dimension;
+
+/**
+ * Swing utility class
+ */
+public class JFrameUtilities {
+
+	/**
+	 * Create a title string from the class name.
+	 */
+	public static String title(Object o) {
+		String t = o.getClass().toString();
+		// Remove the word "class":
+		if(t.indexOf("class") != -1)
+			t = t.substring(6);
+		if(t.lastIndexOf(".") != -1)
+			t = t.substring(t.lastIndexOf(".")+1);
+		return t;
+	}
+
+	public static void run(JFrame frame, int width, int height) {
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.setSize(width, height);
+		frame.setVisible(true);
+	}
+
+	public static void run(JApplet applet, int width, int height) {
+		JFrame frame = new JFrame(title(applet));
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.getContentPane().add(applet);
+		frame.setSize(width, height);
+		applet.init();
+		applet.start();
+		frame.setVisible(true);
+	}
+
+	public static void run(JPanel panel, int width, int height) {
+		JFrame frame = new JFrame(title(panel));
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.getContentPane().add(panel);
+		frame.setSize(width, height);
+		frame.setVisible(true);
+	}
+
+	public static void setNativeLookAndFeel() {
+		try {
+		  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+		} catch(Exception e) {
+		  System.out.println("Error setting native LAF: " + e);
+		}
+	}
+
+  public static void setJavaLookAndFeel() {
+    try {
+      UIManager.setLookAndFeel
+        (UIManager.getCrossPlatformLookAndFeelClassName());
+    } catch(Exception e) {
+      System.out.println("Error setting Java LAF: " + e);
+    }
+  }
+
+  public static void setMotifLookAndFeel() {
+    try {
+      UIManager.setLookAndFeel
+        ("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
+    } catch(Exception e) {
+      System.out.println("Error setting Motif LAF: " + e);
+    }
+  }
+
+  public static void centerWindow(Window window) {
+	  Dimension dim = window.getToolkit().getScreenSize();
+	  window.setLocation(dim.width/2 - window.getWidth()/2, 
+      dim.height/2 - window.getHeight()/2);
+  }
+}
diff --git a/quickserver/src/main/org/quickserver/swing/SensitiveInput.java b/quickserver/src/main/org/quickserver/swing/SensitiveInput.java
new file mode 100644
index 0000000..d9adac4
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/swing/SensitiveInput.java
@@ -0,0 +1,180 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.swing;
+
+import javax.swing.UIManager;
+import javax.swing.ImageIcon;
+import java.util.logging.*;
+
+/**
+ * Simple GUI frame that prompts for masked input.
+ * @author  Akshathkumar Shetty
+ */
+public class SensitiveInput extends javax.swing.JFrame {
+	private static Logger logger = Logger.getLogger(SensitiveInput.class.getName());
+
+	private javax.swing.JLabel inputLabel;
+	private javax.swing.JPanel jPanel1;
+	private javax.swing.JPasswordField passwordField;
+	private javax.swing.JButton submitButton;
+	private boolean gotInput = false;
+	private char input[] = null;
+
+	private ImageIcon logo = new ImageIcon(getClass().getResource("/icons/logo.gif"));
+
+    public SensitiveInput() {
+        this("Input sensitive property value..");
+    }
+
+	public SensitiveInput(String title) {
+		logger.finest("Loading swing gui..");
+		try {
+			UIManager.setLookAndFeel("net.sourceforge.mlf.metouia.MetouiaLookAndFeel");
+		} catch(Exception e) {
+			try {
+				UIManager.setLookAndFeel(
+					UIManager.getSystemLookAndFeelClassName());
+			} catch(Exception ee) {
+				//ignore
+			}
+		}
+        initComponents(title);
+    }
+    
+    private void initComponents(String title) {
+		setIconImage(logo.getImage());
+
+        inputLabel = new javax.swing.JLabel();
+        jPanel1 = new javax.swing.JPanel();
+        submitButton = new javax.swing.JButton();
+        passwordField = new javax.swing.JPasswordField();
+
+        getContentPane().setLayout(new java.awt.BorderLayout(1, 1));
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+        setTitle(title);
+        //setAlwaysOnTop(true);
+        setName("InputFrm");
+        setResizable(false);
+        addWindowListener(new java.awt.event.WindowAdapter() {
+            public void windowClosed(java.awt.event.WindowEvent evt) {
+                formWindowClosed(evt);
+            }
+        });
+
+        inputLabel.setText("  Param Name");
+        inputLabel.setName("inputLabel");
+        inputLabel.setPreferredSize(new java.awt.Dimension(250, 11));
+		javax.swing.JPanel lp = new javax.swing.JPanel();
+		lp.add(inputLabel);
+        getContentPane().add(lp, java.awt.BorderLayout.NORTH);
+
+        jPanel1.setLayout(new java.awt.BorderLayout(5, 2));
+
+        jPanel1.setBorder(new javax.swing.border.EmptyBorder(new java.awt.Insets(1, 1, 1, 1)));
+        submitButton.setText("Submit");
+        submitButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                submitButtonActionPerformed(evt);
+            }
+        });
+
+        jPanel1.add(submitButton, java.awt.BorderLayout.EAST);
+
+        passwordField.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                passwordFieldActionPerformed(evt);
+            }
+        });
+
+        jPanel1.add(passwordField, java.awt.BorderLayout.CENTER);
+
+        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
+
+        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
+        setBounds((screenSize.width-260)/2, (screenSize.height-70)/2, 260, 70);
+    }
+
+    private void formWindowClosed(java.awt.event.WindowEvent evt) {
+        input = null;
+        gotInput = true;
+        passwordField.setText("");
+        synchronized(this) {
+            notify();
+        }
+    }
+
+    private void passwordFieldActionPerformed(java.awt.event.ActionEvent evt) {
+       loadPassword();
+    }
+
+    private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
+       loadPassword();
+    }
+    
+    private void loadPassword() {
+        input = passwordField.getPassword();
+        gotInput = true;
+        passwordField.setText("");
+        synchronized(this) {
+            notify();
+        }
+    }
+    
+    public char[] getInput(String inputName) throws java.io.IOException {
+		try {	
+			gotInput = false;
+			input = null;
+			inputLabel.setText("<html><font style=\"font-size:10pt;color:#535353\"><b>"+inputName+"</b></font>");
+			inputLabel.setToolTipText("Value for "+inputName);
+			if(inputName.length()>=30) {
+				passwordField.setToolTipText("Value for "+inputName);
+			}
+			System.out.println("Opening gui to input sensitive property value: "+inputName);
+			setVisible(true);
+			try {
+				if(gotInput==false) {
+					synchronized(this) {
+						wait();
+					}
+				}
+				setVisible(false);
+			} catch(Exception e) {
+				logger.warning("Error: "+e);
+				throw e;
+			}
+			return input;
+		} catch(Exception e) {
+			logger.warning("Error opening GUI to input sensitive property value : "+e);
+			return org.quickserver.util.io.PasswordField.getPassword("Input property value for "+inputName+" : ");
+		}
+    }
+    
+    
+    public static void main(String args[]) throws Exception {
+       SensitiveInput si = new SensitiveInput();       
+       char pass[] = si.getInput("Some Password");
+       if(pass!=null)
+           logger.info("Some Password : "+new String(pass));
+       else
+           logger.info("Some Password : "+pass);
+       
+       pass = si.getInput("Other Password");
+        if(pass!=null)
+           logger.info("Other Password : "+new String(pass));
+        else
+           logger.info("Other Password : "+pass);
+    }    
+}
diff --git a/quickserver/src/main/org/quickserver/swing/package.html b/quickserver/src/main/org/quickserver/swing/package.html
new file mode 100644
index 0000000..06c119a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/swing/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Classes for GUI related work.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/Assertion.java b/quickserver/src/main/org/quickserver/util/Assertion.java
new file mode 100644
index 0000000..d1c12c2
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/Assertion.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util;
+
+/**
+ * Class to encapsulate Assertion and allows any back ports.
+ * @since 1.4.6
+ */
+public final class Assertion {
+	private static boolean enabled = false;
+
+	static {
+		assert enabled = true;
+	}
+
+	public static boolean isEnabled() {
+		return enabled;
+	}
+
+	public static void affirm(boolean test) { 
+		assert test;
+		//assertBackport(test);
+	}
+
+	public static void affirm(boolean test, String msg) { 
+		assert test : msg;
+		//assertBackport(test, msg);
+	}
+	
+	// Back Port versions
+	// Make sure a AssertionError class is defined that extends from Error
+	/*
+	private static void assertBackport(boolean test, String msg) { 
+		if(enabled && test==false) throw new AssertionError(msg);
+		//if(enabled && test==false) throw new RuntimeException("Assertion failed: "+msg); 
+	}
+
+	private static void assertBackport(boolean test) { 
+		if(enabled && test==false) throw new AssertionError();
+		//if(enabled && test==false) throw new RuntimeException("Assertion failed!"); 
+	}
+	*/
+}
diff --git a/quickserver/src/main/org/quickserver/util/ClassUtil.java b/quickserver/src/main/org/quickserver/util/ClassUtil.java
new file mode 100644
index 0000000..b8cb6d8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/ClassUtil.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util; 
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+import org.quickserver.util.io.*;
+import java.util.logging.*;
+
+/**
+ * A utility class to load class.
+ * @author Akshathkumar Shetty
+ * @since 1.3.2
+ */
+public class ClassUtil {
+	private static Logger logger = Logger.getLogger(ClassUtil.class.getName());
+
+	/**
+	 * Tries to load the classes present in the array 
+	 * passed has second parameter from
+	 * the ClassLoader passed has first parameter.
+	 * Returns the HashMap of all the classed successfully loaded.
+	 * @param classLoader ClassLoader used to find the class
+	 * @param classNames array of classes to load. 
+	 */
+	public static Map loadClass(ClassLoader classLoader, String classNames[]) 
+			throws Exception {
+		Class classloded = null;
+		HashMap classHash = new HashMap();
+		for(int i=0;i<classNames.length;i++) {
+			try	{
+				classloded = classLoader.loadClass(classNames[i]);	
+				classHash.put(classNames[i], classloded);
+			} catch(Exception e) {
+				logger.warning("Could not load classes : "+e);
+			}						
+		}
+		return classHash;
+	}
+
+	/**
+	 * Returns the ClassLoader to all the jars present in the 
+	 * dir passed has first parameter.
+	 * @param jarDir path to the directory containing the jars
+	 */
+	public static ClassLoader getClassLoaderFromJars(String jarDir) 
+			throws Exception {
+		logger.fine("Getting ClassLoader for jars in "+jarDir);
+		File file = new File(jarDir);
+		ArrayList list = new ArrayList();
+		
+		File jars[] =file.listFiles(new JarFileList());
+		for(int j=0; j<jars.length;j++){
+			list.add(jars[j].toURL());
+		}
+
+		Object array[] = list.toArray();
+		URL jarurl[] = new URL[array.length];
+		for(int i=0;i<array.length;i++) {
+			jarurl[i] = (URL)array[i];
+		}
+
+		URLClassLoader classLoader = URLClassLoader.newInstance(jarurl);
+		return classLoader;
+	}
+
+	/**
+	 * Returns the ClassLoader to a jar
+	 * @since 1.3.3
+	 */
+	public static ClassLoader getClassLoaderFromJar(String jarPath) 
+			throws Exception {
+		File file = new File(jarPath);
+		logger.fine("Getting ClassLoader for "+file.getCanonicalPath());		
+		URL jarurl[] = {file.toURL()};
+		URLClassLoader classLoader = URLClassLoader.newInstance(jarurl);
+		return classLoader;
+	}
+
+	/**
+	 * Returns the ClassLoader
+	 * @since 1.3.3
+	 */
+	public static ClassLoader getClassLoader(String path) throws Exception {
+		File file = new File(path);
+		if(file.canRead()==false) {
+			logger.warning("Could not read path: "+path);
+			return null;
+		}
+		if(file.isDirectory())
+			return getClassLoaderFromJars(path);
+		else
+			return getClassLoaderFromJar(path);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/FileChangeListener.java b/quickserver/src/main/org/quickserver/util/FileChangeListener.java
new file mode 100644
index 0000000..db9281c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/FileChangeListener.java
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.util;
+
+/**
+ * @since 1.4.8
+ * @author Akshathkumar Shetty
+ */
+public interface FileChangeListener {
+	public void changed();
+}
diff --git a/quickserver/src/main/org/quickserver/util/FileChangeMonitor.java b/quickserver/src/main/org/quickserver/util/FileChangeMonitor.java
new file mode 100644
index 0000000..09b8ac2
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/FileChangeMonitor.java
@@ -0,0 +1,148 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.util;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.*;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ * @since 1.4.8
+ */
+public class FileChangeMonitor implements Runnable {
+	private static final Logger logger = Logger.getLogger(FileChangeMonitor.class.getName());
+	private static int sleepInterval = 15000;//15sec
+
+	private static Map map = new ConcurrentHashMap();
+	private static Map lastModified = new ConcurrentHashMap();
+	private static volatile boolean flag;
+	private static volatile Thread thread = null;
+	private static FileChangeMonitor fcm = new FileChangeMonitor();
+
+	public synchronized static boolean addListener(String file, 
+			FileChangeListener fcl) {
+		if(file==null) return false;
+		File myFile = new File(file);
+		if(myFile.canRead()==false) return false;
+
+		List list = (List) map.get(file);
+		if(list==null) {
+			list = new ArrayList();
+			map.put(file, list);
+		}
+		return list.add(fcl);
+	}
+
+	public synchronized static boolean removeListener(String file, FileChangeListener fcl) {
+		if(file==null) return false;
+		File myFile = new File(file);
+		if(myFile.canRead()==false) return false;
+
+		List list = (List) map.get(file);
+		if(list==null) {
+			list = new ArrayList();
+			map.put(file, list);
+		}
+		return list.remove(fcl);
+	}
+
+	public static void startMonitoring() {
+		if(flag==true) return;
+
+		flag = true;
+		if(thread!=null) {
+			thread.interrupt();
+			thread = null;
+		}
+		thread = new Thread(fcm);
+		thread.setPriority(Thread.MIN_PRIORITY);
+		thread.setDaemon(true);
+		thread.start();
+	}
+
+	public static void stopMonitoring() {
+		if(flag==false) return;
+
+		flag = false;
+		if(thread!=null) {
+			thread.interrupt();
+		}
+		thread = null;
+	}
+
+	public void run() {
+		logger.info("Starting..");
+		Iterator iterator = null;
+		String key = null;
+		File file = null;
+		String lastModifiedTimeOld = null;
+		String lastModifiedTimeNew = null;
+		FileChangeListener fcl = null;
+		List fclList = null;
+		while(flag) {
+			Set set = map.keySet();
+			iterator = set.iterator();
+			while(flag && iterator.hasNext()) {
+				try {
+					key = (String) iterator.next();
+					file = new File(key);
+					lastModifiedTimeNew = ""+file.lastModified();
+
+					lastModifiedTimeOld = (String) lastModified.get(key);
+					if(lastModifiedTimeOld==null) {
+						lastModified.put(key, lastModifiedTimeNew);
+						continue;
+					}
+					if(lastModifiedTimeOld.equals(lastModifiedTimeNew)==false) {
+						lastModified.put(key, lastModifiedTimeNew);
+						fclList = (List) map.get(key);
+						for(int i=0; i< fclList.size(); i++) {
+							fcl = (FileChangeListener) fclList.get(i);
+							fcl.changed();
+						}
+					}					
+				} catch(Exception e) {
+					logger.log(Level.WARNING, "ERROR: "+e, e);
+				}
+				
+				try {
+					Thread.sleep(sleepInterval);
+				} catch(Exception e) {
+					logger.log(Level.WARNING, "ERROR: "+e, e);
+					break;
+				}
+			}
+		}
+		logger.info("Stopped.");
+	}
+
+	public static void main(String args[]) throws Exception {
+		FileChangeListener fcl = new FileChangeListener() {
+			public void changed() {
+				System.out.println("File changed: "+new Date());
+			}
+		};
+
+		
+		FileChangeMonitor.addListener("test.txt", fcl);
+		FileChangeMonitor.startMonitoring();
+	}
+	
+	static {
+		startMonitoring();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/JvmUtil.java b/quickserver/src/main/org/quickserver/util/JvmUtil.java
new file mode 100644
index 0000000..2a36345
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/JvmUtil.java
@@ -0,0 +1,275 @@
+package org.quickserver.util;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import java.io.*;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.management.MBeanServer;
+
+/**
+ * @version 2.0.0
+ * @author Akshathkumar Shetty
+ */
+public class JvmUtil {
+	private static final Logger logger = Logger.getLogger(JvmUtil.class.getName());
+
+	private static final int SECOND = 1000;
+	private static final int MINUTE = 60 * SECOND;
+	private static final int HOUR = 60 * MINUTE;
+	private static final int DAY = 24 * HOUR;
+	
+	public static String getUptime(Date lst) {
+		if(lst==null) {
+			return "N/A";
+		} 
+		
+		return getUptime(System.currentTimeMillis() - lst.getTime());
+	}
+	
+	public static String getUptime(long ms) {
+		StringBuilder sb = new StringBuilder();		
+		
+		if (ms > DAY) {
+			sb.append(ms / DAY).append("d ");
+			ms %= DAY;
+		}
+		if (ms > HOUR) {
+			sb.append(ms / HOUR).append("h ");
+			ms %= HOUR;
+		}
+		if (ms > MINUTE) {
+			sb.append(ms / MINUTE).append("m ");
+			ms %= MINUTE;
+		}
+		if (ms > SECOND) {
+			sb.append(ms / SECOND).append("s");
+			ms %= SECOND;
+		}
+		//sb.append(ms).append("ms");
+
+		
+		return sb.toString();
+	}
+	
+	public static boolean dumpHeap(String fileName, boolean live) {
+		MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+		try {
+			logger.fine("Taking heap dump..");
+			HotSpotDiagnosticMXBean hotspotMBean =
+				ManagementFactory.newPlatformMXBeanProxy(server,
+				"com.sun.management:type=HotSpotDiagnostic",
+				HotSpotDiagnosticMXBean.class);
+
+			hotspotMBean.dumpHeap(fileName, live);
+
+			logger.fine("Heap dump done");
+			return true;
+		} catch (Throwable e) {
+			logger.log(Level.WARNING, "Error: " + e, e);
+		}
+
+		return false;
+	}
+	
+	public static boolean dumpJmapHisto(String fileName) {
+		String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();  
+		int pi = nameOfRunningVM.indexOf('@');  
+		String pid = nameOfRunningVM.substring(0, pi);  
+		String command = "jmap -histo "+pid;
+		
+		Process p = null;
+		try {
+			logger.log(Level.INFO, "Command executing : {0}", command);
+			p = Runtime.getRuntime().exec(command);
+			dumpProcessOutputToFile(p, fileName);
+			logger.log(Level.INFO, "Command executed : {0}", command);
+			
+			return true;
+		} catch (IOException ex) {
+			logger.log(Level.WARNING, "Error: "+ex, ex);
+		}
+		return false;
+	}
+	
+	public static boolean dumpJmapHistoToLog() {
+		String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();  
+		int pi = nameOfRunningVM.indexOf('@');  
+		String pid = nameOfRunningVM.substring(0, pi);  
+		String command = "jmap -histo "+pid;
+		
+		Process p = null;
+		try {
+			logger.log(Level.INFO, "Command executing : {0}", command);
+			p = Runtime.getRuntime().exec(command);
+			dumpProcessOutputToLog(p);
+			logger.log(Level.INFO, "Command executed : {0}", command);
+			
+			return true;
+		} catch (IOException ex) {
+			logger.log(Level.WARNING, "Error: "+ex, ex);
+		}
+		return false;
+	}
+
+	public static boolean threadDump(String fileName) {
+		ThreadInfo[] threadsInfo = ManagementFactory.getThreadMXBean(
+			).dumpAllThreads(true, true);
+		dumpToFile(threadsInfo, fileName);
+		
+		return true;
+	}
+	
+	public static boolean threadDumpToLog() {
+		ThreadInfo[] threadsInfo = ManagementFactory.getThreadMXBean(
+			).dumpAllThreads(true, true);
+		dumpToLog(threadsInfo);
+		
+		return true;
+	}
+	
+	public static boolean dumpJStack(String fileName) {
+		String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();  
+		int pi = nameOfRunningVM.indexOf('@');  
+		String pid = nameOfRunningVM.substring(0, pi);  
+		String command = "jstack -l "+pid;
+		
+		Process p = null;
+		try {
+			logger.log(Level.INFO, "Command executing : {0}", command);
+			p = Runtime.getRuntime().exec(command);
+			dumpProcessOutputToFile(p, fileName);
+			logger.log(Level.INFO, "Command executed : {0}", command);
+			return true;
+		} catch (IOException ex) {
+			logger.log(Level.WARNING, "Error: "+ex, ex);
+		}
+		return false;
+	}
+	
+	public static boolean dumpJStackToLog() {
+		String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();  
+		int pi = nameOfRunningVM.indexOf('@');  
+		String pid = nameOfRunningVM.substring(0, pi);  
+		String command = "jstack -l "+pid;
+		
+		Process p = null;
+		try {
+			logger.log(Level.INFO, "Command executing : {0}", command);
+			p = Runtime.getRuntime().exec(command);
+			dumpProcessOutputToLog(p);
+			logger.log(Level.INFO, "Command executed : {0}", command);
+			return true;
+		} catch (IOException ex) {
+			logger.log(Level.WARNING, "Error: "+ex, ex);
+		}
+		return false;
+	}
+	
+	public static void dumpProcessOutputToFile(Process p, String fileName) {
+		BufferedWriter writer = null;
+		BufferedReader reader = null;
+		try {
+			logger.log(Level.INFO, "Start of ProcessOutput to file {0}", fileName);
+			String line = null;			
+			reader = new BufferedReader(
+				new InputStreamReader(p.getInputStream()));
+			writer = new BufferedWriter(new FileWriter(fileName));
+			
+			while ((line = reader.readLine()) != null){
+				writer.write(line);
+				writer.write("\r\n");				
+			}
+			writer.flush();
+			logger.log(Level.INFO, "End of ProcessOutput to file {0}", fileName);
+		} catch(Exception e){
+			logger.log(Level.WARNING, "Exception: " + e, e);
+		} finally {
+			try {
+				if (null != reader) {
+					reader.close();
+				}
+			} catch (Exception e) {
+				logger.log(Level.WARNING, "Exception: " + e, e);
+			}
+			
+			try {
+				if (null != writer) {
+					writer.close();
+				}
+			} catch (Exception e) {
+				logger.log(Level.WARNING, "Exception: " + e, e);
+			}
+			
+			if(p!=null) {
+				p.destroy();
+			}
+		}
+	}
+	
+	public static void dumpProcessOutputToLog(Process p) {
+		BufferedReader reader = null;
+		try {
+			logger.log(Level.INFO, "Start of ProcessOutput to log ");
+			String line = null;			
+			reader = new BufferedReader(
+				new InputStreamReader(p.getInputStream()));
+			
+			while ((line = reader.readLine()) != null){
+				logger.info(line);			
+			}
+			logger.log(Level.INFO, "End of ProcessOutput to log");
+		} catch(Exception e){
+			logger.log(Level.WARNING, "Exception: " + e, e);
+		} finally {
+			try {
+				if (null != reader) {
+					reader.close();
+				}
+			} catch (Exception e) {
+				logger.log(Level.WARNING, "Exception: " + e, e);
+			}
+			
+			if(p!=null) {
+				p.destroy();
+			}
+		}
+	}
+
+	public static void dumpToFile(ThreadInfo[] threadsInfo, String fileName) {
+		File file = null;
+		BufferedWriter writer = null;
+		try {
+			logger.log(Level.INFO, "Start of Thread dump to file {0}", fileName);
+			file = new File(fileName);
+			writer = new BufferedWriter(new FileWriter(file));
+			
+			for (ThreadInfo t : threadsInfo) {
+				writer.write(t.toString());
+			}
+			
+			writer.flush();
+			logger.log(Level.INFO, "End of Thread dump to file {0}", fileName);
+		} catch (IOException ioe) {
+			logger.log(Level.WARNING, "IOException: " + ioe, ioe);
+		} finally {
+			try {
+				if (null != writer) {
+					writer.close();
+				}
+			} catch (Exception e) {
+				logger.log(Level.WARNING, "Exception: " + e, e);
+			}
+		}
+	}
+	
+	public static void dumpToLog(ThreadInfo[] threadsInfo) {
+		logger.info("Start of Thread dump to log");
+		for (ThreadInfo t : threadsInfo) {
+			logger.info(t.toString());
+		}
+		logger.info("End of Thread dump to log");
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/MyString.java b/quickserver/src/main/org/quickserver/util/MyString.java
new file mode 100644
index 0000000..e092e33
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/MyString.java
@@ -0,0 +1,276 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util; 
+
+import java.io.*;
+
+/**
+ * Just a simple String utility class.
+ * @author Akshathkumar Shetty
+ */
+public class MyString {
+	private static Runtime runtime = Runtime.getRuntime();
+	private static java.text.DecimalFormat doublePrcNum = 
+		new java.text.DecimalFormat("#,##0.00");
+
+	public static String replace(String source, String key, 
+		String with) {
+		if(source==null)
+			throw new NullPointerException("Parameter -> source was null");
+		if(key==null)
+			throw new NullPointerException("Parameter -> key was null");
+		if(with==null)
+			throw new NullPointerException("Parameter -> with was null");
+		
+		int start=0;
+		int end=0;
+		String result="";
+		
+		start=source.indexOf(key);
+		end=start+key.length();
+		
+		if(start==-1)
+			return null;
+
+		result=source.substring(0,start);
+		result+=with;
+		result+=source.substring(end,source.length());
+		
+		return result;
+	}
+
+	public static String replaceAll(String source, String key, 
+		String with) {
+		if(source==null)
+			throw new NullPointerException("Parameter -> source was null");
+		if(key==null)
+			throw new NullPointerException("Parameter -> key was null");
+		if(with==null)
+			throw new NullPointerException("Parameter -> with was null");
+		
+		String temp="";
+		
+		while(true)	{
+			temp="";
+			temp=replace(source,key,with);
+			if(temp==null)
+				break;
+			else
+				source=temp;
+		}
+
+		return source;
+	}
+
+	
+	public static int replaceCount(String source, 
+		String key) {
+		if(source==null)
+			throw new NullPointerException("Parameter -> source was null");
+		if(key==null)
+			throw new NullPointerException("Parameter -> key was null");
+
+		int count=0;
+		String result="";
+		String temp="";
+		
+		result=source;
+		while(true)	{
+			temp="";
+			temp=replace(result,key,"");
+			if(temp==null) {
+				break;
+			}
+			else {
+				result=temp;
+				count++;
+			}
+		}
+
+		return count;
+	}
+	
+	public static String replaceAllNo(String source, 
+		String with) {
+		if(source==null)
+			throw new NullPointerException("One of parameter -> source was null");
+		if(with==null)
+			throw new NullPointerException("One of parameter -> with was null");
+		
+		for(int i=0;i<10;i++)
+			source=replaceAll(source,""+i,with);
+
+		return source;
+	}
+	
+
+	public static String removeAllHtmlSpChar(String source) {
+		String temp = source;
+		temp = replaceAll(temp,"&nbsp;"," ");
+		temp = replaceAll(temp,"&lt;","<");
+		temp = replaceAll(temp,"&gt;",">");
+		temp = replaceAll(temp,"&amp;","&");
+		temp = replaceAll(temp,"&quot;","\"");
+		return temp;
+	}
+
+	///////// tags ////////////
+	// needs more work
+	public static String replaceTags(String source, String with) {
+		if(source==null)
+			throw new NullPointerException("One of parameter -> source was null");
+		if(with==null)
+			throw new NullPointerException("One of parameter -> with was null");
+
+		int start=0;
+		int end=0;
+		int error=0;
+		String result="";
+		
+		start=source.indexOf("<");
+		end=source.indexOf(">",start+1);
+		
+		error=source.indexOf("<",start+1);
+		if(error!=-1 && error<end)
+			throw new IllegalArgumentException("&lt; found before &gt;");
+
+		if(start==-1 || end==-1)
+			return null;
+
+		result=source.substring(0,start);
+		result+=with;
+		result+=source.substring(end+1,source.length());
+
+		return result;
+	}
+
+	public static String replaceAllTags(String source, String with) {
+		if(source==null)
+			throw new NullPointerException("One of parameter -> source was null");
+		if(with==null)
+			throw new NullPointerException("One of parameter -> with was null");
+			
+		String temp="";
+		
+		while(true)	{
+			temp="";
+			temp=replaceTags(source,with);
+			if(temp==null)
+				break;
+			else
+				source=temp;
+		}
+
+		return source;
+	}
+	
+	/**
+	 * Returns String form of an exception.
+	 * @since 1.3.3
+	 */
+	public static String getStackTrace(Throwable e) {
+		StringWriter writer = new StringWriter(1024);
+		e.printStackTrace(new PrintWriter(writer));
+		return writer.toString();
+	}
+
+	/**
+	 * Returns formatted memory size.
+	 * @since 1.4.5
+	 */
+	public static String getMemInfo(float bytes) {
+		if(bytes<1024) {
+			return doublePrcNum.format(bytes)+" B";
+		}
+
+		bytes = bytes/1024;
+		if(bytes<1024) {
+			return doublePrcNum.format(bytes)+" KB";
+		}
+
+		bytes = bytes/1024;
+		if(bytes<1024) {
+			return doublePrcNum.format(bytes)+" MB";
+		}
+
+		bytes = bytes/1024;
+		return doublePrcNum.format(bytes)+" GB";
+	}
+
+	/**
+	 * Returns System information.
+	 * @since 1.4.5
+	 */
+	public static String getSystemInfo(String version) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("---- System Info Start ---");
+		sb.append("\r\n");
+
+		sb.append("QuickServer v");
+		sb.append(version);
+		sb.append(" is being used.");
+		sb.append("\r\n");
+
+		sb.append("Java VM v");
+		sb.append(System.getProperty("java.version"));
+		sb.append(" is being used.");	
+		sb.append("\r\n");
+
+		sb.append("Operating System: ");
+		sb.append(System.getProperty("os.name"));
+		sb.append(" ");
+		sb.append(System.getProperty("os.version"));
+		sb.append("\r\n");
+
+		sb.append("Current working directory: ");
+		sb.append(System.getProperty("user.dir"));
+		sb.append("\r\n");
+
+		sb.append("Class/s loaded from: ");
+		sb.append(new MyString().getClass().getProtectionDomain().getCodeSource().getLocation());
+		sb.append("\r\n");
+
+		sb.append("Total memory currently available: ");
+		sb.append(MyString.getMemInfo(runtime.totalMemory()));
+		sb.append("\r\n");
+		sb.append("Memory currently in use: ");
+		sb.append(MyString.getMemInfo(runtime.totalMemory()-runtime.freeMemory()));
+		sb.append("\r\n");
+		sb.append("Maximum memory available: ");
+		sb.append(MyString.getMemInfo(runtime.maxMemory()));
+		sb.append("\r\n");
+		
+
+		sb.append("---- System Info End ---");
+
+		return sb.toString();
+	}
+
+	public static String alignRight(String data, int len) {
+		StringBuilder sb = new StringBuilder(data);
+		while(sb.length()<len) {
+			sb.insert(0, ' ');
+		}
+		return sb.toString();
+	}
+
+	public static String alignLeft(String data, int len) {
+		StringBuilder sb = new StringBuilder(data);
+		while(sb.length()<len) {
+			sb.append( ' ');
+		}
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/TextFile.java b/quickserver/src/main/org/quickserver/util/TextFile.java
new file mode 100644
index 0000000..3a473e9
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/TextFile.java
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Static functions for reading and writing text files as
+ * a single string, and treating a file as an ArrayList.
+ */
+public class TextFile extends ArrayList {
+
+	/**
+	 * Read file as single string.
+	 */
+	public static String read(String fileName) throws IOException {
+		File file = new File(fileName);
+		return read(file);
+	}
+
+	/**
+	 * Read file as single string.
+	 */
+	public static String read(File fileName) throws IOException {
+		StringBuilder sb = new StringBuilder();
+		BufferedInputStream bis = null;
+		try {
+			bis = new BufferedInputStream(new FileInputStream(fileName));
+			byte buffer[] = new byte[1024];
+			int len = 0;
+
+			do {
+				len = bis.read(buffer, 0, buffer.length);
+				if(len==-1) break;
+				sb.append(new String(buffer,0,len));
+			} while(true);
+		} finally {
+			if(bis!=null) bis.close();
+		}		
+		return sb.toString();
+	}
+
+	/**
+	 * Write file from a single string.
+	 */
+	public static void write(String fileName, String text) throws IOException {
+		File file = new File(fileName);
+		write(file, text);
+	}
+
+	/**
+	 * Write file from a single string.
+	 */
+	public static void write(File file, String text) throws IOException {
+		write(file, text, false);
+	}
+		
+	public static void write(File file, String text, boolean append) throws IOException {
+		PrintWriter out = null;
+		try {
+			out = new PrintWriter(
+				new BufferedWriter(new FileWriter(file, append)));
+			out.print(text);	
+		} finally {
+			if(out!=null) out.close();
+		}
+	}
+
+	public TextFile(String fileName) throws IOException {
+		super(Arrays.asList(read(fileName).split("\n")));
+	}
+
+	/**
+	 * Write file from a single string.
+	 */
+	public void write(String fileName) throws IOException {
+		PrintWriter out = null;
+		try {
+			out = new PrintWriter(
+				new BufferedWriter(new FileWriter(fileName)));
+			for(int i = 0; i < size(); i++)
+				out.println(get(i));	
+		} finally {
+			if(out!=null) out.close();
+		}		
+	}
+	
+	/**
+	 * Read file as single string.
+	 */
+	public static String read(String fileName, Object parent)
+			throws IOException {
+		StringBuilder sb = new StringBuilder();
+		InputStream is = null;
+		BufferedInputStream bis = null;
+		try {
+			is = parent.getClass().getResourceAsStream(fileName);
+			bis = new BufferedInputStream(is);
+			byte buffer[] = new byte[1024];
+			int len = 0;
+			do {
+				len = bis.read(buffer, 0, buffer.length);
+				if(len==-1) break;
+				sb.append(new String(buffer,0,len));
+			} while(true);
+		} finally {
+			if(bis!=null) bis.close();
+			if(is!=null) is.close();
+		}
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/ByteBufferInputStream.java b/quickserver/src/main/org/quickserver/util/io/ByteBufferInputStream.java
new file mode 100644
index 0000000..223cef7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/ByteBufferInputStream.java
@@ -0,0 +1,423 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.io;
+
+import java.io.*;
+import java.nio.*;
+import java.nio.charset.*;
+import java.util.*;
+import org.quickserver.net.server.ClientHandler;
+import java.util.logging.*;
+import org.quickserver.util.*;
+
+/**
+ * This is an InputStream constructed from list of ByteBuffers. This is
+ * used in non-blocking mode.
+ * @since 1.4.5
+ * @author Akshathkumar Shetty
+ */
+public class ByteBufferInputStream extends InputStream {
+	private static final Logger logger = Logger.getLogger(ByteBufferInputStream.class.getName());
+	static {
+		logger.setLevel(Level.INFO);
+	}
+
+	/**
+	 * Sets the debug flag. 
+	 */
+	public static void setDebug(boolean flag) {
+		if(flag) 
+			logger.setLevel(Level.FINEST);
+		else
+			logger.setLevel(Level.INFO);
+	}
+
+	/**
+	 * @since 1.4.7
+	 */
+	public static boolean isLoggable(Level level) {
+		return logger.isLoggable(level);
+	}
+
+
+	private final ArrayList bufferList;
+	private ClientHandler handler;
+
+	private CharsetDecoder decoder;
+	private CharsetEncoder encoder;
+	private StringBuilder strings;
+
+	private int pos = 0;
+	private int index = -1;
+	private int start = 0;
+	private boolean lookingForLineFeed = false;
+
+	public ByteBufferInputStream(ArrayList bufferList, ClientHandler handler, String charset) {
+		if(bufferList==null || handler==null)
+			throw new IllegalArgumentException("ArrayList or ClientHandler was null.");
+		this.bufferList = bufferList;
+		this.handler = handler;
+		Charset _charset = Charset.forName(charset);
+		decoder = _charset.newDecoder();
+		encoder = _charset.newEncoder();
+		strings = new StringBuilder();
+	}
+
+	public synchronized int availableOnlyInByteBuffer() {
+		int count = 0;
+		ByteBuffer byteBuffer = null;
+		int size = bufferList.size();
+		for(int c=0;c<size;c++) {
+			byteBuffer = (ByteBuffer)bufferList.get(c);
+			count += byteBuffer.remaining();
+		}
+		logger.finest("count: "+count);
+		return count;
+	}
+
+	public synchronized int available() {
+		int count = 0;
+		ByteBuffer byteBuffer = null;
+
+		if(lookingForLineFeed) {
+			char c = '\0';
+			if(strings.length()!=0) {
+				c = strings.charAt(0);			
+				if(c=='\n') {				
+					strings.deleteCharAt(0);
+					lookingForLineFeed = false;
+				}
+			} else {
+				while(!bufferList.isEmpty()) {
+					byteBuffer = (ByteBuffer)bufferList.get(0);
+					if(byteBuffer.remaining()==0) {
+						returnBufferBack();
+						continue;
+					}
+					
+					int p = byteBuffer.position();
+					c = (char) byteBuffer.get(p);
+					if(c=='\n') {
+						byteBuffer.get();//move position
+						lookingForLineFeed = false;
+					}
+					break;
+				}//end of while
+			}
+		}
+		count += strings.length();
+		
+		
+		int size = bufferList.size();
+		for(int c=0;c<size;c++) {
+			byteBuffer = (ByteBuffer)bufferList.get(c);
+			count += byteBuffer.remaining();
+		}
+		//logger.finest("count: "+count);
+		return count;
+	}
+
+	public synchronized void close() throws IOException {
+		if(handler.getSocketChannel()!=null) handler.getSocketChannel().close();
+		//handler.closeConnection();
+	}
+
+	public boolean markSupported() {
+		return false;
+	}
+
+	public synchronized int read() throws IOException {
+		handler.isConnected();
+		if(strings.length()!=0) {
+			addStringsBackAsBuffer();
+		}
+
+		if(bufferList.isEmpty()) {
+			try {
+				wait();
+			} catch(InterruptedException ie) {
+				logger.warning("InterruptedException: "+ie);
+				return -1;
+			}			
+			if(bufferList.isEmpty()) return -1;
+		}
+		ByteBuffer byteBuffer = null;
+		while(!bufferList.isEmpty()) {
+			byteBuffer = (ByteBuffer)bufferList.get(0);
+			if(byteBuffer.remaining()==0) {
+				returnBufferBack();
+				continue;
+			}
+
+			if(lookingForLineFeed) {
+				int lflfChar = (int) byteBuffer.get();
+				lookingForLineFeed = false;
+				if(lflfChar==(int)'\n') {
+					continue;
+				} else {
+					return lflfChar;
+				}
+			} else {
+				return (int) byteBuffer.get();
+			}
+		}
+		return read();
+	}
+
+	public int read(byte[] b) throws IOException {
+		return read(b, 0, b.length);
+	}
+
+	public synchronized int read(byte[] b, int off, int len) throws IOException {
+		handler.isConnected();
+		if(strings.length()!=0) {
+			addStringsBackAsBuffer();
+		}
+
+		if(bufferList.isEmpty()) {
+			try {
+				wait();
+			} catch(InterruptedException ie) {
+				logger.warning("InterruptedException: "+ie);
+				//ie.printStackTrace();
+				return -1;
+			}
+			if(bufferList.isEmpty()) return -1;
+		}
+		ByteBuffer byteBuffer = null;
+		int read = 0;
+		int remaining = 0;
+		int toRead = len;
+		do {
+			byteBuffer = (ByteBuffer) bufferList.get(0);
+			remaining = byteBuffer.remaining();
+
+			if(remaining==0) {
+				returnBufferBack();
+				continue;
+			}			
+
+			if(lookingForLineFeed) {
+				int p = byteBuffer.position();
+				byte lflfChar = byteBuffer.get(p);		
+				lookingForLineFeed = false;
+
+				if(lflfChar==(byte)'\n') {
+					byteBuffer.get();//move position
+					continue;
+				}
+			}
+
+			if(remaining < toRead) {
+				byteBuffer.get(b, off, remaining);
+				off = off + remaining;
+
+				read = read + remaining;
+				toRead = toRead - remaining;				
+			} else {
+				byteBuffer.get(b, off, toRead);
+				read = read + toRead;
+				return read;
+			}
+		} while(!bufferList.isEmpty());
+		return read;
+	}
+
+	public long skip(long n) throws IOException {
+		if(n<0) return 0;
+		int s=0;
+		for(;s<n;s++) {
+			if(read()==-1) break;
+		}
+		return s;
+	}
+
+	private void addStringsBackAsBuffer() {
+		try {
+			ByteBuffer borrowBuffer = null;
+			ByteBuffer bb = encoder.encode(CharBuffer.wrap(strings));
+			strings.setLength(0);
+			do {
+				if(borrowBuffer==null) {
+					borrowBuffer = (ByteBuffer) 
+							handler.getServer().getByteBufferPool().borrowObject();
+				}
+
+				borrowBuffer.put(bb.get());
+
+				if(borrowBuffer.hasRemaining()==false) {
+					borrowBuffer.flip();
+					bufferList.add(0, borrowBuffer);
+					borrowBuffer = null;
+				}
+			} while(bb.hasRemaining());
+
+			if(borrowBuffer!=null) {
+				borrowBuffer.flip();
+				bufferList.add(0, borrowBuffer);
+			}
+		} catch(Exception er) {
+			logger.warning("Error : "+er);
+		}
+		start = 0;
+		index = -1;
+		pos = 0;
+	}
+
+	private void returnBufferBack() {
+		returnBufferBack((ByteBuffer)bufferList.remove(0));
+	}
+
+	private void returnBufferBack(ByteBuffer byteBuffer) {
+		try {
+			handler.getServer().getByteBufferPool().returnObject(byteBuffer);	
+		} catch(Exception er) {
+			logger.warning("Error while returning ByteBuffer to pool: "+er);
+		}
+	}
+
+	//-- extra helpers
+	/**
+	 * Checks if a line of String is ready to be read. 
+	 * @throws IOException if connection is lost or closed.
+	 */
+	public synchronized boolean isLineReady() throws IOException {
+		handler.isConnected();
+		boolean result = false;
+
+		result = isLineReadyForStringBuilder();
+
+		if(result==true || bufferList.isEmpty()) {
+			if(logger.isLoggable(Level.FINEST))
+				logger.finest("result: "+result);
+			return result;
+		}
+
+		ByteBuffer byteBuffer = null;
+		CharBuffer charBuffer = null;
+		
+		while(result==false && !bufferList.isEmpty()) {
+			byteBuffer = (ByteBuffer)bufferList.get(0);
+			if(byteBuffer.remaining()==0) {
+				returnBufferBack();
+				continue;
+			}
+			charBuffer = decoder.decode(byteBuffer);
+			if(charBuffer==null) {
+				returnBufferBack();
+				continue;
+			}
+
+			strings.append(charBuffer);
+			returnBufferBack();
+
+			result = isLineReadyForStringBuilder();
+		}//end of while
+
+		if(logger.isLoggable(Level.FINEST))
+			logger.finest("result: "+result);
+		return result;
+	}
+
+	private boolean isLineReadyForStringBuilder() {
+		if(index!=-1) return true;
+
+		int stringsLength = strings.length();
+
+		while(pos < stringsLength) {
+			char c = strings.charAt(pos);
+
+			if(c=='\n') {
+				if(lookingForLineFeed) {
+					strings.deleteCharAt(0);
+					stringsLength--;
+					lookingForLineFeed = false;
+					continue;
+				} else {
+					index = pos;
+					pos++;
+					return true;
+				}				
+			} if(c=='\r') {
+				index = pos;
+				lookingForLineFeed = true;
+				pos++;
+				return true;
+			} else {
+				pos++;
+				lookingForLineFeed = false;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Reads a line of String if ready. If line is not yet ready this will
+	 * block. To find out if the line is ready use <code>isLineReady()</code>
+	 * @see #isLineReady() 
+	 */
+	public synchronized String readLine() throws IOException {
+		if(index==-1) {
+			while(isLineReady()==false) {
+				try {
+					wait();
+				} catch(InterruptedException ie) {
+					logger.warning("InterruptedException: "+ie);
+					return null;
+				}
+			}
+		}
+
+		int stringsLength = strings.length();
+
+		Assertion.affirm(index <= stringsLength);
+		String data = strings.substring(start,index);
+		
+		if(pos < stringsLength)
+			strings.delete(0, pos);
+		else 
+			strings.setLength(0);
+
+		start = 0;
+		pos = start;
+		index = -1;
+		return data;
+	}
+
+	public void dumpContent() {
+		if(logger.isLoggable(Level.FINE)==false) {
+			//logger.warning("Can't precede. Logging level FINE is not loggable! ");
+			return;
+		}
+
+		logger.fine("Start of dump..");
+		synchronized(bufferList) {
+			int size = bufferList.size();
+			ByteBuffer byteBuffer = null;
+			if(strings.length()!=0) {
+				logger.fine("[decoded] "+strings);
+			}
+			for(int c=0;c<size;c++) {
+				byteBuffer = (ByteBuffer)bufferList.get(c);
+				try {
+					logger.fine("["+c+"] "+decoder.decode(byteBuffer.duplicate()));	
+				} catch(Exception e) {
+					logger.fine("["+c+"] Error : "+e);
+				}				
+			}
+		}
+		logger.fine("End of dump..");
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/ByteBufferOutputStream.java b/quickserver/src/main/org/quickserver/util/io/ByteBufferOutputStream.java
new file mode 100644
index 0000000..b5e6a0a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/ByteBufferOutputStream.java
@@ -0,0 +1,280 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.io;
+
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+import org.apache.commons.pool.ObjectPool;
+import org.quickserver.net.server.ClientHandler;
+import org.quickserver.net.server.impl.NonBlockingClientHandler;
+import java.util.logging.*;
+
+/**
+ * This is an OutputStream constructed from list of ByteBuffers. This is
+ * used in non-blocking mode.
+ * @since 1.4.5
+ * @author Akshathkumar Shetty
+ */
+public class ByteBufferOutputStream extends OutputStream {
+	private static Logger logger = Logger.getLogger(ByteBufferOutputStream.class.getName());
+	static {
+		logger.setLevel(Level.INFO);
+	}
+
+	/**
+	 * Sets the debug flag. When debug is set to <code>true</code>
+	 * one can see number of bytes written.
+	 */
+	public static void setDebug(boolean flag) {
+		if(flag) 
+			logger.setLevel(Level.FINEST);
+		else
+			logger.setLevel(Level.INFO);
+	}
+	
+	/**
+	 * @since 1.4.7
+	 */
+	public static boolean isLoggable(Level level) {
+		return logger.isLoggable(level);
+	}
+
+	private ArrayList bufferList;
+	private ByteBuffer lastByteBuffer = null;
+	private NonBlockingClientHandler handler;
+	private Object toNotify = null;
+	private ArrayList encryptedBufferList;
+
+	/**
+	 * Creates a new ByteBufferOutputStream using the given list as its base
+	 * and ClientHandler as the target channel.
+	 */
+	public ByteBufferOutputStream(ArrayList bufferList, ClientHandler handler) {
+		if(bufferList==null || handler==null)
+			throw new IllegalArgumentException("ArrayList or ClientHandler was null.");
+		this.bufferList = bufferList;
+		this.handler = (NonBlockingClientHandler) handler;
+		if(handler.isSecure()) {
+			encryptedBufferList = new ArrayList();
+		}
+	}
+
+	public synchronized void close() {
+		if(lastByteBuffer!=null) {
+			returnBufferBack(lastByteBuffer);
+		}
+	}
+
+	public void flush() throws IOException {
+		if(bufferList.size()!=0 || lastByteBuffer!=null) {
+			handler.registerWrite();
+		} else {
+			return;
+		}
+		
+		while(bufferList.size()>=5) {
+			handler.waitTillFullyWritten();		
+		}
+	}
+
+	public synchronized void write(int b) throws IOException {
+		handler.isConnected();
+		ByteBuffer byteBuffer = null;
+		if(bufferList.size()!=0) {
+			byteBuffer = (ByteBuffer) bufferList.remove(bufferList.size()-1);
+			if(byteBuffer.remaining()==0) {
+				bufferList.add(byteBuffer);
+				byteBuffer = null;
+			}
+		}
+		try {			
+			if(byteBuffer==null) {
+				byteBuffer = (ByteBuffer) handler.getServer().getByteBufferPool().borrowObject();
+			}
+		} catch(Exception e) {
+			logger.warning("Could not borrow ByteBufer from pool: "+e);
+			throw new IOException(e.toString());
+		}
+		byteBuffer.put((byte)b);
+		bufferList.add(byteBuffer);
+	}
+
+	public void write(byte[] b) throws IOException {
+		write(b, 0, b.length);
+	}
+
+	public synchronized void write(byte[] b, int off, int len) throws IOException {
+		if(len==0) {
+			return;
+		}
+
+		handler.isConnected();
+		ByteBuffer byteBuffer = null;
+		int remaining = 0;
+		int toWrite = len;
+
+		if(toWrite!=0 && bufferList.size()!=0) {
+			byteBuffer = (ByteBuffer) bufferList.remove(bufferList.size()-1);
+			if(byteBuffer.remaining()==0) {
+				bufferList.add(byteBuffer);
+				byteBuffer = null;
+			}
+		}
+
+		while(toWrite!=0) {
+			try {
+				if(byteBuffer==null) {
+					byteBuffer = (ByteBuffer) 
+						handler.getServer().getByteBufferPool().borrowObject();	
+				}
+			} catch(Exception e) {
+				logger.warning("Could not borrow ByteBufer from pool: "+e);
+				throw new IOException(e.toString());
+			}
+
+			remaining = byteBuffer.remaining();
+			if(remaining < toWrite) {
+				byteBuffer.put(b, off, remaining);
+				off = off + remaining;
+
+				toWrite = toWrite - remaining;				
+			} else {
+				byteBuffer.put(b, off, toWrite);
+				toWrite=0;
+			}
+			bufferList.add(byteBuffer);
+			byteBuffer = null;
+		}
+	}
+
+	public synchronized boolean writeAllByteBuffer() throws IOException {
+		if(lastByteBuffer!=null) {
+			writeLastByteBuffer();
+			if(lastByteBuffer!=null) return false;
+		}
+		
+		ByteBuffer dest = null;
+		while(bufferList.size()!=0) {
+			dest = (ByteBuffer) bufferList.remove(0);
+			if(handler.isSecure()==false) {
+				lastByteBuffer = dest;
+				lastByteBuffer.flip();
+				writeLastByteBuffer();						
+				if(lastByteBuffer != null) return false;
+			} else {
+				lastByteBuffer = handler.encrypt(dest);
+				if(lastByteBuffer==null) { //coult not enc.. lets wait..
+					bufferList.add(0, dest);
+					return false;
+				}
+				addEncryptedByteBuffer(lastByteBuffer);
+				lastByteBuffer = null;
+			}			
+		}
+		while(encryptedBufferList!=null && encryptedBufferList.size()!=0) {
+			lastByteBuffer = (ByteBuffer) encryptedBufferList.remove(0);
+			logger.fine("Sening to peer: "+lastByteBuffer.position());
+			lastByteBuffer.flip();
+			writeLastByteBuffer();
+			if(lastByteBuffer != null) return false;
+		}
+
+		if(toNotify!=null) {
+			synchronized(toNotify) {
+				toNotify.notify();
+				toNotify = null;
+			}
+		}
+
+		logger.fine("writeAllByteBuffer is true!"); 
+		return true;
+	}
+
+	private synchronized void writeLastByteBuffer() throws IOException {
+		int written = 0;
+		while(lastByteBuffer.remaining()!=0) {
+			java.nio.channels.SocketChannel sc = handler.getSocketChannel();
+			if(sc!=null && sc.isOpen()) {
+				written = sc.write(lastByteBuffer);
+				if(written==0) {
+					break;
+				}
+				if(logger.isLoggable(Level.FINEST)) { 
+					logger.finest("Written "+written+" bytes");
+				}
+			} else {
+				throw new IOException("SocketChannel was closed.");
+			}
+		}
+		if(lastByteBuffer.remaining()==0) {
+			returnBufferBack(lastByteBuffer);
+			lastByteBuffer = null;
+		}
+	}
+
+	private void returnBufferBack(ByteBuffer byteBuffer) {
+		try {
+			handler.getServer().getByteBufferPool().returnObject(byteBuffer);	
+		} catch(Exception er) {
+			logger.warning("Error while returning ByteBuffer to pool: "+er);
+		}
+	}
+
+	public void forceNotify() {
+		if(toNotify==null) return;
+		synchronized(toNotify) {
+			toNotify.notify();
+			toNotify = null;
+		}
+	}
+
+	public boolean isDataAvailableForWrite(Object toNotify) {
+		if(lastByteBuffer!=null) {
+			if(this.toNotify!=null) {
+				throw new IllegalStateException("toNotify object was already set!");
+			}
+			this.toNotify = toNotify;
+			return true;
+		}
+		if(bufferList.size()==0) {
+			return false;
+		} else {
+			if(this.toNotify!=null) {
+				throw new IllegalStateException("toNotify object was already set!");
+			}
+			this.toNotify = toNotify;
+			return true;
+		}
+	}
+
+	public void addEncryptedByteBuffer(ByteBuffer buff) {
+		encryptedBufferList.add(buff);
+	}
+
+	public boolean doShutdown() throws IOException {
+		if(handler.closeIfSSLOutboundDone()) return true;
+
+		ByteBuffer dummyByteBuffer = ByteBuffer.allocate(0);
+		lastByteBuffer = handler.encrypt(dummyByteBuffer);
+		writeLastByteBuffer();
+		if(lastByteBuffer != null) {
+			handler.registerWrite();
+			return false;
+		} else {
+			return handler.closeIfSSLOutboundDone();
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/DirFileList.java b/quickserver/src/main/org/quickserver/util/io/DirFileList.java
new file mode 100644
index 0000000..74d223c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/DirFileList.java
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.io;
+
+import java.io.*;
+
+/**
+ * DirFileList Class
+ * @author Akshathkumar Shetty
+ * @version 1.3.2
+ */
+public class DirFileList implements java.io.FileFilter {
+	public boolean accept(File file) {
+		return file.isDirectory();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/JarFileList.java b/quickserver/src/main/org/quickserver/util/io/JarFileList.java
new file mode 100644
index 0000000..665b058
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/JarFileList.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.io;
+
+import java.io.*;
+
+/**
+ * JarFileList Class
+ * @author Akshathkumar Shetty
+ * @version 1.3.2
+ */
+public class JarFileList implements java.io.FileFilter {
+	public boolean accept(File file) {
+		if(file.getName().toLowerCase().endsWith(".jar"))
+			return true;
+		else
+			return false;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/MaskingThread.java b/quickserver/src/main/org/quickserver/util/io/MaskingThread.java
new file mode 100644
index 0000000..dd30c2d
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/MaskingThread.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.io;
+
+import java.io.*;
+
+/**
+ * This class attempts to erase characters echoed to the console.
+ * @since 1.4
+ */
+class MaskingThread extends Thread {
+   private volatile boolean stop;
+   //private char echochar = '*';
+
+  /**
+   * @param prompt The prompt displayed to the user
+   */
+   public MaskingThread(String prompt) {
+      System.out.print(prompt);
+   }
+
+  /**
+   * Begin masking until asked to stop.
+   */
+   public void run() {
+      int priority = Thread.currentThread().getPriority();
+      Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
+
+      try {
+         stop = true;
+         while(stop) {
+           System.out.print("\010 " /*+ echochar*/);
+           try {
+              // attempt masking at this rate
+              Thread.currentThread().sleep(1);
+           }catch (InterruptedException iex) {
+              Thread.currentThread().interrupt();
+              return;
+           }
+         }
+      } finally { // restore the original priority
+         Thread.currentThread().setPriority(priority);
+      }
+   }
+
+  /**
+   * Instruct the thread to stop masking.
+   */
+   public void stopMasking() {
+      this.stop = false;
+   }
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/PasswordField.java b/quickserver/src/main/org/quickserver/util/io/PasswordField.java
new file mode 100644
index 0000000..000ae10
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/PasswordField.java
@@ -0,0 +1,112 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.io;
+
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
+
+/**
+ * This class prompts the user for a password and attempts to mask 
+ * input.
+ * @since 1.4
+ */
+public class PasswordField {
+	private static Logger logger = Logger.getLogger(PasswordField.class.getName());
+
+	/**
+	 * @param prompt The prompt to display to the user.
+	 * @return The password as entered by the user.
+	 */
+	public static final char[] getPassword(String prompt) 
+			throws IOException {
+	   return getPassword(System.in, prompt);
+	}
+
+	/**
+	 * @param in input stream to be used (e.g. System.in)
+	 * @param prompt The prompt to display to the user.
+	 * @return The password as entered by the user.
+	 */
+	public static final char[] getPassword(InputStream in, String prompt) 
+			throws IOException {
+		MaskingThread maskingthread = new MaskingThread(prompt);
+		Thread thread = new Thread(maskingthread);
+		thread.start();
+
+		char[] lineBuffer;
+		char[] buf;
+		int i;
+
+		buf = lineBuffer = new char[128];
+
+		int room = buf.length;
+		int offset = 0;
+		int c;
+
+		loop: while(true) {
+			c = in.read();
+			switch(c) {
+				case -1:
+				case '\n':
+				   break loop;
+
+				case '\r':
+				   int c2 = in.read();
+				   if((c2 != '\n') && (c2 != -1)) {
+					  if(!(in instanceof PushbackInputStream)) {
+						 in = new PushbackInputStream(in);
+					  }
+					  ((PushbackInputStream)in).unread(c2);
+					} else {
+					  break loop;
+					}
+				default:
+                   if (--room < 0) {
+                      buf = new char[offset + 128];
+                      room = buf.length - offset - 1;
+                      System.arraycopy(lineBuffer, 0, buf, 0, offset);
+                      Arrays.fill(lineBuffer, ' ');
+                      lineBuffer = buf;
+                   }
+                   buf[offset++] = (char) c;
+                   break;
+			}
+		}	
+		maskingthread.stopMasking();
+		System.out.print("\010");
+		//Code to clear doskey on win nt/2000 - Alt+F7
+		String os = System.getProperty("os.name");
+		if(os!=null && os.toLowerCase().startsWith("windows")) {
+			try {
+				java.awt.Robot robot = new java.awt.Robot();
+				robot.keyPress(java.awt.event.KeyEvent.VK_ALT);
+				robot.keyPress(java.awt.event.KeyEvent.VK_F7);
+				robot.keyRelease(java.awt.event.KeyEvent.VK_F7);
+				robot.keyRelease(java.awt.event.KeyEvent.VK_ALT);
+			} catch(Exception ignore) {
+				logger.warning("Could not clears command history: "+ignore); 
+			}
+		}
+
+		if(offset == 0) {
+			return null;
+		}
+		char[] ret = new char[offset];
+		System.arraycopy(buf, 0, ret, 0, offset);
+		Arrays.fill(buf, ' ');
+		return ret;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/io/package.html b/quickserver/src/main/org/quickserver/util/io/package.html
new file mode 100644
index 0000000..1477a47
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/io/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Support classes for IO operation.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/logging/AsyncHandler.java b/quickserver/src/main/org/quickserver/util/logging/AsyncHandler.java
new file mode 100644
index 0000000..6843b23
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/AsyncHandler.java
@@ -0,0 +1,178 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.util.logging;
+
+import java.util.ArrayList;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+
+public class AsyncHandler extends Handler {
+	private int bufferSize = 3000;
+	private int loggingInterval = 5000;
+	private Handler handler;
+	
+	private Thread thread = null;
+	protected volatile boolean closed = false;
+
+	private ArrayList<LogEntry> inList = new ArrayList<LogEntry>();
+	private ArrayList<LogEntry> outList = new ArrayList<LogEntry>();	
+	
+	int bufferSkipCount = 0;	
+	private static boolean debugMode = false; 
+	
+	public AsyncHandler(Handler handler){
+		super();
+		this.handler = handler;
+		startAsyncService();
+	}	
+	
+	public AsyncHandler(Handler handler, int milliSec, int bufferSize){
+		super();
+		this.handler = handler;
+		this.loggingInterval = milliSec;
+		this.bufferSize = bufferSize;
+		startAsyncService();
+	}	
+	
+	public int getBufferSize() {
+		return bufferSize;
+	}
+
+	public void setBufferSize(int bufferSize) {
+		this.bufferSize = bufferSize;
+	}
+
+	public int getLoggingInterval() {
+		return loggingInterval;
+	}
+
+	public void setLoggingInterval(int loggingInterval) {
+		this.loggingInterval = loggingInterval;
+	}
+
+	public static boolean isDebugMode() {
+		return debugMode;
+	}
+
+	public static void setDebugMode(boolean debugMode) {
+		AsyncHandler.debugMode = debugMode;
+	}
+
+	@Override
+	public void close() throws SecurityException {
+		if (closed) return;
+		closed = true;
+		handler.close();
+	}
+
+	@Override
+	public void flush() {
+		handler.flush();
+	}
+
+	@Override
+	public void publish(LogRecord record) {
+		if (!isLoggable(record)) {
+			return;
+		}
+		LogEntry entry = new LogEntry(record,this);
+
+		if(thread.isAlive()==false) {
+			startAsyncService();
+		}
+		
+		StringBuilder sb = new StringBuilder();
+		sb.append(" - [");
+		sb.append(Thread.currentThread().getName());
+		sb.append("] - ");
+		sb.append(record.getMessage());
+		record.setMessage(sb.toString());
+
+		if(inList.size() >= bufferSize){
+			bufferSkipCount++;
+			handler.publish(record);
+		} else {
+			record.getSourceMethodName();
+			inList.add(entry);
+		} 
+	}
+	
+	public void startAsyncService(){		
+		thread = new Thread("AsyncHandler") {	
+			public void run() {
+				long timeSpent = 0;
+				long timetosleep = 0;
+				while(true) {	
+					timetosleep = loggingInterval - timeSpent;
+					try{
+						if(timetosleep>0) sleep(timetosleep);
+					}catch (InterruptedException e) {
+						e.printStackTrace();
+					}
+
+					long stime = System.currentTimeMillis();
+					initiateLogDispatch();
+					timeSpent = System.currentTimeMillis() - stime;
+				}					
+			}				
+		};
+		thread.start();
+	}	
+	
+	private void initiateLogDispatch() {
+		try {
+			swapList();
+			int logEntrySize = outList.size();
+			if(logEntrySize > 0){
+				for(int i = 0; i < logEntrySize; i++){
+					LogEntry le = outList.get(i);
+					if (le!=null) le.flush();
+				}
+			}
+			if(debugMode){
+				System.out.println("Logged " + logEntrySize + " log entries. Skipped Async count " + bufferSkipCount);
+			}
+			bufferSkipCount = 0;
+			outList.clear();
+		} catch(Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	protected void swapList(){
+		ArrayList<LogEntry> temp1 = inList;
+		ArrayList<LogEntry> temp2 = outList;
+		outList = temp1;
+		inList = temp2;
+	}	
+	
+	protected static class LogEntry {
+		private LogRecord record;
+		private AsyncHandler aHandler;
+		public LogEntry(LogRecord record, AsyncHandler aHandler) {
+			super();
+			this.record = record;
+			this.aHandler = aHandler;
+		}
+
+		public boolean flush() {
+			if (aHandler.closed) {
+				return false;
+			} else {
+				aHandler.handler.publish(record);
+				return true;
+			}
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/MicroFormatter.java b/quickserver/src/main/org/quickserver/util/logging/MicroFormatter.java
new file mode 100644
index 0000000..9ed1b1f
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/MicroFormatter.java
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.logging;
+
+import java.util.logging.*;
+
+/**
+ * Formats the LogRecord as "LEVEL : MESSAGE"
+ */
+public class MicroFormatter extends Formatter {
+	private final String lineSeparator = System.getProperty("line.separator");
+
+	public String format(LogRecord record) {
+		StringBuilder sb = new StringBuilder();
+		sb.append(record.getLevel().getLocalizedName());
+		sb.append(" : ");
+		sb.append(formatMessage(record));
+		if(record.getThrown() != null) {
+			sb.append(lineSeparator);
+			sb.append("[Exception: ");
+			sb.append(record.getThrown().toString());
+			sb.append(']');
+		}
+		sb.append(lineSeparator);
+		return  sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/MiniFormatter.java b/quickserver/src/main/org/quickserver/util/logging/MiniFormatter.java
new file mode 100644
index 0000000..774e529
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/MiniFormatter.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.logging;
+
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.logging.*;
+import org.quickserver.util.MyString;
+
+/**
+ * Formats the LogRecord as "MMM d, yyyy hh:mm a - LEVEL : MESSAGE"
+ */
+public class MiniFormatter extends Formatter {
+	private final SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy HH:mm a");
+    private final String lineSeparator = System.getProperty("line.separator");
+
+
+	public String format(LogRecord record) {
+		Date date = new Date();
+		date.setTime(record.getMillis());
+		StringBuilder sb = new StringBuilder();
+		sb.append(df.format(date));
+		sb.append(" - ");
+		sb.append(MyString.alignLeft(record.getLevel().getLocalizedName(), 7));
+		sb.append(" : ");
+		sb.append(formatMessage(record));
+		if(record.getThrown() != null) {
+			sb.append(lineSeparator);
+			sb.append("[Exception: ");
+			sb.append(record.getThrown().toString());
+			sb.append(']');
+		}
+		sb.append(lineSeparator);
+		return sb.toString();
+	}
+
+	
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/SimpleConsoleFormatter.java b/quickserver/src/main/org/quickserver/util/logging/SimpleConsoleFormatter.java
new file mode 100644
index 0000000..a7fef01
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/SimpleConsoleFormatter.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.logging;
+
+import java.util.logging.*;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import org.quickserver.util.MyString;
+
+/**
+ * Formats the LogRecord as "hh:mm:ss,SSS [LEVEL] Class.method() - MESSAGE"
+ * @since 1.3.2
+ */
+public class SimpleConsoleFormatter extends Formatter {	
+	private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss,SSS");
+    private final String lineSeparator = System.getProperty("line.separator");
+
+	public String format(LogRecord record) {
+		Date date = new Date();
+		date.setTime(record.getMillis());
+
+		StringBuilder sb = new StringBuilder();
+		sb.append(df.format(date));
+		sb.append(" [");
+		sb.append(MyString.alignLeft(record.getLevel().getLocalizedName(), 7));
+		sb.append("] ");
+		if(record.getSourceClassName() != null) {
+			sb.append(record.getSourceClassName());
+		} else {
+			sb.append(record.getLoggerName());
+		}
+		if(record.getSourceMethodName() != null) {	
+			sb.append('.');
+			sb.append(record.getSourceMethodName());
+		}
+		sb.append(" - ");
+		sb.append(formatMessage(record));
+			
+		if(record.getThrown() != null) {
+			sb.append(lineSeparator);
+			sb.append("[Exception: ");
+			sb.append(record.getThrown().toString());
+			sb.append(']');
+		}
+		
+		sb.append(lineSeparator);
+		return  sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/SimpleConsoleWithThreadFormatter.java b/quickserver/src/main/org/quickserver/util/logging/SimpleConsoleWithThreadFormatter.java
new file mode 100644
index 0000000..e4c717a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/SimpleConsoleWithThreadFormatter.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.logging;
+
+import java.util.logging.*;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import org.quickserver.util.MyString;
+
+/**
+ * Formats the LogRecord as "HH:mm:ss,SSS [LEVEL] [<Thread-ID> - <ThreadName>] Class.method() - MESSAGE"
+ * @since 1.5
+ */
+public class SimpleConsoleWithThreadFormatter extends Formatter {
+	private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss,SSS");
+    private final String lineSeparator = System.getProperty("line.separator");
+
+	public String format(LogRecord record) {
+		Date date = new Date();
+		date.setTime(record.getMillis());
+
+		StringBuilder sb = new StringBuilder();
+		sb.append(df.format(date));
+		sb.append(" [");
+		sb.append(MyString.alignLeft(record.getLevel().getLocalizedName(), 7));
+		sb.append("] ");
+		sb.append("[").append(record.getThreadID()).append(" - ");
+		sb.append(Thread.currentThread().getName());
+		sb.append("] ");
+		if(record.getSourceClassName() != null) {
+			sb.append(record.getSourceClassName());
+		} else {
+			sb.append(record.getLoggerName());
+		}
+		if(record.getSourceMethodName() != null) {	
+			sb.append('.');
+			sb.append(record.getSourceMethodName());
+		}
+		sb.append(" - ");
+		sb.append(formatMessage(record));
+			
+		if(record.getThrown() != null) {
+			sb.append(lineSeparator);
+			sb.append("[Exception: ");
+			sb.append(record.getThrown().toString());
+			sb.append(']');
+		}
+		
+		sb.append(lineSeparator);
+		return  sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/SimpleJDKLoggingHook.java b/quickserver/src/main/org/quickserver/util/logging/SimpleJDKLoggingHook.java
new file mode 100644
index 0000000..47e03c0
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/SimpleJDKLoggingHook.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.logging;
+
+import org.quickserver.net.server.*;
+import org.quickserver.net.InitServerHook;
+
+import java.io.*;
+
+import org.quickserver.util.logging.*;
+import java.util.logging.*;
+
+/**
+ * <p>SimpleLoggingHook - may be used to setup quick logging for a server. </p>
+ * This will write log using {@link SimpleTextFormatter} to 
+ * <code>log\&lt;ServerName&gt;_%u%g.txt</code> with maximum of 20 rolling files, 
+ * each of 1MB. 
+ *
+ * <code>-Dorg.quickserver.util.logging.SimpleJDKLoggingHook.Level=FINE</code> may
+ * be used to control the logging level to file. 
+ * <code>-Dorg.quickserver.util.logging.SimpleJDKLoggingHook.Count=100</code> may
+ * be used to control the number of files to use. 
+ *
+ * @author Akshathkumar Shetty
+ * @since 1.4.6
+ */
+public class SimpleJDKLoggingHook implements InitServerHook {
+	private QuickServer quickserver;
+
+	public String info() {
+		return "Init Server Hook to setup logging.";
+	}
+
+	public void handleInit(QuickServer quickserver) throws Exception {
+		Logger logger = null;
+		FileHandler txtLog = null;
+		File log = new File("./log/");
+		if(!log.canRead())
+			log.mkdir();
+		try	{
+			String level = System.getProperty(
+				"org.quickserver.util.logging.SimpleJDKLoggingHook.Level");
+
+			logger = Logger.getLogger("");
+			logger.setLevel(Level.FINEST);
+
+			int count = 100;
+			String temp = System.getProperty(
+				"org.quickserver.util.logging.SimpleJDKLoggingHook.Count");
+			if(temp!=null) {
+				try {
+					count = Integer.parseInt(temp);
+				} catch(Exception e) {/*Ignore*/}
+			}
+
+			txtLog = new FileHandler("log/"+quickserver.getName()+"_%u%g.txt", 
+				1024*1024, count, true);
+			txtLog.setFormatter(new SimpleTextFormatter());
+			setLevel(txtLog, level);
+			logger.addHandler(txtLog);
+
+			logger = Logger.getLogger("filesrv");
+			quickserver.setAppLogger(logger);
+		} catch(IOException e){
+			System.err.println("Could not create txtLog FileHandler : "+e);
+			throw e;
+		}
+	}
+
+	private static void setLevel(FileHandler target, String temp) {
+		if(temp==null) {
+			target.setLevel(Level.FINE);
+			return;
+		}
+		temp = temp.toUpperCase();
+		
+		
+
+		if(temp.equals("SEVERE"))
+			target.setLevel(Level.SEVERE);
+		else if(temp.equals("WARNING"))
+			target.setLevel(Level.WARNING);
+		else if(temp.equals("INFO"))
+			target.setLevel(Level.INFO);
+		else if(temp.equals("CONFIG"))
+			target.setLevel(Level.CONFIG);
+		else if(temp.equals("FINE"))
+			target.setLevel(Level.FINE);
+		else if(temp.equals("FINER"))
+			target.setLevel(Level.FINER);
+		else if(temp.equals("FINEST"))
+			target.setLevel(Level.FINEST);
+		else if(temp.equals("OFF"))
+			target.setLevel(Level.OFF);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/SimpleTextFormatter.java b/quickserver/src/main/org/quickserver/util/logging/SimpleTextFormatter.java
new file mode 100644
index 0000000..9d03778
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/SimpleTextFormatter.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.logging;
+
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.logging.*;
+import java.io.*;
+import org.quickserver.util.MyString;
+
+/**
+ * Formats the LogRecord as "yyyy-MM-dd hh:mm:ss,SSS [LEVEL] [<Thread-ID>] - Class.method() - [<ThreadName>] - MESSAGE"
+ * @since 1.3.2
+ */
+public class SimpleTextFormatter extends Formatter {
+	private boolean logThreadName = true;
+	private final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
+    private final String lineSeparator = System.getProperty("line.separator");
+
+	public String format(LogRecord record) {
+		Date date = new Date();
+		date.setTime(record.getMillis());
+
+		StringBuilder sb = new StringBuilder();
+		sb.append(df.format(date));
+		sb.append(" [");
+		sb.append(MyString.alignLeft(record.getLevel().getLocalizedName(), 7));
+		sb.append("]");	
+		sb.append(" [").append(record.getThreadID()).append("] - ");
+		if(record.getSourceClassName() != null) {
+			sb.append(record.getSourceClassName());
+		} else {
+			sb.append(record.getLoggerName());
+		}
+		if(record.getSourceMethodName() != null) {	
+			sb.append('.');
+			sb.append(record.getSourceMethodName());
+		}		
+		if(isLogThreadName()) {
+			sb.append(" - [");
+			sb.append(Thread.currentThread().getName());
+			sb.append("]");
+		}
+		sb.append(" - ");
+		sb.append(formatMessage(record));
+				
+		if(record.getThrown() != null) {
+			sb.append(lineSeparator);
+			sb.append("[StackTrace: ");
+			try {
+				StringWriter sw = new StringWriter();
+				PrintWriter pw = new PrintWriter(sw);
+				record.getThrown().printStackTrace(pw);
+				pw.close();
+				sb.append(sw.toString());
+			} catch(Exception ex) {
+				sb.append(record.getThrown().toString());
+			}
+			sb.append(']');
+		}
+		
+		sb.append(lineSeparator);
+		return  sb.toString();		
+	}
+
+	/**
+	 * @return the logThreadName
+	 */
+	public boolean isLogThreadName() {
+		return logThreadName;
+	}
+
+	/**
+	 * @param logThreadName the logThreadName to set
+	 */
+	public void setLogThreadName(boolean logThreadName) {
+		this.logThreadName = logThreadName;
+	}
+
+	
+}
diff --git a/quickserver/src/main/org/quickserver/util/logging/package.html b/quickserver/src/main/org/quickserver/util/logging/package.html
new file mode 100644
index 0000000..519fa72
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/logging/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Support classes for LogRecord formatting.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/package.html b/quickserver/src/main/org/quickserver/util/package.html
new file mode 100644
index 0000000..0e42f39
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE>Overview</TITLE>

+</HEAD>

+

+<BODY>

+General utility classes.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/pool/BasicObjectPool.java b/quickserver/src/main/org/quickserver/util/pool/BasicObjectPool.java
new file mode 100644
index 0000000..b684956
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/BasicObjectPool.java
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.commons.pool.*;
+import java.util.logging.*;
+
+/**
+ * This class will maintain a simple pool of object instances.
+ * It internally used a <code>HashSet</code>
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class BasicObjectPool implements QSObjectPool {
+	private static final Logger logger = 
+			Logger.getLogger(BasicObjectPool.class.getName());
+
+	private PoolableObjectFactory factory;
+	private Config config;
+	private final Set activeObjects, idleObjects;
+	private volatile boolean inMaintain = false;
+	protected AtomicLong activeCount = new AtomicLong();
+	private long highestActiveCount;
+
+	public BasicObjectPool() {
+		activeObjects = Collections.synchronizedSet(new HashSet());
+		idleObjects = Collections.synchronizedSet(new HashSet());
+		config = new Config();
+	}
+	public BasicObjectPool(PoolableObjectFactory factory, 
+			BasicObjectPool.Config config) {
+		this();
+		this.factory = factory;
+		if(config!=null) this.config = config;
+	}
+
+	public void addObject() throws Exception {
+		if(config.maxIdle==-1 || config.maxIdle > getNumIdle()) 
+			idleObjects.add(factory.makeObject());
+		else
+			maintain();
+	}
+	
+	public Object borrowObject() throws Exception {
+		if(getNumIdle()<=0 && 
+			(config.maxActive==-1 || config.maxActive > getNumActive()) ) {
+			addObject();
+		}
+		if(getNumIdle()<=0) {
+			throw new NoSuchElementException("No free objects! MaxActive:"+
+				config.maxActive+", NumActive:"+getNumActive());
+		}
+		
+		Object obj = null;
+		synchronized(this) {
+			obj = idleObjects.iterator().next();
+			idleObjects.remove(obj);
+			factory.activateObject(obj);
+			activeObjects.add(obj);
+		}
+		if(getHighestActiveCount() < activeCount.incrementAndGet()) {
+			setHighestActiveCount(activeCount.get());
+		}
+		return obj;
+	}
+
+	/**Clears any objects sitting idle in the pool*/
+	public synchronized void clear() {
+		Iterator iterator = idleObjects.iterator();
+		while(iterator.hasNext()) {
+			try	{
+				invalidateObject(iterator.next());	
+			} catch(Exception e) {
+				logger.warning("Error in BasicObjectPool.clear : "+e);
+			}			
+		}
+		idleObjects.clear();
+	}
+
+	/**Close this pool, and free any resources associated with it.*/
+	public void close() throws Exception {
+		clear();
+		/*
+		Iterator iterator = activeObjects.iterator();
+		while(iterator.hasNext()) {
+			try {
+				invalidateObject(iterator.next());
+			} catch(Exception e) {
+				logger.warning("Error in BasicObjectPool.close : "+e);
+			}
+		}
+		*/
+		activeObjects.clear();
+	}
+
+	/**Return the number of instances currently borrowed from my pool */
+	public int getNumActive() {
+		return activeObjects.size();
+	}
+	/**Return the number of instances currently idle in my pool */
+	public int getNumIdle() {
+		return idleObjects.size();
+	}
+	
+	/**Invalidates an object from the pool */
+	public void invalidateObject(Object obj) throws Exception {
+		factory.destroyObject(obj);
+	}
+
+	/**Return an instance to my pool*/
+	public synchronized void returnObject(Object obj) throws Exception {
+		if(activeObjects.remove(obj)) {
+			activeCount.decrementAndGet();
+		}
+		if(factory.validateObject(obj)==false) {
+			logger.log(Level.FINER, "Object not good for return: {0}", obj);
+			return;
+		}
+		factory.passivateObject(obj);
+		idleObjects.add(obj);
+		if(config.maxIdle!=-1 && config.maxIdle < getNumIdle()) {
+			maintain();
+		}
+	}
+	
+	/**Sets the factory I use to create new instances */
+	public void setFactory(PoolableObjectFactory factory) {
+		this.factory = factory;
+	}
+
+	private void maintain() {
+		if(inMaintain==true) {
+			return;
+		}
+		inMaintain = true;
+		logger.log(Level.FINEST, "Starting maintain: {0}", getNumIdle());
+		while(getNumIdle()>config.maxIdle) {
+			try {
+				synchronized(idleObjects) {
+					Object obj = idleObjects.iterator().next();
+					idleObjects.remove(obj);
+					invalidateObject(obj);
+				}
+			} catch(Exception e) {
+				logger.log(Level.WARNING, "Error in BasicObjectPool.maintain : {0}", e);
+			}
+		}
+		inMaintain = false;
+		logger.log(Level.FINEST, "Finished maintain: {0}", getNumIdle());
+	}
+
+	public static class Config {
+		public int maxActive = -1;
+		public int maxIdle = 10;
+	}
+
+	/**
+	 * Returns the iterator of all active objects
+	 * @since 1.3.1
+	 */
+	public Iterator getAllActiveObjects() {
+		List _list = new LinkedList();
+		_list.addAll(activeObjects);
+		return _list.iterator(); //*/activeObjects.iterator();
+	}
+
+	public Object getObjectToSynchronize() {
+		return activeObjects;
+	}
+	
+	/**
+	 * @return the highestActiveCount
+	 */
+	public long getHighestActiveCount() {
+		return highestActiveCount;
+	}
+
+	/**
+	 * @param highestActiveCount the highestActiveCount to set
+	 */
+	public void setHighestActiveCount(long highestActiveCount) {
+		this.highestActiveCount = highestActiveCount;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/ByteBufferObjectFactory.java b/quickserver/src/main/org/quickserver/util/pool/ByteBufferObjectFactory.java
new file mode 100644
index 0000000..b36406c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/ByteBufferObjectFactory.java
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import java.nio.ByteBuffer;
+import org.apache.commons.pool.BasePoolableObjectFactory; 
+
+/**
+ * A factory for creating java.nio.ByteBuffer instances. 
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ByteBufferObjectFactory extends BasePoolableObjectFactory {
+	int bufferSize = -1;
+	boolean useDirectByteBuffer = true;
+
+	public ByteBufferObjectFactory(int bufferSize, boolean useDirectByteBuffer) {
+		this.bufferSize = bufferSize;
+		this.useDirectByteBuffer = useDirectByteBuffer;
+	}
+
+	//Creates an instance that can be returned by the pool. 
+	public Object makeObject() { 
+		if(useDirectByteBuffer)
+	        return ByteBuffer.allocateDirect(bufferSize);
+		else
+			return ByteBuffer.allocate(bufferSize);
+	} 
+
+	//Uninitialize an instance to be returned to the pool. 
+    public void passivateObject(Object obj) {
+		ByteBuffer ch = (ByteBuffer)obj;
+		ch.clear();
+    } 
+
+	//Reinitialize an instance to be returned by the pool. 
+    public void activateObject(Object obj) {
+	}
+	
+	//Destroys an instance no longer needed by the pool. 
+	public void destroyObject(Object obj) {
+		if(obj==null) return;
+		passivateObject(obj);
+		obj = null;
+	}
+
+	//Ensures that the instance is safe to be returned by the pool. 
+	public boolean validateObject(Object obj) {
+		if(obj==null) 
+			return false;
+		else
+			return true;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/ClientHandlerObjectFactory.java b/quickserver/src/main/org/quickserver/util/pool/ClientHandlerObjectFactory.java
new file mode 100644
index 0000000..7543ad1
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/ClientHandlerObjectFactory.java
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import org.quickserver.net.server.ClientHandler;
+import org.quickserver.net.server.impl.*;
+import org.apache.commons.pool.BasePoolableObjectFactory; 
+
+/**
+ * A factory for creating {@link org.quickserver.net.server.ClientHandler}
+ * instances. 
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ClientHandlerObjectFactory extends BasePoolableObjectFactory {
+	private static int instanceCount = 0;
+	private int id = -1;
+	private boolean blocking = true;
+
+	public ClientHandlerObjectFactory(boolean blocking) {
+		super();
+		id = ++instanceCount;
+		this.blocking = blocking;
+	}
+
+	//Creates an instance that can be returned by the pool. 
+	public Object makeObject() { 
+		if(blocking)
+	        return new BlockingClientHandler(id);
+		else
+			return new NonBlockingClientHandler(id);
+	} 
+
+	//Uninitialize an instance to be returned to the pool. 
+    public void passivateObject(Object obj) {
+		ClientHandler ch = (ClientHandler)obj;
+		ch.clean();
+    } 
+
+	//Reinitialize an instance to be returned by the pool. 
+    public void activateObject(Object obj) {
+	}
+	
+	//Destroys an instance no longer needed by the pool. 
+	public void destroyObject(Object obj) {
+		if(obj==null) return;
+		passivateObject(obj);
+		obj = null;
+	}
+
+	//Ensures that the instance is safe to be returned by the pool. 
+	public boolean validateObject(Object obj) {
+		if(obj==null) 
+			return false;
+		
+		BasicClientHandler ch = (BasicClientHandler)obj;
+		if(ch.getInstanceCount()==id)
+			return true;
+		else {
+			return false;
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/MakeQSObjectPool.java b/quickserver/src/main/org/quickserver/util/pool/MakeQSObjectPool.java
new file mode 100644
index 0000000..b7ec2c6
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/MakeQSObjectPool.java
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.commons.pool.*;
+
+/**
+ * This class that creates QSObjectPool from ObjectPool passed to it.
+ * @since 1.4.5
+ */
+public class MakeQSObjectPool implements QSObjectPool, QSObjectPoolMaker {
+	protected ObjectPool objectPool = null;
+	protected List list = null;
+	
+	protected AtomicLong activeCount = new AtomicLong();
+	private long highestActiveCount;
+
+	public QSObjectPool getQSObjectPool(ObjectPool objectPool) {
+		return new MakeQSObjectPool(objectPool);
+	}
+
+	public MakeQSObjectPool() {
+		activeCount = new AtomicLong();
+	}
+
+	public MakeQSObjectPool(ObjectPool objectPool) {
+		setObjectPool(objectPool);
+	}
+
+	protected void setObjectPool(ObjectPool objectPool) {
+		this.objectPool = objectPool;
+		list = Collections.synchronizedList(new LinkedList());
+	}
+
+	public void returnObject(Object obj) throws Exception {				
+		objectPool.returnObject(obj);
+		if(list.remove(obj)) {
+			activeCount.decrementAndGet();
+		}
+	}
+
+	public Object borrowObject() throws Exception {
+		Object obj = objectPool.borrowObject();
+		list.add(obj);
+		
+		if(getHighestActiveCount() < activeCount.incrementAndGet()) {
+			setHighestActiveCount(activeCount.get());
+		}
+		return obj;
+	}
+
+	public synchronized void close() throws Exception {
+		list.clear();
+		objectPool.close();
+	}
+
+	/**
+	 * Returns the iterator of all active objects
+	 */
+	public Iterator getAllActiveObjects() {
+		return list.iterator();
+	}
+
+	public Object getObjectToSynchronize() {
+		return list;
+	}
+
+	public void addObject() throws Exception {
+		objectPool.addObject();
+	}
+
+	public void clear() throws Exception  {
+		objectPool.clear();
+	}
+
+	public int getNumActive() {
+		return objectPool.getNumActive();
+	}
+
+	public int getNumIdle() {
+		return objectPool.getNumIdle();
+	}
+
+	public void invalidateObject(Object obj) throws Exception {
+		objectPool.invalidateObject(obj);
+	}
+
+	public void setFactory(PoolableObjectFactory factory) {
+		objectPool.setFactory(factory);
+	}	
+
+	/**
+	 * @return the highestActiveCount
+	 */
+	public long getHighestActiveCount() {
+		return highestActiveCount;
+	}
+
+	/**
+	 * @param highestActiveCount the highestActiveCount to set
+	 */
+	public void setHighestActiveCount(long highestActiveCount) {
+		this.highestActiveCount = highestActiveCount;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/PoolHelper.java b/quickserver/src/main/org/quickserver/util/pool/PoolHelper.java
new file mode 100644
index 0000000..857f222
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/PoolHelper.java
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import org.apache.commons.pool.*;
+
+/**
+ * Pool Helper class.
+ * @since 1.4.7
+ */
+public class PoolHelper {
+	
+	/**
+	 * Check if Pool is open.
+	 */
+	public static boolean isPoolOpen(ObjectPool pool) {
+		try {
+			pool.getNumIdle();
+		} catch(Exception e) {
+			return false;
+		}
+		return true;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/PoolableObject.java b/quickserver/src/main/org/quickserver/util/pool/PoolableObject.java
new file mode 100644
index 0000000..9f82b8c
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/PoolableObject.java
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * Interface to be implemented by any user class of QuickServer
+ * so that QuickServer can create a pool of objects and reuse objects
+ * from that pool.
+ * @since 1.3
+ */
+public interface PoolableObject {
+	/**
+	 * Returns  weather or not this Object impelementation 
+	 * can be pooled.
+	 */
+	public boolean isPoolable();
+
+	/**
+	 * Will return a  
+	 * {@link org.apache.commons.pool.PoolableObjectFactory} object for
+	 * this Object implementation if it is poolable
+	 * else will return <code>null</code>
+	 */
+	public PoolableObjectFactory getPoolableObjectFactory();
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/QSObjectPool.java b/quickserver/src/main/org/quickserver/util/pool/QSObjectPool.java
new file mode 100644
index 0000000..b60fd85
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/QSObjectPool.java
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import java.util.*;
+import org.apache.commons.pool.*;
+
+/**
+ * This interface defines ObjectPool that QuickServer needs.
+ * @since 1.4.5
+ */
+public interface QSObjectPool extends ObjectPool {
+	/** Returns the iterator of all active objects */
+	public Iterator getAllActiveObjects();
+	public Object getObjectToSynchronize();
+	public long getHighestActiveCount();
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/QSObjectPoolMaker.java b/quickserver/src/main/org/quickserver/util/pool/QSObjectPoolMaker.java
new file mode 100644
index 0000000..a1c1795
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/QSObjectPoolMaker.java
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool;
+
+import java.util.*;
+import org.apache.commons.pool.*;
+
+/**
+ * This interface defines a class that creates QSObjectPool from ObjectPool. 
+ * Should have a default constructor. 
+ * @since 1.4.5
+ */
+public interface QSObjectPoolMaker {
+	public QSObjectPool getQSObjectPool(ObjectPool objectPool);
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/package.html b/quickserver/src/main/org/quickserver/util/pool/package.html
new file mode 100644
index 0000000..af55f2d
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE>Overview</TITLE>

+</HEAD>

+

+<BODY>

+Provides classes for Object Pools.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/ClientPool.java b/quickserver/src/main/org/quickserver/util/pool/thread/ClientPool.java
new file mode 100644
index 0000000..3bb910b
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/ClientPool.java
@@ -0,0 +1,214 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool.thread;
+
+import java.util.*;
+import org.quickserver.util.pool.*;
+import org.apache.commons.pool.*;
+import org.quickserver.net.server.*;
+import org.quickserver.util.xmlreader.PoolConfig;
+import java.util.logging.*;
+
+/**
+ * This is a class for managing the pool of threads for 
+ * handling clients.
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ClientPool {
+	private static final Logger logger = Logger.getLogger(ClientPool.class.getName());
+
+	protected List clients = new ArrayList(3);
+	protected ObjectPool pool;
+	protected PoolConfig poolConfig;
+	private int countNioWriteThreads; //v1.4.6
+	private int maxThreadsForNioWrite = 10;
+			
+	public ClientPool(QSObjectPool objectPool, PoolConfig poolConfig) {
+		this.poolConfig = poolConfig;
+		pool = objectPool;
+	}
+
+	public ObjectPool getObjectPool() {
+		return pool;
+	}
+
+	public void addClient(Runnable r) throws NoSuchElementException {
+		addClient(r, false);
+	}
+
+	public void addClient(Runnable r, boolean keepObjOnFail) 
+			throws NoSuchElementException {
+		//logger.finest("Adding Runnable: "+r);
+        ClientThread ct = null;
+        synchronized(this) {
+            clients.add(r);        
+            
+            try {
+                ct = (ClientThread)pool.borrowObject();
+                if(ct.isReady()==false) {
+                    //ct.start();
+                    wait(500); //timeout was just in case :-)
+                    //Thread.yield();
+                }			
+
+            } catch(NoSuchElementException e) {
+                logger.info("No free threads: "+e);
+                if(keepObjOnFail==false) {                
+                    clients.remove(r);                
+                }
+                throw e;
+            } catch(Exception e) {
+                logger.warning("Error in addClient: "+e+", Closing client: "+(ClientHandler)r);
+                try {
+                    ((ClientHandler)r).forceClose();
+                } catch(Exception er) {
+                    logger.warning("Error closing client: "+er);
+                }
+                try {
+                    if(ct!=null) pool.returnObject(ct);
+                } catch(Exception er) {
+                    logger.warning("Error in returning thread: "+er);
+                }
+            }
+        }
+        
+        synchronized(ct) {
+            ct.notify();
+        }
+ 	}
+
+	public synchronized void returnObject(Object object) {
+		try {
+			pool.returnObject(object);
+		} catch(Exception e) {
+			logger.warning("IGONRED: Error while returning object : "+e);
+			((Thread)object).interrupt();
+		}
+	}
+
+	public synchronized Runnable getClient() {
+		if(clients.isEmpty()) {
+			return null;
+		}
+		return (Runnable) clients.remove(0);
+	}
+
+	/**
+	 * @since 1.4.5
+	 */
+	public boolean isClientAvailable() {
+		if(clients.isEmpty()) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	public void close() throws Exception {
+		pool.close();
+	}
+
+	public void clear() throws Exception {
+		pool.clear();
+	}
+
+	/**
+	 * Return the number of instances currently borrowed from my pool.
+	 * @since 1.4.1
+	 */
+	public int getNumActive() {
+		return pool.getNumActive();
+	}
+
+	/**
+	 * Return the number of instances currently idle in my pool.
+	 * @since 1.4.1
+	 */
+	public int getNumIdle() {
+		return pool.getNumIdle();
+	}
+
+	/**
+	 * Returns iterator containing all the active
+	 * threads i.e ClientHandler handling connected clients.
+	 * @since 1.3.1
+	 */
+	public final Iterator getAllClientThread() {
+		return ((QSObjectPool)pool).getAllActiveObjects();
+	}
+
+	public Object getObjectToSynchronize() {
+		return ((QSObjectPool)pool).getObjectToSynchronize();
+	}
+
+	/**
+	 * Returns PoolConfig object that configured this pool 
+	 * @since 1.4.5
+	 */
+	public PoolConfig getPoolConfig() {
+		return poolConfig;
+	}
+
+	/**
+	 * Sets the maximum threads allowed for nio write. If set to 0 or less no limit is 
+	 * imposed.
+	 * @since 1.4.6
+	 */
+	public void setMaxThreadsForNioWrite(int count) {
+		this.maxThreadsForNioWrite = count;
+	}
+
+	/**
+	 * Returns the maximum threads allowed for nio write
+	 * @since 1.4.6
+	 */
+	public int getMaxThreadsForNioWrite() {
+		return maxThreadsForNioWrite;
+	}
+
+	/**
+	 * Notifies when NIO write is complete. 
+	 * @since 1.4.6
+	 */
+	protected void nioWriteEnd() {
+		countNioWriteThreads--;
+		if(countNioWriteThreads<0) {
+			logger.warning("countNioWriteThreads should not go less than 0");
+			countNioWriteThreads = 0;
+		}
+	}
+
+	/**
+	 * Notifies when NIO write is about to start. 
+	 * @since 1.4.6
+	 */
+	protected void nioWriteStart() {
+		countNioWriteThreads++;
+	}
+
+	/**
+	 * Method to suggest if nio write should be sent for processing.
+	 * @since 1.4.6
+	 */
+	public boolean shouldNioWriteHappen() {
+		if(maxThreadsForNioWrite <= 0 ||
+				countNioWriteThreads < maxThreadsForNioWrite) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/ClientThread.java b/quickserver/src/main/org/quickserver/util/pool/thread/ClientThread.java
new file mode 100644
index 0000000..ae934cf
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/ClientThread.java
@@ -0,0 +1,201 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool.thread;
+
+import java.util.logging.*;
+import java.util.*;
+import org.quickserver.util.MyString;
+import org.quickserver.net.server.ClientHandler;
+import org.quickserver.net.server.ClientEvent;
+
+/**
+ * This is the worker thread used to handle clients using 
+ * {@link org.quickserver.net.server.ClientHandler}
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ClientThread extends Thread {
+	private static final Logger logger = Logger.getLogger(ClientThread.class.getName());
+	private static Map idMap = new HashMap();
+
+	private String name = "<ClientThread-Pool#";
+	private final ClientPool pool;
+	private Runnable client;
+	private int id;
+	private boolean ready = false;
+
+	/**
+	 * Holds the current Thread state. <code><pre>
+		U = Unknown
+		S = Started
+		R - Running a client
+		I = Idle
+		L = Looking for client
+		P = Was sent back to pool
+		W = Waiting in pool		
+		N = Was notified, Looking for client
+		D = Dead
+		</pre></code>
+	*/
+	protected volatile char state = 'U';
+
+	public boolean isReady() {
+		return ready;
+	}
+
+	public void clean() {
+		client = null;
+	}
+
+	public ClientThread(ClientPool pool) {
+		this(pool, -1);
+	}
+
+	static class InstanceId {
+		private int id = 0;
+		public int getNextId() {
+			return ++id;
+		}
+	};
+
+	private static int getNewId(int instanceCount) {
+		InstanceId instanceId = (InstanceId) idMap.get(""+instanceCount);
+		if(instanceId==null) {
+			instanceId = new InstanceId();
+			idMap.put(""+instanceCount, instanceId);
+		}
+		return instanceId.getNextId();
+	}
+
+	public ClientThread(ClientPool pool, int instanceCount) {
+		id = getNewId(instanceCount);
+		name = name+instanceCount+"-ID:"+id+">";
+		this.pool = pool;
+		setName(name);
+	}
+
+	public int getInstanceId() {
+		return id;
+	}
+
+	private void executeClient() {
+		boolean niowriteFlag = false;
+		state = 'R';       	
+
+		try {
+            if(ClientHandler.class.isInstance(client)) {
+                niowriteFlag = ((ClientHandler) client).isClientEventNext(ClientEvent.WRITE);
+                if(niowriteFlag) {
+                    pool.nioWriteStart();
+                }
+            } else {
+                niowriteFlag = false;
+            }
+            
+			client.run();
+		} catch(Throwable e) {
+			logger.warning("RuntimeException @ thread run() : "+getName()+": "+
+					MyString.getStackTrace(e));
+		} finally {
+			if(niowriteFlag) {
+				pool.nioWriteEnd();
+			}
+		}
+		state = 'I';
+	}
+
+	public void run() {
+		state = 'S';
+		
+        synchronized(pool) {
+            if(pool.isClientAvailable()==true) {
+                ready = true;
+                pool.notify();                
+            }
+        }
+
+		boolean returnToPool = false;
+		while(true) {
+			if(ready) {
+				state = 'L';
+				client = pool.getClient();
+				if(client==null) {
+					logger.fine("ClientPool returned a null client! Other Thread must have taken my client.. Ok");
+				} else {
+					executeClient();					
+					logger.log(Level.FINEST, "Client returned the thread: {0}", getName());
+					client = null;
+					if(pool==null) {
+						logger.log(Level.FINE, "Could not returning client thread {0}, pool was null!", getName());
+						state = 'D';
+						break;
+					}
+				}
+                
+                /*
+                synchronized(pool) {
+                    if(pool.isClientAvailable()==true) {
+                        state = 'L';
+                        continue;
+                    }
+                }
+                */
+				
+				returnToPool = true;
+			} //end if ready
+			
+			synchronized(this) {
+				if(ready==false) ready = true;
+
+				if(returnToPool) {
+					logger.log(Level.FINEST, "Returning client thread to pool: {0}", getName());
+					pool.returnObject(ClientThread.this);
+					returnToPool = false;
+					state = 'P';
+				} else {
+                    //new thread..n no client..  ok
+                }
+				
+				try {
+					state = 'W';
+					wait();
+					state = 'N';
+				} catch(InterruptedException e) {
+					logger.log(Level.FINEST, "Closing thread {0} since interrupted.", 
+						Thread.currentThread().getName());
+					state = 'D';
+					break;
+				}				
+			}
+		}//end while
+	}
+
+	/**
+	 * Returns the {@link org.quickserver.net.server.ClientHandler} being 
+	 * run by the ClientThread.
+	 * @since 1.3.1
+	 */
+	public Runnable getThread() {
+		return client;
+	}
+
+	/**
+	 * [ThreadInPool[<Instance Count>]:<id>] - <state> - Client {ClientHandler:...}
+	 * @since 1.4.1
+	 */
+	public String toString() {
+		return super.toString()+" - "+state+" - Client "+client;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/ThreadObjectFactory.java b/quickserver/src/main/org/quickserver/util/pool/thread/ThreadObjectFactory.java
new file mode 100644
index 0000000..ca5dd3a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/ThreadObjectFactory.java
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.pool.thread;
+
+import org.apache.commons.pool.BasePoolableObjectFactory; 
+
+/**
+ * A factory for creating {@link org.quickserver.util.pool.thread.ClientThread}
+ * instances. 
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ThreadObjectFactory extends BasePoolableObjectFactory {
+	private ClientPool pool;
+	private static int instanceCount = 0;
+	private int id = -1;
+
+	public ThreadObjectFactory() {
+		super();
+		id = ++instanceCount;
+	}
+
+	public void setClientPool(ClientPool pool) {
+		this.pool = pool;
+	}
+
+	//Creates an instance that can be returned by the pool. 
+	public Object makeObject() { 
+		ClientThread ct = new ClientThread(pool, id);
+		ct.start();
+        return ct;
+	} 
+
+	//Uninitialize an instance to be returned to the pool. 
+    public void passivateObject(Object obj) {
+		((ClientThread)obj).clean();		
+    } 
+
+	//Reinitialize an instance to be returned by the pool. 
+    public void activateObject(Object obj) {
+	}
+	
+	//Destroys an instance no longer needed by the pool. 
+	public void destroyObject(Object obj) {
+		if(obj==null) return;
+		Thread thread = (Thread) obj;
+        synchronized(thread) {
+            thread.interrupt();
+        }
+		thread = null;
+	}
+
+	//Ensures that the instance is safe to be returned by the pool. 
+	public boolean validateObject(Object obj) {
+		if(obj==null) return false;
+		Thread thread = (Thread)obj;
+		return thread.isAlive();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/app/AppThreadPool.java b/quickserver/src/main/org/quickserver/util/pool/thread/app/AppThreadPool.java
new file mode 100644
index 0000000..8ba7b43
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/app/AppThreadPool.java
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.util.pool.thread.app;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ * @since 1.4.8
+ */
+public class AppThreadPool {
+	private static final Logger logger = Logger.getLogger(AppThreadPool.class.getName());
+	private static Map poolMap = new HashMap();
+	
+	private static int defaultCorePoolSize = 10;
+	private static int defaultMaximumPoolSize = 50;
+	private static int defaultKeepAliveTime = 120;
+	private static TimeUnit defaultTimeUnit = TimeUnit.SECONDS;
+
+	public static void initPool(String poolName, int corePoolSize, 
+			int maximumPoolSize, int keepAliveTime, TimeUnit timeUnit) {
+		ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) poolMap.get(poolName);
+		if(threadPoolExecutor!=null) {
+			logger.log(Level.FINE, "{0} will be shutdown and re-created", poolName);
+			threadPoolExecutor.shutdown();
+		}
+		threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, 
+				maximumPoolSize, keepAliveTime, timeUnit, 
+				new LinkedBlockingQueue<Runnable>());
+		NamedThreadFactory threadFactory = new NamedThreadFactory("Thread_Pool_"+poolName);
+		threadPoolExecutor.setThreadFactory(threadFactory);
+		poolMap.put(poolName, threadPoolExecutor);
+	}
+	
+	public static void addTask(String poolName, Runnable task) {
+		ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) poolMap.get(poolName);
+		if(threadPoolExecutor==null) {
+			threadPoolExecutor = new ThreadPoolExecutor(defaultCorePoolSize, 
+				defaultMaximumPoolSize, defaultKeepAliveTime, defaultTimeUnit, 
+				new LinkedBlockingQueue<Runnable>());
+			NamedThreadFactory threadFactory = new NamedThreadFactory("Thread_Pool_"+poolName);
+			threadPoolExecutor.setThreadFactory(threadFactory);
+			poolMap.put(poolName, threadPoolExecutor);
+		}
+		threadPoolExecutor.execute(task);
+	}
+	
+	public static ThreadPoolExecutor getPool(String poolName) {
+		return (ThreadPoolExecutor) poolMap.get(poolName);
+	}
+
+	public static int getDefaultCorePoolSize() {
+		return defaultCorePoolSize;
+	}
+
+	public static void setDefaultCorePoolSize(int aDefaultCorePoolSize) {
+		defaultCorePoolSize = aDefaultCorePoolSize;
+	}
+
+	public static int getDefaultMaximumPoolSize() {
+		return defaultMaximumPoolSize;
+	}
+
+	public static void setDefaultMaximumPoolSize(int aDefaultMaximumPoolSize) {
+		defaultMaximumPoolSize = aDefaultMaximumPoolSize;
+	}
+
+	public static int getDefaultKeepAliveTime() {
+		return defaultKeepAliveTime;
+	}
+
+	public static void setDefaultKeepAliveTime(int aDefaultKeepAliveTime) {
+		defaultKeepAliveTime = aDefaultKeepAliveTime;
+	}
+
+	public static TimeUnit getDefaultTimeUnit() {
+		return defaultTimeUnit;
+	}
+
+	public static void setDefaultTimeUnit(TimeUnit aDefaultTimeUnit) {
+		defaultTimeUnit = aDefaultTimeUnit;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/app/NamedThreadFactory.java b/quickserver/src/main/org/quickserver/util/pool/thread/app/NamedThreadFactory.java
new file mode 100644
index 0000000..87914e7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/app/NamedThreadFactory.java
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.util.pool.thread.app;
+
+import java.util.concurrent.ThreadFactory;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ * @since 1.4.8
+ */
+public class NamedThreadFactory implements ThreadFactory {
+	private static final QSUncaughtExceptionHandler eh = new QSUncaughtExceptionHandler();
+	
+	private String namePrefix;
+	private int idx;
+	
+	public NamedThreadFactory(String namePrefix){
+		this.namePrefix = namePrefix;
+	}
+
+
+	public Thread newThread(Runnable r) {
+		Thread t = new Thread(null, r, namePrefix + (++idx));
+		t.setUncaughtExceptionHandler(eh);
+		return t;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/app/QSUncaughtExceptionHandler.java b/quickserver/src/main/org/quickserver/util/pool/thread/app/QSUncaughtExceptionHandler.java
new file mode 100644
index 0000000..76e71ab
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/app/QSUncaughtExceptionHandler.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.util.pool.thread.app;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Akshathkumar Shetty
+ * @since 1.4.8
+ */
+public class QSUncaughtExceptionHandler  implements UncaughtExceptionHandler {
+	private static final Logger logger = Logger.getLogger(QSUncaughtExceptionHandler.class.getName());
+
+	public void uncaughtException(Thread t, Throwable e) {
+		logger.log(Level.SEVERE, "Uncaught Exception [" +t+"]", e);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/app/package.html b/quickserver/src/main/org/quickserver/util/pool/thread/app/package.html
new file mode 100644
index 0000000..7a5c1c3
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/app/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE>Overview</TITLE>

+</HEAD>

+

+<BODY>

+Classes for managing the pool of threads for running application logic.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/pool/thread/package.html b/quickserver/src/main/org/quickserver/util/pool/thread/package.html
new file mode 100644
index 0000000..05a3727
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/pool/thread/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE>Overview</TITLE>

+</HEAD>

+

+<BODY>

+Classes for managing the pool of threads for handling clients.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/AccessConstraintConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/AccessConstraintConfig.java
new file mode 100644
index 0000000..b26a687
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/AccessConstraintConfig.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+import java.net.*;
+import java.io.*;
+import java.util.logging.*;
+
+/**
+ * This class encapsulate the access constraints on servers running.
+ * The xml is &lt;access-constraint&gt;...&lt;/access-constraint&gt;.
+ * @author Akshathkumar Shetty
+ * @since 1.3.3
+ */
+public class AccessConstraintConfig implements Serializable {
+	private static final Logger logger = Logger.getLogger(AccessConstraintConfig.class.getName());
+
+	private IpFilterConfig ipFilterConfig;
+	
+	
+	/**
+	 * Returns the IpFilterConfig.
+	 * @return IpFilterConfig
+	 */
+	public IpFilterConfig getIpFilterConfig() {
+		return ipFilterConfig;
+	}
+	/**
+	 * Sets the IpFilterConfig
+	 * XML Tag: &lt;ip-filter&gt;&lt;/ip-filter&gt;
+	 * @param ipFilterConfig
+	 */
+	public void setIpFilterConfig(IpFilterConfig ipFilterConfig) {
+		this.ipFilterConfig = ipFilterConfig;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+
+		sb.append(pad+"<access-constraint>\n");
+		if(getIpFilterConfig()!=null)
+			sb.append(getIpFilterConfig().toXML(pad+"\t"));
+		sb.append(pad+"</access-constraint>\n");
+		return sb.toString();
+	}
+
+	/**
+	 * Finds if the socket has access to connect to server.
+	 * Based on the access constrains set.
+	 * @exception SecurityException if access not allowed.
+	 */
+	public void checkAccept(Socket socket) {
+		if(socket==null || ipFilterConfig==null || ipFilterConfig.getEnable()==false)
+			return;
+		String remoteIp = socket.getInetAddress().getHostAddress();
+		boolean accessFlag = ipFilterConfig.getAllowAccess()==true;
+
+		if(ipFilterConfig.getIpCollection().contains(remoteIp)!=accessFlag) {
+			try	{
+				socket.close();	
+			} catch(IOException e) {
+				logger.warning("IOException : "+e.getMessage());
+			}			
+			socket = null;
+			throw new SecurityException("Accept denied from "+remoteIp);
+		}
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/AdvancedSettings.java b/quickserver/src/main/org/quickserver/util/xmlreader/AdvancedSettings.java
new file mode 100644
index 0000000..5557402
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/AdvancedSettings.java
@@ -0,0 +1,362 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.nio.charset.UnsupportedCharsetException;	
+import java.nio.charset.Charset;
+
+/**
+ * This class encapsulate Advanced Settings.
+ * The example xml is <pre>
+	....
+	&lt;advanced-settings&gt;
+		&lt;charset&gt;ISO-8859-1&lt;charset&gt;
+		&lt;byte-buffer-size&gt;61440&lt;byte-buffer-size&gt;
+		&lt;use-direct-byte-buffer&gt;true&lt;/use-direct-byte-buffer&gt;
+		&lt;backlog&gt;1024&lt;/backlog&gt;		
+		&lt;socket-linger&gt;-1&lt;/socket-linger&gt;
+		&lt;debug-non-blocking-mode&gt;false&lt;/debug-non-blocking-mode&gt; 
+ 
+        &lt;performance-preferences-connection-time&gt;2&lt;performance-preferences-connection-time&gt;
+        &lt;performance-preferences-latency&gt;4&lt;performance-preferences-latency&gt;
+        &lt;performance-preferences-bandwidth&gt;2&lt;performance-preferences-bandwidth&gt;
+ 
+        &lt;client-socket-tcp-no-delay&gt;false&lt;client-socket-tcp-no-delay&gt;
+        &lt;client-socket-tcp-traffic-class&gt;10&lt;client-socket-tcp-traffic-class&gt;
+ 
+        &lt;client-socket-receive-buffer-size&gt;0&lt;client-socket-receive-buffer-size&gt;
+        &lt;client-socket-send-buffer-size&gt;0&lt;client-socket-send-buffer-size&gt;
+ 	&lt;/advanced-settings&gt;
+	....
+ </pre>
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public class AdvancedSettings implements java.io.Serializable {
+	private String charset = "ISO-8859-1";
+	private int byteBufferSize = 1024*64;
+	private int backlog = 0;
+	private boolean useDirectByteBuffer = true;
+	private int socketLinger = -1;
+	private boolean debugNonBlockingMode;
+	private String clientIdentifierClass = 
+		"org.quickserver.net.server.impl.OptimisticClientIdentifier";
+	private String qsObjectPoolMakerClass = null;
+	private int maxThreadsForNioWrite = 10;
+	
+	private int performancePreferencesConnectionTime = 0;//2
+	private int performancePreferencesLatency = 0;//4
+	private int performancePreferencesBandwidth = 0;
+	
+	private boolean clientSocketTcpNoDelay = false;
+	private String clientSocketTrafficClass;
+	
+	private int clientSocketReceiveBufferSize;
+	private int clientSocketSendBufferSize;
+
+	/**
+     * Sets the Charset to be used for String decoding and encoding.
+	 * XML Tag: &lt;charset&gt;ISO-8859-1&lt;/charset&gt;
+	 * @param charset to be used for String decoding and encoding
+	 * @see #getCharset
+     */
+	public void setCharset(String charset) {
+		if(charset==null || charset.trim().length()==0)
+			return;
+		if(Charset.isSupported(charset)==false) {
+			throw new UnsupportedCharsetException(charset);
+		}
+		this.charset = charset;
+	}
+	/**
+     * Returns Charset to be used for String decoding and encoding..
+     * @see #setCharset
+     */
+	public String getCharset() {
+		return charset;
+	}
+
+	/**
+     * Sets the ByteBuffer size to be used in ByteBuffer pool.
+	 * XML Tag: &lt;byte-buffer-size&gt;65536&lt;/byte-buffer-size&gt;
+	 * @param byteBufferSize size to be used in ByteBuffer pool.
+	 * @see #getByteBufferSize
+     */
+	public void setByteBufferSize(int byteBufferSize) {
+		if(byteBufferSize>0)
+			this.byteBufferSize = byteBufferSize;
+	}
+	/**
+     * Returns ByteBuffer size to be used in ByteBuffer pool.
+     * @see #setByteBufferSize
+     */
+	public int getByteBufferSize() {
+		return byteBufferSize;
+	}
+
+	/**
+     * Sets the listen backlog length for the QuickServer to listen on.
+	 * If not set or set a value equal or less than 0, then the default 
+	 * value will be assumed.<br/>
+	 * XML Tag: &lt;backlog&gt;0&lt;/backlog&gt;
+	 * @param backlog The listen backlog length.
+     * @see #getBacklog
+     */
+	public void setBacklog(int backlog) {
+		if(backlog>=0)
+			this.backlog = backlog;
+	}
+	/**
+     * Returns the listen backlog length for the QuickServer.
+     * @see #setBacklog
+     */
+	public int getBacklog() {
+		return backlog;
+	}
+
+	/**
+     * Sets the UseDirectByteBuffer flag.
+	 * If not set, it will use <code>true</code><br/>
+	 * XML Tag: &lt;use-direct-byte-buffer&gt;true&lt;/use-direct-byte-buffer&gt;
+	 * @param flag UseDirectByteBuffer flag.
+     * @see #getUseDirectByteBuffer
+     */
+	public void setUseDirectByteBuffer(boolean flag) {
+		this.useDirectByteBuffer = flag;
+	}
+	/**
+     * Returns UseDirectByteBuffer flag.
+     * @see #setUseDirectByteBuffer
+     */
+	public boolean getUseDirectByteBuffer() {
+		return useDirectByteBuffer;
+	}
+
+	/**
+     * Enable SO_LINGER with the specified linger time in seconds. If linger time is less than
+	 * <code>0</code> SO_LINGER will be disable.
+	 * XML Tag: &lt;socket-linger&gt;-1&lt;/socket-linger&gt;
+	 * @param socketLinger if the linger value is negative SO_LINGER will be disable.
+     * @see #getSocketLinger
+     */
+	public void setSocketLinger(int socketLinger) {
+		this.socketLinger = socketLinger;
+	}
+	/**
+     * Returns linger time in seconds. If SO_LINGER is disabled time will be negative;
+     * @see #setSocketLinger
+     */
+	public int getSocketLinger() {
+		return socketLinger;
+	}
+	
+	/**
+     * Sets the DebugNonBlockingMode flag.
+	 * If not set, it will use <code>false</code><br/>
+	 * XML Tag: &lt;debug-non-blocking-mode&gt;false&lt;/debug-non-blocking-mode&gt;
+	 * @param debugNonBlockingMode DebugNonBlockingMode flag.
+     * @see #getDebugNonBlockingMode
+     */
+    public void setDebugNonBlockingMode(boolean debugNonBlockingMode) {
+        this.debugNonBlockingMode = debugNonBlockingMode;
+    }
+	/**
+     * Returns DebugNonBlockingMode flag.
+     * @see #setDebugNonBlockingMode
+     */
+	public boolean getDebugNonBlockingMode() {
+        return debugNonBlockingMode;
+    }
+
+	/**
+     * Sets the ClientIdentifier class that implements 
+	 * {@link org.quickserver.net.server.ClientIdentifier}.
+	 * XML Tag: &lt;client-identifier&gt;org.quickserver.net.server.impl.TryClientIdentifier&lt;/client-identifier&gt;
+	 * @param clientIdentifierClass the fully qualified name of the class that 
+	 * implements {@link org.quickserver.net.server.ClientIdentifier}.
+	 * @see #getClientIdentifier
+     */
+	public void setClientIdentifier(String clientIdentifierClass) {
+		if(clientIdentifierClass==null || clientIdentifierClass.trim().length()==0)
+			return;
+		this.clientIdentifierClass = clientIdentifierClass;
+	}
+	/**
+     * Returns the ClientIdentifier class that that implements 
+	 * {@link org.quickserver.net.server.ClientIdentifier}.
+     * @see #setClientIdentifier
+     */
+	public String getClientIdentifier() {
+		return clientIdentifierClass;
+	}
+
+	/**
+     * Sets the QSObjectPoolMaker class that implements 
+	 * {@link org.quickserver.util.pool.QSObjectPoolMaker}.
+	 * XML Tag: &lt;qsobject-pool-maker&gt;org.quickserver.util.pool.MakeQSObjectPool&lt;/qsobject-pool-maker&gt;
+	 * @param qsObjectPoolMakerClass the fully qualified name of the class that 
+	 * implements {@link org.quickserver.util.pool.QSObjectPoolMaker}.
+	 * @see #getQSObjectPoolMaker
+     */
+	public void setQsObjectPoolMaker(String qsObjectPoolMakerClass) {
+		this.qsObjectPoolMakerClass = qsObjectPoolMakerClass;
+	}
+	/**
+     * Returns the QsObjectPoolMaker class that implements 
+	 * {@link org.quickserver.util.pool.QSObjectPoolMaker}.
+     * @see #setQSObjectPoolMaker
+     */
+	public String getQsObjectPoolMaker() {
+		if(qsObjectPoolMakerClass==null)
+			qsObjectPoolMakerClass = "org.quickserver.util.pool.MakeQSObjectPool";
+		return qsObjectPoolMakerClass;
+	}
+
+	/**
+     * Sets the maximum threads allowed for nio write. If set to 0 or less no limit is 
+	 * imposed.
+	 * XML Tag: &lt;max-threads-for-nio-write&gt;10&lt;/max-threads-for-nio-write&gt;
+	 * @param maxThreadsForNioWrite maximum threads allowed for nio write
+     * @see #getMaxThreadsForNioWrite
+	 * @since 1.4.6
+     */
+	public void setMaxThreadsForNioWrite(int maxThreadsForNioWrite) {
+		this.maxThreadsForNioWrite = maxThreadsForNioWrite;
+	}
+	/**
+     * Returns the maximum threads allowed for nio write.
+     * @see #setMaxThreadsForNioWrite
+	 * @since 1.4.6
+     */
+	public int getMaxThreadsForNioWrite() {
+		return maxThreadsForNioWrite;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<advanced-settings>\n");
+		sb.append(pad+"\t<charset>").append(getCharset()).append("</charset>\n");
+		sb.append(pad).append("\t<use-direct-byte-buffer>").append(
+				getUseDirectByteBuffer()).append("</use-direct-byte-buffer>\n");
+		sb.append(pad).append("\t<byte-buffer-size>").append(getByteBufferSize()
+				).append("</byte-buffer-size>\n");
+		sb.append(pad).append("\t<backlog>").append(getBacklog()).append("</backlog>\n");
+		sb.append(pad).append("\t<socket-linger>").append(getSocketLinger()).append("</socket-linger>\n");
+		sb.append(pad).append("\t<debug-non-blocking-mode>").append(
+				getDebugNonBlockingMode()).append("</debug-non-blocking-mode>\n");
+		sb.append(pad).append("\t<client-identifier>").append(
+				getClientIdentifier()).append("</client-identifier>\n");
+		sb.append(pad).append("\t<qsobject-pool-maker>").append(
+				getQsObjectPoolMaker()).append("</qsobject-pool-maker>\n");
+		sb.append(pad).append("\t<max-threads-for-nio-write>").append(
+				getMaxThreadsForNioWrite()).append("</max-threads-for-nio-write>\n");
+		
+		sb.append(pad).append("\t<performance-preferences-connection-time>").append(
+			getPerformancePreferencesConnectionTime()).append(
+				"</performance-preferences-connection-time>\n");
+		sb.append(pad).append("\t<performance-preferences-latency>").append(
+			getPerformancePreferencesLatency()).append(
+				"</performance-preferences-latency>\n");
+		sb.append(pad).append("\t<performance-preferences-bandwidth>").append(
+			getPerformancePreferencesBandwidth()).append(
+				"</performance-preferences-bandwidth>\n");
+		
+		sb.append(pad).append("\t<client-socket-tcp-no-delay>").append(
+			getClientSocketTcpNoDelay()).append(
+				"</client-socket-tcp-no-delay>\n");
+		if(getClientSocketTrafficClass()!=null) {
+			sb.append(pad).append("\t<client-socket-traffic-class>").append(
+				getClientSocketTrafficClass()).append(
+					"</client-socket-traffic-class>\n");
+		}
+		
+		if(getClientSocketReceiveBufferSize()!=0) {
+			sb.append(pad).append("\t<client-socket-receive-buffer-size>").append(
+				getClientSocketReceiveBufferSize()).append(
+					"</client-socket-receive-buffer-size>\n");
+		}
+		if(getClientSocketSendBufferSize()!=0) {
+			sb.append(pad).append("\t<client-socket-send-buffer-size>").append(
+				getClientSocketSendBufferSize()).append(
+					"</client-socket-send-buffer-size>\n");
+		}
+
+		
+		sb.append(pad).append("</advanced-settings>\n");
+		return sb.toString();
+	}
+
+	public int getPerformancePreferencesConnectionTime() {
+		return performancePreferencesConnectionTime;
+	}
+
+	public void setPerformancePreferencesConnectionTime(int performancePreferencesConnectionTime) {
+		this.performancePreferencesConnectionTime = performancePreferencesConnectionTime;
+	}
+
+	public int getPerformancePreferencesLatency() {
+		return performancePreferencesLatency;
+	}
+
+	public void setPerformancePreferencesLatency(int performancePreferencesLatency) {
+		this.performancePreferencesLatency = performancePreferencesLatency;
+	}
+
+	public int getPerformancePreferencesBandwidth() {
+		return performancePreferencesBandwidth;
+	}
+
+	public void setPerformancePreferencesBandwidth(int performancePreferencesBandwidth) {
+		this.performancePreferencesBandwidth = performancePreferencesBandwidth;
+	}
+
+	public boolean getClientSocketTcpNoDelay() {
+		return clientSocketTcpNoDelay;
+	}
+
+	public void setClientSocketTcpNoDelay(boolean clientSocketTcpNoDelay) {
+		this.clientSocketTcpNoDelay = clientSocketTcpNoDelay;
+	}
+
+	public String getClientSocketTrafficClass() {
+		return clientSocketTrafficClass;
+	}
+
+	public void setClientSocketTrafficClass(String clientSocketTrafficClass) {
+		this.clientSocketTrafficClass = clientSocketTrafficClass;
+	}
+
+	public int getClientSocketReceiveBufferSize() {
+		return clientSocketReceiveBufferSize;
+	}
+
+	public void setClientSocketReceiveBufferSize(int clientSocketReceiveBufferSize) {
+		this.clientSocketReceiveBufferSize = clientSocketReceiveBufferSize;
+	}
+
+	public int getClientSocketSendBufferSize() {
+		return clientSocketSendBufferSize;
+	}
+
+	public void setClientSocketSendBufferSize(int clientSocketSendBufferSize) {
+		this.clientSocketSendBufferSize = clientSocketSendBufferSize;
+	}
+
+    
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ApplicationConfiguration.java b/quickserver/src/main/org/quickserver/util/xmlreader/ApplicationConfiguration.java
new file mode 100644
index 0000000..cae1514
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ApplicationConfiguration.java
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+
+/**
+ * This class encapsulate the Application Configuration.
+ * The example xml is <pre>
+ &lt;quickserver&gt;
+	....
+	&lt;application-configuration&gt;
+		&lt;property&gt;
+			&lt;property-name&gt;FTP_ROOT&lt;/property-name&gt;
+			&lt;property-value&gt;c:\&lt;/property-value&gt;
+		&lt;/property&gt;
+		&lt;property&gt;
+			&lt;property-name&gt;Server Name&lt;/property-name&gt;
+			&lt;property-value&gt;My Server&lt;/property-value&gt;
+		&lt;/property&gt;
+	&lt;/application-configuration&gt;
+	....
+&lt;/quickserver&gt;
+</pre>
+ * @author Akshathkumar Shetty
+ * @since 1.3.2
+ */
+public class ApplicationConfiguration extends HashMap {
+	private String promptType = "gui";//OR console
+
+	/**
+	 * Sets the PromptType.
+	 * XML Tag: &lt;prompt-type&gt;true&lt;/prompt-typ&gt;
+	 * Allowed values = <code>gui</code> | <code>console</code>
+ 	 * @see #getPromptType
+	 * @since 1.4.5
+	 */
+	public void setPromptType(String promptType) {
+		if(promptType!=null && promptType.equals("")==false)
+			if(promptType.equals("gui") || promptType.equals("console"))
+				this.promptType = promptType;
+	}
+	/**
+	 * Returns the PromptType
+	 * @see #setPromptType
+	 * @since 1.4.5
+	 */
+	public String getPromptType() {
+		return promptType;
+	}
+
+	/**
+	 * Addes the {@link Property} passed to the HashMap
+	 */
+	public void addProperty(Property property) {
+		put(property.getName(), property.getValue());
+	}
+
+	/**
+	 * Finds if any {@link Property} is present.
+	 * @return <code>null</code> if no Property was found.
+	 */
+	public Property findProperty(String name) {
+		String temp = (String) get(name);
+		if(temp!=null) {
+			return new Property(name, temp);
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<application-configuration>\n");
+		
+		sb.append(pad).append("\t<prompt-type>").append(getPromptType()).append("</prompt-type>");
+
+		Iterator iterator = keySet().iterator();
+		while(iterator.hasNext()) {
+			String key = (String) iterator.next();
+			String value = (String) get(key);
+			sb.append(pad).append("\t<property>");
+			sb.append(pad).append("\t\t<property-name>").append(key).append("</property-name>\n");
+			sb.append(pad).append("\t\t<property-value>").append(value).append("</property-value>\n");
+			sb.append(pad).append("\t</property>\n");
+		}
+		sb.append(pad).append("</application-configuration>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/BasicServerConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/BasicServerConfig.java
new file mode 100644
index 0000000..bff6b63
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/BasicServerConfig.java
@@ -0,0 +1,703 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import org.quickserver.net.server.*;
+
+/**
+ * This class encapsulate the basic configuration of QuickServer.
+ * @author Akshathkumar Shetty
+ * @since 1.2
+ * @see org.quickserver.util.xmlreader.QuickServerConfig
+ * @see org.quickserver.util.xmlreader.QSAdminServerConfig
+ */
+public class BasicServerConfig implements java.io.Serializable {
+	
+	private String clientAuthenticationHandler; //v1.4.6
+	private String clientEventHandler; //v1.4.6
+	private String clientExtendedEventHandler; //v1.4.6
+	private String clientCommandHandler;
+	private String clientObjectHandler;
+	private String clientBinaryHandler;
+	private String clientData;
+	private String clientWriteHandler; //v1.4.5
+	
+	private String serverBanner;
+	private String name = null;
+	private String maxConnectionMsg = "-ERR Server Busy. Max Connection Reached";	
+	private String timeoutMsg = "-ERR Timeout";
+	private int maxAuthTry = 5;
+	private String maxAuthTryMsg = "-ERR Max Auth Try Reached";
+	private int port = 9876;	
+	private String bindAddr;
+	private long maxConnection = -1;
+	private int timeout = 1 * 60 * 1000; //1 min. socket timeout	
+	
+	private String consoleLoggingLevel = "INFO";
+	private String consoleLoggingFormatter;
+
+	//for object pool
+	private ObjectPoolConfig objectPoolConfig = new ObjectPoolConfig();
+	private boolean communicationLogging = false;
+
+	//v1.3.3
+	private AccessConstraintConfig accessConstraintConfig;
+	private ServerHooks serverHooks;
+
+	//v1.4.0
+	private Secure secure = new Secure();
+	private ServerMode serverMode = new ServerMode();
+
+	//v1.4.5
+	private AdvancedSettings advancedSettings = new AdvancedSettings();
+
+	//v1.4.6
+	private DefaultDataMode defaultDataMode = new DefaultDataMode();
+
+	/**
+     * Returns the name of the QuickServer
+     * @see #setName
+     */
+	public String getName() {
+		return name;
+	}
+    /**
+     * Sets the name for the QuickServer. 
+	 * XML Tag: &lt;name&gt;&lt;/name&gt;
+     * @param name for the QuickServer
+     * @see #getName
+     */
+	public void setName(String name) {
+		if(name!=null && name.equals("")==false) 
+			this.name = name;
+	}
+
+	/**
+     * Returns the Server Banner of the QuickServer
+     * @see #setServerBanner
+     */
+	public String getServerBanner() {
+		return serverBanner;
+	}
+    /**
+     * Sets the serverBanner for the QuickServer
+	 * that will be displayed on the standard output [console]
+	 * when server starts. &lt;br&gt;&nbsp;&lt;br&gt;
+	 * To set welcome message to your client
+	 * {@link org.quickserver.net.server.ClientEventHandler#gotConnected} 
+	 * XML Tag: &lt;server-banner&gt;&lt;/server-banner&gt;
+	 * @param banner for the QuickServer
+     * @see #getServerBanner
+     */
+	public void setServerBanner(String banner) {
+		if(banner!=null && banner.equals("")==false) 
+			serverBanner = banner;
+	}
+
+	/**
+     * Sets the port for the QuickServer to listen on.
+	 * If not set, it will run on Port 9876<br/>
+	 * XML Tag: &lt;port&gt;&lt;/port&gt;
+	 * @param port to listen on.
+     * @see #getPort
+     */
+	public void setPort(int port) {
+		if(port>=0)
+			this.port = port;
+	}
+	/**
+     * Returns the port for the QuickServer
+     * @see #setPort
+     */
+	public int getPort() {
+		return port;
+	}
+
+	/**
+     * Sets the ClientCommandHandler class that interacts with 
+	 * client sockets.
+	 * XML Tag: &lt;client-command-handler&gt;&lt;/client-command-handler&gt;
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link org.quickserver.net.server.ClientCommandHandler}
+	 * @see #getClientCommandHandler
+     */
+	public void setClientCommandHandler(String handler) {
+		if(handler!=null && handler.equals("")==false) 
+			clientCommandHandler = handler;
+	}
+	/**
+     * Sets the ClientCommandHandler class that interacts with 
+	 * client sockets.
+	 * @since 1.4.6
+     */
+	public void setClientCommandHandler(ClientCommandHandler handler) {
+		if(handler!=null) 
+			clientCommandHandler = handler.getClass().getName();
+	}
+	/**
+     * Returns the ClientCommandHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientCommandHandler
+     */
+	public String getClientCommandHandler() {
+		return clientCommandHandler;
+	}
+
+	/**
+     * Sets the ClientEventHandler class that gets notified of
+	 * client events.
+	 * XML Tag: &lt;client-event-handler&gt;&lt;/client-event-handler&gt;
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link org.quickserver.net.server.ClientEventHandler}
+	 * @see #getClientEventHandler
+	 * @since 1.4.6
+     */
+	public void setClientEventHandler(String handler) {
+		if(handler!=null && handler.equals("")==false) 
+			clientEventHandler = handler;
+	}
+	/**
+     * Sets the ClientEventHandler class that gets notified of
+	 * client events.
+	 * @since 1.4.6
+     */
+	public void setClientEventHandler(ClientEventHandler handler) {
+		if(handler!=null) 
+			clientEventHandler = handler.getClass().getName();
+	}
+	/**
+     * Returns the ClientEventHandler class that gets notified of
+	 * client events.
+	 * @see #setClientEventHandler
+	 * @since 1.4.6
+     */
+	public String getClientEventHandler() {
+		return clientEventHandler;
+	}
+
+	/**
+     * Sets the ClientExtendedEventHandler class that gets notified of
+	 * client's extended events.
+	 * XML Tag: &lt;client-extended-event-handler&gt;&lt;/client-extended-event-handler&gt;
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link org.quickserver.net.server.ClientExtendedEventHandler}
+	 * @see #getClientExtendedEventHandler
+	 * @since 1.4.6
+     */
+	public void setClientExtendedEventHandler(String handler) {
+		if(handler!=null && handler.equals("")==false) 
+			clientExtendedEventHandler = handler;
+	}
+	/**
+     * Sets the ClientExtendedEventHandler class that gets notified of
+	 * client's extended events.
+	 * @since 1.4.6
+     */
+	public void setClientExtendedEventHandler(ClientExtendedEventHandler handler) {
+		if(handler!=null) 
+			clientExtendedEventHandler = handler.getClass().getName();
+	}
+	/**
+     * Returns the ClientExtendedEventHandler class that gets notified of
+	 * client's extended events.
+	 * @see #setClientExtendedEventHandler
+	 * @since 1.4.6
+     */
+	public String getClientExtendedEventHandler() {
+		return clientExtendedEventHandler;
+	}
+
+	/**
+     * Sets the Authenticator class that handles the 
+	 * authentication of the client.
+	 * XML Tag: &lt;authenticator&gt;&lt;/authenticator&gt;
+	 * @param authenticator the fully qualified name of the class 
+	 * that implements {@link org.quickserver.net.server.Authenticator}.
+	 * @see #getAuthenticator
+	 * @since 1.3
+     */
+	public void setAuthenticator(String authenticator) {
+		if(authenticator!=null && authenticator.equals("")==false) 
+			this.clientAuthenticationHandler = authenticator;
+	}
+	/**
+     * Sets the Authenticator class that handles the 
+	 * authentication of the client.
+	 * @since 1.4.6
+     */
+	public void setAuthenticator(Authenticator authenticator) {
+		if(authenticator!=null) 
+			this.clientAuthenticationHandler = authenticator.getClass().getName();
+	}
+	/**
+     * Returns the Authenticator class that handles the 
+	 * authentication of the client.
+	 * @see #setAuthenticator
+	 * @since 1.3
+     */
+	public String getAuthenticator() {
+		return clientAuthenticationHandler;
+	}
+
+	/**
+     * Sets the ClientAuthenticationHandler class that handles the 
+	 * authentication of the client.
+	 * XML Tag: &lt;client-authentication-handler&gt;&lt;/client-authentication-handler&gt;
+	 * @param clientAuthenticationHandler the fully qualified name of the class 
+	 * that implements {@link org.quickserver.net.server.ClientAuthenticationHandler}.
+	 * @see #getClientAuthenticationHandler
+	 * @since 1.4.6
+     */
+	public void setClientAuthenticationHandler(String clientAuthenticationHandler) {
+		if(clientAuthenticationHandler!=null && clientAuthenticationHandler.equals("")==false) 
+			this.clientAuthenticationHandler = clientAuthenticationHandler;
+	}
+	/**
+     * Sets the ClientAuthenticationHandler class that handles the 
+	 * authentication of the client.
+	 * @since 1.4.6
+     */
+	public void setClientAuthenticationHandler(ClientAuthenticationHandler clientAuthenticationHandler) {
+		if(clientAuthenticationHandler!=null) 
+			this.clientAuthenticationHandler = clientAuthenticationHandler.getClass().getName();
+	}
+	/**
+     * Returns the ClientAuthenticationHandler class that handles the 
+	 * authentication of the client.
+	 * @see #setClientAuthenticationHandler
+	 * @since 1.4.6
+     */
+	public String getClientAuthenticationHandler() {
+		return clientAuthenticationHandler;
+	}
+
+	/**
+     * Sets the ClientData class that carries client data. 
+	 * XML Tag: &lt;client-data&gt;&lt;/client-data&gt;
+	 * @param data the fully qualified name of the class that 
+	 * extends {@link org.quickserver.net.server.ClientData}.
+	 * @see #getClientData
+     */
+	public void setClientData(String data) {
+		if(data!=null && data.equals("")==false)
+			this.clientData = data;
+	}
+	/**
+     * Sets the ClientData class that carries client data. 
+	 * @since 1.4.6
+     */
+	public void setClientData(ClientData data) {
+		if(data!=null)
+			this.clientData = data.getClass().getName();
+	}
+	/**
+     * Returns the ClientData class string that carries client data  
+	 * @return the fully qualified name of the class that 
+	 * implements {@link org.quickserver.net.server.ClientData}.
+	 * @see #setClientData
+     */
+	public String getClientData() {
+		return clientData;
+	}
+
+	/**
+     * Sets the Client Socket timeout in milliseconds.
+	 * XML Tag: &lt;timeout&gt;&lt;/timeout&gt;
+	 * @param time client socket timeout in milliseconds.
+	 * @see #getTimeout
+     */
+	public void setTimeout(int time) {
+		timeout = time;
+	}
+	/**
+     * Returns the Client Socket timeout in milliseconds.
+	 * @see #setTimeout
+     */
+	public int getTimeout() {
+		return timeout;
+	}
+
+	/** 
+	 * Sets maximum allowed login attempts.
+	 * XML Tag: &lt;max-auth-try&gt;&lt;/max-auth-try&gt;
+	 */
+	public void setMaxAuthTry(int authTry) {
+		maxAuthTry = authTry;
+	}
+	/** 
+	 * Returns maximum allowed login attempts.
+	 * Default is : 5
+	 */
+	public int getMaxAuthTry() {
+		return maxAuthTry;
+	}
+
+	/** 
+	 * Sets message to be displayed when maximum allowed login 
+	 * attempts has reached.
+	 * Default is : -ERR Max Auth Try Reached<br/>
+	 * XML Tag: &lt;max-auth-try-msg&gt;&lt;/max-auth-try-msg&gt;
+	 * @see #getMaxAuthTryMsg
+	 */
+	public void setMaxAuthTryMsg(String msg) {
+		if(msg!=null && msg.equals("")==false)
+			maxAuthTryMsg = msg;
+	}
+	/** 
+	 * Returns message to be displayed when maximum allowed login 
+	 * attempts has reached.
+	 * @see #getMaxAuthTryMsg
+	 */
+	public String getMaxAuthTryMsg() {
+		return maxAuthTryMsg;
+	}
+
+	/**
+	 * Sets timeout message. 
+	 * Default is : -ERR Timeout<br/>
+	 * XML Tag: &lt;timeout-msg&gt;&lt;/timeout-msg&gt;
+	 * @see #getTimeoutMsg
+	 */
+	public void setTimeoutMsg(String msg) {
+		if(msg!=null && msg.equals("")==false)
+			timeoutMsg = msg;
+	}
+	/** 
+	 * Returns timeout message.
+	 * @see #setTimeoutMsg
+	 */
+	public String getTimeoutMsg() {
+		return timeoutMsg;
+	}
+
+	/**
+	 * Sets the maximum number of client connection allowed..
+	 * XML Tag: &lt;max-connection&gt;&lt;/max-connection&gt;
+	 * @see #getMaxConnection
+	 */
+	public void setMaxConnection(long maxConnection) {
+		this.maxConnection = maxConnection;
+	}
+	/** 
+	 * Returns the maximum number of client connection allowed.
+	 * @see #setMaxConnection
+	 */
+	public long getMaxConnection() {
+		return maxConnection;
+	}
+
+	/**
+	 * Sets the message to be sent to any new client connected after
+	 * maximum client connection has reached. 
+	 * Default is : <code>-ERR Server Busy. Max Connection Reached</code><br/>
+	 * XML Tag: &lt;max-connection-msg&gt;&lt;/max-connection-msg&gt;
+	 * @see #getMaxConnectionMsg
+	 */
+	public void setMaxConnectionMsg(String maxConnectionMsg) {
+		if(maxConnectionMsg!=null && maxConnectionMsg.equals("")==false)
+			this.maxConnectionMsg = maxConnectionMsg;
+	}
+	/**
+	 * Returns the message to be sent to any new client connected 
+	 * after maximum client connection has reached.
+	 * @see #setMaxConnectionMsg
+	 */
+	public String getMaxConnectionMsg() {
+		return maxConnectionMsg;
+	}
+
+	/**
+	 * Sets the Ip address to bind to. 
+	 * @param bindAddr argument can be used on a multi-homed host for a 
+	 * QuickServer that will only accept connect requests to one 
+	 * of its addresses. If not set, it will default accepting 
+	 * connections on any/all local addresses.
+	 * XML Tag: &lt;bind-address&gt;&lt;/bind-address&gt;
+	 * @see #getBindAddr
+	 */
+	public void setBindAddr(String bindAddr) {
+		if(bindAddr!=null && bindAddr.equals("")==false)
+			this.bindAddr = bindAddr;
+	}
+	/**
+	 * Returns the Ip address binding to. 
+	 * @see #setBindAddr
+	 */
+	public String getBindAddr() {
+		return bindAddr;
+	}
+
+	/**
+     * Sets the ClientObjectHandler class that interacts with 
+	 * client sockets.
+	 * XML Tag: &lt;client-object-handler&gt;&lt;/client-object-handler&gt;
+	 * @param handler object the fully qualified name of the class that 
+	 *  implements {@link org.quickserver.net.server.ClientObjectHandler}
+	 * @see #getClientObjectHandler
+     */
+	public void setClientObjectHandler(String handler) {
+		if(handler!=null && handler.equals("")==false)
+			clientObjectHandler = handler;
+	}
+	/**
+     * Sets the ClientObjectHandler class that interacts with 
+	 * client sockets.
+	 * @since 1.4.6
+     */
+	public void setClientObjectHandler(ClientObjectHandler handler) {
+		if(handler!=null)
+			clientObjectHandler = handler.getClass().getName();
+	}
+	/**
+     * Returns the ClientObjectHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientObjectHandler
+     */
+	public String getClientObjectHandler() {
+		return clientObjectHandler;
+	}
+
+	/**
+	 * Sets the console log handler level.
+	 * XML Tag: &lt;console-logging-level&gt;&lt;/console-logging-level&gt;
+	 * @param level like INFO, FINE, CONFIG
+	 */
+	public void setConsoleLoggingLevel(String level) {
+		if(level!=null && level.equals("")==false)
+			consoleLoggingLevel = level;
+	}
+	/**
+	 * Returns the console log handler level.
+	 */
+	public String getConsoleLoggingLevel() {
+		return consoleLoggingLevel;
+	}
+
+	/**
+	 * Sets the console log handler formatter.
+	 * XML Tag: &lt;console-logging-formatter&gt;&lt;/console-logging-formatter&gt;
+	 * @param formatter fully qualified name of the class that 
+	 *  implements {@link java.util.logging.Formatter}
+	 */
+	public void setConsoleLoggingFormatter(String formatter) {
+		if(formatter!=null && formatter.equals("")==false)
+			consoleLoggingFormatter = formatter;
+	}
+	/**
+	 * Returns the console log handler level.
+	 */
+	public String getConsoleLoggingFormatter() {
+		return consoleLoggingFormatter;
+	}
+
+	/**
+	 * Sets the ObjectPool Config object.
+	 * XML Tag: &lt;object-pool&gt;&lt;/object-pool&gt;
+	 */
+	public void setObjectPoolConfig(ObjectPoolConfig objectPoolConfig) {
+		if(objectPoolConfig!=null)
+			this.objectPoolConfig = objectPoolConfig;
+	}
+	/**
+	 * Returns the ObjectPool Config object.
+	 */
+	public ObjectPoolConfig getObjectPoolConfig() {
+		return objectPoolConfig;
+	}
+
+	/**
+	 * Sets the communication logging flag.
+	 * @see #getCommunicationLogging
+	 * XML Tag: &lt;communication-logging&gt;&lt;enable&gt;true&lt;/enable&gt;&lt;/communication-logging&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+	 * @since 1.3.2
+	 */
+	public void setCommunicationLogging(boolean enable) {
+		this.communicationLogging = enable;
+	}
+	/**
+	 * Returns the communication logging flag.
+	 * @see #setCommunicationLogging
+	 * @since 1.3.2
+	 */
+	public boolean getCommunicationLogging() {
+		return communicationLogging;
+	}
+
+	/**
+	 * Sets the Access constraints
+	 * @since 1.3.3
+	 */
+	public void setAccessConstraintConfig(
+		AccessConstraintConfig accessConstraintConfig) {
+		this.accessConstraintConfig = accessConstraintConfig;
+	}
+	/**
+	 * Returns Access constraints if present else <code>null</code>.
+	 * @since 1.3.3
+	 */
+	public AccessConstraintConfig getAccessConstraintConfig() {
+		return accessConstraintConfig;
+	}
+
+	/**
+	 * Sets the ServerHooks
+	 * @since 1.3.3
+	 */
+	public void setServerHooks(ServerHooks serverHooks) {
+		this.serverHooks = serverHooks;
+	}
+	/**
+	 * Returns ServerHooks if present else <code>null</code>.
+	 * @since 1.3.3
+	 */
+	public ServerHooks getServerHooks() {
+		return serverHooks;
+	}
+
+	/**
+	 * Sets the Secure setting for QuickServer
+	 * @since 1.4.0
+	 */
+	public void setSecure(Secure secure) {
+		this.secure = secure;
+	}
+	/**
+	 * Returns Secure setting for QuickServer
+	 * @since 1.4.0
+	 */
+	public Secure getSecure() {
+		return secure;
+	}
+
+	/**
+     * Sets the ClientBinaryHandler class that interacts with 
+	 * client sockets.
+	 * XML Tag: &lt;client-binary-handler&gt;&lt;/client-binary-handler&gt;
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link org.quickserver.net.server.ClientBinaryHandler}
+	 * @see #getClientBinaryHandler
+     */
+	public void setClientBinaryHandler(String handler) {
+		if(handler!=null && handler.equals("")==false) 
+			clientBinaryHandler = handler;
+	}
+	/**
+     * Sets the ClientBinaryHandler class that interacts with 
+	 * client sockets.
+	 * @since 1.4.6
+     */
+	public void setClientBinaryHandler(ClientBinaryHandler handler) {
+		if(handler!=null) 
+			clientBinaryHandler = handler.getClass().getName();
+	}
+	/**
+     * Returns the ClientBinaryHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientBinaryHandler
+     */
+	public String getClientBinaryHandler() {
+		return clientBinaryHandler;
+	}	
+
+	/**
+     * Sets the ServerMode for the QuickServer.
+	 * @param serverMode ServerMode object.
+     * @see #getServerMode
+	 * @since 1.4.5
+     */
+	public void setServerMode(ServerMode serverMode) {
+		if(serverMode==null) serverMode = new ServerMode();
+		this.serverMode = serverMode;
+	}
+	/**
+     * Returns the ServerMode for the QuickServer.
+     * @see #setServerMode
+	 * @since 1.4.5
+     */
+	public ServerMode getServerMode() {
+		return serverMode;
+	}
+
+	/**
+     * Sets the ClientWriteHandler class that interacts with 
+	 * client sockets.
+	 * XML Tag: &lt;client-write-handler&gt;&lt;/client-write-handler&gt;
+	 * @param handler the fully qualified name of the class that 
+	 *  implements {@link org.quickserver.net.server.ClientWriteHandler}
+	 * @see #getClientWriteHandler
+	 * @since 1.4.5
+     */
+	public void setClientWriteHandler(String handler) {
+		if(handler!=null && handler.equals("")==false) 
+			clientWriteHandler = handler;
+	}
+	/**
+     * Sets the ClientWriteHandler class that interacts with 
+	 * client sockets.
+	 * @since 1.4.6
+     */
+	public void setClientWriteHandler(ClientWriteHandler handler) {
+		if(handler!=null) 
+			clientWriteHandler = handler.getClass().getName();
+	}	
+	/**
+     * Returns the ClientWriteHandler class that interacts with 
+	 * client sockets.
+	 * @see #setClientWriteHandler
+     */
+	public String getClientWriteHandler() {
+		return clientWriteHandler;
+	}
+
+	/**
+     * Sets the AdvancedSettings for the QuickServer.
+	 * @param advancedSettings AdvancedSettings object.
+     * @see #getAdvancedSettings
+	 * @since 1.4.5
+     */
+	public void setAdvancedSettings(AdvancedSettings advancedSettings) {
+		this.advancedSettings = advancedSettings;
+	}
+	/**
+     * Returns the AdvancedSettings for the QuickServer.
+     * @see #setAdvancedSettings
+	 * @since 1.4.5
+     */
+	public AdvancedSettings getAdvancedSettings() {
+		if(advancedSettings==null) advancedSettings = new AdvancedSettings();
+		return advancedSettings;
+	}
+
+	/**
+     * Sets the DefaultDataMode for the QuickServer.
+	 * @param defaultDataMode DefaultDataMode object.
+     * @see #getDefaultDataMode
+	 * @since 1.4.6
+     */
+	public void setDefaultDataMode(DefaultDataMode defaultDataMode) {
+		this.defaultDataMode = defaultDataMode;
+	}
+	/**
+     * Returns the DefaultDataMode for the QuickServer.
+     * @see #setDefaultDataMode
+	 * @since 1.4.6
+     */
+	public DefaultDataMode getDefaultDataMode() {
+		if(defaultDataMode==null) 
+			defaultDataMode = new DefaultDataMode();
+		return defaultDataMode;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ByteBufferObjectPoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/ByteBufferObjectPoolConfig.java
new file mode 100644
index 0000000..c4abe08
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ByteBufferObjectPoolConfig.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the ByteBuffer Object pool configuration.
+ * The xml is &lt;byte-buffer-object-pool&gt;...&lt;/byte-buffer-object-pool&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ByteBufferObjectPoolConfig extends PoolConfig {
+
+	public ByteBufferObjectPoolConfig() {
+		super();
+	}
+
+	public ByteBufferObjectPoolConfig(PoolConfig poolConfig) {
+		setMaxActive(poolConfig.getMaxActive());
+		setMaxIdle(poolConfig.getMaxIdle());
+		setInitSize(poolConfig.getInitSize());
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<byte-buffer-object-pool>\n");
+		sb.append(pad).append("\t<max-active>").append(getMaxActive()).append("</max-active>\n");
+		sb.append(pad).append("\t<max-idle>").append(getMaxIdle()).append("</max-idle>\n");
+		sb.append(pad).append("\t<init-size>").append(getInitSize()).append("</init-size>\n");
+		sb.append(pad).append("</byte-buffer-object-pool>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ClientDataObjectPoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/ClientDataObjectPoolConfig.java
new file mode 100644
index 0000000..c91e673
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ClientDataObjectPoolConfig.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the Thread Object pool configuration.
+ * The xml is &lt;client-data-object-pool&gt;...&lt;/client-data-object-pool&gt;
+ * @author Akshathkumar Shetty
+ */
+public class ClientDataObjectPoolConfig extends PoolConfig {
+
+	public ClientDataObjectPoolConfig() {
+		super();
+	}
+
+	public ClientDataObjectPoolConfig(PoolConfig poolConfig) {
+		setMaxActive(poolConfig.getMaxActive());
+		setMaxIdle(poolConfig.getMaxIdle());
+		setInitSize(poolConfig.getInitSize());
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<client-data-object-pool>\n");
+		sb.append(pad).append("\t<max-active>").append(getMaxActive()).append("</max-active>\n");
+		sb.append(pad).append("\t<max-idle>").append(getMaxIdle()).append("</max-idle>\n");
+		sb.append(pad).append("\t<init-size>").append(getInitSize()).append("</init-size>\n");
+		sb.append(pad).append("</client-data-object-pool>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ClientHandlerObjectPoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/ClientHandlerObjectPoolConfig.java
new file mode 100644
index 0000000..180140e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ClientHandlerObjectPoolConfig.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the ClientHandler Object pool configuration.
+ * The xml is &lt;client-handler-object-pool&gt;...&lt;/client-handler-object-pool&gt;
+ * @author Akshathkumar Shetty
+ */
+public class ClientHandlerObjectPoolConfig extends PoolConfig {
+
+	public ClientHandlerObjectPoolConfig() {
+		super();
+	}
+
+	public ClientHandlerObjectPoolConfig(PoolConfig poolConfig) {
+		setMaxActive(poolConfig.getMaxActive());
+		setMaxIdle(poolConfig.getMaxIdle());
+		setInitSize(poolConfig.getInitSize());
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<client-handler-object-pool>\n");
+		sb.append(pad).append("\t<max-active>").append(getMaxActive()).append("</max-active>\n");
+		sb.append(pad).append("\t<max-idle>").append(getMaxIdle()).append("</max-idle>\n");
+		sb.append(pad).append("\t<init-size>").append(getInitSize()).append("</init-size>\n");
+		sb.append(pad).append("</client-handler-object-pool>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ConfigReader.java b/quickserver/src/main/org/quickserver/util/xmlreader/ConfigReader.java
new file mode 100644
index 0000000..a7b1519
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ConfigReader.java
@@ -0,0 +1,496 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.digester3.Digester;
+import org.quickserver.net.server.QuickServer;
+import org.quickserver.swing.SensitiveInput;
+import org.quickserver.util.io.PasswordField;
+
+/**
+ * This class reads the xml configuration and gives 
+ * QuickServerConfig object.
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ConfigReader {
+	private static Logger logger = Logger.getLogger(ConfigReader.class.getName());
+
+	/**
+	 * Parses XML config of QuickServer of version 1.3 and above
+	 * @since 1.3
+	 */
+	public static QuickServerConfig read(String fileName) throws Exception {
+		File configFile = new File(fileName);
+		
+		FileInputStream fis = null;
+		
+		try {
+			fis = new FileInputStream(configFile);		
+			logger.log(Level.FINE, "Loading config from xml file : {0}", configFile.getAbsolutePath());
+
+			return read(fis, configFile.getAbsolutePath());
+		} finally {
+			if(fis!=null) {
+				fis.close();
+			}
+		}
+	}
+	
+	/**
+	 * Parses XML config of QuickServer of version 1.3 and above
+	 * @since 1.4
+	 */
+	public static QuickServerConfig read(InputStream input,String config_file_location) 
+			throws Exception {
+		Digester digester = new Digester();
+	    digester.setValidating(false);
+
+		//digester.setNamespaceAware(true);
+		//String xsd = "" + new File("quickserver_config.xsd").toURI();
+		//digester.setSchema(xsd);
+		String mainTag = "quickserver";
+		String subTag = "";
+		
+		digester.addObjectCreate(mainTag, QuickServerConfig.class);
+		digester.addBeanPropertySetter(mainTag+"/name", "name");
+		digester.addBeanPropertySetter(mainTag+"/server-banner", "serverBanner");
+		digester.addBeanPropertySetter(mainTag+"/port", "port");
+		digester.addBeanPropertySetter(mainTag+"/bind-address", "bindAddr");
+		//<server-mode>
+		String curTag = mainTag+"/server-mode";
+		digester.addObjectCreate(curTag, ServerMode.class);
+		digester.addBeanPropertySetter(curTag+"/blocking", "blocking");
+		digester.addSetNext(curTag,"setServerMode");
+		//</server-mode>
+		digester.addBeanPropertySetter(mainTag+"/client-event-handler", "clientEventHandler");//v1.4.6
+		digester.addBeanPropertySetter(mainTag+"/client-command-handler", "clientCommandHandler");
+		digester.addBeanPropertySetter(mainTag+"/client-object-handler", "clientObjectHandler");
+		digester.addBeanPropertySetter(mainTag+"/client-binary-handler", "clientBinaryHandler");//v1.4
+		digester.addBeanPropertySetter(mainTag+"/client-write-handler", "clientWriteHandler");//v1.4.5
+		digester.addBeanPropertySetter(mainTag+"/authenticator", "authenticator"); //v1.3
+		digester.addBeanPropertySetter(mainTag+"/client-authentication-handler", "clientAuthenticationHandler"); //v1.4.6
+		digester.addBeanPropertySetter(mainTag+"/client-data", "clientData");
+		digester.addBeanPropertySetter(mainTag+"/client-extended-event-handler", "clientExtendedEventHandler");//v1.4.6
+		digester.addBeanPropertySetter(mainTag+"/timeout", "timeout");
+		digester.addBeanPropertySetter(mainTag+"/timeout-msg", "timeoutMsg");
+		digester.addBeanPropertySetter(mainTag+"/max-auth-try", "maxAuthTry");
+		digester.addBeanPropertySetter(mainTag+"/max-auth-try-msg", "maxAuthTryMsg");		
+		digester.addBeanPropertySetter(mainTag+"/max-connection", "maxConnection");
+		digester.addBeanPropertySetter(mainTag+"/max-connection-msg", "maxConnectionMsg");
+		digester.addBeanPropertySetter(mainTag+"/console-logging-level", "consoleLoggingLevel");
+		digester.addBeanPropertySetter(mainTag+"/console-logging-formatter", "consoleLoggingFormatter");
+		//<default-data-mode>
+		curTag = mainTag+"/default-data-mode";
+		digester.addObjectCreate(curTag, DefaultDataMode.class);
+		digester.addBeanPropertySetter(curTag+"/data-type-in", "dataModeIn");
+		digester.addBeanPropertySetter(curTag+"/data-type-out", "dataModeOut");
+		digester.addSetNext(curTag,"setDefaultDataMode");
+		//</default-data-mode>
+		//<object-pool>
+		curTag = mainTag+"/object-pool";
+		digester.addObjectCreate(curTag, ObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/init-size", "initSize");
+		digester.addBeanPropertySetter(curTag+"/pool-manager", "poolManager");
+		//<thread-object-pool>
+		digester.addObjectCreate(curTag+"/thread-object-pool", ThreadObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/thread-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/thread-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/thread-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/thread-object-pool","setThreadObjectPoolConfig");
+		//</thread-object-pool>
+		//<client-handler-object-pool>
+		digester.addObjectCreate(curTag+"/client-handler-object-pool", ClientHandlerObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/client-handler-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/client-handler-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/client-handler-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/client-handler-object-pool","setClientHandlerObjectPoolConfig");
+		//</client-handler-object-pool>
+		//<byte-buffer-object-pool>
+		digester.addObjectCreate(curTag+"/byte-buffer-object-pool", ByteBufferObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/byte-buffer-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/byte-buffer-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/byte-buffer-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/byte-buffer-object-pool","setByteBufferObjectPoolConfig");
+		//</byte-buffer-object-pool>
+		//<client-data-object-pool>
+		digester.addObjectCreate(curTag+"/client-data-object-pool", ClientDataObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/client-data-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/client-data-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/client-data-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/client-data-object-pool","setClientDataObjectPoolConfig");
+		//</client-data-object-pool>
+		digester.addSetNext(curTag,"setObjectPoolConfig");
+		//</object-pool>
+		//<communication-logging>
+		digester.addBeanPropertySetter(mainTag+"/communication-logging/enable", "communicationLogging");
+		//</communication-logging>
+		digester.addBeanPropertySetter(mainTag+"/security-manager-class", "securityManagerClass");
+		
+		//<access-constraint>
+		digester.addObjectCreate(mainTag+"/access-constraint", AccessConstraintConfig.class);
+		//<ip-filter>
+		digester.addObjectCreate(mainTag+"/access-constraint/ip-filter", IpFilterConfig.class);
+		digester.addBeanPropertySetter(mainTag+"/access-constraint/ip-filter/enable", "enable");
+		digester.addBeanPropertySetter(mainTag+"/access-constraint/ip-filter/allow-access", "allowAccess");
+		//<ip-collection>
+		digester.addCallMethod(mainTag+"/access-constraint/ip-filter/ip-collection/client-ip-address", "addClientIpAddress", 0);
+		//<ip-collection>
+		digester.addSetNext(mainTag+"/access-constraint/ip-filter", "setIpFilterConfig");
+		//<ip-filter>
+		digester.addSetNext(mainTag+"/access-constraint", "setAccessConstraintConfig");
+		//</access-constraint>	
+
+		//<application-jar-path>
+		digester.addBeanPropertySetter(mainTag+"/application-jar-path", "applicationJarPath");
+
+		//<server-hooks>
+		digester.addObjectCreate(mainTag+"/server-hooks", ServerHooks.class);
+		digester.addCallMethod(mainTag+"/server-hooks/class-name", "addClassName", 0);
+		digester.addSetNext(mainTag+"/server-hooks", "setServerHooks");
+		//</server-hooks>
+
+		//<secure>
+		curTag = mainTag+"/secure";
+		digester.addObjectCreate(curTag, Secure.class);
+		digester.addBeanPropertySetter(curTag+"/enable", "enable");
+		digester.addBeanPropertySetter(curTag+"/load", "load");
+		digester.addBeanPropertySetter(curTag+"/port", "port");
+		digester.addBeanPropertySetter(curTag+"/protocol", "protocol");
+		digester.addBeanPropertySetter(curTag+"/client-auth-enable", "clientAuthEnable");
+		//<secure-store>
+		digester.addObjectCreate(curTag+"/secure-store", SecureStore.class);
+		digester.addBeanPropertySetter(curTag+"/secure-store/type", "type");
+		digester.addBeanPropertySetter(curTag+"/secure-store/algorithm", "algorithm");
+		digester.addBeanPropertySetter(curTag+"/secure-store/provider", "provider");
+		//<key-store-info>
+		digester.addObjectCreate(curTag+"/secure-store/key-store-info", KeyStoreInfo.class);
+		digester.addBeanPropertySetter(curTag+"/secure-store/key-store-info/store-file", "storeFile");
+		digester.addBeanPropertySetter(curTag+"/secure-store/key-store-info/store-password", "storePassword");
+		digester.addBeanPropertySetter(curTag+"/secure-store/key-store-info/key-password", "keyPassword");
+		digester.addSetNext(curTag+"/secure-store/key-store-info","setKeyStoreInfo");
+		//</key-store-info>
+		//<trust-store-info>
+		digester.addObjectCreate(curTag+"/secure-store/trust-store-info", TrustStoreInfo.class);
+		digester.addBeanPropertySetter(curTag+"/secure-store/trust-store-info/store-file", "storeFile");
+		digester.addBeanPropertySetter(curTag+"/secure-store/trust-store-info/store-password", "storePassword");
+		digester.addBeanPropertySetter(curTag+"/secure-store/trust-store-info/type", "type");
+		digester.addBeanPropertySetter(curTag+"/secure-store/trust-store-info/provider", "provider");
+		digester.addSetNext(curTag+"/secure-store/trust-store-info","setTrustStoreInfo");
+		//</trust-store-info>
+		digester.addBeanPropertySetter(curTag+"/secure-store/secure-store-manager", "secureStoreManager");
+		digester.addSetNext(curTag+"/secure-store","setSecureStore");
+		//</secure-store>
+		digester.addSetNext(curTag,"setSecure");
+		//</secure>
+
+		//<advanced-settings>
+		curTag = mainTag+"/advanced-settings";
+		digester.addObjectCreate(curTag, AdvancedSettings.class);
+		digester.addBeanPropertySetter(curTag+"/charset", "charset");
+		digester.addBeanPropertySetter(curTag+"/byte-buffer-size", "byteBufferSize");
+		digester.addBeanPropertySetter(curTag+"/backlog", "backlog");
+		digester.addBeanPropertySetter(curTag+"/use-direct-byte-buffer", "useDirectByteBuffer");
+		digester.addBeanPropertySetter(curTag+"/socket-linger", "socketLinger");
+		digester.addBeanPropertySetter(curTag+"/debug-non-blocking-mode", "debugNonBlockingMode");
+		digester.addBeanPropertySetter(curTag+"/client-identifier", "clientIdentifier");
+		digester.addBeanPropertySetter(curTag+"/qsobject-pool-maker", "qsObjectPoolMaker");
+		digester.addBeanPropertySetter(curTag+"/max-threads-for-nio-write", "maxThreadsForNioWrite");
+		
+		digester.addBeanPropertySetter(curTag+"/performance-preferences-connection-time", "performancePreferencesConnectionTime");
+		digester.addBeanPropertySetter(curTag+"/performance-preferences-latency", "performancePreferencesLatency");
+		digester.addBeanPropertySetter(curTag+"/performance-preferences-bandwidth", "performancePreferencesBandwidth");
+		
+		digester.addBeanPropertySetter(curTag+"/client-socket-tcp-no-delay", "clientSocketTcpNoDelay");
+		digester.addBeanPropertySetter(curTag+"/client-socket-traffic-class", "clientSocketTrafficClass");
+		
+		digester.addBeanPropertySetter(curTag+"/client-socket-receive-buffer-size", "clientSocketReceiveBufferSize");
+		digester.addBeanPropertySetter(curTag+"/client-socket-send-buffer-size", "clientSocketSendBufferSize");
+		
+		digester.addSetNext(curTag,"setAdvancedSettings");
+		//</advanced-settings>
+
+		//<qsadmin-server>
+		subTag = "qsadmin-server";
+		curTag = mainTag+"/"+subTag;
+		digester.addObjectCreate(curTag, QSAdminServerConfig.class);
+		digester.addBeanPropertySetter(curTag+"/name", "name");
+		digester.addBeanPropertySetter(curTag+"/server-banner", "serverBanner");
+		digester.addBeanPropertySetter(curTag+"/port", "port");
+		//<server-mode>
+		digester.addObjectCreate(curTag+"/server-mode", ServerMode.class);
+		digester.addBeanPropertySetter(curTag+"/server-mode/blocking", "blocking");
+		digester.addSetNext(curTag+"/server-mode","setServerMode");
+		//</server-mode>
+		digester.addBeanPropertySetter(curTag+"/client-event-handler", "clientEventHandler");
+		digester.addBeanPropertySetter(curTag+"/client-command-handler", "clientCommandHandler");
+		digester.addBeanPropertySetter(curTag+"/client-object-handler", "clientObjectHandler");
+		digester.addBeanPropertySetter(curTag+"/client-binary-handler", "clientBinaryHandler");//v1.4
+		digester.addBeanPropertySetter(curTag+"/client-write-handler", "clientWriteHandler");//v1.4.5
+		digester.addBeanPropertySetter(curTag+"/authenticator", "authenticator"); //v1.3
+		digester.addBeanPropertySetter(curTag+"/client-authentication-handler", "clientAuthenticationHandler"); //v1.4.6
+		digester.addBeanPropertySetter(curTag+"/client-data", "clientData");
+		digester.addBeanPropertySetter(curTag+"/client-extended-event-handler", "clientExtendedEventHandler");//v1.4.6
+		digester.addBeanPropertySetter(curTag+"/timeout", "timeout");
+		digester.addBeanPropertySetter(curTag+"/max-auth-try", "maxAuthTry");
+		digester.addBeanPropertySetter(curTag+"/max-auth-try-msg", "maxAuthTryMsg");
+		digester.addBeanPropertySetter(curTag+"/timeout-msg", "timeoutMsg");
+		digester.addBeanPropertySetter(curTag+"/max-connection", "maxConnection");
+		digester.addBeanPropertySetter(curTag+"/max-connection-msg", "maxConnectionMsg");
+		digester.addBeanPropertySetter(curTag+"/bind-address", "bindAddr");
+		digester.addBeanPropertySetter(curTag+"/client-object-handler", "clientObjectHandler");
+		digester.addBeanPropertySetter(curTag+"/console-logging-level", "consoleLoggingLevel");
+		digester.addBeanPropertySetter(curTag+"/console-logging-formatter", "consoleLoggingFormatter");
+		//<default-data-mode>
+		digester.addObjectCreate(curTag+"/default-data-mode", DefaultDataMode.class);
+		digester.addBeanPropertySetter(curTag+"/default-data-mode/data-type-in", "dataModeIn");
+		digester.addBeanPropertySetter(curTag+"/default-data-mode/data-type-out", "dataModeOut");
+		digester.addSetNext(curTag+"/default-data-mode","setDefaultDataMode");
+		//</default-data-mode>
+		//<object-pool>
+		digester.addObjectCreate(curTag+"/object-pool", ObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/object-pool/init-size", "initSize");
+		digester.addBeanPropertySetter(curTag+"/object-pool/pool-manager", "poolManager");
+		//<thread-object-pool>
+		digester.addObjectCreate(curTag+"/object-pool/thread-object-pool", ThreadObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/object-pool/thread-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/object-pool/thread-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/object-pool/thread-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/object-pool/thread-object-pool","setThreadObjectPoolConfig");
+		//</thread-object-pool>
+		//<client-handler-object-pool>
+		digester.addObjectCreate(curTag+"/object-pool/client-handler-object-pool", ClientHandlerObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/object-pool/client-handler-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/object-pool/client-handler-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/object-pool/client-handler-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/object-pool/client-handler-object-pool","setClientHandlerObjectPoolConfig");
+		//</client-handler-object-pool>
+		//<byte-buffer-object-pool>
+		digester.addObjectCreate(curTag+"/object-pool/byte-buffer-object-pool", ByteBufferObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/object-pool/byte-buffer-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/object-pool/byte-buffer-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/object-pool/byte-buffer-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/object-pool/byte-buffer-object-pool","setByteBufferObjectPoolConfig");
+		//</byte-buffer-object-pool>
+		//<client-data-object-pool>
+		digester.addObjectCreate(curTag+"/object-pool/client-data-object-pool", ClientDataObjectPoolConfig.class);
+		digester.addBeanPropertySetter(curTag+"/object-pool/client-data-object-pool/max-active", "maxActive");
+		digester.addBeanPropertySetter(curTag+"/object-pool/client-data-object-pool/max-idle", "maxIdle");
+		digester.addBeanPropertySetter(curTag+"/object-pool/client-data-object-pool/init-size", "initSize");
+		digester.addSetNext(curTag+"/object-pool/client-data-object-pool","setClientDataObjectPoolConfig");
+		//</client-data-object-pool>
+		digester.addSetNext(curTag+"/object-pool", "setObjectPoolConfig");
+		//</object-pool>		
+		//<command-shell>
+		digester.addBeanPropertySetter(curTag+"/command-shell/enable", "commandShellEnable");
+		digester.addBeanPropertySetter(curTag+"/command-shell/prompt-name", "commandShellPromptName");
+		//</command-shell>
+		//<communication-logging><enable>
+		digester.addBeanPropertySetter(curTag+"/communication-logging/enable", "communicationLogging");
+		//<access-constraint>
+		digester.addObjectCreate(curTag+"/access-constraint", AccessConstraintConfig.class);
+		//<ip-filter>
+		digester.addObjectCreate(curTag+"/access-constraint/ip-filter", IpFilterConfig.class);
+		digester.addBeanPropertySetter(curTag+"/access-constraint/ip-filter/enable", "enable");
+		digester.addBeanPropertySetter(curTag+"/access-constraint/ip-filter/allow-access", "allowAccess");
+		//<ip-collection>
+		digester.addCallMethod(curTag+"/access-constraint/ip-filter/ip-collection/client-ip-address", "addClientIpAddress", 0);
+		//<ip-collection>
+		digester.addSetNext(curTag+"/access-constraint/ip-filter", "setIpFilterConfig");
+		//<ip-filter>
+		digester.addSetNext(curTag+"/access-constraint", "setAccessConstraintConfig");
+		//</access-constraint>	
+		//<server-hooks>
+		digester.addObjectCreate(curTag+"/server-hooks", ServerHooks.class);
+		digester.addCallMethod(curTag+"/server-hooks/class-name", "addClassName", 0);
+		digester.addSetNext(curTag+"/server-hooks", "setServerHooks");
+		//</server-hooks>
+
+		//<secure>
+		digester.addObjectCreate(curTag+"/secure", Secure.class);
+		digester.addBeanPropertySetter(curTag+"/secure/enable", "enable");
+		digester.addBeanPropertySetter(curTag+"/secure/load", "load");
+		digester.addBeanPropertySetter(curTag+"/secure/port", "port");
+		digester.addBeanPropertySetter(curTag+"/secure/protocol", "protocol");
+		digester.addBeanPropertySetter(curTag+"/secure/client-auth-enable", "clientAuthEnable");
+		//<secure-store>
+		digester.addObjectCreate(curTag+"/secure/secure-store", SecureStore.class);
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/type", "type");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/algorithm", "algorithm");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/provider", "provider");
+		//<key-store-info>
+		digester.addObjectCreate(curTag+"/secure/secure-store/key-store-info", KeyStoreInfo.class);
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/key-store-info/store-file", "storeFile");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/key-store-info/store-password", "storePassword");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/key-store-info/key-password", "keyPassword");
+		digester.addSetNext(curTag+"/secure/secure-store/key-store-info","setKeyStoreInfo");
+		//</key-store-info>
+		//<trust-store-info>
+		digester.addObjectCreate(curTag+"/secure/secure-store/trust-store-info", TrustStoreInfo.class);
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/trust-store-info/store-file", "storeFile");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/trust-store-info/store-password", "storePassword");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/trust-store-info/type", "type");
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/trust-store-info/provider", "provider");
+		digester.addSetNext(curTag+"/secure/secure-store/trust-store-info","setTrustStoreInfo");
+		//</trust-store-info>
+		digester.addBeanPropertySetter(curTag+"/secure/secure-store/secure-store-manager", "secureStoreManager");
+		digester.addSetNext(curTag+"/secure/secure-store","setSecureStore");
+		//</secure-store>
+		digester.addSetNext(curTag+"/secure","setSecure");
+		//</secure>
+		digester.addBeanPropertySetter(curTag+"/command-plugin", "commandPlugin");
+		//<advanced-settings>
+		digester.addObjectCreate(curTag+"/advanced-settings", AdvancedSettings.class);
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/charset", "charset");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/byte-buffer-size", "byteBufferSize");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/backlog", "backlog");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/use-direct-byte-buffer", "useDirectByteBuffer");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/socket-linger", "socketLinger");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/debug-non-blocking-mode", "debugNonBlockingMode");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/client-identifier", "clientIdentifier");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/qsobject-pool-maker", "qsObjectPoolMaker");
+		digester.addBeanPropertySetter(curTag+"/advanced-settings/max-threads-for-nio-write", "maxThreadsForNioWrite");
+		digester.addSetNext(curTag+"/advanced-settings","setAdvancedSettings");
+		//</advanced-settings>
+		digester.addSetNext(curTag, "setQSAdminServerConfig");
+		//</qsadmin-server>
+
+
+		//<db-object-pool>
+		subTag = "db-object-pool";
+		digester.addObjectCreate(mainTag+"/"+subTag, DBObjectPoolConfig.class);
+		//<database-connection-set>
+		digester.addObjectCreate(mainTag+"/"+subTag+"/database-connection-set", DatabaseConnectionSet.class);
+		//<database-connection>
+		curTag = mainTag+"/"+subTag+"/database-connection-set/database-connection";
+		digester.addObjectCreate(curTag, DatabaseConnectionConfig.class);
+		digester.addBeanPropertySetter(curTag+"/id", "id");
+		digester.addBeanPropertySetter(curTag+"/driver", "driver");
+		digester.addBeanPropertySetter(curTag+"/url", "url");
+		digester.addBeanPropertySetter(curTag+"/username", "username");
+		digester.addBeanPropertySetter(curTag+"/password", "password");
+		digester.addSetNext(curTag, "addDatabaseConnection");
+		//</database-connection>
+		digester.addSetNext(mainTag+"/"+subTag+"/database-connection-set", "setDatabaseConnectionSet");
+		//</database-connection-set>
+		//<db-pool-util>
+		curTag = mainTag+"/"+subTag+"/db-pool-util";
+		digester.addBeanPropertySetter(curTag, "dbPoolUtil");
+		//</db-pool-util>		
+		digester.addSetNext(mainTag+"/"+subTag, "setDBObjectPoolConfig");
+		//</db-object-pool>
+
+
+		//<application-configuration>
+		subTag = "application-configuration";
+		digester.addObjectCreate(mainTag+"/"+subTag, ApplicationConfiguration.class);
+		digester.addBeanPropertySetter(mainTag+"/"+subTag+"/prompt-type", "promptType");
+		curTag = mainTag+"/"+subTag+"/"+"property";
+		digester.addObjectCreate(curTag, Property.class);
+		digester.addBeanPropertySetter(curTag+"/property-name", "name");
+		digester.addBeanPropertySetter(curTag+"/property-value", "value");
+		digester.addSetNext(curTag, "addProperty");
+		digester.addSetNext(mainTag+"/"+subTag, "setApplicationConfiguration");
+		//</application-configuration>
+
+
+		//<init-server-hooks>
+		subTag = "init-server-hooks";
+		digester.addObjectCreate(mainTag+"/"+subTag, InitServerHooks.class);
+		digester.addCallMethod(mainTag+"/"+subTag+"/class-name", 
+			"addClassName", 0);
+		digester.addSetNext(mainTag+"/"+subTag, "setInitServerHooks");
+		//</init-server-hooks>
+		
+		
+		QuickServerConfig qsc = (QuickServerConfig) digester.parse(input);
+				
+		qsc.setConfigFile(config_file_location);
+		
+		loadMissingApplicationConfiguration(qsc);
+
+		QuickServer.setDebugNonBlockingMode(qsc.getAdvancedSettings().getDebugNonBlockingMode());
+
+		return qsc;
+	}
+
+	private static void loadMissingApplicationConfiguration(QuickServerConfig qsc) 
+			throws IOException {
+		ApplicationConfiguration ac = qsc.getApplicationConfiguration();
+		if(ac==null) return;
+
+		//check if any application-configuration had missing property-value
+		Set propertyNames = ac.keySet();
+		Iterator iterator = propertyNames.iterator();
+		String key = null;
+		Object value = null;
+		char sv[] = null;
+		SensitiveInput sensitiveInput = null;
+		boolean guiPrompt = ac.getPromptType().equals("console")==false?true:false;
+
+		while(iterator.hasNext()) {
+			key = (String) iterator.next();
+			value = ac.get(key);
+			if(value==null) {
+				if(guiPrompt && sensitiveInput==null) {
+					sensitiveInput = new SensitiveInput(
+						qsc.getName()+" - Input Prompt");
+				}
+				
+				if(guiPrompt)
+					sv = sensitiveInput.getInput(key);
+				else
+					sv = PasswordField.getPassword("Input property value for "+key+" : ");				
+
+				if(sv!=null) {
+					value = new String(sv);
+					ac.put(key, value);
+				}
+				value = null;
+			}
+		}
+	}
+
+	/**
+	 * Make the file passed absolute, relative to the location of 
+	 * configuration file that loaded QuickServerConfig object passed. 
+	 * @since 1.4
+	 */
+	public static File makeAbsoluteToConfig(String fileName, 
+			QuickServerConfig config) {
+		File file = new File(fileName);
+		if(config==null) return file;
+		if(file.isAbsolute()==false) {
+			String temp = config.getConfigFile();
+			if(temp==null)  return file;
+			file = new File(temp);
+			temp = file.getParent() + File.separatorChar + fileName;
+			file = new File(temp);
+		}
+		return file;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/DBObjectPoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/DBObjectPoolConfig.java
new file mode 100644
index 0000000..8565573
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/DBObjectPoolConfig.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the database object pool.
+ * The xml is &lt;db-object-pool&gt;...&lt;/db-object-pool&gt;.
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class DBObjectPoolConfig implements java.io.Serializable {
+	private DatabaseConnectionSet databaseConnectionSet;
+	private String dbPoolUtil;
+
+	/**
+	 * Returns the DatabaseConnectionSet.
+	 * @return DatabaseConnectionSet
+	 */
+	public DatabaseConnectionSet getDatabaseConnectionSet() {
+		return databaseConnectionSet;
+	}
+	/**
+	 * Sets the DatabaseConnectionSet.
+	 * XML Tag: &lt;database-connection-set&gt;&lt;/database-connection-set&gt;
+	 * @param databaseConnectionSet
+	 */
+	public void setDatabaseConnectionSet(DatabaseConnectionSet databaseConnectionSet) {
+		this.databaseConnectionSet = databaseConnectionSet;
+	}
+
+	/**
+	 * Sets the {@link org.quickserver.sql.DBPoolUtil} class that handles the 
+	 * database connection pools.
+	 * XML Tag: &lt;db-pool-util&gt;&lt;/db-pool-util&gt;
+	 * @param className the fully qualified name of the class 
+	 * that implements {@link org.quickserver.sql.DBPoolUtil}.
+	 * @see #getDbPoolUtil
+	 */
+	public void setDbPoolUtil(String className) {
+		dbPoolUtil = className;
+	}
+	/**
+	 * Returns the {@link org.quickserver.sql.DBPoolUtil} class that handles the 
+	 * database connection pools.
+	 * @see #setDbPoolUtil
+	 */
+	public String getDbPoolUtil() {
+		return dbPoolUtil;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+
+		sb.append(pad).append("<db-object-pool>\n");
+		if(getDatabaseConnectionSet()!=null)
+			sb.append(getDatabaseConnectionSet().toXML(pad+"\t"));
+		sb.append(pad).append("\t<db-pool-util>").append(getDbPoolUtil()).append("</db-pool-util>\n");
+		sb.append(pad).append("</db-object-pool>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/DatabaseConnectionConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/DatabaseConnectionConfig.java
new file mode 100644
index 0000000..e761165
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/DatabaseConnectionConfig.java
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import org.quickserver.net.server.QuickServer;
+/**
+ * This class encapsulate the database connection configuration.
+ * The xml is &lt;database-connection&gt;...&lt;/database-connection&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class DatabaseConnectionConfig implements java.io.Serializable {
+	private String id = "";
+	private String driver = "";
+	private String url = "";
+	private String username = "";
+	private String password = "";
+
+	/**
+	 * Returns the id.
+	 * @return id that identifies the connection.
+	 */
+	public String getId() {
+		return id;
+	}
+	/**
+	 * Sets the id.
+	 * XML Tag: &lt;id&gt;&lt;/id&gt;
+	 * @param id for this connection.
+	 */
+	public void setId(String id) {
+		if(id!=null)
+			this.id = id;
+	}
+
+	/**
+	 * Returns the database driver.
+	 * @return driver that driver class
+	 */
+	public String getDriver() {
+		return driver;
+	}
+	/**
+	 * Sets the database driver.
+	 * XML Tag: &lt;driver&gt;&lt;/driver&gt;
+	 * @param driver that driver class
+	 */
+	public void setDriver(String driver) {
+		if(driver!=null)
+			this.driver = driver;
+	}
+
+	/**
+	 * Returns the url.
+	 * @return URl for this connection.
+	 */
+	public String getUrl() {
+		return url;
+	}
+	/**
+	 * Sets the url.
+	 * XML Tag: &lt;url&gt;&lt;/url&gt;
+	 * @param url for this connection.
+	 */
+	public void setUrl(String url) {
+		if(url!=null)
+			this.url = url;
+	}
+
+	/**
+	 * Returns the username
+	 * @return username for this connection.
+	 */
+	public String getUsername() {
+		return username;
+	}
+	/**
+	 * Sets the username.
+	 * XML Tag: &lt;username&gt;&lt;/username&gt;
+	 * @param username for this connection.
+	 */
+	public void setUsername(String username) {
+		if(username!=null)
+			this.username = username;
+	}
+
+	/**
+	 * Returns the password.
+	 * @return password for this connection.
+	 */
+	public String getPassword() {
+		return password;
+	}
+	/**
+	 * Sets the password.
+	 * XML Tag: &lt;password&gt;&lt;/password&gt;
+	 * @param password for this connection.
+	 */
+	public void setPassword(String password) {
+		if(password!=null)
+			this.password = password;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<database-connection>\n");
+		sb.append(pad).append("\t<id>").append(getId()).append("</id>\n");
+		sb.append(pad).append("\t<driver>").append(getDriver()).append("</driver>\n");
+		sb.append(pad).append("\t<url>").append(getUrl()).append("</url>\n");
+		sb.append(pad).append("\t<username>").append(getUsername()).append("</username>\n");
+		sb.append(pad).append("\t<password>").append(getPassword()).append("</password>\n");
+		sb.append(pad).append("</database-connection>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/DatabaseConnectionSet.java b/quickserver/src/main/org/quickserver/util/xmlreader/DatabaseConnectionSet.java
new file mode 100644
index 0000000..78f0e53
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/DatabaseConnectionSet.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+/**
+ * This class encapsulate the database connection set.
+ * The xml is &lt;database-connection-set&gt;...&lt;/database-connection-set&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class DatabaseConnectionSet implements java.io.Serializable {
+	private ArrayList databaseConnectionSet=null;
+	
+	public DatabaseConnectionSet() {
+		databaseConnectionSet = new ArrayList();
+	}
+
+	/**
+	 * Adds a DatabaseConnectionConfig object to the set.
+	 */
+	public void addDatabaseConnection(DatabaseConnectionConfig dbcConfig) {
+		if(dbcConfig!=null) {
+			databaseConnectionSet.add(dbcConfig);
+		}
+	}
+
+	public Iterator iterator() {
+		return databaseConnectionSet.iterator();
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<database-connection-set>\n");
+		Iterator iterator = iterator();
+		while(iterator.hasNext()) {
+			DatabaseConnectionConfig dcc = 
+				(DatabaseConnectionConfig)iterator.next();
+			sb.append(dcc.toXML(pad+"\t"));
+		}
+		sb.append(pad).append("</database-connection-set>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/DefaultDataMode.java b/quickserver/src/main/org/quickserver/util/xmlreader/DefaultDataMode.java
new file mode 100644
index 0000000..160ca93
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/DefaultDataMode.java
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import org.quickserver.net.server.DataMode;
+import org.quickserver.net.server.DataType;
+
+/**
+ * This class encapsulate default DataMode for ClientHandler.
+ * The xml is &lt;default-data-mode&gt;...&lt;/default-data-mode&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.4.6
+ */
+public class DefaultDataMode implements java.io.Serializable {
+	private DataMode defaultDataModeIN;
+	private DataMode defaultDataModeOUT;
+
+	public DefaultDataMode() {
+		defaultDataModeIN = DataMode.STRING;
+		defaultDataModeOUT = DataMode.STRING;
+	}
+
+	/**
+	 * Sets DataMode for DataType.IN 
+	 * Valid values are <code>STRING|BYTE|OBJECT|BINARY</code>
+	 */
+	public void setDataModeIn(String dataMode) {
+		if(dataMode.toUpperCase().equals("STRING"))
+			defaultDataModeIN = DataMode.STRING;
+		else if(dataMode.toUpperCase().equals("BYTE"))
+			defaultDataModeIN = DataMode.BYTE;
+		else if(dataMode.toUpperCase().equals("OBJECT"))
+			defaultDataModeIN = DataMode.OBJECT;
+		else if(dataMode.toUpperCase().equals("BINARY"))
+			defaultDataModeIN = DataMode.BINARY;
+	}
+
+	public String getDataModeIn() {
+		return defaultDataModeIN.toString();
+	}
+
+	/**
+	 * Sets DataMode for DataType.OUT
+	 * Valid values are <code>STRING|BYTE|OBJECT|BINARY</code>
+	 */
+	public void setDataModeOut(String dataMode) {
+		if(dataMode.toUpperCase().equals("STRING"))
+			defaultDataModeOUT = DataMode.STRING;
+		else if(dataMode.toUpperCase().equals("BYTE"))
+			defaultDataModeOUT = DataMode.BYTE;
+		else if(dataMode.toUpperCase().equals("OBJECT"))
+			defaultDataModeOUT = DataMode.OBJECT;
+		else if(dataMode.toUpperCase().equals("BINARY"))
+			defaultDataModeOUT = DataMode.BINARY;
+	}
+
+	public String getDataModeOut() {
+		return defaultDataModeOUT.toString();
+	}
+
+
+	/**
+	 * Sets the default {@link DataMode} for the ClientHandler
+	 */
+	public void setDataMode(DataMode dataMode, DataType dataType) {
+		if(dataType==DataType.IN)
+			this.defaultDataModeIN = dataMode;
+		if(dataType==DataType.OUT)
+			this.defaultDataModeOUT = dataMode;
+	}
+	/**
+	 * Returns the default {@link DataMode} for the ClientHandler
+	 */
+	public DataMode getDataMode(DataType dataType) {
+		if(dataType==DataType.IN)
+			return defaultDataModeIN;
+		if(dataType==DataType.OUT)
+			return defaultDataModeOUT;
+		else
+			throw new IllegalArgumentException("Unknown DataType: "+dataType);
+	}
+	
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<default-data-mode>\n");
+		sb.append(pad).append("\t<data-type-in>").append(getDataModeIn()
+				).append("</data-type-in>\n");
+		sb.append(pad).append("\t<data-type-out>").append(getDataModeOut()
+				).append("</data-type-out>\n");
+		sb.append(pad).append("</default-data-mode>\n");
+		return sb.toString();
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/InitServerHooks.java b/quickserver/src/main/org/quickserver/util/xmlreader/InitServerHooks.java
new file mode 100644
index 0000000..14f3a7e
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/InitServerHooks.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+
+/**
+ * This class encapsulate the init Server Hooks. Called just after server 
+ * loads the xml configuration file. Can be using to set up loggers.   
+ * The example xml is <pre>
+	....
+	&lt;init-server-hooks&gt;
+		&lt;class-name&gt;package1.Class1&lt;/class-name&gt;
+		&lt;class-name&gt;package1.Class2&lt;/class-name&gt;
+	&lt;/init-server-hooks&gt;
+	....
+ </pre>
+ * @see org.quickserver.net.InitServerHook
+ * @see org.quickserver.util.xmlreader.ServerHooks
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public class InitServerHooks extends ArrayList {
+	/**
+	 * Addes the class to init server hooks.
+	 */
+	public void addClassName(String className) {
+		if(className!=null && className.trim().length()!=0) {
+			add(className.trim());
+		}
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<init-server-hooks>\n");
+		Iterator iterator = iterator();
+		while(iterator.hasNext()) {
+			String classname = (String) iterator.next();
+			sb.append(pad).append("\t<class-name>").append(classname).append("</class-name>\n");
+		}
+		sb.append(pad).append("</init-server-hooks>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/IpFilterConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/IpFilterConfig.java
new file mode 100644
index 0000000..bdbcc70
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/IpFilterConfig.java
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+/**
+ * This class encapsulate the IP based Filter config.
+ * The xml is &lt;ip-filter&gt;...&lt;/ip-filter&gt;<br>
+ * <b>Note:</b> Make sure that access from 127.0.0.1 is allowed at 
+ * all times, else some of the QsAdmin command will fail.
+ * @author Akshathkumar Shetty
+ * @since 1.3.3
+ */
+public class IpFilterConfig implements java.io.Serializable {
+	private ArrayList ipCollection=null;
+	private boolean enable = false;
+	private boolean allowAccess = false;
+
+	public IpFilterConfig() {
+		ipCollection = new ArrayList();
+	}
+
+	/**
+	 * Adds a Client Ip Address to the list
+	 */
+	public void addClientIpAddress(String clientIpAddress) {
+		if(clientIpAddress!=null) {
+			ipCollection.add(clientIpAddress);
+		}
+	}
+
+	/**
+	 * Returns ClientIpAddress collection
+	 */
+	public ArrayList getIpCollection() {
+		return ipCollection;
+	}
+
+	public Iterator iterator() {
+		return ipCollection.iterator();
+	}
+	
+	/**
+	 * Sets the IP filter enable flag.
+	 * XML Tag: &lt;ip-filter&gt;&lt;enable&gt;true&lt;/enable&gt;&lt;/ip-filter&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+ 	 * @see #getEnable
+	 */
+	public void setEnable(boolean enable) {
+		this.enable = enable;
+	}
+	/**
+	 * Returns the IP filter enable flag.
+	 * @see #setEnable
+	 */
+	public boolean getEnable() {
+		return enable;
+	}
+
+	/**
+	 * Sets the allow access flag.
+	 * XML Tag: &lt;ip-filter&gt;&lt;allow-access&gt;true&lt;/allow-access&gt;&lt;/ip-filter&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+ 	 * @see #getAllowAccess
+	 */
+	public void setAllowAccess(boolean enable) {
+		this.allowAccess = enable;
+	}
+	/**
+	 * Returns the allow access flag.
+	 * @see #setAllowAccess
+	 */
+	public boolean getAllowAccess() {
+		return allowAccess;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<ip-filter>\n");
+		sb.append(pad).append("\t<enable>").append(getEnable()).append("</enable>\n");
+		sb.append(pad).append("\t<allow-access>").append(getAllowAccess()).append("</allow-access>\n");
+		sb.append(pad).append("\t<ip-collection>\n");
+		Iterator iterator = iterator();
+		while(iterator.hasNext()) {
+			String cip = (String)iterator.next();
+			sb.append(pad).append("\t\t<client-ip-address>").append(cip).append("</client-ip-address>\n");
+		}
+		sb.append(pad).append("\t</ip-collection>\n");
+		sb.append(pad).append("</ip-filter>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/KeyStoreInfo.java b/quickserver/src/main/org/quickserver/util/xmlreader/KeyStoreInfo.java
new file mode 100644
index 0000000..2aafbf8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/KeyStoreInfo.java
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate Key Store.
+ * The example xml is <pre>
+	....
+	&lt;key-store-info&gt;
+		&lt;store-file&gt;NONE&lt;/store-file&gt;
+		&lt;store-password&gt;&lt;/store-password&gt;
+		&lt;key-password&gt;&lt;/key-password&gt;
+	&lt;/key-store-info&gt;
+	....
+ </pre>
+ * @see TrustStoreInfo
+ * @see SecureStore
+ * @see Secure
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public class KeyStoreInfo implements java.io.Serializable {
+	private String storeFile = "NONE";
+	private String storePassword = null;
+	private String keyPassword = null;
+
+	/**
+     * Sets the store file path. This can be either absolute or
+	 * relative(to config file) path to the store file.
+	 * XML Tag: &lt;store-file&gt;NONE&lt;/store-file&gt;
+	 * @param storeFile store file.
+     * @see #getStoreFile
+     */
+	public void setStoreFile(String storeFile) {
+		if(storeFile!=null && storeFile.trim().length()!=0)
+			this.storeFile = storeFile;
+	}
+	/**
+     * Returns the store file path. This can be either absolute or
+	 * relative(to config file) path to the store file.
+     * @see #setStoreFile
+     */
+	public String getStoreFile() {
+		return storeFile;
+	}
+
+	/**
+     * Sets the store password.
+	 * XML Tag: &lt;store-password&gt;&lt;/store-password&gt;
+	 * @param storePassword store password
+     * @see #getStorePassword
+     */
+	public void setStorePassword(String storePassword) {
+		if(storePassword!=null)
+			this.storePassword = storePassword;
+	}
+	/**
+     * Returns store password.
+     * @see #setStorePassword
+     */
+	public String getStorePassword() {
+		return storePassword;
+	}
+
+	/**
+     * Sets the key password.
+	 * XML Tag: &lt;key-password&gt;&lt;/key-password&gt;
+	 * @param keyPassword key password
+     * @see #getKeyPassword
+     */
+	public void setKeyPassword(String keyPassword) {
+		if(keyPassword!=null)
+			this.keyPassword = keyPassword;
+	}
+	/**
+     * Returns key password.
+     * @see #setKeyPassword
+     */
+	public String getKeyPassword() {
+		return keyPassword;
+	}
+	
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<key-store-info>\n");
+		sb.append(pad).append("\t<store-file>").append(getStoreFile()).append("</store-file>\n");
+		if(getStorePassword()!=null)
+			sb.append(pad).append("\t<store-password>").append(getStorePassword()
+					).append("</store-password>\n");
+		else
+			sb.append(pad).append("\t</store-password>\n");
+		if(getKeyPassword()!=null)
+			sb.append(pad).append("\t<key-password>").append(getKeyPassword()
+					).append("</key-password>\n");
+		else
+			sb.append(pad).append("\t</key-password>\n");
+		sb.append(pad).append("</key-store-info>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ObjectPoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/ObjectPoolConfig.java
new file mode 100644
index 0000000..611bf50
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ObjectPoolConfig.java
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the Object pool configuration.
+ * The xml is &lt;object-pool&gt;...&lt;/object-pool&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.3
+ */
+public class ObjectPoolConfig extends PoolConfig {
+	private ThreadObjectPoolConfig threadObjectPoolConfig;
+	private ClientHandlerObjectPoolConfig clientHandlerObjectPoolConfig;
+	private ByteBufferObjectPoolConfig byteBufferObjectPoolConfig;
+	private ClientDataObjectPoolConfig clientDataObjectPoolConfig;
+	private String poolManager = null;
+
+	/**
+	 * Returns PoolManager object
+	 * @return poolManager
+	 */
+	public String getPoolManager() {
+		if(poolManager==null) 
+			poolManager = "org.quickserver.net.server.impl.BasicPoolManager";
+		return poolManager;
+	}
+	/**
+	 * @param poolManager
+	 */
+	public void setPoolManager(String poolManager) {
+		this.poolManager = poolManager;
+	}
+
+	/**
+	 * Returns ByteBufferObjectPoolConfig object
+	 * @return byteBufferObjectPoolConfig
+	 */
+	public ByteBufferObjectPoolConfig getByteBufferObjectPoolConfig() {
+		if(byteBufferObjectPoolConfig==null) 
+			byteBufferObjectPoolConfig = new ByteBufferObjectPoolConfig(this);
+		return byteBufferObjectPoolConfig;
+	}
+	/**
+	 * @param byteBufferObjectPoolConfig
+	 */
+	public void setByteBufferObjectPoolConfig(ByteBufferObjectPoolConfig byteBufferObjectPoolConfig) {
+		this.byteBufferObjectPoolConfig = byteBufferObjectPoolConfig;
+	}
+
+	/**
+	 * Returns ClientHandlerObjectPoolConfig object
+	 * @return clientHandlerObjectPoolConfig
+	 */
+	public ClientHandlerObjectPoolConfig getClientHandlerObjectPoolConfig() {
+		if(clientHandlerObjectPoolConfig==null) 
+			clientHandlerObjectPoolConfig = new ClientHandlerObjectPoolConfig(this);
+		return clientHandlerObjectPoolConfig;
+	}
+	/**
+	 * @param clientHandlerObjectPoolConfig
+	 */
+	public void setClientHandlerObjectPoolConfig(ClientHandlerObjectPoolConfig clientHandlerObjectPoolConfig) {
+		this.clientHandlerObjectPoolConfig = clientHandlerObjectPoolConfig;
+	}
+
+	/**
+	 * Returns ThreadObjectPoolConfig object
+	 * @return threadObjectPoolConfig
+	 */
+	public ThreadObjectPoolConfig getThreadObjectPoolConfig() {
+		if(threadObjectPoolConfig==null) 
+			threadObjectPoolConfig = new ThreadObjectPoolConfig(this);
+		return threadObjectPoolConfig;
+	}
+	/**
+	 * @param threadObjectPoolConfig
+	 */
+	public void setThreadObjectPoolConfig(ThreadObjectPoolConfig threadObjectPoolConfig) {
+		this.threadObjectPoolConfig = threadObjectPoolConfig;
+	}
+
+	/**
+	 * Returns ClientDataObjectPoolConfig object
+	 * @return clientDataObjectPoolConfig
+	 */
+	public ClientDataObjectPoolConfig getClientDataObjectPoolConfig() {
+		if(clientDataObjectPoolConfig==null) 
+			clientDataObjectPoolConfig = new ClientDataObjectPoolConfig(this);
+		return clientDataObjectPoolConfig;
+	}
+	/**
+	 * @param clientDataObjectPoolConfig
+	 */
+	public void setClientDataObjectPoolConfig(ClientDataObjectPoolConfig clientDataObjectPoolConfig) {
+		this.clientDataObjectPoolConfig = clientDataObjectPoolConfig;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<object-pool>\n");
+		sb.append(pad).append("\t<max-active>").append(getMaxActive()).append("</max-active>\n");
+		sb.append(pad).append("\t<max-idle>").append(getMaxIdle()).append("</max-idle>\n");
+		sb.append(pad).append("\t<init-size>").append(getInitSize()).append("</init-size>\n");
+		sb.append(getThreadObjectPoolConfig().toXML(pad+"\t"));
+		sb.append(getClientHandlerObjectPoolConfig().toXML(pad+"\t"));
+		sb.append(getByteBufferObjectPoolConfig().toXML(pad+"\t"));
+		sb.append(getClientDataObjectPoolConfig().toXML(pad+"\t"));
+		sb.append(pad).append("\t<pool-manager>").append(getPoolManager()).append("</pool-manager>\n");
+		sb.append(pad).append("</object-pool>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/PluginConfigReader.java b/quickserver/src/main/org/quickserver/util/xmlreader/PluginConfigReader.java
new file mode 100644
index 0000000..28d968a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/PluginConfigReader.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.io.*;
+import java.util.logging.*;
+import org.apache.commons.digester3.Digester;
+
+
+/**
+ * This class reads the xml configuration and gives 
+ * QSAdminPluginConfig object.
+ * @author Akshathkumar Shetty
+ * @since 1.3.2
+ */
+public class PluginConfigReader {
+	private static Logger logger = Logger.getLogger(PluginConfigReader.class.getName());
+
+	public static QSAdminPluginConfig read(String fileName) throws Exception {
+		File input = new File(fileName);
+		return read(input);
+	}
+
+	/**
+	 * Parses XML config of QSAdmin Plugin
+	 */
+	public static QSAdminPluginConfig read(File input) throws Exception {
+		Digester digester = new Digester();
+	    digester.setValidating(false);
+
+		String mainTag = "qsadmin-plugin";
+		
+		digester.addObjectCreate(mainTag, QSAdminPluginConfig.class);
+		digester.addBeanPropertySetter(mainTag+"/name", "name");
+		digester.addBeanPropertySetter(mainTag+"/desc", "desc");
+		digester.addBeanPropertySetter(mainTag+"/type", "type");
+		digester.addBeanPropertySetter(mainTag+"/main-class", "mainClass");
+		digester.addBeanPropertySetter(mainTag+"/active", "active");
+		
+
+		logger.fine("Loading Plugin config from xml file : " + input.getAbsolutePath());
+		QSAdminPluginConfig psc = (QSAdminPluginConfig) digester.parse(input);
+		return psc;
+	} 	
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/PoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/PoolConfig.java
new file mode 100644
index 0000000..fe086a9
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/PoolConfig.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the pool configuration.
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public class PoolConfig implements java.io.Serializable {
+	private int maxActive = -1;
+	private int maxIdle = 50;
+	private int initSize = 25;
+	
+	private long timeBetweenEvictionRunsMillis = 1000*60*3;
+	private long minEvictableIdleTimeMillis = 1000*60*2;
+
+	/**
+     * Returns the inital size of the pool.
+     * @see #setInitSize
+	 * @since 1.4.6
+     */
+	public int getInitSize() {
+		if(maxIdle!=-1 && initSize>maxIdle)
+			return maxIdle;
+		else
+			return initSize;
+	}
+    /**
+     * Sets the inital size of the pool.
+	 * XML Tag: &lt;init-size&gt;&lt;/init-size&gt;
+     * @param initSize inital size of the pool. 
+     * @see #getInitSize
+	 * @since 1.4.6
+     */
+	public void setInitSize(int initSize) {
+		this.initSize = initSize;
+	}
+
+	/**
+     * Returns the maximum active objects allowed in the pool.
+     * @see #setMaxActive
+     */
+	public int getMaxActive() {
+		return maxActive;
+	}
+    /**
+     * Sets the maximum active objects allowed in the pool.
+	 * XML Tag: &lt;max-activ&gt;&lt;/max-activ&gt;
+     * @param maxActive maximum allowed active objects	 
+     * @see #getMaxActive
+     */
+	public void setMaxActive(int maxActive) {
+		this.maxActive = maxActive;
+	}
+
+	/**
+     * Returns the maximum idle objects allowed in the pool.
+     * @see #setMaxIdle
+     */
+	public int getMaxIdle() {
+		return maxIdle;
+	}
+    /**
+     * Sets the maximum Idle objects allowed in the pool.
+	 * XML Tag: &lt;max-idle&gt;&lt;/max-idle&gt;
+     * @param maxIdle maximum allowed active objects
+     * @see #getMaxIdle
+     */
+	public void setMaxIdle(int maxIdle) {
+		this.maxIdle = maxIdle;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/Property.java b/quickserver/src/main/org/quickserver/util/xmlreader/Property.java
new file mode 100644
index 0000000..4f22eb3
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/Property.java
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the Property of Application Configuration.
+ * The xml is &lt;property&gt;...&lt;/property&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.3.2
+ */
+public class Property implements java.io.Serializable {
+	private String name;
+	private String value;
+
+	public Property() {
+	}
+
+	public Property(String name, String value) {
+		setName(name);
+		setValue(value);
+	}
+
+	/**
+	 * @return name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return name
+	 */
+	public String getValue() {
+		return value;
+	}
+
+	/**
+	 * @param value
+	 */
+	public void setValue(String value) {
+		this.value = value;
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/QSAdminPluginConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/QSAdminPluginConfig.java
new file mode 100644
index 0000000..064c443
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/QSAdminPluginConfig.java
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the QSAdmin Plugin configuration.
+ * The xml is &lt;qsadmin-plugin&gt;...&lt;/qsadmin-plugin&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.3.2
+ */
+public class QSAdminPluginConfig implements java.io.Serializable {
+	private String name="";
+	private String desc="";
+	private String type="";
+	private String mainClass="";
+	private String active="no";
+
+	/**
+	 * @return description
+	 */
+	public String getDesc() {
+		return desc;
+	}
+
+	/**
+	 * @param desc
+	 */
+	public void setDesc(String desc) {
+		if(desc!=null)
+			this.desc = desc;
+	}
+
+	/**
+	 * @param active Valid Values: <code>true</code> or <code>false</code>
+	 */
+	public void setActive(String active) {
+		if(active!=null)
+			this.active = active;
+	}
+
+	/**
+	 * Returns active flag.
+	 */
+	public String getActive() {
+		return active;
+	}
+	
+	/**
+	 * @return MainClass
+	 */
+	public String getMainClass() {
+		return mainClass;
+	}
+
+	/**
+	 * @param mainClass
+	 */
+	public void setMainClass(String mainClass) {
+		if(mainClass!=null)
+			this.mainClass = mainClass;
+	}
+
+	/**
+	 * @return name of the plugin
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name
+	 */
+	public void setName(String name) {
+		if(name!=null)
+			this.name = name;
+	}
+
+	/**
+	 * Returns class which plugin extends or implements.
+	 * @return type of plugin. 
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * @param type of class which plugin extends or implements.
+	 */
+	public void setType(String type) {
+		if(type!=null)
+			this.type = type;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<qsadmin-plugin>\n");
+		sb.append(pad).append("\t<name>").append(getName()).append("</name>\n");
+		sb.append(pad).append("\t<desc>").append(getDesc()).append("</desc>\n");
+		sb.append(pad).append("\t<type>").append(getType()).append("</type>\n");
+		sb.append(pad).append("\t<main-class>").append(getMainClass()).append("</main-class>\n");
+		sb.append(pad).append("\t<active>").append(getActive()).append("</active>\n");
+		sb.append(pad).append("</qsadmin-plugin>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/QSAdminServerConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/QSAdminServerConfig.java
new file mode 100644
index 0000000..0bc3c4a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/QSAdminServerConfig.java
@@ -0,0 +1,197 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import org.quickserver.net.server.QuickServer;
+import org.quickserver.net.qsadmin.QSAdminServer;
+
+/**
+ * This class encapsulate the configuration of QSAdminServer.
+ * This class is used by 
+ * {@link org.quickserver.net.server.QuickServer#configQuickServer} 
+ * and {@link org.quickserver.net.server.QuickServer#initService} method to 
+ * initialise QSAdminServer. 
+ * @author Akshathkumar Shetty
+ * @since 1.2
+ */
+public class QSAdminServerConfig extends BasicServerConfig {
+	
+	private String commandPlugin;
+	private String commandShellEnabled = "false";
+	private String commandShellPromptName = "QSAdmin";
+
+	public QSAdminServerConfig() {
+		setName("QSAdminServer v " + QSAdminServer.getVersion());
+		setPort(9877);
+		setBindAddr("127.0.0.1");
+		setClientCommandHandler("org.quickserver.net.qsadmin.CommandHandler");
+		setClientEventHandler("org.quickserver.net.qsadmin.CommandHandler");
+		setClientAuthenticationHandler("org.quickserver.net.qsadmin.Authenticator");
+		setClientData("org.quickserver.net.qsadmin.Data");
+		setMaxConnection(1);
+		getServerMode().setBlocking(true);
+	}
+	
+	
+	/** 
+	 * Set the CommandPlugin for QSAdminServer class which plugs in into 
+	 * CommandHandler of QsAdminServer,it will be null if not set. 
+	 * XML Tag: &lt;command-plugin&gt;&lt;/command-plugin&gt;
+	 */
+	public void setCommandPlugin(String plugin) {
+		if(plugin!=null && plugin.equals("")==false)
+			commandPlugin = plugin;
+	}
+	/** 
+	 * Gets the CommandPlugin for QSAdminServer class which plugsin into 
+	 * CommandHandler of QsAdminServer,it will be null if not set. 
+	 */
+	public String getCommandPlugin() {
+		return commandPlugin;
+	}
+
+
+	/** 
+	 * Set the CommandShellEnable flag for QSAdminServer
+	 * XML Tag: &lt;command-shell&gt;&lt;enable&gt;true&lt;/enable&gt;&lt;/command-shell&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+	 * @since 1.3.2
+	 */
+	public void setCommandShellEnable(String enable) {
+		if(enable!=null && enable.equals("")==false)
+			commandShellEnabled = enable;
+	}
+	/** 
+	 * Gets the CommandShellEnable flag for QSAdminServer
+	 * @since 1.3.2
+	 */
+	public String getCommandShellEnable() {
+		return commandShellEnabled;
+	}
+
+	/** 
+	 * Set the PromptName for QSAdminShell
+	 * XML Tag: &lt;command-shell&gt;&lt;prompt-name&gt;true&lt;/prompt-name&gt;&lt;/command-shell&gt;
+	 * Default values = <code>QSAdmin</code>
+	 * @since 1.3.2
+	 */
+	public void setCommandShellPromptName(String commandShellPromptName) {
+		if(commandShellPromptName!=null && commandShellPromptName.equals("")==false)
+			this.commandShellPromptName = commandShellPromptName;
+	}
+	/** 
+	 * Gets the PromptName for QSAdminShell
+	 * @since 1.3.2
+	 */
+	public String getCommandShellPromptName() {
+		return commandShellPromptName;
+	}
+
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad+"<qsadmin-server>\n");
+
+		if(getName()!=null) 
+			sb.append(pad+"\t<name>"+getName()+"</name>\n");
+		if(getServerBanner()!=null) 
+			sb.append(pad+"\t<server-banner>"+getServerBanner()+"</server-banner>\n");
+		sb.append(pad+"\t<port>"+getPort()+"</port>\n");
+		sb.append(pad+"\t<bind-address>"+getBindAddr()+"</bind-address>\n");
+
+		sb.append( getServerMode().toXML(pad+"\t") );
+
+		if(getClientEventHandler()!=null) 
+			sb.append(pad+"\t<client-event-handler>"+getClientEventHandler()+"</client-event-handler>\n");
+		if(getClientCommandHandler()!=null) 
+			sb.append(pad+"\t<client-command-handler>"+getClientCommandHandler()+"</client-command-handler>\n");		
+		if(getClientObjectHandler()!=null) 
+			sb.append(pad+"\t<client-object-handler>"+getClientObjectHandler()+"</client-object-handler>\n");
+		if(getClientBinaryHandler()!=null) 
+			sb.append(pad+"\t<client-binary-handler>"+getClientBinaryHandler()+"</client-binary-handler>\n");
+		if(getClientWriteHandler()!=null) 
+			sb.append(pad+"\t<client-write-handler>"+getClientWriteHandler()+"</client-write-handler>\n");
+		if(getClientAuthenticationHandler()!=null)
+			sb.append(pad+"\t<client-authentication-handler>"+getClientAuthenticationHandler()+"</client-authentication-handler>\n");
+		else if(getAuthenticator()!=null) 
+			sb.append(pad+"\t<authenticator>"+getAuthenticator()+"</authenticator>\n");
+		if(getClientData()!=null) 
+			sb.append(pad+"\t<client-data>"+getClientData()+"</client-data>\n");
+		if(getClientExtendedEventHandler()!=null) 
+			sb.append(pad+"\t<client-extended-event-handler>"+getClientExtendedEventHandler()+"</client-extended-event-handler>\n");
+	
+		sb.append(pad+"\t<timeout>"+getTimeout()+"</timeout>\n");
+		if(getTimeoutMsg()!=null) 
+			sb.append(pad+"\t<timeout-msg>"+getTimeoutMsg()+"</timeout-msg>\n");
+
+		sb.append(pad+"\t<max-auth-try>"+getMaxAuthTry()+"</max-auth-try>\n");
+		if(getMaxAuthTryMsg()!=null) 
+			sb.append(pad+"\t<max-auth-try-msg>"+getMaxAuthTryMsg()+"</max-auth-try-msg>\n");
+		
+		sb.append(pad+"\t<max-connection>"+getMaxConnection()+"</max-connection>\n");
+		if(getMaxConnectionMsg()!=null) 
+			sb.append(pad+"\t<max-connection-msg>"+getMaxConnectionMsg()+"</max-connection-msg>\n");
+		
+		/*
+		//Not used. Use main QS console logging
+		if(getConsoleLoggingLevel()!=null) 
+			sb.append(pad+"\t<console-logging-level>"+getConsoleLoggingLevel()+"</console-logging-level>\n");
+		if(getConsoleLoggingFormatter()!=null) 
+			sb.append(pad+"\t<console-logging-formatter>"+getConsoleLoggingFormatter()+"</consoleLoggingFormatter>\n");
+		*/
+
+		sb.append(getObjectPoolConfig().toXML(pad+"\t"));
+
+		sb.append(pad).append("\t<communication-logging>\n");
+		sb.append(pad).append("\t\t<enable>").append(getCommunicationLogging()
+				).append("</enable>\n");
+		sb.append(pad).append("\t</communication-logging>\n");
+		
+		if(getCommandPlugin()!=null) 
+			sb.append(pad).append("\t<command-plugin>").append(getCommandPlugin()
+					).append("</command-plugin>\n");
+		
+		sb.append(pad).append("\t<command-shell>\n");
+		sb.append(pad).append("\t\t<enable>").append(getCommandShellEnable()
+				).append("</enable>\n");
+		sb.append(pad).append("\t\t<prompt-name>").append(getCommandShellPromptName()
+				).append("</prompt-name>\n");
+		sb.append(pad+"\t</command-shell>\n");
+	
+		if(getAccessConstraintConfig()!=null) {
+			sb.append(getAccessConstraintConfig().toXML(pad+"\t"));
+		}
+
+		if(getServerHooks()!=null) {
+			sb.append( getServerHooks().toXML(pad+"\t") );
+		}
+
+		sb.append( getSecure().toXML(pad+"\t") );
+		sb.append( getAdvancedSettings().toXML(pad+"\t") );
+
+		sb.append(pad).append("</qsadmin-server>\n");
+		return sb.toString();
+	}
+
+	public String toString() {
+		return toXML(null);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/QuickServerConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/QuickServerConfig.java
new file mode 100644
index 0000000..74c2efe
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/QuickServerConfig.java
@@ -0,0 +1,280 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import org.quickserver.net.server.QuickServer;
+
+/**
+ * This class encapsulate the configuration of QuickServer.
+ * <p>
+ * This is used by {@link QuickServer#configQuickServer} and
+ * {@link QuickServer#initService} method to initialise 
+ * QuickServer. 
+ * </p>
+ * @author Akshathkumar Shetty
+ * @since 1.2
+ */
+public class QuickServerConfig extends BasicServerConfig {
+	
+	private QSAdminServerConfig qSAdminServerConfig;
+	private DBObjectPoolConfig dDObjectPoolConfig;
+	private ApplicationConfiguration applicationConfiguration;
+	private InitServerHooks initServerHooks;
+
+	private String securityManagerClass = null;
+	private String configFile = null;
+	private String applicationJarPath = null;
+
+	public QuickServerConfig() {
+		setName("QuickServer v"+QuickServer.getVersion());
+	}
+	
+	/**
+	 * Sets the QSAdminServer configuration.
+	 * XML Tag: &lt;qsadmin-server&gt;&lt;/qsadmin-server&gt;
+	 */
+	public void setQSAdminServerConfig(QSAdminServerConfig config) {
+		qSAdminServerConfig = config;
+	}
+	/**
+	 * Returns QSAdminServer configuration.
+	 */
+	public QSAdminServerConfig getQSAdminServerConfig() {
+		return qSAdminServerConfig;
+	}
+
+	/**
+	 * Sets the DBObjectPoolConfig
+	 * XML Tag: &lt;object-pool&gt;&lt;/object-pool&gt;
+	 * @since 1.3
+	 */
+	public void setDBObjectPoolConfig(DBObjectPoolConfig dDObjectPoolConfig) {
+		this.dDObjectPoolConfig = dDObjectPoolConfig;
+	}
+	/**
+	 * Returns DBObjectPoolConfig
+	 * @since 1.3
+	 */
+	public DBObjectPoolConfig getDBObjectPoolConfig() {
+		return dDObjectPoolConfig;
+	}
+
+	/**
+	 * Sets the Application Configuration. This can be used by application to 
+	 * store its configuration information.
+	 * XML Tag: &lt;application-configuration&gt;&lt;/application-configuration&gt;
+	 * @since 1.3.2
+	 */
+	public void setApplicationConfiguration(
+			ApplicationConfiguration applicationConfiguration) {
+		this.applicationConfiguration = applicationConfiguration;
+	}
+	/**
+	 * Returns ApplicationConfiguration
+	 * @since 1.3.2
+	 */
+	public ApplicationConfiguration getApplicationConfiguration() {
+		return applicationConfiguration;
+	}
+
+
+	/**
+	 * Sets the SecurityManager class
+	 * XML Tag: &lt;security-manager-class&gt;&lt;/security-manager-class&gt;
+	 * @param securityManagerClass className the fully qualified name of the 
+	 * class that extends {@link java.lang.SecurityManager}.
+	 * @see #getSecurityManagerClass
+	 * @since 1.3.3
+	 */
+	public void setSecurityManagerClass(String securityManagerClass) {
+		if(securityManagerClass!=null)
+			this.securityManagerClass = securityManagerClass;
+	}
+	/**
+	 * Returns the SecurityManager class
+	 * @see #setSecurityManagerClass
+	 * @since 1.3.3
+	 */
+	public String getSecurityManagerClass() {
+		return securityManagerClass;
+	}
+
+	/**
+	 * Sets the file path of the file that loaded the config from.
+	 * @since 1.3.3
+	 */
+	protected void setConfigFile(String fileName) {
+		configFile = fileName;
+	}
+
+	/**
+	 * Returns the file path of the file that loaded the configuration file.
+	 * @since 1.3.3
+	 */
+	public String getConfigFile() {
+		return configFile;
+	}
+
+
+	/**
+	 * Sets the applications jar/s path. This can be either absolute or
+	 * relative(to config file) path to the jar file or the directory containing the jars 
+	 * needed by the application.
+	 * @see #getApplicationJarPath
+	 * @since 1.3.3
+	 */
+	public void setApplicationJarPath(String applicationJarPath) {
+		this.applicationJarPath = applicationJarPath;
+	}
+
+	/**
+	 * Returns the applications jar/s path. This can be either absolute or
+	 * relative(to config file) path to the jar file or the directory containing the jars 
+	 * needed by the application.
+	 * @see #setApplicationJarPath
+	 * @since 1.3.3
+	 */
+	public String getApplicationJarPath() {
+		return applicationJarPath;
+	}
+
+
+	/**
+	 * Sets the InitServerHooks. 
+	 * @see #getInitServerHooks
+	 * @since 1.4
+	 */
+	public void setInitServerHooks(InitServerHooks initServerHooks) {
+		this.initServerHooks = initServerHooks;
+	}
+
+	/**
+	 * Returns the InitServerHooks.
+	 * @see #setInitServerHooks
+	 * @since 1.4
+	 */
+	public InitServerHooks getInitServerHooks() {
+		return initServerHooks;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 * @since 1.3
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad+"<quickserver>\n");
+
+		if(getName()!=null) 
+			sb.append(pad+"\t<name>"+getName()+"</name>\n");
+		if(getServerBanner()!=null) 
+			sb.append(pad+"\t<server-banner>"+getServerBanner()+"</server-banner>\n");
+		sb.append(pad+"\t<port>"+getPort()+"</port>\n");
+		if(getBindAddr()!=null) 
+			sb.append(pad+"\t<bind-address>"+getBindAddr()+"</bind-address>\n");
+
+		sb.append( getServerMode().toXML(pad+"\t") );
+
+		if(getClientEventHandler()!=null) 
+			sb.append(pad+"\t<client-event-handler>"+getClientEventHandler()+"</client-event-handler>\n");
+		if(getClientCommandHandler()!=null) 
+			sb.append(pad+"\t<client-command-handler>"+getClientCommandHandler()+"</client-command-handler>\n");
+		if(getClientObjectHandler()!=null) 
+			sb.append(pad+"\t<client-object-handler>"+getClientObjectHandler()+"</client-object-handler>\n");
+		if(getClientBinaryHandler()!=null) 
+			sb.append(pad+"\t<client-binary-handler>"+getClientBinaryHandler()+"</client-binary-handler>\n");
+		if(getClientWriteHandler()!=null) 
+			sb.append(pad+"\t<client-write-handler>"+getClientWriteHandler()+"</client-write-handler>\n");
+		if(getClientAuthenticationHandler()!=null)
+			sb.append(pad+"\t<client-authentication-handler>"+getClientAuthenticationHandler()+"</client-authentication-handler>\n");
+		else if(getAuthenticator()!=null)
+			sb.append(pad+"\t<authenticator>"+getAuthenticator()+"</authenticator>\n");
+		if(getClientData()!=null) 
+			sb.append(pad+"\t<client-data>"+getClientData()+"</client-data>\n");
+		if(getClientExtendedEventHandler()!=null) 
+			sb.append(pad+"\t<client-extended-event-handler>"+getClientExtendedEventHandler()+"</client-extended-event-handler>\n");
+	
+		sb.append( getDefaultDataMode().toXML(pad+"\t") );
+
+		sb.append(pad+"\t<timeout>"+getTimeout()+"</timeout>\n");
+		if(getTimeoutMsg()!=null) 
+			sb.append(pad+"\t<timeout-msg>"+getTimeoutMsg()+"</timeout-msg>\n");
+
+		sb.append(pad+"\t<max-auth-try>"+getMaxAuthTry()+"</max-auth-try>\n");
+		if(getMaxAuthTryMsg()!=null) 
+			sb.append(pad+"\t<max-auth-try-msg>"+getMaxAuthTryMsg()+"</max-auth-try-msg>\n");
+		
+		sb.append(pad+"\t<max-connection>"+getMaxConnection()+"</max-connection>\n");
+		if(getMaxConnectionMsg()!=null) 
+			sb.append(pad+"\t<max-connection-msg>"+getMaxConnectionMsg()+"</max-connection-msg>\n");
+		
+		
+		if(getConsoleLoggingLevel()!=null) 
+			sb.append(pad+"\t<console-logging-level>"+getConsoleLoggingLevel()+"</console-logging-level>\n");
+		if(getConsoleLoggingFormatter()!=null) 
+			sb.append(pad+"\t<console-logging-formatter>"+getConsoleLoggingFormatter()+"</console-logging-formatter>\n");
+		
+		sb.append(getObjectPoolConfig().toXML(pad+"\t"));
+
+		sb.append(pad+"\t<communication-logging>\n");
+		sb.append(pad+"\t\t<enable>"+getCommunicationLogging()+"</enable>\n");
+		sb.append(pad+"\t</communication-logging>\n");
+
+		if(getDBObjectPoolConfig()!=null) {
+			sb.append( getDBObjectPoolConfig().toXML(pad+"\t") );
+		}
+
+		if(getSecurityManagerClass()!=null) {
+			sb.append(pad+"\t<security-manager-class>"+getSecurityManagerClass()+"</security-manager-class>\n");
+		}
+
+		if(getAccessConstraintConfig()!=null) {
+			sb.append(getAccessConstraintConfig().toXML(pad+"\t"));
+		}
+
+		if(getQSAdminServerConfig()!=null) 
+			sb.append( getQSAdminServerConfig().toXML(pad+"\t") );
+
+
+		if(getApplicationConfiguration()!=null) {
+			sb.append( getApplicationConfiguration().toXML(pad+"\t") );
+		}
+
+		if(getApplicationJarPath()!=null) {
+			sb.append(pad+"\t<application-jar-path>"+
+				getApplicationJarPath()+
+				"</application-jar-path>\n");
+		}
+
+		if(getServerHooks()!=null) {
+			sb.append( getServerHooks().toXML(pad+"\t") );
+		}
+
+		if(getInitServerHooks()!=null) {
+			sb.append( getInitServerHooks().toXML(pad+"\t") );
+		}
+
+		sb.append( getSecure().toXML(pad+"\t") );
+		sb.append( getAdvancedSettings().toXML(pad+"\t") );
+
+		sb.append(pad+"</quickserver>\n");
+		return sb.toString();
+	}
+
+	public String toString() {
+		return toXML(null);
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/Secure.java b/quickserver/src/main/org/quickserver/util/xmlreader/Secure.java
new file mode 100644
index 0000000..ce4ead7
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/Secure.java
@@ -0,0 +1,207 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+
+/**
+ * This class encapsulate the setting that help in configuring a secure socket
+ * based QuickServer.
+ * The example xml is <pre>
+	....
+	&lt;secure&gt;
+		&lt;enable&gt;true&lt;/enable&gt;
+		&lt;load&gt;true&lt;/load&gt;
+		&lt;port&gt;&lt;/port&gt;
+		&lt;protocol&gt;TLS&lt;/protocol&gt;
+		&lt;client-auth-enable&gt;false&lt;/client-auth-enable&gt; 
+		&lt;secure-store&gt;
+			....
+		&lt;/secure-store&gt;
+	&lt;/secure&gt;
+	....
+ </pre>
+ * @see TrustStoreInfo
+ * @see KeyStoreInfo
+ * @see SecureStore
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public class Secure implements java.io.Serializable {
+	private boolean enable = false;
+	private boolean load = false;
+	private int port = -1; //will use servers port
+	private String protocol = "TLS";
+	private boolean clientAuthEnable = false;
+	private SecureStore secureStore = new SecureStore();
+
+	/**
+	 * Sets the Secure enable flag.
+	 * If not set, it will use <code>false</code><br/>
+	 * XML Tag: &lt;secure&gt;&lt;enable&gt;true&lt;/enable&gt;&lt;/secure&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+	 * If enable is set to <code>true</code> load is also set to <code>true</code>.
+ 	 * @see #getEnable
+	 */
+	public void setEnable(boolean enable) {
+		this.enable = enable;
+		if(enable==true) {
+			setLoad(true);
+		}
+	}
+	/**
+	 * Returns the Secure enable flag.
+	 * @see #setEnable
+	 */
+	public boolean getEnable() {
+		return enable;
+	}
+	/**
+	 * Returns the Secure enable flag.
+	 */
+	public boolean isEnable() {
+		return enable;
+	}
+
+
+	/**
+	 * Sets the load flag for SSLContext.
+	 * If not set, it will use <code>false</code><br/>
+	 * XML Tag: &lt;Secure&gt;&lt;load&gt;true&lt;/load&gt;&lt;/Secure&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+ 	 * @see #getLoad
+	 */
+	public void setLoad(boolean load) {
+		this.load = load;
+	}
+	/**
+	 * Returns the load flag for SSLContext.
+	 * @see #setLoad
+	 */
+	public boolean getLoad() {
+		return load;
+	}
+	/**
+	 * Returns the load flag for SSLContext.
+	 */
+	public boolean isLoad() {
+		return load;
+	}
+
+	/**
+     * Sets the port for the QuickServer to listen on in secure mode.
+	 * If not set, it will run on servers non secure port<br/>
+	 * XML Tag: &lt;port&gt;&lt;/port&gt;
+	 * @param port to listen on.
+     * @see #getPort
+     */
+	public void setPort(int port) {
+		if(port>=0)
+			this.port = port;
+	}
+	/**
+     * Returns the port for the QuickServer to listen on in secure mode.
+     * @see #setPort
+     */
+	public int getPort() {
+		return port;
+	}
+
+
+	/**
+     * Sets the protocol for the QuickServer to listen on in secure mode.
+	 * If not set, it will use <code>TLS</code><br/>
+	 * XML Tag: &lt;protocol&gt;TLS&lt;/protocol&gt;
+	 * @param protocol to listen on in secure mode.
+     * @see #getProtocol
+     */
+	public void setProtocol(String protocol) {
+		if(protocol!=null && protocol.trim().length()!=0)
+			this.protocol = protocol;
+	}
+	/**
+     * Returns the protocol for the QuickServer to listen on in secure mode.
+     * @see #setProtocol
+     */
+	public String getProtocol() {
+		return protocol;
+	}
+
+	/**
+     * Sets whether the connections which are accepted must include 
+	 * successful client authentication.
+	 * If not set, it will use <code>false</code><br/>
+	 * XML Tag: &lt;client-auth-enable&gt;false&lt;/client-auth-enable&gt;
+	 * @param enable client authentication enable flag
+     * @see #getClientAuthEnable
+     */
+	public void setClientAuthEnable(boolean enable) {
+		this.clientAuthEnable = enable;
+	}
+	/**
+     * Returns whether the connections which are accepted must include 
+	 * successful client authentication.
+     * @see #setClientAuthEnable
+     */
+	public boolean getClientAuthEnable() {
+		return clientAuthEnable;
+	}
+	/**
+	 * Returns whether the connections which are accepted must include 
+	 * successful client authentication.
+	 */
+	public boolean isClientAuthEnable() {
+		return clientAuthEnable;
+	}
+
+	/**
+     * Sets SecureStore information
+	 * XML Tag: &lt;secure-store&gt;&lt;/secure-store&gt;
+	 * @param secureStore SecureStore information
+     * @see #getSecureStore
+     */
+	public void setSecureStore(SecureStore secureStore) {
+		if(secureStore!=null)
+			this.secureStore = secureStore;
+	}
+	/**
+     * Returns SecureStore information.
+     * @see #setSecureStore
+     */
+	public SecureStore getSecureStore() {
+		return secureStore;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad+"<secure>\n");
+		sb.append(pad+"\t<enable>"+getEnable()+"</enable>\n");
+		sb.append(pad+"\t<load>"+getLoad()+"</load>\n");
+		if(getPort()!=-1)
+			sb.append(pad+"\t<port>"+getPort()+"</port>\n");
+		sb.append(pad+"\t<protocol>"+getProtocol()+"</protocol>\n");
+		sb.append(pad+"\t<client-auth-enable>"+
+			getClientAuthEnable()+"</client-auth-enable>\n");
+		if(getSecureStore()!=null) {
+			sb.append(getSecureStore().toXML(pad+"\t"));
+		}
+		sb.append(pad+"</secure>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/SecureStore.java b/quickserver/src/main/org/quickserver/util/xmlreader/SecureStore.java
new file mode 100644
index 0000000..e2db81a
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/SecureStore.java
@@ -0,0 +1,193 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the setting that help in configuring a secure store.
+ * The example xml is <pre>
+	....
+	&lt;secure-store&gt;
+		&lt;type&gt;JKS&lt;/type&gt;
+		&lt;algorithm&gt;SunX509&lt;/algorithm&gt;
+		&lt;provider&gt;SUN&lt;/provider&gt;
+		&lt;key-store-info&gt;
+			&lt;store-file&gt;&lt;/store-file&gt;
+			&lt;store-password&gt;&lt;/store-password&gt;
+			&lt;key-password&gt;&lt;/key-password&gt;
+		&lt;/key-store-info&gt;
+		&lt;trust-store-info&gt;
+			&lt;store-file&gt;&lt;/store-file&gt;
+			&lt;store-password&gt;&lt;/store-password&gt;
+		&lt;/trust-store-info&gt;
+		&lt;secure-store-manager&gt;org.quickserver.security.SecureStoreManager&lt;/secure-store-manager&gt;
+	&lt;/secure-store&gt;
+	....
+ </pre>
+ * @see TrustStoreInfo
+ * @see KeyStoreInfo
+ * @see Secure
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public class SecureStore implements java.io.Serializable {
+	private String type = "JKS";
+	private String algorithm = "SunX509";
+	private String provider = null;//"SUN";
+	private KeyStoreInfo keyStoreInfo = null;
+	private TrustStoreInfo trustStoreInfo = null;
+	private String secureStoreManager = "org.quickserver.security.SecureStoreManager";
+
+	/**
+     * Sets the type of keystore.
+	 * If not set, it will use <code>JKS</code><br/>
+	 * XML Tag: &lt;type&gt;JKS&lt;/type&gt;
+	 * @param type of keystore.
+     * @see #getType
+     */
+	public void setType(String type) {
+		if(type!=null && type.trim().length()!=0)
+			this.type = type;
+	}
+	/**
+     * Returns the type of keystore.
+     * @see #setType
+     */
+	public String getType() {
+		return type;
+	}
+
+	/**
+     * Sets the algorithm for the QuickServer used for key management 
+	 * when run in a secure mode.
+	 * If not set, it will use <code>SunX509</code><br/>
+	 * XML Tag: &lt;algorithm&gt;SunX509&lt;/algorithm&gt;
+	 * @param algorithm for key management.
+     * @see #getAlgorithm
+     */
+	public void setAlgorithm(String algorithm) {
+		if(algorithm!=null && algorithm.trim().length()!=0)
+			this.algorithm = algorithm;
+	}
+	/**
+     * Returns the algorithm for the QuickServer used for key management 
+	 * when run in a secure mode.
+     * @see #setAlgorithm
+     */
+	public String getAlgorithm() {
+		return algorithm;
+	}
+
+	/**
+     * Sets the provider of keystore.
+	 * Recommended not set, it will auto pick.<br/>
+	 * XML Tag: &lt;provider&gt;SUN&lt;/provider&gt;
+	 * @param provider of keystore.
+     * @see #getProvider
+     */
+	public void setProvider(String provider) {
+		if(provider!=null && provider.trim().length()!=0)
+			this.provider = provider;
+	}
+	/**
+     * Returns the provider of keystore.
+     * @see #setProvider
+     */
+	public String getProvider() {
+		return provider;
+	}
+
+	/**
+     * Sets KeyStore information
+	 * XML Tag: &lt;key-store-info&gt;&lt;/key-store-info&gt;
+	 * @param keyStoreInfo key store information
+     * @see #getKeyStoreInfo
+     */
+	public void setKeyStoreInfo(KeyStoreInfo keyStoreInfo) {
+		if(keyStoreInfo!=null)
+			this.keyStoreInfo = keyStoreInfo;
+	}
+	/**
+     * Returns KeyStore information.
+     * @see #setKeyStoreInfo
+     */
+	public KeyStoreInfo getKeyStoreInfo() {
+		return keyStoreInfo;
+	}
+
+	/**
+     * Sets TrustStore information
+	 * XML Tag: &lt;trust-store-info&gt;&lt;/trust-store-info&gt;
+	 * @param trustStoreInfo trust store information
+     * @see #getTrustStoreInfo
+     */
+	public void setTrustStoreInfo(TrustStoreInfo trustStoreInfo) {
+		if(trustStoreInfo!=null)
+			this.trustStoreInfo = trustStoreInfo;
+	}
+	/**
+     * Returns TrustStore information.
+     * @see #setTrustStoreInfo
+     */
+	public TrustStoreInfo getTrustStoreInfo() {
+		return trustStoreInfo;
+	}
+
+
+	/**
+     * Sets the SecureStoreManager class name.
+	 * If not set, it will use <code>org.quickserver.security.SecureStoreManager</code><br/>
+	 * XML Tag: &lt;secure-store-manager&gt;org.quickserver.security.SecureStoreManager&lt;/secure-store-manager&gt;
+	 * @param className the fully qualified name of the class that 
+	 * extends {@link org.quickserver.security.SecureStoreManager}
+     * @see #getSecureStoreManager
+	 * @see org.quickserver.security.SecureStoreManager
+	 * @since 1.4
+     */
+	public void setSecureStoreManager(String className) {
+		if(className!=null && className.trim().length()!=0)
+			this.secureStoreManager = className;
+	}
+	/**
+     * Returns the SecureStoreManager class.
+	 * @see #setSecureStoreManager
+	 * @see org.quickserver.security.SecureStoreManager
+	 * @since 1.4
+     */
+	public String getSecureStoreManager() {
+		return secureStoreManager;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<secure-store>\n");
+		sb.append(pad).append("\t<type>").append(getType()).append("</type>\n");
+		sb.append(pad).append("\t<algorithm>").append(getAlgorithm()).append("</algorithm>\n");
+		if(getProvider()!=null)
+			sb.append(pad).append("\t<provider>").append(getProvider()).append("</provider>\n");
+		if(getKeyStoreInfo()!=null) {
+			sb.append(getKeyStoreInfo().toXML(pad+"\t"));
+		}
+		if(getTrustStoreInfo()!=null) {
+			sb.append(getTrustStoreInfo().toXML(pad+"\t"));
+		}
+		sb.append(pad).append("\t<secure-store-manager>").append(getSecureStoreManager()).append("</secure-store-manager>\n");
+		sb.append(pad).append("</secure-store>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ServerHooks.java b/quickserver/src/main/org/quickserver/util/xmlreader/ServerHooks.java
new file mode 100644
index 0000000..20246c8
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ServerHooks.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+import java.util.*;
+
+/**
+ * This class encapsulate the Server Hooks. These are event listeners to 
+ * the QuickServer.
+ * The example xml is <pre>
+	....
+	&lt;server-hooks&gt;
+		&lt;class-name&gt;package1.Class1&lt;/class-name&gt;
+		&lt;class-name&gt;package1.Class2&lt;/class-name&gt;
+	&lt;/server-hooks&gt;
+	....
+ </pre>
+ * @see org.quickserver.net.ServerHook
+ * @see org.quickserver.util.xmlreader.InitServerHooks
+ * @author Akshathkumar Shetty
+ * @since 1.3.3
+ */
+public class ServerHooks extends ArrayList {
+	
+	/**
+	 * Addes the class to server hooks
+	 */
+	public void addClassName(String className) {
+		if(className!=null && className.trim().length()!=0) {
+			add(className.trim());
+		}
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<server-hooks>\n");
+		Iterator iterator = iterator();
+		while(iterator.hasNext()) {
+			String classname = (String) iterator.next();
+			sb.append(pad).append("\t<class-name>").append(classname).append("</class-name>\n");
+		}
+		sb.append(pad).append("</server-hooks>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ServerMode.java b/quickserver/src/main/org/quickserver/util/xmlreader/ServerMode.java
new file mode 100644
index 0000000..5abe6ac
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ServerMode.java
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the servers mode.
+ * The xml is &lt;server-mode&gt;...&lt;/server-mode&gt;
+ * @author Akshathkumar Shetty
+ * @since 1.4.5
+ */
+public class ServerMode implements java.io.Serializable {
+	private boolean blocking = true;
+
+	/**
+	 * Returns the blocking mode enable flag. Default is <code>true</code>.
+	 * @return blocking
+	 */
+	public boolean getBlocking() {
+		return blocking;
+	}
+
+	/**
+	 * Sets the blocking mode enable flag.
+	 * XML Tag: &lt;server-mode&gt;&lt;blocking&gt;true&lt;/blocking&gt;&lt;/server-mode&gt;
+	 * Allowed values = <code>true</code> | <code>false</code>
+	 * @param blocking
+	 */
+	public void setBlocking(boolean blocking) {
+		this.blocking = blocking;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<server-mode>\n");
+		sb.append(pad).append("\t<blocking>").append(getBlocking()).append("</blocking>\n");
+		sb.append(pad).append("</server-mode>\n");
+		return sb.toString();
+	}
+
+	public String toString() {
+		if(getBlocking())
+			return "Blocking";
+		else
+			return "Non-Blocking";
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/ThreadObjectPoolConfig.java b/quickserver/src/main/org/quickserver/util/xmlreader/ThreadObjectPoolConfig.java
new file mode 100644
index 0000000..829bc76
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/ThreadObjectPoolConfig.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate the Thread Object pool configuration.
+ * The xml is &lt;thread-object-pool&gt;...&lt;/thread-object-pool&gt;
+ * @author Akshathkumar Shetty
+ */
+public class ThreadObjectPoolConfig extends PoolConfig {
+
+	public ThreadObjectPoolConfig() {
+		super();
+	}
+
+	public ThreadObjectPoolConfig(PoolConfig poolConfig) {
+		setMaxActive(poolConfig.getMaxActive());
+		setMaxIdle(poolConfig.getMaxIdle());
+		setInitSize(poolConfig.getInitSize());
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<thread-object-pool>\n");
+		sb.append(pad).append("\t<max-active>").append(getMaxActive()).append("</max-active>\n");
+		sb.append(pad).append("\t<max-idle>").append(getMaxIdle()).append("</max-idle>\n");
+		sb.append(pad).append("\t<init-size>").append(getInitSize()).append("</init-size>\n");
+		sb.append(pad).append("</thread-object-pool>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/TrustStoreInfo.java b/quickserver/src/main/org/quickserver/util/xmlreader/TrustStoreInfo.java
new file mode 100644
index 0000000..9217967
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/TrustStoreInfo.java
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package org.quickserver.util.xmlreader;
+
+/**
+ * This class encapsulate Trust Store.
+ * The example xml is <pre>
+	....
+	&lt;trust-store-info&gt;
+		&lt;store-file&gt;NONE&lt;/store-file&gt;
+		&lt;store-password&gt;&lt;/store-password&gt;
+	&lt;/trust-store-info&gt;
+	....
+ </pre>
+ * @see KeyStoreInfo
+ * @see SecureStore
+ * @see Secure
+ * @author Akshathkumar Shetty
+ * @since 1.4
+ */
+public class TrustStoreInfo implements java.io.Serializable {
+	private String storeFile = "NONE";
+	private String storePassword = null;
+	private String type = null;
+	private String provider = null;
+
+	/**
+     * Sets the store file path. This can be either absolute or
+	 * relative(to config file) path to the store file.
+	 * XML Tag: &lt;store-file&gt;NONE&lt;/store-file&gt;
+	 * @param storeFile store file.
+     * @see #getStoreFile
+     */
+	public void setStoreFile(String storeFile) {
+		if(storeFile!=null && storeFile.trim().length()!=0)
+			this.storeFile = storeFile;
+	}
+	/**
+     * Returns the store file path. This can be either absolute or
+	 * relative(to config file) path to the store file.
+     * @see #setStoreFile
+     */
+	public String getStoreFile() {
+		return storeFile;
+	}
+
+	/**
+     * Sets the store password.
+	 * XML Tag: &lt;store-password&gt;&lt;/store-password&gt;
+	 * @param storePassword store password
+     * @see #getStorePassword
+     */
+	public void setStorePassword(String storePassword) {
+		if(storePassword!=null)
+			this.storePassword = storePassword;
+	}
+	/**
+     * Returns store password.
+     * @see #setStorePassword
+     */
+	public String getStorePassword() {
+		return storePassword;
+	}
+
+	/**
+     * Sets the type of trust store.
+	 * If not set, it will use value from SecureStore<br/>
+	 * XML Tag: &lt;type&gt;JKS&lt;/type&gt;
+	 * @param type of keystore.
+     * @see #getType
+     */
+	public void setType(String type) {
+		if(type!=null && type.trim().length()!=0)
+			this.type = type;
+	}
+	/**
+     * Returns the type of truststore.
+     * @see #setType
+     */
+	public String getType() {
+		return type;
+	}
+
+	/**
+     * Sets the provider of trust store. If not set, it will use value from SecureStore<br/>
+	 * XML Tag: &lt;provider&gt;SUN&lt;/provider&gt;
+	 * @param provider of keystore.
+     * @see #getProvider
+     */
+	public void setProvider(String provider) {
+		if(provider!=null && provider.trim().length()!=0)
+			this.provider = provider;
+	}
+	/**
+     * Returns the provider of keystore.
+     * @see #setProvider
+     */
+	public String getProvider() {
+		return provider;
+	}
+
+	/**
+	 * Returns XML config of this class.
+	 */
+	public String toXML(String pad) {
+		if(pad==null) pad="";
+		StringBuilder sb = new StringBuilder();
+		sb.append(pad).append("<trust-store-info>\n");
+		sb.append(pad).append("\t<store-file>").append(getStoreFile()).append("</store-file>\n");
+		if(getStorePassword()!=null)
+			sb.append(pad).append("\t<store-password>").append(getStorePassword()).append("</store-password>\n");
+		else
+			sb.append(pad).append("\t</store-password>\n");
+		if(getType()!=null)
+			sb.append(pad).append("\t<type>").append(getType()).append("</type>\n");
+		if(getProvider()!=null)
+			sb.append(pad).append("\t<provider>").append(getProvider()).append("</provider>\n");
+		sb.append(pad).append("</trust-store-info>\n");
+		return sb.toString();
+	}
+}
diff --git a/quickserver/src/main/org/quickserver/util/xmlreader/package.html b/quickserver/src/main/org/quickserver/util/xmlreader/package.html
new file mode 100644
index 0000000..2b057e4
--- /dev/null
+++ b/quickserver/src/main/org/quickserver/util/xmlreader/package.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+<TITLE> Overview </TITLE>

+</HEAD>

+

+<BODY>

+Classes for reading XML and storing the configuration.

+</BODY>

+</HTML>

diff --git a/quickserver/src/main/overview.html b/quickserver/src/main/overview.html
new file mode 100644
index 0000000..4f41b26
--- /dev/null
+++ b/quickserver/src/main/overview.html
@@ -0,0 +1,132 @@
+<body>

+QuickServer is an open source Java library/framework for quick creation 

+of robust multi-client TCP server applications. With QuickServer you can 

+concentrate on just the application logic/protocol on hand.  

+<br/>&nbsp;<br/>

+QuickServer provides an abstraction over the ServerSocket, Socket and 

+other network and input output classes and it eases the creation of 

+powerful network servers.

+

+

+<table><tr><td>

+<img src="quickserver_logo.gif" width="90" height="60" border="0" alt="QuickServer" align="bottom" valign="bottom" />

+</td><td>

+Example programs demonstrating the use of the library can be found 

+with the QuickServer distribution  [examples folder]. 

+Latest examples, documentation is available through the <a href="http://www.quickserver.org">website</a>.

+</td></tr></table>

+

+<br>&nbsp;<br>

+

+

+Brief Architecture<br>

+---------------------<br>

+QuickServer divides the application logic of its developer over eight 

+main classes,

+<br>

+	<ul>

+		<li>{@link org.quickserver.net.server.ClientEventHandler} [Optional Class]<br>

+		   &nbsp;Handles client events.

+		<li>{@link org.quickserver.net.server.ClientCommandHandler} [#]<br>

+		   &nbsp;Handles client interaction - Character/String commands.

+		<li>{@link org.quickserver.net.server.ClientBinaryHandler} [#]<br>

+		   &nbsp;Handles client interaction - Binary data.

+		<li>{@link org.quickserver.net.server.ClientObjectHandler} [#]<br>

+		   &nbsp;Handles client interaction - Java Object commands.	

+		<li>{@link org.quickserver.net.server.ClientAuthenticationHandler} [Optional Class]<br>

+			&nbsp;Used to Authenticate a client.

+		<li>{@link org.quickserver.net.server.ClientData} [Optional Class]<br>

+			&nbsp;Client data carrier (support class)

+		<li>{@link org.quickserver.net.server.ClientExtendedEventHandler} [Optional Class]<br>

+			&nbsp;Handles extended client events.

+	</ul>

+ 

+<p>

+ [#] = Any one of these have to be set based on default DataMode for input. 

+ The default DataMode for input is String so if not changes you will

+ have to set ClientCommandHandler.

+</p>

+For more info view QuickServer Wiki - <A HREF="http://code.google.com/p/quickserver/wiki/Architecture">Architecture</A>.

+<br/>&nbsp;<br />

+QuickServer Source -  <a href="https://github.com/QuickServerLab">GitHub</a>.

+

+<br />&nbsp;<br />

+Major Features<br />

+---------------------<br />

+ &nbsp;&nbsp;* Create multi-client TCP server applications.<br />

+ &nbsp;&nbsp;* Support for secure server creations: SSL, TLS. {@link org.quickserver.util.xmlreader.Secure}<br />

+ &nbsp;&nbsp;* Support for thread per client (multi-threaded) - Blocking Mode.<br />

+ &nbsp;&nbsp;* Clear separation of server, protocol and authentication logic.<br />

+ &nbsp;&nbsp;* Remote administration support: {@link org.quickserver.net.qsadmin.QSAdminServer} (With support plugable application commands).<br />

+ &nbsp;&nbsp;* Command Shell for local administration of server. <br />

+  &nbsp;&nbsp;&nbsp;&nbsp;{@link org.quickserver.net.qsadmin.QSAdminServer#setShellEnable}<br />

+ &nbsp;&nbsp;* GUI based remote administration: QsAdminGUI (with support for plug-ins - {@link org.quickserver.net.qsadmin.gui.PluginPanel})<br />

+ &nbsp;&nbsp;* Restart or Suspend the server without killing connected clients.<br />

+ &nbsp;&nbsp;* Inbuilt pools for reusing of threads and most used Objects.<br />

+ &nbsp;&nbsp;* Full logging support [Java built in Logging].<br />

+ &nbsp;&nbsp;* Support for sending and receiving Strings, Bytes, Binary and serialized java objects.<br />

+ &nbsp;&nbsp;* Support for identifying and searching a client. {@link org.quickserver.net.server.ClientIdentifiable}<br />

+ &nbsp;&nbsp;* Support for xml configuration with ability to store application specific 

+   data in the same xml. <br />

+ &nbsp;&nbsp;&nbsp;&nbsp;[<a href="XMLConfiguration.xml" target="_new">View Sample</a>]<br />

+ &nbsp;&nbsp;* Support for xml Based JDBC Mapping - {@link org.quickserver.sql.DBPoolUtil}.<br />

+ &nbsp;&nbsp;* Support for Service Configurator pattern. {@link org.quickserver.net.Service}<br />

+ &nbsp;&nbsp;* Support for restricting access to server by ip address.<br />

+ &nbsp;&nbsp;* Support for loading/reloading application jar from xml.<br />

+ &nbsp;&nbsp;* Ability to add process hooks into QuickServer. {@link org.quickserver.net.ServerHook}, {@link org.quickserver.net.InitServerHook}<br />

+ &nbsp;&nbsp;* Ability to specify maximum number of clients allowed.<br />

+ &nbsp;&nbsp;* Support for negotiating secure connection over normal tcp connection.<br />

+ &nbsp;&nbsp;* Nice easy examples come with the distribution - FTPServer, CmdServer, EchoWebServer, ChatServer, SecureEchoWebServer, XmlAdder, PipeServer, Filesrv.<br />

+

+<br>&nbsp;<br>

+Whats New in 2.1.0 ?<br>

+------------------------<br>

+&nbsp;&nbsp;* Added support for uptime in Host (QuickServer Client)<br/>

+&nbsp;&nbsp;* Supports null/no banner when server starts<br />

+&nbsp;&nbsp;* Fixed load pattern logic RandomLoadPattern, RoundRobinLoadPattern 

+  (was using index when client key was set)<br />

+&nbsp;&nbsp;* Added getHighestActiveCount() method to Object Pools<br />

+&nbsp;&nbsp;* Added getHighestActiveClientCount method to QuickServer object<br />

+&nbsp;&nbsp;* Defaulted SSL to TLS<br />

+&nbsp;&nbsp;* Bug fix for ThreadPool not reducing to max ideal 

+  (stay in wait state n increase over time)<br />

+&nbsp;&nbsp;* Bug fix for Client (HashedLoadPattern)

+&nbsp;&nbsp;* Disabled non blocking mode (no more supported) 

+

+<br>&nbsp;<br>

+QuickServer Credits <br>

+---------------------<br>

+Thanks to everyone who helped me in this project. Thanks to all users 

+who posted/sent their valuable comments and suggestion. 

+I would also like to thank all the people who have posted/sent bug 

+reports. Please do keep reporting any bugs that you find in QuickServer 

+that way you will be helping in improving it. 

+Do visit our web site for full credits listing.  

+

+

+<br>&nbsp;<br>

+Get Support  <br>

+---------------------<br>

+Do post your questions, suggestions, bug-reports, enhancement-requests 

+etc. at <a href="http://www.quickserver.org/forum/">Developers Forum</a>. Please do not contact development team directly unless you really would like to send a private message. 

+<br/>

+Note: We provide a higher level of support to individuals and companies 

+who have contributed to QuickServer project in some way.

+There are a number of ways to contribute, do visit our web site for details 

+on ways of contributing to QuickServer.

+

+

+<br>&nbsp;<br>

+Request to Developers<br>

+---------------------<br>

+If you would like to contribute to the development of QuickServer 

+please do get in touch with me. I am always on the lookout for

+people who can contribute to make this library even better.

+<br/>

+If you use QuickServer in your development and if you would like to 

+share your experience with the QuickServer community, please feel 

+free to post it in the QuickServer Forums. Thanks

+

+<br>&nbsp;<br>

+Web Site : <a href="http://www.quickserver.org" target="_blank">http://www.quickserver.org</a>

+</body>
\ No newline at end of file
diff --git a/quickserver/src/main/quickserver_logo.gif b/quickserver/src/main/quickserver_logo.gif
new file mode 100644
index 0000000..b4d5c5a
--- /dev/null
+++ b/quickserver/src/main/quickserver_logo.gif
Binary files differ
diff --git a/quickserver/src/test/org/quickserver/AllJUnitTests.java b/quickserver/src/test/org/quickserver/AllJUnitTests.java
new file mode 100644
index 0000000..0498291
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/AllJUnitTests.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import test.org.quickserver.net.server.*;
+
+/**
+ * Simple class to build a TestSuite out of the individual test classes.
+ */
+public class AllJUnitTests extends TestCase {
+
+    public AllJUnitTests(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        TestSuite suite = new TestSuite(SkeletonTest.class);
+		//TestSuite suite = new TestSuite();
+        suite.addTest(new TestSuite(QuickServerTest.class));
+        suite.addTest(new TestSuite(SimpleServerBlockTest.class));
+		suite.addTest(new TestSuite(SimpleServerNBlockTest.class));
+        return suite;
+   }
+}
diff --git a/quickserver/src/test/org/quickserver/SkeletonTest.java b/quickserver/src/test/org/quickserver/SkeletonTest.java
new file mode 100644
index 0000000..8aa9ee6
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/SkeletonTest.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver;
+
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+
+/**
+ *  Template used to create other test
+ */
+public class SkeletonTest extends TestCase {
+
+    public SkeletonTest(String name) {
+        super(name);
+    }
+
+    protected void setUp() {
+    }
+
+    protected void tearDown() {
+    }
+
+    public static void main(String args[]) {
+         junit.textui.TestRunner.run(SkeletonTest.class);
+    }
+
+    public void testAssert() {
+    	assertTrue(true);
+    }
+}
diff --git a/quickserver/src/test/org/quickserver/net/client/BlockingUDPClientTest.java b/quickserver/src/test/org/quickserver/net/client/BlockingUDPClientTest.java
new file mode 100644
index 0000000..8646e46
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/client/BlockingUDPClientTest.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.server;
+
+import org.quickserver.net.client.BlockingUDPClient;
+import org.quickserver.util.xmlreader.Property;
+
+
+
+/**
+ *
+ * @author mukundan
+ */
+public class BlockingUDPClientTest {
+	
+	private static BlockingUDPClient udpClient = new BlockingUDPClient();
+	private static String data = "hello from client";
+	private static String host = "localhost";
+	private static Property property = new Property("name", "value");
+	private static int port = 8855;
+	private static String charset = "ISO-8859-1";
+	
+	private static byte [] resp;
+	private static String response;
+	
+	public static void main (String [] args) throws Exception{
+		UDPEchoServer.setPort(port);
+		test_send_receive_binary();
+		test_send_receive_bytes();
+		test_send_receive_line();
+		test_send_receive_object();
+		resp = udpClient.sendAndReceiveBinary(host, port, data.getBytes());
+		System.out.println("sendAndReceiveBinary:"+new String(resp));
+		response = udpClient.sendAndReceiveBytes(host, port, data);
+		System.out.println("sendAndReceiveBytes:"+response);
+		udpClient = new BlockingUDPClient();
+		response = udpClient.sendAndReceiveLine(host, port, data+"\r\n"+"second line");
+		System.out.println("sendAndReceiveLine1:"+response);
+		response = udpClient.readLine();
+		System.out.println("sendAndReceiveLine2:"+response);
+		property = (Property)udpClient.sendAndReceiveObject(host, port, property);
+		System.out.println("sendAndReceiveObject:"+property.getName()+":"+property.getValue());
+		UDPEchoServer.stopServer();
+	}
+	
+	public static void test_send_receive_binary() throws Exception{
+		udpClient.connect(host, port);
+		udpClient.sendBytes(data.getBytes());
+		resp = udpClient.readBytes();
+		System.out.println("C:gotBinary="+new String(resp));
+	}
+	
+	public static void test_send_receive_bytes() throws Exception{
+		udpClient.connect(host, port);
+		udpClient.sendBytes(data, charset);
+		response = udpClient.readBytes(charset);
+		System.out.println("C:gotBytes="+response);
+	}
+	
+	public static void test_send_receive_line() throws Exception{
+		udpClient.connect(host, port);
+		udpClient.sendLine(data+"\r\n"+"second hello from client",charset);
+		response = udpClient.readLine();
+		System.out.println("C:gotLine1="+response);
+		response = udpClient.readLine();
+		System.out.println("C:gotLine2="+response);
+	}
+	
+	public static void test_send_receive_object() throws Exception{
+		udpClient.connect(host, port);
+		property = new Property();
+		property.setValue("value");
+		udpClient.sendObject(property);
+		property = (Property)udpClient.readObject();
+		System.out.println("C:gotObject:"+property.getValue());
+	}
+}
diff --git a/quickserver/src/test/org/quickserver/net/server/QuickServerTest.java b/quickserver/src/test/org/quickserver/net/server/QuickServerTest.java
new file mode 100644
index 0000000..cb0560e
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/server/QuickServerTest.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver.net.server;
+
+import org.quickserver.net.server.*;
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+import java.util.logging.*;
+
+/**
+ * JUnit test cases for QuickServer
+ */
+
+public class QuickServerTest extends TestCase {
+	private QuickServer server;
+
+    public QuickServerTest(String name) {
+        super(name);
+    }
+
+	public void setUp(){
+		server = new QuickServer("Test");
+	}
+
+	public void tearDown(){
+		server = null;
+	}
+
+    public static void main(String args[]) {
+        junit.textui.TestRunner.run(QuickServerTest.class);
+    }
+
+    public void testQuickServerStatics() {
+		assertEquals("1.47",  ""+QuickServer.getVersionNo() );
+		assertEquals("1.4.7",  QuickServer.getVersion() );
+    }
+
+	public void testQuickServerBasic() {        
+        assertNotNull(server);
+	}
+
+	public void testQuickServerTimeout() {
+		server.setTimeout(5);
+        assertEquals(5, server.getTimeout() );
+	}
+
+	public void testQuickServerClientCount() {
+		assertEquals(0, server.getClientCount() );
+		assertEquals(true, server.isClosed() );
+	}
+
+	public void testQuickServerBindAddr() {
+		assertNotNull(server.getBindAddr());
+	}
+
+	public void testQuickServerStore() {
+		Object[] store = new Object[]{"test123"};
+		server.setStoreObjects(store);
+		assertEquals(store, server.getStoreObjects() );
+    }
+
+	//v1.2	
+	public void testQuickServerAppLogger() {
+		assertNotNull(server.getAppLogger());
+	}
+}
diff --git a/quickserver/src/test/org/quickserver/net/server/SimpleServerBlockTest.java b/quickserver/src/test/org/quickserver/net/server/SimpleServerBlockTest.java
new file mode 100644
index 0000000..66adb7c
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/server/SimpleServerBlockTest.java
@@ -0,0 +1,164 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver.net.server;
+
+import org.quickserver.net.server.*;
+import org.quickserver.net.client.*;
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+import java.util.logging.*;
+import org.quickserver.util.xmlreader.QuickServerConfig;
+
+/**
+ * JUnit test cases for QuickServer
+ */
+
+public class SimpleServerBlockTest extends TestCase {
+	private QuickServer server;
+	private ClientService client;
+	private String host = "127.0.0.1";
+	private int port = 54321;
+	private QuickServerConfig config;
+
+	public boolean getServerMode() {
+		return false;
+	}
+
+	public String getServerName() {
+		return "SimpleServerBlockTest";
+	}
+
+    public SimpleServerBlockTest(String name) {
+        super(name);		
+    }
+
+	private void configServer() {
+		config = new QuickServerConfig();
+		config.setName(getServerName());
+		config.setClientEventHandler("test.org.quickserver.net.server.TestEventHandler");
+		config.setClientCommandHandler("test.org.quickserver.net.server.TestCommandHandler");
+		config.getServerMode().setBlocking(getServerMode());
+		config.setPort(port);
+		config.setBindAddr(host);
+	}
+
+	public void setUp() {
+		server = new QuickServer();
+		client = new BlockingClient();		
+		configServer();
+
+		server.initService(config);
+
+		TestEventHandler.reset();
+		TestCommandHandler.reset();
+		
+		try {
+			server.startServer();
+		} catch(Exception e) {
+			server = null;
+			fail("Server could not start: "+e);
+		}		
+	}
+
+	public void tearDown() {
+		try {
+			if(server!=null) server.stopServer();
+		} catch(Exception e) {
+			fail("Server could not stop: "+e);
+		}
+		//server = null;
+	}
+
+    public static void main(String args[]) {
+        junit.textui.TestRunner.run(SimpleServerBlockTest.class);
+    }
+
+   
+	public void testQuickServerBasic() {
+		try {
+			assertEquals(0, TestEventHandler.getGotConnectedFlag());
+			assertEquals(0, TestEventHandler.getClosingConnectionFlag());
+			assertEquals(0, TestEventHandler.getLostConnectionFlag());
+			assertEquals(0, TestCommandHandler.getHandleCommandFlag());
+
+			client.connect(host, port);
+			sleep(50);
+			assertEquals(1, TestEventHandler.getGotConnectedFlag());
+			System.out.println("GotConnected Pass");
+
+			client.sendString("test1");
+			sleep(50);
+			assertEquals(1, TestCommandHandler.getHandleCommandFlag());
+			assertEquals("test1", TestCommandHandler.getRequest());
+			System.out.println("HandleCommand 1 Pass");
+
+			TestCommandHandler.setResponse("junit");
+			client.sendString("test2");
+			sleep(50);
+			assertEquals(2, TestCommandHandler.getHandleCommandFlag());
+			assertEquals("test2", TestCommandHandler.getRequest());
+			assertEquals("junit", client.readString());
+			System.out.println("HandleCommand 2 Pass");		
+
+			TestCommandHandler.setResponse("quit");
+			client.sendString("test3");
+			sleep(50);
+			assertEquals(3, TestCommandHandler.getHandleCommandFlag());
+			assertEquals(1, TestEventHandler.getClosingConnectionFlag());
+			System.out.println("ClosingConnection Pass");
+
+			sleep(100);
+			assertTrue(client.readString()==null);
+			System.out.println("isConnected Pass");
+			client.close();
+		} catch(Exception e) {
+			fail("Exception: "+e);
+		}
+	}
+
+	public void testQuickServerLostCon() {
+		try {
+			assertEquals(0, TestEventHandler.getGotConnectedFlag());
+			assertEquals(0, TestEventHandler.getClosingConnectionFlag());
+			assertEquals(0, TestEventHandler.getLostConnectionFlag());
+			assertEquals(0, TestCommandHandler.getHandleCommandFlag());
+
+			client.connect(host, port);
+			sleep(50);
+			assertEquals(1, TestEventHandler.getGotConnectedFlag());
+			System.out.println("GotConnected Pass");
+
+			client.sendString("test1");
+			sleep(50);
+			assertEquals(1, TestCommandHandler.getHandleCommandFlag());
+			assertEquals("test1", TestCommandHandler.getRequest());
+			System.out.println("HandleCommand 1 Pass");
+
+			client.close();
+			sleep(50);
+			assertEquals(1, TestEventHandler.getLostConnectionFlag());
+			System.out.println("LostConnection Pass");		
+
+		} catch(Exception e) {
+			fail("Exception: "+e);
+		}
+	}
+
+	private void sleep(int time) {
+		try {
+			Thread.currentThread().sleep(time);
+		} catch(Exception e) {}
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/test/org/quickserver/net/server/SimpleServerNBlockTest.java b/quickserver/src/test/org/quickserver/net/server/SimpleServerNBlockTest.java
new file mode 100644
index 0000000..7d9379d
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/server/SimpleServerNBlockTest.java
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver.net.server;
+
+import org.quickserver.net.server.*;
+import org.quickserver.net.client.*;
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+import java.util.logging.*;
+import org.quickserver.util.xmlreader.QuickServerConfig;
+
+/**
+ * JUnit test cases for QuickServer
+ */
+public class SimpleServerNBlockTest extends SimpleServerBlockTest {
+	public SimpleServerNBlockTest(String name) {
+        super(name);
+    }
+
+	public boolean getServerMode() {
+		return true;
+	}
+	public String getServerName() {
+		return "SimpleServerNBlockTest";
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/test/org/quickserver/net/server/TestCommandHandler.java b/quickserver/src/test/org/quickserver/net/server/TestCommandHandler.java
new file mode 100644
index 0000000..14975ac
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/server/TestCommandHandler.java
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver.net.server;
+
+import org.quickserver.net.server.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * TestEventHandler for QuickServer
+ */
+public class TestCommandHandler implements ClientCommandHandler {
+	private static int handleCommandFlag;
+	private static String response;
+	private static String request;
+
+	public void handleCommand(ClientHandler handler, String command)
+			throws SocketTimeoutException, IOException {
+		handleCommandFlag++;
+		request = command;
+		//System.out.println("Got->"+command+"<-");
+		if(response!=null) {
+			if(response.toLowerCase().equals("quit")) {
+				handler.closeConnection();
+				response = null;
+			} else {
+				handler.sendClientMsg(response);
+				response = null; 
+			}
+		}
+	}
+
+	public static String getRequest() {
+		return request;
+	}
+
+	public static String getResponse() {
+		return response;
+	}
+	public static void setResponse(String res) {
+		response = res;
+	}
+
+	public static int getHandleCommandFlag() {
+		return handleCommandFlag;
+	}
+	public static void reset() {
+		handleCommandFlag = 0;
+	}
+}
\ No newline at end of file
diff --git a/quickserver/src/test/org/quickserver/net/server/TestEventHandler.java b/quickserver/src/test/org/quickserver/net/server/TestEventHandler.java
new file mode 100644
index 0000000..de68e20
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/server/TestEventHandler.java
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+
+package test.org.quickserver.net.server;
+
+import org.quickserver.net.server.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * TestEventHandler for QuickServer
+ */
+public class TestEventHandler implements ClientEventHandler {
+	private static volatile int gotConnectedFlag;
+	private static volatile int lostConnectionFlag;
+	private static volatile int closingConnectionFlag;
+
+	public void gotConnected(ClientHandler handler)	throws SocketTimeoutException, IOException {
+		gotConnectedFlag++;
+	}
+	public void lostConnection(ClientHandler handler) throws IOException {
+		lostConnectionFlag++;
+	}
+	public void closingConnection(ClientHandler handler) throws IOException {
+		closingConnectionFlag++;
+	}
+
+	public static int getGotConnectedFlag() {
+		return gotConnectedFlag;
+	}
+	public static int getLostConnectionFlag() {
+		return lostConnectionFlag;
+	}
+	public static int getClosingConnectionFlag() {
+		return closingConnectionFlag;
+	}
+
+	public static void reset() {
+		gotConnectedFlag = 0;
+		lostConnectionFlag = 0;
+		closingConnectionFlag = 0;
+	}
+}
diff --git a/quickserver/src/test/org/quickserver/net/server/UDPEchoServer.java b/quickserver/src/test/org/quickserver/net/server/UDPEchoServer.java
new file mode 100644
index 0000000..1af5673
--- /dev/null
+++ b/quickserver/src/test/org/quickserver/net/server/UDPEchoServer.java
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the QuickServer library 
+ * Copyright (C) QuickServer.org
+ *
+ * Use, modification, copying and distribution of this software is subject to
+ * the terms and conditions of the GNU Lesser General Public License. 
+ * You should have received a copy of the GNU LGP License along with this 
+ * library; if not, you can download a copy from <http://www.quickserver.org/>.
+ *
+ * For questions, suggestions, bug-reports, enhancement-requests etc.
+ * visit http://www.quickserver.org
+ *
+ */
+package org.quickserver.net.server;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author mukundan
+ */
+public class UDPEchoServer {
+
+	private static final Logger logger = Logger.getLogger(UDPEchoServer.class.getName());
+
+	private static DatagramSocket socket;
+	private static DatagramPacket incoming;
+	private static DatagramPacket outgoing;
+	
+	private static int port;
+	private static byte[] incomingData = new byte[512];
+	
+	private static Thread t;
+	private static boolean stopRunning = false;
+	
+	static{
+		try {
+			t = new Thread(){
+				@Override
+				public void run(){
+					try {
+						startServer();
+					} catch (SocketException ex) {
+						logger.log(Level.SEVERE, null, ex);
+					} catch (IOException ex) {
+						logger.log(Level.SEVERE, null, ex);
+					}
+				}
+			};
+			t.start();
+			t.setName("UDPEchoServer-Thread");
+		} catch (Exception ex) {
+			logger.log(Level.SEVERE, null, ex);
+		}
+	}
+
+	private static void startServer() throws SocketException, IOException {
+		socket = new DatagramSocket(getPort());
+		incoming = new DatagramPacket(incomingData, incomingData.length);
+		byte[] inBytes;
+		int inLen;
+		while (true){
+			try{
+				socket.setSoTimeout(5000);
+				socket.receive(incoming);
+			} catch(SocketTimeoutException e){
+				
+			}
+			if (stopRunning){
+				break;
+			}
+			inLen = incoming.getLength();
+			inBytes = new byte[inLen];
+			System.arraycopy(incoming.getData(), 0, inBytes, 0, inLen);
+			String inData = new String(inBytes);
+			System.out.println("S:got="+inData);
+			logger.log(Level.FINE, "S:got={0}", inData);
+			outgoing = new DatagramPacket(inBytes, inBytes.length, incoming.getSocketAddress());
+			socket.send(outgoing);
+		}
+		logger.fine("UDPEchoServer stopped.");
+	}
+
+	public static void stopServer() {
+		stopRunning = true;
+	}
+	public static int getPort() {
+		return port;
+	}
+
+	public static void setPort(int aPort) {
+		port = aPort;
+	}
+}
diff --git a/quickserver/todo.txt b/quickserver/todo.txt
new file mode 100644
index 0000000..a98a20a
--- /dev/null
+++ b/quickserver/todo.txt
@@ -0,0 +1,61 @@
+++++++++++++++++++++++++++++
+|  Todo for QuickServer    |
+++++++++++++++++++++++++++++
+
+Current Version: 2.1.0
+
+This document contains a list of todo items that needs to be implemented
+or improved upon in future releases of QuickServer. This is not a 
+comprehensive list. There might be other features, which have/may been/be  
+incorporated but not mentioned here.
+
+------------------------------------------------------------------------
+ #  Description						Version  Status
+------------------------------------------------------------------------
+ 1  Add Method setMaxClients() to QuickServer		 1.1.0 	  Done
+ 2  Add Method to bind QuickServer to ip address	 1.1.0	  Done
+ 3  Add an admin port and define the protocol: QsAdmin	 1.1.0	  Done
+ 4  Add logging						 1.2.0	  Done
+ 5  Plug able command handler for QsAdmin		 1.2.0	  Done
+ 6  Support for sending and receive java objects	 1.2.0	  Done
+ 7  Add GUIAdmin Controller for QsAdmin			 1.3.0	  Done
+ 8  Add GUI for QuickServer [About]			 1.3.0	  Done
+ 9  Add Generic Authorisation Class {Authenticator}	 1.3.0	  Done
+10  XML Based JDBC Mapping				 1.3.0	  Done
+11  Method to get info on clients and find specific	 1.3.1	  Done
+    client.
+12  Add Server statistics view to GUIAdmin		 1.3.2	  Done
+13  Loading application commands to GUIAdmin :Plug in	 1.3.2	  Done
+14  IP Filter for clients				 1.3.3	  Done
+15  Loading/Reloading application jar from xml		 1.3.3	  Done
+16  Add startup, shutdown process hooks to QuickServer	 1.3.3	  Done
+17  SecureSocket support (SSL, TLS)			 1.4.0	  Done
+18  Add BINARY mode					 1.4.0	  Done
+19  Support for Java NIO				 1.4.5	  Done
+20  Support for Assertion				 1.4.5	  Done
+22  New interfaces: ClientExtendedEventHandler,		 1.4.6	  Done
+    ClientAuthenticationHandler 
+23  Support for Auto NIO Writes				 1.4.7	  Done
+24  Support for Object Mode in NIO			 -----	  On Hold
+25  SSL support on NIO					 1.4.9
+26  Timeout in NIO mode					 1.5.0
+27  Support for generic logging				 1.5.0
+28  Support for running on more than one port		 1.5.1
+29  Support for managing more than one server using	 1.5.1
+    a single QSAdminServer
+30  JMX Integration					 1.5.2
+31  Delayed close connection				 1.5.3
+32  Add GUI for generating XML for QuickServer	  
+ 
+Access Logs
+------------------------------------------------------------------------
+
+If you have a suggestions on a feature or need to request a new feature do
+post it at http://www.quickserver.org/forum/
+
+
+Date: 12 Aug 2017
+---------------------
+
+Copyright (C) 2003-2017 QuickServer.org
+http://www.quickserver.org     
diff --git a/quickserver/version.txt b/quickserver/version.txt
new file mode 100644
index 0000000..6df6ee8
--- /dev/null
+++ b/quickserver/version.txt
@@ -0,0 +1,393 @@
++++++++++++++++++++++++++++++++++++
+| Version History for QuickServer |
++++++++++++++++++++++++++++++++++++
+
+Current Version: 2.1.0
+
+version 2.1.0 [12-Aug-2017]
+----------------------------
++ Added support for uptime in Host (QuickServer Client)
++ Supports null/no banner when server starts
+# uptime formatting shortened 
+# Fixed load pattern logic RandomLoadPattern, RoundRobinLoadPattern 
+  (was using index when client key was set)
++ added getHighestActiveCount() method to Object Pools
++ Added getHighestActiveClientCount method to QuickServer object
++ Added support for setting Security provider for SSLContext
+# Defaulted SSL to TLS
+! Bug fix for ThreadPool not reducing to max ideal 
+  (stay in wait state n increase over time)
+! Bug fix for Client (HashedLoadPattern)
+- Disabled non blocking mode (no more supported)
+
+version 2.0.0 [15-Feb-2014]
+----------------------------
++ Added new commands in QSAdmin 
+	kill-client-with <target> <search term>
+	kill-clients-all <target>
++ Added readBytes with length support for BlockingClient
++ Added PID, Lib Version, Uptime in info server
++ Added QuickServerDebugHelper class - allows info server and pool dump to log file
+! Bug fix in BlockingClientPool (high tps noop failure fix)
+! Bug fix in SocketMonitor
+! Bug fix in readCRLFLine for BlockingClient
+! QSAdmin New commands introduced like JVM jmap & jstack
+
+
+version 2.0.0 RC1 [20-Oct-2012]
+----------------------------
++ Added BroadcastServer example.
++ Added org.quickserver.net.client
++ Added org.quickserver.net.client.loaddistribution.
++ Added org.quickserver.net.client.monitoring
++ Added org.quickserver.util.pool.thread.app a thread pool for use by application logic
++ Added more param in advanced-settings
+    performance-preferences-connection-time
+    performance-preferences-latency
+    performance-preferences-bandwidth
+
+    client-socket-tcp-no-delay
+    client-socket-traffic-class
+
+    client-socket-receive-buffer-size
+    client-socket-send-buffer-size
++ Added Generic Client Socket Pool
++ Added TotalReadBytes, TotalWrittenBytes to client handler
+  (not accurate in STRING mode - assumes \r\n in request)
+  (in case of object mode just increments by no of objects and not bytes)
++ Added support for raw Communication Logging (in case of binary mode)
+   (any data above 100 bytes would be truncated when logged)
++ Added BlockingUDBClient and UDP Monitoring support
++ Added AsyncHandler for JDK logging
+# sendClientXXX methods improved to make synchronized writes.
+# Improved TextFile read methods.
+# Improved readInputStream() method in BasicClientHandler to check for 
+  available data and EOF in read() method call.
+
+
+version 1.4.7 [01-Mar-2006]
+--------------------------------
++ Implemented support NIO writes in sendClientXXX methods of ClientHandler.
++ Added initServer() that throws App Exception if it fails.
++ Added getServiceError() to Service interface.
++ Added load() method to QuickServer.
+! Removed synchronized from processGotDataInBuffers in NonBlockingClientHandler.
+# Improved ByteBufferInputStream for readLine
++ Added availableOnlyInByteBuffer() in NonBlockingClientHandler.
+# Improved isLineReadyForStringBuffer() in NonBlockingClientHandler.
+# Improved isClientEventNext() in BasicClientHandler.
++ Added check for NewLine miss in NonBlockingClientHandler.
+# Added flush() in closeConnection() in BlockingClientHandler.
+# Improved setClassLoader() of QuickServer.
+! Added check for bootstrap classloader (null) in getClass() method of QuickServer
+# Closed Keystore stream when no longer needed.
+# shutdown command in QSAdminServer improved to close shell, this will
+  make server auto exit the jvm when the last client disconnects. 
+# GhostSocketReaper now will close pools after last client disconnects 
+  after server is stopped.
+! Added checks for null returned in ServerSocketChannel accept method.
+! Fixed run NonBlockingClientHandler code to prevent more than one threads 
+  from processing selector when server is re-started. 
+# Modified registerChannel to add to a list and then process when
+  selector becomes free.
+! Fixed synchronization problem in ClientThread pool.returnObject() call.
++ MaxThreadAccessCount in NonBlockingClientHandler is now configurable. 
++ Wakeup call on selector after RegisterForWrite and RegisterForRead in 
+  NonBlockingClientHandler is now configurable. 
+# Improved validateObject method in ClientHandlerObjectFactory to check 
+  if object was created from the same pool
++ Access to clientEvents method is now synchronized.
++ Added flush call after ObjectOutputStream is created in BasicClientHandler.
+# Improved kill/exit command in QSAdmin to take a param (exit value)
+
+
+version 1.4.6 [15-Oct-2005]
+------------------
+# Improved ThreadPool for performance.
+# Improved BasicClientHandler.
+# Improved XmlAdderLoadTest.
++ Added byte-buffer-pool-info command - QsAdmin
+! Fixed initSize default value setting
+! Fixed synchronized blocks on clientEvents and moved clientConnectedTime code to run()
+# Improved Architecture.pdf
+
+
+version 1.4.6 beta [17-Sep-2005]
+------------------
++ Added initService(QuickServerConfig)
++ Added maxThreadsForNioWrite() for Thread Pools
++ Added ClientEventHandler to xml, also provided default implementation.
++ Added new QsAdmin commands 'client-handler-pool-dump' 
++ Added isOpen() method to ClientHandler
++ Added ability to set default DataMode.
++ Added getBlockingMode() to QuickServer
++ Added Unix shell scripts
++ Added ClientExtendedEventHandler
++ Added facility to configure initial pool size.
++ Added method to BasicServerConfig so that business logic class can
+  be set and checked at compile time.
++ Introducing new ClientAuthenticationHandler (replacing Authenticator) 
++ Added new org.quickserver.util.Assertion class
++ Added new org.quickserver.util.logging.SimpleJDKLoggingHook class
+# Improved logging, ClientHandler
+# Refactored ClientHandler
+# Moved QSAdminGUI into a separate jar
+# Made most beans Serializable
+! Fixed ClientEvent loss bug caused when more than one event gets picked at 
+  the same time.
+! Fixed charset bug in sendClientMsg() and sendClientBytes() methods when 
+  length of byte[] representation is not equal to string representation
+- Removed deprecated setServerAuthenticator(), getServerAuthenticator in QuickServer
+- ServerAuthenticator and "server-authenticator" tag have been removed.
+- Old xml format of v1.2 no longer supported.
+- MaxClientHandler no longer needed, so removed.
+- ObjectCleaner, ObjectCleanup no longer used, so removed.
++ New XML Tags: advanced-settings/max-threads-for-nio-write,
+  object-pool/init-size, object-pool/thread-object-pool/init-size,
+  object-pool/client-handler-object-pool/init-size,
+  object-pool/byte-buffer-object-pool/init-size,
+  object-pool/client-data-object-pool/init-size,
+  client-event-handler, qsadmin-server/client-event-handler
+  default-data-mode/data-type-in,default-data-mode/data-type-out,
+  client-extended-event-handler, qsadmin-server/client-extended-event-handler
+  client-authentication-handler, qsadmin-server/client-authentication-handler
+
+
+version 1.4.5 [10-Jul-2005]
+------------------
+# Made ClientIdentifier implementation plug able.
++ Added ClientIdentifier implementations SyncClientIdentifier, OptimisticClientIdentifier
++ Added PoolManager, QSObjectPoolMaker interface to create pools and is plug able.
++ Added GUI Chat Client for ChatServer example.
++ Added 'FullThreadDump' command at QsAdminShell
+# Made timeout setting to milliseconds, default timeout is now 1 minute.
+# Improved ChatServer, FileServ examples.
+# Improved QSAdminShell, thread dumps can now be done with shell enabled.
+# Improved GhostSocketReaper.
+! Fixed charset issue in readBytes() method of ClientHandler
+! Fixed bug in QuickServer that prevented GhostSocketReaper from loading 
+  when no SerevrHooks are defined.
+! Fixed ByteBuffer object leak in ByteBufferOutputStream
++ New XML Tags: advanced-settings/client-identifier, object-pool/pool-manager,
+  advanced-settings/qsobject-pool-maker
+
+
+version 1.4.5 beta [30-May-2005]
+------------------
++ Added support for NIO (non-blocking mode) for normal sockets: Server Mode
++ QuickServer now uses java assertion
++ Added new QsAdmin commands to find pool information.
++ Added new QsAdmin command 'systeminfo', 'start console' and 'stop console'.
++ Backlog and Socket linger for server is now configurable.
++ Added GUI prompt for sensitive application parameter. 
++ Added -fullXML2File to -load switch.
++ Added new interface ClientEventHandler, ClientWriteHandler
+# Improved object pool handling and creation.
+# Improved QSAdminGUI to handle error in custom authenticators
+# Communication logging is set to false by default now
+# Improved communication logging for BINARY mode and general logging.
+# Improved org.quickserver.util.logging classes implementation.
+# Improved EchoWebServer example
+# ClientHanlder.isConected() renamed to isConnected()
++ New XML Tags: Server Mode, advanced-settings, application-configuration/prompt-type,
+  object-pool/thread-object-pool, object-pool/client-handler-object-pool, 
+  object-pool/byte-buffer-object-pool, object-pool/client-data-object-pool
+
+
+version 1.4.1 [22 Nov 2004]
+------------------
+# Improved ClientHandler, QuickServer, ClientThread classes.
+# Improved BasicObjectPool class
+# Improved QSAdminShell to detect forced exits
+# Improved FTPServer, EchoServer examples.
+! Fixed bug in QSAdminShell bug did not allow prompt changing
+! Fixed bugs in ClientPool (thread pool) that prevented excess threads from 
+  freeing up.
+! Fixed bug in prompt of sensitive <property-value>
+! Fixed bug in <communication-logging> for QSAdminServer from XML
+
+
+version 1.4.0 [01 Oct 2004]
+------------------
++ Added SecureManagerLoader to manage Secure Mode.
++ Added findAllClientByKey to QuickServer object.
++ Added ConnectionLostException class.
+# Improved Secure configuration 
+   a) To prompt the user for store/key password if not specified.
+   b) Auto pick security provider (if not given).
+   c) To handle non file based keystores (pass NONE for <store-file>) 
+      like from HSM or LDAP.
+   d) Ability to override the type and provider of SecureStore in TrustStoreInfo. 
++ Add ability to read sensitive <application-configuration> <property-value> 
+  from console.
+# Improved ChatServer, XmlAdder examples.
+! Many bug fixes as per reports on Developers Forum 
+
+
+version 1.4.0 beta [27 Aug 2004]
+------------------
++ Added Secure Mode: SSL, TLS
++ Added method to negotiate secure connection over normal tcp 
+  connection: ClientHandler.makeSecure()
++ Added method in ClientHandler to find if client is in secure mode.
++ Added Init ServerHook : org.quickserver.net.InitServerHook
++ Added BINARY mode of communication: ClientBinaryHandler
++ Added BINARY reading and writing methods to QuickAuthenticator
++ Added QSAdminAPI api for communicating to QsAdminServer.
++ New example: XmlAdder - A simple xml server that adds 2 integers.
++ New example: PipeServer - A simple redirection server.
+# Improved ClientHandler.
+# Updated jakarta commons jars.
+# Improved Architecture.pdf
+! Fixed bug in QSAdminServer loading of Plugin class from 
+  <application-jar-path>.
+! Fixed bug in AccessConstraintConfig for QsAdminServer
+! Fixed bug in setting of max connection from xml file for QSAdminServer
+- Removed the old package structure form distribution com.ddost
+
+
+version 1.3.3 [27 Jun 2004]
+----------------
++ Added IP Filter for clients <access-constraint><ip-filter>..
++ Added <security-manager> node to specify SecurityManager for JVM
++ Loading/Reloading application jar from xml. Add 
+  <application-jar-path> node to specify location of jars needed by 
+  application. This location can be either absolute or relative (to config
+  file). The jars are reloaded when server is restarted, updating the class 
+  from the changed jars.
++ Added startup, shutdown process hooks to QuickServer : 
+  org.quickserver.net.ServerHook
++ QuickServer is now cloneable
++ Added reaper thread : GhostSocketReaper
++ Added new method to ClientHandler to find the time when client last sent 
+  data to ClientHandler.
+! Fixed bug in communication logging turn off implementation in ClientHandler.
+! Fixed bug in BasicObjectPool return object method. 
+
+
+version 1.3.2 [20 May 2004]
+----------------
++ Added plugin ability to QSAdminGUI : PluginPanel
++ Added "Server Statistics View" Plugin to QSAdminGUI
++ Added QSAdmin Shell - A command shell
++ Added <application-configuration> node xml configuration file to store 
+  data needed by the application.
++ Added BYTE reading and writing methods to QuickAuthenticator
++ Added ability to turn off FINE logging of all data sent in/out of server.
+  Note: This will not log any incoming data when client is being authenticated.
++ Added two new logging formatter - SimpleTextFormatter, SimpleConsoleFormatter
+# Improved login and command version handling in QSAdminGUI
+! Fixed "-load" option to load QSAdmin from XML
+! Fixed ClientHandler detection of lost connections when in BYTE mode.
+
+
+version 1.3.1 [06 Mar 2004]
+----------------
++ Added BYTE mode of communication.
++ Added a new interface ClientIdentifiable and methods to identify and search a 
+  client.
++ Added new method to ClientHandler to find the time when Client was assigned
+  to ClientHandler.
++ New example: ChatServer - Send and receive text b/w connected clients
+# Improved logging in ClientHandler to log all outgoing and incoming 
+  communications at FINE level.
+# Improved error detection for Authenticator implementations.
+! Fixed the ClientHandler Thread cleanup for detection of lost connection 
+  and connection closing condition. 
+! Fixed setConsoleLoggingLevel() method from setting non console handlers level.
+
+
+version 1.3.0 [27 Jan 2004]
+----------------
++ www.quickserver.org was registered.
++ All classes ported to new package org.quickserver from com.ddost
++ Released Developer Guide v 0.2 (Pre-Release)
+# Improved Architecture.pdf.
+
+
+version 1.3.0 beta [01 Jan 2004]
+----------------
++ Object Pool {Includes a thread pool} added for handling clients.
++ Added PoolableObject interface to pool any class used by QuickServer
+  like ClientData.
++ Added QSAdmin GUI (XML Based)
++ New authentication class added QuickAuthenticator and Authenticator.
++ New commands added to QSAdmin CommandHander
++ XML Based JDBC Mapping [org.quickserver.sql.DBPoolUtil]
+# QuickServer optimised for speed.
+# Authentication is now can have single or multiple instance.
+# XML Configuration of QuickServer format is now changed to a easy one.
+  Old XML configuration file is automatically converted to new format.
+! Stack overflow bug when bind ip address was set to QSAdmin fixed.
+
+
+
+version 1.2.0 [24 Sep 2003]
+----------------
++ Released Developer Guide v 0.1 (Pre-Release)
++ XML DTD added for configuration file.
++ New ReadMe added for Examples
+# Improved Architecture.pdf.
+# Location of main jar changed from build\lib to dist folder.
+# Improved Ant build file.
+! setMaxAuthTryMag() method changed to setMaxAuthTryMsg() 
+
+
+version 1.2.0 beta [20 Aug 2003]
+----------------
++ JDK Logging support added to QuickServer.
++ Support for sending and receive java objects in QuickServer.
++ Support for xml configuration.
++ QuickServer now supports Service Configurator Pattern.
++ New example: DateServer - Send and receive java objects.
+# FtpServer example modified to use txt logging.
+# EchoServer example modified to use xml configuration and logging.
+# EchoWebServer example modified to use txt logging and xml configuration.
+! Multiple ObjectCleaner bug when QuickServer is restarted rectified.
+! Cleanup time setting bug in ObjectCleaner rectified. 
+# ObjectCleaner thread is a daemon thread now.
++ Pluggable command handler for QSAdminServer - CommandPlugin
+# FTPServer example: Custom command added to QSAdminServer for 
+  remote changing of ftp root - using CommandPlugin.
+
+
+version 1.1.0 [04 Aug 2003]
+----------------
++ JUnit tests added to QuickServer
++ New example : FTPServer - A basic ftp server.
+
+
+version 1.1.0 beta [14 Jul 2003]
+----------------
++ QuickServer.setMaxClients() added.
++ QuickServer.setBindAddr() added.
++ Many new useful methods added to QuickServer.
++ Admin port & protocol added to QuickServer [org.quickserver.net.qsadmin]
+! ClientHandler.getClientCount(), ClientHandler.getObjectCount() bug 
+  when more than one QuickServer objects created in same JVM rectified.
+# EchoServer example modified to use QSAdminServer.
++ Few new useful methods added to ClientHandler.
++ New example: CmdServer - A remote command shell
+
+
+version 1.0.0 [10 Jul 2003]
+----------------
+# Improved QuickServer.startServer() to detect failure.
+# Improved Main Thread of QuickServer for performance.
+
+
+version 1.0 beta [07 Jul 2003]
+----------------
++ First Release
+
+
+Legends
+-------
++  Feature Addition
+-  Feature Removal, Deprecated
+!  Bug Fix
+#  Feature/Performance Enhancement
+
+
+Copyright (C) 2003-2006 QuickServer.org
+http://www.quickserver.org