package com.mongodb.management;
import com.mongodb.connection.ConnectionId;
import com.mongodb.connection.ServerId;
import com.mongodb.event.ConnectionAddedEvent;
import com.mongodb.event.ConnectionCheckedInEvent;
import com.mongodb.event.ConnectionCheckedOutEvent;
import com.mongodb.event.ConnectionPoolClosedEvent;
import com.mongodb.event.ConnectionPoolListener;
import com.mongodb.event.ConnectionPoolOpenedEvent;
import com.mongodb.event.ConnectionPoolWaitQueueEnteredEvent;
import com.mongodb.event.ConnectionPoolWaitQueueExitedEvent;
import com.mongodb.event.ConnectionRemovedEvent;
import javax.management.ObjectName;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.lang.String.format;
import static java.util.Arrays.asList;
public class JMXConnectionPoolListener implements ConnectionPoolListener {
private final ConcurrentMap<ServerId, ConnectionPoolStatistics> map =
new ConcurrentHashMap<ServerId, ConnectionPoolStatistics>();
@Override
public void connectionPoolOpened(final ConnectionPoolOpenedEvent event) {
ConnectionPoolStatistics statistics = new ConnectionPoolStatistics(event);
map.put(event.getServerId(), statistics);
MBeanServerFactory.getMBeanServer().registerMBean(statistics, getMBeanObjectName(event.getServerId()));
}
@Override
public void connectionPoolClosed(final ConnectionPoolClosedEvent event) {
map.remove(event.getServerId());
MBeanServerFactory.getMBeanServer().unregisterMBean(getMBeanObjectName(event.getServerId()));
}
@Override
public void connectionCheckedOut(final ConnectionCheckedOutEvent event) {
ConnectionPoolStatistics statistics = getStatistics(event.getConnectionId());
if (statistics != null) {
statistics.connectionCheckedOut(event);
}
}
@Override
public void connectionCheckedIn(final ConnectionCheckedInEvent event) {
ConnectionPoolStatistics statistics = getStatistics(event.getConnectionId());
if (statistics != null) {
statistics.connectionCheckedIn(event);
}
}
@Override
public void waitQueueEntered(final ConnectionPoolWaitQueueEnteredEvent event) {
ConnectionPoolListener statistics = getStatistics(event.getServerId());
if (statistics != null) {
statistics.waitQueueEntered(event);
}
}
@Override
public void waitQueueExited(final ConnectionPoolWaitQueueExitedEvent event) {
ConnectionPoolListener statistics = getStatistics(event.getServerId());
if (statistics != null) {
statistics.waitQueueExited(event);
}
}
@Override
public void connectionAdded(final ConnectionAddedEvent event) {
ConnectionPoolStatistics statistics = getStatistics(event.getConnectionId());
if (statistics != null) {
statistics.connectionAdded(event);
}
}
@Override
public void connectionRemoved(final ConnectionRemovedEvent event) {
ConnectionPoolStatistics statistics = getStatistics(event.getConnectionId());
if (statistics != null) {
statistics.connectionRemoved(event);
}
}
String getMBeanObjectName(final ServerId serverId) {
String name = format("org.mongodb.driver:type=ConnectionPool,clusterId=%s,host=%s,port=%s",
ensureValidValue(serverId.getClusterId().getValue()),
ensureValidValue(serverId.getAddress().getHost()),
serverId.getAddress().getPort());
if (serverId.getClusterId().getDescription() != null) {
name = format("%s,description=%s", name, ensureValidValue(serverId.getClusterId().getDescription()));
}
return name;
}
ConnectionPoolStatisticsMBean getMBean(final ServerId serverId) {
return getStatistics(serverId);
}
private ConnectionPoolStatistics getStatistics(final ConnectionId connectionId) {
return getStatistics(connectionId.getServerId());
}
private ConnectionPoolStatistics getStatistics(final ServerId serverId) {
return map.get(serverId);
}
private String ensureValidValue(final String value) {
if (containsQuotableCharacter(value)) {
return ObjectName.quote(value);
} else {
return value;
}
}
private boolean containsQuotableCharacter(final String value) {
if (value == null || value.length() == 0) {
return false;
}
List<String> quoteableCharacters = asList(",", ":", "?", "*", "=", "\"", "\\", "\n");
for (String quotable : quoteableCharacters) {
if (value.contains(quotable)) {
return true;
}
}
return false;
}
}