KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > dyade > aaa > agent > AgentServer


1 /*
2  * Copyright (C) 2001 - 2006 ScalAgent Distributed Technologies
3  * Copyright (C) 2004 - France Telecom R&D
4  * Copyright (C) 1996 - 2000 BULL
5  * Copyright (C) 1996 - 2000 INRIA
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20  * USA.
21  *
22  * Initial developer(s): Dyade
23  * Contributor(s): ScalAgent Distributed Technologies
24  */

25 package fr.dyade.aaa.agent;
26
27 import java.io.*;
28 import java.util.*;
29
30 import org.objectweb.util.monolog.api.BasicLevel;
31 import org.objectweb.util.monolog.api.Logger;
32 import org.objectweb.util.monolog.api.LoggerFactory;
33
34 import fr.dyade.aaa.util.*;
35 import fr.dyade.aaa.agent.conf.*;
36 import fr.dyade.aaa.util.management.MXWrapper;
37
38 /**
39  * The <code>AgentServer</code> class manages the global configuration
40  * of an agent server. It reads the configuration file, then it creates
41  * and configure {@link Engine <code>Engine</code>},
42  * {@link Channel <code>Channel</code>},
43  * {@link Network <code>Network</code>s}.
44  * This class contains the main method for AgentServer, for example to
45  * acivate a server you have to run this class with two parameters: the
46  * server id. and the path of the root of persistancy. You can also use
47  * a specialized main calling methods initi and start.
48  * <p><hr>
49  * To start the agents server an XML configuration file describing the
50  * architecture of the agent platform is needed. By default, this file is
51  * the a3servers.xml file and it should be located inside the running
52  * directory where the server is launched. Each server must use the same
53  * configuration file.<p>
54  * The configuration file contains a <code>config</code> element, that
55  * is essentially made up of <code>domain</code>s elements, and servers
56  * (<code>server</code>s elements):
57  * <ul>
58  * <li>Each domain of the configuration is described by an XML element with
59  * attributes giving the name and the classname for <code>Network</code>
60  * implementation (class {@link SimpleNetwork <code>SimpleNetwork</code>}
61  * by default).
62  * <li>Each server is described by an XML element with attributes giving
63  * the id, the name (optional) and the node (the <code>hostname</code>
64  * attribute describes the name or the IP address of this node)
65  * <ul>
66  * <li>Each persistent server must be part of a domain (at least one), to
67  * do this you need to define a <code>network</code> element with attributes
68  * giving the domain's name (<code>domain</code> attribute) and the
69  * communication port (<code>port</code> attribute).
70  * <li>A service can be declared on any of these servers by inserting a
71  * <code>service</code> element describing it.
72  * </ul>
73  * <li>Additonnaly, you can define property for the global configuration
74  * or for a particular server, it depends where you define it: in the
75  * <code>config</code> element or in a server one.
76  * </ul>
77  * Each server that is part of two domains is named a "router", be careful,
78  * it should have only one route between two domains. If it is not true the
79  * configuration failed.
80  * <p><hr>
81  * A simple example of a3servers.xml follows:
82  * <p><blockquote><pre>
83  * &lt;?xml version="1.0"?&gt;
84  * &lt;!DOCTYPE config SYSTEM "a3config.dtd"&gt;
85  *
86  * &lt;config&gt;
87  * &lt;domain name="D1"/&gt;
88  * &lt;domain name="D2" class="fr.dyade.aaa.agent.PoolCnxNetwork"/&gt;
89  *
90  * &lt;property name="D2.nbMaxCnx" value="1"\&gt;
91  *
92  * &lt;server id="0" name="S0" hostname="acores"&gt;
93  * &lt;network domain="D1" port="16300"/&gt;
94  * &lt;service class=\"fr.dyade.aaa.ns.NameService\" args=\"\"/&gt;
95  * &lt;property name="A3DEBUG_PROXY" value="true"\&gt;
96  * &lt;/server&gt;
97  *
98  * &lt;server id="2" name="S2" hostname="bermudes"&gt;
99  * &lt;network domain="D1" port="16310"/&gt;
100  * &lt;network domain="D2" port="16312"/&gt;
101  * &lt;/server&gt;
102  *
103  * &lt;server id="3" name="S3" hostname="baleares"&gt;
104  * &lt;network domain="D2" port="16320"/&gt;
105  * &lt;/server&gt;
106  * &lt;/config&gt;
107  * </pre></blockquote>
108  * <p>
109  * This file described a 2 domains configuration D1 and D2, D1 with default
110  * network protocol and D2 with the <code>PoolCnxNetwork</code> one, and 4
111  * servers:
112  * <ul>
113  * <li>The first server (id 0 and name "S0") is hosted by acores, it is
114  * in domain D1, and listen on port 16300. It defines a service and a
115  * property.
116  * <li>The second server (id 2) is hosted by bermudes and it is the router
117  * between D1 and D2.
118  * <li>The last server is a persistent one, it is hosted on baleares and it
119  * runs in domain D2.
120  * </ul>
121  * At the beginning of the file, there is a global property that defines
122  * the maximum number of connection handled by each server of domain D2.
123  * <hr>
124  * @see Engine
125  * @see Channel
126  * @see Network
127  * @see MessageQueue
128  * @see fr.dyade.aaa.util.Transaction
129  */

130 public final class AgentServer {
131   public final static short NULL_ID = -1;
132
133   public final static String JavaDoc ADMIN_DOMAIN = "D0";
134   public final static String JavaDoc ADMIN_SERVER = "s0";
135
136   private static short serverId = NULL_ID;
137
138   private static Logger logmon = null;
139
140   public final static String JavaDoc CFG_DIR_PROPERTY = "fr.dyade.aaa.agent.A3CONF_DIR";
141   public final static String JavaDoc DEFAULT_CFG_DIR = null;
142   
143   public final static String JavaDoc CFG_FILE_PROPERTY = "fr.dyade.aaa.agent.A3CONF_FILE";
144   public final static String JavaDoc DEFAULT_CFG_FILE = "a3servers.xml";
145   public final static String JavaDoc DEFAULT_SER_CFG_FILE = "a3cmlconfig";
146   
147   public final static String JavaDoc CFG_NAME_PROPERTY = "fr.dyade.aaa.agent.A3CONF_NAME";
148   public final static String JavaDoc DEFAULT_CFG_NAME = "default";
149   
150   public final static String JavaDoc A3CMLWRP_PROPERTY = "fr.dyade.aaa.agent.A3CMLWrapper";
151   public final static String JavaDoc DEFAULT_A3CMLWRP = "fr.dyade.aaa.agent.conf.A3CMLSaxWrapper";
152
153   static ThreadGroup JavaDoc tgroup = null;
154
155   public static ThreadGroup JavaDoc getThreadGroup() {
156     return tgroup;
157   }
158
159  /**
160    * Static reference to the engine. Used in <code>Channel.sendTo</code> to
161    * know if the method is called from a react or no.
162    * <p><hr>
163    * AF: I think we must supress this dependency in order to be able to run
164    * multiples engine.
165    */

166   static Engine engine = null;
167
168   /**
169    * Returns the agent server engine.
170    */

171   public static Engine getEngine() {
172     return engine;
173   }
174
175   /** Static reference to the transactional monitor. */
176   private static Transaction transaction = null;
177
178   /**
179    * Returns the agent server transaction context.
180    */

181   public static Transaction getTransaction() {
182     return transaction;
183   }
184
185   private static JGroups jgroups = null;
186   private static short clusterId = NULL_ID;
187
188   private static ConfigController configController;
189
190   public static ConfigController getConfigController() {
191     return configController;
192   }
193
194   /**
195    * Static references to all messages consumers initialized in this
196    * agent server (including <code>Engine</code>).
197    */

198   private static Hashtable consumers = null;
199
200   static void addConsumer(String JavaDoc domain,
201                           MessageConsumer cons) throws Exception JavaDoc {
202     if (consumers.containsKey(domain))
203       throw new Exception JavaDoc("Consumer for domain " + domain + " already exist");
204
205     consumers.put(domain, cons);
206
207     try {
208       MXWrapper.registerMBean(cons,
209                               "AgentServer",
210                               "server=" + getName() + ",cons=" + cons.getName());
211     } catch (Exception JavaDoc exc) {
212       logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
213     }
214   }
215
216   static Enumeration getConsumers() {
217     if (consumers == null)
218       return null;
219     else
220       return consumers.elements();
221   }
222
223   static MessageConsumer getConsumer(String JavaDoc domain) throws Exception JavaDoc {
224     if (! consumers.containsKey(domain))
225       throw new Exception JavaDoc("Unknown consumer for domain " + domain);
226     return (MessageConsumer) consumers.get(domain);
227   }
228
229   static void removeConsumer(String JavaDoc domain) {
230     MessageConsumer cons = (MessageConsumer) consumers.remove(domain);
231     if (cons != null) cons.stop();
232
233     try {
234       MXWrapper.unregisterMBean("AgentServer",
235                                 "server=" + getName() + ",cons=" + cons.getName());
236     } catch (Exception JavaDoc exc) {
237       logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
238     }
239   }
240
241   /** Static reference to the configuration. */
242   private static A3CMLConfig a3config = null;
243
244   /**
245    * Set the agent server configuration. Be careful, this method cannot
246    * be called after initialization.
247    *
248    * @param a3config A3CMLConfig
249    * @exception Exception Server is already initialized.
250    */

251   public final static void setConfig(A3CMLConfig a3config) throws Exception JavaDoc {
252     setConfig(a3config, false);
253   }
254
255   final static void setConfig(A3CMLConfig a3config,
256                               boolean force) throws Exception JavaDoc {
257     if (! force) {
258       synchronized(status) {
259         if (status.value != Status.INSTALLED)
260           throw new Exception JavaDoc("cannot set config, bad status: " + status.value);
261       }
262     }
263     AgentServer.a3config = a3config;
264   }
265   
266   /**
267    * Returns the agent server configuration.
268    *
269    * @return agent server configuration (A3CMLConfig)
270    */

271   public final static A3CMLConfig getConfig() throws Exception JavaDoc {
272     if (a3config == null) throw new Exception JavaDoc("Server not configured");
273     return a3config;
274   }
275
276   /**
277    * Gets configuration of agent servers for a domain from the current
278    * A3CMLConfig object. This method fills the object graph configuration
279    * in a <code>A3CMLConfig</code> object.
280    *
281    * @param domains list of domain's names
282    * @return a <code>A3CMLConfig</code> object.
283    */

284   public static A3CMLConfig getAppConfig(String JavaDoc[] domains) throws Exception JavaDoc {
285     return getConfig().getDomainConfig(domains);
286   }
287
288   public final static short getServerId() {
289     return serverId;
290   }
291
292   public final static short getClusterId() {
293     return clusterId;
294   }
295
296   private static String JavaDoc name = null;
297
298   public final static String JavaDoc getName() {
299     return name;
300   }
301
302   /**
303    * Returns the identifier of the agent server which name is specified.
304    *
305    * @param name the name of the agent server
306    * @return the identifier of the agent server
307    * @exception Exception if the server name is unknown.
308    */

309   public static short getServerIdByName(String JavaDoc name) throws Exception JavaDoc {
310     return getConfig().getServerIdByName(name);
311   }
312   
313   /**
314    * Searches for the property with the specified key in the server property
315    * list.
316    *
317    * @param key the hashtable key.
318    * @return the value with the specified key value.
319    */

320   public static String JavaDoc getProperty(String JavaDoc key) {
321     return System.getProperty(key);
322   }
323
324   /**
325    * Searches for the property with the specified key in the server property
326    * list.
327    *
328    * @param key the hashtable key.
329    * @param value a default value.
330    * @return the value with the specified key value.
331    */

332   public static String JavaDoc getProperty(String JavaDoc key, String JavaDoc value) {
333     return System.getProperty(key, value);
334   }
335
336   /**
337    * Determines the integer value of the server property with the
338    * specified name.
339    *
340    * @param key property name.
341    * @return the Integer value of the property.
342    */

343   public static Integer JavaDoc getInteger(String JavaDoc key) {
344     try {
345       return Integer.getInteger(key);
346     } catch (Exception JavaDoc exc) {
347       return null;
348     }
349   }
350
351   /**
352    * Determines the integer value of the server property with the
353    * specified name.
354    *
355    * @param key property name.
356    * @param value a default value.
357    * @return the Integer value of the property.
358    */

359   public static Integer JavaDoc getInteger(String JavaDoc key, int value) {
360     try {
361       return Integer.getInteger(key, value);
362     } catch (Exception JavaDoc exc) {
363       return null;
364     }
365   }
366
367   /** Static description of all known agent servers in ascending order. */
368   private static ServersHT servers = null;
369
370   static void addServerDesc(ServerDesc desc) throws Exception JavaDoc {
371     if (desc == null) return;
372     servers.put(desc);
373   }
374
375   static ServerDesc removeServerDesc(short sid) throws Exception JavaDoc {
376     return servers.remove(sid);
377   }
378
379   public static Enumeration elementsServerDesc() {
380     return servers.elements();
381   }
382
383   public static Enumeration getServersIds() {
384     return servers.keys();
385   }
386
387   /**
388    * Gets the number of server known on the current server.
389    *
390    * @return the number of server.
391    */

392   final static int getServerNb() {
393     return servers.size();
394   }
395
396   /**
397    * Gets the characteristics of the corresponding server.
398    *
399    * @param sid agent server id.
400    * @return the server's descriptor.
401    */

402   final static ServerDesc getServerDesc(short sid) throws UnknownServerException {
403     ServerDesc serverDesc = servers.get(sid);
404     if (serverDesc == null)
405       throw new UnknownServerException("Unknow server id. #" + sid);
406     return serverDesc;
407   }
408
409   /**
410    * Gets the message consumer for the corresponding server.
411    *
412    * @param sid agent server id.
413    * @return the corresponding message consumer.
414    */

415   final static MessageConsumer getConsumer(short sid) throws UnknownServerException {
416     return getServerDesc(sid).domain;
417   }
418
419   /**
420    * Get the host name of an agent server.
421    *
422    * @param sid agent server id
423    * @return server host name as declared in configuration file
424    */

425   public final static String JavaDoc getHostname(short sid) throws UnknownServerException {
426     return getServerDesc(sid).getHostname();
427   }
428
429   /**
430    * Get the description of all services of the current agent server.
431    *
432    * @return server host name as declared in configuration file
433    */

434   final static ServiceDesc[] getServices() throws UnknownServerException {
435     return getServerDesc(getServerId()).services;
436   }
437
438   /**
439    * Get the argument strings for a particular service.
440    * The information provides from the A3 configuration file, so it's
441    * only available if this file contains service's informations for all
442    * nodes.
443    *
444    * @see A3CMLConfig#getServiceArgs(short,String)
445    *
446    * @param sid agent server id
447    * @param classname the service class name
448    * @return the arguments as declared in configuration file
449    * @exception UnknownServerException
450    * The specified server does not exist.
451    * @exception UnknownServiceException
452    * The specified service is not declared on this server.
453    * @exception Exception
454    * Probably there is no configuration defined.
455    */

456   public final static
457   String JavaDoc getServiceArgs(short sid,
458             String JavaDoc classname) throws Exception JavaDoc {
459     return getConfig().getServiceArgs(sid, classname);
460   }
461
462   /**
463    * Get the argument strings for a particular service running on a server
464    * identified by its host.
465    * The information provides from the A3 configuration file, so it's
466    * only available if this file contains service's informations for all
467    * nodes.
468    *
469    * @see A3CMLConfig#getServiceArgs(String, String)
470    *
471    * @param hostname hostname
472    * @param classname the service class name
473    * @return the arguments as declared in configuration file
474    * @exception UnknownServiceException
475    * The specified service is not declared on this server.
476    * @exception Exception
477    * Probably there is no configuration defined.
478    */

479   public final static
480   String JavaDoc getServiceArgs(String JavaDoc hostname,
481             String JavaDoc classname) throws Exception JavaDoc {
482     return getConfig().getServiceArgsHost(hostname, classname);
483   }
484
485   /**
486    * The second step of initialization. It needs the Transaction component
487    * be up, then it initializes all <code>AgentServer</code> structures from
488    * the <code>A3CMLConfig</code> ones. In particular the servers array is
489    * initialized.
490    */

491   private static void configure() throws Exception JavaDoc {
492     A3CMLServer root = getConfig().getServer(serverId, clusterId);
493     //Allocates the temporary descriptors hashtable for each server.
494
servers = new ServersHT();
495     // Initialized the descriptor of current server in order to permit
496
// Channel and Engine initialization.
497
ServerDesc local = new ServerDesc(root.sid, root.name, root.hostname, -1);
498     servers.put(local);
499
500     // Parse configuration in order to fix route related to the
501
// current server
502
getConfig().configure(root);
503
504     // Creates all the local MessageConsumer.
505
createConsumers(root);
506     
507     for (Enumeration s = getConfig().servers.elements();
508          s.hasMoreElements();) {
509       A3CMLServer server = (A3CMLServer) s.nextElement();
510       if (server.sid == root.sid) continue;
511
512       ServerDesc desc = createServerDesc(server);
513       addServerDesc(desc);
514     }
515
516     // for clusters
517
for (Enumeration c = getConfig().clusters.elements();
518          c.hasMoreElements();) {
519       A3CMLCluster cluster = (A3CMLCluster) c.nextElement();
520
521       for (Enumeration s = cluster.servers.elements();
522            s.hasMoreElements();) {
523         A3CMLServer server = (A3CMLServer) s.nextElement();
524         if (server.sid == root.sid) continue;
525
526         ServerDesc desc = servers.get(server.sid);
527         if (desc == null) {
528           desc = createServerDesc(server);
529           addServerDesc(desc);
530         } else {
531           desc.addSockAddr(server.hostname, server.port);
532         }
533       }
534     }
535
536     initServices(root, local);
537     local.domain = engine;
538
539 // if (logmon.isLoggable(BasicLevel.DEBUG)) {
540
// for (int i=0; i<servers.length; i++) {
541
// logmon.log(BasicLevel.DEBUG,
542
// getName() + ", servers[" + i + "]=(" +
543
// "sid=" + servers[i].sid +
544
// ", name=" + servers[i].name +
545
// ", gateway=" + servers[i].gateway +
546
// ", domain=" + servers[i].domain + ")");
547
// }
548
// }
549

550     return;
551   }
552
553   private static void createConsumers(A3CMLServer root) throws Exception JavaDoc {
554     consumers = new Hashtable();
555
556     // Creates the local MessageConsumer: the Engine.
557
engine = Engine.newInstance();
558     addConsumer("local", engine);
559
560     // if JGroups
561
if (clusterId > NULL_ID) {
562       jgroups = new JGroups();
563       if (engine instanceof HAEngine) {
564         jgroups.setEngine((HAEngine) engine);
565         ((HAEngine) engine).setJGroups(jgroups);
566       } else
567         logmon.log(BasicLevel.ERROR, getName() + ", createConsumers(" + root + ")\n" +
568                    "engine [" + engine + "] is not a HAEngine");
569     }
570
571     // Search alls directly accessible domains.
572
for (Enumeration n = root.networks.elements();
573      n.hasMoreElements();) {
574       A3CMLNetwork network = (A3CMLNetwork) n.nextElement();
575
576       A3CMLDomain domain = getConfig().getDomain(network.domain);
577       // Creates the corresponding MessageConsumer.
578
try {
579         Network consumer = (Network) Class.forName(domain.network).newInstance();
580         // Initializes it with domain description. Be careful, this array
581
// is kept in consumer, don't reuse it!!
582
consumer.init(domain.name, network.port, domain.getServersId());
583         if (consumer instanceof SimpleNetwork &&
584             jgroups != null) {//NTA modify to SimpleHANetwork
585
((SimpleNetwork) consumer).setJGroups(jgroups);
586           jgroups.setNetWork((SimpleNetwork) consumer);
587         }
588 // domain.consumer = consumer;
589
addConsumer(network.domain, consumer);
590       } catch (ClassNotFoundException JavaDoc exc) {
591         throw exc;
592       } catch (InstantiationException JavaDoc exc) {
593         throw exc;
594       } catch (IllegalAccessException JavaDoc exc) {
595         throw exc;
596       }
597     }
598   }
599
600   static void initServerDesc(ServerDesc desc,
601                              A3CMLServer server) throws Exception JavaDoc {
602     desc.gateway = server.gateway;
603     // For each server set the gateway to the real next destination of
604
// messages; if the server is directly accessible: itself.
605
if ((desc.gateway == -1) || (desc.gateway == server.sid)) {
606       desc.gateway = server.sid;
607       desc.updateSockAddr(desc.getHostname(), server.port);
608       A3CMLServer current = getConfig().getServer(getServerId(),getClusterId());
609       if (current.containsNat(server.sid)) {
610         A3CMLNat nat = current.getNat(server.sid);
611         desc.updateSockAddr(nat.host, nat.port);
612         if (logmon.isLoggable(BasicLevel.DEBUG))
613           logmon.log(BasicLevel.DEBUG, getName() + " : NAT sDesc = " + desc);
614       }
615     }
616     desc.domain = getConsumer(server.domain);
617   }
618
619   private static ServerDesc
620       createServerDesc(A3CMLServer server) throws Exception JavaDoc {
621     if (! server.visited)
622       throw new Exception JavaDoc(server + " inaccessible");
623     
624     ServerDesc desc = new ServerDesc(server.sid,
625                                      server.name,
626                                      server.hostname,
627                                      -1);
628
629     initServerDesc(desc, server);
630     initServices(server, desc);
631
632     return desc;
633   }
634
635   private static void initServices(A3CMLServer server, ServerDesc desc) {
636     if (server.services != null) {
637       ServiceDesc services[] = new ServiceDesc[server.services.size()];
638       int idx = 0;
639       for (Enumeration x = server.services.elements();
640            x.hasMoreElements();) {
641         A3CMLService service = (A3CMLService) x.nextElement();
642         services[idx++] = new ServiceDesc(service.classname, service.args);
643       }
644       desc.services = services;
645     }
646   }
647   
648   private static void setProperties(short sid, short cid) throws Exception JavaDoc {
649     if (a3config == null) return;
650
651     // add global properties
652
if (a3config.properties != null) {
653       for (Enumeration e = a3config.properties.elements(); e.hasMoreElements();) {
654         A3CMLProperty p = (A3CMLProperty) e.nextElement();
655         System.getProperties().put(p.name,p.value);
656       }
657     }
658
659     A3CMLServer server = null;
660     if (cid != NULL_ID) {
661       A3CMLCluster cluster = null;
662       cluster = a3config.getCluster(sid);
663
664       // add cluster properties
665
if (cluster != null
666           && cluster.properties != null
667           && cluster.properties.size() > 0) {
668         Enumeration e = cluster.properties.elements();
669         do {
670           A3CMLProperty p = (A3CMLProperty) e.nextElement();
671           System.getProperties().put(p.name,p.value);
672         } while (e.hasMoreElements());
673       }
674       server = cluster.getServer(cid);
675     } else {
676       server = a3config.getServer(sid);
677     }
678
679     // add server properties
680
if (server != null && server.properties != null) {
681       Enumeration e = server.properties.elements();
682       do {
683         A3CMLProperty p = (A3CMLProperty) e.nextElement();
684         System.getProperties().put(p.name,p.value);
685       } while (e.hasMoreElements());
686     }
687   }
688   
689   public static class Status {
690     public static final int INSTALLED = 0;
691     public static final int INITIALIZING = 0x1;
692     public static final int INITIALIZED = 0x2;
693     public static final int STARTING = 0x3;
694     public static final int STARTED = 0x4;
695     public static final int STOPPING = 0x5;
696     public static final int STOPPED = 0x6;
697     public static final int RESETING = 0x7;
698
699     private int value = INSTALLED;
700
701     public static String JavaDoc[] info = {"installed",
702                                    "initializing", "initialized",
703                                    "starting", "started",
704                                    "stopping", "stopped",
705                                    "reseting"};
706   }
707
708   static Status status = new Status();
709
710   public static int getStatus() {
711     return status.value;
712   }
713
714   public static String JavaDoc getStatusInfo() {
715     return Status.info[status.value];
716   }
717
718   /**
719    * Parses agent server arguments, then initializes this agent server. The
720    * <code>start</code> function is then called to start this agent server
721    * execution. Between the <code>init</code> and </code>start</code> calls,
722    * agents may be created and deployed, and notifications may be sent using
723    * the <code>Channel</code> <code>sendTo</code> function.
724    *
725    * @param args lauching arguments, the first one is the server id
726    * and the second one the persistency directory.
727    * @return number of arguments consumed in args
728    *
729    * @exception Exception
730    * unspecialized exception
731    */

732   public static int init(String JavaDoc args[]) throws Exception JavaDoc {
733     if (args.length < 2)
734       throw new Exception JavaDoc("usage: java <main> sid storage");
735     short sid = NULL_ID;
736     try {
737       sid = (short) Integer.parseInt(args[0]);
738     } catch (NumberFormatException JavaDoc exc) {
739       throw new Exception JavaDoc("usage: java <main> sid storage");
740     }
741     String JavaDoc path = args[1];
742     short cid = NULL_ID;
743     try {
744       if (args.length == 3)
745       cid = (short) Integer.parseInt(args[2]);
746     } catch (NumberFormatException JavaDoc exc) {}
747
748     init(sid, path, null, cid);
749
750     configController = new ConfigController();
751
752     return 2;
753   }
754
755   public static void reset(boolean force) {
756     if (force) {
757       synchronized(status) {
758         if (status.value != Status.STOPPED) {
759           logmon.log(BasicLevel.WARN,
760                      getName() + ", force status: " + status.value);
761         }
762         status.value = Status.STOPPED;
763       }
764     }
765     reset();
766   }
767
768   /**
769    * Cleans an AgentServer configuration in order to restart it from
770    * persistent storage.
771    */

772   public static void reset() {
773     synchronized(status) {
774       if (status.value != Status.STOPPED) {
775         logmon.log(BasicLevel.WARN,
776                    getName() + ", cannot reset, bad status: " + status.value);
777         return;
778       }
779       status.value = Status.RESETING;
780     }
781
782     // Remove all consumers Mbean
783
Enumeration e = getConsumers();
784     if (e != null) {
785       for (; e.hasMoreElements();) {
786         MessageConsumer cons = (MessageConsumer) e.nextElement();
787         try {
788           MXWrapper.unregisterMBean(
789             "AgentServer",
790             "server=" + getName() + ",cons=" + cons.getName());
791         } catch (Exception JavaDoc exc) {
792           logmon.log(BasicLevel.DEBUG,
793                      getName() + ", jmx failed: " +
794                      "server=" + getName() + ",cons=" + cons.getName(), exc);
795         }
796       }
797       consumers = null;
798     }
799
800     try {
801       MXWrapper.unregisterMBean("AgentServer",
802                                 "server=" + getName() + ",cons=Transaction");
803     } catch (Exception JavaDoc exc) {
804       logmon.log(BasicLevel.DEBUG,
805                  getName() + ", jmx failed: " +
806                  "server=" + getName() + ",cons=Transaction", exc);
807     }
808
809     if (transaction != null) transaction.close();
810     transaction = null;
811
812     try {
813       MXWrapper.unregisterMBean("AgentServer", "server=" + getName());
814     } catch (Exception JavaDoc exc) {
815       logmon.log(BasicLevel.DEBUG,
816                  getName() + " jmx failed: "+ "server=" + getName(), exc);
817     }
818     
819     a3config = null;
820
821     synchronized(status) {
822       status.value = Status.INSTALLED;
823     }
824   }
825
826  /**
827    * Initializes this agent server.
828    * <code>start</code> function is then called to start this agent server
829    * execution. Between the <code>init</code> and </code>start</code> calls,
830    * agents may be created and deployed, and notifications may be sent using
831    * the <code>Channel</code> <code>sendTo</code> function.
832    *
833    * @param sid the server id
834    * @param path the persistency directory.
835    * @param loggerFactory the monolog LoggerFactory;
836    *
837    *
838    * @exception Exception
839    * unspecialized exception
840    */

841   public static void init(short sid,
842                           String JavaDoc path,
843                           LoggerFactory loggerFactory) throws Exception JavaDoc {
844     init(sid, path, loggerFactory, NULL_ID);
845   }
846
847  /**
848    * Initializes this agent server.
849    * <code>start</code> function is then called to start this agent server
850    * execution. Between the <code>init</code> and </code>start</code> calls,
851    * agents may be created and deployed, and notifications may be sent using
852    * the <code>Channel</code> <code>sendTo</code> function.
853    *
854    * @param sid the server id
855    * @param path the persistency directory.
856    * @param loggerFactory the monolog LoggerFactory;
857    * @param cid the cluster id
858    *
859    *
860    * @exception Exception
861    * unspecialized exception
862    */

863   public static void init(short sid,
864                           String JavaDoc path,
865                           LoggerFactory loggerFactory,
866                           short cid) throws Exception JavaDoc {
867     name = new StringBuffer JavaDoc("AgentServer#").append(sid).toString();
868
869     if (loggerFactory != null) Debug.setLoggerFactory(loggerFactory);
870     logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer.#" + sid);
871
872     if (logmon.isLoggable(BasicLevel.DEBUG))
873       logmon.log(BasicLevel.DEBUG, getName() + ", init()", new Exception JavaDoc());
874     else
875       logmon.log(BasicLevel.WARN, getName() + ", init()");
876
877     synchronized(status) {
878       if (status.value == Status.STOPPED) {
879         logmon.log(BasicLevel.DEBUG, getName() + ", reset configuration");
880         reset();
881       }
882       if (status.value != Status.INSTALLED)
883         throw new Exception JavaDoc("cannot initialize, bad status: " + status.value);
884       status.value = Status.INITIALIZING;
885     }
886
887     try {
888       serverId = sid;
889
890       tgroup = new ThreadGroup JavaDoc(getName()) {
891           public void uncaughtException(Thread JavaDoc t, Throwable JavaDoc e) {
892             if (logmon.isLoggable(BasicLevel.WARN)) {
893               logmon.log(BasicLevel.WARN,
894                          "Abnormal termination for " +
895                          t.getThreadGroup().getName() + "." + t.getName(),
896                          e);
897             }
898           }
899         };
900    
901       // Try to get transaction type from disk, then initialize the rigth
902
// transaction manager and get the configuration.
903
File dir = new File(path);
904       if (dir.exists() && dir.isDirectory()) {
905         File tfc = new File(dir, "TFC");
906         if (tfc.exists()) {
907           DataInputStream dis = null;
908           try {
909             dis = new DataInputStream(new FileInputStream(tfc));
910             String JavaDoc tname = dis.readUTF();
911             Class JavaDoc tclass = Class.forName(tname);
912             transaction = (Transaction) tclass.newInstance();
913           } catch (Exception JavaDoc exc) {
914             logmon.log(BasicLevel.FATAL,
915                        getName() + ", can't instanciate transaction manager",
916                        exc);
917             throw new Exception JavaDoc("Can't instanciate transaction manager");
918           } finally {
919             if (dis != null) dis.close();
920           }
921           try {
922             transaction.init(path);
923           } catch (IOException exc) {
924             logmon.log(BasicLevel.FATAL,
925                        getName() + ", can't start transaction manager", exc);
926             throw new Exception JavaDoc("Can't start transaction manager");
927           }
928         }
929       }
930
931       // Gets static configuration of agent servers from a file. This method
932
// fills the object graph configuration in the <code>A3CMLConfig</code>
933
// object, then the configure method really initializes the server.
934
// There are two steps because the configuration step needs the
935
// transaction components to be initialized.
936
if (transaction != null) {
937         // Try to read the serialiazed configuration (trough transaction)
938
try {
939           a3config = A3CMLConfig.load();
940         } catch (Exception JavaDoc exc) {
941           logmon.log(BasicLevel.WARN, getName() + ", config not found");
942         }
943       }
944
945       if (a3config == null) {
946         // Try to load an initial configuration (serialized or XML), or
947
// generates a default one in case of failure.
948
try {
949           a3config = A3CMLConfig.getConfig(DEFAULT_SER_CFG_FILE);
950         } catch (Exception JavaDoc exc) {
951           logmon.log(BasicLevel.WARN,
952                      getName() + ", serialized a3cmlconfig not found");
953         }
954
955         if (a3config == null) {
956           // Try to found XML configuration file, then parse it.
957
try {
958             a3config = A3CML.getXMLConfig();
959           } catch (Exception JavaDoc exc) {
960             logmon.log(BasicLevel.WARN,
961                        getName() + ", XML configuration file not found");
962           }
963         }
964
965         if (a3config == null) {
966           // 3rd, Generate A3CMLConfig base.
967
logmon.log(BasicLevel.WARN,
968                      "Generate default configuration");
969           A3CMLDomain d = new A3CMLDomain(ADMIN_DOMAIN,
970                                           "fr.dyade.aaa.agent.SimpleNetwork");
971           A3CMLServer s = new A3CMLServer((short) 0, ADMIN_SERVER, "localhost");
972           s.networks.addElement(new A3CMLNetwork(ADMIN_DOMAIN, 27300));
973           s.services.addElement(new A3CMLService("fr.dyade.aaa.agent.AgentAdmin",null));
974           s.services.addElement(new A3CMLService("fr.dyade.aaa.agent.HttpDebug","20080"));
975           d.addServer(s);
976           a3config = new A3CMLConfig();
977           a3config.addDomain(d);
978           a3config.addServer(s);
979         }
980       }
981
982       // if JGroups
983
if (cid > NULL_ID) clusterId = cid;
984
985       // set properties
986
setProperties(serverId, clusterId);
987
988       // Initializes the JMX Wrapper
989
MXWrapper.init();
990
991       if (transaction == null) {
992         try {
993           String JavaDoc tname = getProperty("Transaction",
994                                      "fr.dyade.aaa.util.NTransaction");
995           Class JavaDoc tclass = Class.forName(tname);
996           transaction = (Transaction) Class.forName(tname).newInstance();
997         } catch (Exception JavaDoc exc) {
998           logmon.log(BasicLevel.FATAL,
999                      getName() + ", can't instanciate transaction manager", exc);
1000          throw new Exception JavaDoc("Can't instanciate transaction manager");
1001        }
1002
1003        try {
1004          transaction.init(path);
1005        } catch (IOException exc) {
1006          logmon.log(BasicLevel.FATAL,
1007                     getName() + ", can't start transaction manager", exc);
1008          throw new Exception JavaDoc("Can't start transaction manager");
1009        }
1010      }
1011
1012      try {
1013        MXWrapper.registerMBean(transaction,
1014                                "AgentServer",
1015                                "server=" + getName() + ",cons=Transaction");
1016      } catch (Exception JavaDoc exc) {
1017        if (logmon == null)
1018          logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer");
1019        logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
1020      }
1021
1022      // save A3CMLConfig (May be we can omit it in some case).
1023
a3config.save();
1024
1025      try {
1026        // Initialize AgentId class's variables.
1027
AgentId.init();
1028      } catch (ClassNotFoundException JavaDoc exc) {
1029        logmon.log(BasicLevel.FATAL,
1030                   getName() + ", can't initialize AgentId", exc);
1031        throw new Exception JavaDoc("Can't initialize AgentId, bad classpath");
1032      } catch (IOException exc) {
1033        logmon.log(BasicLevel.FATAL,
1034                   getName() + ", can't initialize AgentId", exc);
1035        throw new Exception JavaDoc("Can't initialize AgentId, storage problems");
1036      }
1037
1038      try {
1039        // Configure the agent server.
1040
configure();
1041      } catch (Exception JavaDoc exc) {
1042        logmon.log(BasicLevel.FATAL, getName() + ", can't configure", exc);
1043        throw new Exception JavaDoc("Can't configure server");
1044      }
1045
1046      try {
1047        // then restores all messages.
1048
String JavaDoc[] list = transaction.getList("@");
1049        for (int i=0; i<list.length; i++) {
1050          Message msg = Message.load(list[i]);
1051
1052          if (msg.getSource() == serverId) {
1053            // The update has been locally generated, the message is ready to
1054
// deliver to its consumer (Engine or Network component). So we have
1055
// to insert it in the queue of this consumer.
1056
try {
1057              getServerDesc(msg.getDest()).domain.insert(msg);
1058            } catch (UnknownServerException exc) {
1059              logmon.log(BasicLevel.ERROR,
1060                         getName() + ", discard message to unknown server id#" +
1061                         msg.getDest());
1062              msg.delete();
1063              msg.free();
1064              continue;
1065            } catch (NullPointerException JavaDoc exc) {
1066              logmon.log(BasicLevel.ERROR,
1067                         getName() + ", discard message to unknown server id#" +
1068                         msg.getDest());
1069              msg.delete();
1070              msg.free();
1071              continue;
1072            } catch (ArrayIndexOutOfBoundsException JavaDoc exc) {
1073              logmon.log(BasicLevel.ERROR,
1074                         getName() + ", discard message to unknown server id#" +
1075                         msg.getDest());
1076              msg.delete();
1077              msg.free();
1078              continue;
1079            }
1080          } else {
1081            logmon.log(BasicLevel.ERROR,
1082                       getName() + ", discard undelivered message from server id#" +
1083                       msg.getDest());
1084            msg.delete();
1085            continue;
1086          }
1087        }
1088      } catch (ClassNotFoundException JavaDoc exc) {
1089        logmon.log(BasicLevel.FATAL,
1090                   getName() + ", can't restore messages", exc);
1091        throw new Exception JavaDoc("Can't restore messages, bad classpath");
1092      } catch (IOException exc) {
1093        logmon.log(BasicLevel.FATAL,
1094                   getName() + ", can't restore messages", exc);
1095        throw new Exception JavaDoc("Can't restore messages, storage problems");
1096      }
1097
1098      // initializes channel before initializing fixed agents
1099
Channel.newInstance();
1100
1101      try {
1102        // Initialize services.
1103
ServiceManager.init();
1104
1105        logmon.log(BasicLevel.DEBUG,
1106                   getName() + ", ServiceManager initialized");
1107
1108        /* Actually get Services from A3CML configuration file. */
1109        ServiceDesc services[] = AgentServer.getServices();
1110        if (services != null) {
1111          for (int i = 0; i < services.length; i ++) {
1112            ServiceManager.register(services[i].getClassName(),
1113                                    services[i].getArguments());
1114          }
1115        }
1116        ServiceManager.save();
1117      } catch (Exception JavaDoc exc) {
1118        logmon.log(BasicLevel.FATAL,
1119                   getName() + ", can't initialize services", exc);
1120        throw new Exception JavaDoc("Can't initialize services");
1121      }
1122
1123      // initializes fixed agents
1124
engine.init();
1125
1126      // If the server is part of an HA group starts the JGroup component
1127
if (jgroups != null) jgroups.init(getName());
1128
1129      logmon.log(BasicLevel.WARN,
1130                 getName() + ", initialized at " + new Date());
1131
1132      // Commit all changes.
1133
transaction.begin();
1134      transaction.commit();
1135      transaction.release();
1136
1137      try {
1138        SCServerMBean bean = new SCServer();
1139        MXWrapper.registerMBean(bean, "AgentServer", "server=" + getName());
1140      } catch (Exception JavaDoc exc) {
1141        if (logmon == null)
1142          logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer");
1143        logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
1144      }
1145    } catch (Exception JavaDoc exc) {
1146      logmon.log(BasicLevel.ERROR, getName() + "Cannot initialize", exc);
1147      synchronized(status) {
1148        // AF: Will be replaced by a BAD_INITIALIZED status allowing the
1149
// re-initialization..
1150
status.value = Status.INSTALLED;
1151      }
1152      throw exc;
1153    } catch (Throwable JavaDoc t) {
1154      logmon.log(BasicLevel.ERROR, getName() + "Cannot initialize", t);
1155      synchronized(status) {
1156        // AF: Will be replaced by a BAD_INITIALIZED status allowing the
1157
// re-initialization..
1158
status.value = Status.INSTALLED;
1159      }
1160      throw new Exception JavaDoc(t);
1161    }
1162
1163    synchronized(status) {
1164      status.value = Status.INITIALIZED;
1165    }
1166  }
1167
1168  static String JavaDoc startConsumers() throws Exception JavaDoc {
1169    StringBuffer JavaDoc errBuf = null;
1170
1171    // Now we can start all networks.
1172
if (consumers != null) {
1173      for (Enumeration c=AgentServer.getConsumers(); c.hasMoreElements(); ) {
1174        MessageConsumer cons = (MessageConsumer) c.nextElement();
1175        if (cons != null) {
1176          try {
1177            if (! (cons instanceof Engine)) {
1178              cons.start();
1179            }
1180          } catch (IOException exc) {
1181            if (errBuf == null) errBuf = new StringBuffer JavaDoc();
1182            errBuf.append(cons.getName()).append(": ");
1183            errBuf.append(exc.getMessage()).append('\n');
1184            logmon.log(BasicLevel.FATAL,
1185                       getName() +
1186                       ", problem during " + cons.getName() + " starting", exc);
1187          }
1188        }
1189      }
1190    }
1191
1192    if (errBuf == null) return null;
1193    return errBuf.toString();
1194  }
1195
1196  /**
1197   * Causes this AgentServer to begin its execution. This method starts all
1198   * <code>MessageConsumer</code> (i.e. the engine and the network components).
1199   */

1200  public static String JavaDoc start() throws Exception JavaDoc {
1201    if (logmon.isLoggable(BasicLevel.DEBUG))
1202      logmon.log(BasicLevel.DEBUG, getName() + ", start()", new Exception JavaDoc());
1203    else
1204      logmon.log(BasicLevel.WARN, getName() + ", start()");
1205
1206    synchronized(status) {
1207      if ((status.value != Status.INITIALIZED) &&
1208          (status.value != Status.STOPPED))
1209        throw new Exception JavaDoc("cannot start, bad status: " + status.value);
1210      status.value = Status.STARTING;
1211    }
1212
1213    StringBuffer JavaDoc errBuf = null;
1214    try {
1215      try {
1216        if (jgroups == null) {
1217          ServiceManager.start();
1218          // Be careful, we have to save ServiceManager after start (initialized
1219
// attribute).
1220
ServiceManager.save();
1221          logmon.log(BasicLevel.DEBUG,
1222                     getName() + ", ServiceManager started");
1223        }
1224      } catch (Exception JavaDoc exc) {
1225        logmon.log(BasicLevel.FATAL,
1226                   getName() + ", can't initialize services", exc);
1227        throw new Exception JavaDoc("Can't initialize services");
1228      }
1229
1230      // Now we can start all message consumers.
1231
if (consumers != null) {
1232        for (Enumeration c=AgentServer.getConsumers(); c.hasMoreElements(); ) {
1233          MessageConsumer cons = (MessageConsumer) c.nextElement();
1234          if (cons != null) {
1235            try {
1236              if ((jgroups == null) || (cons instanceof Engine)) {
1237                cons.start();
1238              }
1239            } catch (IOException exc) {
1240              if (errBuf == null) errBuf = new StringBuffer JavaDoc();
1241              errBuf.append(cons.getName()).append(": ");
1242              errBuf.append(exc.getMessage()).append('\n');
1243              logmon.log(BasicLevel.FATAL,
1244                         getName() +
1245                         ", problem during " + cons.getName() + " starting", exc);
1246            }
1247          }
1248        }
1249      }
1250      // The server is running.
1251
logmon.log(BasicLevel.WARN, getName() + ", started at " + new Date());
1252
1253      // Commit all changes.
1254
transaction.begin();
1255      transaction.commit();
1256      transaction.release();
1257    } catch (Exception JavaDoc exc) {
1258      logmon.log(BasicLevel.ERROR, getName() + "Cannot start", exc);
1259      synchronized(status) {
1260        // AF: Will be replaced by a BAD_STARTED status allowing the
1261
// stop and reset..
1262
status.value = Status.STOPPED;
1263      }
1264      throw exc;
1265    } catch (Throwable JavaDoc t) {
1266      logmon.log(BasicLevel.ERROR, getName() + "Cannot start", t);
1267      synchronized(status) {
1268        // AF: Will be replaced by a BAD_STARTED status allowing the
1269
// stop and reset..
1270
status.value = Status.STOPPED;
1271      }
1272      throw new Exception JavaDoc(t);
1273    }
1274
1275    synchronized(status) {
1276      status.value = Status.STARTED;
1277    }
1278
1279    if (errBuf == null) return null;
1280    return errBuf.toString();
1281  }
1282
1283  /**
1284   * Forces this AgentServer to stop executing. This method stops all
1285   * consumers and services. Be careful, if you specify a synchronous
1286   * process, this method wait for all server's thread to terminate; so
1287   * if this method is called from a server's thread it should result a
1288   * dead-lock.
1289   *
1290   * @param sync If true the stop is precessed synchronous, otherwise
1291   * a thread is created and the method returns.
1292   */

1293  public static void stop(boolean sync) {
1294    stop(sync, 0, false);
1295  }
1296
1297  /**
1298   * Forces this AgentServer to stop executing. This method stops all
1299   * consumers and services. Be careful, if you specify a synchronous
1300   * process, this method wait for all server's thread to terminate; so
1301   * if this method is called from a server's thread it should result a
1302   * dead-lock.
1303   *
1304   * @param sync If true the stop is precessed synchronous, otherwise
1305   * a thread is created and the method returns.
1306   * @param delay if sync is false then the thread in charge of
1307   * stopping the server waits this delay before
1308   * initiating the stop.
1309   * @param reset If true the server is stopped then reseted.
1310   */

1311  public static void stop(boolean sync, long delay, boolean reset) {
1312    ServerStopper stopper = new ServerStopper(delay, reset);
1313    if (sync == true) {
1314      stopper.run();
1315    } else {
1316      // Creates a thread to execute AgentServer.stop in order to
1317
// avoid deadlock.
1318
Thread JavaDoc t = new Thread JavaDoc(stopper);
1319      t.setDaemon(true);
1320      t.start();
1321    }
1322  }
1323
1324  static class ServerStopper implements Runnable JavaDoc {
1325    private long delay;
1326    private boolean reset;
1327
1328    ServerStopper(long delay, boolean reset) {
1329      this.delay = delay;
1330      this.reset = reset;
1331    }
1332
1333    public void run() {
1334      if (delay > 0) {
1335        try {
1336          Thread.sleep(delay);
1337        } catch (InterruptedException JavaDoc exc) {}
1338      }
1339      AgentServer.stop();
1340      if (reset) {
1341        AgentServer.reset();
1342      }
1343    }
1344  }
1345
1346  /**
1347   * Forces this AgentServer to stop executing. This method stops all
1348   * consumers and services. Be careful, the stop process is now synchronous
1349   * and wait for all server's thread to terminate ; If this method is called
1350   * from a server's thread it should result a dead-lock.
1351   */

1352  public static void stop() {
1353    if (logmon.isLoggable(BasicLevel.DEBUG))
1354      logmon.log(BasicLevel.DEBUG, getName() + ", stop()", new Exception JavaDoc());
1355    else
1356      logmon.log(BasicLevel.WARN, getName() + ", stop()");
1357
1358    synchronized(status) {
1359      if ((status.value != Status.STARTED) &&
1360          (status.value != Status.STOPPED)) {
1361        logmon.log(BasicLevel.WARN,
1362                   getName() + "cannot stop, bad status: " + status.value);
1363        return;
1364      }
1365      status.value = Status.STOPPING;
1366    }
1367
1368    try {
1369      // If the server is part of an HA group stops the JGroup component
1370
if (jgroups != null) jgroups.disconnect();
1371
1372      // Stop all message consumers.
1373
if (consumers != null) {
1374        for (Enumeration c=AgentServer.getConsumers(); c.hasMoreElements(); ) {
1375          MessageConsumer cons = (MessageConsumer) c.nextElement();
1376          if (cons != null) {
1377            if (logmon.isLoggable(BasicLevel.DEBUG))
1378              logmon.log(BasicLevel.DEBUG,
1379                         getName() + ", stop " + cons.getName());
1380
1381            cons.stop();
1382
1383            if (logmon.isLoggable(BasicLevel.DEBUG))
1384              logmon.log(BasicLevel.DEBUG,
1385                         getName() + ", " + cons.getName() + " stopped");
1386          }
1387        }
1388      }
1389      // Stop all services.
1390
ServiceManager.stop();
1391      // Stop all drivers
1392
Driver.stopAll();
1393
1394      // Wait for all threads before stop the TM !!
1395
while (true) {
1396        int nbt = getThreadGroup().activeCount();
1397        if (nbt == 0) break;
1398
1399        Thread JavaDoc[] tab = new Thread JavaDoc[nbt];
1400        getThreadGroup().enumerate(tab);
1401        if ((nbt == 1) && (tab[0] == Thread.currentThread())) break;
1402
1403        for (int j=0; j<tab.length; j++) {
1404          logmon.log(BasicLevel.DEBUG,
1405                     "[" + tab[j].getName() + ":" +
1406                     (tab[j].isAlive()?"alive":"-") + "/" +
1407                     (tab[j].isDaemon()?"daemon":"-") + "," +
1408                     tab[j]);
1409        }
1410        try {
1411          Thread.sleep(2500);
1412        } catch (InterruptedException JavaDoc e) {}
1413      }
1414
1415      // Stop the transaction manager.
1416
if (transaction != null) transaction.stop();
1417
1418      // Wait for the transaction manager stop
1419

1420      Runtime.getRuntime().gc();
1421      System.runFinalization();
1422
1423      logmon.log(BasicLevel.WARN, getName() + ", stopped at " + new Date());
1424    } catch (Throwable JavaDoc t) {
1425      logmon.log(BasicLevel.ERROR, getName() + "Cannot stop", t);
1426      synchronized(status) {
1427        // AF: Will be replaced by a BAD_STOPPED status allowing the
1428
// stop and reset..
1429
status.value = Status.STOPPED;
1430      }
1431    }
1432
1433    synchronized(status) {
1434      status.value = Status.STOPPED;
1435    }
1436  }
1437
1438  public static final String JavaDoc OKSTRING = "OK";
1439  public static final String JavaDoc ERRORSTRING = "ERROR";
1440  public static final String JavaDoc ENDSTRING = "END";
1441  /**
1442   * Main for a standard agent server.
1443   * The start arguments include in first position the identifier of the
1444   * agent server to start, and in second position the directory name where
1445   * the agent server stores its persistent data.
1446   *
1447   * @param args start arguments
1448   *
1449   * @exception Exception
1450   * unspecialized exception
1451   */

1452  public static void main(String JavaDoc args[]) throws Exception JavaDoc {
1453    try {
1454      init(args);
1455    } catch (Throwable JavaDoc exc) {
1456      System.out.println(getName() + "initialisation failed: " + ERRORSTRING);
1457      System.out.println(exc.toString());
1458      System.out.println(ENDSTRING);
1459      if (logmon == null)
1460        logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer");
1461      logmon.log(BasicLevel.ERROR,
1462                 getName() + " initialisation failed", exc);
1463      System.exit(1);
1464    }
1465
1466    try {
1467      String JavaDoc errStr = start();
1468      // Be careful, the output below is needed by some tools (AdminProxy for
1469
// example.
1470
if (errStr == null) {
1471        System.out.println(getName() + " started: " + OKSTRING);
1472      } else {
1473        System.out.println(getName() + " started: " + ERRORSTRING);
1474        System.out.print(errStr);
1475        System.out.println(ENDSTRING);
1476      }
1477    } catch (Throwable JavaDoc exc) {
1478      System.out.println(getName() + " start failed: " + ERRORSTRING);
1479      System.out.print(exc.toString());
1480      System.out.println(ENDSTRING);
1481      if (logmon == null)
1482        logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer");
1483      logmon.log(BasicLevel.ERROR, getName() + " failed", exc);
1484      System.exit(1);
1485    }
1486  }
1487}
1488
Popular Tags