Skip to content

Commit

Permalink
Refactore backend handling and keep now a timetamp for the last MBean…
Browse files Browse the repository at this point in the history
… change.
  • Loading branch information
rhuss committed Mar 6, 2013
1 parent 706c546 commit e3a05b4
Show file tree
Hide file tree
Showing 12 changed files with 531 additions and 203 deletions.
Expand Up @@ -17,17 +17,14 @@
*/

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.*;

import javax.management.*;
import javax.management.relation.MBeanServerNotificationFilter;

import org.jolokia.backend.executor.AbstractMBeanServerExecutor;
import org.jolokia.detector.ServerDetector;
import org.jolokia.handler.JsonRequestHandler;
import org.jolokia.request.JmxRequest;
import org.jolokia.util.ServersInfo;

/**
* Singleton responsible for doing the merging of all MBeanServer detected.
Expand All @@ -45,14 +42,8 @@
*/
public class MBeanServerExecutorLocal extends AbstractMBeanServerExecutor implements NotificationListener {

// Private Jolokia MBeanServer
private MBeanServer jolokiaMBeanServer;

// Set of detected MBeanSevers
private Set<MBeanServerConnection> mBeanServers;

// All MBeanServers including the JolokiaMBeanServer
private Set<MBeanServerConnection> allMBeanServers;
// Set of MBeanServers found
private MBeanServers mbeanServers;

/**
* Constructor with a given list of destectors
Expand Down Expand Up @@ -88,33 +79,11 @@ public MBeanServerExecutorLocal() {
*/
private synchronized void init(List<ServerDetector> pDetectors) {

// Check for JBoss MBeanServer via its utility class
mBeanServers = new LinkedHashSet<MBeanServerConnection>();

// Create and add our own JolokiaMBeanServer first and
// add us for registration/deregestration of the MBeanServer
jolokiaMBeanServer = lookupJolokiaMBeanServer();
addMBeanServerNotificationHandler();
// Create the MBeanServerList
mbeanServers = new MBeanServers(pDetectors,this);

// Let every detector add its own MBeanServer
for (ServerDetector detector : pDetectors) {
detector.addMBeanServers(mBeanServers);
}

// All MBean Server known by the MBeanServerFactory
List<MBeanServer> beanServers = MBeanServerFactory.findMBeanServer(null);
if (beanServers != null) {
mBeanServers.addAll(beanServers);
}

// Last entry is always the platform MBeanServer
mBeanServers.add(ManagementFactory.getPlatformMBeanServer());

allMBeanServers = new LinkedHashSet<MBeanServerConnection>();
if (jolokiaMBeanServer != null) {
allMBeanServers.add(jolokiaMBeanServer);
}
allMBeanServers.addAll(mBeanServers);
// Register for registers/deregister of MBean changes in order to update lastUpdateTime
registerForMBeanNotifications();
}

/**
Expand All @@ -129,7 +98,7 @@ private synchronized void init(List<ServerDetector> pDetectors) {
* @throws AttributeNotFoundException
* @throws InstanceNotFoundException
*/
public Object handleRequest(JsonRequestHandler pRequestHandler, JmxRequest pJmxReq)
public <R extends JmxRequest> Object handleRequest(JsonRequestHandler<R> pRequestHandler, R pJmxReq)
throws MBeanException, ReflectionException, AttributeNotFoundException, InstanceNotFoundException {
AttributeNotFoundException attrException = null;
InstanceNotFoundException objNotFoundException = null;
Expand All @@ -153,55 +122,12 @@ public Object handleRequest(JsonRequestHandler pRequestHandler, JmxRequest pJmxR
throw objNotFoundException;
}

/** {@inheritDoc} */
@Override
protected Set<MBeanServerConnection> getMBeanServers() {
return allMBeanServers;
}

/** {@inheritDoc} */
@Override
protected MBeanServerConnection getJolokiaMBeanServer() {
return jolokiaMBeanServer;
}

// ==========================================================================================

// Check, whether the Jolokia MBean Server is available and return it.
private MBeanServer lookupJolokiaMBeanServer() {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
try {
ObjectName oName = new ObjectName("jolokia:type=MBeanServer");
return server.isRegistered(oName) ?
(MBeanServer) server.getAttribute(oName,"JolokiaMBeanServer") :
null;
} catch (JMException e) {
throw new IllegalStateException("Internal: Cannot get Jolokia MBeanServer via JMX lookup: " + e,e);
}
}

/**
* Fetch Jolokia MBeanServer when it gets registered
*
* @param notification notification emitted
* @param handback not used here
*/
public synchronized void handleNotification(Notification notification, Object handback) {
if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(notification.getType())) {
jolokiaMBeanServer = lookupJolokiaMBeanServer();
} else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(notification.getType())) {
jolokiaMBeanServer = null;
}
allMBeanServers.clear();
allMBeanServers.add(jolokiaMBeanServer);
allMBeanServers.addAll(mBeanServers);
}

/**
* Lifecycle method called at the end of life for this object.
*/
public void destroy() {
removeMBeanServerNotificationListener();
super.destroy();
mbeanServers.destroy();
}

/**
Expand All @@ -210,56 +136,22 @@ public void destroy() {
* @return string representation of the servers along with some statistics.
*/
public String getServersInfo() {
return ServersInfo.dump(allMBeanServers);
return mbeanServers.dump();
}

// =====================================================================================================
// ==============================================================================

// Register this executor as notification listener for the JolokiaMBeanServer at the PlatformMBeanServer
private void addMBeanServerNotificationHandler() {
MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter();
try {
filter.enableObjectName(new ObjectName("jolokia:type=MBeanServer"));
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
server.addNotificationListener(getMBeanServerDelegateName(), this, filter, null);
} catch (InstanceNotFoundException e) {
// Will not happen, since a delegate is always created during the creation
// of an MBeanServer
throw new IllegalStateException("Internal: Cannot lookup " +
getMBeanServerDelegateName() + ": " + e,e);
} catch (MalformedObjectNameException e) {
// How I hate this MalformedObjectNameException to be a checked one. Probably the one biggest mistake
// in JMX ...
throw new IllegalStateException("Internal: jolokia:type=MBeanServer is invalid ?!? ");
}
}

// Unregister as listener for MBeanServer registrations
private void removeMBeanServerNotificationListener() {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
server.removeNotificationListener(getMBeanServerDelegateName(), this);
} catch (InstanceNotFoundException e) {
// Will not happen, since a delegate is always created during the creation
// of an MBeanServer
throw new IllegalStateException("Internal: Cannot lookup " + MBeanServerDelegate.DELEGATE_NAME + ": " + e,e);
} catch (ListenerNotFoundException e) {
// Ignored, but we tried it.
}
/** {@inheritDoc} */
@Override
protected Set<MBeanServerConnection> getMBeanServers() {
return mbeanServers.getMBeanServers();
}

// Lookup the server delegate name, which works for sure for Java 1.6 but maye not for Java 1.5
// JAVA15
private ObjectName getMBeanServerDelegateName() {
try {
return MBeanServerDelegate.DELEGATE_NAME;
} catch (NoSuchFieldError error) {
// For Java 1.5 we return the fixed name
try {
return new ObjectName("JMImplementation:type=MBeanServerDelegate");
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException("Internal: Server delegate object name could not be created",e);
}
}
/**
* {@inheritDoc}
*/
@Override
protected MBeanServerConnection getJolokiaMBeanServer() {
return mbeanServers.getJolokiaMBeanServer();
}
}
149 changes: 149 additions & 0 deletions agent/core/src/main/java/org/jolokia/backend/MBeanServers.java
@@ -0,0 +1,149 @@
package org.jolokia.backend;

import java.lang.management.ManagementFactory;
import java.util.*;

import javax.management.*;

import org.jolokia.detector.ServerDetector;
import org.jolokia.util.JmxUtil;
import org.jolokia.util.ServersInfo;

import static javax.management.MBeanServerNotification.REGISTRATION_NOTIFICATION;
import static javax.management.MBeanServerNotification.UNREGISTRATION_NOTIFICATION;

/**
* Class managing the set of available MBeanServers
*/
class MBeanServers implements NotificationListener {

// All detected MBeanServces
private final Set<MBeanServerConnection> detectedMBeanServers;

// detectedMBeanServers + JolokiaMBeanServer (if available)
private final Set<MBeanServerConnection> allMBeanServers;

// Notification listener to register to the JolokiaMBean server
// which listens for MBean registration events
private final NotificationListener jolokiaMBeanServerListener;

// Private Jolokia MBeanServer
private MBeanServerConnection jolokiaMBeanServer;

private static final ObjectName JOLOKIA_MBEAN_SERVER_ONAME = JmxUtil.newObjectName("jolokia:type=MBeanServer");

/**
* Constructor building up the list of available MBeanServers
*
* @param pDetectors detectors to be used for looking up MBeanServers
* @param pListener listener to register to the Jolokia MBeanServer when this server
* comes in late
*/
MBeanServers(List<ServerDetector> pDetectors, NotificationListener pListener) {
detectedMBeanServers = new LinkedHashSet<MBeanServerConnection>();
jolokiaMBeanServerListener = pListener;
// Create and add our own JolokiaMBeanServer first and
// add us for registration/deregestration of the MBeanServer
jolokiaMBeanServer = lookupJolokiaMBeanServer();
addJolokiaMBeanServerRegistrationListener();

// Let every detector add its own MBeanServer
for (ServerDetector detector : pDetectors) {
detector.addMBeanServers(detectedMBeanServers);
}

// All MBean Server known by the MBeanServerFactory
List<MBeanServer> beanServers = MBeanServerFactory.findMBeanServer(null);
if (beanServers != null) {
detectedMBeanServers.addAll(beanServers);
}

// Last entry is always the platform MBeanServer
detectedMBeanServers.add(ManagementFactory.getPlatformMBeanServer());

allMBeanServers = new LinkedHashSet<MBeanServerConnection>();
if (jolokiaMBeanServer != null) {
allMBeanServers.add(jolokiaMBeanServer);
}
allMBeanServers.addAll(detectedMBeanServers);
}

/**
* Fetch Jolokia MBeanServer when it gets registered, remove it if being unregistered
*
* @param notification notification emitted
* @param handback not used here
*/
public synchronized void handleNotification(Notification notification, Object handback) {
String type = notification.getType();
if (REGISTRATION_NOTIFICATION.equals(type)) {
jolokiaMBeanServer = lookupJolokiaMBeanServer();
// We need to add the listener provided during construction time to add the Jolokia MBeanServer
// so that it is kept updated, too.
if (jolokiaMBeanServerListener != null) {
JmxUtil.addMBeanRegistrationListener(jolokiaMBeanServer, jolokiaMBeanServerListener, null);
}
} else if (UNREGISTRATION_NOTIFICATION.equals(type)) {
jolokiaMBeanServer = null;
}

allMBeanServers.clear();
if (jolokiaMBeanServer != null) {
allMBeanServers.add(jolokiaMBeanServer);
}
allMBeanServers.addAll(detectedMBeanServers);
}

/**
* Get the list of the current set of MBeanServers which are active
* @return the list of current MBeanServers
*/
public Set<MBeanServerConnection> getMBeanServers() {
return allMBeanServers;
}

/**
* Return a dump information of all known MBeanServers
*
* @return information about the registered MBeanServers
*/
public String dump() {
return ServersInfo.dump(allMBeanServers);
}

/**
* To be called during deconstruction.
*/
public void destroy() {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
JmxUtil.removeMBeanRegistrationListener(server,this);
}

/**
* Get the Jolokia MBean server
* @return Jolokia MBeanServer or null
*/
public MBeanServerConnection getJolokiaMBeanServer() {
return jolokiaMBeanServer;
}

// ======================================================================================================

// Check, whether the Jolokia MBean Server is available and return it.
private MBeanServer lookupJolokiaMBeanServer() {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
try {
return server.isRegistered(JOLOKIA_MBEAN_SERVER_ONAME) ?
(MBeanServer) server.getAttribute(JOLOKIA_MBEAN_SERVER_ONAME, "JolokiaMBeanServer") :
null;
} catch (JMException e) {
throw new IllegalStateException("Internal: Cannot get Jolokia MBeanServer via JMX lookup: " + e, e);
}
}

// Register this executor as notification listener for the JolokiaMBeanServer at the PlatformMBeanServer
private void addJolokiaMBeanServerRegistrationListener() {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
JmxUtil.addMBeanRegistrationListener(server,this,JOLOKIA_MBEAN_SERVER_ONAME);
}
}

0 comments on commit e3a05b4

Please sign in to comment.