KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > management > support > AMXImplBase


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23  
24 /*
25  * $Header: /cvs/glassfish/admin/mbeanapi-impl/src/java/com/sun/enterprise/management/support/AMXImplBase.java,v 1.19 2006/03/17 03:34:20 llc Exp $
26  * $Revision: 1.19 $
27  * $Date: 2006/03/17 03:34:20 $
28  */

29
30 package com.sun.enterprise.management.support;
31
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.Set JavaDoc;
36 import java.util.Collections JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Properties JavaDoc;
39 import java.util.HashSet JavaDoc;
40
41 import java.util.logging.Logger JavaDoc;
42
43 import java.lang.reflect.Field JavaDoc;
44 import java.lang.reflect.Method JavaDoc;
45 import java.lang.reflect.InvocationTargetException JavaDoc;
46
47 import java.io.IOException JavaDoc;
48
49 import javax.management.*;
50
51 import com.sun.appserv.management.util.stringifier.SmartStringifier;
52 import com.sun.appserv.management.util.stringifier.ArrayStringifier;
53
54 import com.sun.appserv.management.base.AMX;
55 import com.sun.appserv.management.base.AMXDebug;
56 import com.sun.appserv.management.base.AMXAttributes;
57 import com.sun.appserv.management.base.Extra;
58 import com.sun.appserv.management.base.Container;
59 import com.sun.appserv.management.base.Singleton;
60 import com.sun.appserv.management.base.Utility;
61
62 import com.sun.appserv.management.base.QueryMgr;
63 import com.sun.appserv.management.base.XTypes;
64 import com.sun.appserv.management.base.XTypesMapper;
65 import com.sun.appserv.management.base.AllTypesMapper;
66
67 import com.sun.appserv.management.base.AMXLoggerBase;
68
69 import com.sun.appserv.management.config.NamedConfigElement;
70
71 import com.sun.appserv.management.base.QueryMgr;
72 import com.sun.appserv.management.DomainRoot;
73 import com.sun.appserv.management.base.Util;
74
75 import com.sun.appserv.management.client.ConnectionSource;
76 import com.sun.appserv.management.util.jmx.MBeanServerConnectionSource;
77 import com.sun.enterprise.management.support.AMXAttributeNameMapper;
78 import com.sun.appserv.management.util.jmx.Acronyms;
79 import com.sun.appserv.management.util.jmx.JMXUtil;
80
81 import com.sun.appserv.management.util.misc.ClassUtil;
82 import com.sun.appserv.management.util.misc.ExceptionUtil;
83 import com.sun.appserv.management.util.misc.GSetUtil;
84 import com.sun.appserv.management.util.misc.ThrowableMapper;
85 import com.sun.appserv.management.util.misc.StringUtil;
86 import com.sun.appserv.management.util.misc.CollectionUtil;
87
88 import com.sun.enterprise.management.support.ObjectNames;
89 import com.sun.enterprise.management.support.oldconfig.OldConfigProxies;
90 import com.sun.enterprise.management.support.TypeInfo;
91 import com.sun.enterprise.management.support.TypeInfos;
92 import com.sun.appserv.management.base.AMX;
93 import com.sun.appserv.management.base.Container;
94
95
96 import com.sun.appserv.management.client.ProxyFactory;
97
98 import com.sun.appserv.management.util.jmx.NotificationBuilder;
99 import com.sun.appserv.management.util.jmx.AttributeChangeNotificationBuilder;
100 import com.sun.appserv.management.util.jmx.stringifier.MBeanInfoStringifier;
101
102 import com.sun.appserv.management.util.misc.MapUtil;
103 import com.sun.appserv.management.config.AMXConfig;
104 import com.sun.appserv.management.config.PropertiesAccess;
105
106 import com.sun.appserv.management.j2ee.J2EETypes;
107
108 import com.sun.logging.LogDomains;
109
110 /**
111     Base class from which all AMX MBeans should derive (but not "must").
112     <p>
113     Note that even though this base class implements a number of interfaces,
114     the actual MBean interface supplied by the subclass construction-time
115     determines which of these is actually exposed in the MBeanInfo.
116     <p>
117     A subclass should generally <b>not</b> implement get/setAttribute(s) as these
118     calls are processed in this base class--
119     <p>
120     If a subclass implements a getter or setter Method it will be invoked automatically.
121     If there is no getter or setter Method, then the getAttributeManually() or
122     setAttributeManually() methods will be invoked; the subclass should implement
123     these methods instead.
124     <p>
125     Method invocation is also handled automatically. If a Method cannot be found,
126     the invokeManually() method is called; the subclass should implement this method.
127     <p>
128     Note that various optimizations are possible, but not implemented. These include
129     caching Methods for each Attribute and for operations as well. Careful testing
130     should be done before complicating the code with such optimizations.
131  */

132 public class AMXImplBase extends MBeanImplBase
133     implements DynamicMBean, MBeanRegistration,
134     AMX,
135     NotificationEmitter, DelegateOwner
136 {
137     protected static final String JavaDoc GET = "get";
138     protected static final String JavaDoc SET = "set";
139     
140     /**
141         The interface this MBean implements
142     */

143     private Class JavaDoc mInterface;
144     
145     /**
146         The MBeanInfo
147     */

148     private MBeanInfo mMBeanInterfaceMBeanInfo;
149     
150     /**
151         The parent MBean for this MBean.
152     */

153     private ObjectName mCachedContainerObjectName;
154     
155     /**
156         Flag to enable or disable whether AttributeChangeNotifications are
157         emitted.
158     */

159     private final boolean mEmitAttributeChangeNotifications;
160     
161     
162     private QueryMgr mQueryMgr;
163     private AMX mSelfProxy;
164     
165     private ConnectionSource mConnectionSource;
166     
167     /**
168         An optional Delegate
169     */

170     private Delegate mSuppliedDelegate;
171     private Delegate mDelegate;
172     
173     
174     private AMXAttributeNameMapper mAttributeNameMapper = null;
175     
176     private Map JavaDoc<String JavaDoc,MBeanAttributeInfo> mAttributeInfos;
177     
178     private String JavaDoc mFullType;
179     private final String JavaDoc mJ2EEType;
180     
181     protected CoverageInfo mCoverage;
182     
183     
184         protected Class JavaDoc
185     getInterface( final String JavaDoc j2eeType )
186     {
187         return( AllTypesMapper.getInstance().getInterfaceForType( j2eeType ) );
188     }
189     
190         protected String JavaDoc
191     deduceJ2EEType( final Class JavaDoc c)
192     {
193         // it may extend the interface in which case its type is readily available
194
String JavaDoc j2eeType = (String JavaDoc)ClassUtil.getFieldValue( c, "J2EE_TYPE" );
195         if ( j2eeType == null )
196         {
197             final String JavaDoc strippedName = StringUtil.stripSuffix(
198                                                 ClassUtil.stripPackageName( c.getName() ), "Impl" );
199             
200             if ( c.getPackage().getName().endsWith( ".j2ee" ) )
201             {
202                 // j2ee standard type
203
j2eeType = strippedName;
204             }
205             else
206             {
207                 j2eeType = "X-" + strippedName;
208             }
209         }
210         
211         return( j2eeType );
212     }
213
214         protected
215     AMXImplBase( String JavaDoc j2eeType, Delegate delegate )
216     {
217         this( j2eeType, null, delegate );
218     }
219     
220         protected
221     AMXImplBase()
222     {
223         this( null, null, null );
224     }
225     
226         protected
227     AMXImplBase( final Delegate delegate )
228     {
229         this( null, null, delegate );
230     }
231
232
233         protected boolean
234     coverageActive()
235     {
236         return ! (mCoverage instanceof CoverageInfoDummy);
237     }
238
239         public final CoverageInfo
240     getCoverageInfo()
241     {
242         mCoverage.setMBeanInfo( getMBeanInfo() );
243         return mCoverage;
244     }
245     
246         public final void
247     clearCoverageInfo()
248     {
249         mCoverage.clear();
250     }
251
252
253         protected CoverageInfo
254     createCoverageInfo( final boolean enable )
255     {
256         final CoverageInfo info = enable ?
257             new CoverageInfoImpl( getMBeanInfo() ) : new CoverageInfoDummy();
258         
259         clearCoverageInfo();
260         
261         return info;
262     }
263     
264         public boolean
265     enableCoverageInfo( final boolean enable )
266     {
267         final boolean wasEnabled = ! ( mCoverage instanceof CoverageInfoDummy);
268         
269         if ( enable != wasEnabled )
270         {
271             mCoverage = createCoverageInfo( enable );
272         }
273
274         return wasEnabled;
275     }
276     
277     /**
278         Construct a new implementation that implements the supplied mbeanInterface.
279         
280         @param j2eeTypeIn (may be null) the j2eeType of this instance
281         @param theInterface (may be null) the public interface as seen on the client
282         @param delegate an MBean to which unknown requests are delegated
283     */

284         private
285     AMXImplBase(
286         final String JavaDoc j2eeTypeIn,
287         final Class JavaDoc theInterface,
288         final Delegate delegate )
289     {
290         super();
291
292         mCoverage = new CoverageInfoDummy(); // will change below...
293

294         if ( delegate != null )
295         {
296             delegate.setOwner( this );
297         }
298         
299         mJ2EEType = j2eeTypeIn == null ?
300                             deduceJ2EEType( getClass() ): j2eeTypeIn;
301                             
302         if ( getAMXDebug() && j2eeTypeIn != null )
303         {
304             final String JavaDoc deducedJ2EEType = deduceJ2EEType( getClass() );
305             
306             if ( ! deducedJ2EEType.equals( mJ2EEType ) )
307             {
308                 debug( "warning: deducedj2eeType " + deducedJ2EEType +
309                     " does not match: " + j2eeTypeIn );
310             }
311         }
312         
313         mInterface = theInterface == null ? getInterface( mJ2EEType ) : theInterface;
314         if ( mInterface == null )
315         {
316             throw new Error JavaDoc( "AMXImplBase: can't get interface for j2eeType " + j2eeTypeIn );
317         }
318         
319         mCachedContainerObjectName = null;
320         mEmitAttributeChangeNotifications = true;
321         mQueryMgr = null;
322         mSelfProxy = null;
323         
324         
325         mSuppliedDelegate = delegate;
326         if ( mSuppliedDelegate instanceof DelegateBase )
327         {
328             ((DelegateBase)mSuppliedDelegate).setDebugOutput( getDebugOutput() );
329         }
330             
331         // initialization of mDelegate is deferred until later; the supplied delegate
332
// may not be in a position to run yet
333
mDelegate = null;
334         mAttributeNameMapper = null;
335         
336         mAttributeInfos = null;
337         mFullType = null;
338         
339         mMBeanInterfaceMBeanInfo =
340             MBeanInfoConverter.getInstance().convert( mInterface, getExtraAttributeInfos());
341         
342         if ( getAMXDebug() )
343         {
344             debug( "Interface " + mInterface.getName() +
345                 " has MBeanInfo:\n" +
346                 MBeanInfoStringifier.DEFAULT.stringify( mMBeanInterfaceMBeanInfo ) );
347                 
348             mMBeanInterfaceMBeanInfo = addDebugMBeanInfo( mMBeanInterfaceMBeanInfo );
349         }
350     }
351
352     private static MBeanAttributeInfo[] EXTRA_ATTRIBUTE_INFOS = null;
353     private static final String JavaDoc[] EXTRA_REMOVALS =
354     {
355         "ProxyFactory",
356         "ConnectionSource",
357         "MBeanInfo",
358         "AllAttributes",
359     };
360     
361         public void
362     delegateFailed( final Throwable JavaDoc t )
363     {
364         // the delegate has fatally failed
365
}
366     
367     
368         protected String JavaDoc
369     getDebugID()
370     {
371         return ClassUtil.stripPackageName( this.getClass().getName() );
372     }
373     
374     /**
375         An design decision was to not include certain Attributes or pseuod-Attributes directly
376         in AMX, so these fields are separated out into 'Extra'. However, some of these
377         are real Attributes that do need to be present in the MBeanInfo supplied by each
378         MBean.
379      */

380         private static synchronized MBeanAttributeInfo[]
381     getExtraAttributeInfos()
382     {
383         if ( EXTRA_ATTRIBUTE_INFOS == null )
384         {
385             final MBeanAttributeInfo[] extraInfos =
386                 JMXUtil.interfaceToMBeanInfo( Extra.class ).getAttributes();
387             final Map JavaDoc<String JavaDoc,MBeanAttributeInfo> m = JMXUtil.attributeInfosToMap( extraInfos );
388             
389             // remove items that are client-side constructs; not real Attributes
390
for( int i = 0; i < EXTRA_REMOVALS.length; ++i )
391             {
392                 m.remove( EXTRA_REMOVALS[ i ] );
393             }
394             
395             EXTRA_ATTRIBUTE_INFOS = new MBeanAttributeInfo[ m.values().size() ];
396             m.values().toArray( EXTRA_ATTRIBUTE_INFOS );
397             
398         }
399         
400         return( EXTRA_ATTRIBUTE_INFOS );
401     }
402     
403         protected MBeanInfo
404     getMBeanInfoFromInterface()
405     {
406         return( mMBeanInterfaceMBeanInfo );
407     }
408     
409     /**
410         Almost all MBeans don't change their MBeanInfo once it's created, making it
411         possible to cache it on the client side.
412     */

413         public boolean
414     getMBeanInfoIsInvariant()
415     {
416         return( true );
417     }
418         
419         protected MBeanInfo
420     removeUnsupportedMBeanInfo( final MBeanInfo info )
421     {
422         return( info );
423     }
424     
425     /**
426         Hook for subclass to modify anything in MBeanInfo.
427      */

428         protected MBeanInfo
429     modifyMBeanInfo( final MBeanInfo info )
430     {
431         return( info );
432     }
433     
434     /**
435         Verify that the Delegate's interface is consistent with the MBeanInfo
436         for this MBean. Called by unit test code when AMX-DEBUG is enabled.
437      */

438         public String JavaDoc
439     checkInterfaceAgainstDelegate()
440     {
441         final Delegate delegate = getDelegate();
442         if ( ! ( getAMXDebug() && delegate != null) )
443         {
444             return null;
445         }
446         
447         final String JavaDoc NEWLINE = System.getProperty( "line.separator" );
448         final String JavaDoc result = null;
449         
450         final MBeanInfo amxMBeanInfo = getMBeanInfo();
451         
452         
453         final Map JavaDoc<String JavaDoc,MBeanAttributeInfo> amxAttributeInfos =
454             JMXUtil.attributeInfosToMap( amxMBeanInfo.getAttributes() );
455             
456         // check that every Attribute in the Delegate exists in AMX
457
final MBeanInfo delegateMBeanInfo = delegate.getMBeanInfo();
458         final MBeanAttributeInfo[] delegateAttributeInfos = delegateMBeanInfo.getAttributes();
459         
460         //debug( "Delegate MBeanInfo: " + MBeanInfoStringifier.DEFAULT.stringify( delegateMBeanInfo ) );
461

462         final StringBuilder JavaDoc builder = new StringBuilder JavaDoc();
463         for( final MBeanAttributeInfo delegateAttrInfo : delegateAttributeInfos )
464         {
465             final String JavaDoc delegateAttrName = delegateAttrInfo.getName();
466             assert( delegateAttrName != null ) :
467                 "delegate for " + getJ2EEType() + " supplied an MBeanAttributeInfo with a null name";
468             
469             try
470             {
471                 final Object JavaDoc value = delegateGetAttribute( delegateAttrName );
472                 // OK, we got the value. Does AMX have it?
473
if ( ! amxAttributeInfos.containsKey( delegateAttrName ) )
474                 {
475                     builder.append( "Attribute " + quote( delegateAttrName ) +
476                         " exists in Delegate, but not in AMX MBeanInfo" + NEWLINE );
477                 }
478             }
479             catch( Exception JavaDoc e )
480             {
481                 builder.append( "Getting Attribute " +
482                     quote( delegateAttrName ) +
483                     " threw Exception: " + e + NEWLINE );
484             }
485         }
486         
487         // return empty string if nothing found
488
return builder.length() == 0 ?
489             "" : (getObjectName() + NEWLINE + builder.toString());
490     }
491     
492     
493     /**
494         Subclass may override, but should call super.addDebugMBeanInfo().
495         Add any additional debugging stuff to the MBeanInfo.
496      */

497         protected MBeanInfo
498     addDebugMBeanInfo( final MBeanInfo origInfo )
499     {
500         final MBeanInfo debugInfo =
501             MBeanInfoConverter.getInstance().convert( AMXDebugStuff.class, null );
502     
503         return JMXUtil.mergeMBeanInfos( origInfo, debugInfo );
504     }
505     
506     
507     
508     /**
509         By default, the MBeanInfo is derived once from the MBean interface.
510         Then certain items are removed, and optional debugging is added.
511         This method should not cache the MBeanInfo because it may change
512         dynamically. The client-side proxies cache the MBeanInfo if
513         getMBeanInfoIsInvariant() returns true.
514     */

515         public MBeanInfo
516     getMBeanInfo()
517     {
518         MBeanInfo mbeanInfo = null;
519     
520         try
521         {
522             mbeanInfo = getMBeanInfoFromInterface();
523             
524             final MBeanNotificationInfo[] notifs = getNotificationInfo();
525             if ( notifs != null && notifs.length != 0 )
526             {
527                 mbeanInfo = JMXUtil.addNotificationInfos( mbeanInfo, notifs );
528             }
529         }
530         catch( Exception JavaDoc e )
531         {
532             e.printStackTrace();
533             throw new RuntimeException JavaDoc( e );
534         }
535         
536         mbeanInfo = removeUnsupportedMBeanInfo( mbeanInfo );
537         mbeanInfo = modifyMBeanInfo( mbeanInfo );
538         
539         return( mbeanInfo );
540     }
541     
542     
543         protected final boolean
544     shouldEmitNotifications()
545     {
546         return( mEmitAttributeChangeNotifications && getListenerCount() != 0 );
547     }
548     
549     
550         public synchronized Delegate
551     getDelegate()
552     {
553         return( mDelegate );
554     }
555     
556         protected void
557     setDelegate( final Delegate delegate )
558     {
559         mDelegate = delegate;
560     }
561     
562         protected boolean
563     haveDelegate()
564     {
565         return( getDelegate() != null );
566     }
567     
568         protected Object JavaDoc
569     getDelegateProxy( final Class JavaDoc theInterface )
570     {
571         return( DelegateInvocationHandler.newProxyInstance( getDelegate(), theInterface ) );
572     }
573     
574         public OldConfigProxies
575     getOldConfigProxies()
576     {
577         return( OldConfigProxies.getInstance( getMBeanServer() ) );
578     }
579     
580     
581         protected AMXAttributeNameMapper
582     getAttributeNameMapper()
583     {
584         return( mAttributeNameMapper );
585     }
586  
587     private static final MBeanNotificationInfo[] EMPTY_NOTIFICATIONS = new MBeanNotificationInfo[ 0 ];
588     
589     /**
590         Defined by NotificationBroadcaster.
591         
592         @return an empty array
593         Subclass may wish to override this.
594     */

595         public MBeanNotificationInfo[]
596     getNotificationInfo()
597     {
598         return( EMPTY_NOTIFICATIONS );
599     }
600  
601     
602     
603     /**
604         Get the value of a property within this MBean's ObjectName.
605         
606         @return the value of the specified property, or null if not found.
607     */

608         protected String JavaDoc
609     getKeyProperty( final String JavaDoc key )
610     {
611         return( getObjectName().getKeyProperty( key ) );
612     }
613     
614     
615         public ProxyFactory
616     getProxyFactory()
617     {
618         assert( mConnectionSource != null );
619         return( ProxyFactory.getInstance( mConnectionSource, true ) );
620     }
621     
622         public <T extends AMX> T
623     getProxy( final ObjectName objectName, final Class JavaDoc<T> theClass)
624     {
625         return getProxyFactory().getProxy( objectName, theClass );
626     }
627     
628
629         protected boolean
630     shouldOmitObjectNameForDebug()
631     {
632         return super.shouldOmitObjectNameForDebug() ||
633             getObjectName().getKeyProperty( "name" ).equals( AMX.NO_NAME );
634     }
635     
636         protected static boolean
637     isSingletonMBean( final Class JavaDoc mbeanInterface )
638     {
639         return( Singleton.class.isAssignableFrom( mbeanInterface ) );
640     }
641     
642         protected static boolean
643     isUtilityMBean( final Class JavaDoc mbeanInterface )
644     {
645         return( Utility.class.isAssignableFrom( mbeanInterface ) );
646     }
647     
648         protected static boolean
649     hasElementName( final Class JavaDoc mbeanInterface )
650     {
651         return( NamedConfigElement.class.isAssignableFrom( mbeanInterface ) );
652     }
653     
654     
655         public Container
656     getFactoryContainer()
657     {
658         return( Container.class.cast( getSelf() ) );
659     }
660     
661         public final ObjectName
662     getContainerObjectName( )
663     {
664         return( getContainerObjectName( getObjectName() ) );
665     }
666     
667         public final Container
668     getContainer( )
669     {
670         final ObjectName objectName = getContainerObjectName( getObjectName() );
671         
672         return( getProxyFactory().getProxy( objectName, Container.class) );
673     }
674     
675         protected ObjectNames
676     getObjectNames()
677     {
678         return ObjectNames.getInstance( getJMXDomain() );
679     }
680     
681         protected synchronized ObjectName
682     getContainerObjectName( final ObjectName selfObjectName )
683     {
684         if ( mCachedContainerObjectName == null &&
685             ! getSelfJ2EEType().equals( XTypes.DOMAIN_ROOT ) )
686         {
687             try
688             {
689                 mCachedContainerObjectName =
690                     getObjectNames().getContainerObjectName( getMBeanServer(), selfObjectName );
691             }
692             catch( InstanceNotFoundException e )
693             {
694                 debug( ExceptionUtil.getStackTrace( e ) );
695                 throw new RuntimeException JavaDoc( e );
696             }
697         }
698
699         return( mCachedContainerObjectName );
700     }
701
702     /**
703         Use the ObjectName with which this MBean was registered in combination with
704         its j2eeType and its parent keys to determine the ObjectName <i>pattern</i>
705         that uniquely identifies it.
706     */

707         public final ObjectName
708     getObjectNamePattern()
709     {
710         final ObjectName selfObjectName = getObjectName();
711         final Set JavaDoc<String JavaDoc> requiredKeys = Util.getPatternKeys( getFullType() );
712         
713         final String JavaDoc requiredProps = JMXUtil.getProps( selfObjectName, requiredKeys, true );
714         final ObjectName pat = Util.newObjectNamePattern( selfObjectName.getDomain(), requiredProps );
715         
716         return( pat );
717     }
718         
719         public final Class JavaDoc
720     getInterface()
721     {
722         return( mInterface );
723     }
724     
725         public final String JavaDoc
726     getInterfaceName()
727     {
728         return( getInterface().getName() );
729     }
730         public final String JavaDoc[]
731     getAttributeNames()
732     {
733         return( GSetUtil.toStringArray( getAttributeInfos().keySet() ) );
734     }
735     
736     /**
737         An operation has not been implemented. Deal with appropriately.
738     */

739         protected final void
740     unimplementedOperation( final String JavaDoc operation )
741     {
742         final String JavaDoc msg = "UNIMPLEMENTED OPERATION: " + operation + " in " + getObjectName();
743         
744         logInfo( msg );
745         
746         throw new UnsupportedOperationException JavaDoc( operation );
747     }
748     
749
750     /**
751         An Attribute has not been implemented.
752     */

753         protected final Object JavaDoc
754     unimplementedAttribute( final String JavaDoc attrName )
755     {
756         final String JavaDoc msg = "UNIMPLEMENTED ATTRIBUTE: " + attrName + " in " + getObjectName();
757         logInfo( msg );
758                 
759         return( null );
760     }
761     
762     /**
763         The impossible has happened.
764     */

765         protected final void
766     impossible( final Throwable JavaDoc t )
767     {
768         logSevere( "AMXImplBase.impossible: " + t.getMessage() );
769         assert( false );
770         throw new RuntimeException JavaDoc( t );
771     }
772     
773     
774         private Object JavaDoc
775     convertToClass(
776         final Object JavaDoc value,
777         final Class JavaDoc theClass )
778         throws Exception JavaDoc
779     {
780         Object JavaDoc result = value;
781         
782         if ( value instanceof String JavaDoc )
783         {
784             result = ClassUtil.InstantiateFromString( theClass, (String JavaDoc)value );
785         }
786         else
787         {
788             getMBeanLogger().info( "convertToClass: don't know how to convert: " +
789                 value.getClass().getName() );
790         }
791         
792         return( result );
793     }
794     
795         private Class JavaDoc<?>
796     getAttributeClass( final String JavaDoc attributeName )
797         throws ClassNotFoundException JavaDoc
798     {
799         final MBeanAttributeInfo[] infos = getMBeanInfo().getAttributes();
800         
801         Class JavaDoc theClass = null;
802         
803         // do it the dumb way; later we can optimize
804
for( int i = 0; i < infos.length; ++i )
805         {
806             if ( infos[ i ].getName().equals( attributeName ) )
807             {
808                 theClass = ClassUtil.getClassFromName( infos[ i ].getType() );
809                 break;
810             }
811         }
812         
813         return( theClass );
814     }
815     
816     /**
817     */

818         protected Object JavaDoc
819     delegateGetAttribute( final String JavaDoc name )
820         throws Exception JavaDoc
821     {
822         assert( name != null );
823         final Delegate delegate = getDelegate();
824         assert( delegate != null );
825         
826         final Object JavaDoc value = delegate.getAttribute( name );
827         
828         Object JavaDoc result = value;
829         
830         if ( value != null )
831         {
832             Class JavaDoc<?> attrClass = getAttributeClass( name );
833             
834             if ( attrClass != null )
835             {
836                 if ( ClassUtil.IsPrimitiveClass( attrClass ) )
837                 {
838                     attrClass = ClassUtil.PrimitiveClassToObjectClass( attrClass );
839                 }
840                     
841                 if ( ! attrClass.isAssignableFrom( value.getClass() ) )
842                 {
843                     try
844                     {
845                         result = convertToClass( value, attrClass );
846                     }
847                     catch( Exception JavaDoc e )
848                     {
849                         // OK, there are a few exceptions
850
result = value;
851                     }
852                 }
853             }
854             else
855             {
856                 getMBeanLogger().warning( "AMXImplBase.delegateGetAttribute: " +
857                     "Can't find class for attribute: " + name + "=" + value +
858                     " in object " + getObjectName() );
859             }
860         }
861         
862         return( result );
863     }
864     
865         protected Object JavaDoc
866     delegateGetAttributeNoThrow( String JavaDoc name )
867     {
868         try
869         {
870             final Object JavaDoc value = delegateGetAttribute( name );
871             
872             return( value );
873         }
874         catch( Exception JavaDoc e )
875         {
876             throw new RuntimeException JavaDoc( e );
877         }
878     }
879     
880         protected void
881     delegateSetAttribute(
882         final String JavaDoc name,
883         final Object JavaDoc value )
884         throws AttributeNotFoundException, InvalidAttributeValueException
885     {
886         getDelegate().setAttribute( new Attribute( name, value ) );
887     }
888     
889         protected void
890     delegateSetAttributeNoThrow( String JavaDoc name, Object JavaDoc value )
891     {
892         try
893         {
894             delegateSetAttribute( name, value );
895         }
896         catch( JMException e )
897         {
898             debug( ExceptionUtil.toString( e ) );
899             throw new RuntimeException JavaDoc( e );
900         }
901         catch( RuntimeException JavaDoc ee )
902         {
903             debug( ExceptionUtil.toString( ee ) );
904             throw ee;
905         }
906     }
907     
908     
909     
910         protected Object JavaDoc
911     getAttributeNoThrow( String JavaDoc name )
912     {
913         Object JavaDoc result = null;
914         
915         try
916         {
917             result = getAttribute( name );
918         }
919         catch( Exception JavaDoc e )
920         {
921             throw new RuntimeException JavaDoc( new ThrowableMapper( e ).map() );
922         }
923         return( result );
924     }
925     
926         protected synchronized Map JavaDoc<String JavaDoc,MBeanAttributeInfo>
927     getAttributeInfos()
928     {
929         if ( mAttributeInfos == null || ! getMBeanInfoIsInvariant() )
930         {
931             synchronized( this )
932             {
933                 mAttributeInfos = JMXUtil.attributeInfosToMap( getMBeanInfo().getAttributes() );
934             }
935         }
936         
937         return( mAttributeInfos );
938     }
939     
940     /**
941         Subclasses may need to force a refresh.
942      */

943         protected void
944     clearAttributeInfos()
945     {
946         mAttributeInfos = null;
947     }
948     
949         protected boolean
950     isLegalAttribute( final String JavaDoc name )
951     {
952         return( getAttributeInfos().keySet().contains( name ) );
953     }
954     
955         protected MBeanAttributeInfo
956     getAttributeInfo( final String JavaDoc name )
957     {
958         return( (MBeanAttributeInfo)getAttributeInfos().get( name ) );
959     }
960     
961         protected boolean
962     isReadOnlyAttribute( final String JavaDoc name )
963     {
964         return( ! getAttributeInfo( name ).isWritable() );
965     }
966     
967     
968         public Logger JavaDoc
969     getLogger()
970     {
971         return( getMBeanLogger() );
972     }
973     
974     
975         protected void
976     checkAttributeSupportedInBuild( final String JavaDoc attributeName )
977     {
978     }
979     
980         protected void
981     checkOperationSupportedInBuild(
982         final String JavaDoc operationName,
983         Object JavaDoc[] args,
984         String JavaDoc[] types)
985     {
986     }
987
988     /**
989         Get an Attribute value, first by looking for a getter method
990         of the correct name and signature, then by looking for a delegate,
991         and finally by calling getAttributeManually(), which a subclass
992         is expected to override.
993         
994         @param name name of the Attribute
995         @return value of the Attribute
996     */

997         public Object JavaDoc
998     getAttribute( final String JavaDoc name )
999         throws AttributeNotFoundException
1000    {
1001        mCoverage.attributeWasRead( name );
1002        
1003        Object JavaDoc result = null;
1004        
1005        checkAttributeSupportedInBuild( name );
1006        
1007        if ( ! isLegalAttribute( name ) )
1008        {
1009            mCoverage.attributeGetFailure( name );
1010            
1011            debug( "getAttribute: unknown Attribute " + name + ", legal Attributes are: " +
1012                toString( getAttributeInfos().keySet() ) );
1013            throw new AttributeNotFoundException( name );
1014        }
1015        
1016        try
1017        {
1018            result = getAttributeInternal( name );
1019        }
1020        catch( AttributeNotFoundException e)
1021        {
1022            mCoverage.attributeGetFailure( name );
1023            throw e;
1024        }
1025        catch( Exception JavaDoc e )
1026        {
1027            mCoverage.attributeGetFailure( name );
1028            throw new AttributeNotFoundException( name );
1029        }
1030        
1031        return( result );
1032    }
1033    
1034        protected Object JavaDoc
1035    getAttributeInternal( String JavaDoc name )
1036        throws AttributeNotFoundException,
1037                ReflectionException, MBeanException
1038    {
1039        Object JavaDoc result = null;
1040        boolean handleManually = false;
1041        
1042        // see if a getter exists
1043
final Method JavaDoc m = findGetter( name );
1044        if ( m != null )
1045        {
1046            result = getAttributeByMethod( name, m );
1047            debug( "getAttribute: " + name + " CALLED GETTER: " + m + " = " + result);
1048            handleManually = false;
1049        }
1050        else if ( haveDelegate() )
1051        {
1052            trace( "getAttribute: " + name + " HAVE DELEGATE " );
1053                
1054            if ( getDelegate().supportsAttribute( name ) )
1055            {
1056                trace( "getAttribute: " + name + " CALLING DELEGATE " );
1057                try
1058                {
1059                    result = delegateGetAttribute( name );
1060                }
1061                catch( Exception JavaDoc e )
1062                {
1063                    trace( "getAttribute: DELEGATE claims support, but fails: " + name );
1064                    handleManually = true;
1065                }
1066            }
1067            else
1068            {
1069                trace( "getAttribute: " + name + " DELEGATE DOES NOT SUPPORT " );
1070                handleManually = true;
1071            }
1072        }
1073        else
1074        {
1075            handleManually = true;
1076        }
1077        
1078        if ( handleManually )
1079        {
1080            trace( "getAttribute: handle manually: " + name );
1081            try
1082            {
1083                result = getAttributeManually( name );
1084            }
1085            catch( AttributeNotFoundException e )
1086            {
1087                trace( "getAttribute: " + name + " NOT FOUND " );
1088                throw e;
1089            }
1090        }
1091        
1092        return( result );
1093    }
1094    
1095    /**
1096        Bulk get. Note that is is important for this implementation to
1097        call getAttribute() for each name so that each may be processed
1098        appropriately; some Attributes may be in this MBean itself, and some
1099        may reside in a {@link Delegate}.
1100        
1101        @param names array of Attribute names
1102        @return AttributeList of Attributes successfully fetched
1103    */

1104        public AttributeList
1105    getAttributes( String JavaDoc[] names )
1106    {
1107        trace( "AMXImplBase.getAttributes: " + SmartStringifier.toString( names ) );
1108        //trace( "AMXImplBase.getAttributes: delegate class = " + getDelegate().getClass().getName() );
1109

1110        final AttributeList attrs = new AttributeList();
1111        
1112        for( int i = 0; i < names.length; ++i )
1113        {
1114            try
1115            {
1116                trace( "%%% calling getAttribute: " + names[ i ] + " on " + getObjectName() );
1117                final Object JavaDoc value = getAttribute( names[ i ] );
1118                attrs.add( new Attribute( names[ i ], value ) );
1119            }
1120            catch( Exception JavaDoc e )
1121            {
1122                trace( "### AttributeNotFoundException: " + names[ i ] );
1123                // ignore, as per spec
1124
}
1125        }
1126        return( attrs );
1127    }
1128    
1129    
1130        private final void
1131    rethrowAttributeNotFound(
1132        final Throwable JavaDoc t,
1133        final String JavaDoc msg )
1134        throws AttributeNotFoundException
1135    {
1136        final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( t );
1137        if ( rootCause instanceof AttributeNotFoundException )
1138        {
1139            throw (AttributeNotFoundException)rootCause;
1140        }
1141        
1142        throw new AttributeNotFoundException( msg );
1143    }
1144    
1145    /**
1146        Set an Attribute by invoking the supplied method.
1147    */

1148        protected Object JavaDoc
1149    getAttributeByMethod( final String JavaDoc attrName, final Method JavaDoc m)
1150        throws AttributeNotFoundException
1151    {
1152        Object JavaDoc result = null;
1153        
1154        try
1155        {
1156            //trace( "getAttributeByMethod: " + attrName );
1157
result = m.invoke( this, (Object JavaDoc[])null );
1158        }
1159        catch( InvocationTargetException JavaDoc e )
1160        {
1161            trace( "InvocationTargetException: " + attrName + " by " + m );
1162            rethrowAttributeNotFound( e, attrName );
1163        }
1164        catch( IllegalAccessException JavaDoc e )
1165        {
1166            trace( "ILLEGAL ACCESS TO: " + attrName + " by " + m );
1167            rethrowAttributeNotFound( e, attrName );
1168        }
1169        catch( Exception JavaDoc e )
1170        {
1171            trace( "Exception: " + attrName + " by " + m );
1172            rethrowAttributeNotFound( e, attrName );
1173        }
1174        
1175        return( result );
1176    }
1177    
1178        protected void
1179    setAttributeByMethod( final Attribute attr, final Method JavaDoc m)
1180        throws AttributeNotFoundException, InvalidAttributeValueException
1181    {
1182        try
1183        {
1184            // trace( "setAttributeByMethod: " + m );
1185
m.invoke( this, new Object JavaDoc[] { attr.getValue() } );
1186        }
1187        catch( InvocationTargetException JavaDoc e )
1188        {
1189            trace( "setAttributeByMethod: InvocationTargetException: " + e );
1190        
1191            final Throwable JavaDoc t = ExceptionUtil.getRootCause( e );
1192            if ( t instanceof InvalidAttributeValueException)
1193            {
1194                throw (InvalidAttributeValueException)t;
1195            }
1196            rethrowAttributeNotFound( e, attr.getName() );
1197        }
1198        catch( IllegalAccessException JavaDoc e )
1199        {
1200            trace( "setAttributeByMethod: IllegalAccessException: " + e );
1201            rethrowAttributeNotFound( e, attr.getName() );
1202        }
1203        catch( Exception JavaDoc e )
1204        {
1205            trace( "setAttributeByMethod: Exception: " + e );
1206            rethrowAttributeNotFound( e, attr.getName() );
1207        }
1208    }
1209    
1210    /**
1211        Subclasses should override this to handle getAttribute( attrName ). It will
1212        be called if no appropriate getter is found.
1213        <p>
1214        It generically handles all <Abc>ObjectName() and <Abc>ObjectNameMap
1215        Attributes.
1216    */

1217        protected Object JavaDoc
1218    getAttributeManually( final String JavaDoc attributeName )
1219        throws AttributeNotFoundException
1220    {
1221        Object JavaDoc result = null;
1222        
1223        AMXDebug.getInstance().getOutput( "getAttributeManually" ).println(
1224            attributeName + " on " + getObjectName() );
1225            
1226        if ( isObjectNameAttribute( attributeName ) )
1227        {
1228            final String JavaDoc j2eeType = attributeNameToJ2EEType( attributeName );
1229            debug( "getAttributeManually: attributeName " + attributeName + " => j2eeType " + j2eeType );
1230            result = getContaineeObjectName( j2eeType );
1231        }
1232        else if ( isObjectNameMapAttribute( attributeName ) )
1233        {
1234            final String JavaDoc j2eeType = attributeNameToJ2EEType( attributeName );
1235            debug( "invokeManually: attributeName " + attributeName + " => j2eeType " + j2eeType );
1236            result = getContaineeObjectNameMap( j2eeType );
1237        }
1238        else
1239        {
1240            throw new AttributeNotFoundException( attributeName );
1241        }
1242        return result;
1243    }
1244
1245
1246    /**
1247        Subclasses should override this to handle setAttribute( attr ). It will
1248        be called if no appropriate setter is found.
1249    */

1250        protected void
1251    setAttributeManually( final Attribute attr )
1252        throws AttributeNotFoundException, InvalidAttributeValueException
1253    {
1254        throw new AttributeNotFoundException( attr.getName() );
1255    }
1256
1257        public void
1258    setAttribute( final Attribute attr )
1259        throws AttributeNotFoundException, InvalidAttributeValueException
1260    {
1261        final String JavaDoc name = attr.getName();
1262        
1263        mCoverage.attributeWasWritten( name );
1264            
1265        if ( isReadOnlyAttribute( name ) )
1266        {
1267            mCoverage.attributeSetFailure( name );
1268            throw new IllegalArgumentException JavaDoc( "Attribute is read-only: " + attr.getName() );
1269        }
1270        
1271        boolean failure = true;
1272        
1273        try
1274        {
1275            setAttributeInternal( attr );
1276            failure = false;
1277        }
1278        catch( AttributeNotFoundException e )
1279        {
1280            throw e;
1281        }
1282        catch( InvalidAttributeValueException e )
1283        {
1284            throw e;
1285        }
1286        catch( RuntimeException JavaDoc e )
1287        {
1288            throw (RuntimeException JavaDoc)e;
1289        }
1290        catch( Exception JavaDoc e )
1291        {
1292            throw new RuntimeException JavaDoc( e );
1293        }
1294        finally
1295        {
1296            if ( failure )
1297            {
1298                mCoverage.attributeSetFailure( name );
1299            }
1300        }
1301    }
1302    
1303    
1304    /**
1305        Set an Attribute value, first by looking for a setter method
1306        of the correct name and signature, then by looking for a delegate,
1307        and finally by calling setAttributeManually(), which a subclass
1308        is expected to override.
1309        
1310        @param attr the Attribute
1311    */

1312        protected void
1313    setAttributeInternal( final Attribute attr )
1314        throws AttributeNotFoundException, InvalidAttributeValueException,
1315                ReflectionException, MBeanException
1316    {
1317        trace( "setAttribute: " + attr.getName() + " = " + attr.getValue() );
1318        
1319        boolean handleManually = false;
1320        final Method JavaDoc m = findSetter( attr );
1321        
1322        final boolean shouldEmitNotifications = shouldEmitNotifications();
1323        // note that this will fail if an Attribute is write-only
1324
final Object JavaDoc oldValue = shouldEmitNotifications ?
1325                        getAttribute( attr.getName() ) : null;
1326        
1327        if ( m != null )
1328        {
1329            setAttributeByMethod( attr, m );
1330        }
1331        else if ( haveDelegate() )
1332        {
1333            if ( getDelegate().supportsAttribute( attr.getName() ) )
1334            {
1335                try
1336                {
1337                    getDelegate().setAttribute( attr );
1338                }
1339                catch( JMException e )
1340                {
1341                    handleManually = true;
1342                }
1343            }
1344            else
1345            {
1346                handleManually = true;
1347            }
1348        }
1349        else
1350        {
1351            handleManually = true;
1352        }
1353        
1354        if ( handleManually )
1355        {
1356            setAttributeManually( attr );
1357        }
1358        
1359        if ( shouldEmitNotifications )
1360        {
1361            final String JavaDoc attrType = getAttributeType( attr.getName() );
1362            
1363            sendAttributeChangeNotification( "", attrType, oldValue, attr );
1364        }
1365    }
1366    
1367        protected String JavaDoc
1368    getAttributeType( final String JavaDoc attrName )
1369    {
1370        final MBeanAttributeInfo info =
1371            JMXUtil.getMBeanAttributeInfo( getMBeanInfo(), attrName );
1372        
1373        return( info.getType() );
1374    }
1375    
1376        protected synchronized void
1377    sendAttributeChangeNotification(
1378        final String JavaDoc msg,
1379        final String JavaDoc attrType,
1380        final Object JavaDoc oldValue,
1381        final Attribute newAttr)
1382    {
1383        final AttributeChangeNotificationBuilder builder =
1384        (AttributeChangeNotificationBuilder)
1385            getNotificationBuilder( AttributeChangeNotification.ATTRIBUTE_CHANGE );
1386        
1387        final AttributeChangeNotification n =
1388            builder.buildAttributeChange( msg, newAttr.getName(), attrType, oldValue, newAttr.getValue() );
1389            
1390        sendNotification( n );
1391    }
1392    
1393    /**
1394        Bulk get. Note that is is important for this implementation to
1395        call setAttribute() for each name so that each may be processed
1396        appropriately; some Attributes may be in this MBean itself, and some
1397        may reside in a {@link Delegate}.
1398        
1399        @param attrs attributes to be set
1400        @return AttributeList containing Attributes successfully set
1401    */

1402        public AttributeList
1403    setAttributes( final AttributeList attrs )
1404    {
1405        trace( "AMXImplBase.setAttributes = " + SmartStringifier.toString( attrs ) );
1406        
1407        final int numAttrs = attrs.size();
1408        final AttributeList successList = new AttributeList();
1409        
1410        for( int i = 0; i < numAttrs; ++i )
1411        {
1412            final Attribute attr = (Attribute)attrs.get( i );
1413            trace( "setAttributes: " + attr.getName() );
1414            try
1415            {
1416                setAttribute( attr );
1417                
1418                successList.add( attr );
1419            }
1420            catch( Exception JavaDoc e )
1421            {
1422                // ignore, as per spec
1423
}
1424        }
1425        return( successList );
1426    }
1427    
1428    
1429    /**
1430        Find a method.
1431        
1432        @param methodName
1433        @param sig
1434        @return a Method or null if not found
1435    */

1436        protected final Method JavaDoc
1437    findMethod( String JavaDoc methodName, final Class JavaDoc[] sig )
1438    {
1439        return( ClassUtil.findMethod( this.getClass(), methodName, sig ) );
1440    }
1441    
1442    /**
1443        Find a getXXX() method that matches the Attribute
1444        
1445        @param name the name to which "get" will be prepended
1446        @return a Method or null if not found
1447    */

1448    static private final Class JavaDoc[] GETTER_SIG = new Class JavaDoc[0];
1449        protected final Method JavaDoc
1450    findGetter( String JavaDoc name )
1451    {
1452        final String JavaDoc methodName = GET + name;
1453        
1454        Method JavaDoc m = findMethod( methodName, GETTER_SIG );
1455        if ( m == null )
1456        {
1457            m = findMethod( "is" + name, GETTER_SIG );
1458        }
1459        
1460        return( m );
1461    }
1462    
1463    /**
1464        Find a setXXX() method that matches the Attribute.
1465        
1466        @param attr an Attribute for which a matching setter should be located
1467        @return a Method or null if not found
1468    */

1469        protected final Method JavaDoc
1470    findSetter( final Attribute attr )
1471    {
1472        final Object JavaDoc value = attr.getValue();
1473        Class JavaDoc valueClass = null;
1474        if ( value == null )
1475        {
1476            final MBeanAttributeInfo info = getAttributeInfos().get( attr.getName() );
1477            if ( info != null )
1478            {
1479                try
1480                {
1481                    valueClass = ClassUtil.getClassFromName( info.getType() );
1482                }
1483                catch( Exception JavaDoc e )
1484                {
1485                }
1486            }
1487        }
1488        else
1489        {
1490            valueClass = value.getClass();
1491        }
1492        
1493        if ( valueClass == null )
1494        {
1495            return null;
1496        }
1497        
1498        final String JavaDoc methodName = SET + attr.getName();
1499        Class JavaDoc[] sig = new Class JavaDoc[] { valueClass };
1500        Method JavaDoc setter = findMethod( methodName, sig );
1501        
1502        final Class JavaDoc primitiveClass = ClassUtil.ObjectClassToPrimitiveClass( valueClass );
1503        if ( setter == null && primitiveClass != valueClass )
1504        {
1505            //trace( "findSetter: retrying for primitive class: " + primitiveClass );
1506
// the Attribute value is always an object. But it may be
1507
// that the setter takes a primitive type. So for example,
1508
// the Attribute may contain a value of type Boolean, but the setter
1509
// may required type boolean
1510
sig[ 0 ] = primitiveClass;
1511            setter = findMethod( methodName, sig );
1512        }
1513        
1514        return( setter );
1515    }
1516
1517    protected static final String JavaDoc GET_PREFIX = "get";
1518    protected static final String JavaDoc OBJECT_NAME_SUFFIX = "ObjectName";
1519    protected static final String JavaDoc OBJECT_NAME_MAP_SUFFIX = "ObjectNameMap";
1520    
1521        protected boolean
1522    operationNameMatches(
1523        final String JavaDoc operationName,
1524        final String JavaDoc prefix,
1525        final String JavaDoc suffix )
1526    {
1527        return operationName.startsWith( prefix ) &&
1528            operationName.endsWith( suffix );
1529    }
1530    
1531        protected boolean
1532    getterNameMatches(
1533        final String JavaDoc operationName,
1534        final String JavaDoc suffix )
1535    {
1536        return operationNameMatches( operationName, GET_PREFIX, suffix );
1537    }
1538    
1539        protected boolean
1540    isObjectNameGetter(
1541        final String JavaDoc operationName,
1542        final Object JavaDoc[] args,
1543        final String JavaDoc[] types )
1544    {
1545        final int numArgs = args == null ? 0 : args.length;
1546        return numArgs == 0 && isObjectNameGetter( operationName );
1547    }
1548    
1549       protected boolean
1550    isObjectNameGetter( final String JavaDoc operationName)
1551    {
1552        return getterNameMatches( operationName, OBJECT_NAME_SUFFIX );
1553    }
1554    
1555    private static final Set JavaDoc<String JavaDoc> NO_AUTO_GET = GSetUtil.newUnmodifiableStringSet(
1556            "ContainerObjectName",
1557            "MonitoringPeerObjectName",
1558            "ObjectName",
1559            "ConfigPeerObjectName",
1560            "ServerObjectName" );
1561           
1562       protected boolean
1563    isObjectNameAttribute(final String JavaDoc attributeName)
1564    {
1565        return attributeName.endsWith( OBJECT_NAME_SUFFIX ) &&
1566            ! NO_AUTO_GET.contains( attributeName );
1567    }
1568    
1569        protected boolean
1570    isObjectNameMapAttribute(final String JavaDoc attributeName)
1571    {
1572        return attributeName.endsWith( OBJECT_NAME_MAP_SUFFIX ) &&
1573            ! NO_AUTO_GET.contains( attributeName );
1574    }
1575    
1576        protected String JavaDoc
1577    attributeNameToJ2EEType( final String JavaDoc attributeName )
1578    {
1579        String JavaDoc j2eeType = null;
1580        
1581        if ( isObjectNameAttribute( attributeName ) )
1582        {
1583            j2eeType = StringUtil.stripSuffix( attributeName, OBJECT_NAME_SUFFIX);
1584        }
1585        else if ( isObjectNameMapAttribute( attributeName ) )
1586        {
1587            j2eeType = StringUtil.stripSuffix( attributeName, OBJECT_NAME_MAP_SUFFIX);
1588        }
1589        
1590        if ( ! J2EETypes.ALL_STD.contains( j2eeType ) )
1591        {
1592            j2eeType = XTypes.PREFIX + j2eeType;
1593        }
1594            
1595        return j2eeType;
1596    }
1597
1598        protected boolean
1599    isObjectNameMapGetter(
1600        final String JavaDoc operationName,
1601        final Object JavaDoc[] args,
1602        final String JavaDoc[] types )
1603    {
1604        final int numArgs = args == null ? 0 : args.length;
1605        return numArgs == 0 && isObjectNameMapGetter( operationName );
1606    }
1607    
1608        protected boolean
1609    isObjectNameMapGetter( final String JavaDoc operationName)
1610    {
1611        return getterNameMatches( operationName, OBJECT_NAME_MAP_SUFFIX );
1612    }
1613    
1614        protected String JavaDoc
1615    j2eeTypeToSimpleClassname( final String JavaDoc j2eeType )
1616    {
1617        return StringUtil.stripPrefix( j2eeType, XTypes.PREFIX );
1618    }
1619    
1620    
1621        protected String JavaDoc
1622    operationNameToJ2EEType( final String JavaDoc operationName )
1623    {
1624        String JavaDoc j2eeType = null;
1625        
1626        if ( isObjectNameGetter( operationName ) )
1627        {
1628            j2eeType =
1629                StringUtil.stripPrefixAndSuffix( operationName, GET_PREFIX, OBJECT_NAME_SUFFIX);
1630        }
1631        else if ( isObjectNameMapGetter( operationName ) )
1632        {
1633            j2eeType =
1634                StringUtil.stripPrefixAndSuffix( operationName, GET_PREFIX, OBJECT_NAME_MAP_SUFFIX);
1635        }
1636        
1637        if ( ! J2EETypes.ALL_STD.contains( j2eeType ) )
1638        {
1639            j2eeType = XTypes.PREFIX + j2eeType;
1640        }
1641            
1642        return j2eeType;
1643    }
1644    
1645     /**
1646        An operation is being invoked manually, meaning that it is missing as a method.
1647        invokeManually() will be called only if no appropriate Method is found.
1648        <p>
1649        Subclasses may override this to handle invoke(), though usually it's just
1650        easier to write the appropriate method directly, which will be found and called
1651        if present.
1652     */

1653        protected Object JavaDoc
1654    invokeManually(
1655        String JavaDoc operationName,
1656        Object JavaDoc[] args,
1657        String JavaDoc[] types )
1658        throws MBeanException, ReflectionException, NoSuchMethodException JavaDoc, AttributeNotFoundException
1659    {
1660        final int numArgs = args == null ? 0 : args.length;
1661        
1662        Object JavaDoc result = null;
1663        
1664        boolean handled = false;
1665        
1666        final boolean ALLOW_GETTERS = true;
1667        
1668        if ( ALLOW_GETTERS &&
1669            numArgs == 0 &&
1670            operationName.startsWith( GET ) )
1671        {
1672            final String JavaDoc attributeName = StringUtil.stripPrefix( operationName, GET );
1673            
1674            if ( getAttributeInfos().get( attributeName ) != null )
1675            {
1676                result = getAttribute( attributeName );
1677                handled = true;
1678            }
1679        }
1680        else if ( operationName.equals( "toString" ) && numArgs == 0 )
1681        {
1682            result = toString();
1683        }
1684        
1685        if ( ! handled )
1686        {
1687            debugMethod( operationName, args );
1688            throw new NoSuchMethodException JavaDoc( "no operation " + operationName +
1689                toString( types ) + " in " + getObjectName() );
1690        }
1691        
1692        return result;
1693    }
1694
1695    
1696        protected void
1697    handleException( final Exception JavaDoc e )
1698        throws MBeanException, ReflectionException
1699    {
1700        final ThrowableMapper mapper = new ThrowableMapper( e );
1701        final Throwable JavaDoc mapped = mapper.map();
1702        
1703        if ( mapped instanceof ReflectionException )
1704        {
1705            throw (ReflectionException)mapped;
1706        }
1707        else if ( mapped instanceof MBeanException )
1708        {
1709            throw (MBeanException)mapped;
1710        }
1711        else if ( ! (mapped instanceof Exception JavaDoc) )
1712        {
1713            // wrap the Throwable in an Exception
1714
final Exception JavaDoc wrapper = new Exception JavaDoc( mapped );
1715            throw new MBeanException( wrapper );
1716        }
1717        else
1718        {
1719            throw new MBeanException( (Exception JavaDoc)mapped );
1720        }
1721    }
1722    
1723        protected void
1724    handleGetAttributeException( final Exception JavaDoc e )
1725        throws MBeanException, ReflectionException, AttributeNotFoundException
1726    {
1727        if ( e instanceof AttributeNotFoundException )
1728        {
1729            // AttributeNotFoundException can never contain anything non-standard
1730
throw (AttributeNotFoundException)e;
1731        }
1732        else
1733        {
1734            handleException( e );
1735        }
1736    }
1737    
1738        protected void
1739    handleInvokeThrowable( final Exception JavaDoc e )
1740        throws MBeanException, ReflectionException
1741    {
1742        handleException( e );
1743    }
1744    
1745
1746    /**
1747        Generic handling of invoke(). Converts the types[] to a Class[], then attempts
1748        to locate a suitable Method. If a suitable Method is found, it is invoked.
1749        If not found the subclass is expected to handle it in invokeManually();
1750    */

1751        public final Object JavaDoc
1752    invoke(
1753        String JavaDoc operationName,
1754        Object JavaDoc[] args,
1755        String JavaDoc[] types )
1756        throws MBeanException, ReflectionException
1757    {
1758        mCoverage.operationWasInvoked( operationName, types );
1759        
1760        Object JavaDoc result = null;
1761        boolean unimplemented = false;
1762        
1763        try
1764        {
1765            checkOperationSupportedInBuild( operationName, args, types );
1766        
1767            final Class JavaDoc[] signature = ClassUtil.signatureFromClassnames( types );
1768            final Method JavaDoc m = findMethod( operationName, signature );
1769            if ( m != null )
1770            {
1771                debugMethod( "invoking method: " + operationName, args );
1772                result = m.invoke( this, args );
1773            }
1774            else if ( haveDelegate() &&
1775                getDelegate().supportsOperation( operationName, args, types ) )
1776            {
1777                debug( "AMXImplBase.invoke: calling delegate for ", operationName );
1778                result = getDelegate().invoke( operationName, args, types );
1779
1780            }
1781            else
1782            {
1783                result = invokeManually( operationName, args, types );
1784            }
1785        }
1786        catch( Exception JavaDoc e )
1787        {
1788            mCoverage.operationFailed( operationName, types );
1789            debug( ExceptionUtil.toString( e ) );
1790            handleInvokeThrowable( e );
1791        }
1792        
1793        return( result );
1794    }
1795    
1796        protected TypeInfo
1797    getTypeInfo( final String JavaDoc j2eeType )
1798    {
1799        return( TypeInfos.getInstance().getInfo( j2eeType ) );
1800    }
1801    
1802        protected String JavaDoc
1803    getSelfJ2EEType()
1804    {
1805        return( mJ2EEType );
1806    }
1807    
1808        protected String JavaDoc
1809    getSelfName()
1810    {
1811        return( Util.getName( getObjectName() ) );
1812    }
1813    
1814        protected TypeInfo
1815    getSelfTypeInfo()
1816    {
1817        return( getTypeInfo( getSelfJ2EEType() ) );
1818    }
1819    
1820        private boolean
1821    isContainer()
1822    {
1823        return( Container.class.isAssignableFrom( getInterface() ) );
1824    }
1825    
1826        protected Set JavaDoc<String JavaDoc>
1827    getChildJ2EETypes()
1828    {
1829        return( getSelfTypeInfo().getChildJ2EETypes() );
1830    }
1831    
1832    protected final static Set JavaDoc<String JavaDoc> EMPTY_STRING_SET = Collections.emptySet();
1833
1834    /**
1835        Certain special cases are present (eg standalone ejb/web modules) where
1836        a parent as described by the FullType (TypeInfos) does not exist.
1837        In this case, the actual parent must contain these items.
1838     */

1839        protected Set JavaDoc<String JavaDoc>
1840    getFauxChildTypes()
1841    {
1842        return( EMPTY_STRING_SET );
1843    }
1844    
1845        public Set JavaDoc<String JavaDoc>
1846    getContaineeJ2EETypes()
1847    {
1848        if ( ! isContainer() )
1849        {
1850            final Exception JavaDoc e =
1851                new AttributeNotFoundException( "ContaineeJ2EETypes" );
1852            
1853            throw new RuntimeException JavaDoc( e );
1854        }
1855        
1856        final Set JavaDoc<String JavaDoc> fauxTypes = getFauxChildTypes();
1857        final Set JavaDoc<String JavaDoc> officialTypes = getSelfTypeInfo().getContaineeJ2EETypes();
1858
1859        return( fauxTypes.size() == 0 ? officialTypes : GSetUtil.newSet( fauxTypes, officialTypes ) );
1860    }
1861    
1862    
1863        protected String JavaDoc
1864    getChildJ2EEType()
1865    {
1866        final Set JavaDoc<String JavaDoc> types = getChildJ2EETypes();
1867        if ( types.size() != 1 )
1868        {
1869            debug( "getChildJ2EEType failing on: ", getObjectName(),
1870                ", got this many children: ", types.size() );
1871            throw new IllegalArgumentException JavaDoc(
1872                        SmartStringifier.toString( types ) );
1873        }
1874        
1875        return( GSetUtil.getSingleton( types ) );
1876    }
1877    
1878    
1879    /**
1880        Our container is the one that actually holds the MBeans we
1881        created. Ask it for the ObjectName.
1882     */

1883        protected ObjectName
1884    getProgenyObjectName(
1885        final String JavaDoc j2eeType,
1886        final String JavaDoc name )
1887    {
1888        final Container container = getContainer();
1889        
1890        final AMX containee = container.getContainee( j2eeType, name );
1891        if ( containee == null )
1892        {
1893            throw new IllegalArgumentException JavaDoc( "Not containee found: " + j2eeType + "=" + name );
1894        }
1895        
1896        return( Util.getObjectName( containee ) );
1897    }
1898    
1899        protected boolean
1900    isOfflineCapable( final TypeInfo childInfo )
1901    {
1902        final Class JavaDoc c = childInfo.getInterface();
1903        
1904        return AMXConfig.class.isAssignableFrom( c ) ||
1905                Utility.class.isAssignableFrom( c ) ||
1906                c == DomainRoot.class;
1907    }
1908    
1909        protected boolean
1910    getOffline()
1911    {
1912        return BootUtil.getInstance().getOffline();
1913    }
1914    
1915    /**
1916        Register a child MBean which is a manager.
1917    */

1918        protected void
1919    registerSelfMgrChild( final TypeInfo childInfo )
1920        throws JMException, InstantiationException JavaDoc, IllegalAccessException JavaDoc
1921    {
1922        final String JavaDoc childJ2EEType = childInfo.getJ2EEType( );
1923        
1924        if ( ( ! getOffline() ) || isOfflineCapable( childInfo ) )
1925        {
1926            final Class JavaDoc implClass = childInfo.getImplClass();
1927            
1928            final ObjectName childObjectName =
1929                getObjectNames().buildContaineeObjectName( getObjectName(), getFullType(), childJ2EEType );
1930            if ( ! getMBeanServer().isRegistered ( childObjectName ) )
1931            {
1932                final Object JavaDoc impl = implClass.newInstance();
1933            
1934                registerMBean( impl, childObjectName );
1935            }
1936        }
1937        else
1938        {
1939            debug( "Not loading child in offline mode: " + childJ2EEType );
1940        }
1941    }
1942
1943        protected void
1944    unregisterSelfMgrChildren()
1945    {
1946        final TypeInfo selfInfo = getSelfTypeInfo();
1947        final Set JavaDoc<String JavaDoc> childTypesSet = selfInfo.getContaineeJ2EETypes();
1948        final String JavaDoc[] childTypes = GSetUtil.toStringArray( childTypesSet );
1949        final MBeanServer mbeanServer = getMBeanServer();
1950        for( int i = 0; i < childTypes.length; ++i )
1951        {
1952            final String JavaDoc childType = childTypes[ i ];
1953            debug( "unregisterSelfMgrChildren: processing type: ", childType);
1954
1955            final TypeInfo childInfo = getTypeInfo( childType );
1956    
1957            final Class JavaDoc childInterface = childInfo.getInterface();
1958
1959            if ( //isConfigMgrMBean( childInterface ) ||
1960
isSingletonMBean( childInterface ) ||
1961                    isUtilityMBean( childInterface )
1962                )
1963            {
1964                final ObjectName containeeObjectName =
1965                    getContaineeObjectName( childType );
1966                if ( containeeObjectName != null )
1967                {
1968                    try
1969                    {
1970                        mbeanServer.unregisterMBean( containeeObjectName );
1971                        debug( "unregisterSelfMgrChildren: ", containeeObjectName,
1972                            " is unregistered" );
1973                    }
1974                    catch ( InstanceNotFoundException infe )
1975                    {
1976                        logWarning( "unregisterSelfMgrChildren: " + infe.getMessage() );
1977                    }
1978                    catch ( Exception JavaDoc e )
1979                    {
1980                        logSevere( "unregisterSelfMgrChildren: " +
1981                            ExceptionUtil.getRootCause(e).getMessage() );
1982                    }
1983                    }
1984            }
1985            else
1986            {
1987                debug( "unregisterSelfMgrChildren: skipping: ", childInterface.getName() );
1988            }
1989        }
1990    }
1991    
1992        protected void
1993    registerSelfMgrChildren( )
1994    {
1995        final TypeInfo selfInfo = getSelfTypeInfo();
1996        final Set JavaDoc<String JavaDoc> childTypesSet = selfInfo.getContaineeJ2EETypes();
1997
1998        debug( "registerSelfMgrChildren for ", getSelfJ2EEType(), ": ", toString( childTypesSet ) );
1999        
2000        if ( childTypesSet.size() != 0 )
2001        {
2002            debug( "registerSelfMgrChildren: child types = ", toString( childTypesSet ) );
2003        }
2004        else
2005        {
2006            debug( "no child types for: ", quote( getObjectName() ) );
2007        }
2008        
2009        final String JavaDoc[] childTypes = GSetUtil.toStringArray( childTypesSet );
2010        for( int i = 0; i < childTypes.length; ++i )
2011        {
2012            final String JavaDoc childType = childTypes[ i ];
2013            debug( "registerSelfMgrChildren: processing type: ", childType);
2014            
2015            final TypeInfo childInfo = getTypeInfo( childType );
2016    
2017            final Class JavaDoc childInterface = childInfo.getInterface();
2018        
2019            if ( isSingletonMBean( childInterface ) ||
2020                    isUtilityMBean( childInterface )
2021                    )
2022            {
2023                try
2024                {
2025                    registerSelfMgrChild( childInfo );
2026                }
2027                catch( InstantiationException JavaDoc e )
2028                {
2029                    trace( "InstantiationException for child of type: " + childInfo.getJ2EEType() +
2030                        " = " + e.getMessage() );
2031                    e.printStackTrace();
2032                    
2033                    final Throwable JavaDoc t = ExceptionUtil.getRootCause( e );
2034                    if ( t != e && t != null )
2035                    {
2036                        trace( "InstantiationException: root cause msg =" + t.getMessage() );
2037                        trace( ExceptionUtil.getStackTrace( t ) );
2038                    }
2039                    else
2040                    {
2041                        trace( ExceptionUtil.getStackTrace( ExceptionUtil.getRootCause( e ) ));
2042                    }
2043                }
2044                catch( Exception JavaDoc e )
2045                {
2046                    trace( "Can't create child, info = " + childInfo + "\n" + e + "\n\n" );
2047                    debug( ExceptionUtil.getStackTrace( e ) );
2048                }
2049            }
2050            else
2051            {
2052                trace( "registerSelfMgrChildren: skipping: " + childInterface.getName() );
2053            }
2054        }
2055    }
2056    
2057    /**
2058        Register special containee MBeans.
2059        Usually this should only be done for child MBeans
2060        that otherwise would not come into existence.
2061    */

2062        protected final void
2063    registerSpecialContainees()
2064    {
2065        registerSelfMgrChildren( );
2066        registerMisc();
2067    }
2068    
2069        protected void
2070    registerMisc()
2071    {
2072        // nothing by default
2073
}
2074    
2075        protected void
2076    preDeregisterHook()
2077    {
2078        unregisterMisc();
2079        unregisterSelfMgrChildren( );
2080    }
2081    
2082        protected void
2083    postDeregisterHook()
2084    {
2085    }
2086    
2087        protected void
2088    unregisterMisc()
2089    {
2090        // nothing by default
2091
}
2092    
2093    
2094    
2095    /**
2096        Classes of MBeans should override this.
2097    */

2098        public String JavaDoc
2099    getGroup()
2100    {
2101        return( GROUP_OTHER );
2102    }
2103    
2104        public String JavaDoc
2105    getName()
2106    {
2107        return( Util.getName( getObjectName() ) );
2108    }
2109    
2110        public String JavaDoc
2111    getJ2EEType()
2112    {
2113        return( Util.getJ2EEType( getObjectName() ) );
2114    }
2115    
2116    /**
2117        @param partialSelfObjectName the ObjectName, lacking the type property
2118        @return the fully qualified type as required by AMX.FULL_TYPE
2119     */

2120        protected static String JavaDoc
2121    getFullType( final ObjectName partialSelfObjectName )
2122    {
2123        final String JavaDoc selfJ2EEType = Util.getJ2EEType( partialSelfObjectName );
2124        
2125        final TypeInfos typeInfos = TypeInfos.getInstance();
2126        final TypeInfo info = typeInfos.getInfo( selfJ2EEType );
2127        
2128        final String JavaDoc[] chain = typeInfos.getJ2EETypeChain( partialSelfObjectName );
2129        
2130        final String JavaDoc fullType = ArrayStringifier.stringify( chain, "." );
2131        
2132        return( fullType );
2133    }
2134    
2135        public final String JavaDoc
2136    getFullType( )
2137    {
2138        assert( mFullType != null ) : "******************************************************";
2139        return( mFullType );
2140    }
2141    
2142    
2143    /**
2144        O the ObjectName by adding to it:
2145        <ul>
2146        <li>adding AMX.FULL_TYPE_KEY property</li>
2147        <li></li>
2148        </ul>
2149    */

2150        protected ObjectName
2151    preRegisterModifyName(
2152        final MBeanServer server,
2153        final ObjectName nameIn )
2154    {
2155        mFullType = getFullType( nameIn );
2156        
2157        // now ensure that certain singleton ancestors have a name
2158
String JavaDoc ancestorProps = "";
2159        final String JavaDoc[] fullTypeArray = Util.getTypeArray( mFullType );
2160        for( int i = 0; i < fullTypeArray.length - 1; ++i )
2161        {
2162            final String JavaDoc key = fullTypeArray[ i ];
2163            
2164            if ( nameIn.getKeyProperty( key ) == null )
2165            {
2166                final String JavaDoc name = ObjectNames.getSingletonName( key );
2167                final String JavaDoc prop = Util.makeProp( key, name );
2168                
2169                ancestorProps = Util.concatenateProps( ancestorProps, prop );
2170            }
2171        }
2172        
2173        final String JavaDoc props = ancestorProps;
2174        
2175        final String JavaDoc newName =
2176            Util.concatenateProps( nameIn.toString(), props );
2177        
2178        final ObjectName nameOut = Util.newObjectName( newName );
2179
2180        return( nameOut );
2181    }
2182    
2183        public final ObjectName
2184    preRegister(
2185        final MBeanServer server,
2186        final ObjectName nameIn)
2187        throws Exception JavaDoc
2188    {
2189        final ObjectName nameFromSuper = super.preRegister( server, nameIn );
2190
2191        mConnectionSource = new MBeanServerConnectionSource( server );
2192        
2193        mSelfObjectName = preRegisterModifyName( server, nameFromSuper );
2194        
2195        if ( mSuppliedDelegate != null )
2196        {
2197            mDelegate = wrapSuppliedDelegate( mSuppliedDelegate );
2198        }
2199        
2200        if ( getAMXDebug() )
2201        {
2202            implCheck();
2203        }
2204        
2205        mSelfObjectName = preRegisterHook( mSelfObjectName );
2206        
2207        registerSpecialContainees();
2208        
2209        preRegisterDone();
2210        return( mSelfObjectName );
2211    }
2212    
2213    /**
2214        This is an opportunity for a subclass to do initialization
2215        and optionally to modify the ObjectName one last time.
2216     */

2217        protected ObjectName
2218    preRegisterHook( final ObjectName selfObjectName)
2219        throws Exception JavaDoc
2220    {
2221        // subclass may do something
2222
return selfObjectName;
2223    }
2224    
2225        protected void
2226    preRegisterDone()
2227        throws Exception JavaDoc
2228    {
2229        debug( "AMXImplBase.preRegister() done for: ", getObjectName() );
2230        
2231        mCoverage.setMBeanInfo( getMBeanInfo() );
2232    }
2233    
2234    
2235    static private final Set JavaDoc<String JavaDoc> AMX_NATIVE_ATTRIBUTES =
2236        Collections.unmodifiableSet( GSetUtil.newSet(
2237            new String JavaDoc[]
2238            {
2239                "Name",
2240                "ObjectName", "FullType", "Group", "J2EEType", "InterfaceName",
2241                "MBeanEmitLogNotifications", "MBeanInfoIsInvariant", "MBeanLoggerName",
2242                "AttributeNames", "MBeanLogLevel",
2243                "WhatsNotDone",
2244                "DomainRootObjectName",
2245                "ContainerObjectName", "ContaineeJ2EETypes", "ContaineeObjectNameSet",
2246                "NotificationInfo",
2247                "Properties", "PropertyNames",
2248                "SystemProperties", "SystemPropertyNames",
2249                "OpenStats", "StatsInterfaceName", "StatisticNames", "Stats",
2250                "ConfigProvider",
2251            }));
2252        
2253    
2254    /**
2255        An optimization to not bother with all the names that are
2256        native to AMX and not mapped to a Delegate Attribute.
2257     */

2258        private Set JavaDoc<String JavaDoc>
2259    getMyAttributeMappingCandidates()
2260    {
2261        final Set JavaDoc<String JavaDoc> candidates = GSetUtil.newSet( getAttributeNames() );
2262        
2263        candidates.removeAll( AMX_NATIVE_ATTRIBUTES );
2264        
2265        // now remove all Attributes that end appropriately
2266
final Set JavaDoc<String JavaDoc> toRemove = new HashSet JavaDoc<String JavaDoc>();
2267        for( final String JavaDoc name : candidates )
2268        {
2269            if ( name.endsWith( "ObjectNameMap" ) ||
2270                 name.endsWith( "ObjectNameSet" ) ||
2271                 name.endsWith( "ObjectName" ) ||
2272                 name.endsWith( "Stats" )
2273                )
2274            {
2275                toRemove.add( name );
2276            }
2277        }
2278        
2279        candidates.removeAll( toRemove );
2280        
2281        return candidates;
2282    }
2283
2284        protected final AMXAttributeNameMapper
2285    createAttributeNameMapper()
2286    {
2287        final AMXAttributeNameMapper mapper = new AMXAttributeNameMapperImpl();
2288        //mapper.setDebugOutput( getDebugOutput() );
2289

2290        final Set JavaDoc<String JavaDoc> myAttributeNames = getMyAttributeMappingCandidates();
2291        
2292        final String JavaDoc[] delegateAttributeNames =
2293            JMXUtil.getAttributeNames( mSuppliedDelegate.getMBeanInfo().getAttributes() );
2294        
2295        mapper.matchNames(
2296            GSetUtil.toStringArray( myAttributeNames ), delegateAttributeNames );
2297        addCustomMappings( mapper );
2298        
2299        if ( getAMXDebug() || false )
2300        {
2301            // this is stuff helpful when implementing; leave here
2302
// so it can be enabled
2303

2304            final Set JavaDoc<String JavaDoc> missingAttributeNames =
2305                GSetUtil.removeSet( myAttributeNames, mapper.getDerivedNames() );
2306            if ( missingAttributeNames.size() != 0 )
2307            {
2308                //handleMissingAttributeMappings( missingAttributeNames );
2309
}
2310        
2311            final Set JavaDoc<String JavaDoc> missingOriginals = mapper.getUnmappedOriginals();
2312            missingOriginals.remove( "name" ); // special case, getName() always overides
2313
missingOriginals.remove( "Name" );
2314            if ( missingOriginals.size() != 0 )
2315            {
2316                handleMissingOriginals( missingOriginals );
2317            }
2318        }
2319        
2320        return mapper;
2321    }
2322    
2323    /**
2324        Mapping of Attributes names is done. But some of our Attributes
2325        don't map to anything in the Delegate.
2326     */

2327        protected void
2328    handleMissingAttributeMappings( final Set JavaDoc<String JavaDoc> missing )
2329    {
2330        if ( missing.size() != 0 )
2331        {
2332            final String JavaDoc msg = getJ2EEType() +
2333                ": AMX Attributes have no corresponding delegate Attribute: " +
2334                CollectionUtil.toString( missing, ", " );
2335                
2336            AMXDebug.getInstance().getOutput( "AMXImplBase.handleMissingAttributeMappings" ).println( msg );
2337            logInfo( msg );
2338        }
2339    }
2340    
2341    /**
2342        Mapping of Attributes names is done. But there are still names in the
2343        Delegate which don't map to anything in this AMX MBean. This may be OK;
2344        some delegates contain a bunch of extra stuff not used by AMX.
2345     */

2346        protected void
2347    handleMissingOriginals( final Set JavaDoc<String JavaDoc> missingOriginals )
2348    {
2349        if ( missingOriginals.size() != 0 )
2350        {
2351            final String JavaDoc msg = getJ2EEType() +
2352                ": Delegate Attributes have no matching AMX Attribute: " +
2353                CollectionUtil.toString( missingOriginals, ", " ) +
2354                "--(this may or may not be an error; if necessary override handleMissingOriginals()";
2355            
2356            AMXDebug.getInstance().getOutput( "AMXImplBase.handleMissingOriginals" ).println( msg );
2357            logFine( msg );
2358        }
2359    }
2360    
2361    
2362    /**
2363        Subclasses may choose to override any Attribute names by adding custom mappings
2364        that can't be handled algorithmically.
2365        <p>
2366        <b>IMPORTANT: mappings for config delegates should use the same
2367        name as found in domain.xml, not the name found in the com.sun.appserv MBean.</b>
2368        This is because a switchover to using ConfigAPI directly will only know
2369        the names found in domain.xml; we don't want to maintain two sets of custom
2370        mappings. The requisite mapping is handled internally, so even though the
2371        com.sun.appserv MBean might advertise "Id", using the domain.xml form "id"
2372        will work correctly.
2373        <p>
2374        Example:
2375        </pre>
2376        super.addCustomMappings( mapper );
2377        mapper.matchName( "MyName", "YourName", "your-name" );
2378        </pre>
2379     */

2380        protected void
2381    addCustomMappings( final AMXAttributeNameMapper mapper )
2382    {
2383    }
2384    
2385    /**
2386        Wrap the supplied delegate (if one was supplied) with a MappedDelegate
2387        which will be created by calling createAttributeNameMapper()
2388     */

2389        protected final Delegate
2390    wrapSuppliedDelegate( final Delegate delegate )
2391    {
2392        mAttributeNameMapper = createAttributeNameMapper();
2393        
2394        final MappedDelegate result = new MappedDelegate( mSuppliedDelegate, mAttributeNameMapper );
2395        result.setDebugOutput( getDebugOutput() );
2396        
2397        return( result );
2398    }
2399    
2400        protected void
2401    implCheck()
2402    {
2403        final boolean isContainer = isContainer();
2404        final String JavaDoc j2eeType = getSelfJ2EEType();
2405        final TypeInfo selfInfo = TypeInfos.getInstance().getInfo( j2eeType );
2406        
2407        final Set JavaDoc<String JavaDoc> nonChildren = selfInfo.getNonChildJ2EETypes();
2408        final Set JavaDoc<String JavaDoc> children = selfInfo.getChildJ2EETypes();
2409        
2410        if ( isContainer )
2411        {
2412            assert( nonChildren.size() != 0 || children.size() != 0 ) :
2413                "ERROR: is Container but contains no children or containees " + j2eeType;
2414        }
2415        else
2416        {
2417            assert( nonChildren.size() == 0 ) :
2418                "ERROR: not a Container: " + j2eeType + " but contains types: " + toString( nonChildren );
2419                
2420            assert( children.size() == 0 ) :
2421                "ERROR: not a Container: " + j2eeType + " but contains children: " + toString( children );
2422        }
2423        
2424        checkSuperfluousMethods();
2425    }
2426    
2427    
2428    private static final Set JavaDoc<String JavaDoc> NOT_SUPERFLUOUS =
2429        GSetUtil.newUnmodifiableStringSet(
2430            "getProxyFactory",
2431            "getDomainRootObjectName",
2432            "getQueryMgrObjectName",
2433            "getServerRootMonitorObjectName"
2434            );
2435            
2436    
2437    /**
2438        @return any non-superflous methods that are the exception to the default assumptions
2439     */

2440        protected Set JavaDoc<String JavaDoc>
2441    getNotSuperfluousMethods()
2442    {
2443        return NOT_SUPERFLUOUS;
2444    }
2445    
2446    /**
2447        @return all method names that appear superfluous
2448     */

2449        protected Set JavaDoc<String JavaDoc>
2450    getSuperfluousMethods()
2451    {
2452        final Set JavaDoc<String JavaDoc> items = new HashSet JavaDoc<String JavaDoc>();
2453        
2454        final Method JavaDoc[] methods = this.getClass().getMethods();
2455        for( final Method JavaDoc m : methods )
2456        {
2457            if ( JMXUtil.isGetter( m ) )
2458            {
2459                final String JavaDoc name = m.getName();
2460            
2461                final String JavaDoc attributeName = StringUtil.stripPrefix( name, GET );
2462                if ( isObjectNameAttribute( attributeName ) ||
2463                    isObjectNameMapAttribute( attributeName ) )
2464                {
2465                    items.add( name );
2466                }
2467            }
2468        }
2469        
2470        items.removeAll( NOT_SUPERFLUOUS );
2471        
2472        return items;
2473    }
2474
2475        protected final void
2476    checkSuperfluousMethods()
2477    {
2478        final Set JavaDoc<String JavaDoc> items = getSuperfluousMethods();
2479        
2480        items.removeAll( getNotSuperfluousMethods() );
2481        
2482        if ( items.size() != 0 )
2483        {
2484            final String JavaDoc LINE_SEP = System.getProperty( "line.separator" );
2485            
2486            final String JavaDoc msg =
2487            "The following methods in " + getJ2EEType() +
2488            " are probably superfluous:" + LINE_SEP +
2489            CollectionUtil.toString( items, LINE_SEP ) + LINE_SEP;
2490            
2491            AMXDebug.getInstance().getOutput( "AMXImplBase.checkSuperfluousMethods" ).println( msg );
2492            logFine( msg );
2493        }
2494    }
2495    
2496        public final void
2497    postRegister( Boolean JavaDoc registrationSucceeded )
2498    {
2499        super.postRegister( registrationSucceeded );
2500        
2501        postRegisterHook( registrationSucceeded );
2502    }
2503    
2504    
2505        public void
2506    postRegisterHook( Boolean JavaDoc registrationSucceeded )
2507    {
2508        if ( registrationSucceeded.booleanValue() )
2509        {
2510            enableCoverageInfo( getAMXDebug() );
2511        }
2512    }
2513
2514        public final void
2515    preDeregister()
2516        throws Exception JavaDoc
2517    {
2518        super.preDeregister();
2519        
2520        preDeregisterHook();
2521    }
2522    
2523        public void
2524    postDeregister()
2525    {
2526        super.postDeregister();
2527        
2528        postDeregisterHook();
2529    }
2530
2531        public final ObjectName
2532    getDomainRootObjectName()
2533    {
2534        return( Util.getObjectName( getDomainRoot() ) );
2535    }
2536
2537    /**
2538        The QueryMgr is a special-case; all the other types rely on it.
2539    */

2540        public synchronized ObjectName
2541    getQueryMgrObjectName()
2542    {
2543        ObjectName objectName = null;
2544        
2545        if ( mQueryMgr != null )
2546        {
2547            // do it the fast way if we already have the proxy
2548
objectName = Util.getObjectName( mQueryMgr );
2549        }
2550        else
2551        {
2552            final MBeanServer server = getMBeanServer();
2553            final String JavaDoc domainName = getObjectName().getDomain();
2554            
2555            objectName = QueryMgrImpl.querySingletonJ2EETypeObjectName( server,
2556                            domainName, QueryMgr.J2EE_TYPE );
2557        }
2558    
2559        assert( objectName != null ) : "getQueryMgrObjectName failed";
2560        return( objectName );
2561    }
2562    
2563    
2564        protected ConnectionSource
2565    getMBeanServerConnectionSource()
2566    {
2567        return( mConnectionSource );
2568    }
2569    
2570        public final LoaderMBean
2571    getLoader()
2572    {
2573        return( Loader.getLoader( getMBeanServer() ) );
2574    }
2575    
2576        public boolean
2577    isDAS()
2578    {
2579        return getLoader().isDAS();
2580    }
2581    
2582    
2583        protected final synchronized AMX
2584    getSelf()
2585    {
2586        if ( mSelfProxy == null )
2587        {
2588            final ObjectName selfObjectName = getObjectName();
2589            assert( selfObjectName != null );
2590            
2591            mSelfProxy = getProxyFactory().getProxy( selfObjectName, AMX.class );
2592            assert( mSelfProxy != null );
2593        }
2594        return( mSelfProxy );
2595    }
2596    
2597    
2598    
2599        public final DomainRoot
2600    getDomainRoot()
2601    {
2602        return( getProxyFactory().getDomainRoot() );
2603    }
2604    
2605    
2606        protected final QueryMgr
2607    getQueryMgr()
2608    {
2609        if ( mQueryMgr == null )
2610        {
2611            final ObjectName objectName = getQueryMgrObjectName();
2612            if ( objectName != null )
2613            {
2614                synchronized( this )
2615                {
2616                    mQueryMgr = getProxyFactory().getProxy( objectName, QueryMgr.class);
2617                }
2618            }
2619        }
2620        
2621        return( mQueryMgr );
2622    }
2623    
2624    /**
2625        Extract the value of the "name" key for each ObjectName and place
2626        it into an array.
2627        
2628        @return String[] containing values of "name" property, one for each ObjectName
2629    */

2630        protected final String JavaDoc[]
2631    getNamePropertyValues( final Set JavaDoc<ObjectName> objectNameSet )
2632    {
2633        return( JMXUtil.getKeyProperty( NAME_KEY, objectNameSet ) );
2634    }
2635    
2636    
2637    /**
2638        @return String[] containing names of all children of specified type
2639    */

2640        protected final String JavaDoc[]
2641    getChildNames()
2642    {
2643        return( getContaineeNamesOfType( getChildJ2EEType() ) );
2644    }
2645    
2646    /**
2647        @return String[] containing names of all children of specified type
2648    */

2649        protected final String JavaDoc[]
2650    getContaineeNamesOfType( final String JavaDoc j2eeType )
2651    {
2652        final Set JavaDoc<ObjectName> objectNames = getContaineeObjectNameSet( j2eeType );
2653                
2654        return( getNamePropertyValues( objectNames ) );
2655    }
2656    
2657    /**
2658        Get the names of all child objects, which may be of more
2659        than one type.
2660        
2661        @return Set containing all child ObjectNames
2662    */

2663        public final Set JavaDoc<ObjectName>
2664    getContaineeObjectNameSet()
2665    {
2666        final String JavaDoc selfType = getSelfJ2EEType();
2667        
2668        final Set JavaDoc<ObjectName> allChildren = new HashSet JavaDoc<ObjectName>();
2669        
2670        final Set JavaDoc<String JavaDoc> containedTypes =
2671            GSetUtil.newSet( getChildJ2EETypes(), getContaineeJ2EETypes() );
2672        
2673        for( final String JavaDoc childJ2eeType : containedTypes )
2674        {
2675            final Set JavaDoc<ObjectName> childrenOfType = getContaineeObjectNameSet( childJ2eeType );
2676            
2677            allChildren.addAll( childrenOfType );
2678        }
2679        
2680        return( allChildren );
2681    }
2682    
2683    /**
2684        Get the name of a child MBean, assuming there is only one kind,
2685        and there is never more than one.
2686        
2687        @return ObjectName of child, or null if not found
2688    */

2689        protected ObjectName
2690    getOnlyChildObjectName()
2691    {
2692        return( getContaineeObjectName( getChildJ2EEType() ) );
2693    }
2694    
2695
2696    /**
2697        @param parentType
2698        @param subType
2699     */

2700        private static String JavaDoc
2701    makeType( final String JavaDoc parentType, final String JavaDoc subType )
2702    {
2703        String JavaDoc result = null;
2704        
2705        if ( parentType == null || parentType.length() == 0 )
2706        {
2707            result = subType;
2708        }
2709        else
2710        {
2711            result = parentType + AMX.FULL_TYPE_DELIM + subType;
2712        }
2713
2714        return( result );
2715    }
2716    
2717        
2718        protected Set JavaDoc<ObjectName>
2719    getFauxContaineeObjectNameSet(
2720        final String JavaDoc childJ2EEType,
2721        final String JavaDoc nullProps )
2722    {
2723        assert getFauxChildTypes().contains( childJ2EEType );
2724        
2725        final String JavaDoc selfProp = Util.makeProp( getJ2EEType(), getSelfName() );
2726        
2727        final String JavaDoc childJ2EETypeProp = Util.makeJ2EETypeProp( childJ2EEType );
2728        final String JavaDoc props = Util.concatenateProps( selfProp, nullProps, childJ2EETypeProp );
2729        
2730        final Set JavaDoc<AMX> candidates = getQueryMgr().queryPropsSet( props );
2731        final Set JavaDoc<ObjectName> objectNames = Util.toObjectNames( candidates );
2732        
2733        return( objectNames );
2734    }
2735    
2736        public Set JavaDoc<ObjectName>
2737    getContaineeObjectNameSet( final String JavaDoc childJ2EEType )
2738    {
2739        final TypeInfos infos = TypeInfos.getInstance();
2740        final TypeInfo info = infos.getInfo( childJ2EEType );
2741        
2742        String JavaDoc props = Util.makeJ2EETypeProp( childJ2EEType );
2743        
2744        QueryExp expr = null;
2745        if ( info.isSubType() )
2746        {
2747            final String JavaDoc selfFullType = getFullType();
2748            final String JavaDoc childFullType = makeType( selfFullType, childJ2EEType );
2749            
2750            final String JavaDoc selfProps = Util.getFullTypeProps( getObjectName(), getFullType() );
2751            
2752            props = Util.concatenateProps( props, selfProps );
2753            expr = Query.eq(Query.attr( AMXAttributes.ATTR_FULL_TYPE ), Query.value( childFullType ));
2754        }
2755        else
2756        {
2757            // not a sub-type; nothing else to add
2758
expr = null;
2759        }
2760        
2761        final ObjectName pattern =
2762            JMXUtil.newObjectNamePattern( getObjectName().getDomain(), props );
2763        final Set JavaDoc<ObjectName> candidates = JMXUtil.queryNames( getMBeanServer(), pattern, expr);
2764        
2765        return( candidates );
2766    }
2767    
2768    
2769        public final Set JavaDoc<ObjectName>
2770    getContaineeObjectNameSet( final Set JavaDoc<String JavaDoc> j2eeTypes )
2771    {
2772        final Set JavaDoc<ObjectName> all = new HashSet JavaDoc<ObjectName>();
2773
2774        final Set JavaDoc<String JavaDoc> actualTypes =
2775            j2eeTypes == null ? getContaineeJ2EETypes() : j2eeTypes;
2776            
2777        for( final String JavaDoc j2eeType : actualTypes )
2778        {
2779            final Set JavaDoc<ObjectName> objectNames = getContaineeObjectNameSet( j2eeType );
2780            
2781            all.addAll( objectNames );
2782        }
2783                
2784        return( all );
2785    }
2786    
2787
2788
2789    /**
2790        There must be 0 or 1 children of the specified type or an exception
2791        will be thrown.
2792        
2793        @return ObjectName for child of specified type
2794    */

2795        public final ObjectName
2796    getContaineeObjectName( final String JavaDoc j2eeType )
2797    {
2798        final Set JavaDoc<ObjectName> children = getContaineeObjectNameSet( j2eeType );
2799        
2800        ObjectName result = null;
2801        
2802        if ( children.size() == 1 )
2803        {
2804            result = GSetUtil.getSingleton( children );
2805        }
2806        else if ( children.size() == 0 )
2807        {
2808            trace( "AMXImplBase.getContaineeObjectName: no children of type " + j2eeType );
2809            result = null;
2810        }
2811        else
2812        {
2813            trace( "AMXImplBase.getContaineeObjectName: " + j2eeType + " impossible");
2814            impossible( new UnsupportedOperationException JavaDoc( "getContaineeObjectName" ) );
2815        }
2816                
2817        return( result );
2818    }
2819    
2820        protected final ObjectName
2821    getNamedChildObjectName( final String JavaDoc name)
2822    {
2823        trace( "\nAMXImplBase.getNamedContaineeObjectName: " +
2824            "Looking for " + name + " in " + quote( getObjectName() ) );
2825        
2826        return( getContaineeObjectName( getChildJ2EEType(), name ) );
2827    }
2828    
2829        public final ObjectName
2830    getContaineeObjectName(
2831        final String JavaDoc j2eeType,
2832        final String JavaDoc name)
2833    {
2834        final Set JavaDoc<ObjectName> candidates = getContaineeObjectNameSet( j2eeType );
2835        
2836        final Set JavaDoc<ObjectName> matching =
2837            JMXUtil.findByProperty( candidates, NAME_KEY, name );
2838        
2839        final ObjectName result = (matching.size() == 0) ?
2840            null : GSetUtil.getSingleton( matching );
2841        
2842        return( result );
2843    }
2844    
2845        public Map JavaDoc<String JavaDoc,Map JavaDoc<String JavaDoc,ObjectName>>
2846    getMultiContaineeObjectNameMap( final Set JavaDoc<String JavaDoc> j2eeTypesIn )
2847    {
2848        // if Set is null, it means all types
2849
final Set JavaDoc<String JavaDoc> j2eeTypes = j2eeTypesIn == null ?
2850            getContaineeJ2EETypes() : j2eeTypesIn;
2851            
2852        final Map JavaDoc<String JavaDoc,Map JavaDoc<String JavaDoc,ObjectName>> m =
2853            new HashMap JavaDoc<String JavaDoc,Map JavaDoc<String JavaDoc,ObjectName>>();
2854        
2855        for( final String JavaDoc j2eeType : j2eeTypes )
2856        {
2857            final Map JavaDoc<String JavaDoc,ObjectName> nameMap = getContaineeObjectNameMap( j2eeType );
2858            if ( nameMap.keySet().size() != 0 )
2859            {
2860                m.put( j2eeType, nameMap );
2861            }
2862        }
2863        
2864        return( m );
2865    }
2866    
2867        public final Map JavaDoc<String JavaDoc,ObjectName>
2868    getContaineeObjectNameMap( final String JavaDoc j2eeType )
2869    {
2870        if ( ! getContaineeJ2EETypes().contains( j2eeType ) )
2871        {
2872            throw new IllegalArgumentException JavaDoc( getObjectName() +
2873                " does not contain j2eeType: " + j2eeType );
2874        }
2875
2876        final Set JavaDoc<ObjectName> objectNames = getContaineeObjectNameSet( j2eeType );
2877        
2878        Map JavaDoc<String JavaDoc,ObjectName> result = Collections.emptyMap();
2879        
2880        if ( objectNames.size() != 0 )
2881        {
2882            result = Util.createObjectNameMap( objectNames );
2883        }
2884        assert( result.keySet().size() == objectNames.size() );
2885        
2886        return( result );
2887    }
2888
2889
2890        public Set JavaDoc<ObjectName>
2891    getByNameContaineeObjectNameSet(
2892        final Set JavaDoc<String JavaDoc> j2eeTypes,
2893        final String JavaDoc name )
2894    {
2895        final Iterator JavaDoc iter = getContaineeObjectNameSet( j2eeTypes ).iterator();
2896        final Set JavaDoc<ObjectName> result = new HashSet JavaDoc<ObjectName>();
2897        
2898        while ( iter.hasNext() )
2899        {
2900            final ObjectName objectName = (ObjectName)iter.next();
2901            
2902            if ( Util.getName( objectName ).equals( name ) )
2903            {
2904                result.add( objectName );
2905            }
2906        }
2907        return( result );
2908    }
2909    
2910    //------------------------ Access to other MBeans --------------------------------
2911

2912    
2913        protected Object JavaDoc
2914    getAttribute(
2915        final ObjectName objectName,
2916        String JavaDoc name )
2917        throws AttributeNotFoundException, InstanceNotFoundException,
2918                ReflectionException, MBeanException
2919    {
2920        return( getMBeanServer().getAttribute( objectName, name ) );
2921    }
2922    
2923        protected AttributeList
2924    getAttributes(
2925        final ObjectName objectName,
2926        String JavaDoc[] names )
2927        throws AttributeNotFoundException, InstanceNotFoundException,
2928                ReflectionException, MBeanException
2929    {
2930        return( getMBeanServer().getAttributes( objectName, names ) );
2931    }
2932    
2933        protected void
2934    setAttribute(
2935        final ObjectName objectName,
2936        Attribute attr )
2937        throws AttributeNotFoundException, InvalidAttributeValueException,
2938                InstanceNotFoundException,
2939                ReflectionException, MBeanException
2940    {
2941        getMBeanServer().setAttribute( objectName, attr );
2942    }
2943    
2944        protected AttributeList
2945    setAttributes(
2946        final ObjectName objectName,
2947        AttributeList attrs )
2948        throws AttributeNotFoundException, InvalidAttributeValueException,
2949                InstanceNotFoundException,
2950                ReflectionException, MBeanException
2951    {
2952        return( getMBeanServer().setAttributes( objectName, attrs ) );
2953    }
2954    
2955    //-------------------------------------------------------------------------------
2956

2957        protected ObjectName
2958    registerMBean( Object JavaDoc mbean, ObjectName name )
2959        throws MalformedObjectNameException, InstanceAlreadyExistsException,
2960        NotCompliantMBeanException, MBeanRegistrationException
2961    {
2962        return getMBeanServer().registerMBean( mbean, name ).getObjectName();
2963    }
2964    
2965    
2966        protected String JavaDoc
2967    stringify( Object JavaDoc o )
2968    {
2969        return( SmartStringifier.toString( o ) );
2970    }
2971    
2972    
2973        public String JavaDoc
2974    toString()
2975    {
2976        return getImplString( false );
2977    }
2978    
2979        public String JavaDoc
2980    getImplString( final boolean verbose )
2981    {
2982        final String JavaDoc NEWLINE = System.getProperty( "line.separator" );
2983        
2984        String JavaDoc s = this.getClass().getName() + NEWLINE +
2985            MBeanInfoStringifier.DEFAULT.stringify( getMBeanInfo() ) + NEWLINE;
2986        
2987        if ( verbose )
2988        {
2989            final AttributeList attrs = getAttributes( getAttributeNames() );
2990            final Map JavaDoc<String JavaDoc,Object JavaDoc> m = JMXUtil.attributeListToValueMap( attrs );
2991            s = NEWLINE + s + MapUtil.toString( m, NEWLINE + NEWLINE ) + NEWLINE;
2992        }
2993        
2994        return s;
2995    }
2996
2997}
2998
2999
3000
3001
3002
3003
3004
3005
3006
Popular Tags