KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > appserv > management > client > handler > AMXProxyHandler


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 package com.sun.appserv.management.client.handler;
24
25 import java.io.IOException JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.logging.Logger JavaDoc;
35
36 import javax.management.Attribute JavaDoc;
37 import javax.management.AttributeList JavaDoc;
38 import javax.management.MBeanInfo JavaDoc;
39 import javax.management.MBeanAttributeInfo JavaDoc;
40 import javax.management.MBeanServerConnection JavaDoc;
41 import javax.management.NotificationListener JavaDoc;
42 import javax.management.NotificationFilter JavaDoc;
43 import javax.management.ListenerNotFoundException JavaDoc;
44 import javax.management.ObjectName JavaDoc;
45 import javax.management.NotificationBroadcaster JavaDoc;
46 import javax.management.ReflectionException JavaDoc;
47 import javax.management.IntrospectionException JavaDoc;
48 import javax.management.JMException JavaDoc;
49 import javax.management.InstanceNotFoundException JavaDoc;
50 import javax.management.AttributeNotFoundException JavaDoc;
51 import javax.management.ListenerNotFoundException JavaDoc;
52 import javax.management.MBeanException JavaDoc;
53
54 import java.lang.reflect.Proxy JavaDoc;
55 import java.lang.reflect.Method JavaDoc;
56
57 import com.sun.appserv.management.base.AMX;
58 import com.sun.appserv.management.base.AMXDebug;
59 import com.sun.appserv.management.base.AMXAttributes;
60 import com.sun.appserv.management.base.Extra;
61 import com.sun.appserv.management.base.AMXClientLogger;
62 import com.sun.appserv.management.base.Util;
63 import com.sun.appserv.management.client.ConnectionSource;
64 import com.sun.appserv.management.util.jmx.MBeanProxyHandler;
65 import com.sun.appserv.management.util.jmx.JMXUtil;
66 import com.sun.appserv.management.util.misc.ClassUtil;
67 import com.sun.appserv.management.util.misc.GSetUtil;
68 import com.sun.appserv.management.util.misc.TypeCast;
69 import com.sun.appserv.management.util.misc.StringUtil;
70 import com.sun.appserv.management.util.stringifier.SmartStringifier;
71 import com.sun.appserv.management.util.stringifier.ArrayStringifier;
72 import com.sun.appserv.management.DomainRoot;
73 import com.sun.appserv.management.base.Container;
74 import com.sun.appserv.management.client.ProxyFactory;
75
76 /**
77     Extends MBeanProxyHandler by also supporting the functionality required of an AMX.
78  */

79 class AMXProxyHandler extends MBeanProxyHandler
80     implements Extra
81 {
82     protected final PerMBeanCache mCache;
83     private boolean mCheckedForInvariantMBeanInfo = false;
84     
85     static protected final String JavaDoc DEBUG_ID =
86         "com.sun.appserv.management.util.jmx.AMXProxyHandler";
87     
88     
89         protected String JavaDoc
90     getDebugID()
91     {
92         return DEBUG_ID;
93     }
94     
95     /**
96         Create a new AMX proxy.
97         
98         @param connectionSource the connection
99         @param proxiedMBeanObjectName the ObjectName of the proxied MBean
100      */

101         protected
102     AMXProxyHandler(
103         final ConnectionSource connectionSource,
104         final ObjectName JavaDoc proxiedMBeanObjectName )
105         throws IOException JavaDoc
106     {
107         super( connectionSource, proxiedMBeanObjectName );
108         
109         mDebug = AMXDebug.getInstance().getOutput( getDebugID() );
110         
111         mCache = new PerMBeanCache();
112         
113         setProxyLogger( AMXClientLogger.getInstance() );
114     }
115     
116         protected void
117     cacheAttribute( final Attribute JavaDoc attr )
118     {
119         mCache.cacheAttribute( attr );
120     }
121     
122     /**
123         Get an Attribute, first from the cache, but if not in the cache, fetching a new
124         copy, then caching it. This routine should only be used on invariant Attributes.
125      */

126         protected Attribute JavaDoc
127     getCachedAttribute( final String JavaDoc attrName )
128         throws IOException JavaDoc, InstanceNotFoundException JavaDoc,
129         MBeanException JavaDoc, AttributeNotFoundException JavaDoc, ReflectionException JavaDoc
130     {
131         Attribute JavaDoc attr = mCache.getCachedAttribute( attrName );
132         
133         if ( attr == null )
134         {
135             final MBeanServerConnection JavaDoc conn = getConnection();
136                 
137             final Object JavaDoc value = getConnection().getAttribute( getTargetObjectName(), attrName );
138             attr = new Attribute JavaDoc( attrName, value );
139             mCache.cacheAttribute( attr );
140         }
141         
142         return( attr );
143     }
144     
145         protected Object JavaDoc
146     getCachedAttributeValue( final String JavaDoc attrName )
147         throws IOException JavaDoc, JMException JavaDoc
148     {
149         final Attribute JavaDoc attr = getCachedAttribute( attrName );
150         
151         assert( attr != null ) : "getCachedAttributeValue: null for " + attrName;
152         return( attr == null ? null : attr.getValue() );
153     }
154     
155     /**
156         All proxies cached by ObjectName get cached by the ProxyFactory.
157         
158         Proxies keyed by other values may not be unique and need to be cached
159         as items in mCache.
160      */

161         private AMX
162     getCachedProxy( Object JavaDoc key )
163     {
164         AMX proxy = null;
165         
166         if ( key instanceof ObjectName JavaDoc )
167         {
168             proxy = getProxyFactory().getProxy( (ObjectName JavaDoc)key, AMX.class );
169         }
170         else
171         {
172             proxy = Util.asAMX(mCache.getCachedItem( key ) );
173         }
174         
175         if ( proxy != null )
176         {
177             final AMXProxyHandler handler = (AMXProxyHandler)Proxy.getInvocationHandler( proxy );
178             if ( ! handler.targetIsValid() )
179             {
180                 debug( "removing cached proxy for key: ", key );
181                 mCache.remove( key );
182                 proxy = null;
183             }
184         }
185         
186         return( proxy );
187     }
188     
189     /**
190         A proxy cached by ObjectName can safely be shared globally, since the
191         ObjectNames are unique per connection. But non-ObjectName keys may
192         actually conflict from like MBeans
193      */

194         private void
195     cacheProxy( final String JavaDoc key, final AMX proxy)
196     {
197         mCache.cacheItem( key, proxy );
198     }
199     
200     
201     private static final String JavaDoc CREATE = "create";
202     private static final String JavaDoc GET = "get";
203     
204     private static final String JavaDoc MAP_SUFFIX = "Map";
205     private static final String JavaDoc SET_SUFFIX = "Set";
206     private static final String JavaDoc LIST_SUFFIX = "List";
207     private static final String JavaDoc OBJECT_NAME_MAP_SUFFIX= "ObjectName" + MAP_SUFFIX;
208     private static final String JavaDoc OBJECT_NAME_SET_SUFFIX= "ObjectName" + SET_SUFFIX;
209     private static final String JavaDoc OBJECT_NAME_LIST_SUFFIX= "ObjectName" + LIST_SUFFIX;
210     
211     private static final String JavaDoc OBJECT_NAME_SUFFIX = "ObjectName";
212     
213     private static final String JavaDoc CONTAINEE_J2EE_TYPES = Container.ATTR_CONTAINEE_J2EE_TYPES;
214     
215     
216     private static final String JavaDoc CONTAINER = "Container";
217     private static final String JavaDoc DOMAIN_ROOT = "DomainRoot";
218     private static final String JavaDoc MBEAN_INFO = "MBeanInfo";
219     private static final String JavaDoc ATTRIBUTE_NAMES = "AttributeNames";
220     private static final String JavaDoc J2EE_NAME = "Name";
221     private static final String JavaDoc J2EE_TYPE = "J2EEType";
222     
223     public final static String JavaDoc ADD_NOTIFICATION_LISTENER = "addNotificationListener";
224     public final static String JavaDoc REMOVE_NOTIFICATION_LISTENER = "removeNotificationListener";
225     
226     private final static String JavaDoc QUERY = "query";
227
228         protected ObjectName JavaDoc
229     getContainerObjectName()
230         throws IOException JavaDoc, JMException JavaDoc
231     {
232         return( (ObjectName JavaDoc)getCachedAttributeValue( AMXAttributes.ATTR_CONTAINER_OBJECT_NAME ) );
233     }
234     
235     
236         protected Class JavaDoc
237     getProxyInterface( final ObjectName JavaDoc objectName )
238         throws IOException JavaDoc, JMException JavaDoc, ClassNotFoundException JavaDoc
239     {
240         // by fetching a proxy this way, it may already exist, with an already-cached
241
// interface.
242
final AMX proxy = getProxyFactory().getProxy( objectName, AMX.class );
243         
244         final Class JavaDoc proxyInterface = ClassUtil.getClassFromName( Util.getExtra( proxy ).getInterfaceName() );
245         
246         return( proxyInterface );
247     }
248     
249         private String JavaDoc
250     _getInterfaceName()
251         throws IOException JavaDoc, JMException JavaDoc
252     {
253         return( (String JavaDoc)getCachedAttributeValue( AMXAttributes.ATTR_INTERFACE_NAME ) );
254     }
255         
256         public String JavaDoc
257     getInterfaceName()
258     {
259         try
260         {
261             return( _getInterfaceName() );
262         }
263         catch( Exception JavaDoc e )
264         {
265             throw new RuntimeException JavaDoc( e );
266         }
267     }
268     
269         public ProxyFactory
270     getProxyFactory()
271     {
272         return( ProxyFactory.getInstance( getConnectionSource() ) );
273     }
274     
275     /**
276         Get the proxy which is the parent of this one.
277      */

278         synchronized Container
279     getContainer( final AMX myProxy )
280         throws IOException JavaDoc, JMException JavaDoc,
281         ClassNotFoundException JavaDoc
282     {
283         Container containerProxy = null;
284         
285         if ( ! ( myProxy instanceof DomainRoot ) )
286         {
287             containerProxy = getProxyFactory().getProxy( getContainerObjectName(), Container.class );
288         }
289         
290         return( containerProxy );
291     }
292     
293     /**
294         Get the proxy corresponding to the DomainMBean for the domain to which
295         this proxy corresponds.
296      */

297         private final DomainRoot
298     getDomainRoot( )
299         throws IOException JavaDoc
300     {
301         return( getProxyFactory().getDomainRoot( ) );
302     }
303     
304     private static final String JavaDoc STRING = String JavaDoc.class.getName();
305     
306     private static final String JavaDoc[] EMPTY_SIG = new String JavaDoc[ 0 ];
307     private static final String JavaDoc[] STRING_SIG = new String JavaDoc[] { STRING } ;
308     private static final String JavaDoc[] STRING2_SIG = new String JavaDoc[] { STRING, STRING } ;
309     
310     private static final String JavaDoc GET_SINGLETON_CONTAINEE = "getSingletonContainee";
311     private static final String JavaDoc GET_CONTAINEE = "getContainee";
312     private static final String JavaDoc GET_SINGLETON_CONTAINEE_OBJECT_NAME=
313                                         GET_SINGLETON_CONTAINEE + OBJECT_NAME_SUFFIX;
314     private static final String JavaDoc[] GET_SINGLETON_CONTAINEE_OBJECT_NAME_SIG1 = STRING_SIG;
315     private static final String JavaDoc[] GET_SINGLETON_CONTAINEE_OBJECT_NAME_SIG2 = STRING2_SIG;
316     
317     private static final String JavaDoc[] GET_OBJECT_NAMES_SIG_EMPTY = EMPTY_SIG;
318     private static final String JavaDoc[] GET_OBJECT_NAMES_SIG_STRING = STRING_SIG;
319     
320
321         protected synchronized AMX
322     createProxy(
323         final ObjectName JavaDoc objectName )
324     {
325         return( getProxyFactory().getProxy( objectName, AMX.class ) );
326     }
327     
328     /**
329         Return true if the method is one that is requesting a Map of AMX object.
330      */

331         protected static boolean
332     isProxyMapGetter(
333         final Method JavaDoc method,
334         final int argCount )
335     {
336         boolean isProxyMapGetter = false;
337         
338         final String JavaDoc name = method.getName();
339         if ( name.startsWith( GET ) &&
340             name.endsWith( MAP_SUFFIX ) &&
341             (! name.endsWith( OBJECT_NAME_MAP_SUFFIX )) &&
342             argCount <= 1 &&
343             Map JavaDoc.class.isAssignableFrom( method.getReturnType() ) )
344         {
345             isProxyMapGetter = true;
346         }
347         
348         return( isProxyMapGetter );
349     }
350     
351     /**
352         Return true if the method is one that is requesting a List of AMX object.
353      */

354         protected static boolean
355     isProxyListGetter(
356         final Method JavaDoc method,
357         final int argCount )
358     {
359         boolean isProxyListGetter = false;
360         
361         final String JavaDoc name = method.getName();
362         if ( ( name.startsWith( GET ) || name.startsWith( QUERY ) ) &&
363             name.endsWith( LIST_SUFFIX ) &&
364             (! name.endsWith( OBJECT_NAME_LIST_SUFFIX )) &&
365             argCount <= 1 &&
366             List JavaDoc.class.isAssignableFrom( method.getReturnType() ) )
367         {
368             isProxyListGetter = true;
369         }
370         
371         return( isProxyListGetter );
372     }
373     
374     /**
375         Return true if the method is one that is requesting a single AMX object.
376         Such methods are client-side methods and do not operate on the target MBean.
377      */

378         protected static boolean
379     isSingleProxyGetter( final Method JavaDoc method, final int argCount )
380     {
381         boolean isProxyGetter = false;
382         
383         final String JavaDoc name = method.getName();
384         if ( ( name.startsWith( GET ) || name.startsWith( QUERY ) ) &&
385             argCount <= 2 &&
386             AMX.class.isAssignableFrom( method.getReturnType() ) )
387         {
388             isProxyGetter = true;
389         }
390         
391         return( isProxyGetter );
392     }
393     
394     /**
395         @return true if the method is one that is requesting a Set of AMX.
396      */

397         protected static boolean
398     isProxySetGetter( final Method JavaDoc method, final int argCount )
399     {
400         boolean isProxySetGetter = false;
401         
402         final String JavaDoc name = method.getName();
403         if ( ( name.startsWith( GET ) || name.startsWith( QUERY ) ) &&
404             name.endsWith( SET_SUFFIX ) &&
405             !name.endsWith( OBJECT_NAME_SET_SUFFIX ) &&
406             argCount <= 2 &&
407             Set JavaDoc.class.isAssignableFrom( method.getReturnType() ) )
408         {
409             isProxySetGetter = true;
410         }
411         
412         return( isProxySetGetter );
413     }
414     
415     
416         private static String JavaDoc
417     proxyGetterToObjectNameGetter( final String JavaDoc methodName )
418     {
419         return( methodName + OBJECT_NAME_SUFFIX );
420     }
421     
422         private Object JavaDoc
423     invokeTarget(
424         final String JavaDoc methodName,
425         final Object JavaDoc[] args,
426         final String JavaDoc[] sig )
427         throws IOException JavaDoc, ReflectionException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc,
428         AttributeNotFoundException JavaDoc
429     {
430         final int numArgs = args == null ? 0 : args.length;
431         
432         Object JavaDoc result = null;
433         
434         if ( numArgs == 0 &&
435             methodName.startsWith( GET ) )
436         {
437             final String JavaDoc attributeName = StringUtil.stripPrefix( methodName, GET );
438             result = getConnection().getAttribute( getTargetObjectName(), attributeName );
439         }
440         else
441         {
442             result = getConnection().invoke( getTargetObjectName(), methodName, args, sig );
443         }
444         
445         return result;
446     }
447     
448         private String JavaDoc
449     getJ2EEType( final Class JavaDoc c )
450     {
451         return( (String JavaDoc)ClassUtil.getFieldValue( c, "J2EE_TYPE" ) );
452     }
453     
454     /**
455         The method is one that requests a Proxy. Create the proxy by asking the
456         target MBean for the appropriate ObjectName. The resulting Proxy will implement
457         the interface given as the return type of the Method.
458      */

459         AMX
460     invokeSingleProxyGetter(
461         final Object JavaDoc myProxy,
462         final Method JavaDoc method,
463         final Object JavaDoc[] args )
464         throws IOException JavaDoc, ReflectionException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc,
465         AttributeNotFoundException JavaDoc
466     {
467         // use the methodName as the key for the cache
468
final String JavaDoc methodName = method.getName();
469         final int numArgs = (args == null) ? 0 : args.length;
470         
471         final String JavaDoc argString = args == null ? "" : ArrayStringifier.stringify( args, "_" );
472         final String JavaDoc cacheKey = methodName + argString;
473         
474         AMX proxy = getCachedProxy( cacheKey );
475     
476         if ( proxy == null )
477         {
478             final Class JavaDoc returnClass = method.getReturnType();
479             ObjectName JavaDoc objectName = null;
480             final String JavaDoc j2eeType = getJ2EEType( returnClass );
481                 
482             if ( numArgs == 0 ) // of the form getXXX() eg getSSLConfig()
483
{
484                 final String JavaDoc newMethodName = proxyGetterToObjectNameGetter( methodName );
485                 objectName = (ObjectName JavaDoc) invokeTarget( newMethodName, null, EMPTY_SIG);
486             }
487             else if ( numArgs == 1 && args[ 0 ].getClass() == String JavaDoc.class )
488             {
489                 final String JavaDoc newMethodName = proxyGetterToObjectNameGetter( methodName );
490                 objectName = (ObjectName JavaDoc) invokeTarget( newMethodName, args, STRING_SIG );
491             }
492             else if ( (methodName.equals( GET_SINGLETON_CONTAINEE ) ||
493                     methodName.equals( GET_CONTAINEE )) && numArgs == 2 )
494             {
495                 // getContainee( j2eeType, name )
496
final String JavaDoc newMethodName = proxyGetterToObjectNameGetter( methodName );
497                 
498                 objectName = (ObjectName JavaDoc)
499                     invokeTarget( newMethodName, args, GET_SINGLETON_CONTAINEE_OBJECT_NAME_SIG2 );
500             }
501             else
502             {
503                 getProxyLogger().warning( "Unknown form of proxy getter: " + method );
504                 assert( false );
505                 throw new IllegalArgumentException JavaDoc();
506             }
507                 
508             if ( objectName != null )
509             {
510                 proxy = createProxy( objectName );
511             }
512             
513             // the underlying object may not exist, this occurs normally sometimes
514
if ( proxy != null )
515             {
516                 if ( cacheKey != null )
517                 {
518                     //debug( "CACHING: " + cacheKey + " => " + Util.getExtra( proxy ).getObjectName);
519
cacheProxy( cacheKey, proxy );
520                 }
521                 else
522                 {
523                     //debug( "NOT CACHING: " + Util.getExtra( proxy ).getObjectName);
524
}
525             }
526             else
527             {
528                 getProxyLogger().fine( "invokeSingleProxyGetter: NULL ObjectName for: " +
529                     methodName + "()" );
530             }
531         }
532         else
533         {
534             //debug( "FOUND CACHED using \"" + cacheKey + "\": " + Util.getExtra( proxy ).getObjectName);
535
}
536         
537         return( proxy );
538     }
539     
540     
541         protected static boolean
542     isProxyCreator( final Method JavaDoc method )
543     {
544         final String JavaDoc methodName = method.getName();
545         
546         return( methodName.startsWith( CREATE ) &&
547             AMX.class.isAssignableFrom( method.getReturnType() ) );
548     }
549     
550     /**
551      */

552         AMX
553     invokeProxyCreator(
554         final Method JavaDoc method,
555         final Object JavaDoc[] args )
556         throws IOException JavaDoc, ReflectionException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc,
557         AttributeNotFoundException JavaDoc
558     {
559         final String JavaDoc methodName = method.getName();
560         
561         final String JavaDoc[] stringSig = getStringSig( method );
562         final ObjectName JavaDoc objectName = (ObjectName JavaDoc)invokeTarget( methodName, args, stringSig );
563         assert( objectName != null ) :
564             "received null ObjectName from: " + methodName + " on target " + getTargetObjectName();
565         
566         final AMX proxy = createProxy( objectName );
567         assert( getProxyFactory().getProxy( Util.getExtra( proxy ).getObjectName(),AMX.class, false ) == proxy );
568         
569         return( proxy );
570     }
571     
572
573
574     
575         private static String JavaDoc
576     toString( Object JavaDoc o )
577     {
578         String JavaDoc result = o == null ? "null" : SmartStringifier.toString( o );
579         
580         final int MAX_LENGTH = 256;
581         if ( result.length() > MAX_LENGTH )
582         {
583             result = result.substring( 0, MAX_LENGTH - 1 ) + "...";
584         }
585         
586         return result;
587     }
588     
589         private static String JavaDoc[]
590     getStringSig( final Method JavaDoc method )
591     {
592         final Class JavaDoc[] sig = method.getParameterTypes();
593         final String JavaDoc[] stringSig = ClassUtil.classnamesFromSignature( sig );
594         return( stringSig );
595     }
596
597
598         protected static String JavaDoc
599     convertMethodName(
600         final String JavaDoc srcName,
601         final String JavaDoc srcSuffix,
602         final String JavaDoc resultSuffix )
603     {
604         if ( ! srcName.endsWith( srcSuffix ) )
605         {
606             throw new IllegalArgumentException JavaDoc( srcName + " does not end with " + srcSuffix );
607         }
608         final String JavaDoc baseName = srcName.substring( 0, srcName.lastIndexOf( srcSuffix ) );
609         
610         return( baseName + resultSuffix );
611     }
612     
613     private static final Map JavaDoc<String JavaDoc,AMX> EMPTY_String_AMX = Collections.emptyMap();
614     
615         private Map JavaDoc<String JavaDoc,?>
616     invokeProxyMapGetter(
617         final Object JavaDoc myProxy,
618         final Method JavaDoc method,
619         final Object JavaDoc[] args )
620         throws java.io.IOException JavaDoc, ReflectionException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc,
621         ClassNotFoundException JavaDoc, AttributeNotFoundException JavaDoc, JMException JavaDoc
622     {
623         final int argCount = args == null ? 0 : args.length;
624         
625         // turn getXXXObjectNameMap() into getXXXMap()
626
final String JavaDoc methodName = method.getName();
627         final String JavaDoc getObjectNameMapName =
628             convertMethodName( methodName, MAP_SUFFIX, OBJECT_NAME_MAP_SUFFIX );
629         
630         final MBeanServerConnection JavaDoc conn = getConnection();
631         
632         final Map JavaDoc<String JavaDoc,?> m = TypeCast.asMap(
633             invokeTarget( getObjectNameMapName, args, getStringSig( method ) ) );
634         assert( m != null ) :
635             "mbean " + getTargetObjectName() + " returned null Map for " + getObjectNameMapName;
636         
637         /*
638             The Map may be either a:
639             - Map of <name>=<ObjectName>
640             - Map of <j2eeType>=<Map of <name>=<ObjectName>
641          */

642         Map JavaDoc<String JavaDoc,?> result = null;
643         if ( m.keySet().size() != 0 )
644         {
645             final ProxyFactory proxyFactory = getProxyFactory();
646         
647             final Object JavaDoc firstValue = m.values().iterator().next();
648             
649             if ( firstValue instanceof ObjectName JavaDoc )
650             {
651                 // it's <name>=<ObjectName>
652
final Map JavaDoc<String JavaDoc,ObjectName JavaDoc> onm = TypeCast.asMap( m );
653                 final Map JavaDoc<String JavaDoc,AMX> proxyMap = proxyFactory.toProxyMap( onm );
654                 result = proxyMap;
655             }
656             else if ( firstValue instanceof Map JavaDoc )
657             {
658                 final Map JavaDoc<String JavaDoc,Map JavaDoc<String JavaDoc,ObjectName JavaDoc>> objectNameMaps = TypeCast.asMap( m );
659                 final Map JavaDoc<String JavaDoc,Map JavaDoc<String JavaDoc,AMX>> proxyMaps = new HashMap JavaDoc<String JavaDoc,Map JavaDoc<String JavaDoc,AMX>>();
660                 
661                 for ( final String JavaDoc j2eeType : objectNameMaps.keySet() )
662                 {
663                     final Map JavaDoc<String JavaDoc,ObjectName JavaDoc> objectNameMap = objectNameMaps.get( j2eeType );
664                     final Map JavaDoc<String JavaDoc,AMX> proxyMap = proxyFactory.toProxyMap( objectNameMap );
665                     proxyMaps.put( j2eeType, proxyMap );
666                 }
667                 
668                 result = proxyMaps;
669             }
670             else
671             {
672                 throw new IllegalArgumentException JavaDoc();
673             }
674         }
675         else
676         {
677             result = EMPTY_String_AMX;
678         }
679         
680         return( result );
681     }
682     
683         private List JavaDoc<AMX>
684     invokeProxyListGetter(
685         final Object JavaDoc myProxy,
686         final Method JavaDoc method,
687         final Object JavaDoc[] args )
688         throws java.io.IOException JavaDoc, ReflectionException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc,
689         ClassNotFoundException JavaDoc, AttributeNotFoundException JavaDoc, JMException JavaDoc
690     {
691         // get the List<ObjectName> from the MBean
692
final String JavaDoc remoteNAME =
693             convertMethodName( method.getName(), LIST_SUFFIX, OBJECT_NAME_LIST_SUFFIX );
694         final List JavaDoc<ObjectName JavaDoc> objectNames = TypeCast.asList(
695             invokeTarget( remoteNAME, args, getStringSig( method ) ) );
696         
697         final List JavaDoc<AMX> result = getProxyFactory().toProxyList( objectNames );
698         
699         return( result );
700     }
701     
702     /**
703         The method is one that requests a Set of Proxies. Create the proxies by asking the
704         target MBean for the ObjectNames. Then generate proxies of the appropriate type
705         for each resulting ObjectName.
706      */

707         private Set JavaDoc<AMX>
708     invokeProxySetGetter(
709         final Object JavaDoc myProxy,
710         final Method JavaDoc method,
711         final Object JavaDoc[] args )
712         throws java.io.IOException JavaDoc, JMException JavaDoc, ClassNotFoundException JavaDoc
713     {
714         assert( Set JavaDoc.class.isAssignableFrom( method.getReturnType() ) );
715     
716         final String JavaDoc methodName = method.getName();
717         
718         final String JavaDoc getObjectNamesName =
719             convertMethodName( methodName, SET_SUFFIX, OBJECT_NAME_SET_SUFFIX );
720         
721         final MBeanServerConnection JavaDoc conn = getConnection();
722         
723         final String JavaDoc[] stringSig = getStringSig( method );
724         // ask the MBean for an ObjectName corresponding to an id (name)
725
final Set JavaDoc<ObjectName JavaDoc> objectNames = TypeCast.asSet( invokeTarget( getObjectNamesName, args, stringSig ) );
726         
727         final Set JavaDoc<AMX> proxies = getProxyFactory().toProxySet( objectNames );
728         
729         return( proxies );
730     }
731     
732     
733     private final static Class JavaDoc[] NOTIFICATION_LISTENER_SIG1 = new Class JavaDoc[]
734     {
735         NotificationListener JavaDoc.class
736     };
737     private final static Class JavaDoc[] NOTIFICATION_LISTENER_SIG2 = new Class JavaDoc[]
738     {
739         NotificationListener JavaDoc.class,
740         NotificationFilter JavaDoc.class,
741         Object JavaDoc.class
742     };
743     
744     
745     
746         private MBeanInfo JavaDoc
747     _getMBeanInfo()
748         throws IOException JavaDoc,
749         InstanceNotFoundException JavaDoc, ReflectionException JavaDoc, IntrospectionException JavaDoc
750     {
751         MBeanInfo JavaDoc mbeanInfo = null;
752         
753         if ( ! mCheckedForInvariantMBeanInfo )
754         {
755             mCheckedForInvariantMBeanInfo = true;
756             
757             // see if target has the boolean which tells us if caching is OK
758
try
759             {
760                 final Boolean JavaDoc cacheIt = (Boolean JavaDoc)
761                     getAttribute( AMXAttributes.ATTR_MBEAN_INFO_IS_INVARIANT );
762                 setMBeanInfoIsInvariant( cacheIt.booleanValue() );
763                 cacheMBeanInfo( cacheIt.booleanValue() );
764                 
765             }
766             catch( Exception JavaDoc e )
767             {
768                 // not found, or other problem, have to assume we can't cache it
769
cacheMBeanInfo( false );
770                 setMBeanInfoIsInvariant( false );
771             }
772         }
773
774         mbeanInfo = getMBeanInfo( getCacheMBeanInfo() );
775         
776         return( mbeanInfo );
777     }
778     
779     
780         public MBeanInfo JavaDoc
781     getMBeanInfo()
782     {
783         try
784         {
785             return( _getMBeanInfo() );
786         }
787         catch( Exception JavaDoc e )
788         {
789             throw new RuntimeException JavaDoc( e );
790         }
791     }
792     
793         public ObjectName JavaDoc
794     getObjectName()
795     {
796         return( getTargetObjectName() );
797     }
798     
799         public Map JavaDoc<String JavaDoc,Object JavaDoc>
800     getAllAttributes( )
801     {
802         Map JavaDoc<String JavaDoc,Object JavaDoc> result = Collections.emptyMap();
803         
804         try
805         {
806             final String JavaDoc[] names = getAttributeNames();
807             
808             final AttributeList JavaDoc attrs = getAttributes(names );
809             
810             result = JMXUtil.attributeListToValueMap( attrs );
811         }
812         catch( Exception JavaDoc e )
813         {
814             throw new RuntimeException JavaDoc( e );
815         }
816         return( result );
817     }
818     
819         public String JavaDoc[]
820     getAttributeNames()
821     {
822         final String JavaDoc attrName = "AttributeNames";
823         
824         Attribute JavaDoc attr = null;
825         try
826         {
827             attr = getCachedAttribute( attrName );
828         }
829         catch( AttributeNotFoundException JavaDoc e )
830         {
831             // it's supposed to be there!
832
attr = null;
833         }
834         catch( Exception JavaDoc e )
835         {
836             throw new RuntimeException JavaDoc( e );
837         }
838         
839         String JavaDoc[] names = null;
840         if ( attr == null )
841         {
842             final MBeanInfo JavaDoc mbeanInfo = getMBeanInfo();
843         
844             names = JMXUtil.getAttributeNames( mbeanInfo.getAttributes() );
845             if ( getMBeanInfoIsInvariant() )
846             {
847                 // only cache if MBeanInfo is invariant
848
cacheAttribute( new Attribute JavaDoc( attrName, names ) );
849             }
850         }
851         else
852         {
853             names = (String JavaDoc[])attr.getValue();
854         }
855         
856         return( names );
857     }
858     
859     /**
860         The values of these Attributes are cached forever. Proxies are handled separately
861         because the API will be getXXX() wherease the Attribute name will be XXXObjectName.
862      */

863     private static final Set JavaDoc<String JavaDoc> CACHED_ATTRIBUTE_NAMES = GSetUtil.newUnmodifiableStringSet(
864                 AMXAttributes.ATTR_MBEAN_INFO_IS_INVARIANT,
865                 AMXAttributes.ATTR_INTERFACE_NAME,
866                 AMXAttributes.ATTR_GROUP,
867                 AMXAttributes.ATTR_FULL_TYPE,
868                 CONTAINEE_J2EE_TYPES );
869
870     private static final String JavaDoc GET_MBEAN_INFO = GET + MBEAN_INFO;
871     private static final String JavaDoc GET_J2EE_TYPE = GET + J2EE_TYPE;
872     private static final String JavaDoc GET_J2EE_NAME = GET + J2EE_NAME;
873     private static final String JavaDoc GET_ATTRIBUTE_NAMES = GET + ATTRIBUTE_NAMES;
874     private static final String JavaDoc GET_CONTAINER = GET + CONTAINER;
875     private static final String JavaDoc GET_EXTRA = GET + "Extra";
876     private static final String JavaDoc GET_ALL_ATTRIBUTES = GET + "AllAttributes";
877     private static final String JavaDoc GET_DOMAIN_ROOT = GET + DOMAIN_ROOT;
878     private static final String JavaDoc GET_OBJECT_NAME = GET + AMXAttributes.ATTR_OBJECT_NAME;
879     
880     /**
881         These Attributes are handled specially. For example, J2EE_TYPE and
882         J2EE_NAME are part of the ObjectName.
883      */

884     private static final Set JavaDoc<String JavaDoc> SPECIAL_METHOD_NAMES = GSetUtil.newUnmodifiableStringSet(
885                 GET_MBEAN_INFO,
886                 GET_J2EE_TYPE,
887                 GET_J2EE_NAME,
888                 GET_ATTRIBUTE_NAMES,
889                 GET_CONTAINER,
890                 GET_DOMAIN_ROOT,
891                 GET_OBJECT_NAME,
892                 GET_EXTRA,
893                 GET_ALL_ATTRIBUTES,
894                 
895                 ADD_NOTIFICATION_LISTENER,
896                 REMOVE_NOTIFICATION_LISTENER
897             );
898     
899     /**
900         Handle a "special" method; one that requires special handling and/or can
901         be dealt with on the client side and/or can be handled most efficiently
902         by special-casing it.
903      */

904         private Object JavaDoc
905     handleSpecialMethod(
906         final Object JavaDoc myProxy,
907         final Method JavaDoc method,
908         final Object JavaDoc[] args )
909         throws ClassNotFoundException JavaDoc, JMException JavaDoc, IOException JavaDoc
910     {
911         final String JavaDoc methodName = method.getName();
912         final int numArgs = args == null ? 0 : args.length;
913         Object JavaDoc result = null;
914         boolean handled = true;
915         
916         if ( numArgs == 0 )
917         {
918             if ( methodName.equals( GET_CONTAINER ) )
919             {
920                 result = getContainer( Util.asAMX(myProxy) );
921             }
922             else if ( methodName.equals( GET_EXTRA ) )
923             {
924                 assert( this instanceof Extra );
925                 result = this;
926             }
927             else if ( methodName.equals( GET_OBJECT_NAME ) )
928             {
929                 result = getTargetObjectName();
930             }
931             else if ( methodName.equals( GET_DOMAIN_ROOT ) )
932             {
933                 result = getDomainRoot( );
934             }
935             else if ( methodName.equals( GET_ATTRIBUTE_NAMES ) )
936             {
937                 result = getAttributeNames();
938             }
939             else if ( methodName.equals( GET_J2EE_TYPE ) )
940             {
941                 result = Util.getJ2EEType( getTargetObjectName() );
942             }
943             else if ( methodName.equals( GET_J2EE_NAME ) )
944             {
945                 result = Util.getName( getTargetObjectName() );
946             }
947             else if ( methodName.equals( GET_ALL_ATTRIBUTES ) )
948             {
949                 result = getAllAttributes();
950             }
951             else
952             {
953                 handled = false;
954             }
955         }
956         else if ( numArgs == 1 && methodName.equals( "equals" ) )
957         {
958             return equals( args[ 0 ] );
959         }
960         else
961         {
962             final Class JavaDoc[] signature = method.getParameterTypes();
963         
964             if ( methodName.equals( ADD_NOTIFICATION_LISTENER ) &&
965                         ( ClassUtil.sigsEqual( NOTIFICATION_LISTENER_SIG1, signature ) ||
966                             ClassUtil.sigsEqual( NOTIFICATION_LISTENER_SIG2, signature ) )
967                     )
968             {
969                 addNotificationListener( args );
970             }
971             else if ( methodName.equals( REMOVE_NOTIFICATION_LISTENER ) &&
972                         ( ClassUtil.sigsEqual( NOTIFICATION_LISTENER_SIG1, signature ) ||
973                             ClassUtil.sigsEqual( NOTIFICATION_LISTENER_SIG2, signature ) )
974                     )
975             {
976                 removeNotificationListener( args );
977             }
978             else
979             {
980                 handled = false;
981             }
982         }
983         
984         if ( ! handled )
985         {
986             assert( false );
987             throw new RuntimeException JavaDoc( "unknown method: " + method );
988         }
989         
990         return( result );
991     }
992     
993         public final Object JavaDoc
994     invoke(
995         final Object JavaDoc myProxy,
996         final Method JavaDoc method,
997         final Object JavaDoc[] args )
998         throws java.lang.Throwable JavaDoc
999     {
1000        try
1001        {
1002            final Object JavaDoc result = _invoke( myProxy, method, args );
1003            
1004            assert( result == null ||
1005                ClassUtil.IsPrimitiveClass( method.getReturnType() ) ||
1006                method.getReturnType().isAssignableFrom( result.getClass() ) ) :
1007                    method.getName() + ": result of type " + result.getClass().getName() +
1008                    " not assignable to " + method.getReturnType().getName() + ", " +
1009                    "interfaces: " + toString( result.getClass().getInterfaces() +
1010                    ", ObjectName = " + JMXUtil.toString( getTargetObjectName() ) );
1011                    
1012            return result;
1013        }
1014        catch( IOException JavaDoc e )
1015        {
1016            getProxyFactory().checkConnection();
1017            throw e;
1018        }
1019        catch( InstanceNotFoundException JavaDoc e )
1020        {
1021            checkValid();
1022            throw e;
1023        }
1024    }
1025    
1026        protected Object JavaDoc
1027    _invoke(
1028        final Object JavaDoc myProxy,
1029        final Method JavaDoc method,
1030        final Object JavaDoc[] args )
1031        throws java.lang.Throwable JavaDoc
1032    {
1033        debugMethod( method.getName(), args );
1034        
1035        // clients can retain proxies that go invalid if their corresponding
1036
// MBeans are removed.
1037
if ( ! targetIsValid() )
1038        {
1039            throw new InstanceNotFoundException JavaDoc( getTargetObjectName().toString() );
1040        }
1041        
1042        Object JavaDoc result = null;
1043        
1044        final String JavaDoc methodName = method.getName();
1045        final int numArgs = args == null ? 0 : args.length;
1046        
1047        boolean handled = false;
1048        
1049        if ( SPECIAL_METHOD_NAMES.contains( methodName ) )
1050        {
1051            handled = true;
1052            result = handleSpecialMethod( myProxy, method, args );
1053        }
1054        else if ( JMXUtil.isIsOrGetter( method ) )
1055        {
1056            assert( ! handled );
1057        
1058            final String JavaDoc attrName = JMXUtil.getAttributeName( method );
1059            
1060            if ( CACHED_ATTRIBUTE_NAMES.contains( attrName ) )
1061            {
1062                result = getCachedAttributeValue( attrName );
1063                handled = true;
1064            }
1065        }
1066        
1067        if ( ! handled )
1068        {
1069            if ( isSingleProxyGetter( method, numArgs) )
1070            {
1071                result = invokeSingleProxyGetter( myProxy, method, args );
1072            }
1073            else if ( isProxySetGetter( method, numArgs ) )
1074            {
1075                result = invokeProxySetGetter( myProxy, method, args );
1076            }
1077            else if ( isProxyMapGetter( method, numArgs ) )
1078            {
1079                result = invokeProxyMapGetter( myProxy, method, args );
1080            }
1081            else if ( isProxyListGetter( method, numArgs ) )
1082            {
1083                result = invokeProxyListGetter( myProxy, method, args );
1084            }
1085            else if ( isProxyCreator( method ) )
1086            {
1087                result = invokeProxyCreator( method, args );
1088            }
1089            else
1090            {
1091                result = super.invoke( myProxy, method, args );
1092            }
1093        }
1094
1095        if ( getDebug() )
1096        {
1097            debug( AMXDebug.methodString( methodName, args ) +
1098                " => " + toString( result ) );
1099        }
1100        
1101        return( result );
1102    }
1103   
1104   
1105        protected void
1106    addNotificationListener( final Object JavaDoc[] args )
1107        throws IOException JavaDoc, InstanceNotFoundException JavaDoc
1108    {
1109        final NotificationListener JavaDoc listener = (NotificationListener JavaDoc)args[ 0 ];
1110        final NotificationFilter JavaDoc filter = (NotificationFilter JavaDoc)(args.length <= 1 ? null : args[ 1 ]);
1111        final Object JavaDoc handback = args.length <= 1 ? null : args[ 2 ];
1112        
1113        getConnection().addNotificationListener(
1114            getTargetObjectName(), listener, filter, handback );
1115    }
1116    
1117        protected void
1118    removeNotificationListener( final Object JavaDoc[] args )
1119        throws IOException JavaDoc, InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc
1120    {
1121        final NotificationListener JavaDoc listener = (NotificationListener JavaDoc)args[ 0 ];
1122        
1123        // important:
1124
// this form removes the same listener registered with different filters and/or handbacks
1125
if ( args.length == 1 )
1126        {
1127            getConnection().removeNotificationListener( getTargetObjectName(), listener );
1128        }
1129        else
1130        {
1131            final NotificationFilter JavaDoc filter = (NotificationFilter JavaDoc)args[ 1 ];
1132            final Object JavaDoc handback = args[ 2 ];
1133            
1134            getConnection().removeNotificationListener(
1135                getTargetObjectName(), listener, filter, handback );
1136        }
1137    }
1138}
1139
1140
1141
1142
1143
1144
Popular Tags