/*
Derby - Class org.apache.derby.impl.services.jmx.JMXManagementService
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.derby.impl.services.jmx;
import java.lang.management.ManagementFactory;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import javax.management.JMException;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.StandardMBean;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.reference.Property;
import org.apache.derby.iapi.services.info.Version;
import org.apache.derby.iapi.services.jmx.ManagementService;
import org.apache.derby.iapi.services.monitor.ModuleControl;
import org.apache.derby.iapi.services.monitor.Monitor;
import org.apache.derby.iapi.services.property.PropertyUtil;
import org.apache.derby.mbeans.ManagementMBean;
import org.apache.derby.mbeans.VersionMBean;
import org.apache.derby.security.SystemPermission;
/**
* This class implements the ManagementService interface and provides a simple
* management and monitoring service.
*
* An mbean registered with this service remains until it is unregistered.
* While registered with this service it may be registered and unregistered
* with the jmx service a number of times.
*
* @see org.apache.derby.iapi.services.jmx.ManagementService
*/
public final class JMXManagementService implements ManagementService, ModuleControl {
/**
* Platform MBean server, from ManagementFactory.getPlatformMBeanServer().
* If not null then this service has registered mbeans with the
* plaform MBean server.
* If null then this service either has no mbeans registered
* or one mbean registered (representing itself).
*/
private MBeanServer mbeanServer;
/**
* The set of mbeans registered to this service by
* Derby's code. These beans are registered with
* the platform mbean server if mbeanServer is not null.
*/
private Map registeredMbeans;
/**
* If this object is registered as a management mbean
* then myManagementBean represents its name. This will
* be non-null when derby.system.jmx is true.
*/
private ObjectName myManagementBean;
private MBeanServer myManagementServer;
/**
* Runtime value to disambiguate
* multiple Derby systems in the same virtual machine but
* different class loaders. Set as the system attribute in
* the ObjectName for all MBeans registered.
*/
private String systemIdentifier;
public JMXManagementService() {
}
/**
* Start the management service if derby.system.jmx is true.
*
* Starting the service means:
*
* - getting the platform MBeanServer which may require starting it
*
- registering a Version mbean representing the system
*
*/
public synchronized void boot(boolean create, Properties properties)
throws StandardException {
registeredMbeans = new HashMap();
systemIdentifier =
Monitor.getMonitor().getUUIDFactory().createUUID().toString();
findServer();
myManagementBean = (ObjectName) registerMBean(this,
ManagementMBean.class,
"type=Management");
myManagementServer = mbeanServer;
registerMBean(
new Version(
Monitor.getMonitor().getEngineVersion(),
SystemPermission.ENGINE),
VersionMBean.class,
"type=Version,jar=derby.jar");
}
public synchronized void stop() {
// If we are currently not registering any mbeans
// then we might still have this registered as
// a management mbean. Need to explicitly remove this
// using the mbean server that created it, which
// possibly could not be the same as the current server.
if (mbeanServer == null && myManagementBean != null)
{
mbeanServer = myManagementServer;
unregisterMBean(myManagementBean);
mbeanServer = null;
}
// Need a copy of registeredMbeans since unregisterMBean will remove
// items from registeredMbeans and thus invalidate any iterator
// on it directly.
for (ObjectName mbeanName :
new HashSet(registeredMbeans.keySet()))
unregisterMBean(mbeanName);
mbeanServer = null;
// registeredMbeans == null indicates service is not active
registeredMbeans = null;
myManagementServer = null;
systemIdentifier = null;
}
/**
* Initialize the management service by obtaining the platform
* MBeanServer and registering system beans. Separate from
* boot() to allow future changes where the jmx management
* can be enabled on the fly.
*/
private synchronized void findServer() {
try {
mbeanServer = AccessController
.doPrivileged(new PrivilegedAction() {
public MBeanServer run() {
return ManagementFactory.getPlatformMBeanServer();
}
});
} catch (SecurityException se) {
// Ignoring inability to create or
// find the mbean server. MBeans can continue
// to be registered with this service and
// startMangement() can be called to get
// them registered with JMX if someone else
// starts the MBean server.
}
}
/**
* Registers an MBean with the MBean server as a StandardMBean.
* Use of the StandardMBean allows the implementation details
* of Derby's mbeans to be hidden from JMX, thus only exposing
* the MBean's interface in org.apache.derby.mbeans.
*
*
* @param bean The MBean to wrap with a StandardMBean and register
* @param beanInterface The management interface for the MBean.
* @param keyProperties The String representation of the MBean's key properties,
* they will be added into the ObjectName with Derby's domain. Key
* type should be first with a short name for the bean, typically the
* class name without the package.
*
*/
public synchronized Object registerMBean(final T bean,
final Class beanInterface,
final String keyProperties)
throws StandardException {
try {
final ObjectName beanName = new ObjectName(
DERBY_JMX_DOMAIN + ":" + keyProperties
+ ",system=" + systemIdentifier);
final StandardMBean standardMBean =
new StandardMBean(bean, beanInterface) {
/**
* Hide the implementation name from JMX clients
* by providing the interface name as the class
* name for the MBean. Allows the permissions
* in a policy file to be granted to the public
* MBean interfaces.
*/
protected String getClassName(MBeanInfo info) {
return beanInterface.getName();
}
};
// new StandardMBean(bean, beanInterface);
registeredMbeans.put(beanName, standardMBean);
if (mbeanServer != null)
jmxRegister(standardMBean, beanName);
return beanName;
} catch (JMException jme) {
throw StandardException.plainWrapException(jme);
}
}
/**
* Register an mbean with the platform mbean server.
*/
private void jmxRegister(final StandardMBean standardMBean,
final ObjectName beanName) throws JMException
{
// Already registered? Can happen if we don't have permission
// to unregister the MBeans.
if (mbeanServer.isRegistered(beanName))
return;
try {
AccessController
.doPrivileged(new PrivilegedExceptionAction
Ads help maintain this website.