1 /*
2 * Copyright (c) 1998-2002 The Jgroup Team.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19 package jgroup.core;
20
21 import java.io.File;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.List;
25
26 import jgroup.core.registry.RegistryFactory;
27 import jgroup.core.registry.RegistryLocator;
28 import jgroup.relacs.config.BootstrapRegistryConfig;
29 import jgroup.relacs.config.ConfigParser;
30 import jgroup.relacs.config.DistributedSystemConfig;
31 import jgroup.util.Network;
32 import jgroup.util.Util;
33
34 import org.apache.log4j.LogManager;
35 import org.apache.log4j.joran.JoranConfigurator;
36
37 /**
38 * The configuration manager class is used initialize the required
39 * Jgroup system configuration data, including logging configuration.
40 * It will read the logging configuration and the Jgroup system
41 * configuration, by parsing the XML files supplied to the JVM using
42 * the following system properties: <p>
43 *
44 * <code>jgroup.system.config</code>: XML-based configuration file for
45 * specifying the required system configurations for Jgroup/ARM.
46 * <p>
47 *
48 * <code>jgroup.system.services</code>: XML-based configuration file for
49 * specifying the services required for Jgroup/ARM.
50 * <p>
51 *
52 * <code>jgroup.system.applications</code>: XML-based configuration file for
53 * specifying the applications used in a Jgroup/ARM system.
54 * <p>
55 *
56 * <code>jgroup.log.config</code>: XML-based configuration file for
57 * log4j, allows the user to limit the amount of debug information
58 * being sent to the console; among numerous other configuration
59 * options available through the log4j toolkit. For details concerning
60 * the format of the configuration file, please refer to the log4j
61 * documentation. The default for this property:
62 * <code>config/log4j.xml</code>
63 * <p>
64 *
65 * In addition, the following logging related system properties may be
66 * specified by the user: <p>
67 *
68 * <code>jgroup.registry.locator</code>: The registry locator class to be used
69 * by Jgroup. The default is <code>jgroup.relacs.registry.RelacsRegistryLocator</code>
70 * <p>
71 *
72 * <code>jgroup.log.app</code>: The application name that will be appended
73 * to the log filename. Note that, when using the ARM framework (the
74 * <code>ExecDaemon</code>) to create replicas, the log.app name for the
75 * replica will be given the name of the class (exclusive the package name).
76 * <p>
77 *
78 * <code>jgroup.log.dir</code>: The directory into which log files will be
79 * written. If not specified, the default is used (<code>./log</code>)
80 * <p>
81 *
82 * <code>jgroup.log.msgcontent</code>: True/False. Used to turn on/off
83 * the logging of message content at both the mss and daemon level.
84 * <p>
85 *
86 * The following system properties are initialized at runtime, allowing the
87 * log4j toolkit to use these properties in its XML based log file for
88 * constructing unique files. Passing these properties to the Java runtime
89 * will have no effect as they will be overwritten. <p>
90 *
91 * <code>jgroup.log.machine</code>: The local host of this replica.
92 * <p>
93 *
94 * <code>jgroup.log.time</code>: The time when this replica was initialized.
95 * <p>
96 *
97 * <code>jgroup.log.date</code>: The date when this replica was initialized.
98 * <p>
99 *
100 * @author Hein Meling
101 * @since Jgroup 1.2
102 */
103 public final class ConfigManager
104 {
105
106 public static final String DEFAULT_REGISTRY_LOCATOR = "jgroup.relacs.registry.RelacsRegistryLocator";
107 public static final String DEFAULT_REPLICATION_MANAGER = "jgroup.arm.ReplicaManagerImpl";
108
109 private static final String DEFAULT_SYSTEM_CONFIG = "file:target/classes/siteconfig/lx-config.xml";
110 private static final String DEFAULT_SYSTEM_SERVICES = "file:target/classes/config/services.xml";
111 private static final String DEFAULT_SYSTEM_APPLICATIONS = "file:target/classes/config/applications.xml";
112 private static final String DEFAULT_LOGGING_CONFIG = "file:target/classes/logging/log4j.xml";
113 private static final String DEFAULT_LOG_DIR = File.separator + "tmp" + File.separator + "jgroup-logs";
114
115
116 /**
117 * Indicates if message content should be logged. To change this
118 * use the system property: <code>jgroup.log.msgcontent</code>.
119 */
120 public static boolean logMsgContent = false;
121
122 /**
123 * Variable used to avoid duplicate reading/parsing of the
124 * configuration files. That is to make the init methods idempotent.
125 */
126 private static boolean initialized = false;
127
128 /**
129 * Variable used to avoid duplicate reading/initialization of the
130 * logging configuration. That is to make the configureLogging method
131 * idempotent.
132 */
133 private static boolean logInitialized = false;
134
135 /** The port used by the bootstrap registry */
136 private static int bootstrapPort;
137
138 /** The distributed system configuration object */
139 private static DistributedSystemConfig dsc;
140
141
142 ////////////////////////////////////////////////////////////////////////////////////////////
143 // Public static methods
144 ////////////////////////////////////////////////////////////////////////////////////////////
145
146 /**
147 * Invoked to initialize various system configuration variables
148 * required by Jgroup/ARM. This includes reading and parsing the
149 * logging configuration and the distributed system configuration.
150 *
151 * The method is idempotent (it can be invoked many times without
152 * changing its behavior), meaning that no configuration files will
153 * be read and parsed several times.
154 *
155 * @exception ConfigurationException
156 * Raised if there was an error parsing the configuration files,
157 * or the system properties required to specify the configuration
158 * file names were unset.
159 */
160 public static void init()
161 throws ConfigurationException
162 {
163 configureLogging();
164 String urlConfig = System.getProperty("jgroup.system.config", DEFAULT_SYSTEM_CONFIG);
165 init(urlConfig);
166 }
167
168
169 /**
170 * Helper method to parse a specified configuration file instead of the
171 * system configured default. This is useful for the Java based experiment
172 * framework.
173 *
174 * @param urlConfig
175 * @throws ConfigurationException
176 */
177 public static void init(String urlConfig)
178 throws ConfigurationException
179 {
180 if (initialized)
181 return;
182 initialized = true;
183
184 /*
185 * Parse the given URL (should be either a distributed system config
186 * or an experiment config; the latter will invoke the parser again
187 * to obtain the distributed system config.)
188 */
189 ConfigParser.parse(urlConfig);
190 /*
191 * Parse the service and application configuration. Multiple services and applications
192 * configuration files can be specified and separated by comma.
193 */
194 urlConfig = System.getProperty("jgroup.system.services", DEFAULT_SYSTEM_SERVICES);
195 String urlConfigs[] = urlConfig.split(",");
196 for (int i=0; i < urlConfigs.length; i++) {
197 ConfigParser.parse(urlConfigs[i]);
198 }
199 urlConfig = System.getProperty("jgroup.system.applications", DEFAULT_SYSTEM_APPLICATIONS);
200 urlConfigs = urlConfig.split(",");
201 for (int i=0; i < urlConfigs.length; i++) {
202 ConfigParser.parse(urlConfigs[i]);
203 }
204 setRegistryLocator();
205 BootstrapRegistryConfig brc =
206 (BootstrapRegistryConfig) ConfigParser.getConfig(BootstrapRegistryConfig.class);
207 bootstrapPort = brc.getPort();
208 dsc = (DistributedSystemConfig) ConfigParser.getConfig(DistributedSystemConfig.class);
209 }
210
211
212 /**
213 * Method to set up log directory, and initialize the Log4j configuration.
214 * This can be used externally when custom configuration is required, such
215 * as the experiment framework.
216 *
217 * @throws ConfigurationException
218 * Thrown if the specified log directory could not be created, or
219 * if the log4j configuration URL was malformed.
220 */
221 public static void configureLogging()
222 throws ConfigurationException
223 {
224 if (logInitialized)
225 return;
226 logInitialized = true;
227
228 /*
229 * Get the directory in which log files should be stored;
230 * if the directory does not exist, it is created.
231 */
232 String logDir = System.getProperty("jgroup.log.dir", DEFAULT_LOG_DIR);
233 File dir = new File(logDir);
234 if (!dir.exists()) {
235 /* Directory does not exist; create it. */
236 if (!dir.mkdir())
237 throw new ConfigurationException("Could not create the specified log directory: " + logDir);
238 }
239 /*
240 * Check if the application name is defined; if not 'noapp' is
241 * set to this property so that log4j use that when constructing
242 * the logging filenames.
243 */
244 String logApp = System.getProperty("jgroup.log.app");
245 if (logApp == null || logApp.length() == 0) {
246 System.setProperty("jgroup.log.app", "noapp");
247 }
248 /*
249 * Obtain the property used to set if the message content should be logged.
250 */
251 logMsgContent = Boolean.getBoolean("jgroup.log.msgcontent");
252 /*
253 * Set the values for the local machine, date and time when the Jgroup
254 * related application was initialized. These values can be used in the
255 * log4j.xml file to avoid overwriting the log files of concurrently
256 * running applications on the same host. The can be used along with the
257 * app property defined above.
258 */
259 System.setProperty("jgroup.log.machine", Network.getLocalMachineName());
260 System.setProperty("jgroup.log.time", Util.getTimeString());
261 System.setProperty("jgroup.log.date", Util.getDateString());
262 /*
263 * Initialize and parse the log4j configuration file.
264 */
265 String logConfig = System.getProperty("jgroup.log.config", DEFAULT_LOGGING_CONFIG);
266 // JoranConfigurator requires log4j version 1.3
267 JoranConfigurator jc = new JoranConfigurator();
268 try {
269 jc.doConfigure(new URL(logConfig), LogManager.getLoggerRepository());
270 } catch (MalformedURLException e) {
271 throw new ConfigurationException("Bad URL provided for log4j configuration: " + logConfig, e);
272 }
273 List errorList = jc.getErrorList();
274 for (int i = 0; i < errorList.size(); i++) {
275 System.out.println(errorList.get(i));
276 }
277 }
278
279 /**
280 * Set the registry to use based on a system property,
281 * jgroup.registry. Default is DependableRegistry.
282 *
283 * @exception ConfigurationException
284 * Raised if unable to create the registry.
285 */
286 private static void setRegistryLocator()
287 throws ConfigurationException
288 {
289 String locatorName = System.getProperty("jgroup.registry", DEFAULT_REGISTRY_LOCATOR);
290 try {
291 Class clazz = Class.forName(locatorName);
292 RegistryLocator locator = (RegistryLocator) clazz.newInstance();
293 RegistryFactory.setLocator(locator);
294 } catch (ClassNotFoundException e) {
295 throw new ConfigurationException("Registry locator class not found: " + locatorName);
296 } catch (InstantiationException e) {
297 throw new ConfigurationException("Could not instanstiate: " + locatorName);
298 } catch (IllegalAccessException e) {
299 throw new ConfigurationException("Illegal access to : " + locatorName);
300 }
301 }
302
303
304 /**
305 * Retrieve an instance of the given configuration class, that is
306 * containing the configuration information. For example, the
307 * configuration data object associated with the XML tag
308 * <code>Transport</code>, can be retreived using the class literal
309 * <code>TransportConfig.class</code>.
310 *
311 * @param cl
312 * The class literal of the configuration object to retreive.
313 * @return
314 * An instance of the configuration object retreived.
315 *
316 * @exception NullPointerException
317 * If there is no such configuration object in the internal
318 * configuration map. This may occur for two reasons; (i) there
319 * is no such configuration tag specified in the configuration file,
320 * or (ii) the specified class literal is a non-existant class.
321 * @exception IllegalStateException
322 * If the init method was not invoked prior to invoking this method.
323 */
324 public static Object getConfig(Class cl)
325 {
326 return ConfigParser.getConfig(cl);
327 }
328
329
330 /**
331 * Returns the <code>DistributedSystemConfig</code> object.
332 */
333 public static DistributedSystemConfig getDistributedSystem()
334 {
335 return dsc;
336 }
337
338
339 /**
340 * Returns the port for the bootstrap registry.
341 */
342 public static int getBootstrapPort()
343 {
344 return bootstrapPort;
345 }
346
347 } // END ConfigManager