/* * 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.tomcat.util.modeler;
/** * Registry for modeler MBeans. * * This is the main entry point into modeler. It provides methods to create and * manipulate model mbeans and simplify their use. * * This class is itself an mbean. * * @author Craig R. McClanahan * @author Costin Manolache
*/ publicclass Registry implements RegistryMBean, MBeanRegistration {
/** * The Log instance to which we will write our log messages.
*/ privatestaticfinal Log log = LogFactory.getLog(Registry.class); privatestaticfinal StringManager sm = StringManager.getManager(Registry.class);
// Support for the factory methods
/** * The registry instance created by our factory method the first time it is * called.
*/ privatestatic Registry registry = null;
// Per registry fields
/** * The <code>MBeanServer</code> instance that we will use to register * management beans.
*/ privatevolatile MBeanServer server = null; privatefinal Object serverLock = new Object();
/** * The set of ManagedBean instances for the beans this registry knows about, * keyed by name.
*/ private Map<String, ManagedBean> descriptors = new HashMap<>();
/** * List of managed beans, keyed by class name
*/ private Map<String, ManagedBean> descriptorsByClass = new HashMap<>();
// map to avoid duplicated searching or loading descriptors private Map<String, URL> searchedPaths = new HashMap<>();
private Object guard;
// Id - small ints to use array access. No reset on stop() // Used for notifications privatefinal Hashtable<String, Hashtable<String, Integer>> idDomains = new Hashtable<>(); privatefinal Hashtable<String, int[]> ids = new Hashtable<>();
/** * Lifecycle method - clean up the registry metadata. Called from * resetMetadata(). * * @since 1.1
*/
@Override publicvoid stop() {
descriptorsByClass = new HashMap<>();
descriptors = new HashMap<>();
searchedPaths = new HashMap<>();
}
/** * Register a bean by creating a modeler mbean and adding it to the * MBeanServer. * * If metadata is not loaded, we'll look up and read a file named * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package * or parent. * * If the bean is an instance of DynamicMBean. it's metadata will be * converted to a model mbean and we'll wrap it - so modeler services will * be supported * * If the metadata is still not found, introspection will be used to extract * it automatically. * * If an mbean is already registered under this name, it'll be first * unregistered. * * If the component implements MBeanRegistration, the methods will be * called. If the method has a method "setRegistry" that takes a * RegistryMBean as parameter, it'll be called with the current registry. * * * @param bean Object to be registered * @param oname Name used for registration * @param type The type of the mbean, as declared in mbeans-descriptors. If * null, the name of the class will be used. This can be used as * a hint or by subclasses. * @throws Exception if a registration error occurred * @since 1.1
*/
@Override publicvoid registerComponent(Object bean, String oname, String type) throws Exception {
registerComponent(bean, new ObjectName(oname), type);
}
/** * Unregister a component. We'll first check if it is registered, and mask * all errors. This is mostly a helper. * * @param oname Name used for unregistration * * @since 1.1
*/
@Override publicvoid unregisterComponent(String oname) { try {
unregisterComponent(new ObjectName(oname));
} catch (MalformedObjectNameException e) {
log.info(sm.getString("registry.objectNameCreateError"), e);
}
}
/** * Invoke a operation on a list of mbeans. Can be used to implement * lifecycle operations. * * @param mbeans list of ObjectName on which we'll invoke the operations * @param operation Name of the operation ( init, start, stop, etc) * @param failFirst If false, exceptions will be ignored * @throws Exception Error invoking operation * @since 1.1
*/
@Override publicvoid invoke(List<ObjectName> mbeans, String operation, boolean failFirst) throws Exception {
if (mbeans == null) { return;
} for (ObjectName current : mbeans) { try { if (current == null) { continue;
} if (getMethodInfo(current, operation) == null) { continue;
}
getMBeanServer().invoke(current, operation, new Object[] {}, new String[] {});
// -------------------- ID registry --------------------
/** * Return an int ID for faster access. Will be used for notifications and * for other operations we want to optimize. * * @param domain Namespace * @param name Type of the notification * @return A unique id for the domain:name combination * @since 1.1
*/
@Override publicsynchronizedint getId(String domain, String name) { if (domain == null) {
domain = "";
}
Hashtable<String, Integer> domainTable = idDomains.computeIfAbsent(domain, k -> new Hashtable<>()); if (name == null) {
name = "";
}
Integer i = domainTable.get(name);
if (i != null) { return i.intValue();
}
int[] id = ids.computeIfAbsent(domain, k -> newint[1]); int code = id[0]++;
domainTable.put(name, Integer.valueOf(code)); return code;
}
// -------------------- Metadata -------------------- // methods from 1.0
/** * Add a new bean metadata to the set of beans known to this registry. This * is used by internal components. * * @param bean The managed bean to be added * @since 1.0
*/ publicvoid addManagedBean(ManagedBean bean) { // XXX Use group + name
descriptors.put(bean.getName(), bean); if (bean.getType() != null) {
descriptorsByClass.put(bean.getType(), bean);
}
}
/** * Find and return the managed bean definition for the specified bean name, * if any; otherwise return <code>null</code>. * * @param name Name of the managed bean to be returned. Since 1.1, both * short names or the full name of the class can be used. * @return the managed bean * @since 1.0
*/ public ManagedBean findManagedBean(String name) { // XXX Group ?? Use Group + Type
ManagedBean mb = descriptors.get(name); if (mb == null) {
mb = descriptorsByClass.get(name);
} return mb;
}
/** * Get the type of an attribute of the object, from the metadata. * * @param oname The bean name * @param attName The attribute name * @return null if metadata about the attribute is not found * @since 1.1
*/ public String getType(ObjectName oname, String attName) {
String type = null;
MBeanInfo info = null; try {
info = getMBeanServer().getMBeanInfo(oname);
} catch (Exception e) {
log.info(sm.getString("registry.noMetadata", oname)); returnnull;
}
MBeanAttributeInfo attInfo[] = info.getAttributes(); for (MBeanAttributeInfo mBeanAttributeInfo : attInfo) { if (attName.equals(mBeanAttributeInfo.getName())) {
type = mBeanAttributeInfo.getType(); return type;
}
} returnnull;
}
/** * Find the operation info for a method * * @param oname The bean name * @param opName The operation name * @return the operation info for the specified operation
*/ public MBeanOperationInfo getMethodInfo(ObjectName oname, String opName) {
MBeanInfo info = null; try {
info = getMBeanServer().getMBeanInfo(oname);
} catch (Exception e) {
log.info(sm.getString("registry.noMetadata", oname)); returnnull;
}
MBeanOperationInfo attInfo[] = info.getOperations(); for (MBeanOperationInfo mBeanOperationInfo : attInfo) { if (opName.equals(mBeanOperationInfo.getName())) { return mBeanOperationInfo;
}
} returnnull;
}
/** * Find the operation info for a method. * * @param oname The bean name * @param opName The operation name * @param argCount The number of arguments to the method * @return the operation info for the specified operation * @throws InstanceNotFoundException If the object name is not bound to an MBean
*/ public MBeanOperationInfo getMethodInfo(ObjectName oname, String opName, int argCount) throws InstanceNotFoundException
{
MBeanInfo info = null; try {
info = getMBeanServer().getMBeanInfo(oname);
} catch (InstanceNotFoundException infe) { throw infe;
} catch (Exception e) {
log.warn(sm.getString("registry.noMetadata", oname), e); returnnull;
}
MBeanOperationInfo attInfo[] = info.getOperations(); for (MBeanOperationInfo mBeanOperationInfo : attInfo) { if (opName.equals(mBeanOperationInfo.getName())
&& argCount == mBeanOperationInfo.getSignature().length) { return mBeanOperationInfo;
}
} returnnull;
}
/** * Unregister a component. This is just a helper that avoids exceptions by * checking if the mbean is already registered * * @param oname The bean name
*/ publicvoid unregisterComponent(ObjectName oname) { try { if (oname != null && getMBeanServer().isRegistered(oname)) {
getMBeanServer().unregisterMBean(oname);
}
} catch (Throwable t) {
log.error(sm.getString("registry.unregisterError"), t);
}
}
/** * Factory method to create (if necessary) and return our * <code>MBeanServer</code> instance. * * @return the MBean server
*/ public MBeanServer getMBeanServer() { if (server == null) { synchronized (serverLock) { if (server == null) { long t1 = System.currentTimeMillis(); if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
server = MBeanServerFactory.findMBeanServer(null).get(0); if (log.isDebugEnabled()) {
log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1));
}
} else {
server = ManagementFactory.getPlatformMBeanServer(); if (log.isDebugEnabled()) {
log.debug("Created MBeanServer" + (System.currentTimeMillis() - t1));
}
}
}
}
} return server;
}
/** * Find or load metadata. * * @param bean The bean * @param beanClass The bean class * @param type The registry type * @return the managed bean * @throws Exception An error occurred
*/ public ManagedBean findManagedBean(Object bean, Class<?> beanClass, String type) throws Exception {
// first look for existing descriptor
ManagedBean managed = findManagedBean(type);
// Search for a descriptor in the same package if (managed == null) { // check package and parent packages if (log.isDebugEnabled()) {
log.debug("Looking for descriptor ");
}
findDescriptor(beanClass, type);
managed = findManagedBean(type);
}
// Still not found - use introspection if (managed == null) { if (log.isDebugEnabled()) {
log.debug("Introspecting ");
}
/** * Convert a string to object, based on type. Used by several * components. We could provide some pluggability. It is here to keep things * consistent and avoid duplication in other tasks * * @param type Fully qualified class name of the resulting value * @param value String value to be converted * @return Converted value
*/ public Object convertValue(String type, String value) {
Object objValue = value;
/** * Lookup the component descriptor in the package and in the parent * packages. * * @param packageName The package name * @param classLoader The class loader
*/ publicvoid loadDescriptors(String packageName, ClassLoader classLoader) {
String res = packageName.replace('.', '/');
if (log.isTraceEnabled()) {
log.trace("Finding descriptor " + res);
}
if (searchedPaths.get(packageName) != null) { return;
}
String descriptors = res + "/mbeans-descriptors.xml";
URL dURL = classLoader.getResource(descriptors);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.