Quelle Registry.java
Sprache: JAVA
/*
* 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;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.management.DynamicMBean;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.modeler.modules.ModelerSource;
import org.apache.tomcat.util.res.StringManager;
/**
* 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
*/
public class Registry implements RegistryMBean, MBeanRegistration {
/**
* The Log instance to which we will write our log messages .
*/
private static final Log log = LogFactory.getLog(Registry.class );
private static final 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 .
*/
private static Registry registry = null ;
// Per registry fields
/**
* The < code > MBeanServer < / code > instance that we will use to register
* management beans .
*/
private volatile MBeanServer server = null ;
private final 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
private final Hashtable<String, Hashtable<String, Integer>> idDomains = new Hashtable<>();
private final Hashtable<String, int []> ids = new Hashtable<>();
// ----------------------------------------------------------- Constructors
protected Registry() {
super ();
}
// -------------------- Static methods --------------------
// Factories
/**
* Factory method to create ( if necessary ) and return our
* < code > Registry < / code > instance .
*
* @ param key Unused
* @ param guard Prevent access to the registry by untrusted components
*
* @ return the registry
* @ since 1 . 1
*/
public static synchronized Registry getRegistry(Object key, Object guard) {
if (registry == null ) {
registry = new Registry();
registry.guard = guard;
}
if (registry.guard != null && registry.guard != guard) {
return null ;
}
return registry;
}
public static synchronized void disableRegistry() {
if (registry == null ) {
registry = new NoDescriptorRegistry();
} else if (!(registry instanceof NoDescriptorRegistry)) {
log.warn(sm.getString("registry.noDisable" ));
}
}
// -------------------- Generic methods --------------------
/**
* Lifecycle method - clean up the registry metadata . Called from
* resetMetadata ( ) .
*
* @ since 1 . 1
*/
@Override
public void 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
public void 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
public void 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
public void 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[] {});
} catch (Exception t) {
if (failFirst) {
throw t;
}
log.info(sm.getString("registry.initError" ), t);
}
}
}
// -------------------- 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
public synchronized int 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 -> new int [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
*/
public void 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;
}
// -------------------- Helpers --------------------
/**
* 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));
return null ;
}
MBeanAttributeInfo attInfo[] = info.getAttributes();
for (MBeanAttributeInfo mBeanAttributeInfo : attInfo) {
if (attName.equals(mBeanAttributeInfo.getName())) {
type = mBeanAttributeInfo.getType();
return type;
}
}
return null ;
}
/**
* 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));
return null ;
}
MBeanOperationInfo attInfo[] = info.getOperations();
for (MBeanOperationInfo mBeanOperationInfo : attInfo) {
if (opName.equals(mBeanOperationInfo.getName())) {
return mBeanOperationInfo;
}
}
return null ;
}
/**
* 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);
return null ;
}
MBeanOperationInfo attInfo[] = info.getOperations();
for (MBeanOperationInfo mBeanOperationInfo : attInfo) {
if (opName.equals(mBeanOperationInfo.getName())
&& argCount == mBeanOperationInfo.getSignature().length) {
return mBeanOperationInfo;
}
}
return null ;
}
/**
* Unregister a component . This is just a helper that avoids exceptions by
* checking if the mbean is already registered
*
* @ param oname The bean name
*/
public void 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 {
if (bean != null && beanClass == null ) {
beanClass = bean.getClass();
}
if (type == null ) {
type = beanClass.getName();
}
// 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 " );
}
// introspection
load("MbeansDescriptorsIntrospectionSource" , beanClass, type);
managed = findManagedBean(type);
if (managed == null ) {
log.warn(sm.getString("registry.noTypeMetadata" , type));
return null ;
}
managed.setName(type);
addManagedBean(managed);
}
return managed;
}
/**
* 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;
if (type == null || "java.lang.String" .equals(type)) {
// string is default
objValue = value;
} else if ("javax.management.ObjectName" .equals(type) || "ObjectName" .equals(type)) {
try {
objValue = new ObjectName(value);
} catch (MalformedObjectNameException e) {
return null ;
}
} else if ("java.lang.Integer" .equals(type) || "int" .equals(type)) {
objValue = Integer.valueOf(value);
} else if ("java.lang.Long" .equals(type) || "long" .equals(type)) {
objValue = Long .valueOf(value);
} else if ("java.lang.Boolean" .equals(type) || "boolean" .equals(type)) {
objValue = Boolean .valueOf(value);
}
return objValue;
}
/**
* Load descriptors .
*
* @ param sourceType The source type
* @ param source The bean
* @ param param A type to load
* @ return List of descriptors
* @ throws Exception Error loading descriptors
*/
public List<ObjectName> load(String sourceType, Object source, String param) throws Exception {
if (log.isTraceEnabled()) {
log.trace("load " + source);
}
String location = null ;
String type = null ;
Object inputsource = null ;
if (source instanceof URL) {
URL url = (URL) source;
location = url.toString();
type = param;
inputsource = url.openStream();
if (sourceType == null && location.endsWith(".xml" )) {
sourceType = "MbeansDescriptorsDigesterSource" ;
}
} else if (source instanceof File) {
location = ((File) source).getAbsolutePath();
inputsource = new FileInputStream((File) source);
type = param;
if (sourceType == null && location.endsWith(".xml" )) {
sourceType = "MbeansDescriptorsDigesterSource" ;
}
} else if (source instanceof InputStream) {
type = param;
inputsource = source;
} else if (source instanceof Class <?>) {
location = ((Class <?>) source).getName();
type = param;
inputsource = source;
if (sourceType == null ) {
sourceType = "MbeansDescriptorsIntrospectionSource" ;
}
} else {
throw new IllegalArgumentException(sm.getString("registry.invalidSource" ));
}
if (sourceType == null ) {
sourceType = "MbeansDescriptorsDigesterSource" ;
}
ModelerSource ds = getModelerSource(sourceType);
List<ObjectName> mbeans = ds.loadDescriptors(this , type, inputsource);
return mbeans;
}
/**
* Register a component
*
* @ param bean The bean
* @ param oname The object name
* @ param type The registry type
* @ throws Exception Error registering component
*/
public void registerComponent(Object bean, ObjectName oname, String type) throws Exception {
if (log.isDebugEnabled()) {
log.debug("Managed= " + oname);
}
if (bean == null ) {
log.error(sm.getString("registry.nullBean" , oname));
return ;
}
try {
if (type == null ) {
type = bean.getClass().getName();
}
ManagedBean managed = findManagedBean(null , bean.getClass(), type);
// The real mbean is created and registered
DynamicMBean mbean = managed.createMBean(bean);
if (getMBeanServer().isRegistered(oname)) {
if (log.isDebugEnabled()) {
log.debug("Unregistering existing component " + oname);
}
getMBeanServer().unregisterMBean(oname);
}
getMBeanServer().registerMBean(mbean, oname);
} catch (Exception ex) {
log.error(sm.getString("registry.registerError" , oname), ex);
throw ex;
}
}
/**
* Lookup the component descriptor in the package and in the parent
* packages .
*
* @ param packageName The package name
* @ param classLoader The class loader
*/
public void 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);
if (dURL == null ) {
return ;
}
log.debug("Found " + dURL);
searchedPaths.put(packageName, dURL);
try {
load("MbeansDescriptorsDigesterSource" , dURL, null );
} catch (Exception ex) {
log.error(sm.getString("registry.loadError" , dURL));
}
}
/**
* Lookup the component descriptor in the package and in the parent
* packages .
*/
private void findDescriptor(Class <?> beanClass, String type) {
if (type == null ) {
type = beanClass.getName();
}
ClassLoader classLoader = null ;
if (beanClass != null ) {
classLoader = beanClass.getClassLoader();
}
if (classLoader == null ) {
classLoader = Thread .currentThread().getContextClassLoader();
}
if (classLoader == null ) {
classLoader = this .getClass().getClassLoader();
}
String className = type;
String pkg = className;
while (pkg.indexOf('.' ) > 0 ) {
int lastComp = pkg.lastIndexOf('.' );
if (lastComp <= 0 ) {
return ;
}
pkg = pkg.substring(0 , lastComp);
if (searchedPaths.get(pkg) != null ) {
return ;
}
loadDescriptors(pkg, classLoader);
}
}
private ModelerSource getModelerSource(String type) throws Exception {
if (type == null ) {
type = "MbeansDescriptorsDigesterSource" ;
}
if (!type.contains("." )) {
type = "org.apache.tomcat.util.modeler.modules." + type;
}
Class <?> c = Class .forName(type);
ModelerSource ds = (ModelerSource) c.getConstructor().newInstance();
return ds;
}
// -------------------- Registration --------------------
@Override
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
synchronized (serverLock) {
this .server = server;
}
return name;
}
@Override
public void postRegister(Boolean registrationDone) {
}
@Override
public void preDeregister() throws Exception {
}
@Override
public void postDeregister() {
}
}
Messung V0.5 in Prozent C=92 H=92 G=91
¤ Dauer der Verarbeitung: 0.23 Sekunden
¤
*© Formatika GbR, Deutschland
2026-10-11
Neuigkeiten
Aktuelles
Motto des Tages
letze Version des Elbe Quellennavigators
Jenseits des Üblichen ....
Besucher
Statistik
#Sources=1127926
#Domains=1947682