KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > petals > jbi > transport > JoramAgent


1 /**
2  * PETALS: PETALS Services Platform
3  * Copyright (C) 2005 EBM WebSourcing
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA.
19  *
20  * Initial developer(s): EBM WebSourcing
21  * --------------------------------------------------------------------------
22  * $Id: JoramAgent.java,v 0.3 2005/07/22 10:24:27 alouis Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.petals.jbi.transport;
27
28 import java.io.File JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.net.ConnectException JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Properties JavaDoc;
35
36 import javax.naming.Binding JavaDoc;
37 import javax.naming.Context JavaDoc;
38 import javax.naming.InitialContext JavaDoc;
39 import javax.naming.NamingEnumeration JavaDoc;
40 import javax.naming.NamingException JavaDoc;
41
42 import org.apache.commons.io.FileUtils;
43 import org.objectweb.joram.client.jms.admin.AdminException;
44 import org.objectweb.joram.client.jms.admin.AdminModule;
45 import org.objectweb.util.monolog.Monolog;
46 import org.objectweb.util.monolog.api.LoggerFactory;
47
48 import org.objectweb.petals.PetalsException;
49 import org.objectweb.petals.jbi.transport.util.JoramConfigurationBuilder;
50 import org.objectweb.petals.kernel.admin.ContainerInformation;
51 import org.objectweb.petals.kernel.admin.ContainerInformation.ContainerState;
52 import org.objectweb.petals.util.JNDIUtil;
53 import org.objectweb.petals.util.LoggingUtil;
54 import org.objectweb.petals.util.PropertyUtil;
55 import org.objectweb.petals.util.SystemUtil;
56
57 import fr.dyade.aaa.agent.AgentServer;
58
59 /**
60  * Joram Agent used to start and stop the Joram server
61  *
62  * @author Adrien LOUIS - EBM WebSourcing
63  * @author ddesjardins - eBMWebsourcing
64  */

65 public class JoramAgent {
66
67     protected static final String JavaDoc CONTAINERS_REF = "containers";
68
69     /**
70      * Joram directory
71      */

72     private static final String JavaDoc JORAM_LOCATION = "joram";
73
74     /**
75      * Container UID
76      */

77     protected long containerUID;
78
79     /**
80      * Container Joram domain
81      */

82     protected String JavaDoc domain;
83
84     /**
85      * Container Joram domain port
86      */

87     protected String JavaDoc domainPort;
88
89     /**
90      * Monolog logger factory
91      */

92     protected LoggerFactory factory;
93
94     /**
95      * Component LifeCycle state.
96      */

97     protected String JavaDoc fcState;
98
99     /**
100      * Container host
101      */

102     protected String JavaDoc host;
103
104     /**
105      * Container id
106      */

107     protected String JavaDoc id;
108
109     /**
110      * Joram directory
111      */

112     protected File JavaDoc joramDir;
113
114     /**
115      * Logger Util
116      */

117     protected LoggingUtil log;
118
119     /**
120      * Container name
121      */

122     protected String JavaDoc name;
123
124     /**
125      * Container joram password
126      */

127     protected String JavaDoc password;
128
129     /**
130      * Initial context
131      */

132     protected InitialContext JavaDoc rootContext;
133
134     /**
135      * Container Joram tcp port
136      */

137     protected String JavaDoc tcpPort;
138
139     /**
140      * Container Joram user name
141      */

142     protected String JavaDoc username;
143
144     public JoramAgent(LoggingUtil log) {
145         this.log = log;
146     }
147
148     /**
149      * Retrieve the list of ContainerInformation by connecting to a JNDI
150      * directory
151      *
152      * @return List of ContainerInformation
153      */

154     protected List JavaDoc<ContainerInformation> retrieveAllContainersInformation() {
155         log.start();
156         List JavaDoc<ContainerInformation> containers = new ArrayList JavaDoc<ContainerInformation>();
157         try {
158             InitialContext JavaDoc rootContext = new InitialContext JavaDoc(PropertyUtil
159                 .retrieveJNDIProperties());
160             if (JNDIUtil.isBound(rootContext, "/", CONTAINERS_REF)) {
161                 NamingEnumeration JavaDoc<Binding JavaDoc> enums = rootContext
162                     .listBindings(CONTAINERS_REF);
163                 while (enums.hasMoreElements()) {
164                     Binding JavaDoc binding = (Binding JavaDoc) enums.next();
165                     ContainerInformation containerInformation = (ContainerInformation) binding
166                         .getObject();
167                     if (containerInformation.isStarted()) {
168                         containers.add(containerInformation);
169                     }
170                 }
171             }
172         } catch (NamingException JavaDoc e) {
173             log
174                 .debug("Problem while trying to retrieve all the containers information : context may not be initialized");
175         }
176         log.end();
177         return containers;
178     }
179
180     /**
181      * List of containers
182      */

183     protected List JavaDoc<ContainerInformation> containers = new ArrayList JavaDoc<ContainerInformation>();
184
185     /**
186      * Start the local Joram server
187      */

188     public void startServer() {
189
190         boolean isInit = false;
191
192         if (!isServerRunning()) {
193
194             try {
195                 // retrieves the global network configuration if any
196
containers = retrieveAllContainersInformation();
197
198                 // init the Joram server configuration from the
199
// server.properties file
200
initConfiguration();
201
202                 // Check if this server has already been started
203
// and have a stored network configuration.
204
boolean previsouslyStarted = isExistingConfiguration();
205
206                 if (!previsouslyStarted) {
207                     log
208                         .debug("First start, create a a3servers.xml configuration file.");
209                     // First start.
210
// We need to create an a3servers.xml file.
211

212                     // if a global configuration exists (other servers are
213
// launched),
214
// retreive this global network configuration
215
// and create the a3servers.xml file with it
216
// otherwise, assume this server is the first,
217
// create an a3servers.xml with this container only.
218
String JavaDoc configurationContent = null;
219                     if (containers.size() > 0) {
220                         /*
221                          * DISTRIBUTED CONFIGURATION
222                          */

223                         log
224                             .debug("Retrieve the existing network configuration from one of the running server.");
225                         configurationContent = retrieveDistributedConfiguration();
226                     } else {
227                         /*
228                          * ALONE CONFIGURATION
229                          */

230                         log
231                             .debug("Create an empty configuration as no server is runnning on the network.");
232                         name = id;
233                         SystemUtil.setContainerName(id);
234                         // Get alone Joram configuration
235
configurationContent = JoramConfigurationBuilder
236                             .buildFullMasterConf(domain, id, name, host,
237                                 username, password, domainPort, tcpPort, Long
238                                     .toString(containerUID));
239                     }
240
241                     // Check if a former Joram server was not stop correctly
242
cleanJoramServerNotStoppedCorrectly();
243
244                     // Write the configuration file with the
245
// distributed or alone configuration
246
FileUtils.writeStringToFile(new File JavaDoc(joramDir
247                         + File.separator + "a3servers.xml"),
248                         configurationContent, "UTF-8");
249
250                     System.setProperty("fr.dyade.aaa.agent.A3CONF_DIR",
251                         joramDir.getAbsolutePath());
252
253                 } else {
254                     // Nothing to do, the Joram persistance repository
255
// contains the last known configuration
256
log
257                         .debug("A stored network configuration as been found, restart with it.");
258                 }
259
260                 // Init the Joram server
261
initJoramAgentServer();
262
263                 isInit = true;
264
265                 // Start the Joram server
266
startJoramAgentServer();
267
268                 //register this server in the JNDI server
269
registerContainer(createContainerInformation());
270                 
271                 log.info("Joram server started at [host:port " + host + ":"
272                     + domainPort + ",tcp port " + tcpPort + ", jndi port "
273                     + ", domain name " + domain + ", server name " + name
274                     + ", server id " + id + "\n");
275
276             } catch (Exception JavaDoc e) {
277                 log.error("Problem while starting the Joram server", e);
278                 if (isInit) {
279                     fr.dyade.aaa.agent.AgentServer.stop(true);
280                 }
281             }
282         }
283     }
284
285     /**
286      * Stop the local Joram server
287      */

288     public void stopServer() {
289         log.start();
290         updateContainerState(SystemUtil.getContainerName(),
291             ContainerState.STOPPED);
292
293         if (isServerRunning()) {
294             fr.dyade.aaa.agent.AgentServer.stop();
295         }
296         log.end();
297     }
298
299     /**
300      * Add a Joram server to the Joram network
301      *
302      * @param id
303      * id of the server to add
304      * @param host
305      * host of the server to add
306      * @param domain
307      * domain of the server to add
308      * @param domainPort
309      * domain port of the server to add
310      * @param tcpPort
311      * tcp port of the server to add
312      * @throws ConnectException
313      * if a problems occurs while adding the server
314      * @throws AdminException
315      * if a problems occurs while adding the server
316      */

317     protected void addJoramServer(int id, String JavaDoc host, String JavaDoc domain,
318         int domainPort, String JavaDoc tcpPort) throws ConnectException JavaDoc, AdminException {
319         AdminModule
320             .addServer(
321                 id,
322                 host,
323                 domain,
324                 domainPort,
325                 name,
326                 new String JavaDoc[] {"org.objectweb.joram.mom.proxies.tcp.TcpProxyService"},
327                 new String JavaDoc[] {tcpPort});
328     }
329
330     /**
331      * This method is used to clean the Joram directory
332      *
333      * It will search for not correctly stopped Joram server
334      */

335     protected void cleanJoramServerNotStoppedCorrectly() {
336         for (File JavaDoc file : joramDir.listFiles()) {
337             if (file.isDirectory()) {
338                 // We are in a Joram backup directory
339
boolean isLock = false;
340                 for (File JavaDoc joramFile : file.listFiles()) {
341                     if ("lock".equals(joramFile.getName())) {
342                         // We are looking for a lock file
343
isLock = true;
344                         break;
345                     }
346                 }
347                 if (isLock) {
348                     // This Joram server was not shutdown correctly
349
// We need to remove the backup directory
350
try {
351                         FileUtils.forceDelete(file);
352                     } catch (IOException JavaDoc e) {
353                         // Do nothing
354
}
355                 }
356             }
357         }
358     }
359
360     /**
361      * Check if this server has been previously started and contains a
362      * configuration (check that the JORAM persistance directory is not empty)
363      *
364      * @return the server contains a previous network configuration
365      */

366     protected boolean isExistingConfiguration() {
367         return (joramDir != null && joramDir.exists() && joramDir.listFiles().length > 0);
368     }
369
370     /**
371      * Initialises the Joram configuration from the server.propertis file.
372      * Creates the JORAM persistance directory if not exists
373      *
374      * @throws IOException
375      */

376     protected void initConfiguration() {
377         // Retreive the logger factory
378
factory = Monolog
379             .instanciateMonologFactory("org.objectweb.petals.util.monolog.wrapper.javalog.LoggerFactory");
380
381         // Set the cache files directory for Joram
382
joramDir = new File JavaDoc(SystemUtil.getPetalsInstallDirectory()
383             + File.separator + JORAM_LOCATION + File.separator);
384         if (!joramDir.exists()) {
385             joramDir.mkdir();
386         }
387
388         // Retreive Joram properties
389
domain = SystemUtil.getJoramDomain();
390         id = SystemUtil.getJoramId();
391         name = SystemUtil.getJoramId();
392         host = SystemUtil.getHost();
393
394         username = SystemUtil.getJoramUser();
395         password = SystemUtil.getJoramPassword();
396         tcpPort = SystemUtil.getJoramTCPPort();
397         domainPort = SystemUtil.getJoramDomainPort();
398         containerUID = SystemUtil.getContainerUID();
399     }
400
401     /**
402      * @see AgentServer#init(short, String, LoggerFactory)
403      */

404     protected void initJoramAgentServer() throws Exception JavaDoc {
405         log.call();
406         fr.dyade.aaa.agent.AgentServer.init((short) Integer.parseInt(id),
407             joramDir.getAbsolutePath() + File.separator + id, factory);
408     }
409
410     /**
411      * Is the local joram server running or not
412      *
413      * @return true if the server is running
414      */

415     protected boolean isServerRunning() {
416         return 4 == fr.dyade.aaa.agent.AgentServer.getStatus();
417     }
418
419     /**
420      * Is the specified server is registered in the Joram global configuration.
421      * <b>AdminModule.connect required</b>
422      *
423      * @return
424      * @throws AdminException
425      * @throws ConnectException
426      */

427     protected boolean isServerRegistered(String JavaDoc serverId)
428         throws ConnectException JavaDoc, AdminException {
429         boolean serverAlreadyExist = false;
430         for (Iterator JavaDoc serverIdsIt = AdminModule.getServersIds().iterator(); serverIdsIt
431             .hasNext()
432             && !serverAlreadyExist;) {
433             String JavaDoc aServerId = serverIdsIt.next().toString();
434             serverAlreadyExist = (aServerId.equalsIgnoreCase(serverId));
435         }
436         return serverAlreadyExist;
437     }
438
439     /**
440      * Retrieve a distribution configuration for this Joram server. <br>
441      * We search for a valid Joram server on the network, <br>
442      * then catch its configuration, <br>
443      * add our container into it if necessary (if it has been previously <br>
444      * started, it is already in this conf), <br>
445      * and return this new configuration (as an XML string)
446      *
447      * @return String containing the Joram configuration
448      */

449     protected String JavaDoc retrieveDistributedConfiguration() {
450         String JavaDoc conf = null;
451
452         if (containers.size() > 0) {
453             // Loop on the containers to connect to the AdminModule
454
Iterator JavaDoc<ContainerInformation> containersIt = containers.iterator();
455             boolean fail = true;
456             while (fail && containersIt.hasNext()) {
457                 try {
458                     ContainerInformation information = containersIt.next();
459                     log.debug("Trying to connect to Joram server on "
460                         + information.getHost() + ":"
461                         + information.getJoramTCPPort());
462                     AdminModule.connect(information.getHost(), Integer
463                         .parseInt(information.getJoramTCPPort()), information
464                         .getJoramLogin(), information.getJoramPassword(), 3);
465
466                     // Recover the configuration
467
conf = AdminModule.getConfiguration();
468
469                     // if our server has not been already recorded in the global
470
// conf, add it
471
if (!isServerRegistered(id)) {
472                         addJoramServer(Integer.parseInt(id), host, domain,
473                             Integer.parseInt(domainPort), tcpPort);
474                     }
475                     AdminModule.disconnect();
476
477                     // Exit the loop if everything is OK
478
fail = false;
479                 } catch (Exception JavaDoc e) {
480                     log.warning("Impossible to connect to Joram, try another",
481                         e);
482                 }
483             }
484             if (conf != null) {
485                 // Set correct parameters in the Conf if necessary
486
conf = JoramConfigurationBuilder.buildFullConfiguration(conf,
487                     domain, id, name, host, username, password, domainPort,
488                     tcpPort, Long.toString(containerUID));
489             } else {
490                 throw new RuntimeException JavaDoc(
491                     "Unable to connect to other Petals container, so stop");
492             }
493         } else {
494             conf = JoramConfigurationBuilder.buildFullMasterConf(domain, id,
495                 name, host, username, password, domainPort, tcpPort, Long
496                     .toString(containerUID));
497         }
498         return conf;
499     }
500
501     /**
502      * Retrieve an initial context
503      *
504      * @param outProperties
505      * properties of the JNDI directory
506      * @return Initial context
507      * @throws NamingException
508      * if a problem occurs
509      */

510     protected InitialContext JavaDoc retrieveInitialContext(Properties JavaDoc outProperties)
511         throws NamingException JavaDoc {
512         return new InitialContext JavaDoc(outProperties);
513     }
514
515     /**
516      * @see AgentServer#start()
517      */

518     protected void startJoramAgentServer() throws Exception JavaDoc {
519         log.call();
520         fr.dyade.aaa.agent.AgentServer.start();
521     }
522
523     /**
524      * Update the state of a container
525      *
526      * @param containerName
527      * name of the container to update
528      * @param state
529      * state of the container
530      */

531     protected void updateContainerState(String JavaDoc containerName,
532         ContainerState state) {
533         log.start();
534         if (containerName == null) {
535             throw new IllegalArgumentException JavaDoc(
536                 "Container name must be non null");
537         }
538         if (!(!state.equals(ContainerState.STARTED) || !state
539             .equals(ContainerState.STOPPED))) {
540             throw new IllegalArgumentException JavaDoc("State must be "
541                 + ContainerState.STARTED + " or " + ContainerState.STOPPED);
542         }
543         try {
544             InitialContext JavaDoc rootContext = new InitialContext JavaDoc(PropertyUtil
545                 .retrieveJNDIProperties());
546             if (JNDIUtil.isBound(rootContext, "/", CONTAINERS_REF)) {
547                 if (JNDIUtil
548                     .isBound(rootContext, CONTAINERS_REF, containerName)) {
549                     Context JavaDoc containersContext = (Context JavaDoc) rootContext
550                         .lookup(CONTAINERS_REF);
551                     ContainerInformation containerInformation = (ContainerInformation) containersContext
552                         .lookup(containerName);
553                     containerInformation.setState(state);
554                     containersContext.rebind(containerName,
555                         containerInformation);
556                 }
557             }
558         } catch (Exception JavaDoc e) {
559             log.error("Problem while updating container state", e);
560         }
561         log.end();
562     }
563
564     /**
565      * Shutdown the Joram server. It is unreferenced the distributed joram
566      * server configuration, and its <code>ContainerInformation</code> is
567      * removed from the distributed jndi server.
568      */

569     public void shutdown() throws Exception JavaDoc {
570
571         // algo : connect to this server,
572
// remove ourselves from the configuration,
573
// this remove is automaticcaly propagated
574
// to other Servers
575

576         try {
577             AdminModule.connect(host, Integer.parseInt(tcpPort), username,
578                 password, 3);
579             AdminModule.removeServer(Integer.parseInt(SystemUtil.getJoramId()));
580             AdminModule.disconnect();
581
582             removeFromContainersInformation();
583         } catch (Exception JavaDoc e) {
584             log.error("Problem while connecting to this Joram server", e);
585         }
586     }
587
588     /**
589      * Remove this container from JNDI
590      */

591     protected void removeFromContainersInformation() {
592         log.start();
593         String JavaDoc containerName = SystemUtil.getContainerName();
594         try {
595             InitialContext JavaDoc rootContext = new InitialContext JavaDoc(PropertyUtil
596                 .retrieveJNDIProperties());
597             if (JNDIUtil.isBound(rootContext, "/", CONTAINERS_REF)) {
598                 if (JNDIUtil
599                     .isBound(rootContext, CONTAINERS_REF, containerName)) {
600                     Context JavaDoc containersContext = (Context JavaDoc) rootContext
601                         .lookup(CONTAINERS_REF);
602                     containersContext.unbind(containerName);
603                 }
604             }
605         } catch (Exception JavaDoc e) {
606             log.error("Problem while removing container information", e);
607         }
608     }
609     
610     /**
611      * Register the local container in the jndi directory
612      *
613      * @throws PetalsException
614      */

615     protected void registerContainer(ContainerInformation containerInformation) throws PetalsException {
616         log.start();
617         try {
618             InitialContext JavaDoc rootContext = new InitialContext JavaDoc(PropertyUtil
619                 .retrieveJNDIProperties());
620             if (!JNDIUtil.isBound(rootContext, CONTAINERS_REF,
621                 containerInformation.getName())) {
622                 Context JavaDoc containerCtx = (Context JavaDoc)rootContext.lookup(CONTAINERS_REF);
623                 containerCtx.bind(containerInformation.getName(),
624                     containerInformation);
625             } else {
626                 Context JavaDoc containerCtx = (Context JavaDoc)rootContext.lookup(CONTAINERS_REF);
627                 containerCtx.rebind(containerInformation.getName(),
628                     containerInformation);
629             }
630         } catch (NamingException JavaDoc e) {
631             throw new PetalsException(
632                 "Error while binding container information", e);
633         }
634         log.end();
635     }
636
637     /**
638      * Retrieve the information of the local container
639      *
640      * @return information of the container
641      * @throws PetalsException
642      * if a problem occurs while readings the properties files
643      */

644     protected ContainerInformation createContainerInformation()
645         throws PetalsException {
646         log.start();
647         ContainerInformation containerInformation = new ContainerInformation();
648         try {
649             containerInformation.setHost(SystemUtil.getHost());
650             containerInformation.setName(SystemUtil.getContainerName());
651             containerInformation.setJoramId(SystemUtil.getContainerName());
652             containerInformation.setJoramDomainPort(SystemUtil
653                 .getJoramDomainPort());
654             containerInformation.setJoramLogin(SystemUtil.getJoramUser());
655             containerInformation
656                 .setJoramPassword(SystemUtil.getJoramPassword());
657             containerInformation.setJoramTCPPort(SystemUtil.getJoramTCPPort());
658             containerInformation.setJoramDomain(SystemUtil.getJoramDomain());
659
660             // set jmx properties
661
containerInformation.setJmxPort(SystemUtil.getJmxPort());
662             containerInformation.setJmxLogin(SystemUtil.getJmxUser());
663             containerInformation.setJmxPassword(SystemUtil.getJmxPassword());
664
665             // Set HTML properties
666
containerInformation.setHtmlPort(SystemUtil.getHtmlPort());
667
668             // Set jndi properties
669
containerInformation.setJndiFactory(SystemUtil.getJndiFactory());
670             containerInformation.setJndiPort(SystemUtil.getJndiPort());
671
672             containerInformation.setUid(SystemUtil.getContainerUID());
673
674             containerInformation.setState(ContainerState.STARTED);
675
676         } catch (Exception JavaDoc e) {
677             throw new PetalsException(
678                 "Failed to retrieve container informations", e);
679         }
680         log.end();
681         return containerInformation;
682     }
683
684 }
685
Popular Tags