0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.tomcat.util.modeler;
0019:
0020: import java.io.File;
0021: import java.io.FileInputStream;
0022: import java.io.InputStream;
0023: import java.net.URL;
0024: import java.util.ArrayList;
0025: import java.util.HashMap;
0026: import java.util.Hashtable;
0027: import java.util.Iterator;
0028: import java.util.List;
0029:
0030: import javax.management.DynamicMBean;
0031: import javax.management.MBeanAttributeInfo;
0032: import javax.management.MBeanInfo;
0033: import javax.management.MBeanOperationInfo;
0034: import javax.management.MBeanRegistration;
0035: import javax.management.MBeanServer;
0036: import javax.management.MBeanServerFactory;
0037: import javax.management.MalformedObjectNameException;
0038: import javax.management.ObjectName;
0039:
0040: import org.apache.juli.logging.Log;
0041: import org.apache.juli.logging.LogFactory;
0042: import org.apache.tomcat.util.modeler.modules.ModelerSource;
0043:
0044: /*
0045: Issues:
0046: - exceptions - too many "throws Exception"
0047: - double check the interfaces
0048: - start removing the use of the experimental methods in tomcat, then remove
0049: the methods ( before 1.1 final )
0050: - is the security enough to prevent Registry beeing used to avoid the permission
0051: checks in the mbean server ?
0052: */
0053:
0054: /**
0055: * Registry for modeler MBeans.
0056: *
0057: * This is the main entry point into modeler. It provides methods to create
0058: * and manipulate model mbeans and simplify their use.
0059: *
0060: * Starting with version 1.1, this is no longer a singleton and the static
0061: * methods are strongly deprecated. In a container environment we can expect
0062: * different applications to use different registries.
0063: *
0064: * This class is itself an mbean.
0065: *
0066: * IMPORTANT: public methods not marked with @since x.x are experimental or
0067: * internal. Should not be used.
0068: *
0069: * @author Craig R. McClanahan
0070: * @author Costin Manolache
0071: */
0072: public class Registry implements RegistryMBean, MBeanRegistration {
0073: /**
0074: * The Log instance to which we will write our log messages.
0075: */
0076: private static Log log = LogFactory.getLog(Registry.class);
0077:
0078: // Support for the factory methods
0079:
0080: /** Will be used to isolate different apps and enhance security.
0081: */
0082: private static HashMap perLoaderRegistries = null;
0083:
0084: /**
0085: * The registry instance created by our factory method the first time
0086: * it is called.
0087: */
0088: private static Registry registry = null;
0089:
0090: // Per registy fields
0091:
0092: /**
0093: * The <code>MBeanServer</code> instance that we will use to register
0094: * management beans.
0095: */
0096: private MBeanServer server = null;
0097:
0098: /**
0099: * The set of ManagedBean instances for the beans this registry
0100: * knows about, keyed by name.
0101: */
0102: private HashMap descriptors = new HashMap();
0103:
0104: /** List of managed byeans, keyed by class name
0105: */
0106: private HashMap descriptorsByClass = new HashMap();
0107:
0108: // map to avoid duplicated searching or loading descriptors
0109: private HashMap searchedPaths = new HashMap();
0110:
0111: private Object guard;
0112:
0113: // Id - small ints to use array access. No reset on stop()
0114: // Used for notifications
0115: private Hashtable idDomains = new Hashtable();
0116: private Hashtable ids = new Hashtable();
0117:
0118: // ----------------------------------------------------------- Constructors
0119:
0120: /**
0121: */
0122: public Registry() {
0123: super ();
0124: }
0125:
0126: // -------------------- Static methods --------------------
0127: // Factories
0128:
0129: /**
0130: * Factory method to create (if necessary) and return our
0131: * <code>Registry</code> instance.
0132: *
0133: * Use this method to obtain a Registry - all other static methods
0134: * are deprecated and shouldn't be used.
0135: *
0136: * The current version uses a static - future versions could use
0137: * the thread class loader.
0138: *
0139: * @param key Support for application isolation. If null, the context class
0140: * loader will be used ( if setUseContextClassLoader is called ) or the
0141: * default registry is returned.
0142: * @param guard Prevent access to the registry by untrusted components
0143: *
0144: * @since 1.1
0145: */
0146: public synchronized static Registry getRegistry(Object key,
0147: Object guard) {
0148: Registry localRegistry;
0149: if (perLoaderRegistries != null) {
0150: if (key == null)
0151: key = Thread.currentThread().getContextClassLoader();
0152: if (key != null) {
0153: localRegistry = (Registry) perLoaderRegistries.get(key);
0154: if (localRegistry == null) {
0155: localRegistry = new Registry();
0156: // localRegistry.key=key;
0157: localRegistry.guard = guard;
0158: perLoaderRegistries.put(key, localRegistry);
0159: return localRegistry;
0160: }
0161: if (localRegistry.guard != null
0162: && localRegistry.guard != guard) {
0163: return null; // XXX Should I throw a permission ex ?
0164: }
0165: return localRegistry;
0166: }
0167: }
0168:
0169: // static
0170: if (registry == null) {
0171: registry = new Registry();
0172: }
0173: if (registry.guard != null && registry.guard != guard) {
0174: return null;
0175: }
0176: return (registry);
0177: }
0178:
0179: /**
0180: * Allow containers to isolate apps. Can be called only once.
0181: * It is highly recommended you call this method if using Registry in
0182: * a container environment. The default is false for backward compatibility
0183: *
0184: * @param enable
0185: * @since 1.1
0186: */
0187: public static void setUseContextClassLoader(boolean enable) {
0188: if (enable) {
0189: perLoaderRegistries = new HashMap();
0190: }
0191: }
0192:
0193: // -------------------- Generic methods --------------------
0194:
0195: /** Lifecycle method - clean up the registry metadata.
0196: * Called from resetMetadata().
0197: *
0198: * @since 1.1
0199: */
0200: public void stop() {
0201: descriptorsByClass = new HashMap();
0202: descriptors = new HashMap();
0203: searchedPaths = new HashMap();
0204: }
0205:
0206: /**
0207: * Load an extended mlet file. The source can be an URL, File or
0208: * InputStream.
0209: *
0210: * All mbeans will be instantiated, registered and the attributes will be
0211: * set. The result is a list of ObjectNames.
0212: *
0213: * @param source InputStream or URL of the file
0214: * @param cl ClassLoader to be used to load the mbeans, or null to use the
0215: * default JMX mechanism ( i.e. all registered loaders )
0216: * @return List of ObjectName for the loaded mbeans
0217: * @throws Exception
0218: *
0219: * @since 1.1
0220: */
0221: public List loadMBeans(Object source, ClassLoader cl)
0222: throws Exception {
0223: return load("MbeansSource", source, null);
0224: }
0225:
0226: /** Load descriptors. The source can be a File or URL or InputStream for the
0227: * descriptors file. In the case of File and URL, if the extension is ".ser"
0228: * a serialized version will be loaded.
0229: *
0230: * This method should be used to explicitely load metadata - but this is not
0231: * required in most cases. The registerComponent() method will find metadata
0232: * in the same pacakge.
0233: *
0234: * @param source
0235: */
0236: public void loadMetadata(Object source) throws Exception {
0237: loadDescriptors(null, source, null);
0238: }
0239:
0240: /** Register a bean by creating a modeler mbean and adding it to the
0241: * MBeanServer.
0242: *
0243: * If metadata is not loaded, we'll look up and read a file named
0244: * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package
0245: * or parent.
0246: *
0247: * If the bean is an instance of DynamicMBean. it's metadata will be converted
0248: * to a model mbean and we'll wrap it - so modeler services will be supported
0249: *
0250: * If the metadata is still not found, introspection will be used to extract
0251: * it automatically.
0252: *
0253: * If an mbean is already registered under this name, it'll be first
0254: * unregistered.
0255: *
0256: * If the component implements MBeanRegistration, the methods will be called.
0257: * If the method has a method "setRegistry" that takes a RegistryMBean as
0258: * parameter, it'll be called with the current registry.
0259: *
0260: *
0261: * @param bean Object to be registered
0262: * @param oname Name used for registration
0263: * @param type The type of the mbean, as declared in mbeans-descriptors. If
0264: * null, the name of the class will be used. This can be used as a hint or
0265: * by subclasses.
0266: *
0267: * @since 1.1
0268: */
0269: public void registerComponent(Object bean, String oname, String type)
0270: throws Exception {
0271: registerComponent(bean, new ObjectName(oname), type);
0272: }
0273:
0274: /** Unregister a component. We'll first check if it is registered,
0275: * and mask all errors. This is mostly a helper.
0276: *
0277: * @param oname
0278: *
0279: * @since 1.1
0280: */
0281: public void unregisterComponent(String oname) {
0282: try {
0283: unregisterComponent(new ObjectName(oname));
0284: } catch (MalformedObjectNameException e) {
0285: log.info("Error creating object name " + e);
0286: }
0287: }
0288:
0289: /** Invoke a operation on a list of mbeans. Can be used to implement
0290: * lifecycle operations.
0291: *
0292: * @param mbeans list of ObjectName on which we'll invoke the operations
0293: * @param operation Name of the operation ( init, start, stop, etc)
0294: * @param failFirst If false, exceptions will be ignored
0295: * @throws Exception
0296: * @since 1.1
0297: */
0298: public void invoke(List mbeans, String operation, boolean failFirst)
0299: throws Exception {
0300: if (mbeans == null) {
0301: return;
0302: }
0303: Iterator itr = mbeans.iterator();
0304: while (itr.hasNext()) {
0305: Object current = itr.next();
0306: ObjectName oN = null;
0307: try {
0308: if (current instanceof ObjectName) {
0309: oN = (ObjectName) current;
0310: }
0311: if (current instanceof String) {
0312: oN = new ObjectName((String) current);
0313: }
0314: if (oN == null) {
0315: continue;
0316: }
0317: if (getMethodInfo(oN, operation) == null) {
0318: continue;
0319: }
0320: getMBeanServer().invoke(oN, operation, new Object[] {},
0321: new String[] {});
0322:
0323: } catch (Exception t) {
0324: if (failFirst)
0325: throw t;
0326: log.info("Error initializing " + current + " "
0327: + t.toString());
0328: }
0329: }
0330: }
0331:
0332: // -------------------- ID registry --------------------
0333:
0334: /** Return an int ID for faster access. Will be used for notifications
0335: * and for other operations we want to optimize.
0336: *
0337: * @param domain Namespace
0338: * @param name Type of the notification
0339: * @return An unique id for the domain:name combination
0340: * @since 1.1
0341: */
0342: public synchronized int getId(String domain, String name) {
0343: if (domain == null) {
0344: domain = "";
0345: }
0346: Hashtable domainTable = (Hashtable) idDomains.get(domain);
0347: if (domainTable == null) {
0348: domainTable = new Hashtable();
0349: idDomains.put(domain, domainTable);
0350: }
0351: if (name == null) {
0352: name = "";
0353: }
0354: Integer i = (Integer) domainTable.get(name);
0355:
0356: if (i != null) {
0357: return i.intValue();
0358: }
0359:
0360: int id[] = (int[]) ids.get(domain);
0361: if (id == null) {
0362: id = new int[1];
0363: ids.put(domain, id);
0364: }
0365: int code = id[0]++;
0366: domainTable.put(name, new Integer(code));
0367: return code;
0368: }
0369:
0370: // -------------------- Metadata --------------------
0371: // methods from 1.0
0372:
0373: /**
0374: * Add a new bean metadata to the set of beans known to this registry.
0375: * This is used by internal components.
0376: *
0377: * @param bean The managed bean to be added
0378: * @since 1.0
0379: */
0380: public void addManagedBean(ManagedBean bean) {
0381: // XXX Use group + name
0382: descriptors.put(bean.getName(), bean);
0383: if (bean.getType() != null) {
0384: descriptorsByClass.put(bean.getType(), bean);
0385: }
0386: }
0387:
0388: /**
0389: * Find and return the managed bean definition for the specified
0390: * bean name, if any; otherwise return <code>null</code>.
0391: *
0392: * @param name Name of the managed bean to be returned. Since 1.1, both
0393: * short names or the full name of the class can be used.
0394: * @since 1.0
0395: */
0396: public ManagedBean findManagedBean(String name) {
0397: // XXX Group ?? Use Group + Type
0398: ManagedBean mb = ((ManagedBean) descriptors.get(name));
0399: if (mb == null)
0400: mb = (ManagedBean) descriptorsByClass.get(name);
0401: return mb;
0402: }
0403:
0404: /**
0405: * Return the set of bean names for all managed beans known to
0406: * this registry.
0407: *
0408: * @since 1.0
0409: */
0410: public String[] findManagedBeans() {
0411: return ((String[]) descriptors.keySet().toArray(new String[0]));
0412: }
0413:
0414: /**
0415: * Return the set of bean names for all managed beans known to
0416: * this registry that belong to the specified group.
0417: *
0418: * @param group Name of the group of interest, or <code>null</code>
0419: * to select beans that do <em>not</em> belong to a group
0420: * @since 1.0
0421: */
0422: public String[] findManagedBeans(String group) {
0423:
0424: ArrayList results = new ArrayList();
0425: Iterator items = descriptors.values().iterator();
0426: while (items.hasNext()) {
0427: ManagedBean item = (ManagedBean) items.next();
0428: if ((group == null) && (item.getGroup() == null)) {
0429: results.add(item.getName());
0430: } else if (group.equals(item.getGroup())) {
0431: results.add(item.getName());
0432: }
0433: }
0434: String values[] = new String[results.size()];
0435: return ((String[]) results.toArray(values));
0436:
0437: }
0438:
0439: /**
0440: * Remove an existing bean from the set of beans known to this registry.
0441: *
0442: * @param bean The managed bean to be removed
0443: * @since 1.0
0444: */
0445: public void removeManagedBean(ManagedBean bean) {
0446: // TODO: change this to use group/name
0447: descriptors.remove(bean.getName());
0448: descriptorsByClass.remove(bean.getType());
0449: }
0450:
0451: // -------------------- Deprecated 1.0 methods --------------------
0452:
0453: /**
0454: * Factory method to create (if necessary) and return our
0455: * <code>MBeanServer</code> instance.
0456: *
0457: * @since 1.0
0458: * @deprecated Use the instance method
0459: */
0460: public static MBeanServer getServer() {
0461: return Registry.getRegistry().getMBeanServer();
0462: }
0463:
0464: /**
0465: * Set the <code>MBeanServer</code> to be utilized for our
0466: * registered management beans.
0467: *
0468: * @param mbeanServer The new <code>MBeanServer</code> instance
0469: * @since 1.0
0470: * @deprecated Use the instance method
0471: */
0472: public static void setServer(MBeanServer mbeanServer) {
0473: Registry.getRegistry().setMBeanServer(mbeanServer);
0474: }
0475:
0476: /**
0477: * Load the registry from the XML input found in the specified input
0478: * stream.
0479: *
0480: * @param stream InputStream containing the registry configuration
0481: * information
0482: *
0483: * @exception Exception if any parsing or processing error occurs
0484: * @deprecated use normal class method instead
0485: * @since 1.0
0486: */
0487: public static void loadRegistry(InputStream stream)
0488: throws Exception {
0489: Registry registry = getRegistry();
0490: registry.loadMetadata(stream);
0491: }
0492:
0493: /** Get a "singelton" registry, or one per thread if setUseContextLoader
0494: * was called
0495: *
0496: * @deprecated Not enough info - use the method that takes CL and domain
0497: * @since 1.0
0498: */
0499: public synchronized static Registry getRegistry() {
0500: return getRegistry(null, null);
0501: }
0502:
0503: // -------------------- Helpers --------------------
0504:
0505: /** Get the type of an attribute of the object, from the metadata.
0506: *
0507: * @param oname
0508: * @param attName
0509: * @return null if metadata about the attribute is not found
0510: * @since 1.1
0511: */
0512: public String getType(ObjectName oname, String attName) {
0513: String type = null;
0514: MBeanInfo info = null;
0515: try {
0516: info = server.getMBeanInfo(oname);
0517: } catch (Exception e) {
0518: log.info("Can't find metadata for object" + oname);
0519: return null;
0520: }
0521:
0522: MBeanAttributeInfo attInfo[] = info.getAttributes();
0523: for (int i = 0; i < attInfo.length; i++) {
0524: if (attName.equals(attInfo[i].getName())) {
0525: type = attInfo[i].getType();
0526: return type;
0527: }
0528: }
0529: return null;
0530: }
0531:
0532: /** Find the operation info for a method
0533: *
0534: * @param oname
0535: * @param opName
0536: * @return the operation info for the specified operation
0537: */
0538: public MBeanOperationInfo getMethodInfo(ObjectName oname,
0539: String opName) {
0540: String type = null;
0541: MBeanInfo info = null;
0542: try {
0543: info = server.getMBeanInfo(oname);
0544: } catch (Exception e) {
0545: log.info("Can't find metadata " + oname);
0546: return null;
0547: }
0548: MBeanOperationInfo attInfo[] = info.getOperations();
0549: for (int i = 0; i < attInfo.length; i++) {
0550: if (opName.equals(attInfo[i].getName())) {
0551: return attInfo[i];
0552: }
0553: }
0554: return null;
0555: }
0556:
0557: /** Unregister a component. This is just a helper that
0558: * avoids exceptions by checking if the mbean is already registered
0559: *
0560: * @param oname
0561: */
0562: public void unregisterComponent(ObjectName oname) {
0563: try {
0564: if (getMBeanServer().isRegistered(oname)) {
0565: getMBeanServer().unregisterMBean(oname);
0566: }
0567: } catch (Throwable t) {
0568: log.error("Error unregistering mbean ", t);
0569: }
0570: }
0571:
0572: /**
0573: * Factory method to create (if necessary) and return our
0574: * <code>MBeanServer</code> instance.
0575: *
0576: */
0577: public synchronized MBeanServer getMBeanServer() {
0578: long t1 = System.currentTimeMillis();
0579:
0580: if (server == null) {
0581: if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
0582: server = (MBeanServer) MBeanServerFactory
0583: .findMBeanServer(null).get(0);
0584: if (log.isDebugEnabled()) {
0585: log.debug("Using existing MBeanServer "
0586: + (System.currentTimeMillis() - t1));
0587: }
0588: } else {
0589: server = MBeanServerFactory.createMBeanServer();
0590: if (log.isDebugEnabled()) {
0591: log.debug("Creating MBeanServer"
0592: + (System.currentTimeMillis() - t1));
0593: }
0594: }
0595: }
0596: return (server);
0597: }
0598:
0599: /** Find or load metadata.
0600: */
0601: public ManagedBean findManagedBean(Object bean, Class beanClass,
0602: String type) throws Exception {
0603: if (bean != null && beanClass == null) {
0604: beanClass = bean.getClass();
0605: }
0606:
0607: if (type == null) {
0608: type = beanClass.getName();
0609: }
0610:
0611: // first look for existing descriptor
0612: ManagedBean managed = findManagedBean(type);
0613:
0614: // Search for a descriptor in the same package
0615: if (managed == null) {
0616: // check package and parent packages
0617: if (log.isDebugEnabled()) {
0618: log.debug("Looking for descriptor ");
0619: }
0620: findDescriptor(beanClass, type);
0621:
0622: managed = findManagedBean(type);
0623: }
0624:
0625: if (bean instanceof DynamicMBean) {
0626: if (log.isDebugEnabled()) {
0627: log.debug("Dynamic mbean support ");
0628: }
0629: // Dynamic mbean
0630: loadDescriptors("MbeansDescriptorsDynamicMBeanSource",
0631: bean, type);
0632:
0633: managed = findManagedBean(type);
0634: }
0635:
0636: // Still not found - use introspection
0637: if (managed == null) {
0638: if (log.isDebugEnabled()) {
0639: log.debug("Introspecting ");
0640: }
0641:
0642: // introspection
0643: loadDescriptors("MbeansDescriptorsIntrospectionSource",
0644: beanClass, type);
0645:
0646: managed = findManagedBean(type);
0647: if (managed == null) {
0648: log.warn("No metadata found for " + type);
0649: return null;
0650: }
0651: managed.setName(type);
0652: addManagedBean(managed);
0653: }
0654: return managed;
0655: }
0656:
0657: /** EXPERIMENTAL Convert a string to object, based on type. Used by several
0658: * components. We could provide some pluggability. It is here to keep
0659: * things consistent and avoid duplication in other tasks
0660: *
0661: * @param type Fully qualified class name of the resulting value
0662: * @param value String value to be converted
0663: * @return Converted value
0664: */
0665: public Object convertValue(String type, String value) {
0666: Object objValue = value;
0667:
0668: if (type == null || "java.lang.String".equals(type)) {
0669: // string is default
0670: objValue = value;
0671: } else if ("javax.management.ObjectName".equals(type)
0672: || "ObjectName".equals(type)) {
0673: try {
0674: objValue = new ObjectName(value);
0675: } catch (MalformedObjectNameException e) {
0676: return null;
0677: }
0678: } else if ("java.lang.Integer".equals(type)
0679: || "int".equals(type)) {
0680: objValue = new Integer(value);
0681: } else if ("java.lang.Long".equals(type) || "long".equals(type)) {
0682: objValue = new Long(value);
0683: } else if ("java.lang.Boolean".equals(type)
0684: || "boolean".equals(type)) {
0685: objValue = new Boolean(value);
0686: }
0687: return objValue;
0688: }
0689:
0690: /** Experimental.
0691: *
0692: * @param sourceType
0693: * @param source
0694: * @param param
0695: * @return List of descriptors
0696: * @throws Exception
0697: * @deprecated bad interface, mixing of metadata and mbeans
0698: */
0699: public List load(String sourceType, Object source, String param)
0700: throws Exception {
0701: if (log.isTraceEnabled()) {
0702: log.trace("load " + source);
0703: }
0704: String location = null;
0705: String type = null;
0706: Object inputsource = null;
0707:
0708: if (source instanceof DynamicMBean) {
0709: sourceType = "MbeansDescriptorsDynamicMBeanSource";
0710: inputsource = source;
0711: } else if (source instanceof URL) {
0712: URL url = (URL) source;
0713: location = url.toString();
0714: type = param;
0715: inputsource = url.openStream();
0716: if (sourceType == null) {
0717: sourceType = sourceTypeFromExt(location);
0718: }
0719: } else if (source instanceof File) {
0720: location = ((File) source).getAbsolutePath();
0721: inputsource = new FileInputStream((File) source);
0722: type = param;
0723: if (sourceType == null) {
0724: sourceType = sourceTypeFromExt(location);
0725: }
0726: } else if (source instanceof InputStream) {
0727: type = param;
0728: inputsource = source;
0729: } else if (source instanceof Class) {
0730: location = ((Class) source).getName();
0731: type = param;
0732: inputsource = source;
0733: if (sourceType == null) {
0734: sourceType = "MbeansDescriptorsIntrospectionSource";
0735: }
0736: }
0737:
0738: if (sourceType == null) {
0739: sourceType = "MbeansDescriptorsDigesterSource";
0740: }
0741: ModelerSource ds = getModelerSource(sourceType);
0742: List mbeans = ds.loadDescriptors(this , location, type,
0743: inputsource);
0744:
0745: return mbeans;
0746: }
0747:
0748: private String sourceTypeFromExt(String s) {
0749: if (s.endsWith(".ser")) {
0750: return "MbeansDescriptorsSerSource";
0751: } else if (s.endsWith(".xml")) {
0752: return "MbeansDescriptorsDigesterSource";
0753: }
0754: return null;
0755: }
0756:
0757: /** Register a component
0758: * XXX make it private
0759: *
0760: * @param bean
0761: * @param oname
0762: * @param type
0763: * @throws Exception
0764: */
0765: public void registerComponent(Object bean, ObjectName oname,
0766: String type) throws Exception {
0767: if (log.isDebugEnabled()) {
0768: log.debug("Managed= " + oname);
0769: }
0770:
0771: if (bean == null) {
0772: log.error("Null component " + oname);
0773: return;
0774: }
0775:
0776: try {
0777: if (type == null) {
0778: type = bean.getClass().getName();
0779: }
0780:
0781: ManagedBean managed = findManagedBean(bean.getClass(), type);
0782:
0783: // The real mbean is created and registered
0784: DynamicMBean mbean = managed.createMBean(bean);
0785:
0786: if (getMBeanServer().isRegistered(oname)) {
0787: if (log.isDebugEnabled()) {
0788: log.debug("Unregistering existing component "
0789: + oname);
0790: }
0791: getMBeanServer().unregisterMBean(oname);
0792: }
0793:
0794: getMBeanServer().registerMBean(mbean, oname);
0795: } catch (Exception ex) {
0796: log.error("Error registering " + oname, ex);
0797: throw ex;
0798: }
0799: }
0800:
0801: /** Lookup the component descriptor in the package and
0802: * in the parent packages.
0803: *
0804: * @param packageName
0805: */
0806: public void loadDescriptors(String packageName,
0807: ClassLoader classLoader) {
0808: String res = packageName.replace('.', '/');
0809:
0810: if (log.isTraceEnabled()) {
0811: log.trace("Finding descriptor " + res);
0812: }
0813:
0814: if (searchedPaths.get(packageName) != null) {
0815: return;
0816: }
0817: String descriptors = res + "/mbeans-descriptors.ser";
0818:
0819: URL dURL = classLoader.getResource(descriptors);
0820:
0821: if (dURL == null) {
0822: descriptors = res + "/mbeans-descriptors.xml";
0823: dURL = classLoader.getResource(descriptors);
0824: }
0825: if (dURL == null) {
0826: return;
0827: }
0828:
0829: log.debug("Found " + dURL);
0830: searchedPaths.put(packageName, dURL);
0831: try {
0832: if (descriptors.endsWith(".xml"))
0833: loadDescriptors("MbeansDescriptorsDigesterSource",
0834: dURL, null);
0835: else
0836: loadDescriptors("MbeansDescriptorsSerSource", dURL,
0837: null);
0838: return;
0839: } catch (Exception ex) {
0840: log.error("Error loading " + dURL);
0841: }
0842:
0843: return;
0844: }
0845:
0846: /** Experimental. Will become private, some code may still use it
0847: *
0848: * @param sourceType
0849: * @param source
0850: * @param param
0851: * @throws Exception
0852: * @deprecated
0853: */
0854: public void loadDescriptors(String sourceType, Object source,
0855: String param) throws Exception {
0856: List mbeans = load(sourceType, source, param);
0857: if (mbeans == null)
0858: return;
0859:
0860: Iterator itr = mbeans.iterator();
0861: while (itr.hasNext()) {
0862: Object mb = itr.next();
0863: if (mb instanceof ManagedBean) {
0864: addManagedBean((ManagedBean) mb);
0865: }
0866: }
0867: }
0868:
0869: /** Lookup the component descriptor in the package and
0870: * in the parent packages.
0871: *
0872: * @param beanClass
0873: * @param type
0874: */
0875: private void findDescriptor(Class beanClass, String type) {
0876: if (type == null) {
0877: type = beanClass.getName();
0878: }
0879: ClassLoader classLoader = null;
0880: if (beanClass != null) {
0881: classLoader = beanClass.getClassLoader();
0882: }
0883: if (classLoader == null) {
0884: classLoader = Thread.currentThread()
0885: .getContextClassLoader();
0886: }
0887: if (classLoader == null) {
0888: classLoader = this .getClass().getClassLoader();
0889: }
0890:
0891: String className = type;
0892: String pkg = className;
0893: while (pkg.indexOf(".") > 0) {
0894: int lastComp = pkg.lastIndexOf(".");
0895: if (lastComp <= 0)
0896: return;
0897: pkg = pkg.substring(0, lastComp);
0898: if (searchedPaths.get(pkg) != null) {
0899: return;
0900: }
0901: loadDescriptors(pkg, classLoader);
0902: }
0903: return;
0904: }
0905:
0906: private ModelerSource getModelerSource(String type)
0907: throws Exception {
0908: if (type == null)
0909: type = "MbeansDescriptorsDigesterSource";
0910: if (type.indexOf(".") < 0) {
0911: type = "org.apache.tomcat.util.modeler.modules." + type;
0912: }
0913:
0914: Class c = Class.forName(type);
0915: ModelerSource ds = (ModelerSource) c.newInstance();
0916: return ds;
0917: }
0918:
0919: // -------------------- Registration --------------------
0920:
0921: public ObjectName preRegister(MBeanServer server, ObjectName name)
0922: throws Exception {
0923: this .server = server;
0924: return name;
0925: }
0926:
0927: public void postRegister(Boolean registrationDone) {
0928: }
0929:
0930: public void preDeregister() throws Exception {
0931: }
0932:
0933: public void postDeregister() {
0934: }
0935:
0936: // -------------------- DEPRECATED METHODS --------------------
0937: // May still be used in tomcat
0938: // Never part of an official release
0939:
0940: /** Called by a registry or by the container to unload a loader
0941: * @param loader
0942: */
0943: public void unregisterRegistry(ClassLoader loader) {
0944: // XXX Cleanup ?
0945: perLoaderRegistries.remove(loader);
0946: }
0947:
0948: public ManagedBean findManagedBean(Class beanClass, String type)
0949: throws Exception {
0950: return findManagedBean(null, beanClass, type);
0951: }
0952:
0953: /**
0954: * Set the <code>MBeanServer</code> to be utilized for our
0955: * registered management beans.
0956: *
0957: * @param server The new <code>MBeanServer</code> instance
0958: */
0959: public void setMBeanServer(MBeanServer server) {
0960: this .server = server;
0961: }
0962:
0963: public void resetMetadata() {
0964: stop();
0965: }
0966:
0967: /**
0968: * Load the registry from the XML input found in the specified input
0969: * stream.
0970: *
0971: * @param source Source to be used to load. Can be an InputStream or URL.
0972: *
0973: * @exception Exception if any parsing or processing error occurs
0974: */
0975: public void loadDescriptors(Object source) throws Exception {
0976: loadDescriptors("MbeansDescriptorsDigesterSource", source, null);
0977: }
0978:
0979: /** @deprecated - may still be used in code using pre-1.1 builds
0980: */
0981: public void registerComponent(Object bean, String domain,
0982: String type, String name) throws Exception {
0983: StringBuffer sb = new StringBuffer();
0984: sb.append(domain).append(":");
0985: sb.append(name);
0986: String nameStr = sb.toString();
0987: ObjectName oname = new ObjectName(nameStr);
0988: registerComponent(bean, oname, type);
0989: }
0990:
0991: // should be removed
0992: public void unregisterComponent(String domain, String name) {
0993: try {
0994: ObjectName oname = new ObjectName(domain + ":" + name);
0995:
0996: // XXX remove from our tables.
0997: getMBeanServer().unregisterMBean(oname);
0998: } catch (Throwable t) {
0999: log.error("Error unregistering mbean ", t);
1000: }
1001: }
1002:
1003: /**
1004: * Load the registry from a cached .ser file. This is typically 2-3 times
1005: * faster than parsing the XML.
1006: *
1007: * @param source Source to be used to load. Can be an InputStream or URL.
1008: *
1009: * @exception Exception if any parsing or processing error occurs
1010: * @deprecated Loaded automatically or using a File or Url ending in .ser
1011: */
1012: public void loadCachedDescriptors(Object source) throws Exception {
1013: loadDescriptors("MbeansDescriptorsSerSource", source, null);
1014: }
1015: }
|