KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > management > ReconfigManager


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  */

22 package org.objectweb.jonas.management;
23
24 // general Java imports
25
import java.util.Hashtable JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 import javax.management.JMException JavaDoc;
29 import javax.management.MBeanServer JavaDoc;
30 import javax.management.MBeanServerNotification JavaDoc;
31 import javax.management.Notification JavaDoc;
32 import javax.management.NotificationListener JavaDoc;
33 import javax.management.ObjectName JavaDoc;
34
35 import org.objectweb.jonas.common.JProp;
36 import org.objectweb.jonas.common.Log;
37 import org.objectweb.jonas.jmx.JonasObjectName;
38 import org.objectweb.util.monolog.api.BasicLevel;
39 import org.objectweb.util.monolog.api.Logger;
40 /**
41  * This MBean allows persistent reconfiguration of a JOnAS server, alltogether with its embedded services,
42  * and possibly used resources like Data Sources ans Mail Factories.
43  * This class implements NotificationListener interface. The ReconfigManager adds itself as Listener to
44  * the following JMX Notification types (JAVA types):
45  * <ul>
46  * <li>MBeanServerNotification</li>, sent by the MBean server on MBeans registration/un-registration
47  * <li>Notification with type equal to ReconfigDispatcher.RECONFIG_TYPE</li>
48  * <li>Notification with type equal to ReconfigDispatcher.SAVE_RECONFIG_TYPE</li>
49  * </ul>
50  * @author Adriana Danes
51  * 04/09/20 Update with JSR77 JDBCDataSource MBeans
52  */

53 public class ReconfigManager implements ReconfigManagerMBean, NotificationListener JavaDoc {
54
55     /**
56      * The logger used in JOnAS
57      */

58     private static Logger logger = null;
59
60     /**
61      * The MBean server attached to the current JOnAS server
62      */

63     MBeanServer JavaDoc jmxServer = null;
64
65     // The following Strings reflect the current implementation of the org.objectweb.jonas.jmx.JonasObjectName class !!
66
// ------------------------------------------------------------------------------------------------------------------
67
// The value of the 'type' property in JonasObjectName of the services MBeans
68
private static final String JavaDoc SERVICE_TYPE = "service";
69
70     // The value of the 'type' property in JonasObjectName used by DataSources
71
private static final String JavaDoc DATASOURCE_TYPE = "datasource";
72
73
74     // J2EE Management specification conformance
75
// -----------------------------------------
76
/**
77      * The value of the j2eeType key for Mail Resources
78      */

79     private static final String JavaDoc MAIL_RESOURCE_TYPE = "JavaMailResource";
80     /**
81      * The value of the j2eeType key for JTA Resources
82      */

83     private static final String JavaDoc JTA_RESOURCE_TYPE = "JTAResource";
84     /**
85      * The value of the j2eeType key for JDBCDataSources
86      */

87     private static final String JavaDoc JDBC_RESOURCE_TYPE = "JDBCDataSource";
88
89     /**
90      * Type of the security realm
91      */

92     private static final String JavaDoc SECURITYREALM_FACTORY = "securityfactory";
93
94
95     /**
96      * Name of the security realm file
97      */

98     private static final String JavaDoc SECURITYREALM_FILE = "jonas-realm.xml";
99
100
101     // My JMX name
102
ObjectName JavaDoc reconfigManagerObectName = JonasObjectName.serverConfig();
103
104     // The JOnAS server's initialization properties (saves several method call JProp.getInstance().getConfigFileEnv();)
105
// and configuration file name
106
Properties JavaDoc serverProperties = null;
107     String JavaDoc serverConfigFileName = null;
108
109     // Table of Reconfigurator objects.
110
// We have a Reconfigurator object per each reconfigurable service + one for the server itself + one per resource
111
Hashtable JavaDoc reconfigurators = new Hashtable JavaDoc();
112
113     /**
114      * Create the ReconfigManager MBean instance and add itself as listner to MBeanServerNotifications.
115      * @param serverProperties The JOnAS server's initial configuration properties
116      * @param jmxServer The JOnAS server's MBean server
117      */

118     public ReconfigManager(Properties JavaDoc serverProperties, MBeanServer JavaDoc jmxServer) throws ReconfigException {
119         // get a logger for server traces
120
logger = Log.getLogger(Log.JONAS_MANAGEMENT_PREFIX);
121
122         this.serverProperties = serverProperties;
123         this.jmxServer = jmxServer;
124         try {
125             this.serverConfigFileName = JProp.getInstance().getPropFile();
126         } catch (Exception JavaDoc e) {
127             throw new ReconfigException("Can't initialize ReconfigManager because of exception: " + e.toString());
128         }
129
130         // Add myself as listner to MBeanServerNotifications. Use for this the MBeanServerDelegate ObjectName as
131
// argument in the addNotificationListener method (see JMX API for more info).
132
// Use null NotificationFilter and null handback object.
133
try {
134             ObjectName JavaDoc delegate = new ObjectName JavaDoc("JMImplementation:type=MBeanServerDelegate");
135             jmxServer.addNotificationListener(delegate, this, null, null);
136         } catch (JMException JavaDoc me) {
137             // MalformedObjectNameException should not occur if the JMX implementation is correct
138
// InstanceNotFoundException should not occur as we use MBeanServerDelegate ObjectName
139
throw new ReconfigException("ReconfigManager can't listen to MBeanServerNotifications because of exception: " + me.toString());
140         }
141         if (logger.isLoggable(BasicLevel.DEBUG)) {
142             logger.log(BasicLevel.DEBUG, "ReconfigManager MBean registered itself as listner to MBeanServerNotifications");
143         }
144     }
145
146     /**
147      * Treat the notifications emitted by those MBeans having the ReconfigManager added as listener.
148      * This method determines the type of the notification and calls the specific treatement.
149      * @param notification received notification
150      * @param handback received handback object
151      */

152     public void handleNotification(Notification JavaDoc notification, java.lang.Object JavaDoc handback) {
153         String JavaDoc notificationType = notification.getType();
154         if (notification instanceof MBeanServerNotification JavaDoc) {
155             // This notification is sent by the jmx server. It may be a REGISTRATION_NOTIFICATION or an UNREGISTRATION_NOTIFICATION
156
if (notificationType.equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
157                 try {
158                     handleRegistrationNotification((MBeanServerNotification JavaDoc) notification);
159                 } catch (ReconfigException re) {
160                     logger.log(BasicLevel.ERROR, "ReconfigManager error when trying to handle REGISTRATION_NOTIFICATION");
161                 }
162             } else if (notificationType.equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
163                 if (logger.isLoggable(BasicLevel.DEBUG)) {
164                     logger.log(BasicLevel.DEBUG, "Received UNREGISTRATION_NOTIFICATION for MBean " + ((MBeanServerNotification JavaDoc) notification).getMBeanName().toString());
165                 }
166                 // TO DO ...
167
}
168         } else {
169             // The MBean sending this notification has an associated Reconfigurator object created by the handleRegistrationNotification() method.
170
// Get the Reconfigurator's name from the 'message' field
171
String JavaDoc name = notification.getMessage();
172             // get the sequence number
173
long sequence = notification.getSequenceNumber();
174             if (notificationType.equals(ReconfigDispatcher.RECONFIG_TYPE)) {
175                 // get the reconfigured property (or properties) sent as a UserData within the notification
176
Reconfigured reconfigured = (Reconfigured) notification.getUserData();
177                 if (reconfigured instanceof ReconfiguredProp) {
178                     ReconfiguredProp prop = (ReconfiguredProp) reconfigured;
179                         handleReconfig(name, sequence, prop);
180                 } else {
181                     ReconfiguredXml reconfiguredXml = (ReconfiguredXml) reconfigured;
182                     handleReconfig(name, sequence, reconfiguredXml);
183                 }
184             } else if (notificationType.equals(ReconfigDispatcher.SAVE_RECONFIG_TYPE)) {
185                 handleSave(name, sequence);
186             }
187         }
188     }
189
190     /**
191      * Treat REGISTRATION_NOTIFICATION methods. If the notification sender is a MBean associated to a service or resources,
192      * create a Reconfigurator associated to the sender and adds itself as listener
193      * for notifications emitted by the sender.
194      * @param notification notification to treat
195      * @throws ReconfigException pb. when trying to create reconfiguration support
196      */

197     private void handleRegistrationNotification(MBeanServerNotification JavaDoc notification) throws ReconfigException {
198         ObjectName JavaDoc notificationSender = notification.getMBeanName();
199         String JavaDoc senderType = notificationSender.getKeyProperty("type");
200         String JavaDoc senderName = notificationSender.getKeyProperty("name");
201         String JavaDoc senderJ2eeType = notificationSender.getKeyProperty("j2eeType");
202         Reconfigurator reconfig = null;
203         if (senderJ2eeType != null) {
204             senderType = senderJ2eeType;
205         }
206
207         if (senderType == null) {
208             // Nothing to do
209
return;
210         }
211
212         if (senderType.equals(SERVICE_TYPE)) {
213             // The registered MBean is a JOnAS service MBean.
214
// Create a Reconfigurator for the service (the reconfigurator name is the service name)
215
// Currently only support Reconfiguration for JOnAS services
216
// (are not supported : the Log system and the server itself)
217
if (!senderName.equals("jonasServer")) {
218                 if (senderName.equals("log")) {
219                     // treat log system case
220
String JavaDoc configFileName = notificationSender.getKeyProperty("fname");
221                     try {
222                         reconfig = new ReconfiguratorProp(senderName, JProp.getInstance(configFileName).getPropFile(), JProp.getInstance(configFileName).getConfigFileEnv());
223                     } catch (Exception JavaDoc e) {
224                         // This is a FileNotFound exception thrown by JProp.getInstance(resourceName)
225
// which means that the resource was not created from a configuration file at the server start-up.
226
// The persistent configuration of dynamically loaded resource is not implementes yet !!!!!
227
logger.log(BasicLevel.WARN, "Cannot do persistent reconfiguration for dynamically loaded resources!");
228                     }
229                 } else {
230                     // treat regular jonas services
231
reconfig = new ReconfiguratorProp(senderName, serverConfigFileName, serverProperties);
232                 }
233             }
234         } else {
235             // Check if the registered MBean is a JOnAS resource
236
// The currently considered resources are Mail Factories and Datasources
237
String JavaDoc resourceName = null;
238             try {
239                 if (senderType.equals(MAIL_RESOURCE_TYPE)) {
240                     // get the name of the Mail Factory
241
resourceName = (String JavaDoc) jmxServer.getAttribute(notificationSender, "FactoryName");
242                 } else if (senderType.equals(JDBC_RESOURCE_TYPE)) {
243                     // get the name of the Datasource
244
resourceName = (String JavaDoc) jmxServer.getAttribute(notificationSender, "name");
245                 } else if (senderType.equals(JTA_RESOURCE_TYPE)) {
246                     // treat as the regular service case
247
reconfig = new ReconfiguratorProp(senderName, serverConfigFileName, serverProperties);
248                     // resource name keeps null so avoids entering in code (if) below
249
}
250
251                 // xml type
252
if (senderType.equals(SECURITYREALM_FACTORY)) {
253                     JProp jprop = JProp.getInstance(SECURITYREALM_FILE);
254                     String JavaDoc propsFilename = jprop.getPropFile();
255                     String JavaDoc txt = jprop.getConfigFileXml();
256                     // Create a Reconfigurator for this resource
257
reconfig = new ReconfiguratorXml(SECURITYREALM_FILE, propsFilename, txt);
258                 } else if (resourceName != null) {
259                     JProp jprop = JProp.getInstance(resourceName);
260                     String JavaDoc propsFilename = jprop.getPropFile();
261                     Properties JavaDoc props = JProp.getInstance(resourceName).getConfigFileEnv();
262                     // Create a Reconfigurator for this resource
263
reconfig = new ReconfiguratorProp(resourceName, propsFilename, props);
264                 }
265             } catch (JMException JavaDoc me) {
266                 logger.log(BasicLevel.ERROR, "Catched Exception when trying to treat reconfiguration of the following resource: " + me);
267                 throw new ReconfigException("Catched Exception when trying to treat reconfiguration of the following resource: " + me.toString());
268             } catch (Exception JavaDoc e) {
269                 // this exception is thrown by JProp.getInstance(resourceName)
270
// its not possible to receive it here because if the MBean registered itself, this call was already exceuted succesfully
271
logger.log(BasicLevel.ERROR, "Catched Exception when calling JProp.getInstance(" + resourceName + "): " + e);
272                 throw new ReconfigException("Catched Exception when calling JProp.getInstance(" + resourceName + "): " + e.toString());
273             }
274         }
275         if (reconfig != null) {
276             try {
277                 jmxServer.addNotificationListener(notificationSender, reconfigManagerObectName, null, null);
278             } catch (JMException JavaDoc me) {
279                 logger.log(BasicLevel.ERROR, "ReconfigManager can't listen to Notifications because of exception: " + me.toString());
280                 throw new ReconfigException("ReconfigManager can't listen to Notifications because of exception: " + me.toString());
281             }
282             reconfigurators.put(senderName, reconfig);
283             if (logger.isLoggable(BasicLevel.DEBUG)) {
284                 logger.log(BasicLevel.DEBUG, "Received Registration Notification from " + notificationSender.toString());
285             }
286         }
287     }
288
289     /**
290      * Treat reconfiguration operation by calling the specific method on the associated reconfigurator
291      * @param name reconfigurator name
292      * @param sequence sequence number of the reconfiguration notification to treat
293      * @param prop reconfigured property (or properties)
294      */

295     private void handleReconfig(String JavaDoc name, long sequence, ReconfiguredProp prop) throws ReconfigException {
296         if (logger.isLoggable(BasicLevel.DEBUG)) {
297             logger.log(BasicLevel.DEBUG, "Received 'jonas.management.reconfiguration' notification concerning service or ressource: " + name);
298         }
299         Reconfigurator reconfigurator = (ReconfiguratorProp) reconfigurators.get(name);
300         if (reconfigurator == null) {
301             throw new ReconfigException("Can't find Reconfigurator associated to service or resource " + name);
302         } else {
303            if (prop.getPropValue() != null) {
304                if (logger.isLoggable(BasicLevel.DEBUG)) {
305                    logger.log(BasicLevel.DEBUG, "Try to reconfigure property : " + prop.getPropName() + " using value value : " + prop.getPropValue());
306                }
307                 if (prop.replaceProp()) {
308                     ((ReconfiguratorProp) reconfigurator).updateConfig(prop.getPropName(), prop.getPropValue(), sequence);
309                 } else {
310                     if (logger.isLoggable(BasicLevel.DEBUG)) {
311                         if (prop.addProp()) {
312                             logger.log(BasicLevel.DEBUG, "This value has to be added to the values sequence");
313                         } else {
314                             logger.log(BasicLevel.DEBUG, "This value has to be removed from the values sequence");
315                         }
316                     }
317                     ((ReconfiguratorProp) reconfigurator).updateConfig(prop.getPropName(), prop.getPropValue(), prop.addProp(), sequence);
318                 }
319             } else {
320                 if (logger.isLoggable(BasicLevel.DEBUG)) {
321                     logger.log(BasicLevel.DEBUG, "Reconfiguration made on a group of properties");
322                 }
323                 ((ReconfiguratorProp) reconfigurator).updateConfig(prop.getProps(), sequence);
324             }
325         }
326     }
327
328     /**
329      * Treat reconfiguration operation by calling the specific method on the associated reconfigurator
330      * @param name reconfigurator name
331      * @param sequence sequence number of the reconfiguration notification to treat
332      * @param reconfiguredXml reconfigured xml
333      */

334     private void handleReconfig(String JavaDoc name, long sequence, ReconfiguredXml reconfiguredXml) throws ReconfigException {
335         if (logger.isLoggable(BasicLevel.DEBUG)) {
336             logger.log(BasicLevel.DEBUG, "Received 'jonas.management.reconfiguration' notification concerning service or ressource: " + name);
337         }
338         Reconfigurator reconfigurator = (ReconfiguratorXml) reconfigurators.get(name);
339         if (reconfigurator == null) {
340             throw new ReconfigException("Can't find Reconfigurator associated to service or resource " + name);
341         } else {
342                 ((ReconfiguratorXml) reconfigurator).updateConfig(reconfiguredXml.getXml(), sequence);
343         }
344     }
345
346
347     /**
348      * Treat save operation by calling the specific method on the associated reconfigurator
349      * @param name reconfigurator name
350      * @param sequence sequence number of the reconfiguration notification to treat
351      */

352     private void handleSave(String JavaDoc name, long sequence) throws ReconfigException {
353         if (logger.isLoggable(BasicLevel.DEBUG)) {
354             logger.log(BasicLevel.DEBUG, "Received 'jonas.management.reconfiguration.save' notification concerning service or ressource: " + name);
355         }
356         Reconfigurator reconfigurator = (Reconfigurator) reconfigurators.get(name);
357         if (reconfigurator == null) {
358             throw new ReconfigException("Can't find Reconfigurator associated to service or resource " + name);
359         } else {
360             reconfigurator.saveConfig(sequence);
361         }
362     }
363 }
364
Popular Tags