Java tutorial
/* * Licensed under the GPL License. You may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ package net.testdriven.psiprobe.beans; import java.net.InetAddress; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; import javax.management.MBeanServerNotification; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.RuntimeOperationsException; import net.sf.javainetlocator.InetAddressLocator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import net.testdriven.psiprobe.model.Connector; import net.testdriven.psiprobe.model.RequestProcessor; import net.testdriven.psiprobe.model.ThreadPool; import net.testdriven.psiprobe.model.jmx.ThreadPoolObjectName; import net.testdriven.psiprobe.tools.JmxTools; /** * This class interfaces Tomcat JMX functionality to read connection status. The * class essentially provides and maintains the list of connection ThreadPools. * * @author Vlad Ilyushchenko * @author Mark Lewis */ public class ContainerListenerBean implements NotificationListener { private Log logger = LogFactory.getLog(getClass()); private List poolNames = null; private List executorNames = null; /** * Used to obtain required {@link MBeanServer} instance. */ private ContainerWrapperBean containerWrapper; public ContainerWrapperBean getContainerWrapper() { return containerWrapper; } public void setContainerWrapper(ContainerWrapperBean containerWrapper) { this.containerWrapper = containerWrapper; } private boolean isInitialized() { return poolNames != null && poolNames.size() > 0; } /** * Finds ThreadPoolObjectName by its string name. * @param name - pool name * * @return null if the input name is null or ThreadPoolObjectName is not found */ private ThreadPoolObjectName findPool(String name) { if (name != null && isInitialized()) { for (Iterator it = poolNames.iterator(); it.hasNext();) { ThreadPoolObjectName threadPoolObjectName = (ThreadPoolObjectName) it.next(); if (name.equals(threadPoolObjectName.getThreadPoolName().getKeyProperty("name"))) { return threadPoolObjectName; } } } return null; } /** * Handles creation and deletion of new "worker" threads. */ public synchronized void handleNotification(Notification notification, Object object) { if (notification instanceof MBeanServerNotification) { ObjectName objectName = ((MBeanServerNotification) notification).getMBeanName(); if (notification.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) { if ("RequestProcessor".equals(objectName.getKeyProperty("type"))) { ThreadPoolObjectName threadPoolObjectName = findPool(objectName.getKeyProperty("worker")); if (threadPoolObjectName != null) { threadPoolObjectName.getRequestProcessorNames().add(objectName); } } } else if (notification.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { if ("RequestProcessor".equals(objectName.getKeyProperty("type"))) { ThreadPoolObjectName threadPoolObjectName = findPool(objectName.getKeyProperty("worker")); if (threadPoolObjectName != null) { threadPoolObjectName.getRequestProcessorNames().remove(objectName); } } } } } /** * Load ObjectNames for the relevant MBeans so they can be queried at a later stage without searching MBean server * over and over again. * * @throws Exception - this method does not handle any of the exceptions that may be thrown when querying MBean server. */ private synchronized void initialize() throws Exception { MBeanServer server = getContainerWrapper().getResourceResolver().getMBeanServer(); String serverName = getContainerWrapper().getTomcatContainer().getName(); Set threadPools = server.queryMBeans(new ObjectName(serverName + ":type=ThreadPool,*"), null); poolNames = new ArrayList(threadPools.size()); for (Iterator it = threadPools.iterator(); it.hasNext();) { ThreadPoolObjectName threadPoolObjectName = new ThreadPoolObjectName(); ObjectName threadPoolName = ((ObjectInstance) it.next()).getObjectName(); String name = threadPoolName.getKeyProperty("name"); threadPoolObjectName.setThreadPoolName(threadPoolName); ObjectName grpName = server .getObjectInstance(new ObjectName( threadPoolName.getDomain() + ":type=GlobalRequestProcessor,name=" + name)) .getObjectName(); threadPoolObjectName.setGlobalRequestProcessorName(grpName); // // unfortunately exact workers could not be found at the time of testing // so we filter out the relevant workers within the loop // Set workers = server .queryMBeans(new ObjectName(threadPoolName.getDomain() + ":type=RequestProcessor,*"), null); for (Iterator wrkIt = workers.iterator(); wrkIt.hasNext();) { ObjectName wrkName = ((ObjectInstance) wrkIt.next()).getObjectName(); if (name.equals(wrkName.getKeyProperty("worker"))) { threadPoolObjectName.getRequestProcessorNames().add(wrkName); } } poolNames.add(threadPoolObjectName); } Set executors = server.queryMBeans(new ObjectName(serverName + ":type=Executor,*"), null); executorNames = new ArrayList(executors.size()); for (Iterator it = executors.iterator(); it.hasNext();) { ObjectName executorName = ((ObjectInstance) it.next()).getObjectName(); executorNames.add(executorName); } // Register with MBean server server.addNotificationListener(new ObjectName("JMImplementation:type=MBeanServerDelegate"), this, null, null); } public synchronized List getThreadPools() throws Exception { if (!isInitialized()) { initialize(); } List threadPools = new ArrayList(poolNames.size()); MBeanServer server = getContainerWrapper().getResourceResolver().getMBeanServer(); for (Iterator it = executorNames.iterator(); it.hasNext();) { ObjectName executorName = (ObjectName) it.next(); ThreadPool threadPool = new ThreadPool(); threadPool.setName(executorName.getKeyProperty("name")); threadPool.setMaxThreads(JmxTools.getIntAttr(server, executorName, "maxThreads")); threadPool.setMaxSpareThreads(JmxTools.getIntAttr(server, executorName, "largestPoolSize")); threadPool.setMinSpareThreads(JmxTools.getIntAttr(server, executorName, "minSpareThreads")); threadPool.setCurrentThreadsBusy(JmxTools.getIntAttr(server, executorName, "activeCount")); threadPool.setCurrentThreadCount(JmxTools.getIntAttr(server, executorName, "poolSize")); threadPools.add(threadPool); } for (Iterator it = poolNames.iterator(); it.hasNext();) { ThreadPoolObjectName threadPoolObjectName = (ThreadPoolObjectName) it.next(); try { ObjectName poolName = threadPoolObjectName.getThreadPoolName(); ThreadPool threadPool = new ThreadPool(); threadPool.setName(poolName.getKeyProperty("name")); threadPool.setMaxThreads(JmxTools.getIntAttr(server, poolName, "maxThreads")); if (JmxTools.hasAttribute(server, poolName, "maxSpareThreads")) { threadPool.setMaxSpareThreads(JmxTools.getIntAttr(server, poolName, "maxSpareThreads")); threadPool.setMinSpareThreads(JmxTools.getIntAttr(server, poolName, "minSpareThreads")); } threadPool.setCurrentThreadsBusy(JmxTools.getIntAttr(server, poolName, "currentThreadsBusy")); threadPool.setCurrentThreadCount(JmxTools.getIntAttr(server, poolName, "currentThreadCount")); // Tomcat 6.0.21+ will return -1 for maxThreads if the connector uses an executor for its threads. // In this case, don't add its ThreadPool to the results. if (threadPool.getMaxThreads() > -1) { threadPools.add(threadPool); } } catch (InstanceNotFoundException e) { logger.error("Failed to query entire thread pool " + threadPoolObjectName); logger.debug(" Stack trace:", e); } } return threadPools; } public synchronized List getConnectors(boolean includeRequestProcessors) throws Exception { boolean workerThreadNameSupported = true; if (!isInitialized()) { initialize(); } List connectors = new ArrayList(poolNames.size()); MBeanServer server = getContainerWrapper().getResourceResolver().getMBeanServer(); for (Iterator it = poolNames.iterator(); it.hasNext();) { ThreadPoolObjectName threadPoolObjectName = (ThreadPoolObjectName) it.next(); try { ObjectName poolName = threadPoolObjectName.getThreadPoolName(); Connector connector = new Connector(); connector.setName(poolName.getKeyProperty("name")); ObjectName grpName = threadPoolObjectName.getGlobalRequestProcessorName(); connector.setMaxTime(JmxTools.getLongAttr(server, grpName, "maxTime")); connector.setProcessingTime(JmxTools.getLongAttr(server, grpName, "processingTime")); connector.setBytesReceived(JmxTools.getLongAttr(server, grpName, "bytesReceived")); connector.setBytesSent(JmxTools.getLongAttr(server, grpName, "bytesSent")); connector.setRequestCount(JmxTools.getIntAttr(server, grpName, "requestCount")); connector.setErrorCount(JmxTools.getIntAttr(server, grpName, "errorCount")); if (includeRequestProcessors) { for (Iterator wrkIt = threadPoolObjectName.getRequestProcessorNames().iterator(); wrkIt .hasNext();) { ObjectName wrkName = (ObjectName) wrkIt.next(); try { RequestProcessor rp = new RequestProcessor(); rp.setName(wrkName.getKeyProperty("name")); rp.setStage(JmxTools.getIntAttr(server, wrkName, "stage")); rp.setProcessingTime(JmxTools.getLongAttr(server, wrkName, "requestProcessingTime")); rp.setBytesSent(JmxTools.getLongAttr(server, wrkName, "requestBytesSent")); rp.setBytesReceived(JmxTools.getLongAttr(server, wrkName, "requestBytesReceived")); try { String remoteAddr = JmxTools.getStringAttr(server, wrkName, "remoteAddr"); rp.setRemoteAddr(remoteAddr); rp.setRemoteAddrLocale(InetAddressLocator .getLocale(InetAddress.getByName(remoteAddr).getAddress())); } catch (RuntimeOperationsException ex) { /* * if it's not available for this request processor, then it's * not available for any request processor in this thread pool */ } rp.setVirtualHost(JmxTools.getStringAttr(server, wrkName, "virtualHost")); rp.setMethod(JmxTools.getStringAttr(server, wrkName, "method")); rp.setCurrentUri(JmxTools.getStringAttr(server, wrkName, "currentUri")); rp.setCurrentQueryString(JmxTools.getStringAttr(server, wrkName, "currentQueryString")); rp.setProtocol(JmxTools.getStringAttr(server, wrkName, "protocol")); // Relies on https://issues.apache.org/bugzilla/show_bug.cgi?id=41128 if (workerThreadNameSupported && JmxTools.hasAttribute(server, wrkName, "workerThreadName")) { rp.setWorkerThreadName(JmxTools.getStringAttr(server, wrkName, "workerThreadName")); rp.setWorkerThreadNameSupported(true); } else { // // attribute should consistently either exist or be missing across all the workers so // it does not make sense to check attribute existence // if we have found once that it is not supported // rp.setWorkerThreadNameSupported(false); workerThreadNameSupported = false; } connector.addRequestProcessor(rp); } catch (InstanceNotFoundException e) { logger.info("Failed to query RequestProcessor " + wrkName); logger.debug(" Stack trace:", e); } } } connectors.add(connector); } catch (InstanceNotFoundException e) { logger.error("Failed to query entire thread pool " + threadPoolObjectName); logger.debug(" Stack trace:", e); } } return connectors; } }