1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid;
12
13 import java.util.Hashtable;
14
15 import javax.naming.Context;
16 import javax.naming.InitialContext;
17 import javax.naming.NamingException;
18
19 import org.apache.commons.logging.LogFactory;
20 import org.jconfig.Configuration;
21 import org.jconfig.ConfigurationManager;
22 import org.jconfig.ConfigurationManagerException;
23 import org.jconfig.handler.ConfigurationHandler;
24 import org.jconfig.handler.InputStreamHandler;
25 import org.jconfig.handler.URLHandler;
26 import org.jconfig.handler.XMLFileHandler;
27
28 import org.astrogrid.i18n.AstroGridMessage;
29
30 /***
31 * A wrapper around jconfig to provide access to configuration files.
32 * Subclass this for each component and implement the methods giving the name of the config file.
33 * The class first searches JNDI for the location of the file, if that files it looks for config file
34 * on the classpath.
35 * @author unknown
36 * @see http://www.jconfig.org
37 * @TODO factor out the logging and replace with commons logging http://jakarta.apache.org/commons/logging/api/index.html
38 */
39 public abstract class Configurator {
40 /*** error message */
41 private static final String ASTROGRIDERROR_COULD_NOT_READ_CONFIGFILE =
42 "AG{0}Z00001:{1}: Could not read my configuration file {2}. Missing file or malformed XML.",
43 ASTROGRIDERROR_COMPONENT_NOT_INITIALIZED =
44 "AG{0}Z00002:{1}: Not initialized. Perhaps my configuration file is missing or contains malformed XML.";
45 /*** keys for config file */
46 public static final String GENERAL_CATEGORY = "GENERAL",
47 GENERAL_VERSION_NUMBER = "VERSION";
48
49 /*** key to indicate template file should be loaded */
50 private static final String TEMPLATE = "TEMPLATE.";
51
52 /*** config files that have already been loaded*/
53 private static Hashtable loadedConfigurations = new Hashtable();
54 /*** ctor */
55 protected Configurator() {
56 this.init();
57 }
58 /***
59 * Initialisation of configurator
60 *
61 */
62 private void init() {
63 Log.trace("Configurator.init(): entry");
64
65 try {
66
67
68 if (Configurator
69 .getConfig(getSubsystemAcronym(), getConfigFileName(), getJNDIName())
70 == null) {
71
72
73 AstroGridMessage message =
74 new AstroGridMessage(
75 ASTROGRIDERROR_COULD_NOT_READ_CONFIGFILE,
76 getSubsystemAcronym(),
77 Configurator.getClassName(Configurator.class),
78 getConfigFileName());
79 Log.logError(message.toString());
80 return;
81
82 }
83
84 try {
85
86
87 AstroGridMessage.loadMessages(this.getSubsystemAcronym());
88 } catch (AstroGridException agex) {
89 Log.logError(agex.getAstroGridMessage().toString());
90 }
91
92 } finally {
93 Log.trace("Configurator.init(): exit");
94 }
95
96 }
97
98
99 /***
100 * Verify that the configuration file has been located and loaded
101 * @throws AstroGridException if not
102 */
103 public final void checkPropertiesLoaded() throws AstroGridException {
104 Log.trace("checkPropertiesLoaded() entry");
105
106 String check = "NOT LOADED";
107 Configuration config =
108 getConfig(
109 this.getSubsystemAcronym(),
110 this.getConfigFileName(),
111 this.getJNDIName());
112
113 try {
114 if (config == null
115 || config.getProperty(
116 GENERAL_VERSION_NUMBER,
117 check,
118 GENERAL_CATEGORY).equals(
119 check)) {
120
121 AstroGridMessage message =
122 new AstroGridMessage(
123 ASTROGRIDERROR_COMPONENT_NOT_INITIALIZED,
124 this.getSubsystemAcronym(),
125 Configurator.getClassName(Configurator.class));
126 Log.logError(message.toString());
127 throw new AstroGridException(message);
128 }
129 } finally {
130 Log.trace("checkPropertiesLoaded() exit");
131 }
132
133 }
134
135 /***
136 *
137 * Static getter for properties from the component's configuration.
138 * <p>
139 *
140 * @param subsystemAcronym TLA used to identify component
141 * @param key - the property key within category
142 * @param category - the category within the configuration
143 * @return the String value of the property, or the empty string if null
144 *
145 * @see org.jconfig.jConfig
146 **/
147 public static String getProperty(
148 final String subsystemAcronym,
149 final String key,
150 final String category) {
151 Log.trace("getProperty() entry");
152
153 String targetProperty = null;
154
155 try {
156
157 Configuration config =
158 ConfigurationManager.getConfiguration(subsystemAcronym);
159
160 targetProperty = config.getProperty(key
161 , ""
162 , category)
163 .trim();
164
165 if (key.startsWith(TEMPLATE)) {
166 targetProperty =
167 TemplateManager.getInstance().getTemplate(
168 subsystemAcronym,
169 targetProperty);
170 }
171
172 } finally {
173 Log.trace("getProperty() exit");
174 }
175
176 return targetProperty;
177
178 }
179
180 /***
181 * Set a property
182 * @param subsystemAcronym e.g. JES
183 * @param key key
184 * @param category category
185 * @param value value
186 */
187 public static void setProperty(
188 final String subsystemAcronym,
189 final String key,
190 final String category,
191 final String value) {
192
193 Log.trace("setProperty() entry");
194 try {
195
196 Configuration config =
197 ConfigurationManager.getConfiguration(subsystemAcronym);
198
199 config.setProperty(key, value, category);
200
201 if (key.startsWith(TEMPLATE)) {
202
203 throw new UnsupportedOperationException("This method isn't supported for TEMPLATEs");
204 }
205
206 } finally {
207 Log.trace("setProperty() exit");
208 }
209 }
210
211 /***
212 * Save the configuration to a file
213 * @param subsystemAcronym e.g.JES
214 * @param configFileName where do you want it?
215 * @throws AstroGridException probably an IOException
216 */
217 public static void save(
218 final String subsystemAcronym,
219 final String configFileName)
220 throws AstroGridException {
221
222 Log.trace("save() entry");
223
224 try {
225
226 Configuration config =
227 ConfigurationManager.getConfiguration(subsystemAcronym);
228 ConfigurationHandler handler = new XMLFileHandler(configFileName);
229 ConfigurationManager.getInstance().save(handler, config);
230
231 } catch (ConfigurationManagerException e) {
232 Log.logError("Error saving configuration file ", e);
233 throw new AstroGridException(e);
234 } finally {
235 Log.trace("save() exit");
236 }
237 }
238
239 /***
240 * Save the configuration to a file
241 * @throws AstroGridException probably an IOException
242 */
243 public final void save() throws AstroGridException {
244 assert getSubsystemAcronym() != null;
245 assert getConfigFileName() != null;
246 this.save(getConfigFileName());
247 }
248
249 /***
250 * Save the configuration to a given file
251 * @param fileName Name of file
252 * @throws AstroGridException probably an IOException
253 */
254 public final void save(final String fileName) throws AstroGridException {
255 assert getSubsystemAcronym() != null;
256 Configurator.save(getSubsystemAcronym(), fileName);
257 }
258
259 /***
260 * Name of xml configuration file - implemented by subclass
261 * @return see above
262 */
263 protected abstract String getConfigFileName();
264 /***
265 * TLA for specific component - implemented by subclass
266 * @return see above
267 */
268 protected abstract String getSubsystemAcronym();
269 /***
270 * Returns the JNDI name of the URL for locating the config file.
271 * e.g. if you place
272 * <verbatim>
273 * <Environment description="URL giving location of the properties file to use for configuration"
274 * name="jesConfigFileURL" override="false" type="java.lang.String" value="http://localhost:8080/ASTROGRID_jesconfig.xml"/>
275 * </verbatim>
276 * in Tomcat's server.xml file (under a <context> element), then the name you return here would be
277 * <verbatim>
278 * java:comp/env/jesConfigFileURL
279 * </verbatim>
280 * @return To be implemented by subclasses. This just returns null.
281 */
282 protected abstract String getJNDIName();
283
284 /***
285 * Loads the configuration file. Firstly an attempt is made to find a URL
286 * in the naming service. If the subclass has not set a key, or that key
287 * is not set in the NamingService then an attempt is made to load the file
288 * from the classpath. Otherwise the file is loaded from the URL.
289 * @param subsystemAcronym the TLA for the component - supplied by subclass
290 * @param configFileName the name of the config file on the classpath - supplied by subclass
291 * @param jndiName name to lookfor in JNDI, may be null
292 * @return The configuration
293 */
294 private static Configuration getConfig(
295 final String subsystemAcronym,
296 final String configFileName,
297 final String jndiName) {
298 Log.trace("Configurator.getConfig(): entry");
299
300 assert subsystemAcronym != null;
301 assert !(
302 configFileName == null
303 && jndiName == null) : "Either configFileName or jndiName must be nonnull";
304
305 Configuration configuration = null;
306
307 try {
308
309 if (!loadedConfigurations.containsKey(subsystemAcronym)) {
310 ConfigurationHandler handler = null;
311 if (jndiName != null) {
312
313 try {
314 Context ic = new InitialContext();
315 String url = (String) ic.lookup(jndiName);
316 URLHandler urlHandler = new URLHandler();
317 assert url != null;
318 urlHandler.setURL(url);
319 handler = urlHandler;
320 } catch (NamingException ne) {
321 Log.logDebug(
322 "No InitialContext in Configurator:getConfig "
323 + "- unable to get log file URL from JNDI - switch to loading from classpath",
324 ne);
325 }
326 }
327
328 if (handler == null) {
329 handler = new InputStreamHandler(configFileName);
330 }
331
332 ConfigurationManager.getInstance().load(handler, subsystemAcronym);
333 loadedConfigurations.put(subsystemAcronym, configFileName);
334 }
335
336 configuration = ConfigurationManager.getConfiguration(subsystemAcronym);
337 } catch (Exception cme) {
338 Log.logError(
339 "Could not get config subsystem '"
340 + subsystemAcronym
341 + "', filename '"
342 + configFileName
343 + "'",
344 cme);
345 } finally {
346 Log.trace("Configurator.getConfig(): exit");
347 }
348 return configuration;
349
350 }
351
352 /***
353 * Utility method to get the name of a class
354 * @param cls the class in question
355 * @return its name of course, minus the .class bit
356 */
357 public static String getClassName(final java.lang.Class cls) {
358
359 String componentName = cls.getName();
360 int iLastPoint = componentName.lastIndexOf('.');
361 return componentName.substring(iLastPoint + 1);
362
363 }
364
365 }
366
367 /***
368 * Delegates to commons logging
369 * This class used to use org.astrogrid.log.Log
370 *
371 * @author jdt
372 */
373 final class Log {
374 /***
375 * Do nothing ctor
376 *
377 */
378 private Log() {
379 }
380 /***
381 * Logger for this class
382 */
383 private static org.apache.commons.logging.Log log =
384 LogFactory.getLog(Configurator.class);
385 /***
386 * delegates to commons logging
387 * @param string message
388 */
389 public static void trace(final String string) {
390 log.trace(string);
391 }
392
393 /***
394 * * delegates to commons logging
395 * @param string message
396 * @param cme exception
397 */
398 public static void logError(final String string, final Throwable cme) {
399 log.error(string, cme);
400 }
401
402 /***
403 * * delegates to commons logging
404 * @param string message
405 * @param ne exception
406 */
407 public static void logDebug(final String string, final Throwable ne) {
408 log.debug(string, ne);
409
410 }
411
412 /***
413 * * delegates to commons logging
414 * @param string message
415 */
416 public static void logError(final String string) {
417 log.error(string);
418 }
419
420 }