/*
* Copyright (C) 2003-2011 eXo Platform SAS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.etk.kernel.management.jmx;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBeanInfo;
import org.etk.common.logging.Logger;
import org.etk.kernel.management.jmx.annotations.NameTemplate;
import org.etk.kernel.management.spi.ManagedResource;
import org.etk.kernel.management.spi.ManagementProvider;
/**
* Created by The eXo Platform SAS
* Author : eXoPlatform
* exo@exoplatform.com
* Jul 28, 2011
*/
public class JMXManagementProvider implements ManagementProvider {
/**
* The logger
*/
private static final Logger LOG = Logger.getLogger(JMXManagementProvider.class);
/** . */
private final MBeanServer server;
public JMXManagementProvider() {
this(MBeanServerFactory.createMBeanServer());
}
public JMXManagementProvider(MBeanServer server) {
this.server = server;
}
/**
* MBeanServer to add the Component to management.
*/
public Object manage(ManagedResource context) {
ExoModelMBean mbean = null;
try {
ExoMBeanInfoBuilder infoBuilder = new ExoMBeanInfoBuilder(context.getMetaData());
ModelMBeanInfo info = infoBuilder.build();
mbean = new ExoModelMBean(context, context.getResource(), info);
} catch (Exception e) {
LOG.warn("Could not create the ExoModelMBean for the class "
+ (context == null ? null : (context.getResource() == null ? null : context.getResource().getClass())),e);
}
//
if (mbean != null) {
ObjectName on = null;
PropertiesInfo oni = PropertiesInfo.resolve(context.getResource().getClass(), NameTemplate.class);
if (oni != null) {
try {
Map<String, String> foo = oni.resolve(context.getResource());
on = JMX.createObjectName("exo", foo);
} catch (MalformedObjectNameException e) {
LOG.warn("Could not create the ObjectName for the class " + context.getResource().getClass(), e);
}
}
if (on != null) {
// Merge with the container hierarchy context
try {
Map<String, String> props = new LinkedHashMap<String, String>();
// Merge scoping properties
List<MBeanScopingData> list = context.getScopingData(MBeanScopingData.class);
// Read in revert order because wee received list of parents in upward
// order
for (int i = list.size(); i > 0; i--) {
MBeanScopingData scopingData = list.get(i - 1);
props.putAll(scopingData);
}
// Julien : I know it's does not look great but it's necessary
// for compiling under Java 5 and Java 6 properly. The methods
// ObjectName#getKeyPropertyList() returns an Hashtable with Java 5
// and a Hashtable<String, String> with Java 6.
for (Object o : on.getKeyPropertyList().entrySet()) {
Map.Entry entry = (Map.Entry) o;
String key = (String) entry.getKey();
String value = (String) entry.getValue();
props.put(key, value);
}
//
on = JMX.createObjectName(on.getDomain(), props);
//
attemptToRegister(on, mbean);
//
return on;
} catch (MalformedObjectNameException e) {
LOG.warn("Could not register the MBean for the class " + context.getResource().getClass(), e);
}
}
}
//
return null;
}
/**
* Register a component
*
* @param name
* @param mbean
*/
private void attemptToRegister(final ObjectName name, final Object mbean) {
synchronized (server) {
if (server.isRegistered(name)) {
if (LOG.isTraceEnabled()) {
LOG.trace("The MBean '" + name + " has already been registered, it will be unregistered and then re-registered");
}
try {
server.unregisterMBean(name);
} catch (Exception e) {
throw new RuntimeException("Failed to unregister MBean '" + name + " due to " + e.getMessage(), e);
}
}
try {
server.registerMBean(mbean, name);
} catch (Exception e) {
throw new RuntimeException("Failed to register MBean '" + name + " due to " + e.getMessage(), e);
}
}
}
public void unmanage(Object key) {
final ObjectName name = (ObjectName) key;
try {
server.unregisterMBean(name);
} catch (InstanceNotFoundException e) {
LOG.warn("Could not unregister the MBean " + name, e);
} catch (MBeanRegistrationException e) {
LOG.warn("Could not unregister the MBean " + name, e);
}
}
}