1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19 package org.apache.tomcat.util.modeler;
20
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.InputStream;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.List;
31
32 import javax.management.DynamicMBean;
33 import javax.management.MBeanAttributeInfo;
34 import javax.management.MBeanInfo;
35 import javax.management.MBeanOperationInfo;
36 import javax.management.MBeanRegistration;
37 import javax.management.MBeanServer;
38 import javax.management.MBeanServerFactory;
39 import javax.management.MalformedObjectNameException;
40 import javax.management.ObjectName;
41
42 import org.apache.juli.logging.Log;
43 import org.apache.juli.logging.LogFactory;
44 import org.apache.tomcat.util.modeler.modules.ModelerSource;
45
46 /*
47 Issues:
48 - exceptions - too many "throws Exception"
49 - double check the interfaces
50 - start removing the use of the experimental methods in tomcat, then remove
51 the methods ( before 1.1 final )
52 - is the security enough to prevent Registry beeing used to avoid the permission
53 checks in the mbean server ?
54 */
55
56 /**
57 * Registry for modeler MBeans.
58 *
59 * This is the main entry point into modeler. It provides methods to create
60 * and manipulate model mbeans and simplify their use.
61 *
62 * Starting with version 1.1, this is no longer a singleton and the static
63 * methods are strongly deprecated. In a container environment we can expect
64 * different applications to use different registries.
65 *
66 * This class is itself an mbean.
67 *
68 * IMPORTANT: public methods not marked with @since x.x are experimental or
69 * internal. Should not be used.
70 *
71 * @author Craig R. McClanahan
72 * @author Costin Manolache
73 */
74 public class Registry implements RegistryMBean, MBeanRegistration {
75 /**
76 * The Log instance to which we will write our log messages.
77 */
78 private static Log log = LogFactory.getLog(Registry.class);
79
80 // Support for the factory methods
81
82 /** Will be used to isolate different apps and enhance security.
83 */
84 private static HashMap perLoaderRegistries=null;
85
86 /**
87 * The registry instance created by our factory method the first time
88 * it is called.
89 */
90 private static Registry registry = null;
91
92 // Per registy fields
93
94 /**
95 * The <code>MBeanServer</code> instance that we will use to register
96 * management beans.
97 */
98 private MBeanServer server = null;
99
100 /**
101 * The set of ManagedBean instances for the beans this registry
102 * knows about, keyed by name.
103 */
104 private HashMap descriptors = new HashMap();
105
106 /** List of managed byeans, keyed by class name
107 */
108 private HashMap descriptorsByClass = new HashMap();
109
110 // map to avoid duplicated searching or loading descriptors
111 private HashMap searchedPaths=new HashMap();
112
113 private Object guard;
114
115 // Id - small ints to use array access. No reset on stop()
116 // Used for notifications
117 private Hashtable idDomains=new Hashtable();
118 private Hashtable ids=new Hashtable();
119
120
121 // ----------------------------------------------------------- Constructors
122
123 /**
124 */
125 public Registry() {
126 super();
127 }
128
129 // -------------------- Static methods --------------------
130 // Factories
131
132 /**
133 * Factory method to create (if necessary) and return our
134 * <code>Registry</code> instance.
135 *
136 * Use this method to obtain a Registry - all other static methods
137 * are deprecated and shouldn't be used.
138 *
139 * The current version uses a static - future versions could use
140 * the thread class loader.
141 *
142 * @param key Support for application isolation. If null, the context class
143 * loader will be used ( if setUseContextClassLoader is called ) or the
144 * default registry is returned.
145 * @param guard Prevent access to the registry by untrusted components
146 *
147 * @since 1.1
148 */
149 public synchronized static Registry getRegistry(Object key, Object guard) {
150 Registry localRegistry;
151 if( perLoaderRegistries!=null ) {
152 if( key==null )
153 key=Thread.currentThread().getContextClassLoader();
154 if( key != null ) {
155 localRegistry=(Registry)perLoaderRegistries.get(key);
156 if( localRegistry == null ) {
157 localRegistry=new Registry();
158 // localRegistry.key=key;
159 localRegistry.guard=guard;
160 perLoaderRegistries.put( key, localRegistry );
161 return localRegistry;
162 }
163 if( localRegistry.guard != null &&
164 localRegistry.guard != guard ) {
165 return null; // XXX Should I throw a permission ex ?
166 }
167 return localRegistry;
168 }
169 }
170
171 // static
172 if (registry == null) {
173 registry = new Registry();
174 }
175 if( registry.guard != null &&
176 registry.guard != guard ) {
177 return null;
178 }
179 return (registry);
180 }
181
182 /**
183 * Allow containers to isolate apps. Can be called only once.
184 * It is highly recommended you call this method if using Registry in
185 * a container environment. The default is false for backward compatibility
186 *
187 * @param enable
188 * @since 1.1
189 */
190 public static void setUseContextClassLoader( boolean enable ) {
191 if( enable ) {
192 perLoaderRegistries=new HashMap();
193 }
194 }
195
196 // -------------------- Generic methods --------------------
197
198 /** Lifecycle method - clean up the registry metadata.
199 * Called from resetMetadata().
200 *
201 * @since 1.1
202 */
203 public void stop() {
204 descriptorsByClass = new HashMap();
205 descriptors = new HashMap();
206 searchedPaths=new HashMap();
207 }
208
209 /**
210 * Load an extended mlet file. The source can be an URL, File or
211 * InputStream.
212 *
213 * All mbeans will be instantiated, registered and the attributes will be
214 * set. The result is a list of ObjectNames.
215 *
216 * @param source InputStream or URL of the file
217 * @param cl ClassLoader to be used to load the mbeans, or null to use the
218 * default JMX mechanism ( i.e. all registered loaders )
219 * @return List of ObjectName for the loaded mbeans
220 * @throws Exception
221 *
222 * @since 1.1
223 */
224 public List loadMBeans( Object source, ClassLoader cl )
225 throws Exception
226 {
227 return load("MbeansSource", source, null );
228 }
229
230
231 /** Load descriptors. The source can be a File or URL or InputStream for the
232 * descriptors file. In the case of File and URL, if the extension is ".ser"
233 * a serialized version will be loaded.
234 *
235 * This method should be used to explicitely load metadata - but this is not
236 * required in most cases. The registerComponent() method will find metadata
237 * in the same pacakge.
238 *
239 * @param source
240 */
241 public void loadMetadata(Object source ) throws Exception {
242 loadDescriptors( null, source, null );
243 }
244
245 /** Register a bean by creating a modeler mbean and adding it to the
246 * MBeanServer.
247 *
248 * If metadata is not loaded, we'll look up and read a file named
249 * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package
250 * or parent.
251 *
252 * If the bean is an instance of DynamicMBean. it's metadata will be converted
253 * to a model mbean and we'll wrap it - so modeler services will be supported
254 *
255 * If the metadata is still not found, introspection will be used to extract
256 * it automatically.
257 *
258 * If an mbean is already registered under this name, it'll be first
259 * unregistered.
260 *
261 * If the component implements MBeanRegistration, the methods will be called.
262 * If the method has a method "setRegistry" that takes a RegistryMBean as
263 * parameter, it'll be called with the current registry.
264 *
265 *
266 * @param bean Object to be registered
267 * @param oname Name used for registration
268 * @param type The type of the mbean, as declared in mbeans-descriptors. If
269 * null, the name of the class will be used. This can be used as a hint or
270 * by subclasses.
271 *
272 * @since 1.1
273 */
274 public void registerComponent(Object bean, String oname, String type)
275 throws Exception
276 {
277 registerComponent(bean, new ObjectName(oname), type);
278 }
279
280 /** Unregister a component. We'll first check if it is registered,
281 * and mask all errors. This is mostly a helper.
282 *
283 * @param oname
284 *
285 * @since 1.1
286 */
287 public void unregisterComponent( String oname ) {
288 try {
289 unregisterComponent(new ObjectName(oname));
290 } catch (MalformedObjectNameException e) {
291 log.info("Error creating object name " + e );
292 }
293 }
294
295
296 /** Invoke a operation on a list of mbeans. Can be used to implement
297 * lifecycle operations.
298 *
299 * @param mbeans list of ObjectName on which we'll invoke the operations
300 * @param operation Name of the operation ( init, start, stop, etc)
301 * @param failFirst If false, exceptions will be ignored
302 * @throws Exception
303 * @since 1.1
304 */
305 public void invoke( List mbeans, String operation, boolean failFirst )
306 throws Exception
307 {
308 if( mbeans==null ) {
309 return;
310 }
311 Iterator itr=mbeans.iterator();
312 while(itr.hasNext()) {
313 Object current=itr.next();
314 ObjectName oN=null;
315 try {
316 if( current instanceof ObjectName) {
317 oN=(ObjectName)current;
318 }
319 if( current instanceof String ) {
320 oN=new ObjectName( (String)current );
321 }
322 if( oN==null ) {
323 continue;
324 }
325 if( getMethodInfo(oN, operation) == null) {
326 continue;
327 }
328 getMBeanServer().invoke(oN, operation,
329 new Object[] {}, new String[] {});
330
331 } catch( Exception t ) {
332 if( failFirst ) throw t;
333 log.info("Error initializing " + current + " " + t.toString());
334 }
335 }
336 }
337
338 // -------------------- ID registry --------------------
339
340 /** Return an int ID for faster access. Will be used for notifications
341 * and for other operations we want to optimize.
342 *
343 * @param domain Namespace
344 * @param name Type of the notification
345 * @return An unique id for the domain:name combination
346 * @since 1.1
347 */
348 public synchronized int getId( String domain, String name) {
349 if( domain==null) {
350 domain="";
351 }
352 Hashtable domainTable=(Hashtable)idDomains.get( domain );
353 if( domainTable == null ) {
354 domainTable=new Hashtable();
355 idDomains.put( domain, domainTable);
356 }
357 if( name==null ) {
358 name="";
359 }
360 Integer i=(Integer)domainTable.get(name);
361
362 if( i!= null ) {
363 return i.intValue();
364 }
365
366 int id[]=(int [])ids.get( domain );
367 if( id == null ) {
368 id=new int[1];
369 ids.put( domain, id);
370 }
371 int code=id[0]++;
372 domainTable.put( name, new Integer( code ));
373 return code;
374 }
375
376 // -------------------- Metadata --------------------
377 // methods from 1.0
378
379 /**
380 * Add a new bean metadata to the set of beans known to this registry.
381 * This is used by internal components.
382 *
383 * @param bean The managed bean to be added
384 * @since 1.0
385 */
386 public void addManagedBean(ManagedBean bean) {
387 // XXX Use group + name
388 descriptors.put(bean.getName(), bean);
389 if( bean.getType() != null ) {
390 descriptorsByClass.put( bean.getType(), bean );
391 }
392 }
393
394
395 /**
396 * Find and return the managed bean definition for the specified
397 * bean name, if any; otherwise return <code>null</code>.
398 *
399 * @param name Name of the managed bean to be returned. Since 1.1, both
400 * short names or the full name of the class can be used.
401 * @since 1.0
402 */
403 public ManagedBean findManagedBean(String name) {
404 // XXX Group ?? Use Group + Type
405 ManagedBean mb=((ManagedBean) descriptors.get(name));
406 if( mb==null )
407 mb=(ManagedBean)descriptorsByClass.get(name);
408 return mb;
409 }
410
411 /**
412 * Return the set of bean names for all managed beans known to
413 * this registry.
414 *
415 * @since 1.0
416 */
417 public String[] findManagedBeans() {
418 return ((String[]) descriptors.keySet().toArray(new String[0]));
419 }
420
421
422 /**
423 * Return the set of bean names for all managed beans known to
424 * this registry that belong to the specified group.
425 *
426 * @param group Name of the group of interest, or <code>null</code>
427 * to select beans that do <em>not</em> belong to a group
428 * @since 1.0
429 */
430 public String[] findManagedBeans(String group) {
431
432 ArrayList results = new ArrayList();
433 Iterator items = descriptors.values().iterator();
434 while (items.hasNext()) {
435 ManagedBean item = (ManagedBean) items.next();
436 if ((group == null) && (item.getGroup() == null)) {
437 results.add(item.getName());
438 } else if (group.equals(item.getGroup())) {
439 results.add(item.getName());
440 }
441 }
442 String values[] = new String[results.size()];
443 return ((String[]) results.toArray(values));
444
445 }
446
447
448 /**
449 * Remove an existing bean from the set of beans known to this registry.
450 *
451 * @param bean The managed bean to be removed
452 * @since 1.0
453 */
454 public void removeManagedBean(ManagedBean bean) {
455 // TODO: change this to use group/name
456 descriptors.remove(bean.getName());
457 descriptorsByClass.remove( bean.getType());
458 }
459
460 // -------------------- Deprecated 1.0 methods --------------------
461
462 /**
463 * Factory method to create (if necessary) and return our
464 * <code>MBeanServer</code> instance.
465 *
466 * @since 1.0
467 * @deprecated Use the instance method
468 */
469 public static MBeanServer getServer() {
470 return Registry.getRegistry().getMBeanServer();
471 }
472
473 /**
474 * Set the <code>MBeanServer</code> to be utilized for our
475 * registered management beans.
476 *
477 * @param mbeanServer The new <code>MBeanServer</code> instance
478 * @since 1.0
479 * @deprecated Use the instance method
480 */
481 public static void setServer(MBeanServer mbeanServer) {
482 Registry.getRegistry().setMBeanServer(mbeanServer);
483 }
484
485 /**
486 * Load the registry from the XML input found in the specified input
487 * stream.
488 *
489 * @param stream InputStream containing the registry configuration
490 * information
491 *
492 * @exception Exception if any parsing or processing error occurs
493 * @deprecated use normal class method instead
494 * @since 1.0
495 */
496 public static void loadRegistry(InputStream stream) throws Exception {
497 Registry registry = getRegistry();
498 registry.loadMetadata(stream);
499 }
500
501 /** Get a "singelton" registry, or one per thread if setUseContextLoader
502 * was called
503 *
504 * @deprecated Not enough info - use the method that takes CL and domain
505 * @since 1.0
506 */
507 public synchronized static Registry getRegistry() {
508 return getRegistry(null, null);
509 }
510
511 // -------------------- Helpers --------------------
512
513 /** Get the type of an attribute of the object, from the metadata.
514 *
515 * @param oname
516 * @param attName
517 * @return null if metadata about the attribute is not found
518 * @since 1.1
519 */
520 public String getType( ObjectName oname, String attName )
521 {
522 String type=null;
523 MBeanInfo info=null;
524 try {
525 info=server.getMBeanInfo(oname);
526 } catch (Exception e) {
527 log.info( "Can't find metadata for object" + oname );
528 return null;
529 }
530
531 MBeanAttributeInfo attInfo[]=info.getAttributes();
532 for( int i=0; i<attInfo.length; i++ ) {
533 if( attName.equals(attInfo[i].getName())) {
534 type=attInfo[i].getType();
535 return type;
536 }
537 }
538 return null;
539 }
540
541 /** Find the operation info for a method
542 *
543 * @param oname
544 * @param opName
545 * @return the operation info for the specified operation
546 */
547 public MBeanOperationInfo getMethodInfo( ObjectName oname, String opName )
548 {
549 String type=null;
550 MBeanInfo info=null;
551 try {
552 info=server.getMBeanInfo(oname);
553 } catch (Exception e) {
554 log.info( "Can't find metadata " + oname );
555 return null;
556 }
557 MBeanOperationInfo attInfo[]=info.getOperations();
558 for( int i=0; i<attInfo.length; i++ ) {
559 if( opName.equals(attInfo[i].getName())) {
560 return attInfo[i];
561 }
562 }
563 return null;
564 }
565
566 /** Unregister a component. This is just a helper that
567 * avoids exceptions by checking if the mbean is already registered
568 *
569 * @param oname
570 */
571 public void unregisterComponent( ObjectName oname ) {
572 try {
573 if( getMBeanServer().isRegistered(oname)) {
574 getMBeanServer().unregisterMBean(oname);
575 }
576 } catch( Throwable t ) {
577 log.error( "Error unregistering mbean ", t);
578 }
579 }
580
581 /**
582 * Factory method to create (if necessary) and return our
583 * <code>MBeanServer</code> instance.
584 *
585 */
586 public synchronized MBeanServer getMBeanServer() {
587 long t1=System.currentTimeMillis();
588
589 if (server == null) {
590 if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {
591 server=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);
592 if( log.isDebugEnabled() ) {
593 log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1 ));
594 }
595 } else {
596 server=MBeanServerFactory.createMBeanServer();
597 if( log.isDebugEnabled() ) {
598 log.debug("Creating MBeanServer"+ (System.currentTimeMillis() - t1 ));
599 }
600 }
601 }
602 return (server);
603 }
604
605 /** Find or load metadata.
606 */
607 public ManagedBean findManagedBean(Object bean, Class beanClass, String type)
608 throws Exception
609 {
610 if( bean!=null && beanClass==null ) {
611 beanClass=bean.getClass();
612 }
613
614 if( type==null ) {
615 type=beanClass.getName();
616 }
617
618 // first look for existing descriptor
619 ManagedBean managed = findManagedBean(type);
620
621 // Search for a descriptor in the same package
622 if( managed==null ) {
623 // check package and parent packages
624 if( log.isDebugEnabled() ) {
625 log.debug( "Looking for descriptor ");
626 }
627 findDescriptor( beanClass, type );
628
629 managed=findManagedBean(type);
630 }
631
632 if( bean instanceof DynamicMBean ) {
633 if( log.isDebugEnabled() ) {
634 log.debug( "Dynamic mbean support ");
635 }
636 // Dynamic mbean
637 loadDescriptors("MbeansDescriptorsDynamicMBeanSource",
638 bean, type);
639
640 managed=findManagedBean(type);
641 }
642
643 // Still not found - use introspection
644 if( managed==null ) {
645 if( log.isDebugEnabled() ) {
646 log.debug( "Introspecting ");
647 }
648
649 // introspection
650 loadDescriptors("MbeansDescriptorsIntrospectionSource",
651 beanClass, type);
652
653 managed=findManagedBean(type);
654 if( managed==null ) {
655 log.warn( "No metadata found for " + type );
656 return null;
657 }
658 managed.setName( type );
659 addManagedBean(managed);
660 }
661 return managed;
662 }
663
664
665 /** EXPERIMENTAL Convert a string to object, based on type. Used by several
666 * components. We could provide some pluggability. It is here to keep
667 * things consistent and avoid duplication in other tasks
668 *
669 * @param type Fully qualified class name of the resulting value
670 * @param value String value to be converted
671 * @return Converted value
672 */
673 public Object convertValue(String type, String value)
674 {
675 Object objValue=value;
676
677 if( type==null || "java.lang.String".equals( type )) {
678 // string is default
679 objValue=value;
680 } else if( "javax.management.ObjectName".equals( type ) ||
681 "ObjectName".equals( type )) {
682 try {
683 objValue=new ObjectName( value );
684 } catch (MalformedObjectNameException e) {
685 return null;
686 }
687 } else if( "java.lang.Integer".equals( type ) ||
688 "int".equals( type )) {
689 objValue=new Integer( value );
690 } else if( "java.lang.Long".equals( type ) ||
691 "long".equals( type )) {
692 objValue=new Long( value );
693 } else if( "java.lang.Boolean".equals( type ) ||
694 "boolean".equals( type )) {
695 objValue=new Boolean( value );
696 }
697 return objValue;
698 }
699
700 /** Experimental.
701 *
702 * @param sourceType
703 * @param source
704 * @param param
705 * @return List of descriptors
706 * @throws Exception
707 * @deprecated bad interface, mixing of metadata and mbeans
708 */
709 public List load( String sourceType, Object source, String param)
710 throws Exception
711 {
712 if( log.isTraceEnabled()) {
713 log.trace("load " + source );
714 }
715 String location=null;
716 String type=null;
717 Object inputsource=null;
718
719 if( source instanceof DynamicMBean ) {
720 sourceType="MbeansDescriptorsDynamicMBeanSource";
721 inputsource=source;
722 } else if( source instanceof URL ) {
723 URL url=(URL)source;
724 location=url.toString();
725 type=param;
726 inputsource=url.openStream();
727 if( sourceType == null ) {
728 sourceType = sourceTypeFromExt(location);
729 }
730 } else if( source instanceof File ) {
731 location=((File)source).getAbsolutePath();
732 inputsource=new FileInputStream((File)source);
733 type=param;
734 if( sourceType == null ) {
735 sourceType = sourceTypeFromExt(location);
736 }
737 } else if( source instanceof InputStream ) {
738 type=param;
739 inputsource=source;
740 } else if( source instanceof Class ) {
741 location=((Class)source).getName();
742 type=param;
743 inputsource=source;
744 if( sourceType== null ) {
745 sourceType="MbeansDescriptorsIntrospectionSource";
746 }
747 }
748
749 if( sourceType==null ) {
750 sourceType="MbeansDescriptorsDigesterSource";
751 }
752 ModelerSource ds=getModelerSource(sourceType);
753 List mbeans=ds.loadDescriptors(this, location, type, inputsource);
754
755 return mbeans;
756 }
757
758 private String sourceTypeFromExt( String s ) {
759 if( s.endsWith( ".ser")) {
760 return "MbeansDescriptorsSerSource";
761 }
762 else if( s.endsWith(".xml")) {
763 return "MbeansDescriptorsDigesterSource";
764 }
765 return null;
766 }
767
768 /** Register a component
769 * XXX make it private
770 *
771 * @param bean
772 * @param oname
773 * @param type
774 * @throws Exception
775 */
776 public void registerComponent(Object bean, ObjectName oname, String type)
777 throws Exception
778 {
779 if( log.isDebugEnabled() ) {
780 log.debug( "Managed= "+ oname);
781 }
782
783 if( bean ==null ) {
784 log.error("Null component " + oname );
785 return;
786 }
787
788 try {
789 if( type==null ) {
790 type=bean.getClass().getName();
791 }
792
793 ManagedBean managed = findManagedBean(bean.getClass(), type);
794
795 // The real mbean is created and registered
796 DynamicMBean mbean = managed.createMBean(bean);
797
798 if( getMBeanServer().isRegistered( oname )) {
799 if( log.isDebugEnabled()) {
800 log.debug("Unregistering existing component " + oname );
801 }
802 getMBeanServer().unregisterMBean( oname );
803 }
804
805 getMBeanServer().registerMBean( mbean, oname);
806 } catch( Exception ex) {
807 log.error("Error registering " + oname, ex );
808 throw ex;
809 }
810 }
811
812 /** Lookup the component descriptor in the package and
813 * in the parent packages.
814 *
815 * @param packageName
816 */
817 public void loadDescriptors( String packageName, ClassLoader classLoader ) {
818 String res=packageName.replace( '.', '/');
819
820 if( log.isTraceEnabled() ) {
821 log.trace("Finding descriptor " + res );
822 }
823
824 if( searchedPaths.get( packageName ) != null ) {
825 return;
826 }
827 String descriptors=res + "/mbeans-descriptors.ser";
828
829 URL dURL=classLoader.getResource( descriptors );
830
831 if( dURL == null ) {
832 descriptors=res + "/mbeans-descriptors.xml";
833 dURL=classLoader.getResource( descriptors );
834 }
835 if( dURL == null ) {
836 return;
837 }
838
839 log.debug( "Found " + dURL);
840 searchedPaths.put( packageName, dURL );
841 try {
842 if( descriptors.endsWith(".xml" ))
843 loadDescriptors("MbeansDescriptorsDigesterSource", dURL, null);
844 else
845 loadDescriptors("MbeansDescriptorsSerSource", dURL, null);
846 return;
847 } catch(Exception ex ) {
848 log.error("Error loading " + dURL);
849 }
850
851 return;
852 }
853
854 /** Experimental. Will become private, some code may still use it
855 *
856 * @param sourceType
857 * @param source
858 * @param param
859 * @throws Exception
860 * @deprecated
861 */
862 public void loadDescriptors( String sourceType, Object source, String param)
863 throws Exception
864 {
865 List mbeans=load( sourceType, source, param );
866 if( mbeans == null) return;
867
868 Iterator itr=mbeans.iterator();
869 while( itr.hasNext() ) {
870 Object mb=itr.next();
871 if( mb instanceof ManagedBean) {
872 addManagedBean((ManagedBean)mb);
873 }
874 }
875 }
876
877 /** Lookup the component descriptor in the package and
878 * in the parent packages.
879 *
880 * @param beanClass
881 * @param type
882 */
883 private void findDescriptor( Class beanClass, String type ) {
884 if( type==null ) {
885 type=beanClass.getName();
886 }
887 ClassLoader classLoader=null;
888 if( beanClass!=null ) {
889 classLoader=beanClass.getClassLoader();
890 }
891 if( classLoader==null ) {
892 classLoader=Thread.currentThread().getContextClassLoader();
893 }
894 if( classLoader==null ) {
895 classLoader=this.getClass().getClassLoader();
896 }
897
898 String className=type;
899 String pkg=className;
900 while( pkg.indexOf( ".") > 0 ) {
901 int lastComp=pkg.lastIndexOf( ".");
902 if( lastComp <= 0 ) return;
903 pkg=pkg.substring(0, lastComp);
904 if( searchedPaths.get( pkg ) != null ) {
905 return;
906 }
907 loadDescriptors(pkg, classLoader);
908 }
909 return;
910 }
911
912 private ModelerSource getModelerSource( String type )
913 throws Exception
914 {
915 if( type==null ) type="MbeansDescriptorsDigesterSource";
916 if( type.indexOf( ".") < 0 ) {
917 type="org.apache.tomcat.util.modeler.modules." + type;
918 }
919
920 Class c=Class.forName( type );
921 ModelerSource ds=(ModelerSource)c.newInstance();
922 return ds;
923 }
924
925
926 // -------------------- Registration --------------------
927
928 public ObjectName preRegister(MBeanServer server,
929 ObjectName name) throws Exception
930 {
931 this.server=server;
932 return name;
933 }
934
935 public void postRegister(Boolean registrationDone) {
936 }
937
938 public void preDeregister() throws Exception {
939 }
940
941 public void postDeregister() {
942 }
943
944
945
946
947 // -------------------- DEPRECATED METHODS --------------------
948 // May still be used in tomcat
949 // Never part of an official release
950
951 /** Called by a registry or by the container to unload a loader
952 * @param loader
953 */
954 public void unregisterRegistry(ClassLoader loader ) {
955 // XXX Cleanup ?
956 perLoaderRegistries.remove(loader);
957 }
958
959 public ManagedBean findManagedBean(Class beanClass, String type)
960 throws Exception
961 {
962 return findManagedBean(null, beanClass, type);
963 }
964
965 /**
966 * Set the <code>MBeanServer</code> to be utilized for our
967 * registered management beans.
968 *
969 * @param server The new <code>MBeanServer</code> instance
970 */
971 public void setMBeanServer( MBeanServer server ) {
972 this.server=server;
973 }
974
975 public void resetMetadata() {
976 stop();
977 }
978 /**
979 * Load the registry from the XML input found in the specified input
980 * stream.
981 *
982 * @param source Source to be used to load. Can be an InputStream or URL.
983 *
984 * @exception Exception if any parsing or processing error occurs
985 */
986 public void loadDescriptors( Object source )
987 throws Exception
988 {
989 loadDescriptors("MbeansDescriptorsDigesterSource", source, null );
990 }
991
992 /** @deprecated - may still be used in code using pre-1.1 builds
993 */
994 public void registerComponent(Object bean, String domain, String type,
995 String name)
996 throws Exception
997 {
998 StringBuffer sb=new StringBuffer();
999 sb.append( domain ).append(":");
1000 sb.append( name );
1001 String nameStr=sb.toString();
1002 ObjectName oname=new ObjectName( nameStr );
1003 registerComponent(bean, oname, type );
1004 }
1005
1006
1007
1008 // should be removed
1009 public void unregisterComponent( String domain, String name ) {
1010 try {
1011 ObjectName oname=new ObjectName( domain + ":" + name );
1012
1013 // XXX remove from our tables.
1014 getMBeanServer().unregisterMBean( oname );
1015 } catch( Throwable t ) {
1016 log.error( "Error unregistering mbean ", t );
1017 }
1018 }
1019
1020
1021 /**
1022 * Load the registry from a cached .ser file. This is typically 2-3 times
1023 * faster than parsing the XML.
1024 *
1025 * @param source Source to be used to load. Can be an InputStream or URL.
1026 *
1027 * @exception Exception if any parsing or processing error occurs
1028 * @deprecated Loaded automatically or using a File or Url ending in .ser
1029 */
1030 public void loadCachedDescriptors( Object source )
1031 throws Exception
1032 {
1033 loadDescriptors("MbeansDescriptorsSerSource", source, null );
1034 }
1035 }