ReconfigManager.java

00001 
00022 package org.objectweb.jonas.management;
00023 
00024 // general Java imports
00025 import java.util.Hashtable;
00026 import java.util.Properties;
00027 
00028 import javax.management.JMException;
00029 import javax.management.MBeanServer;
00030 import javax.management.MBeanServerNotification;
00031 import javax.management.Notification;
00032 import javax.management.NotificationListener;
00033 import javax.management.ObjectName;
00034 
00035 import org.objectweb.jonas.common.JProp;
00036 import org.objectweb.jonas.common.Log;
00037 import org.objectweb.jonas.jmx.JonasObjectName;
00038 import org.objectweb.util.monolog.api.BasicLevel;
00039 import org.objectweb.util.monolog.api.Logger;
00053 public class ReconfigManager implements ReconfigManagerMBean, NotificationListener {
00054 
00058     private static Logger logger = null;
00059 
00063     MBeanServer jmxServer = null;
00064 
00065     // The following Strings reflect the current implementation of the org.objectweb.jonas.jmx.JonasObjectName class !!
00066     // ------------------------------------------------------------------------------------------------------------------
00067     // The value of the 'type' property in JonasObjectName of the services MBeans
00068     private static final String SERVICE_TYPE = "service";
00069 
00070     // The value of the 'type' property in JonasObjectName used by DataSources
00071     private static final String DATASOURCE_TYPE = "datasource";
00072 
00073 
00074     // J2EE Management specification conformance
00075     // -----------------------------------------
00079     private static final String MAIL_RESOURCE_TYPE = "JavaMailResource";
00083     private static final String JTA_RESOURCE_TYPE = "JTAResource";
00087     private static final String JDBC_RESOURCE_TYPE = "JDBCDataSource";
00088 
00092     private static final String SECURITYREALM_FACTORY = "securityfactory";
00093 
00094 
00098     private static final String SECURITYREALM_FILE = "jonas-realm.xml";
00099 
00100 
00101     // My JMX name
00102     ObjectName reconfigManagerObectName = JonasObjectName.serverConfig();
00103 
00104     // The JOnAS server's initialization properties (saves several method call JProp.getInstance().getConfigFileEnv();)
00105     // and configuration file name
00106     Properties serverProperties = null;
00107     String serverConfigFileName = null;
00108 
00109     // Table of Reconfigurator objects.
00110     // We have a Reconfigurator object per each reconfigurable service + one for the server itself + one per resource
00111     Hashtable reconfigurators = new Hashtable();
00112 
00118     public ReconfigManager(Properties serverProperties, MBeanServer jmxServer) throws ReconfigException {
00119         // get a logger for server traces
00120         logger = Log.getLogger(Log.JONAS_MANAGEMENT_PREFIX);
00121 
00122         this.serverProperties = serverProperties;
00123         this.jmxServer = jmxServer;
00124         try {
00125             this.serverConfigFileName = JProp.getInstance().getPropFile();
00126         } catch (Exception e) {
00127             throw new ReconfigException("Can't initialize ReconfigManager because of exception: " + e.toString());
00128         }
00129 
00130         // Add myself as listner to  MBeanServerNotifications. Use for this the MBeanServerDelegate ObjectName as
00131         // argument in the addNotificationListener method (see JMX API for more info).
00132         // Use null NotificationFilter and null handback object.
00133         try {
00134             ObjectName delegate = new ObjectName("JMImplementation:type=MBeanServerDelegate");
00135             jmxServer.addNotificationListener(delegate, this, null, null);
00136         } catch (JMException me) {
00137             // MalformedObjectNameException should not occur if the JMX implementation is correct
00138             // InstanceNotFoundException should not occur as we use MBeanServerDelegate ObjectName
00139             throw new ReconfigException("ReconfigManager can't listen to MBeanServerNotifications because of exception: " + me.toString());
00140         }
00141         logger.log(BasicLevel.DEBUG, "ReconfigManager MBean registered itself as listner to MBeanServerNotifications");
00142     }
00143 
00150     public void handleNotification(Notification notification, java.lang.Object handback) {
00151         String notificationType = notification.getType();
00152         if (notification instanceof MBeanServerNotification) {
00153             // This notification is sent by the jmx server. It may be a REGISTRATION_NOTIFICATION or an UNREGISTRATION_NOTIFICATION
00154             if (notificationType.equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
00155                 try {
00156                     handleRegistrationNotification((MBeanServerNotification) notification);
00157                 } catch (ReconfigException re) {
00158                     logger.log(BasicLevel.ERROR, "ReconfigManager error when trying to handle REGISTRATION_NOTIFICATION");
00159                 }
00160             } else if (notificationType.equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
00161                 logger.log(BasicLevel.DEBUG, "Received UNREGISTRATION_NOTIFICATION for MBean " + ((MBeanServerNotification) notification).getMBeanName().toString());
00162                 // TO DO ...
00163             }
00164         } else {
00165             // The MBean sending this notification has an associated Reconfigurator object created by the handleRegistrationNotification() method.
00166             // Get the Reconfigurator's name from the 'message' field
00167             String name = notification.getMessage();
00168             // get the sequence number
00169             long sequence = notification.getSequenceNumber();
00170             if (notificationType.equals(ReconfigDispatcher.RECONFIG_TYPE)) {
00171                 // get the reconfigured property (or properties) sent as a UserData within the notification
00172                 Reconfigured  reconfigured = (Reconfigured) notification.getUserData();
00173                 if (reconfigured instanceof ReconfiguredProp) {
00174                     ReconfiguredProp prop = (ReconfiguredProp) reconfigured;
00175                         handleReconfig(name, sequence, prop);
00176                 } else {
00177                     ReconfiguredXml reconfiguredXml = (ReconfiguredXml) reconfigured;
00178                     handleReconfig(name, sequence, reconfiguredXml);
00179                 }
00180             } else if (notificationType.equals(ReconfigDispatcher.SAVE_RECONFIG_TYPE)) {
00181                 handleSave(name, sequence);
00182             }
00183         }
00184     }
00185 
00193     private void handleRegistrationNotification(MBeanServerNotification notification) throws ReconfigException {
00194         ObjectName notificationSender = notification.getMBeanName();
00195         String senderType = notificationSender.getKeyProperty("type");
00196         String senderName = notificationSender.getKeyProperty("name");
00197         String senderJ2eeType = notificationSender.getKeyProperty("j2eeType");
00198         Reconfigurator reconfig = null;
00199         if (senderJ2eeType != null) {
00200             senderType = senderJ2eeType;
00201         }
00202 
00203         if (senderType == null) {
00204             // Nothing to do
00205             return;
00206         }
00207 
00208         if (senderType.equals(SERVICE_TYPE)) {
00209             // The registered MBean is a JOnAS service MBean.
00210             // Create a Reconfigurator for the service (the reconfigurator name is the service name)
00211             // Currently only support Reconfiguration for JOnAS services
00212             // (are not supported : the Log system and the server itself)
00213             if (!senderName.equals("jonasServer")) {
00214                 if (senderName.equals("log")) {
00215                     // treat log system case
00216                     String configFileName = notificationSender.getKeyProperty("fname");
00217                     try {
00218                         reconfig = new ReconfiguratorProp(senderName, JProp.getInstance(configFileName).getPropFile(), JProp.getInstance(configFileName).getConfigFileEnv());
00219                     } catch (Exception e) {
00220                         // This is a FileNotFound exception thrown by JProp.getInstance(resourceName)
00221                         // which means that the resource was not created from a configuration file at the server start-up.
00222                         // The persistent configuration of dynamically loaded resource is not implementes yet !!!!!
00223                         logger.log(BasicLevel.WARN, "Cannot do persistent reconfiguration for dynamically loaded resources!");
00224                     }
00225                 } else {
00226                     // treat regular jonas services
00227                     reconfig = new ReconfiguratorProp(senderName, serverConfigFileName, serverProperties);
00228                 }
00229             }
00230         } else {
00231             // Check if the registered MBean is a JOnAS resource
00232             // The currently considered resources are Mail Factories and Datasources
00233             String resourceName = null;
00234             try {
00235                 if (senderType.equals(MAIL_RESOURCE_TYPE)) {
00236                     // get the name of the Mail Factory
00237                     resourceName = (String) jmxServer.getAttribute(notificationSender, "FactoryName");
00238                 } else if (senderType.equals(JDBC_RESOURCE_TYPE)) {
00239                     // get the name of the Datasource
00240                     resourceName = (String) jmxServer.getAttribute(notificationSender, "name");
00241                 } else if (senderType.equals(JTA_RESOURCE_TYPE)) {
00242                     // treat as the regular service case
00243                     reconfig = new ReconfiguratorProp(senderName, serverConfigFileName, serverProperties);
00244                     // resource name keeps null so avoids entering in code (if) below
00245                 }
00246 
00247                 // xml type
00248                 if (senderType.equals(SECURITYREALM_FACTORY)) {
00249                     JProp jprop = JProp.getInstance(SECURITYREALM_FILE);
00250                     String propsFilename = jprop.getPropFile();
00251                     String txt = jprop.getConfigFileXml();
00252                     // Create a Reconfigurator for this resource
00253                     reconfig = new ReconfiguratorXml(SECURITYREALM_FILE, propsFilename, txt);
00254                 } else if (resourceName != null) {
00255                     JProp jprop = JProp.getInstance(resourceName);
00256                     String propsFilename = jprop.getPropFile();
00257                     Properties props = JProp.getInstance(resourceName).getConfigFileEnv();
00258                     // Create a Reconfigurator for this resource
00259                     reconfig = new ReconfiguratorProp(resourceName, propsFilename, props);
00260                 }
00261             } catch (JMException me) {
00262                 logger.log(BasicLevel.ERROR, "Catched Exception when trying to treat reconfiguration of the following resource: " + me);
00263                 throw new ReconfigException("Catched Exception when trying to treat reconfiguration of the following resource: " + me.toString());
00264             } catch (Exception e) {
00265                 // this exception is thrown by JProp.getInstance(resourceName)
00266                 // its not possible to receive it here because if the MBean registered itself, this call was already exceuted succesfully
00267                 logger.log(BasicLevel.ERROR, "Catched Exception when calling JProp.getInstance(" + resourceName + "): " + e);
00268                 throw new ReconfigException("Catched Exception when calling JProp.getInstance(" + resourceName + "): " + e.toString());
00269             }
00270         }
00271         if (reconfig != null) {
00272             try {
00273                 jmxServer.addNotificationListener(notificationSender, reconfigManagerObectName, null, null);
00274             } catch (JMException me) {
00275                 logger.log(BasicLevel.ERROR, "ReconfigManager can't listen to Notifications because of exception: " + me.toString());
00276                 throw new ReconfigException("ReconfigManager can't listen to Notifications because of exception: " + me.toString());
00277             }
00278             reconfigurators.put(senderName, reconfig);
00279             logger.log(BasicLevel.DEBUG, "Received Registration Notification from " + notificationSender.toString());
00280         }
00281     }
00282 
00289     private void handleReconfig(String name, long sequence, ReconfiguredProp prop) throws ReconfigException {
00290         logger.log(BasicLevel.DEBUG, "Received 'jonas.management.reconfiguration' notification concerning service or ressource: " +  name);
00291         Reconfigurator reconfigurator = (ReconfiguratorProp) reconfigurators.get(name);
00292         if (reconfigurator == null) {
00293             throw new ReconfigException("Can't find Reconfigurator associated to service or resource " + name);
00294         } else {
00295            if (prop.getPropValue() != null) {
00296                 logger.log(BasicLevel.DEBUG, "Try to reconfigure property : " + prop.getPropName() + " using value value : " + prop.getPropValue());
00297                 if (prop.replaceProp()) {
00298                     ((ReconfiguratorProp) reconfigurator).updateConfig(prop.getPropName(), prop.getPropValue(), sequence);
00299                 } else {
00300                     if (prop.addProp()) {
00301                         logger.log(BasicLevel.DEBUG, "This value has to be added to the values sequence");
00302                     } else {
00303                         logger.log(BasicLevel.DEBUG, "This value has to be removed from the values sequence");
00304                     }
00305                     ((ReconfiguratorProp) reconfigurator).updateConfig(prop.getPropName(), prop.getPropValue(), prop.addProp(), sequence);
00306                 }
00307             } else {
00308                 logger.log(BasicLevel.DEBUG, "Reconfiguration made on a group of properties");
00309                 ((ReconfiguratorProp) reconfigurator).updateConfig(prop.getProps(), sequence);
00310             }
00311         }
00312     }
00313 
00320     private void handleReconfig(String name, long sequence, ReconfiguredXml reconfiguredXml) throws ReconfigException {
00321         logger.log(BasicLevel.DEBUG, "Received 'jonas.management.reconfiguration' notification concerning service or ressource: " +  name);
00322         Reconfigurator reconfigurator = (ReconfiguratorXml) reconfigurators.get(name);
00323         if (reconfigurator == null) {
00324             throw new ReconfigException("Can't find Reconfigurator associated to service or resource " + name);
00325         } else {
00326                 ((ReconfiguratorXml) reconfigurator).updateConfig(reconfiguredXml.getXml(), sequence);
00327         }
00328     }
00329 
00330 
00336     private void handleSave(String name, long sequence) throws ReconfigException {
00337         logger.log(BasicLevel.DEBUG, "Received 'jonas.management.reconfiguration.save' notification concerning service or ressource: " + name);
00338         Reconfigurator reconfigurator = (Reconfigurator) reconfigurators.get(name);
00339         if (reconfigurator == null) {
00340             throw new ReconfigException("Can't find Reconfigurator associated to service or resource " + name);
00341         } else {
00342             reconfigurator.saveConfig(sequence);
00343         }
00344     }
00345 }

Generated on Tue Feb 15 15:05:18 2005 for JOnAS by  doxygen 1.3.9.1