package org.opensource.clearpool.console.hook;
import java.lang.reflect.Field;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.opensource.clearpool.console.MBeanFacade;
import org.opensource.clearpool.exception.ConnectionPoolMBeanException;
import org.opensource.clearpool.logging.PoolLogger;
import org.opensource.clearpool.logging.PoolLoggerFactory;
import org.opensource.clearpool.util.PoolLatchUtil;
import com.sun.jdmk.comm.AuthInfo;
import com.sun.jdmk.comm.CommunicatorServer;
import com.sun.jdmk.comm.HtmlAdaptorServer;
/**
* This class's duty is to start HtmlAdaptorServer and count down the latch to run
* CommonPoolContainer.
*
* @author xionghui
* @date 26.07.2014
* @version 1.0
*/
public class HtmlAdaptorHook extends HtmlAdaptorServer {
private static final PoolLogger LOGGER = PoolLoggerFactory.getLogger(HtmlAdaptorHook.class);
/**
* Start HtmlAdaptorHook
*/
public static CommunicatorServer startHook(MBeanServer server) {
CommunicatorServer communicatorServer = initServer(server);
Thread serverThread = new Thread(communicatorServer);
serverThread.setName("HtmlAdaptorHook");
serverThread.setDaemon(true);
serverThread.start();
return communicatorServer;
}
/**
* Get CommunicatorServer and register it to MBeanServer.
*/
private static CommunicatorServer initServer(MBeanServer server) {
// we should know that securityMap isn't null
Map<String, String> securityMap = MBeanFacade.console.getSecurityMap();
List<AuthInfo> infoList = new ArrayList<AuthInfo>();
for (Entry<String, String> e : securityMap.entrySet()) {
infoList.add(new AuthInfo(e.getKey(), e.getValue()));
}
CommunicatorServer communicatorServer =
new HtmlAdaptorHook(MBeanFacade.console.getPort(), infoList.toArray(new AuthInfo[0]));
try {
ObjectName adapterName = new ObjectName("com.sun.jdmk.comm:type=HtmlAdaptorServer");
server.registerMBean(communicatorServer, adapterName);
} catch (Exception e) {
LOGGER.error("registerMBean error: ", e);
throw new ConnectionPoolMBeanException(e);
}
return communicatorServer;
}
/**
* Hide the constructor
*/
private HtmlAdaptorHook(int port, AuthInfo[] infos) {
super(port, infos);
}
@Override
public void run() {
LOGGER
.info("HtmlAdaptorServer running:url is http://localhost:" + MBeanFacade.console.getPort());
// I'm running.
PoolLatchUtil.countDownStartLatch();
super.run();
}
/**
* Set fields to stop it.Note:HtmlAdaptorServer didn't provided useful interface to stop it,so we
* use reflection to get it.
*/
public static void stop(CommunicatorServer communicatorServer) {
try {
Field field = CommunicatorServer.class.getDeclaredField("stopRequested");
field.setAccessible(true);
field.set(communicatorServer, true);
field = HtmlAdaptorServer.class.getDeclaredField("sockListen");
field.setAccessible(true);
ServerSocket sockListen = (ServerSocket) field.get(communicatorServer);
sockListen.close();
} catch (Exception e) {
LOGGER.error("stop CommunicatorServer error: ", e);
throw new ConnectionPoolMBeanException(e);
}
}
}