package com.eactive.eai.adapter.socket2.protocol.http.servlet;

import com.eactive.eai.adapter.socket2.common.Env;
import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
import com.eactive.eai.adapter.socket2.common.SimpleFuture;
import com.eactive.eai.adapter.socket2.common.TimeUtil;
import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
import com.eactive.eai.common.util.Logger;
import org.apache.mina.common.IoSession;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;

public class AdapterInternalServlet extends HttpServlet {
	static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
	static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");

	protected void doService(HttpRequest request, HttpResponse response) throws Exception {
		String command = request.getContext();
		if (command.lastIndexOf('/') == -1) {
			command = "";
		} else {
			command = command.substring(command.indexOf('/') + 1);
		}

		String result = "";

		try {
			if (command == null || "".equals(command) || "show".equals(command)) {
				result = show(request.getParameter("adapter"));
			} else if (command.startsWith("traceLevel")) {
				result = traceLevel(request.getParameter("adapter"), Integer.parseInt(request.getParameter("level")));
			} else if (command.startsWith("clear")) {
				result = clear(request.getParameter("adapter"));
			} else if (command.startsWith("start")) {
				String adapterName = request.getParameter("adapter");
				logger.fatal("HttpAdapter | " + adapterName + " | start - " + request.getSession());
				result = start(adapterName);
			} else if (command.startsWith("stopforcely")) {
				String adapterName = request.getParameter("adapter");
				logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
				result = stop(adapterName, true);
			} else if (command.startsWith("stop")) {
				String adapterName = request.getParameter("adapter");
				logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
				result = stop(adapterName, false);
			} else if (command.startsWith("error")) {
				result = error(request.getParameter("adapter"));
			} else if (command.startsWith("sendRecv")) {
				result = sendRecv(request.getParameter("adapter"));
			} else if (command.startsWith("removeSession")) {
				result = removeSession(request.getParameter("adapter"), request.getParameter("localPort"),
						request.getParameter("remotePort"));
			} else if (command.startsWith("sessionValidate")) {
				result = sessionValidate(request.getParameter("adapter"));
			} else {
				response.setResponseCode(404);
				return;
			}
		} catch (Throwable e) {
			result = "<pre>" + ExceptionStackTrace.dump(e) + "</pre>";
		}

		response.setContentType("text/html;charset=utf-8;");
		response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
		response.appendBody(result);
	}

	private String show(String adapterName) throws Exception {
		StringBuffer sb = new StringBuffer();
		ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
		sb.append(adapterName);

		if (adapter == null) {
			sb.append(" <b>Not found adapter (" + adapterName + ")</b>");
			return sb.toString();
		}
		/**
		 * status
		 */
		if ("STARTED".equals(adapter.getState().name())) {
			sb.append(" (" + adapter.getState().name() + ")");
		} else {
			sb.append(" <b>(" + adapter.getState().name() + ")</b>");
		}

		sb.append("  uptime:" + TimeUtil.formatDate(adapter.getUptime().getTime()));
		sb.append(", pool:" + adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
		sb.append(", recv:" + adapter.getMessageRecv());
		sb.append(", send:" + adapter.getMessageSend());
		if (adapter.getRecentErrorCount() > 0) {
			sb.append(", ");
			sb.append("<b>");
			sb.append("error:" + adapter.getRecentErrorCount());
			sb.append("</b>");
		} else {
			sb.append(", error:" + adapter.getRecentErrorCount());
		}

		// sb.append(", (<a href='/adapter/clear?adapter=" + adapterName +
		// "'>clear</a>)");

		// sb.append(" (<a href='/adapter/start?adapter=" + adapterName +
		// "'>start</a>");
		// sb.append("|<a href='/adapter/stop?adapter=" + adapterName + "'>stop</a>)");

		if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
			sb.append("\n    " + adapter.getContext().getDescription() + "\n");
		}

		sb.append("\n\n");

		/**
		 * common info
		 */
		sb.append(String.format("%4s %-30s : %s\n", "", "host.name", adapter.getContext().getHostName()));
		sb.append(String.format("%4s %-30s : %s\n", "", "port.number", adapter.getContext().getPortNumber()));
		sb.append(String.format("%4s %-30s : %s\n", "", "local.host.name", adapter.getContext().getLocalHostName()));
		sb.append(
				String.format("%4s %-30s : %s\n", "", "local.port.number", adapter.getContext().getLocalPortNumber()));
		sb.append("\n");
		sb.append(String.format("%4s %-30s : %s\n", "", "protocol", adapter.getContext().getProtocol()));
		sb.append(String.format("%4s %-30s : %s\n", "", "bound.usage", adapter.getContext().getBoundUsage()));
		sb.append(String.format("%4s %-30s : %s\n", "", "socket.type", adapter.getContext().getSocketType()));
		sb.append(String.format("%4s %-30s : %s\n", "", "response.type", adapter.getContext().getResponseType()));
		sb.append(String.format("%4s %-30s : %s\n", "", "ack.support", adapter.getContext().getAckSupport()));
		sb.append("\n");
		sb.append(String.format("%4s %-30s : %s\n", "", "permanent", adapter.getContext().getPermanent()));
		sb.append(String.format("%4s %-30s : %s\n", "", "blocking(NIO, BIO)", adapter.getContext().getBlocking()));
		sb.append(String.format("%4s %-30s : %s (sec)\n", "", "timeout", adapter.getContext().getTimeout()));
		sb.append(String.format("%4s %-30s : %s (sec)\n", "", "idle.timeout", adapter.getContext().getIdleTimeout()));
		sb.append(String.format("%4s %-30s : %s\n", "", "socket.reuse", adapter.getContext().getSocketReuse()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "business.work.class.code",
				adapter.getContext().getBwkClsCd()));
		sb.append(String.format("%4s %-30s : %s\n", "", "max.connection",
				(adapter.getContext().getCloseExistingConnection() ? "-" : "")
						+ adapter.getContext().getMaxConnection()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "connection.limit.per.ip",
				adapter.getContext().getConnLimitPerIp()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "max.thread", adapter.getContext().getMaxThread()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "validation.rule", adapter.getContext().getValidationRule()));
		sb.append(
				String.format("%4s %-30s : %s\n\n", "", "datacontrol.rule", adapter.getContext().getDataControlRule()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "acl.list", adapter.getContext().getAclList()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "block.ip.list", adapter.getContext().getBlockIpList()));
		sb.append(String.format("%4s %-30s : %s\n\n", "", "l4.skip.ip.list", adapter.getContext().getL4SkipIpList()));

		sb.append(
				String.format("%4s %-30s : %s\n\n", "", "is.single.session", adapter.getContext().getSingleSession()));

		int traceLevel = adapter.getContext().getTraceLevel();
		sb.append(String.format("%4s %-30s : %s \n", "", "trace.level", adapter.getContext().getTraceLevel()));
//      switch(traceLevel) {
//      case 0:
//         sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
//               "<b>0(DEFAULT)</b>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=1'>1</a>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=2'>2</a>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=3'>3</a>"));
//         break;
//      case 1:
//         sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=0'>0</a>",
//               "<b>1(INFO)</b>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=2'>2</a>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=3'>3</a>"));
//         break;
//      case 2:
//         sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=0'>0</a>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=1'>1</a>",
//               "<b>2(DEBUG)</b>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=3'>3</a>"));
//         break;
//      case 3:
//         sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=0'>0</a>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=1'>1</a>",
//               "<a href='/adapter/traceLevel?adapter=" + adapterName + "&level=2'>2</a>",
//               "<b>3(TRACE)</b>"));
//         break;
//      }

		if (adapter.getContext().isPollingUse()) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "polling.use", adapter.getContext().getPollingUse()));
			if ("".equals(adapter.getContext().getPollingRole().trim())) {
				if (adapter.getContext().isPollingSender())
					sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "SENDER (client)"));
				else
					sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "RECEIVER (server)"));
			} else {
				sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", adapter.getContext().getPollingRole()));
			}
			sb.append(String.format("%4s %-30s : %s\n", "", "polling.oneway", adapter.getContext().getPollingOneway()));

			if (adapter.getContext().isPollingReceiver()) {
				sb.append("<font color='#B0B0B0'><i>");
			}
			sb.append(
					String.format("%4s %-30s : %s\n", "", "polling.timeout", adapter.getContext().getPollingTimeout()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "polling.request", adapter.getContext().getPollingRequest()));
			sb.append(String.format("%4s %-30s : %s\n", "", "polling.response.pattern",
					adapter.getContext().getPollingResponsePattern()));
			if (adapter.getContext().isPollingReceiver()) {
				sb.append("</i></font>");
			}

			if (adapter.getContext().isPollingSender()) {
				sb.append("<font color='#B0B0B0'><i>");
			}
			sb.append(String.format("%4s %-30s : %s\n", "", "polling.request.pattern",
					adapter.getContext().getPollingRequestPattern()));
			sb.append(String.format("%4s %-30s : %s\n", "", "polling.replacement",
					adapter.getContext().getPollingReplacement()));
			if (adapter.getContext().isPollingSender()) {
				sb.append("</i></font>");
			}

			sb.append("\n");
		}

		// KSH
		if (adapter.getContext().isInitMsgUse()) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.use", adapter.getContext().getInitMsgUse()));
			if ("".equals(adapter.getContext().getInitMsgRole().trim())) {
				if (adapter.getContext().isInitMsgSender())
					sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "SENDER (client)"));
				else
					sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "RECEIVER (server)"));
			} else {
				sb.append(
						String.format("%4s %-30s : %s\n", "", "init.msg.role", adapter.getContext().getInitMsgRole()));
			}

			if (adapter.getContext().isInitMsgReceiver()) {
				sb.append("<font color='#B0B0B0'><i>");
			}
			sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request",
					adapter.getContext().getInitMsgRequest()));
			sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.response.pattern",
					adapter.getContext().getInitMsgResponsePattern()));
			if (adapter.getContext().isInitMsgReceiver()) {
				sb.append("</i></font>");
			}

			if (adapter.getContext().isInitMsgSender()) {
				sb.append("<font color='#B0B0B0'><i>");
			}
			sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request.pattern",
					adapter.getContext().getInitMsgRequestPattern()));
			sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.replacement",
					adapter.getContext().getInitMsgReplacement()));
			if (adapter.getContext().isInitMsgSender()) {
				sb.append("</i></font>");
			}

			sb.append("\n");
		}

		/**
		 * ll info (fixed length header)
		 */
		if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
				|| "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
				|| "EGSEED".equals(adapter.getContext().getProtocol())
				|| "TCSEED".equals(adapter.getContext().getProtocol()) // 20101213 JGY
				|| "ENVELOP".equals(adapter.getContext().getProtocol())
				|| "XECURE".equals(adapter.getContext().getProtocol())
				|| "XECURE2".equals(adapter.getContext().getProtocol())
				|| "XECURE3".equals(adapter.getContext().getProtocol())
				|| "XC3EPB".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include",
					adapter.getContext().getLlFieldInclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude",
					adapter.getContext().getLlOffsetExclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
		}

		/**
		 * ll info (variable length payload) 20130719 KSH
		 */
		if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include",
					adapter.getContext().getLlFieldInclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude",
					adapter.getContext().getLlOffsetExclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "send.header.length",
					adapter.getContext().getSendHeaderLength()));
			sb.append(String.format("%4s %-30s : %s\n", "", "recv.header.length",
					adapter.getContext().getRecvHeaderLength()));
		}

		/**
		 * ll info (fixed length payload)
		 */
		if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
				|| "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
				|| "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "send.payload.length",
					adapter.getContext().getSendPayloadLength()));
			sb.append(String.format("%4s %-30s : %s\n", "", "recv.payload.length",
					adapter.getContext().getRecvPayloadLength()));
		}

		/**
		 * xecure
		 */
		if ("XECURE".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure.config.path",
					adapter.getContext().getXecureConfigPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure.remote.cert",
					adapter.getContext().getXecureRemoteCert()));
		}

		/**
		 * xecure2
		 */
		if ("XECURE2".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.config.path",
					adapter.getContext().getXecure2ConfigPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.sm.ip", adapter.getContext().getXecure2SmIp()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "xecure2.sm.port", adapter.getContext().getXecure2SmPort()));
			// use CISCO interface only
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
		}

		/**
		 * xecure3 20100901 JGY
		 */
		if ("XECURE3".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.store",
					adapter.getContext().getXecure3CertStore()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.server.cert",
					adapter.getContext().getXecure3ServerCert()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.client.cert",
					adapter.getContext().getXecure3ClientCert()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.key",
					adapter.getContext().getXecure3CertKey()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.password",
					adapter.getContext().getXecure3CertPassword()));
		}

		/**
		 * xc3epb 20210929
		 */
		if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(
					String.format("%4s %-30s : %s\n", "", "xc3epb.password", adapter.getContext().getXc3epbPassword()));
			sb.append(String.format("%4s %-30s : %s\n", "", "xc3epb.config.path",
					adapter.getContext().getXc3epbConfigPath()));
		}

		/**
		 * inisafe inisafe_payload 20100515 JGY
		 */
		if ("INISAFE".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
					adapter.getContext().getInisafeConfigPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups",
					adapter.getContext().getInisafeRelatedAdapterGroups()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message",
					adapter.getContext().getInisafeStartMessage()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message",
					adapter.getContext().getInisafeStopMessage()));
		} else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
					adapter.getContext().getInisafeConfigPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups",
					adapter.getContext().getInisafeRelatedAdapterGroups()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message",
					adapter.getContext().getInisafeStartMessage()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message",
					adapter.getContext().getInisafeStopMessage()));
		} else if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
					adapter.getContext().getInisafeConfigPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups",
					adapter.getContext().getInisafeRelatedAdapterGroups()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message",
					adapter.getContext().getInisafeStartMessage()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message",
					adapter.getContext().getInisafeStopMessage()));
		} else if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
					adapter.getContext().getInisafeConfigPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.id.password",
					adapter.getContext().getInisafeIdPassword()));
		}

		/**
		 * ENVELOP : JGY 20100423
		 */
		if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signcert.path",
					adapter.getContext().getEnvelopSigncertPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signkey.path",
					adapter.getContext().getEnvelopSignkeyPath()));
			sb.append(String.format("%4s %-30s : %s\n", "", "envelop.password",
					adapter.getContext().getEnvelopPassword()));
		}

		/**
		 * TCSEED : JGY 20101213
		 */
		if ("TCSEED".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "tcseed.key.store",
					adapter.getContext().getTcseedKeyStore()));
		}

		if ("DYNAMIC_OFFSET".equals(adapter.getContext().getProtocol())) {
			sb.append("\n");
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
			sb.append(
					String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include",
					adapter.getContext().getLlFieldInclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude",
					adapter.getContext().getLlOffsetExclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
			sb.append(String.format("%4s %-30s : %s\n", "", "dynamic.offset.pattern",
					adapter.getContext().getDynamicOffsetPattern()));
			sb.append(String.format("%4s %-30s : %s\n", "", "data.add.rule", adapter.getContext().getDataAddRule()));
			sb.append(String.format("%4s %-30s : %s\n", "", "data.remove.rule",
					adapter.getContext().getDataRemoveRule()));
		}

		/**
		 * script
		 */
		if (!"".equals(adapter.getContext().getScript().trim())) {
			sb.append("\n");
			// sb.append(String.format("%4s %-30s : %s\n", "", "script", "<a href='/file/" +
			// adapter.getContext().getScript() + "'>" + adapter.getContext().getScript() +
			// "</a>"));
		}

		sb.append("</font>\n");

		/**
		 * session list
		 */
		sb.append("\n<b>session pool (remaining)</b>\n");
		sb.append("<font color='gray'>");
		for (Iterator iii = adapter.getSessionPool().iterator(); iii.hasNext();) {
			IoSession session = (IoSession) iii.next();
			sb.append("     ");
			if (!session.isConnected())
				sb.append("●");
			else if (session.isClosing())
				sb.append("◐");
			else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
				sb.append("⊙");
			else
				sb.append("○");
			sb.append(" Session :");
			;
			if (session.isClosing())
				sb.append(" [CLOSING]");
			if (!session.isConnected())
				sb.append(" [NOT CONNECTED]");
			sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-")
					+ session.getRemoteAddress());
			sb.append(", recv:" + session.getReadMessages());
			sb.append("(" + session.getReadBytes() + ")");
			sb.append(", send:" + session.getWrittenMessages());
			sb.append("(" + session.getWrittenBytes() + ")");
			sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
			sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
		}
		sb.append("</font>");

		if (adapter.getSessionPool().checkedOut() > 0) {
			sb.append("<b>session pool (checked out)</b>\n");
		}

		sb.append("<font color='red'>");
		for (Iterator iii = adapter.getSessionPool().checkedOutIterator(); iii.hasNext();) {
			IoSession session = (IoSession) iii.next();
			sb.append("     ");
			if (!session.isConnected())
				sb.append("●");
			else if (session.isClosing())
				sb.append("◐");
			else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
				sb.append("⊙");
			else
				sb.append("○");
			sb.append(" Session :");
			;
			// sb.append(" [" + session.getTrafficMask() + "]");
			if (session.isClosing())
				sb.append(" [CLOSING]");
			if (!session.isConnected())
				sb.append(" [NOT CONNECTED]");
			sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-")
					+ session.getRemoteAddress());
			sb.append(", recv:" + session.getReadMessages());
			sb.append("(" + session.getReadBytes() + ")");
			sb.append(", send:" + session.getWrittenMessages());
			sb.append("(" + session.getWrittenBytes() + ")");
			sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
			sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
		}
		sb.append("</font>");
		sb.append("\n");

		/**
		 * netstat
		 */
		try {
			String[] cmd;
			if (Env.isWindows()) {
				cmd = new String[] { "cmd.exe", "/c", "netstat -an | findstr " + adapter.getContext().getPortNumber() };
			} else {
				cmd = new String[] { "sh", "-c",
						"netstat -an | grep -E 'tcp|udp' | grep " + adapter.getContext().getPortNumber() };
			}
			Runtime runtime = Runtime.getRuntime();
			Process process = runtime.exec(cmd);

			StreamForNetstat netstat1 = new StreamForNetstat(process.getInputStream(), adapter);
			StreamForNetstat netstat2 = new StreamForNetstat(process.getErrorStream(), adapter);
			netstat1.start();
			netstat2.start();
			while (true) {
				if (!netstat1.isAlive() && !netstat2.isAlive()) { // 두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
					process.waitFor();
					sb.append(netstat1.getData());
					break;
				}
			}
		} catch (Exception e) {
			logger.error("Error", e);
		}

		/**
		 * lsof && ps
		 */
		if (!Env.isWindows()) {
			try {
				String[] cmd = new String[] { "sh", "-c",
						"lsof -iTCP"
								+ ("*".equals(adapter.getContext().getHostName()) ? ""
										: "@" + adapter.getContext().getHostName())
								+ ":" + adapter.getContext().getPortNumber() +
								// " | grep " + adapter.getContext().getHostName() +
								" | grep -E '\\([A-Z0-9_]+\\)$'" };
				Runtime runtime = Runtime.getRuntime();
				Process process = runtime.exec(cmd);

				StreamForLsof lsof1 = new StreamForLsof(process.getInputStream());
				StreamForLsof lsof2 = new StreamForLsof(process.getErrorStream());
				lsof1.start();
				lsof2.start();
				while (true) {
					if (!lsof1.isAlive() && !lsof2.isAlive()) { // 두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
						process.waitFor();
						sb.append(lsof1.getData());
						break;
					}
				}

//              Process process = new ProcessBuilder(cmd).start();
//              InputStream is = process.getInputStream();
//              InputStreamReader isr = new InputStreamReader(is);
//              BufferedReader br = new BufferedReader(isr);        
//              int result = process.waitFor();
//      
//             sb.append("\n<b>lsof</b>");
//             sb.append("\n<font color='gray'>");
//             String line = "";
//              while ((line = br.readLine()) != null) {
//                 String[] cols = line.trim().split("[ ]+");
//                 String separator = Env.isWindows() ? ":" : ".";
//                  sb.append("    " + line + "\n");
//              }        
//             sb.append("</font>");       
//             sb.append("\n");
			} catch (Exception e) {
				logger.error("Error", e);
			}
		}

		/**
		 * threads info
		 */
		sb.append("\n<b>threads</b>");
		sb.append("\n<font color='gray'>");
		ThreadGroup it = Thread.currentThread().getThreadGroup();
		Thread[] threads = new Thread[it.activeCount()];
		it.enumerate(threads);

		sb.append("<table border='0' align='left'>");
		for (int i = 0; i < threads.length; i++) {
			try {
				if ((threads[i] != null && threads[i].getName() != null
						&& threads[i].getName()
								.startsWith(adapterName.substring(adapterName.lastIndexOf('.') + 1) + "-"))
						|| (adapter.getThreadMap().get(threads[i]) != null)) {
					sb.append("<tr>");
					sb.append(ThreadDumpUtil.getStackTrace(threads[i]));
					sb.append("</tr>");
				}
			} catch (Exception e) {
				logger.error("Error", e);
			}
		}
		sb.append("</table>");
		sb.append("</font>");
		sb.append("\n");

		return "<pre>" + sb.toString() + "</pre>";
	}

	private String traceLevel(String adapterName, int level) throws Exception {
//      StringBuffer sb = new StringBuffer();
		ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
		if (adapter != null)
			adapter.getContext().setTraceLevel(level);
		return show(adapterName);
	}

	private String clear(String adapterName) throws Exception {
		ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
		if (adapter == null)
			throw new Exception("adapter does not exist");
		adapter.clearStat();
		return adapterName + " | statistics cleared successfully.";
	}

	private String start(String adapterName) throws Exception {
		if (adapterName.indexOf('.') != -1) {
			ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
			if (adapter == null)
				throw new Exception("adapter does not exist");
			SimpleFuture future = adapter.start();
			Object result = future.join(60000L);
			if (result instanceof Throwable) {
				return "<pre>" + ExceptionStackTrace.dump((Throwable) result) + "</pre>";
			}
			return adapterName + " | adapter successfully started";
		} else {
			ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
			if (adapters == null)
				throw new Exception("adapter group '" + adapterName + "' does not exist");
			for (int i = 0; i < adapters.length; i++) {
				SimpleFuture future = adapters[i].start();
				Object result = future.join(60000L);
				if (result instanceof Throwable) {
					return "<pre>" + ExceptionStackTrace.dump((Throwable) result) + "</pre>";
				}
			}
			return adapterName + " | adapter group successfully started";
		}
	}

	private String stop(String adapterName, boolean isForce) throws Exception {
		if (adapterName.indexOf('.') != -1) {
			ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
			if (adapter == null)
				return adapterName + " | adapter does not exist";
			try {
				SimpleFuture future = null;
				if (isForce) {
					future = adapter.stopForcely();
				} else {
					future = adapter.stop();
				}
				Object result = future.join();
				if (result instanceof Throwable) {
					return "<pre>" + ExceptionStackTrace.dump((Throwable) result) + "</pre>";
				}
				return adapterName + " | adapter successfully stopped";
			} catch (Exception e) {
				return e.getMessage();
			}
		} else {
			ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
			if (adapters == null)
				throw new Exception(adapterName + " | adapter group does not exist");
			for (int i = 0; i < adapters.length; i++) {
				SimpleFuture future = null;
				if (isForce) {
					future = adapters[i].stopForcely();
				} else {
					future = adapters[i].stop();
				}
				Object result = future.join();
				if (result instanceof Throwable) {
					return "<pre>" + ExceptionStackTrace.dump((Throwable) result) + "</pre>";
				}
			}
			return adapterName + " | adapter group successfully stopped";
		}
	}

	final static String SCRIPT = "   <script>                                        \n"
			+ "      function toggle(obj){                       \n"
			+ "         if (obj.style.height == \"17px\"){      \n"
			+ "            obj.style.height=\"\";              \n"
			+ "            obj.style.overflow=\"visible\";     \n"
			+ "         }else{                                  \n"
			+ "            obj.style.height=\"17px\";          \n"
			+ "            obj.style.overflow=\"hidden\";      \n"
			+ "         }                                       \n"
			+ "      }                                           \n"
			+ "   </script>                                       \n";

	private String error(String adapterName) throws Exception {
		StringBuffer sb = new StringBuffer();
		ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
		if (adapter == null)
			throw new Exception(adapterName + " - adapter does not exist");

		String[] errors = adapter.getRecentErrors();

		sb.append(SCRIPT);
		sb.append("adapter = " + adapterName + "<br>");
		sb.append("\n");
		for (int i = errors.length - 1; i >= 0; i--) {
			sb.append(
					"<div style=\"height: 17px; margin: 0px 0px 0px 0px;overflow: hidden;padding:0px 0px 0px 0px;cursor:hand;\" ondblclick=\"toggle(this)\">");
			sb.append("<pre style=\"padding:0px 0px 0px 0px;margin: 0px 0px 0px 0px\">");
			sb.append(unescape(errors[i]));
			sb.append("</pre>");
			sb.append("</div>");
			sb.append("<div style=\"height: 1px; overflow: hidden;border:0px;background-color:black;\"></div>");
		}
		return sb.toString();

	}

	private String sendRecv(String adapterName) throws Exception {
		StringBuffer sb = new StringBuffer();
		ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
		if (adapter == null)
			throw new Exception(adapterName + " - adapter does not exist");

		String[] msgs = adapter.getRecentSendRecv();

		sb.append(SCRIPT);
		sb.append("adapter = " + adapterName + "<br>");
		sb.append("\n");
		sb.append("<pre>");
		for (int i = msgs.length - 1; i >= 0; i--) {
			sb.append(
					"<div style=\"height: 17px; margin: 0px 0px 0px 0px;overflow: hidden;padding:0px 0px 0px 0px;cursor:hand;\" ondblclick=\"toggle(this)\">");
			sb.append("<pre style=\"padding:0px 0px 0px 0px;margin: 0px 0px 0px 0px\">");
			sb.append(unescape(msgs[i]));
			sb.append("\n\n");
			sb.append("</pre>");
			sb.append("</div>");
			sb.append("<div style=\"height: 1px; overflow: hidden;border:0px;background-color:black;\"></div>");
		}
		sb.append("</pre>\n");
		return sb.toString();
	}

	private String removeSession(String adapterName, String localPort, String remotePort) throws Exception {
		if (adapterName.indexOf('.') != -1) {
			ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
			if (adapter == null)
				throw new Exception("adapter does not exist");
			adapter.getSessionPool().remove(Integer.parseInt(localPort), Integer.parseInt(remotePort));
			return adapterName + " | adapter session remove local(" + localPort + ") remote(" + remotePort + ")";
		}
		return "fail";
	}

	private String sessionValidate(String adapterName) throws Exception {
		if (adapterName.indexOf('.') != -1) {
			ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
			if (adapter == null)
				throw new Exception("adapter does not exist");
			adapter.getSessionPool().sessionValidate();
			return adapterName + " | adapter session validate";
		}
		return "fail";
	}

	private String unescape(String string) {
		string = string.replace("<b>", "(b)").replace("</b>", "(/b)");
		string = string.replaceAll("<a( href=\\'[a-zA-Z0-9_/]+\\')>", "(a$1)").replace("</a>", "(/a)");
		string = string.replaceAll("<font color='([a-zA-Z0-9# ]+)'>", "(font color='$1')").replace("</font>",
				"(/font)");
		string = string.replace(">", "&gt;").replace("<", "&lt;");
		string = string.replace("(b)", "<b>").replace("(/b)", "</b>");
		string = string.replaceAll("\\(a( href=\\'[a-zA-Z0-9_/]+\\')\\)", "<a$1>").replace("(/a)", "</a>");
		string = string.replaceAll("\\(font color='([a-zA-Z0-9# ]+)'\\)", "<font color='$1'>").replace("(/font)",
				"</font>");
		return string;
	}

	class StreamForNetstat extends Thread {
		InputStream is;
		StringBuffer sb;
		ISocketAdapter adapter;

		public StreamForNetstat(InputStream is, ISocketAdapter adapter) {
			this.adapter = adapter;
			this.is = is;
			sb = new StringBuffer();
		}

		public void run() {
			try {
				InputStreamReader isr = new InputStreamReader(is);
				BufferedReader br = new BufferedReader(isr);
				sb.append("\n<b>netstat</b>");
				sb.append("\n<font color='gray'>");
				String line;
				while ((line = br.readLine()) != null) {
					if (!line.trim().toUpperCase().startsWith("TCP") && !line.trim().toUpperCase().startsWith("UDP"))
						continue;
					String[] cols = line.trim().split("[ ]+");
					String separator = Env.isWindows() ? ":" : ".";
					if (Env.isWindows()) {
						if (adapter.getContext().isServer()) {
							if (!cols[1].endsWith(separator + adapter.getContext().getPortNumber())) {
								continue;
							}
						} else {
							if (!cols[2].equals(adapter.getContext().getHostName() + separator
									+ adapter.getContext().getPortNumber())) {
								continue;
							}
						}
					} else {
						if (adapter.getContext().isServer()) {
							if (!cols[3].endsWith(separator + adapter.getContext().getPortNumber())) {
								continue;
							}
						} else {
							if (!cols[4].equals(adapter.getContext().getHostName() + separator
									+ adapter.getContext().getPortNumber())) {
								continue;
							}
						}
					}
					sb.append("    " + line + "\n");
				}
				sb.append("</font>");
				sb.append("\n");

			} catch (IOException ioe) {
				logger.error("StreamForNetstat", ioe);
			}
		}

		public String getData() {
			return sb.toString();
		}
	}

	class StreamForLsof extends Thread {
		InputStream is;
		StringBuffer sb;

		public StreamForLsof(InputStream is) {
			this.is = is;
			sb = new StringBuffer();
		}

		public void run() {
			try {
				InputStreamReader isr = new InputStreamReader(is);
				BufferedReader br = new BufferedReader(isr);
				sb.append("\n<b>lsof</b>");
				sb.append("\n<font color='gray'>");
				String line = "";
				while ((line = br.readLine()) != null) {
//                 String[] cols = line.trim().split("[ ]+");
//                 String separator = Env.isWindows() ? ":" : ".";
					sb.append("    " + line + "\n");
				}
				sb.append("</font>");
				sb.append("\n");

			} catch (IOException ioe) {
				logger.error("StreamForLsof", ioe);
			}
		}

		public String getData() {
			return sb.toString();
		}
	}
}