EMMA Coverage Report (generated Sat Jul 01 16:38:45 PDT 2006)
[all classes][jade.jademx.mbean]

COVERAGE SUMMARY FOR SOURCE FILE [JadeAgent.java]

nameclass, %method, %block, %line, %
JadeAgent.java100% (1/1)100% (19/19)81%  (1005/1243)87%  (214.8/248)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JadeAgent100% (1/1)100% (19/19)81%  (1005/1243)87%  (214.8/248)
kill (): void 100% (1/1)19%  (5/27)60%  (3/5)
getFullName (): String 100% (1/1)24%  (7/29)60%  (3/5)
getStateCode (): int 100% (1/1)27%  (8/30)60%  (3/5)
getStateName (): String 100% (1/1)27%  (8/30)60%  (3/5)
setAttribute (Attribute): void 100% (1/1)72%  (53/74)76%  (10.7/14)
invoke (String, Object [], String []): Object 100% (1/1)72%  (79/109)75%  (15/20)
getMBeanInfo (): MBeanInfo 100% (1/1)87%  (227/262)89%  (23.2/26)
waitForJademxAgentBinding (long, int): boolean 100% (1/1)89%  (278/312)89%  (70.4/79)
getAttribute (String): Object 100% (1/1)89%  (133/149)91%  (34.7/38)
setAttributes (AttributeList): AttributeList 100% (1/1)89%  (25/28)78%  (7/9)
JadeAgent (JadePlatform, AgentController, String, String, String, Object []):... 100% (1/1)91%  (50/55)99%  (14.9/15)
setJademxAgent (JademxAgent): void 100% (1/1)92%  (59/64)99%  (6.9/7)
<static initializer> 100% (1/1)94%  (16/17)98%  (2.9/3)
getArguments (): Object [] 100% (1/1)100% (3/3)100% (1/1)
getAttributes (String []): AttributeList 100% (1/1)100% (41/41)100% (11/11)
getClassName (): String 100% (1/1)100% (3/3)100% (1/1)
getLocalName (): String 100% (1/1)100% (3/3)100% (1/1)
getPlatformObjectNameString (): String 100% (1/1)100% (3/3)100% (1/1)
setAgentController (AgentController): void 100% (1/1)100% (4/4)100% (2/2)

1// jademx - JADE management using JMX
2// Copyright 2005 Caboodle Networks, Inc.
3//
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8//
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12// Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 
18package jade.jademx.mbean;
19 
20import jade.jademx.agent.JademxAgent;
21import jade.jademx.util.MBeanUtil;
22import jade.util.Logger;
23import jade.wrapper.AgentController;
24 
25import javax.management.Attribute;
26import javax.management.AttributeList;
27import javax.management.AttributeNotFoundException;
28import javax.management.InvalidAttributeValueException;
29import javax.management.MBeanAttributeInfo;
30import javax.management.MBeanConstructorInfo;
31import javax.management.MBeanException;
32import javax.management.MBeanInfo;
33import javax.management.MBeanNotificationInfo;
34import javax.management.MBeanOperationInfo;
35import javax.management.MBeanParameterInfo;
36import javax.management.ReflectionException;
37 
38/** 
39 * Implementation class for JadeAgentMBeanDef.
40 * <p>The integration between jademx and jade.core.Agent is not as clean
41 * as it could be.  The problem is that jademx is a management subsystem
42 * that really should have some access to JADE internals, but it's been
43 * developed as a piece of application code so that it can use the standard
44 * distribution.  A better solution would be for part of this to be taken
45 * as a core part of the distribution or for a tiny bit more of the
46 * management interface to be exposed.</p>
47 * <p>The specific problem is a combination of information hiding and
48 * the sequence of actions and design constraints.  Specifically:</p>
49 * <ul>
50 * <li>JadeAgent and JademxAgent need to have references to each other
51 * so that the full set of JMX attributes, operations, and notifications can
52 * be implemented.</li>
53 * <li>For certain actions, synchronous operation is desired, so behaviour
54 * scheduling is inappropriate.</li>
55 * <li>It is a design goal that jademx should be able to run <em>non</em>-jademx
56 * JADE agents.</li>
57 * <li>It is a design goal that a JademxAgent should be able to run when
58 * <em>not</em> under the control of jademx.</li>
59 * <li>It is a design goal to be able to have an MBean for an agent even
60 * if that agent was created within JADE instead of via jademx.</li>
61 * <li>The relevant part of agent initialization occurs in the following
62 * order:
63 * <ul>
64 * <li>The JADE agent constructor is invoked, but:
65 * <ul> 
66 * <li>A JADE agent constructor does not have access to its own agent name,
67 * so it can't tell jademx that an agent with that name should exchange
68 * references.</li>
69 * <li>A JADE agent may be created by another agent instead of via jademx,
70 * and jademx can't find out the java class of such agents, so jademx may not 
71 * be able to tell that such an agent should exchange references</li>
72 * </ul> 
73 * </li>
74 * <li>After the agent object has been instantiated, its thread is started,
75 * for example by calling <code>AgentController.start()</code>.  During that
76 * process, <code>Agent.setup()</code> is called.  At that point, the agent
77 * has access to its name but no clean way to get a reference to jademx so
78 * that references can be exchanged.</li>
79 * </ul>
80 * </li>
81 * </ul>
82 * <p>The solution chosen is to expose:
83 * <ul>
84 * <li>the name of a class that can be instantiated to get the MBeanServer,
85 * and</li>
86 * <li>the name of the root of the jademx MBean hierarchy</li>
87 * </ul>
88 * via java system properties.  In this way, the agent can obtain a reference
89 * to jademx and register itself with jademx</p>
90 * <p>Because of the conditions described, it's not feasible to use JADE's
91 * O2A mechanism to pass object references.</p>
92 * <p>Somewhat cleaner ways of doing this could be implemented if:
93 * <ul>
94 * <li>the holder of a platform controller object could register some sort
95 * of environment object that were accessible to the JADE agent, or</li>
96 * <li>the holder of a platform controller object could gain access to the
97 * JADE agent object, or</li>
98 * <li>the holder of a platform controller object could find out what class
99 * an agent is, or</li>
100 * <li>there were a tighter integration between jademx and JADE itself.</li>
101 * </ul>
102 * The first two options, in particular, may violate the principle of
103 * information hiding too much for some people's tastes.
104 * </p>
105 * <p>
106 * Another area where a JADE change could make for a cleaner implementation
107 * would be to open up the NotificationService so that could can see every
108 * message sent rather than having to get sniffed messages from AMS.
109 * </p>
110 * 
111 * 
112 * 
113 * 
114 * 
115 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
116 * TODO: add aclmsgcmp variables as Properties or one one property at at time
117 * setProperty
118 * getProperty
119 * setProperties
120 * getProperties
121 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
122 * 
123 * 
124 * 
125 * 
126 * 
127 * 
128 * 
129 * 
130 * 
131 * 
132 * @author David Bernstein, <a href="http://www.caboodlenetworks.com"
133 *  >Caboodle Networks, Inc.</a>
134 */
135public class JadeAgent extends JadeBase implements JadeAgentMBeanDef {
136    
137    /** JADE MBean type */
138    public final static String TYPE = "Agent";
139    
140    //
141    // ATTRIBUTES
142    //
143    
144    // basic attributes
145    
146    /** arguments attribute name */
147    public static final String ATTR_ARGUMENTS = "Arguments";
148    /** class name attribute name */
149    public static final String ATTR_CLASS_NAME = "ClassName";
150    /** local name attribute name */
151    public static final String ATTR_LOCAL_NAME = "LocalName";
152    /** platform object name string attribute name */
153    public static final String ATTR_PLATFORM_OBJECT_NAME_STRING = 
154        "PlatformObjectNameString";
155    /** full name attribute name */
156    public static final String ATTR_FULL_NAME = "FullName";
157    /** state code attribute name */
158    public static final String ATTR_STATE_CODE = "StateCode";
159    /** state name attribute name */
160    public static final String ATTR_STATE_NAME = "StateName";
161    
162 
163    
164    //
165    // OPERATIONS
166    //
167    
168    // basic operations
169    
170    //    /** activation operation name */
171    //    public static final String OPER_ACTIVATE = "activate";
172    /** shutdown operation name */
173    public static final String OPER_KILL_NAME = "kill";
174    /** unitTestInject operation description */
175    private final static String OPER_KILL_DESC = 
176        "kill this agent";
177    /** signature for a kill operation */
178    public final static String OPER_KILL_SIGNATURE[] = { 
179        // intentionally empty
180    };
181    /** return type for unitTestInject operation */
182    public final static String OPER_KILL_TYPE = 
183        void.class.getName();
184    //    /** startup operation name */
185    //    public static final String OPER_START = "start";
186    //    /** suspension operation name */
187    //    public static final String OPER_SUSPEND = "suspend";
188 
189    
190    //
191    // NOTIFICATIONS
192    //
193    
194    // base notifications
195    
196    /* none at this level */
197    
198     
199    ///** this agent's platform */
200    //private JadePlatform jadePlatform;
201    /** agent controller this MBean represents */
202    private AgentController agentController;
203    /** ObjectName string for this agent's platform */
204    private String platformObjectNameString;
205    /** local (nick) name for agent */
206    private String localName;
207    /** class name for agent */
208    private String className;
209    /** creation arguments */
210    private Object[] arguments;
211 
212    
213    /** my logger */
214    private final Logger logger = 
215        Logger.getMyLogger(JadeAgent.class.getName());
216 
217    // LOCK MONITORING
218    ///** the threadmxbean for lock monitoring */
219    //java.lang.management.ThreadMXBean tmxb = 
220    //   java.lang.management.ManagementFactory.getThreadMXBean();
221 
222    
223    
224    
225    
226    /**
227     * Construct a JADE agent MBean implementation.
228     * @param jadePlatform superior mbean that proxies platform
229     * @param agentController agent controller to set for this MBean
230     */
231    public JadeAgent(
232            JadePlatform jadePlatform,
233            AgentController agentController,
234            String platformObjectNameString,
235            String localName,
236            String className,
237            Object[] arguments
238            ) {
239        super( jadePlatform.getJadeFactory(), TYPE, localName );
240        //this.jadePlatform = jadePlatform;
241        setAgentController( agentController );
242        this.platformObjectNameString = platformObjectNameString;
243        this.localName = localName;
244        this.className = className;
245        this.arguments = arguments;
246        //JadeRuntime jadeRuntime = jadePlatform.getJadeRuntime();
247        // don't register here: done by JadePlatform.bornAgent()
248        
249 
250        // LOCK MONITORING
251        //tmxb.setThreadContentionMonitoringEnabled( true );
252        
253    }
254    
255    /**
256     * set agent controller for this MBean.
257     * must be set via this method or constructor before can do anything.
258     * @param agentController agent controller to set for this MBean
259     */
260    void setAgentController( AgentController agentController ) {
261        this.agentController = agentController;
262    }
263    
264    ///**
265    // * only for use by this package: get this agent's controller.
266    // * @return agent's controller
267    // */
268    //AgentController getAgentController() {
269    //    return agentController;
270    //}
271 
272    /* (non-Javadoc)
273     * @see jade.management.mbean.JadeAgentMBean#getArguments()
274     */
275    public Object[] getArguments() {
276        return arguments;
277    }
278    /* (non-Javadoc)
279     * @see jade.management.mbean.JadeAgentMBean#getClassName()
280     */
281    public String getClassName() {
282        return className;
283    }
284    /* (non-Javadoc)
285     * @see jade.management.mbean.JadeAgentMBean#getLocalName()
286     */
287    public String getLocalName() {
288        return localName;
289    }
290    /* (non-Javadoc)
291     * @see jade.management.mbean.JadeAgentMBean#getPlatformObjectNameString()
292     */
293    public String getPlatformObjectNameString() {
294        return platformObjectNameString;
295    }
296    
297    // BEGIN AgentController MEDIATION
298    
299    // attributes
300 
301    /* (non-Javadoc)
302     * @see jade.management.mbean.JadeAgentMBean#getFullName()
303     */
304    public String getFullName() throws JademxException {
305        String fullName;
306        try {
307            fullName = agentController.getName();
308        }
309        catch ( Exception e ) {
310            throw new JademxException(
311                    "exception getting full JADE name for agent \""+
312                    localName+"\" in platform \""+platformObjectNameString+"\"",
313                    e );
314        }
315        return fullName;
316    }
317    /* (non-Javadoc)
318     * @see jade.management.mbean.JadeAgentMBean#getStateCode()
319     */
320    public int getStateCode() throws JademxException {
321        int stateCode;
322        try {
323            stateCode = agentController.getState().getCode();
324        }
325        catch ( Exception e ) {
326            throw new JademxException(
327                    "exception getting state code for agent \""+
328                    localName+"\" in platform \""+platformObjectNameString+"\"",
329                    e );
330        }
331        return stateCode;
332    }
333    /* (non-Javadoc)
334     * @see jade.management.mbean.JadeAgentMBean#getStateName()
335     */
336    public String getStateName() throws JademxException  {
337        String stateName;
338        try {
339            stateName = agentController.getState().getName();
340        }
341        catch ( Exception e ) {
342            throw new JademxException(
343                    "exception getting state name for agent \""+
344                    localName+"\" in platform \""+platformObjectNameString+"\"",
345                    e );
346        }
347        return stateName;
348    }
349 
350    // operations
351    
352    //    /* (non-Javadoc)
353    //     * @see jade.management.mbean.JadeAgentMBean#activate()
354    //     */
355    //    public void activate() throws StaleProxyException {
356    //        agentController.activate();
357    //    }
358    /* (non-Javadoc)
359     * @see jade.management.mbean.JadeAgentMBean#kill()
360     */
361    public void kill() throws JademxException {
362        try {
363            agentController.kill();
364        }
365        catch ( Exception e ) {
366            throw new JademxException(
367                    "exception killing agent \""+
368                    localName+"\" in platform \""+platformObjectNameString+"\"",
369                    e );
370        }
371    }
372    ///* (non-Javadoc)
373    // * @see jade.management.mbean.JadeAgentMBean#start()
374    // */
375    //public void start() throws StaleProxyException {
376    //    logger.log( Logger.FINE, "entering JadeAgent.start()..." );
377    //    agentController.start();
378    //}
379    //    /* (non-Javadoc)
380    //     * @see jade.management.mbean.JadeAgentMBean#suspend()
381    //     */
382    //    public void suspend() throws StaleProxyException {
383    //        agentController.suspend();
384    //    }
385 
386    // END AgentController MEDIATION
387    
388 
389    // DYNAMIC MBEAN SUPPORT
390 
391    /** MBean information for superclass(es) class hierarchy */
392    private MBeanInfo mBeanInfoSuper = null;
393    /** MBean information for JadeAgent level in class hierarchy */
394    private MBeanInfo mBeanInfoThisLevel = null;
395    /** merged MBean information for JadeAgent and its superclass(es) */
396    private MBeanInfo mBeanInfoJademx = null;
397    /** MBean information from JMXAgent */
398    private MBeanInfo mBeanInfoAgent = null;
399    /** merged MBean information from JadeAgent and JMXAgent */
400    private MBeanInfo mBeanInfo = null;
401    /** agent's DynamicMBean */
402    private JademxAgent jademxAgent = null;
403    /** has mBeanInfo changed since last looked */
404    private Boolean   mBeanInfoChanged = Boolean.FALSE;
405    /** class name for MBeanInfo */
406    private final static String MBI_CLASS_NAME = JadeAgent.class.getName();
407    /** description for MBeanInfo */
408    private final static String MBI_DESCRIPTION = 
409        "MBeanInfo for JadeAgent in class hierarchy"; 
410 
411    
412//    /**
413//     * non-nanosecond version of waitForJademxAgentBinding()
414//     * @param timeout milliseconds to wait
415//     * @return whether binding occurred before timeout
416//     */
417//    public boolean waitForJademxAgentBinding( String timeoutStr ) {
418//        Duration timeout = new Duration( timeoutStr );
419//        long timeoutMS = timeout.toMilliseconds();
420//        return waitForJademxAgentBinding( timeoutMS, 0 );
421//    }
422    
423    /**
424     * wait given amount of time or until interrupted or jademxAgent bound.
425     * if nanosecond argument zero or running on pre-5.0 Java, then the timeout
426     * is calculated in milliseconds (rounded up if nanoseconds specified).
427     * <p><b>IMPLEMENTATION NOTE:</b>Using the Windows version of J2SE 5.0
428     * there is some problem with <code>wait()</code>/<code>notify()</code>,
429     * such that even though the thread calling <code>setJademxAgent()</code> 
430     * has the mBeanInfoChgd lock by virtue of a synchronized block 
431     * (verified by checking the lock owner using the ThreadMXBean), the
432     * JVM throws: 
433     * <code>java.lang.IllegalMonitorStateException: 
434     *       current thread not owner</code>.
435     * when the code tries to use <code>notify()</code>.</p>
436     * <p>As a workaround, the code now repeatedly sleeps rather than depending
437     * on being notified when the desired condition has changed.  Once the
438     * wait/notify problem is fixed, the approach should be reverted (and
439     * rip out all sleep code).</p>
440     * @param timeout milliseconds to wait
441     * @param nanos nanoseconds to wait on top of milliseconds
442     * @return whether MBean bound to instance of JademxAgent
443     */
444    public boolean waitForJademxAgentBinding( long timeout, int nanos ) {
445        final int THOUSAND =       1000;
446        final int MILLION  = THOUSAND * THOUSAND; 
447        final int BILLION  = THOUSAND * MILLION; 
448        //final long MILLISECOND_MS = 1;
449        //final long CENTISECOND_MS = 10;
450        //final long DECISECOND_MS = 100;
451        final long ONE_SECOND_MS = THOUSAND;
452        final long ONE_SECOND_NS = ONE_SECOND_MS * MILLION;
453        final long ONE_MINUTE_MS = 60 * ONE_SECOND_MS;
454        final long TEN_SEC_MS = 10 * ONE_SECOND_MS;
455        final long ONE_MINUTE_NS = 60 * ONE_SECOND_NS;
456        final int MICROSECOND_NS = THOUSAND;
457        long sleepMs = 0;
458        int  sleepNs = 0;
459        if ( ( nanos < 0 ) || ( nanos >= MILLION ) ) {
460            throw new IllegalArgumentException("nanosecond argument "+nanos+
461                    " must be >=0 and <"+MILLION);
462        }
463        boolean isBound;
464        boolean msResolution = false;
465        long startTime = 0;
466        long stopTime;
467        long timeoutMS = timeout;
468        //int timeoutNS = nanos;
469        if ( 0 == nanos ) {
470            msResolution = true;
471        }
472        else { 
473            try {
474                startTime = System.nanoTime(); // JDK 1.5
475            }
476            catch ( NoSuchMethodError nsme1 ) {
477                msResolution = true;
478            }
479        }
480        if ( msResolution ) {
481            startTime = System.currentTimeMillis();
482            stopTime = startTime + timeoutMS;
483            if ( nanos > 0 ) {
484                // gracefully handle < JDK 1.5
485                stopTime++;
486                timeoutMS++;
487            }
488            if ( timeoutMS >= ONE_MINUTE_MS ) {
489                sleepMs = TEN_SEC_MS;
490            }
491            else if ( timeoutMS >= ONE_SECOND_MS ) {
492                sleepMs = ONE_SECOND_MS;
493            }
494            else if ( 0 == timeoutMS ) {
495                sleepMs = ONE_SECOND_MS;
496            }
497            else {
498                sleepMs = timeoutMS;
499            }
500        }
501        else {
502            long waitNs = ((MILLION*timeoutMS)+nanos);
503            stopTime = startTime + waitNs;
504            if ( waitNs >= ONE_MINUTE_NS ) {
505                sleepMs = TEN_SEC_MS;
506            }
507            else if ( waitNs >= ONE_SECOND_NS ) {
508                sleepMs = ONE_SECOND_MS;
509            }
510            else if ( waitNs >= MICROSECOND_NS ) {
511                sleepMs = MICROSECOND_NS;
512            }
513            else {
514                sleepNs = nanos;
515            }
516        }
517        long crntTime = startTime;
518        Thread myThread = Thread.currentThread();
519        synchronized ( mBeanInfoChanged ) {
520            logger.log( Logger.FINER, 
521                    "JadeAgent.waitForJademxAgentBinding(): this.jademxAgent="+
522                    this.jademxAgent);
523            isBound = ( null != jademxAgent );
524        }
525        
526        logger.log(Logger.FINEST,"isBound="+isBound);
527        boolean interrupted = false;
528        while ( !( isBound || interrupted ||
529                ( ( crntTime >= stopTime ) &&
530                        ( stopTime >  startTime ) ) ) ) {
531            synchronized ( mBeanInfoChanged ) {
532                logger.log(Logger.FINEST,"isBound="+isBound+",waiting...");
533                myThread.yield(); //...............
534                try {
535                    // WAIT/NOTIFY
536                    //waiting = true;
537                    
538                    // LOCK MONITORING
539                    //Thread crntThread = Thread.currentThread();
540                    //long waitingThreadId = crntThread.getId();
541                    //String waitingThreadName = crntThread.getName();
542                    //logger.log(Logger.INFO,"waiting thread: id="+
543                    // waitingThreadId+",waitingThreadName="+waitingThreadName);
544                    //waitingTI = tmxb.getThreadInfo( waitingThreadId);
545                    
546                    
547                    logger.log(Logger.FINER,"sleeping "+
548                            sleepMs+"ms, "+sleepNs+"ns...");
549                    if ( msResolution ) {
550                        myThread.sleep( sleepMs );
551                        // WAIT/NOTIFY
552                        //mBeanInfoChanged.wait( timeoutMS );
553                    }
554                    else {
555                        myThread.sleep( sleepMs, sleepNs );
556                        // WAIT/NOTIFY
557                        //mBeanInfoChanged.wait( timeoutMS, timeoutNS );
558                    }
559                }
560                catch ( InterruptedException ie ) {
561                    interrupted = true;
562                }
563                isBound = ( null != jademxAgent );
564            }
565            crntTime = ( msResolution 
566                    ? System.currentTimeMillis() 
567                            : System.nanoTime() );
568            // WAIT/NOTIFY
569            //if ( !( isBound || interrupted ||
570            //        ( ( crntTime >= stopTime ) &&
571            //                ( stopTime >  startTime ) ) ) ) {
572            //    long timeLeft = stopTime - crntTime;
573            //    if ( msResolution ) {
574            //        timeoutMS = timeLeft;
575            //    }
576            //    else {
577            //        timeoutMS = timeLeft / MILLION;
578            //        timeoutNS = (int)(timeoutMS - timeLeft);
579            //    }
580            //}
581            
582        }
583        double elapsedTime = crntTime - startTime;
584        logger.log( Logger.FINE, "isBound="+isBound+", elapsed wait time "+
585                (elapsedTime/(msResolution?THOUSAND:BILLION)+
586                " seconds")); 
587        return isBound;
588    }
589    
590    // LOCK MONITORING
591    ///** ThreadInfo about the waiting thread */
592    //java.lang.management.ThreadInfo waitingTI = null;
593    
594    // WAIT/NOTIFY
595    ///** is there a thread waiting for jademxAgent to be set */
596    //private boolean waiting = false;
597    
598 
599    /**
600     * callback for agent to make its MBeanInfo available.
601     * can be called repeatedly without problem as way of indicating
602     * the MBeanInfo has changed since previous invocation or for first time.
603     * @param jademxAgent DynamicMBean for the agent
604     */
605    public void setJademxAgent( JademxAgent jademxAgent ) {
606        synchronized ( mBeanInfoChanged ) {
607            
608            //LOCK MONITORING
609            //Thread crntThread = Thread.currentThread();
610            //long crntThreadId = crntThread.getId();
611            //String crntThreadName = crntThread.getName();
612            //logger.log( Logger.INFO,"crntThreadId="+crntThreadId+",
613            //  crntThreadName="+crntThreadName );
614            //java.lang.management.ThreadInfo ti = 
615            //  tmxb.getThreadInfo( crntThread.getId());
616            //long threadIds[] = tmxb.getAllThreadIds();
617            //System.err.println("mBeanInfoChanged.hashCode="+
618            //  mBeanInfoChanged.hashCode());
619            //for ( int i = 0; i < threadIds.length; i++ ) {
620            //    long threadId = threadIds[i];
621            //    ti = tmxb.getThreadInfo( threadId );
622            //    String lockname = ti.getLockName();
623            //    if ( ( null != lockname ) && 
624            //         lockname.startsWith("java.lang.Boolean") ) {
625            //        System.err.println(i+". "+threadId+": "+"lockname:"+
626            //          ti.getLockName()+",lockownerid:"+ti.getLockOwnerId()+
627            //          ",lockownername:"+ti.getLockOwnerName());
628            //    }
629            //}
630            
631            
632            logger.log( Logger.FINE, 
633                    "entering JadeAgent.setJademxAgent(),JadeAgent="+this+
634                    ",JadeAgent.hashCode()="+this.hashCode()+",jademxAgent="+
635                    jademxAgent+",jademxAgent.hashCode()="+
636                    jademxAgent.hashCode());
637            this.jademxAgent = jademxAgent;
638            mBeanInfoChanged = Boolean.TRUE;
639            // WAIT/NOTIFY
640            //if ( waiting ) {
641            //    waiting = false;
642            //    mBeanInfoChanged.notifyAll();
643            //}
644            logger.log( Logger.FINE, 
645                    "JadeAgent.setJademxAgent(): this.jademxAgent="+
646                    this.jademxAgent+",this.jademxAgent.hashCode()="+
647                    jademxAgent.hashCode());
648        }
649    }
650    
651    /**
652     * return MBean information for base JADE MBean class.
653     * this is a merge of the agent, this class, and this class's superclass.
654     * @return MBean information for base JADE MBean class
655     */
656    public MBeanInfo getMBeanInfo() {
657        // lazy evaluation
658        if ( null == mBeanInfoJademx ) {
659            
660            // attributes
661            MBeanAttributeInfo aI[] = new MBeanAttributeInfo[] {
662                    new MBeanAttributeInfo( 
663                            ATTR_ARGUMENTS, 
664                            Object[].class.getName(), 
665                            "agent startup arguments",
666                            true, false, false ),
667                    new MBeanAttributeInfo( 
668                            ATTR_CLASS_NAME, 
669                            String.class.getName(), 
670                            "agent class name",
671                            true, false, false ),
672                    new MBeanAttributeInfo( 
673                            ATTR_LOCAL_NAME, 
674                            String.class.getName(), 
675                            "agent local name",
676                            true, false, false ),
677                    new MBeanAttributeInfo( 
678                            ATTR_PLATFORM_OBJECT_NAME_STRING, 
679                            String.class.getName(), 
680                            "agent's platform object name string",
681                            true, false, false ),
682                    new MBeanAttributeInfo( 
683                            ATTR_FULL_NAME, 
684                            String.class.getName(), 
685                            "agent full name",
686                            true, false, false ),
687                    new MBeanAttributeInfo( 
688                            ATTR_STATE_CODE, 
689                            int.class.getName(), 
690                            "agent state code",
691                            true, false, false ),
692                    new MBeanAttributeInfo( 
693                            ATTR_STATE_NAME, 
694                            String.class.getName(), 
695                            "agent state name",
696                            true, false, false )
697            };
698            
699            // constructors
700            MBeanConstructorInfo cI[] = new MBeanConstructorInfo[0];
701            
702            // operations
703            MBeanParameterInfo pIKill[] = new MBeanParameterInfo[0];
704            
705            MBeanOperationInfo oI[] = new MBeanOperationInfo[] {
706                    //new MBeanOperationInfo( OPER_ACTIVATE, 
707                    //        "activate this agent", 
708                    //        pI, 
709                    //        void.class.getName(), 
710                    //        MBeanOperationInfo.ACTION ),
711                    new MBeanOperationInfo( OPER_KILL_NAME, 
712                            OPER_KILL_DESC, 
713                            pIKill, 
714                            OPER_KILL_TYPE, 
715                            MBeanOperationInfo.ACTION )//,
716                    //new MBeanOperationInfo( OPER_START, 
717                    //        "start this agent", 
718                    //        pI, 
719                    //        void.class.getName(), 
720                    //        MBeanOperationInfo.ACTION ),
721                    //new MBeanOperationInfo( OPER_SUSPEND, 
722                    //        "suspend this agent", 
723                    //        pI, 
724                    //        void.class.getName(), 
725                    //        MBeanOperationInfo.ACTION )
726            };
727            
728            // notifications
729            MBeanNotificationInfo nI[] = new MBeanNotificationInfo[0];
730            
731            // now, MBeanInfo for this level of class hierarchy
732            mBeanInfoThisLevel = new MBeanInfo( MBI_CLASS_NAME, MBI_DESCRIPTION,
733                    aI, cI, oI, nI );
734            
735            // finally, MBeanInfo for jademx functionality
736            mBeanInfoSuper = super.getMBeanInfo();
737            mBeanInfoJademx = MBeanUtil.mergeMBeanInfo( 
738                    MBI_CLASS_NAME, MBI_DESCRIPTION, 
739                    mBeanInfoThisLevel, mBeanInfoSuper );
740            
741            synchronized ( mBeanInfoChanged ) {
742                mBeanInfoChanged = Boolean.TRUE;
743            }
744            
745        }
746        
747        // if there's been a change in constituent MBeanInfo, 
748        // reconstruct merged version
749        synchronized ( mBeanInfoChanged ) {
750            if ( mBeanInfoChanged.booleanValue() ) {
751                if ( null == jademxAgent ) {
752                    mBeanInfoAgent = null;
753                    mBeanInfo = mBeanInfoJademx;
754                }
755                else {
756                    mBeanInfoAgent = jademxAgent.getMBeanInfo();
757                    if ( mBeanInfoJademx == mBeanInfoAgent ) {
758                        mBeanInfo = mBeanInfoJademx;
759                    }
760                    else {
761                        mBeanInfo = MBeanUtil.mergeMBeanInfo( 
762                                MBI_CLASS_NAME, MBI_DESCRIPTION,
763                                mBeanInfoJademx, mBeanInfoAgent );
764                    }
765                }
766                mBeanInfoChanged = Boolean.FALSE;
767            }
768        }
769        
770        // this is the merge between this class's info, parent class's info
771        // and any info set by the actual JADE agent
772        return mBeanInfo;
773    }
774 
775 
776    /**
777     * get an attribute value
778     * @param attribute name of attribute to get
779     * @return attribute value
780     * @throws AttributeNotFoundException no such attribute
781     * @throws MBeanException exception from getter
782     * @throws ReflectionException exception invoking getter
783     */
784    public Object getAttribute( String attribute ) 
785    throws AttributeNotFoundException,
786    MBeanException, 
787    ReflectionException {
788        getMBeanInfo(); // make sure have MBeanInfo
789        Object o;
790        if ( MBeanUtil.mBeanHasAttr( mBeanInfoThisLevel, attribute ) ) {
791            try {
792                // base attributes
793                if ( ATTR_ARGUMENTS.equals( attribute ) ) {
794                    o = getArguments();
795                }
796                else if ( ATTR_CLASS_NAME.equals( attribute ) ) {
797                    o = getClassName();
798                }
799                else if ( ATTR_LOCAL_NAME.equals( attribute ) ) {
800                    o = getLocalName();
801                }
802                else if ( ATTR_PLATFORM_OBJECT_NAME_STRING.equals( attribute )){
803                    o = getPlatformObjectNameString();
804                }
805                else if ( ATTR_FULL_NAME.equals( attribute ) ) {
806                    o = getFullName();
807                }
808                else if ( ATTR_STATE_CODE.equals( attribute ) ) {
809                    o = new Integer( getStateCode() );
810                }
811                else if ( ATTR_STATE_NAME.equals( attribute ) ) {
812                    o = getStateName();
813                }
814                // should never get here
815                else {
816                    throw new RuntimeException("unreachable");
817                }        
818            }
819            catch ( JademxException je ) {
820                throw new MBeanException( je );
821            }
822        }
823        else if ( MBeanUtil.mBeanHasAttr( mBeanInfoSuper, attribute ) ) {
824            o = super.getAttribute( attribute );
825        }
826        else if ( ( null != mBeanInfoAgent ) && 
827                   MBeanUtil.mBeanHasAttr( mBeanInfoAgent, attribute ) ) {
828            synchronized ( mBeanInfoChanged ) {
829                o = jademxAgent.getAttribute( attribute );
830            }
831        }
832        else {
833            throw new AttributeNotFoundException(
834                    "no such readable attribute \""+attribute+"\"");
835        }
836        logger.log(Logger.FINE,"for attribute "+attribute+" returning "+o);
837        return o;
838    }
839    
840    /**
841     * get multiple attribute values
842     * @param attributes attributes to be retrieved
843     * @return retrieved attributes 
844     */
845    public AttributeList getAttributes(String[] attributes) {
846        AttributeList aL = null;
847        int attrCount = attributes.length;
848        if ( attrCount >= 0 ) {
849            aL = new AttributeList( attrCount );
850            for ( int i = 0; i < attrCount; i++ ) {
851                try {
852                    String attrName = attributes[i];
853                    aL.add( new Attribute( attrName, getAttribute( attrName )));
854                }
855                catch ( Exception e ) {
856                    throw new RuntimeException( e );
857                }
858            }
859        }
860        return aL;
861    }
862    
863    /**
864     * @param attribute
865     * @throws AttributeNotFoundException
866     * @throws InvalidAttributeValueException
867     * @throws MBeanException
868     * @throws ReflectionException
869     */
870    public void setAttribute( Attribute attribute )
871      throws AttributeNotFoundException,
872             InvalidAttributeValueException,
873             MBeanException,
874             ReflectionException {
875        getMBeanInfo(); // make sure have MBeanInfo
876        String attributeName = attribute.getName();
877        if ( MBeanUtil.mBeanHasAttr( mBeanInfoThisLevel, attributeName ) ) {
878            // i have no writable attributes
879            //throw new AttributeNotFoundException(
880            //        "no such writable attribute"+attribute.getName() );
881            
882            //Object v = attribute.getValue();
883 
884            // should never get here
885            //else {
886                throw new AttributeNotFoundException(
887                        "no such writable attribute"+attributeName );
888            //}
889            
890        }
891        else if ( MBeanUtil.mBeanHasAttr( mBeanInfoSuper, attributeName ) ) {
892            super.setAttribute( attribute );
893        }
894        else if ( ( null != mBeanInfoAgent ) && 
895                  MBeanUtil.mBeanHasAttr( mBeanInfoAgent, attributeName ) ) {
896            synchronized ( mBeanInfoChanged ) {
897                jademxAgent.setAttribute( attribute );
898            }
899        }
900        else {
901            throw new AttributeNotFoundException(
902                    "no such writable attribute \""+attributeName+"\"");
903        }
904    }
905    
906    /**
907     * set multiple attribute values
908     * @param attributes attribute values to set
909     * @return set attribute values
910     */
911    public AttributeList setAttributes(AttributeList attributes) {
912        int attrCount = attributes.size();
913        for ( int i = 0; i < attrCount; i++ ) {
914            try {
915                setAttribute( (Attribute)attributes.get(i) );
916            }
917            catch ( RuntimeException re ) {
918                throw re;
919            }
920            catch ( Exception e ) {
921                throw new RuntimeException( e );
922            }
923        }
924        return attributes;
925    }
926    
927    
928 
929 
930    /**
931     * invoke an action
932     * @param actionName name of action to invoke
933     * @param params action parameters
934     * @param signature action signature
935     * @return object result
936     * @exception MBeanException wrap action exception
937     * @exception ReflectionException wrap action invocation exception
938     */
939    public Object invoke(String actionName, Object params[], String signature[])
940          throws MBeanException, ReflectionException {
941        getMBeanInfo(); // make sure have MBeanInfo
942        Object o = null;
943        if ( MBeanUtil.mBeanHasOper( mBeanInfoThisLevel, actionName, signature ) ) {
944            try {
945                
946                // base operations
947                
948                //if ( OPER_ACTIVATE.equals( actionName ) ) {
949                //    activate();
950                //}
951                /*else*/
952                if ( OPER_KILL_NAME.equals( actionName ) && 
953                     MBeanUtil.signaturesEqual( OPER_KILL_SIGNATURE, signature ) ) {
954                    kill();
955                }
956                //else if ( OPER_START.equals( actionName ) ) {
957                //    start();
958                //}
959                //else if ( OPER_SUSPEND.equals( actionName ) ) {
960                //    suspend();
961                //}
962                
963                // should never get here
964                
965                else {
966                    throw new ReflectionException( new RuntimeException(), 
967                            "no action named \""+actionName+"\"");
968                }
969            }
970            catch ( Exception e ) {
971                throw new MBeanException( e );
972            }
973        }
974        else if ( MBeanUtil.mBeanHasOper( mBeanInfoSuper, actionName, signature ) ) {
975            o = super.invoke( actionName, params, signature );
976        }
977        else if ( ( null != mBeanInfoAgent ) && 
978                  MBeanUtil.mBeanHasOper( mBeanInfoAgent, actionName, signature ) ) {
979            synchronized ( mBeanInfoChanged ) {
980                o = jademxAgent.invoke( actionName, params, signature );
981            }
982        }
983        else {
984            throw new ReflectionException( new RuntimeException(), 
985                    "no action named \""+actionName+"\" with given signature");
986        }
987        return o;
988    }
989    
990//    // UNIT TESTING
991//    
992//    
993//    /**
994//     * assert that agent has bound to JMX
995//     */
996//    public void assertIsJademxBound() {
997//        JademxAgent.assertIsJademxBound( getObjectName(), 
998//                getJadeFactory().getJadeMXServer().getMBeanServer() );
999//    }
1000     
1001}

[all classes][jade.jademx.mbean]
EMMA 2.0.5312 (C) Vladimir Roubtsov