fr/dyade/aaa/agent/AgentServer.java

00001 /*
00002  * Copyright (C) 2001 - 2008 ScalAgent Distributed Technologies
00003  * Copyright (C) 2004 - France Telecom R&D
00004  * Copyright (C) 1996 - 2000 BULL
00005  * Copyright (C) 1996 - 2000 INRIA
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or any later version.
00011  * 
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00020  * USA.
00021  *
00022  * Initial developer(s): Dyade
00023  * Contributor(s): ScalAgent Distributed Technologies
00024  */
00025 package fr.dyade.aaa.agent;
00026 
00027 import java.io.DataInputStream;
00028 import java.io.File;
00029 import java.io.FileInputStream;
00030 import java.io.IOException;
00031 import java.util.Date;
00032 import java.util.Enumeration;
00033 import java.util.Hashtable;
00034 
00035 import org.objectweb.util.monolog.api.BasicLevel;
00036 import org.objectweb.util.monolog.api.Logger;
00037 import org.objectweb.util.monolog.api.LoggerFactory;
00038 
00039 import fr.dyade.aaa.agent.conf.A3CML;
00040 import fr.dyade.aaa.agent.conf.A3CMLCluster;
00041 import fr.dyade.aaa.agent.conf.A3CMLConfig;
00042 import fr.dyade.aaa.agent.conf.A3CMLDomain;
00043 import fr.dyade.aaa.agent.conf.A3CMLNat;
00044 import fr.dyade.aaa.agent.conf.A3CMLNetwork;
00045 import fr.dyade.aaa.agent.conf.A3CMLProperty;
00046 import fr.dyade.aaa.agent.conf.A3CMLServer;
00047 import fr.dyade.aaa.agent.conf.A3CMLService;
00048 import fr.dyade.aaa.util.Timer;
00049 import fr.dyade.aaa.util.Transaction;
00050 import fr.dyade.aaa.util.management.MXWrapper;
00051 
00144 public final class AgentServer {
00145   public final static short NULL_ID = -1;
00146 
00147   public final static String ADMIN_DOMAIN = "D0";
00148   public final static String ADMIN_SERVER = "s0";
00149 
00150   private static short serverId = NULL_ID;
00151 
00152   private static Logger logmon = null;
00153 
00154   public final static String CFG_DIR_PROPERTY = "fr.dyade.aaa.agent.A3CONF_DIR";
00155   public final static String DEFAULT_CFG_DIR = null;
00156   
00157   public final static String CFG_FILE_PROPERTY = "fr.dyade.aaa.agent.A3CONF_FILE";
00158   public final static String DEFAULT_CFG_FILE = "a3servers.xml";
00159   public final static String DEFAULT_SER_CFG_FILE = "a3cmlconfig";
00160   
00161   public final static String CFG_NAME_PROPERTY = "fr.dyade.aaa.agent.A3CONF_NAME";
00162   public final static String DEFAULT_CFG_NAME = "default";
00163   
00164   public final static String A3CMLWRP_PROPERTY = "fr.dyade.aaa.agent.A3CMLWrapper";
00165   public final static String DEFAULT_A3CMLWRP = "fr.dyade.aaa.agent.conf.A3CMLSaxWrapper";
00166 
00167   static ThreadGroup tgroup = null;
00168 
00169   public static ThreadGroup getThreadGroup() {
00170     return tgroup;
00171   }
00172 
00180   static Engine engine = null;
00181 
00185   public static Engine getEngine() {
00186     return engine;
00187   }
00188 
00190   static Transaction transaction = null;
00191 
00195   public static Transaction getTransaction() {
00196     return transaction;
00197   }
00198 
00199   private static JGroups jgroups = null;
00200   private static short clusterId = NULL_ID;
00201   
00207   public static boolean isHAServer() {
00208     return (jgroups != null);
00209   }
00210 
00216   public static boolean isMasterHAServer() {
00217     if (jgroups != null)
00218       return jgroups.isCoordinator();
00219     return false;
00220   }
00221   
00222   private static ConfigController configController;
00223 
00224   public static ConfigController getConfigController() {
00225     return configController;
00226   }
00227 
00232   private static Hashtable consumers = null;
00233 
00234   static void addConsumer(String domain,
00235                           MessageConsumer cons) throws Exception {
00236     if (consumers.containsKey(domain))
00237       throw new Exception("Consumer for domain " + domain + " already exist");
00238 
00239     consumers.put(domain, cons);
00240 
00241     try {
00242       MXWrapper.registerMBean(cons,
00243                               "AgentServer",
00244                               "server=" + getName() + ",cons=" + cons.getName());
00245     } catch (Exception exc) {
00246       logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
00247     }
00248   }
00249 
00250   static Enumeration getConsumers() {
00251     if (consumers == null)
00252       return null;
00253     else
00254       return consumers.elements();
00255   }
00256 
00257   static MessageConsumer getConsumer(String domain) throws Exception {
00258     if (! consumers.containsKey(domain))
00259       throw new Exception("Unknown consumer for domain " + domain);
00260     return (MessageConsumer) consumers.get(domain);
00261   }
00262 
00263   static void removeConsumer(String domain) {
00264     MessageConsumer cons = (MessageConsumer) consumers.remove(domain);
00265     if (cons != null) {
00266       cons.stop();
00267       try {
00268         MXWrapper.unregisterMBean("AgentServer", "server=" + getName() + ",cons=" + cons.getName());
00269       } catch (Exception exc) {
00270         logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
00271       }
00272     }
00273   }
00274   
00278   private static Timer timer;
00279 
00283   public static final Timer getTimer() {
00284     if (timer == null) {
00285       timer = new Timer();
00286     }
00287     return timer;
00288   }
00289 
00291   private static A3CMLConfig a3config = null;
00292 
00300   public final static void setConfig(A3CMLConfig a3config) throws Exception {
00301     setConfig(a3config, false);
00302   }
00303 
00304   final static void setConfig(A3CMLConfig a3config,
00305                               boolean force) throws Exception {
00306     if (! force) {
00307       synchronized(status) {
00308         if (status.value != Status.INSTALLED)
00309           throw new Exception("cannot set config, bad status: " + getStatusInfo());
00310       }
00311     }
00312     AgentServer.a3config = a3config;
00313   }
00314   
00320   public final static A3CMLConfig getConfig() throws Exception {
00321     if (a3config == null) throw new Exception("Server not configured");
00322     return a3config;
00323   }
00324 
00333   public static A3CMLConfig getAppConfig(String[] domains) throws Exception {
00334     return getConfig().getDomainConfig(domains);
00335   }
00336 
00337   public final static short getServerId() {
00338     return serverId;
00339   }
00340 
00341   public final static short getClusterId() {
00342     return clusterId;
00343   }
00344 
00345   private static String name = null;
00346 
00347   public final static String getName() {
00348     return name;
00349   }
00350 
00358   public static short getServerIdByName(String name) throws Exception {
00359     return getConfig().getServerIdByName(name);
00360   }
00361   
00369   public static String getProperty(String key) {
00370     return System.getProperty(key);
00371   }
00372 
00381   public static String getProperty(String key, String value) {
00382     return System.getProperty(key, value);
00383   }
00384 
00392   public static Integer getInteger(String key) {
00393     try {
00394       return Integer.getInteger(key);
00395     } catch (Exception exc) {
00396       return null;
00397     }
00398   }
00399 
00408   public static Integer getInteger(String key, int value) {
00409     try {
00410       return Integer.getInteger(key, value);
00411     } catch (Exception exc) {
00412       return null;
00413     }
00414   }
00415 
00417   private static ServersHT servers = null;
00418 
00419   static void addServerDesc(ServerDesc desc) throws Exception {
00420     if (desc == null) return;
00421     servers.put(desc);
00422   }
00423 
00424   static ServerDesc removeServerDesc(short sid) throws Exception {
00425     return servers.remove(sid);
00426   }
00427 
00428   public static Enumeration elementsServerDesc() {
00429     return servers.elements();
00430   }
00431 
00432   public static Enumeration getServersIds() {
00433     return servers.keys();
00434   }
00435 
00441   final static int getServerNb() {
00442     return servers.size();
00443   }
00444 
00451   final static ServerDesc getServerDesc(short sid) throws UnknownServerException {
00452     ServerDesc serverDesc = servers.get(sid);
00453     if (serverDesc == null)
00454       throw new UnknownServerException("Unknow server id. #" + sid);
00455     return serverDesc;
00456   }
00457 
00464   final static MessageConsumer getConsumer(short sid) throws UnknownServerException {
00465     return getServerDesc(sid).domain;
00466   }
00467 
00474   public final static String getHostname(short sid) throws UnknownServerException {
00475     return getServerDesc(sid).getHostname();
00476   }
00477 
00483   final static ServiceDesc[] getServices() throws UnknownServerException {
00484     return getServerDesc(getServerId()).services;
00485   }
00486 
00505   public final static
00506   String getServiceArgs(short sid,
00507                         String classname) throws Exception {
00508     return getConfig().getServiceArgs(sid, classname);
00509   }
00510 
00528   public final static
00529   String getServiceArgs(String hostname,
00530                         String classname) throws Exception {
00531     return getConfig().getServiceArgsHost(hostname, classname);
00532   }
00533 
00540   private static void configure() throws Exception {
00541     A3CMLServer root = getConfig().getServer(serverId, clusterId);
00542     //Allocates the temporary descriptors hashtable for each server.
00543     servers = new ServersHT();
00544     // Initialized the descriptor of current server in order to permit
00545     // Channel and Engine initialization.
00546     ServerDesc local = new ServerDesc(root.sid, root.name, root.hostname, -1);
00547     servers.put(local);
00548 
00549     // Parse configuration in order to fix route related to the
00550     // current server
00551     getConfig().configure(root);
00552 
00553     // Creates all the local MessageConsumer.
00554     createConsumers(root);
00555     
00556     for (Enumeration s = getConfig().servers.elements();
00557          s.hasMoreElements();) {
00558       A3CMLServer server = (A3CMLServer) s.nextElement();
00559       if (server.sid == root.sid) continue;
00560 
00561       ServerDesc desc = createServerDesc(server);
00562       addServerDesc(desc);
00563     }
00564 
00565     // for clusters
00566     for (Enumeration c = getConfig().clusters.elements();
00567          c.hasMoreElements();) {
00568       A3CMLCluster cluster = (A3CMLCluster) c.nextElement();
00569 
00570       for (Enumeration s = cluster.servers.elements();
00571            s.hasMoreElements();) {
00572         A3CMLServer server = (A3CMLServer) s.nextElement();
00573         if (server.sid == root.sid) continue;
00574 
00575         ServerDesc desc = servers.get(server.sid);
00576         if (desc == null) {
00577           desc = createServerDesc(server);
00578           addServerDesc(desc);
00579         } else {
00580           desc.addSockAddr(server.hostname, server.port);
00581         }
00582       }
00583     }
00584 
00585     initServices(root, local);
00586     local.domain = engine;
00587 
00588 //     if (logmon.isLoggable(BasicLevel.DEBUG)) {
00589 //       for (int i=0; i<servers.length; i++) {
00590 //         logmon.log(BasicLevel.DEBUG,
00591 //                    getName() + ", servers[" + i + "]=(" + 
00592 //                    "sid=" + servers[i].sid + 
00593 //                    ", name=" + servers[i].name + 
00594 //                    ", gateway=" + servers[i].gateway + 
00595 //                    ", domain=" + servers[i].domain + ")");
00596 //       }
00597 //     }
00598     
00599     return;
00600   }
00601 
00602   private static void createConsumers(A3CMLServer root) throws Exception {
00603     consumers = new Hashtable();
00604 
00605     // Creates the local MessageConsumer: the Engine.
00606     engine = Engine.newInstance();
00607     addConsumer("local", engine);
00608 
00609     // if JGroups
00610     if (clusterId > NULL_ID) {
00611       jgroups = new JGroups();
00612       if (engine instanceof HAEngine) {
00613         jgroups.setEngine((HAEngine) engine);
00614         ((HAEngine) engine).setJGroups(jgroups);
00615       } else
00616         logmon.log(BasicLevel.ERROR, getName() + ", createConsumers(" + root + ")\n" +
00617                    "engine [" + engine + "] is not a HAEngine");
00618     }
00619 
00620     // Search all directly accessible domains.
00621     for (Enumeration n = root.networks.elements();
00622          n.hasMoreElements();) {
00623       A3CMLNetwork network = (A3CMLNetwork) n.nextElement();
00624 
00625       A3CMLDomain domain = getConfig().getDomain(network.domain);
00626       // Creates the corresponding MessageConsumer.
00627       try {
00628         Network consumer = (Network) Class.forName(domain.network).newInstance();
00629         // Initializes it with domain description. Be careful, this array
00630         // is kept in consumer, don't reuse it!!
00631         consumer.init(domain.name, network.port, domain.getServersId());
00632         if (consumer instanceof SimpleNetwork &&
00633             jgroups != null) {//NTA modify to SimpleHANetwork
00634           ((SimpleNetwork) consumer).setJGroups(jgroups);
00635           jgroups.setNetWork((SimpleNetwork) consumer);
00636         }
00637 //         domain.consumer = consumer;
00638         addConsumer(network.domain, consumer);
00639       } catch (ClassNotFoundException exc) {
00640         throw exc;
00641       } catch (InstantiationException exc) {
00642         throw exc;
00643       } catch (IllegalAccessException exc) {
00644         throw exc;
00645       }
00646     }
00647   }
00648 
00649   static void initServerDesc(ServerDesc desc,
00650                              A3CMLServer server) throws Exception {
00651     desc.gateway = server.gateway;
00652     // For each server set the gateway to the real next destination of
00653     // messages; if the server is directly accessible: itself.
00654     if ((desc.gateway == -1) || (desc.gateway == server.sid)) {
00655       desc.gateway = server.sid;
00656       desc.updateSockAddr(desc.getHostname(), server.port);   
00657       A3CMLServer current = getConfig().getServer(getServerId(),getClusterId());
00658       if (current.containsNat(server.sid)) {
00659         A3CMLNat nat = current.getNat(server.sid);
00660         desc.updateSockAddr(nat.host, nat.port);
00661         if (logmon.isLoggable(BasicLevel.DEBUG))
00662           logmon.log(BasicLevel.DEBUG, getName() + " : NAT sDesc = " + desc);
00663       }
00664     }
00665     desc.domain = getConsumer(server.domain);
00666   }   
00667 
00668   private static ServerDesc
00669       createServerDesc(A3CMLServer server) throws Exception {
00670     if (! server.visited)
00671       throw new Exception(server + " inaccessible");
00672     
00673     ServerDesc desc = new ServerDesc(server.sid, 
00674                                      server.name, 
00675                                      server.hostname,
00676                                      -1);
00677 
00678     initServerDesc(desc, server);
00679     initServices(server, desc);
00680 
00681     return desc;
00682   }
00683 
00684   private static void initServices(A3CMLServer server, ServerDesc desc) {
00685     if (server.services != null) {
00686       ServiceDesc services[]  = new ServiceDesc[server.services.size()];
00687       int idx = 0;
00688       for (Enumeration x = server.services.elements();
00689            x.hasMoreElements();) {
00690         A3CMLService service = (A3CMLService) x.nextElement();
00691         services[idx++] = new ServiceDesc(service.classname, service.args);
00692       }
00693       desc.services = services;
00694     }
00695   }
00696   
00697   private static void setProperties(short sid, short cid) throws Exception {
00698     if (a3config == null) return;
00699 
00700     // add global properties
00701     if (a3config.properties != null) {
00702       for (Enumeration e = a3config.properties.elements(); e.hasMoreElements();) {
00703         A3CMLProperty p = (A3CMLProperty) e.nextElement();
00704         System.getProperties().put(p.name, p.value);
00705 
00706         if (logmon.isLoggable(BasicLevel.DEBUG))
00707           logmon.log(BasicLevel.DEBUG,
00708                      getName() + " : Adds global property: " +
00709                      p.name + " = " + p.value);
00710       }
00711     }
00712 
00713     A3CMLServer server = null;
00714     if (cid != NULL_ID) {
00715       A3CMLCluster cluster = null;
00716       cluster = a3config.getCluster(sid);
00717 
00718       // add cluster properties
00719       if (cluster != null 
00720           && cluster.properties != null 
00721           && cluster.properties.size() > 0) {
00722         Enumeration e = cluster.properties.elements();
00723         do {
00724           A3CMLProperty p = (A3CMLProperty) e.nextElement();
00725           System.getProperties().put(p.name,p.value);
00726 
00727           if (logmon.isLoggable(BasicLevel.DEBUG))
00728             logmon.log(BasicLevel.DEBUG,
00729                        getName() + " : Adds cluster property: " +
00730                        p.name + " = " + p.value);
00731         } while (e.hasMoreElements());
00732       }
00733       server = cluster.getServer(cid);
00734     } else {
00735       server = a3config.getServer(sid);
00736     }
00737 
00738     // add server properties
00739     if (server != null && server.properties != null) {
00740       Enumeration e = server.properties.elements();
00741       do {
00742         A3CMLProperty p = (A3CMLProperty) e.nextElement();
00743         System.getProperties().put(p.name,p.value);
00744 
00745         if (logmon.isLoggable(BasicLevel.DEBUG))
00746           logmon.log(BasicLevel.DEBUG,
00747                      getName() + " : Adds server property: " +
00748                      p.name + " = " + p.value);
00749       } while (e.hasMoreElements());
00750     }
00751   }
00752   
00753   public static class Status {
00754     public static final int INSTALLED = 0;
00755     public static final int INITIALIZING = 0x1;
00756     public static final int INITIALIZED = 0x2;
00757     public static final int STARTING = 0x3;
00758     public static final int STARTED = 0x4;
00759     public static final int STOPPING = 0x5;
00760     public static final int STOPPED = 0x6;
00761     public static final int RESETING = 0x7;
00762 
00763     private int value = INSTALLED;
00764 
00765     public static String[] info = {"installed",
00766                                    "initializing", "initialized",
00767                                    "starting", "started",
00768                                    "stopping", "stopped",
00769                                    "reseting"};
00770   }
00771 
00772   static Status status = new Status();
00773 
00774   public static int getStatus() {
00775     return status.value;
00776   }
00777 
00778   public static String getStatusInfo() {
00779     return Status.info[status.value];
00780   }
00781 
00796   public static int init(String args[]) throws Exception {
00797     if (args.length < 2)
00798       throw new Exception("usage: java <main> sid storage");
00799     short sid = NULL_ID;
00800     try {
00801       sid = (short) Integer.parseInt(args[0]);
00802     } catch (NumberFormatException exc) {
00803       throw new Exception("usage: java <main> sid storage");
00804     }
00805     String path = args[1];
00806     short cid = NULL_ID;
00807     try {
00808       if (args.length == 3)
00809       cid = (short) Integer.parseInt(args[2]);
00810     } catch (NumberFormatException exc) {}
00811 
00812     init(sid, path, null, cid);
00813 
00814     configController = new ConfigController();
00815 
00816     return 2;
00817   }
00818 
00819   public static void reset(boolean force) {
00820     if (force) {
00821       synchronized(status) {
00822         if (status.value != Status.STOPPED) {
00823           logmon.log(BasicLevel.WARN,
00824                      getName() + ", force status: " + getStatusInfo());
00825         }
00826         status.value = Status.STOPPED;
00827       }
00828     }
00829     reset();
00830   }
00831 
00836   public static void reset() {
00837     synchronized(status) {
00838       if (status.value != Status.STOPPED) {
00839         logmon.log(BasicLevel.WARN,
00840                    getName() + ", cannot reset, bad status: " + getStatusInfo());
00841         return;
00842       }
00843       status.value = Status.RESETING;
00844     }
00845 
00846     // Remove all consumers Mbean
00847     Enumeration e = getConsumers();
00848     if (e != null) {
00849       for (; e.hasMoreElements();) {
00850         MessageConsumer cons = (MessageConsumer) e.nextElement();
00851         try {
00852           MXWrapper.unregisterMBean(
00853             "AgentServer",
00854             "server=" + getName() + ",cons=" + cons.getName());
00855         } catch (Exception exc) {
00856           logmon.log(BasicLevel.DEBUG,
00857                      getName() + ", jmx failed: " +
00858                      "server=" + getName() + ",cons=" + cons.getName(), exc);
00859         }
00860       }
00861       consumers = null;
00862     }
00863 
00864     try {
00865       MXWrapper.unregisterMBean("AgentServer",
00866                                 "server=" + getName() + ",cons=Transaction");
00867     } catch (Exception exc) {
00868       logmon.log(BasicLevel.DEBUG,
00869                  getName() + ", jmx failed: " +
00870                  "server=" + getName() + ",cons=Transaction", exc);
00871     }
00872 
00873     if (transaction != null) transaction.close();
00874     transaction = null;
00875 
00876     try {
00877       MXWrapper.unregisterMBean("AgentServer", "server=" + getName());
00878     } catch (Exception exc) {
00879       logmon.log(BasicLevel.DEBUG,
00880                  getName() + " jmx failed: "+ "server=" + getName(), exc);
00881     }
00882     
00883     a3config = null;
00884 
00885     synchronized(status) {
00886       status.value = Status.INSTALLED;
00887     }
00888   }
00889 
00905   public static void init(short sid,
00906                           String path,
00907                           LoggerFactory loggerFactory) throws Exception {
00908     init(sid, path, loggerFactory, NULL_ID);
00909   }
00910 
00927   public static void init(short sid,
00928                           String path,
00929                           LoggerFactory loggerFactory,
00930                           short cid) throws Exception {
00931     if (cid == NULL_ID)
00932       name = new StringBuffer("AgentServer#").append(sid).toString();
00933     else
00934       name = new StringBuffer("AgentServer#").append(sid).append('.').append(cid).toString();
00935 
00936     if (loggerFactory != null) Debug.setLoggerFactory(loggerFactory);
00937     logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer.#" + sid);
00938 
00939     if (logmon.isLoggable(BasicLevel.DEBUG))
00940       logmon.log(BasicLevel.DEBUG, getName() + ", init()", new Exception());
00941     else
00942       logmon.log(BasicLevel.WARN, getName() + ", init()");
00943 
00944     synchronized(status) {
00945       if (status.value == Status.STOPPED) {
00946         logmon.log(BasicLevel.DEBUG, getName() + ", reset configuration");
00947         reset();
00948       }
00949       if (status.value != Status.INSTALLED)
00950         throw new Exception("cannot initialize, bad status: " + getStatusInfo());
00951       status.value = Status.INITIALIZING;
00952     }
00953 
00954     try {
00955       serverId = sid; 
00956 
00957       tgroup = new ThreadGroup(getName()) {
00958         public void uncaughtException(Thread t, Throwable e) {
00959           if (e instanceof VirtualMachineError) {
00960             if (logmon.isLoggable(BasicLevel.FATAL)) {
00961               logmon.log(BasicLevel.FATAL,
00962                          "Abnormal termination for " +
00963                          t.getThreadGroup().getName() + "." + t.getName(),
00964                          e);
00965               // AF: Should be AgentServer.stop() ?
00966               System.exit(-1);
00967             }
00968           } else {
00969             if (logmon.isLoggable(BasicLevel.WARN)) {
00970               logmon.log(BasicLevel.WARN,
00971                          "Abnormal termination for " + t.getThreadGroup().getName() + "." + t.getName(), e);
00972             }
00973           }
00974         }
00975       };
00976    
00977       //  Try to get transaction type from disk, then initialize the rigth
00978       // transaction manager and get the configuration.
00979       File dir = new File(path);
00980       if (dir.exists() && dir.isDirectory()) {
00981         File tfc = new File(dir, "TFC");
00982         if (tfc.exists()) {
00983           DataInputStream dis = null;
00984           try {
00985             dis = new DataInputStream(new FileInputStream(tfc));
00986             String tname = dis.readUTF();
00987             Class tclass = Class.forName(tname);
00988             transaction = (Transaction) tclass.newInstance();
00989           } catch (Exception exc) {
00990             logmon.log(BasicLevel.FATAL,
00991                        getName() + ", can't instanciate transaction manager",
00992                        exc);
00993             throw new Exception("Can't instanciate transaction manager");
00994           } finally {
00995             if (dis != null) dis.close();
00996           }
00997           try {
00998             transaction.init(path);
00999           } catch (IOException exc) {
01000             logmon.log(BasicLevel.FATAL,
01001                        getName() + ", can't start transaction manager", exc);
01002             throw new Exception("Can't start transaction manager");
01003           }
01004         }
01005       }
01006 
01007       // Gets static configuration of agent servers from a file. This method
01008       // fills the object graph configuration in the <code>A3CMLConfig</code>
01009       // object, then the configure method really initializes the server.
01010       // There are two steps because the configuration step needs the
01011       // transaction components to be initialized.
01012       if (transaction != null) {
01013         // Try to read the serialized configuration (through transaction)
01014         try {
01015           a3config = A3CMLConfig.load();
01016         } catch (Exception exc) {
01017           logmon.log(BasicLevel.WARN, getName() + ", config not found");
01018         }
01019       }
01020 
01021       if (a3config == null) {
01022         //  Try to load an initial configuration (serialized or XML), or
01023         // generates a default one in case of failure.
01024         try {
01025           a3config = A3CMLConfig.getConfig(DEFAULT_SER_CFG_FILE);
01026         } catch (Exception exc) {
01027           logmon.log(BasicLevel.WARN,
01028                      getName() + ", serialized a3cmlconfig not found");
01029         }
01030 
01031         if (a3config == null) {
01032           // Try to found XML configuration file, then parse it.
01033           try {
01034             a3config = A3CML.getXMLConfig();
01035           } catch (Exception exc) {
01036             logmon.log(BasicLevel.WARN,
01037                        getName() + ", XML configuration file not found");
01038           }
01039         }
01040 
01041         if (a3config == null) {
01042           // 3rd, Generate A3CMLConfig base.
01043           logmon.log(BasicLevel.WARN,
01044                      "Generate default configuration");
01045           A3CMLDomain d = new A3CMLDomain(ADMIN_DOMAIN,
01046                                           "fr.dyade.aaa.agent.SimpleNetwork");
01047           A3CMLServer s = new A3CMLServer((short) 0, ADMIN_SERVER, "localhost");
01048           s.networks.addElement(new A3CMLNetwork(ADMIN_DOMAIN, 27300));
01049           s.services.addElement(new A3CMLService("fr.dyade.aaa.agent.AgentAdmin",null));
01050           d.addServer(s);
01051           a3config = new A3CMLConfig();
01052           a3config.addDomain(d);
01053           a3config.addServer(s);
01054         }
01055       }
01056 
01057       // if JGroups
01058       if (cid > NULL_ID) clusterId = cid;
01059 
01060       // set properties
01061       setProperties(serverId, clusterId);
01062 
01063       // Initializes the JMX Wrapper
01064       MXWrapper.init();
01065 
01066       if (transaction == null) {
01067         try {
01068           String tname = getProperty("Transaction",
01069                                      "fr.dyade.aaa.util.NTransaction");
01070           transaction = (Transaction) Class.forName(tname).newInstance();
01071         } catch (Exception exc) {
01072           logmon.log(BasicLevel.FATAL,
01073                      getName() + ", can't instanciate transaction manager", exc);
01074           throw new Exception("Can't instanciate transaction manager");
01075         }
01076 
01077         try {
01078           transaction.init(path);
01079         } catch (IOException exc) {
01080           logmon.log(BasicLevel.FATAL,
01081                      getName() + ", can't start transaction manager", exc);
01082           throw new Exception("Can't start transaction manager");
01083         }
01084       }
01085 
01086       try {
01087         MXWrapper.registerMBean(transaction,
01088                                 "AgentServer",
01089                                 "server=" + getName() + ",cons=Transaction");
01090       } catch (Exception exc) {
01091         if (logmon == null)
01092           logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer");
01093         logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
01094       }
01095 
01096       // save A3CMLConfig (Maybe we can omit it in some case).
01097       a3config.save();
01098 
01099       try {
01100         // Initialize AgentId class's variables.
01101         AgentId.init();
01102       } catch (ClassNotFoundException exc) {
01103         logmon.log(BasicLevel.FATAL,
01104                    getName() + ", can't initialize AgentId", exc);
01105         throw new Exception("Can't initialize AgentId, bad classpath");
01106       } catch (IOException exc) {
01107         logmon.log(BasicLevel.FATAL,
01108                    getName() + ", can't initialize AgentId", exc);
01109         throw new Exception("Can't initialize AgentId, storage problems");
01110       }
01111 
01112       try {
01113         // Configure the agent server.
01114         configure();
01115       } catch (Exception exc) {
01116         logmon.log(BasicLevel.FATAL, getName() + ", can't configure", exc);
01117         throw new Exception("Can't configure server");
01118       }
01119 
01120       try {
01121         // then restores all messages.
01122         String[] list = transaction.getList("@");
01123         for (int i=0; i<list.length; i++) {
01124           Message msg = Message.load(list[i]);
01125 
01126           if (msg.getSource() == serverId) {
01127             // The update has been locally generated, the message is ready to
01128             // deliver to its consumer (Engine or Network component). So we have
01129             // to insert it in the queue of this consumer.
01130             try {
01131               getServerDesc(msg.getDest()).domain.insert(msg);
01132             } catch (UnknownServerException exc) {
01133               logmon.log(BasicLevel.ERROR,
01134                          getName() + ", discard message to unknown server id#" +
01135                          msg.getDest());
01136               msg.delete();
01137               msg.free();
01138               continue;
01139             } catch (NullPointerException exc) {
01140               logmon.log(BasicLevel.ERROR,
01141                          getName() + ", discard message to unknown server id#" +
01142                          msg.getDest());
01143               msg.delete();
01144               msg.free();
01145               continue;
01146             } catch (ArrayIndexOutOfBoundsException exc) {
01147               logmon.log(BasicLevel.ERROR,
01148                          getName() + ", discard message to unknown server id#" +
01149                          msg.getDest());
01150               msg.delete();
01151               msg.free();
01152               continue;
01153             }
01154           } else {
01155             logmon.log(BasicLevel.ERROR,
01156                        getName() + ", discard undelivered message from server id#" +
01157                        msg.getDest());
01158             msg.delete();
01159             continue;
01160           }
01161         }
01162       } catch (ClassNotFoundException exc) {
01163         logmon.log(BasicLevel.FATAL,
01164                    getName() + ", can't restore messages", exc);
01165         throw new Exception("Can't restore messages, bad classpath");
01166       } catch (IOException exc) {
01167         logmon.log(BasicLevel.FATAL,
01168                    getName() + ", can't restore messages", exc);
01169         throw new Exception("Can't restore messages, storage problems");
01170       }
01171 
01172       // initializes channel before initializing fixed agents
01173       Channel.newInstance();    
01174 
01175       try {
01176         //  Initialize services.
01177         ServiceManager.init();
01178 
01179         logmon.log(BasicLevel.INFO,
01180                    getName() + ", ServiceManager initialized");
01181 
01182         /* Actually get Services from A3CML configuration file. */
01183         ServiceDesc services[] = AgentServer.getServices();
01184         if (services != null) {
01185           for (int i = 0; i < services.length; i ++) {
01186             ServiceManager.register(services[i].getClassName(),
01187                                     services[i].getArguments());
01188           }
01189         }
01190         ServiceManager.save();
01191       } catch (Exception exc) {
01192         logmon.log(BasicLevel.FATAL,
01193                    getName() + ", can't initialize services", exc);
01194         throw new Exception("Can't initialize services");
01195       }
01196 
01197       // initializes fixed agents
01198       engine.init();
01199 
01200       // If the server is part of an HA group starts the JGroup component
01201       if (jgroups != null) jgroups.init(sid);
01202 
01203       logmon.log(BasicLevel.WARN,
01204                  getName() + ", initialized at " + new Date());
01205 
01206       // Commit all changes.
01207       transaction.begin();
01208       transaction.commit(true);
01209 
01210       try {
01211         SCServerMBean bean = new SCServer();
01212         MXWrapper.registerMBean(bean, "AgentServer", "server=" + getName());
01213       } catch (Exception exc) {
01214         if (logmon == null)
01215           logmon = Debug.getLogger(Debug.A3Debug + ".AgentServer");
01216         logmon.log(BasicLevel.ERROR, getName() + " jmx failed", exc);
01217       }
01218     } catch (Exception exc) {
01219       logmon.log(BasicLevel.ERROR, getName() + "Cannot initialize", exc);
01220       synchronized(status) {
01221         // AF: Will be replaced by a BAD_INITIALIZED status allowing the
01222         // re-initialization..
01223         status.value = Status.INSTALLED;
01224       }
01225       throw exc;
01226     } catch (Throwable t) {
01227       logmon.log(BasicLevel.ERROR, getName() + "Cannot initialize", t);
01228       synchronized(status) {
01229         // AF: Will be replaced by a BAD_INITIALIZED status allowing the
01230         // re-initialization..
01231         status.value = Status.INSTALLED;
01232       }
01233       throw new Exception(t.getMessage());
01234     }
01235 
01236     synchronized(status) {
01237       status.value = Status.INITIALIZED;
01238     }
01239   }
01240 
01241   static String startConsumers() throws Exception {
01242     StringBuffer errBuf = null;
01243 
01244     // Now we can start all networks.
01245     if (consumers != null) {
01246       for (Enumeration c=AgentServer.getConsumers(); c.hasMoreElements(); ) {
01247         MessageConsumer cons = (MessageConsumer) c.nextElement();