All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.runtime.monitor.db.ConnectionMonitor Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.4.0
Show newest version
/*
 * $Id: ConnectionMonitor.java,v 1.5 2014/05/03 20:02:39 oboehm Exp $
 *
 * Copyright (c) 2012 by Oliver Boehm
 *
 * 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 orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 07.10.2012 by oliver ([email protected])
 */

package patterntesting.runtime.monitor.db;

import java.sql.Connection;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.management.JMException;
import javax.management.openmbean.*;

import org.slf4j.*;

import patterntesting.runtime.jmx.MBeanHelper;


/**
 * This is the monitor class for the {@link ProxyConnection} which monitors the
 * different newInstance() and close() call. So you can ask this class how many
 * and which connections are open.
 * 

* The instance of this class is automatically registered as MBean as soon as a * {@link ProxyConnection} is used. *

*

* Note: Since 1.4.2 this class was moved from package * "patterntesting.runtime.db" to here. *

* * @author oliver ([email protected]) * @since 1.3 (07.10.2012) * @version $Revision: 1.5 $ */ public class ConnectionMonitor implements ConnectionMonitorMBean { private static final Logger log = LoggerFactory.getLogger(ConnectionMonitor.class); private static final ConnectionMonitorMBean instance; private static final List openConnections = new CopyOnWriteArrayList(); private static int sumOfConnections = 0; static { instance = new ConnectionMonitor(); log.debug("{} created and registered as MBean.", instance); try { MBeanHelper.registerMBean(instance); } catch (JMException e) { log.info("{} can't be registered as MBean ({})", instance, e); } } /** * No need to instantiate it - we provide only some services. The * constructor is protected because it is still used by the (deprecated) * ConnectionMonitor in patterntesting.runtime.db. */ protected ConnectionMonitor() { log.trace("{} created.", this); } /** * Yes, it is a Singleton because it offers only some services. So we don't * need the object twice. * * @return the only instance */ public static ConnectionMonitorMBean getInstance() { return instance; } /** * If you want to monitor the connection use this method. * * @param connection the original connection * @return a proxy for the connection */ public static Connection getMonitoredConnection(final Connection connection) { return ProxyConnection.newInstance(connection); } /** * Adds the connection. * * @param proxyConnection the proxy connection */ public static void addConnection(final ProxyConnection proxyConnection) { openConnections.add(proxyConnection); sumOfConnections++; } /** * Removes the connection. * * @param proxyConnection the proxy connection */ public static void removeConnection(final ProxyConnection proxyConnection) { openConnections.remove(proxyConnection); } /** * Gets the caller of the given connection. * * @param connection the connection * @return the caller of */ public static StackTraceElement getCallerOf(final Connection connection) { for (ProxyConnection proxy : openConnections) { if (proxy.getConnection().equals(connection)) { return proxy.getCaller()[0]; } } throw new IllegalArgumentException("not monitored or closed: " + connection); } /** * Gets the callers. * * @return the callers * @see ConnectionMonitorMBean#getCallers() */ public StackTraceElement[] getCallers() { StackTraceElement[] callers = new StackTraceElement[openConnections.size()]; int i = 0; for (ProxyConnection proxy : openConnections) { callers[i] = proxy.getCaller()[0]; i++; } return callers; } /** * Gets the stacktrace of the caller which opens the last connection. * * @return the all caller */ public StackTraceElement[] getLastCallerStacktrace() { ProxyConnection lastConnection = openConnections.get(openConnections.size() - 1); return lastConnection.getCaller(); } /** * Gets the caller stacktraces of all connections. * * @return stacktraces of all callers * @throws OpenDataException the open data exception */ public TabularData getCallerStacktraces() throws OpenDataException { String[] itemNames = { "Caller", "Stacktrace" }; String[] itemDescriptions = { "caller name", "stacktrace" }; try { OpenType[] itemTypes = { SimpleType.STRING, new ArrayType(1, SimpleType.STRING) }; CompositeType rowType = new CompositeType("propertyType", "property entry", itemNames, itemDescriptions, itemTypes); TabularDataSupport data = MBeanHelper.createTabularDataSupport(rowType, itemNames); for (ProxyConnection proxy : openConnections) { StackTraceElement[] stacktrace = proxy.getCaller(); Map map = new HashMap(); map.put("Caller", stacktrace[0].toString()); map.put("Stacktrace", toStringArray(stacktrace)); CompositeDataSupport compData = new CompositeDataSupport( rowType, map); data.put(compData); } return data; } catch (OpenDataException ex) { log.warn("Cannot get caller stacktraces of " + openConnections.size() + " open connections.", ex); throw ex; } } private static String[] toStringArray(final StackTraceElement[] stacktrace) { String[] array = new String[stacktrace.length]; for (int i = 0; i < stacktrace.length; i++) { array[i] = stacktrace[i].toString(); } return array; } /** * Gets the caller which opens the last connection. * * @return the all caller */ public StackTraceElement getLastCaller() { StackTraceElement[] callers = this.getCallers(); if (callers.length == 0) { log.debug("No open connections - last caller is null."); return null; } return callers[callers.length-1]; } /** * Gets the number of open connections. * * @return the open count * @see ConnectionMonitorMBean#getOpenConnections() */ public int getOpenConnections() { return ConnectionMonitor.openConnections.size(); } /** * Gets the closed connections. * * @return the closed connections * @since 1.4.1 */ public int getClosedConnections() { return this.getSumOfConnections() - this.getOpenConnections(); } /** * Gets the total sum of open and closed connections. * * @return the sum of connections * @since 1.4.1 */ public int getSumOfConnections() { return sumOfConnections; } /** * Assert that all connections are closed. */ public static void assertConnectionsClosed() { int count = instance.getOpenConnections(); if (count > 0) { AssertionError error = new AssertionError(count + " connection(s) not closed"); error.setStackTrace(openConnections.iterator().next().getCaller()); throw error; } } /** * To string. * * @return the string * @see java.lang.Object#toString() */ @Override public String toString() { int n = this.getOpenConnections(); if (n < 1) { return this.getClass().getSimpleName(); } return this.getClass().getSimpleName() + " watching " + n + " connection(s)"; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy