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

COVERAGE SUMMARY FOR SOURCE FILE [JadeRuntime.java]

nameclass, %method, %block, %line, %
JadeRuntime.java100% (1/1)100% (40/40)81%  (1654/2043)86%  (376.6/438)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JadeRuntime100% (1/1)100% (40/40)81%  (1654/2043)86%  (376.6/438)
validateExpectedChildTag (String, String, String): void 100% (1/1)16%  (7/43)60%  (3/5)
preDeregister (): void 100% (1/1)30%  (7/23)52%  (3.7/7)
shutdown (): void 100% (1/1)65%  (135/208)64%  (26.9/42)
readDocument (String, boolean): Document 100% (1/1)68%  (163/239)71%  (32.9/46)
xmlToConfig (String, boolean): JademxConfig 100% (1/1)68%  (91/133)78%  (25/32)
makeAndStartPlatform (Profile, int): JadePlatform 100% (1/1)73%  (97/133)72%  (18/25)
removePlatform (String): void 100% (1/1)74%  (14/19)93%  (3.7/4)
addPlatform (JadePlatform): void 100% (1/1)77%  (17/22)94%  (3.8/4)
instantiateAgent (JadePlatform, ConfigAgentSpecifier, int, int): void 100% (1/1)78%  (140/180)87%  (27/31)
instantiatePlatforms (String, boolean): JadePlatform [] 100% (1/1)85%  (66/78)93%  (13/14)
getTextContent (Node): String 100% (1/1)85%  (89/105)90%  (18/20)
<static initializer> 100% (1/1)85%  (34/40)95%  (5.7/6)
platformFromJadeName (String): JadePlatform 100% (1/1)86%  (30/35)97%  (4.8/5)
getPlatformNames (): String [] 100% (1/1)88%  (35/40)94%  (9.4/10)
getPlatforms (): JadePlatform [] 100% (1/1)88%  (35/40)94%  (9.4/10)
getPlatformObjectNames (): ObjectName [] 100% (1/1)88%  (36/41)94%  (9.4/10)
JadeRuntime (JadeFactory, Runtime): void 100% (1/1)96%  (141/147)88%  (29/33)
agentSpecifierElementToConfig (Element): ConfigAgentSpecifier 100% (1/1)100% (139/139)100% (27/27)
argumentElementToConfig (Element): ConfigArgument 100% (1/1)100% (24/24)100% (7/7)
cvsDateToTimestamp (String): String 100% (1/1)100% (15/15)100% (4/4)
getCopyrightNotice (): String 100% (1/1)100% (2/2)100% (1/1)
getJademxTimestamp (): String 100% (1/1)100% (2/2)100% (1/1)
getJademxVersion (): String 100% (1/1)100% (2/2)100% (1/1)
getTextContentTrim (Node): String 100% (1/1)100% (12/12)100% (4/4)
getVersion (): String 100% (1/1)100% (2/2)100% (1/1)
getVersionInfo (): String 100% (1/1)100% (2/2)100% (1/1)
getVersionTimestamp (): String 100% (1/1)100% (2/2)100% (1/1)
instantiateAgents (JadePlatform, ConfigPlatform, int): void 100% (1/1)100% (27/27)100% (9/9)
instantiatePlatform (ConfigPlatform, int): JadePlatform 100% (1/1)100% (17/17)100% (4/4)
instantiatePlatforms (ConfigRuntime): JadePlatform [] 100% (1/1)100% (55/55)100% (14/14)
platformElementToConfig (Element): ConfigPlatform 100% (1/1)100% (101/101)100% (28/28)
platformNameFromJadeName (String): String 100% (1/1)100% (14/14)100% (3/3)
platformNamesFromConfigResource (String): String [] 100% (1/1)100% (7/7)100% (1/1)
platformNamesFromConfigUrl (String): String [] 100% (1/1)100% (7/7)100% (1/1)
platformProfile (ConfigPlatform, int): Profile 100% (1/1)100% (39/39)100% (13/13)
platformsFromConfigResource (String): JadePlatform [] 100% (1/1)100% (5/5)100% (1/1)
platformsFromConfigUrl (String): JadePlatform [] 100% (1/1)100% (5/5)100% (1/1)
platformsToStrings (JadePlatform []): String [] 100% (1/1)100% (22/22)100% (5/5)
postRegister (Boolean): void 100% (1/1)100% (12/12)100% (4/4)
setPlatformActive (boolean): void 100% (1/1)100% (4/4)100% (2/2)

1// jademx - JADE management using JMX
2// Copyright 2005-2006 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.BootProfileImpl;
21import jade.core.Profile;
22import jade.core.Runtime;
23import jade.jademx.config.jademx.onto.ConfigAgentSpecifier;
24import jade.jademx.config.jademx.onto.ConfigArgument;
25import jade.jademx.config.jademx.onto.ConfigPlatform;
26import jade.jademx.config.jademx.onto.ConfigRuntime;
27import jade.jademx.config.jademx.onto.JademxConfig;
28import jade.util.Logger;
29import jade.util.leap.List;
30import jade.wrapper.PlatformController;
31 
32import java.lang.reflect.Constructor;
33import java.net.MalformedURLException;
34import java.net.URL;
35import java.util.HashMap;
36import java.util.Iterator;
37import java.util.MissingResourceException;
38import java.util.ResourceBundle;
39 
40import javax.management.ObjectName;
41import javax.xml.XMLConstants;
42import javax.xml.parsers.DocumentBuilder;
43import javax.xml.parsers.DocumentBuilderFactory;
44import javax.xml.parsers.ParserConfigurationException;
45import javax.xml.validation.Schema;
46import javax.xml.validation.SchemaFactory;
47 
48import org.w3c.dom.Document;
49import org.w3c.dom.Element;
50import org.w3c.dom.Node;
51import org.w3c.dom.NodeList;
52import org.xml.sax.SAXException;
53 
54/** 
55 * MBean implementation wrapper for JADE Runtime.
56 * TODO: some more work so can get line numbers even though using DOM XML.
57 * @author David Bernstein, <a href="http://www.caboodlenetworks.com"
58 *  >Caboodle Networks, Inc.</a>
59 */
60public class JadeRuntime 
61  extends JadeBase 
62  implements JadeRuntimeMBean, JadePlatformMonitor {
63    
64    ///** the JADE runtime */
65    //private Runtime runtime;
66    /** JADE copyright notice */
67    private static String copyrightNotice = Runtime.getCopyrightNotice();
68    /** JADE version info */
69    private static String versionInfo = Runtime.instance().getVersionInfo();
70    /** JADE version */
71    private static String version;
72    /** JADE version timestamp */
73    private static String versionTimestamp;
74    /** jademx version */
75    private static String jademxVersion = null;
76    /** jademx version timestamp */
77    private static String jademxTimestamp = null;
78    /** jademx resource bundle name */
79    private static final String JADEMX_BUNDLE_NAME = 
80        "jade.jademx.config.jademx";
81    /** name of jademx major version property */
82    private static final String JADEMX_MAJOR_VERSION_PROP =
83        "jademx.major.version";
84    /** name of jademx minor version property */
85    private static final String JADEMX_MINOR_VERSION_PROP =
86        "jademx.minor.version";
87    /** name of jademx patch version property */
88    private static final String JADEMX_PATCH_VERSION_PROP =
89        "jademx.patch.version";
90    /** name of jademx cvs date property */
91    private static final String JADEMX_CVS_DATE_PROP =
92        "jademx.cvs.date";
93    /** my logger */
94    private final Logger logger = 
95        Logger.getMyLogger(JadeRuntime.class.getName());
96 
97    /** thread group to put created threads in */
98    private ThreadGroup threadGroup = null;
99    /** active state of platform currently being started */
100    private volatile boolean platformActive = false;
101    /** milliseconds to wait for thread initialization (+ns) */
102    private long INIT_SLEEP_MS = 50;
103    /** nanoseconds to wait for thread initialization (+ms) */
104    private int INIT_SLEEP_NS = 0; 
105    ///** prefix for platform name */
106    //private final static String PLATFORM_MBEAN_NAME_PREFIX = "platform";
107    
108    /** signature for operations that take one string argument */
109    public final static String SIGN_STR[] = 
110        new String[] { String.class.getName() };
111    
112    /** has shutdown been called at least once */
113    private Boolean shutdownInvoked = Boolean.FALSE;
114 
115    
116    /**
117     * runtime implementation wrapper for JADE runtime.
118     * @param jadeFactory factory this MBean related to
119     * @param runtime JADE runtime this MBean proxies
120     */
121    public JadeRuntime( JadeFactory jadeFactory, Runtime runtime ) {
122        super( jadeFactory, TYPE, jadeFactory.getRuntimeName() );
123        //this.runtime = runtime;
124 
125        int dashIndex = versionInfo.indexOf('-');
126        version = versionInfo.substring( 0, dashIndex-1 );
127        version = version.trim();
128        version = version.replaceAll("JADE","");
129        //System.out.println("version:"+version);
130        versionTimestamp = 
131            cvsDateToTimestamp( versionInfo.substring( dashIndex+1 ) );
132        //System.out.println("versionTimestamp:"+versionTimestamp);
133        
134        ResourceBundle b = ResourceBundle.getBundle(JADEMX_BUNDLE_NAME);
135        try {
136            String major = b.getString( JADEMX_MAJOR_VERSION_PROP );
137            String minor = b.getString( JADEMX_MINOR_VERSION_PROP );
138            String patch = b.getString( JADEMX_PATCH_VERSION_PROP );
139            jademxVersion = major + "." + minor + "." + patch;
140        }
141        catch ( MissingResourceException mre ) {
142            jademxVersion = "?";
143        }
144        String cvsDate = null;
145        try {
146            cvsDate = b.getString( JADEMX_CVS_DATE_PROP );
147        }
148        catch ( MissingResourceException mre ) {
149            cvsDate = "?";
150        }
151        int colonPos = cvsDate.indexOf(':');
152        int dollarPos = cvsDate.lastIndexOf('$');
153        String date = cvsDate.substring(colonPos + 1, dollarPos);
154        jademxTimestamp = cvsDateToTimestamp( date );
155        
156        logger.log( Logger.FINE, "created jademx JadeRuntime" );
157        logger.info( "jademx "+jademxVersion+
158                ", LGPL license, http://jademx.sourceforge.net/");
159    }
160    
161    /**
162     * convert cvs-style date/time string to iso 8601 timestamp
163     * @param cvsDate date to convert
164     * @return equivalent iso8601 timestamp
165     */
166    private String cvsDateToTimestamp( String cvsDate ) {
167        String timestamp = cvsDate.trim();
168        timestamp = timestamp.replace('/','-');
169        timestamp = timestamp.replace(' ','T');
170        return timestamp;
171    }
172 
173    /* (non-Javadoc)
174     * @see jade.management.mbean.JadeRuntimeMBean#getCopyrightNotice()
175     */
176    public String getCopyrightNotice() {
177        return copyrightNotice;
178    }
179    
180    /* (non-Javadoc)
181     * @see jade.management.mbean.JadeRuntimeMBean#getCopyrightNotice()
182     */
183    public String getVersionInfo() {
184        return versionInfo;
185    }
186    /* (non-Javadoc)
187     * @see jade.jademx.mbean.JadeRuntimeMBean#getVersion()
188     */
189    public String getVersion() {
190        return version;
191    }
192    /* (non-Javadoc)
193     * @see jade.jademx.mbean.JadeRuntimeMBean#getVersionTimestamp()
194     */
195    public String getVersionTimestamp() {
196        return versionTimestamp;
197    }
198    /* (non-Javadoc)
199     * @see jade.jademx.mbean.JadeRuntimeMBean#getVersion()
200     */
201    public String getJademxVersion() {
202        return jademxVersion;
203    }
204    /* (non-Javadoc)
205     * @see jade.jademx.mbean.JadeRuntimeMBean#getJademxTimestamp()
206     */
207    public String getJademxTimestamp() {
208        return jademxTimestamp;
209    }
210    
211    
212    /** 
213     * set of platforms managed by this runtime.
214     * map is: JADE platform name => JadePlatform 
215     */
216    private HashMap platformMap = new HashMap();
217    /**
218     * add a platform to set managed by runtime
219     * @param jadePlatform platform to add
220     */
221    void addPlatform( JadePlatform jadePlatform ) {
222        synchronized ( platformMap ) {
223            platformMap.put( jadePlatform.getPlatformController().getName(), 
224                    jadePlatform );
225        }
226    }
227    /**
228     * remove a platform from set managed by runtime
229     * @param platformName JADE name of platform to remove 
230     */
231    void removePlatform( String platformName ) {
232        synchronized ( platformMap ) {
233            platformMap.remove( platformName );
234        }
235    }
236    
237    // ATTRIBUTES DESCRIBING CHILD MBEANS 
238    
239 
240    /* (non-Javadoc)
241     * @see jade.jademx.mbean.JadeRuntimeMBean#getPlatforms()
242     */
243    public JadePlatform[] getPlatforms() {
244        JadePlatform platforms[];
245        synchronized ( platformMap ) {
246            int agentCount = platformMap.size();
247            platforms = new JadePlatform[agentCount];
248            Iterator agentIter = platformMap.values().iterator();
249            int agentIndex = 0;
250            while ( agentIter.hasNext() ) {
251                platforms[agentIndex++] = (JadePlatform)agentIter.next();
252            }
253        }
254        return platforms;
255    }
256    
257 
258    /* (non-Javadoc)
259     * @see jade.jademx.mbean.JadeRuntimeMBean#getPlatformNames()
260     */
261    public String[] getPlatformNames() {
262        String platforms[];
263        synchronized ( platformMap ) {
264            int agentCount = platformMap.size();
265            platforms = new String[agentCount];
266            Iterator agentIter = platformMap.values().iterator();
267            int agentIndex = 0;
268            while ( agentIter.hasNext() ) {
269                platforms[agentIndex++] = agentIter.next().toString();
270            }
271        }
272        return platforms;
273    }
274    
275    
276    /* (non-Javadoc)
277     * @see jade.jademx.mbean.JadeRuntimeMBean#getPlatformObjectNames()
278     */
279    public ObjectName[] getPlatformObjectNames() {
280        ObjectName platforms[];
281        synchronized ( platformMap ) {
282            int agentCount = platformMap.size();
283            platforms = new ObjectName[agentCount];
284            Iterator agentIter = platformMap.values().iterator();
285            int agentIndex = 0;
286            while ( agentIter.hasNext() ) {
287                platforms[agentIndex++] = 
288                    ((JadePlatform)agentIter.next()).getObjectName();
289            }
290        }
291        return platforms;
292    }
293    
294    
295    
296    /* (non-Javadoc)
297     * @see jade.jademx.mbean.JadeRuntimeMBean#shutdown()
298     */
299    public void shutdown() throws JademxException {
300        logger.log( Logger.FINE, "entering JadeRuntime.shutdown()");
301        
302        // make sure don't try to do this more than once!
303        synchronized ( shutdownInvoked ) {
304            if ( shutdownInvoked.booleanValue() ) {
305                throw new JademxException(
306                        "JadeRuntime.shutdown() invoked multiple times");
307            }
308            shutdownInvoked = Boolean.TRUE;
309        }
310 
311        // in this method, try to be as thorough as possible in cleaning up,
312        // so even if an exception is thrown, catch it and keep on going.
313        // the first exception caught is re-thrown, subsequent exceptions are
314        // logged
315        
316        JademxException je = null; // 1st exception received
317        JadePlatform jadePlatforms[] = null;
318        synchronized ( platformMap ) {
319            // copy platformMap out so don't have concurrent modification
320            // when they go away
321            jadePlatforms = new JadePlatform[platformMap.size()];
322            logger.log( Logger.FINE, "JadeRuntime.shutdown():found "+jadePlatforms.length+" platforms...");
323            Iterator platformIter = platformMap.values().iterator();
324            int i = 0;
325            while ( platformIter.hasNext() ) {
326                jadePlatforms[i++]= (JadePlatform)platformIter.next();
327            }            
328        }
329        logger.log( Logger.FINE, "JadeRuntime.shutdown():about to loop thru "+jadePlatforms.length+" platforms...");
330        for ( int i = 0; i < jadePlatforms.length; i++ ) {
331            JadePlatform platform = (JadePlatform)jadePlatforms[i];
332            logger.log( Logger.FINE, "about to try to kill platform:"+platform);
333            try {
334                platform.kill();
335            } 
336            catch (JademxException e) {
337                if ( null == je ) {
338                    je = e; // only keep 1st
339                }
340                else {
341                    logger.log( Logger.SEVERE, 
342                      "non-first platform kill exception not thrown but logged", 
343                      e );
344                }
345            }
346            // platform.kill tries to remove this, but in case it didn't
347            // get that far, this is an ok 2nd attempt to get rid of it
348            removePlatform( platform.getPlatformName() );
349        }
350        logger.log( Logger.FINE, "about to unregister "+this);
351        try {
352            unregister();
353        } 
354        catch ( Exception e ) {
355            logger.log( Logger.SEVERE, "JadeRuntime.shutdown(): "+
356                    "exception unregistering:"+e);
357            e.printStackTrace( System.out );
358            if ( null == je ) {
359                je = new JademxException("exception unregistering "+this+":"+e,
360                        e );
361            }
362            else {
363                logger.log( Logger.SEVERE, 
364                  "non-first platform unregister exception not thrown but logged", 
365                  e );
366            }
367        }
368        if ( null != je ) {
369            throw je;
370        }
371    }
372    
373 
374    /**
375     * read in jademx xml configuration document
376     * @param xml string description of how to get jademx XML configuration
377     * @param isResource true=>it's a resource name, false=>URL string
378     * @return jademx xml configuration document
379     * @throws JademxException problem reading document
380     */
381    private Document readDocument(String xml, boolean isResource) 
382      throws JademxException {
383        ClassLoader myClassLoader = this.getClass().getClassLoader();
384        
385        // get config schema
386        SchemaFactory schemaFactory = 
387            SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
388        URL configSchemaURL = 
389            myClassLoader.getResource( CONFIG_XML_SCHEMA_RESOURCE_NAME );
390        Schema schema = null;
391        logger.log( Logger.CONFIG, 
392                "jademx config schema url: " + configSchemaURL );
393        
394        try {
395            schema = schemaFactory.newSchema( configSchemaURL );
396        }
397        catch ( SAXException saxe ) {
398            // it's an unrecoverable internal or configuration error if
399            // can't parse the jademx configuration schema
400            throw new JademxException(
401                    "exception creating jademx configuration schema from URL "+
402                    configSchemaURL,saxe);
403        }
404        
405        // get document builder
406        DocumentBuilderFactory documentBuilderFactory =
407            DocumentBuilderFactory.newInstance();
408        
409        logger.log( Logger.FINER, 
410                "documentBuilderFactory:"+documentBuilderFactory);
411        
412        documentBuilderFactory.setCoalescing( true );
413        documentBuilderFactory.setExpandEntityReferences( true );
414        documentBuilderFactory.setIgnoringComments( true );
415        documentBuilderFactory.setIgnoringElementContentWhitespace( false);
416        documentBuilderFactory.setNamespaceAware( true );
417        try {
418            documentBuilderFactory.setXIncludeAware( true );
419        }
420        catch ( NoSuchMethodError nsme ) {
421            logger.log( Logger.CONFIG, 
422                    "(NoSuchMethodError)"+
423                    "XInclude not supported by DocumentBuilderFactory "+
424                    documentBuilderFactory );
425        }
426        catch ( UnsupportedOperationException uoe ) {
427            logger.log( Logger.CONFIG, 
428                    "(UnsupportedOperationException)"+
429                    "XInclude not supported by DocumentBuilderFactory "+
430                    documentBuilderFactory );
431        }
432        try {
433            documentBuilderFactory.setSchema( schema );
434        }
435        catch ( NoSuchMethodError nsme ) {
436            logger.log( Logger.CONFIG, 
437                    "(NoSuchMethodError)"+
438                    "schema setting not supported by DocumentBuilderFactory "+
439                    documentBuilderFactory );
440        }
441        catch ( UnsupportedOperationException uoe ) {
442            logger.log( Logger.CONFIG, 
443                    "(UnsupportedOperationException)"+
444                    "schema setting not supported by DocumentBuilderFactory "+
445                    documentBuilderFactory );
446        }
447        DocumentBuilder documentBuilder = null;
448        try {
449            documentBuilder = documentBuilderFactory.newDocumentBuilder();
450        }
451        catch ( ParserConfigurationException pcee ) {
452            // it's an unrecoverable internal or configuration error if
453            // can't create a document builder to parse configuration
454            throw new JademxException(
455                    "exception creating jademx configuration document builder ",
456                    pcee);
457        }
458        
459        // normalize spec to a URL
460        URL configURL;
461        try {
462            configURL = ( isResource
463                    ? myClassLoader.getResource( xml )
464                    : new URL( xml ) );
465        } 
466        catch ( MalformedURLException murle ) {
467            throw new JademxException( "error creating URL for \""+xml+"\"", 
468                    murle);
469        }
470        logger.log( Logger.CONFIG, "jademx config url: " + configURL );
471        if ( null == configURL ) {
472            throw new JademxException( "bad jademx config url",
473                   new MalformedURLException("unable to get jademx config URL "+
474                            (isResource?"for resource ":"")+xml));
475        }        
476        // read config in
477        String configUrlString = configURL.toExternalForm();
478        Document document;
479        try {
480            document = documentBuilder.parse( configUrlString );
481        }
482        catch ( Exception e ) {
483            throw new JademxException("error parsing configuration \""+
484                    configUrlString+"\"", e);
485        }
486        return document;
487    }
488    
489 
490    /**
491     * make a boot profile representing platform options
492     * @param platform platform configuration object
493     * @param platformIndex place in platform list
494     */
495    private Profile platformProfile( ConfigPlatform platform, int platformIndex ) {
496        
497        List optionList = platform.getOptions();
498        int optionCount = 0;
499        if ( null != optionList ) {
500            optionCount = optionList.size();
501        }
502        String[] options = new String[optionCount];
503        if ( optionCount > 0 ) {
504            Iterator optionI = optionList.iterator();
505            int i = 0;
506            while ( optionI.hasNext() ) {
507                options[i++] = (String)optionI.next();
508            }
509        }
510 
511        // put options in jade object
512        BootProfileImpl profile = new BootProfileImpl( options );
513        
514        return profile;
515    }
516    
517    /**
518     * convert XML platform element to jademx platform configuration
519     * @param platformElement platform element to convert
520     * @return platform configuration equivalent of platform element
521     */
522    private ConfigPlatform platformElementToConfig( Element platformElement ) 
523      throws JademxException {
524        ConfigPlatform platform = new ConfigPlatform();
525        
526        // options
527        
528        // get platform options
529        NodeList optionsList = 
530            platformElement.getElementsByTagName( OPTIONS_TAG );
531        // when we can use assertions...
532        // assert 1 == optionsList.getLength() : optionsList.getLength();
533        Element optionsElement = (Element)optionsList.item( 0 );
534        NodeList optionList = null;
535        if ( null != optionsElement ) {
536            optionList = optionsElement.getElementsByTagName( OPTION_TAG );
537        }
538        int optionCount = 0;
539        if ( null != optionList ) {
540            optionCount = optionList.getLength();
541        }
542        for ( int i = 0; i < optionCount; i++ ) {
543            Element optionElement= (Element)optionList.item(i);
544            String option = getTextContent( optionElement );
545            platform.addOption( option );
546        }
547        
548        // agent specifiers
549        
550        // get agent specifiers element
551        NodeList agentSpecifiersList = 
552            platformElement.getElementsByTagName( AGENT_SPECIFIERS_TAG );
553        // when we can use assertions...
554        // assert 1 == optionsList.getLength() : optionsList.getLength();
555        Element agentSpecifiersElement = null;
556        if ( null != agentSpecifiersList ) {
557            agentSpecifiersElement = (Element)agentSpecifiersList.item( 0 );
558        }
559        NodeList agentSpecifierList = null;
560        if ( null != agentSpecifiersElement ) {
561            agentSpecifierList =
562                agentSpecifiersElement.getElementsByTagName( 
563                        AGENT_SPECIFIER_TAG );
564        }
565        int agentCount = 0;
566        if ( null != agentSpecifierList ) {
567            agentCount = agentSpecifierList.getLength();
568        }
569        // for each <agent-specifier>
570        for ( int i = 0; i < agentCount; i++ ) {
571            // fire up the agent
572            Element agentSpecifierElement = (Element)agentSpecifierList.item(i);
573            ConfigAgentSpecifier agentSpecifier = 
574                agentSpecifierElementToConfig( agentSpecifierElement );
575            platform.addAgentSpecifier( agentSpecifier );
576        }
577        
578        
579        return platform;
580    }
581 
582    
583    /**
584     * provide DOM Level 3 functionality to get text even if DOM Level 2.
585     * @param node the node whose text content to get
586     * @return the collected text content for the element
587     */
588    private String getTextContent( Node node ) {
589        String textContent = null;
590        if ( null != node ) {
591            StringBuffer sb = new StringBuffer();
592            
593            // DOM Level 3
594            //sb.append( element.getTextContent() );
595            
596            // DOM Level 2
597            node.normalize();
598            
599            short nodeType = node.getNodeType();
600            switch ( nodeType ) {
601                case Node.CDATA_SECTION_NODE:
602                case Node.TEXT_NODE:
603                    logger.log( Logger.FINEST, 
604                            "CDATA or TEXT:"+node.getNodeValue());
605                    sb.append( node.getNodeValue() );
606                    break;
607                case Node.ENTITY_REFERENCE_NODE:
608                    logger.log( Logger.WARNING, 
609                            "entity references not supported: " + 
610                            node.getNodeName()+" not expanded");
611                    break;
612                default:
613                    logger.log( Logger.FINEST, "node type:"+nodeType);
614                
615                NodeList nodeList = node.getChildNodes();
616                int nodeCount = nodeList.getLength();
617                
618                for ( int i = 0; i < nodeCount; i++ ) {
619                    Node n = nodeList.item( i );
620                    sb.append( getTextContent( n ) );
621                }
622            }
623            
624            textContent = sb.toString();
625        }
626        logger.log( Logger.FINER, "returning \""+textContent+"\"");
627        return textContent;
628    }
629    
630    /**
631     * a version of getTextContent that trims the returned string safely
632     * @param node the node whose text content to get
633     * @return the (trimmed if not null) text content for the element
634     */
635    private String getTextContentTrim( Node node ) {
636        String textContent = getTextContent( node );
637        if ( null != textContent) {
638            textContent = textContent.trim();
639        }
640        return textContent;
641    }
642   
643    /* (non-Javadoc)
644     * @see jade.jademx.mbean.JadePlatformMonitor#setPlatformActive(boolean)
645     */
646    public void setPlatformActive( boolean platformActive ) {
647        this.platformActive = platformActive;
648    }
649    
650    
651    /**
652     * make thread for this platform, start it, make its MBean and return it.
653     * @param profile profile to use to start platform
654     * @param platformIndex platform number
655     * @return platform MBean implementation
656     */
657    private JadePlatform makeAndStartPlatform( 
658            Profile profile, int platformIndex ) {
659        
660        //System.err.println("JadeRuntime.makeAndStartPlatform(): my thread:"+
661        //        Thread.currentThread()+",id:"+Thread.currentThread().getId());
662 
663        // make Runnable for the thread
664        
665        JadeRunnable jadeRunnable = 
666            new JadeRunnable( profile, this );
667        String threadName = "JADE platform "+platformIndex;
668        Thread platformThread = 
669            new Thread( threadGroup, jadeRunnable, threadName );
670 
671        
672        //TODO: do we need to set context class loader..........?
673        //platformThread.setContextClassLoader(
674        // Thread.currentThread().getContextClassLoader());
675        
676        // start the thread
677        
678        platformActive = false;
679        platformThread.start();
680 
681        logger.log( Logger.FINER, "waiting for platform "+platformIndex+
682        " thread to start...");
683        while ( !platformActive ) {
684            try {
685                Thread.sleep( INIT_SLEEP_MS, INIT_SLEEP_NS );
686            }
687            catch ( InterruptedException ie ) {
688                String msg = "interrupted while waiting for platform "+
689                        platformIndex+" to start";
690                logger.log( Logger.SEVERE, msg, ie );
691                // this is unrecoverable
692                throw new RuntimeException( msg, ie );
693            }
694        }
695        logger.log( Logger.FINER, "platform "+platformIndex+" started");
696 
697        // make JadePlatformMBean and return its canonical string name
698        
699        PlatformController platformController = 
700            jadeRunnable.getPlatformController();
701 
702        String platformName = "platform" + platformIndex;
703        JadePlatform jadePlatform = null;
704        try {
705            jadePlatform = 
706                new JadePlatform( this, 
707                        platformName, platformController, platformThread );
708            jadePlatform.setParentObjectName( getObjectName() );
709        } 
710        catch (Exception e) {
711            // unrecoverable
712            throw new RuntimeException("exception creating platform mbean", e);
713        }
714        if ( null == jadePlatform ) {
715            throw new RuntimeException("null JadePlatform");
716        }
717        //System.err.println("JadeRuntime.makeAndStartPlatform(): "+
718        //"platformThread:"+platformThread+",id:"+platformThread.getId());
719        return jadePlatform;
720    }
721    
722    /**
723     * verify that an expected child tag found.
724     * If the XML library being used can't read a schema, then this can
725     * be helpful in debugging.
726     * TODO: get line number into error message with fancier DOM programming.
727     * @param text the text derived for the node
728     * @param parent name of the parent node
729     * @param child name of this node
730     * @throws JademxException on problem
731     */
732    private void validateExpectedChildTag( 
733            String text, String parent, String child ) 
734      throws JademxException {
735      
736        if ( null == text ) {
737            throw new JademxException("<"+child+"> not found inside <"+ 
738                    parent +"> in jademx configuration");
739        }
740        if ( text.length() == 0 ) {
741            throw new JademxException("empty <"+child+"> inside <"+
742                    parent+"> in jademx configuration");
743        }
744    }
745    
746    /** array of one String class, for Class.getConstructor() */
747    private static final Class oneStringArg[] = new Class[] {String.class};
748    
749    /**
750     * start up specified agent
751     * @param jadePlatform platform mbean implementation
752     * @param agentSpecifier agent specifier
753     * @param platformIndex platform number
754     * @param agentIndex agent number with respect to platform
755     * @throws JademxException problem starting agent
756     */
757    private void instantiateAgent( JadePlatform jadePlatform,
758            ConfigAgentSpecifier agentSpecifier, int platformIndex, int agentIndex )
759      throws JademxException {
760 
761        logger.log( Logger.CONFIG, 
762                "platform " + platformIndex +", agent " + agentIndex );
763 
764        // get agent name
765        String agentName = agentSpecifier.getName();
766        logger.log( Logger.CONFIG, 
767                "agent name" + ":\"" + agentName +"\"");
768 
769        // get agent class name
770        String className = agentSpecifier.getClassname();
771        logger.log( Logger.CONFIG, 
772                "class name" + ":\"" + className +"\"");
773 
774        // get agent arguments
775        List argumentList = agentSpecifier.getArguments();
776        int argumentCount = 0;
777        if ( null != argumentList ) {
778            argumentCount = argumentList.size();
779        }
780        Object[] arguments = new Object[argumentCount];
781        if ( argumentCount > 0 ) {
782            Iterator argumentI = argumentList.iterator();
783            int argNum = 0;
784            while ( argumentI.hasNext() ) {
785                ConfigArgument argument = (ConfigArgument)argumentI.next();
786                String argumentValue = argument.getValue();
787                // permit intentional null argument
788//                if ( null == argumentValue ) {
789//                    NullPointerException npe = new NullPointerException(
790//                            "platform "+jadePlatform+", agent "+agentSpecifier+
791//                            ", argument value "+argNum+" is null");
792//                    throw new JademxException( "null argument value", npe );
793//                }
794                String argumentClassName = argument.getClassname();
795                Object thisArg;
796                if ( ( null != argumentClassName ) && 
797                     ( argumentClassName.trim().length() > 0 ) ) {
798                    try {
799                        logger.log( Logger.FINER,
800                                "constructing non-String argument \""+
801                                argument+"\" of class \""+argumentClassName+"\"");
802                        Constructor constructor =
803                            Class.forName( argumentClassName ).
804                            getConstructor( oneStringArg );
805                        thisArg =
806                            constructor.newInstance( (Object[])
807                                    new String[] { argumentValue } );
808                    }
809                    catch ( Exception e) {
810                        String msg = 
811                            "problem constructing argument "+argNum+" "+
812                            argumentClassName + "("+argument+") "+
813                            "starting agent "+agentName+
814                            " in platform "+platformIndex;
815                        logger.log( Logger.SEVERE, msg, e );
816                        throw new JademxException( msg, e );
817                    }
818                }
819                else {
820                    thisArg = argumentValue;
821                }
822                arguments[argNum++] = thisArg;
823            }
824        }
825        
826        jadePlatform.createNewAgent( agentName, className, arguments );
827 
828    }
829    
830    
831    /**
832     * convert XML agent specifier element to agent specifier config object
833     * @param agentSpecifierElement agent specifier element in xml config
834     * @throws JademxException problem converting
835     */
836    private ConfigAgentSpecifier agentSpecifierElementToConfig( 
837            Element agentSpecifierElement ) throws JademxException {
838        
839        ConfigAgentSpecifier agentSpecifier = new ConfigAgentSpecifier();
840 
841        // get agent name
842        NodeList agentNameList = 
843            agentSpecifierElement.getElementsByTagName( AGENT_NAME_TAG );
844        Element agentNameElement = (Element)agentNameList.item( 0 );
845        String agentName = getTextContentTrim( agentNameElement );
846        validateExpectedChildTag( agentName, 
847                AGENT_SPECIFIER_TAG, AGENT_NAME_TAG );
848        logger.log( Logger.CONFIG, 
849                "agent name" + ":\"" + agentName +"\"");
850        agentSpecifier.setName( agentName );
851 
852        // get agent class name
853        NodeList classNameList = 
854            agentSpecifierElement.getElementsByTagName( CLASS_NAME_TAG );
855        Element classNameElement = (Element)classNameList.item( 0 );
856        String className = getTextContentTrim( classNameElement );
857        validateExpectedChildTag( className, 
858                AGENT_SPECIFIER_TAG, CLASS_NAME_TAG );
859        logger.log( Logger.CONFIG, 
860                "class name" + ":\"" + className +"\"");
861        agentSpecifier.setClassname( className );
862 
863        // get agent arguments
864        NodeList argumentsList = 
865            agentSpecifierElement.getElementsByTagName( ARGUMENTS_TAG );
866        int argumentCount = 0;
867        NodeList argumentList = null; 
868        if ( null != argumentsList) {
869            Element argumentsElement = (Element)argumentsList.item( 0 );
870            if ( null != argumentsElement ) {
871                argumentList = 
872                    argumentsElement.getElementsByTagName( ARGUMENT_TAG );
873                argumentCount = argumentList.getLength();
874            }
875        }
876         for ( int i = 0; i < argumentCount; i++ ) {
877            Element argumentElement = (Element)argumentList.item( i );
878            ConfigArgument argument = argumentElementToConfig( argumentElement );
879            agentSpecifier.addArgument( argument );
880             logger.log( Logger.FINE, "argument " + i + ":\"" +argument+"\"");
881        }
882        
883        
884        return agentSpecifier;
885 
886    }
887    
888    /**
889     * convert argument XML element to jademx configuration agent argument
890     * @param argumentElement
891     * @return argument configuration for XML argument element
892     */
893    private ConfigArgument argumentElementToConfig( Element argumentElement ) {
894        ConfigArgument argument = new ConfigArgument();
895        String argumentValue = getTextContent( argumentElement );
896        argument.setValue( argumentValue );
897        String argumentClassName = 
898            argumentElement.getAttribute( CLASS_NAME_ATTR );
899        if ( ( argumentClassName.trim().length() > 0 ) ) {
900            argument.setClassname( argumentClassName );
901        }
902        return argument;
903    }
904 
905    
906    /**
907     * start up specified agents for JADE platform.
908     * @param jadePlatform platform mbean implementation
909     * @param platform platform config
910     * @param platformIndex platform number
911     */
912    private void instantiateAgents( JadePlatform jadePlatform,
913            ConfigPlatform platform, int platformIndex ) throws JademxException {
914        
915        List agentSpecifiers = platform.getAgentSpecifiers();
916        if ( null != agentSpecifiers ) {
917            Iterator agentSpecifierI = agentSpecifiers.iterator();
918            int agentCount = 0;
919            while ( agentSpecifierI.hasNext() ) {
920                ConfigAgentSpecifier agentSpecifier = 
921                    (ConfigAgentSpecifier)agentSpecifierI.next();
922                instantiateAgent( 
923                        jadePlatform, agentSpecifier, 
924                        platformIndex, agentCount++ );
925            }
926        }
927        
928    }
929    
930    /**
931     * start up specified JADE platform.
932     * each platform gets its own thread.
933     * @param platform platform configuration
934     * @param platformIndex platform number
935     * @return platform MBean
936     */
937    private JadePlatform instantiatePlatform( ConfigPlatform platform,
938            int platformIndex ) throws JademxException{
939    
940        Profile bootProfile = 
941            platformProfile( platform, platformIndex );
942    
943        JadePlatform jadePlatform = 
944            makeAndStartPlatform( bootProfile, platformIndex );
945 
946        instantiateAgents( jadePlatform, platform, platformIndex );
947        
948        return jadePlatform;
949        
950    }
951 
952    
953    /**
954     * instantiate platforms for given runtime configuration
955     * @param runtime runtime configuration
956     * @return platforms for runtime
957     * @throws JademxException on error
958     */
959    JadePlatform[] instantiatePlatforms( ConfigRuntime runtime )
960      throws JademxException {
961        logger.log( Logger.CONFIG, 
962                "instantiating platforms from runtime configuration " + runtime );
963        
964        threadGroup = new ThreadGroup( getJadeFactory().getThreadGroupName() );
965        
966        List platforms = runtime.getPlatforms();
967        int platformCount = 0;
968        if ( null != platforms ) {
969            platformCount = platforms.size();
970        }
971        JadePlatform jadePlatforms[] = new JadePlatform[platformCount];
972        Iterator platformI = platforms.iterator();
973        int i = 0;
974        while ( platformI.hasNext() ) {
975            jadePlatforms[i] =
976                instantiatePlatform( (ConfigPlatform)platformI.next(), i );
977            i++;
978        }
979 
980        // return array of platform object names
981        return jadePlatforms;
982    }
983    
984    
985    /**
986     * convert configuration XML to a configuration object
987     * @param xml name of XML to convert
988     * @param isResource whether name specifies a resource
989     * @return object representation of input xml
990     */
991    private JademxConfig xmlToConfig( String xml, boolean isResource )
992      throws JademxException  {
993 
994        // read in doc
995        Document document = readDocument( xml, isResource );
996        
997        // get <jademx-config>
998        NodeList jademxConfigNodeList = 
999            document.getElementsByTagName( JADEMX_CONFIG_TAG );
1000        int jademxConfigCount = 0;
1001        if ( null != jademxConfigNodeList ) {
1002            jademxConfigCount = jademxConfigNodeList.getLength();
1003        }
1004        if ( 0 == jademxConfigCount ) {
1005            throw new JademxException("no <jademx-config> found in "+xml);
1006        }
1007        if ( jademxConfigCount > 1 ) {
1008            throw new JademxException("multiple <jademx-config> in "+xml);
1009        }
1010        Element jademxConfigElement = (Element)jademxConfigNodeList.item(0);
1011        JademxConfig jademxConfig = new JademxConfig();
1012        
1013        // get <runtime>
1014        NodeList runtimeList = 
1015            jademxConfigElement.getElementsByTagName( RUNTIME_TAG );
1016        int runtimeCount;
1017        if ( null == runtimeList ) {
1018            runtimeCount = 0;
1019        }
1020        else {
1021            runtimeCount = jademxConfigNodeList.getLength();   
1022        }
1023        if ( runtimeCount > 1 ) {
1024            throw new JademxException("multiple <runtime> tags found in "+xml);
1025        }
1026        else if ( 1 == runtimeCount ) {
1027            Element runtimeElement = (Element)runtimeList.item( 0 );
1028            ConfigRuntime runtime = new ConfigRuntime();
1029            jademxConfig.addRuntime( runtime );
1030            
1031            // get each <platform>
1032            NodeList platformNodeList =
1033                runtimeElement.getElementsByTagName( PLATFORM_TAG );
1034            int platformCount;
1035            if ( null == platformNodeList ) {
1036                platformCount = 0;
1037            }
1038            else {
1039                platformCount = platformNodeList.getLength();
1040                for ( int i = 0; i < platformCount; i++ ) {
1041                    Element platformElement = (Element)platformNodeList.item(i);
1042                    ConfigPlatform platform = platformElementToConfig( platformElement );
1043                    runtime.addPlatform( platform );
1044                }
1045            }
1046        }
1047        return jademxConfig;
1048    }
1049    
1050    
1051 
1052    /**
1053     * instantiate platforms described by jademx configuration XML.
1054     * each platform gets its own thread.
1055     * @param xml string description of how to get jademx XML configuration
1056     * @param isResource true=>it's a resource name, false=>URL string
1057     * @return JadePlatform array proxying instantiated platforms
1058     * @throws JademxException problem instantiating platforms
1059     */
1060    private JadePlatform[] instantiatePlatforms( String xml, boolean isResource ) 
1061      throws JademxException {
1062        
1063        JadePlatform jadePlatforms[] = null;
1064        
1065        logger.log( Logger.CONFIG, 
1066                "instantiating platforms from " +
1067                (isResource?"resource":"URL") +
1068                " \"" + xml + "\""  );
1069        
1070        // get config xml doc
1071        // for each platform
1072        //   start the platform
1073        //   for each agent
1074        //     start the agent
1075        //   add platform mbean object name to return array
1076        // return array of platform object names
1077        
1078        threadGroup = new ThreadGroup( getJadeFactory().getThreadGroupName() );
1079        JademxConfig jademxConfig = xmlToConfig( xml, isResource );
1080        if ( null != jademxConfig ) {
1081            List runtimes = jademxConfig.getRuntimes();
1082            if ( null != runtimes ) {
1083                if ( runtimes.size() > 1 ) {
1084                    throw new JademxException("multiple <runtime> tags in "+xml);
1085                }
1086                Iterator runtimeI = runtimes.iterator();
1087                if ( runtimeI.hasNext() ) {
1088                    ConfigRuntime runtime = (ConfigRuntime)runtimeI.next();
1089                    jadePlatforms = instantiatePlatforms( runtime );
1090                }
1091            }
1092        }
1093        
1094        // return array of platform objects
1095        return jadePlatforms;
1096    }
1097 
1098    /* (non-Javadoc)
1099     * @see jade.jademx.mbean.JadeRuntimeMBean#platformsFromConfigResource(
1100     * java.lang.String)
1101     */
1102    public JadePlatform[] platformsFromConfigResource( String xmlResName )
1103      throws JademxException {
1104              return instantiatePlatforms( xmlResName, true );
1105    }
1106    
1107    /* (non-Javadoc)
1108     * @see jade.jademx.mbean.JadeRuntimeMBean#platformsFromConfigUrl(
1109     * java.lang.String)
1110     */
1111    public JadePlatform[] platformsFromConfigUrl( String xmlUrlString )
1112      throws JademxException {
1113              return instantiatePlatforms( xmlUrlString, false );
1114    }
1115    
1116    /**
1117     * convert array of JadePlatform to array of String
1118     * @param platforms input to convert
1119     * @return string representation of input
1120     */
1121    private String[] platformsToStrings( JadePlatform[] platforms ) {
1122        int platformCount = platforms.length;
1123        String strings[] = new String[platformCount];
1124        for ( int i = 0; i < platformCount; i++ ) {
1125            strings[i] = platforms[i].toString();
1126        }
1127        return strings;
1128    }
1129    
1130    /* (non-Javadoc)
1131     * @see jade.jademx.mbean.JadeRuntimeMBean#platformsFromConfigResource(
1132     * java.lang.String)
1133     */
1134    public String[] platformNamesFromConfigResource( String xmlResName )
1135      throws JademxException {
1136              return platformsToStrings( 
1137                      instantiatePlatforms( xmlResName, true ) );
1138    }
1139    
1140    /* (non-Javadoc)
1141     * @see jade.jademx.mbean.JadeRuntimeMBean#platformsFromConfigUrl(
1142     * java.lang.String)
1143     */
1144    public String[] platformNamesFromConfigUrl( String xmlUrlString )
1145      throws JademxException {
1146              return platformsToStrings( 
1147                      instantiatePlatforms( xmlUrlString, false ) );
1148    }
1149    
1150 
1151    /* (non-Javadoc)
1152     * @see jade.jademx.mbean.JadeRuntimeMBean#platformFromJadeName(
1153     * java.lang.String)
1154     */
1155    public JadePlatform platformFromJadeName( String jadePlatformName ) 
1156      throws JademxException {
1157        JadePlatform jadePlatform;
1158        logger.log(Logger.FINER,
1159                "looking for platform \""+jadePlatformName+"\"");
1160        synchronized ( platformMap ) {
1161            jadePlatform = (JadePlatform)platformMap.get( jadePlatformName );
1162        }
1163        return jadePlatform;
1164    }
1165    
1166    /* (non-Javadoc)
1167     * @see jade.jademx.mbean.JadeRuntimeMBean#platformNameFromJadeName(
1168     * java.lang.String)
1169     */
1170    public String platformNameFromJadeName( String jadePlatformName ) 
1171      throws JademxException {
1172        JadePlatform jadePlatform = platformFromJadeName( jadePlatformName );
1173        String jademxPlatformName = ( ( null != jadePlatform )
1174            ? jadePlatform.toString()
1175            : null );
1176        return jademxPlatformName;
1177    }
1178    
1179    
1180    /* (non-Javadoc)
1181     * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
1182     */
1183    public void postRegister(Boolean registrationDone) {
1184        super.postRegister(registrationDone);
1185        if ( registrationDone.booleanValue() ) {
1186            System.setProperty( MBEAN_SYS_PROP_NAME, getMBeanName() );
1187        }
1188    }
1189    /* (non-Javadoc)
1190     * @see javax.management.MBeanRegistration#preDeregister()
1191     */
1192    public void preDeregister() throws Exception {
1193        try {
1194            System.clearProperty( MBEAN_SYS_PROP_NAME );
1195        }
1196        catch ( NoSuchMethodError nsme ) {
1197            // intentionally empty
1198            // method arrived with J2SE 1.5
1199        }
1200        catch ( Throwable t ) {
1201            logger.log( Logger.FINE, "issue clearing system property "+ 
1202                    MBEAN_SYS_PROP_NAME+": "+t, t );
1203            // message is just an FYI.
1204            // don't throw it, it was just trying to clean up nicely.
1205            // for example, there might be a security exception.
1206        }
1207        super.preDeregister();
1208    }
1209}

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