/*
 * EasySocket SocketServer.java
 *
 * Copyright (c) 2014, Qingfeng Lee
 * PROJECT DESCRIPTION
 * 
 * See LICENSE file for more information
 */
package easysocket.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import easysocket.session.AioTcpSession;
import easysocket.utils.PrintStackTrace;

public class SocketServer {

	public static interface ClientConnectedEventHandler {
		public void OnConnect(AioTcpSession session);
	}

	private CompletionHandler<AsynchronousSocketChannel, Void> acceptCompletionHanlder = new CompletionHandler<AsynchronousSocketChannel, Void>() {

		@Override
		public void completed(AsynchronousSocketChannel channel, Void attachment) {
			SocketServer.this.pendingAccept();

			AioTcpSession session = new AioTcpSession(channel);
			session.pendingRead();
			int sessionId = session.getSessionId();
			SESSION_POOL.put(sessionId, session);

			if (connectedEventHandler != null) {
				connectedEventHandler.OnConnect(session);
			}
		}

		@Override
		public void failed(Throwable exc, Void attachment) {
			PrintStackTrace.print(logger, exc);
		}
	};

	static Logger logger = LoggerFactory.getLogger(SocketServer.class);
	private final Map<Integer, AioTcpSession> SESSION_POOL = new ConcurrentHashMap<>();

	private AsynchronousServerSocketChannel server;
	private final ClientConnectedEventHandler connectedEventHandler;
	private final int port;

	public SocketServer(int port,
			ClientConnectedEventHandler connectedEventHandler) {
		this.port = port;
		this.connectedEventHandler = connectedEventHandler;
	}

	public void start() throws IOException {
		int initialSize = Runtime.getRuntime().availableProcessors();
		AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup
				.withCachedThreadPool(Executors.newCachedThreadPool(),
						initialSize);
		AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel
				.open(channelGroup);
		server.bind(new InetSocketAddress(port));
		this.server = server;
		this.pendingAccept();
		logger.debug("server started at port " + this.port);
	}

	private void pendingAccept() {
		if (this.server == null) {
			throw new NullPointerException(
					"server is null, invoke start before pendingAccept");
		}

		this.server.accept(null, this.acceptCompletionHanlder);
	}

	public AioTcpSession findClient(int sessionId) {
		return this.SESSION_POOL.get(sessionId);
	}

	public void stop() throws IOException {
		if (this.server == null) {
			throw new IllegalStateException("server never opend");
		}
		this.server.close();
	}
}

@@ -1122,16 +1122,45 @@
 ession =
+ null;%0A%09%09%09try %7B%0A%09%09%09%09session =
  new Aio
@@ -1180,16 +1180,17 @@
 annel);%0A
+%09
 %09%09%09sessi
@@ -1210,16 +1210,17 @@
 d();%0A%09%09%09
+%09
 int sess
@@ -1254,16 +1254,17 @@
 d();%0A%09%09%09
+%09
 SESSION_
@@ -1294,16 +1294,17 @@
 sion);%0A%0A
+%09
 %09%09%09if (c
@@ -1339,16 +1339,17 @@
 ) %7B%0A%09%09%09%09
+%09
 connecte
@@ -1385,17 +1385,78 @@
 on);%0A%09%09%09
-%7D
+%09%7D%0A%09%09%09%7D catch (IOException e) %7B%0A%09%09%09%09e.printStackTrace();%0A%09%09%09%7D%0A
 %0A%09%09%7D%0A%0A%09%09

handle IOException in SocketServer.java