1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package jgroup.relacs.config;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Set;
27
28 import javax.xml.parsers.DocumentBuilder;
29 import javax.xml.parsers.DocumentBuilderFactory;
30
31 import jgroup.core.ConfigurationException;
32 import jgroup.util.Abort;
33
34 import org.apache.log4j.Logger;
35 import org.w3c.dom.Document;
36 import org.w3c.dom.Element;
37 import org.w3c.dom.Node;
38 import org.w3c.dom.NodeList;
39 import org.xml.sax.ErrorHandler;
40 import org.xml.sax.SAXException;
41 import org.xml.sax.SAXParseException;
42
43
44
45
46
47
48
49 public final class ConfigParser
50 {
51
52
53
54
55
56
57 private static final Logger log = Logger.getLogger(ConfigParser.class);
58
59
60
61
62
63
64 private static final String CONFIG_ROOT_TAG_NAME = "Configuration";
65 private static final String SERVICES_ROOT_TAG_NAME = "Services";
66 private static final String APPLICATIONS_ROOT_TAG_NAME = "Applications";
67 private static final String CLIENT_CONFIG_ROOT_TAG_NAME = "ClientConfiguration";
68 private static final String EXPERIMENT_ROOT_TAG_NAME = "ExperimentConfiguration";
69 private static final String VERSION_ATTRIB = "version";
70
71
72
73
74
75
76
77
78
79
80
81 private static Map<Class,ConfigurationObject> configMap =
82 new HashMap<Class,ConfigurationObject>();
83
84
85 private static Set<String> parsedFiles = new HashSet<String>();
86
87
88
89
90
91
92
93
94
95 public static void parse(String urlConfig)
96 throws ConfigurationException
97 {
98 parse(urlConfig, false);
99 }
100
101
102
103
104
105
106
107
108
109
110
111 public static void parse(String urlConfig, boolean parseAgain)
112 throws ConfigurationException
113 {
114
115 if (parsedFiles.contains(urlConfig) && !parseAgain)
116 return;
117 parsedFiles.add(urlConfig);
118
119 Document doc = null;
120 try {
121 DocumentBuilderFactory docBF = DocumentBuilderFactory.newInstance();
122 boolean validate = false;
123 String validateStr = System.getProperty("jgroup.config.validate");
124 if (validateStr != null && validateStr.equals("true")) {
125 validate = true;
126 }
127 docBF.setValidating(validate);
128 DocumentBuilder db = docBF.newDocumentBuilder();
129 db.setErrorHandler(new ParsingErrorHandler());
130 doc = db.parse(urlConfig);
131 } catch (Exception exception) {
132 log.warn("Parser exception while parsing configuration file", exception);
133 throw new ConfigurationException("Unable to parse configuration file: " + urlConfig);
134 }
135
136
137 Element elm = doc.getDocumentElement();
138 if (!checkVersion(elm, CONFIG_ROOT_TAG_NAME, "1.1") &&
139 !checkVersion(elm, CLIENT_CONFIG_ROOT_TAG_NAME, "1.0") &&
140 !checkVersion(elm, SERVICES_ROOT_TAG_NAME, "1.0") &&
141 !checkVersion(elm, APPLICATIONS_ROOT_TAG_NAME, "1.1") &&
142 !checkVersion(elm, EXPERIMENT_ROOT_TAG_NAME, "0.1" ))
143 throw new ConfigurationException("Unexpected root tag in " + urlConfig);
144
145
146 NodeList nl = elm.getChildNodes();
147 for (int i = 1; i <= nl.getLength(); i++) {
148 Node node = nl.item(i);
149 if (node != null && !node.getNodeName().startsWith("#")) {
150
151
152 ConfigurationObject obj = parseTag((Element) node);
153
154
155 configMap.put(obj.getClass(), obj);
156 }
157 }
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 public static Object getConfig(Class cl)
182 {
183 if (configMap.isEmpty())
184 throw new IllegalStateException("getConfig() invoked before parsing the config files");
185 Object obj = configMap.get(cl);
186 if (obj == null)
187 throw new NullPointerException("No configuration data available for " + cl);
188 return obj;
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 private static ConfigurationObject parseTag(Element elm)
210 throws ConfigurationException
211 {
212 try {
213 Class cl = Class.forName("jgroup.relacs.config." + elm.getTagName() + "Config");
214 ConfigurationObject config = (ConfigurationObject) cl.newInstance();
215 config.parse(elm);
216 return config;
217 } catch (ClassCastException e) {
218 e.printStackTrace();
219 throw new ConfigurationException("Unexpected tag " + elm.getTagName());
220 } catch (ConfigurationException e) {
221 throw e;
222 } catch (Exception e) {
223 e.printStackTrace();
224 throw new ConfigurationException("Error parsing configuration file: " + e.getMessage());
225 }
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 static Element[] parseList(Element elm)
242 {
243 NodeList tagList = elm.getChildNodes();
244 ArrayList<Node> elmList = new ArrayList<Node>(tagList.getLength());
245
246
247 for (int i = 1; i <= tagList.getLength(); i++) {
248 Node node = tagList.item(i);
249 if (node != null && !node.getNodeName().startsWith("#"))
250 elmList.add(node);
251 }
252 elmList.trimToSize();
253 return (Element[]) elmList.toArray(new Element[elmList.size()]);
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 static boolean checkVersion(Element elm, String rootTagName, String versionValue)
273 throws ConfigurationException
274 {
275 String cfgRoot = elm.getTagName();
276 String cfgVersion = elm.getAttribute(VERSION_ATTRIB);
277 if (cfgRoot.equalsIgnoreCase(rootTagName))
278 if (cfgVersion.equals(versionValue))
279 return true;
280 else
281 throw new ConfigurationException("Wrong version (" + cfgVersion + ") for "
282 + rootTagName + " configuration file. Expected version: " + versionValue);
283 else
284 return false;
285 }
286
287
288
289
290
291
292
293
294
295
296
297 static boolean checkTag(Element elm, String tag)
298 {
299 return elm.getTagName().equalsIgnoreCase(tag);
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313 static String getAttrib(Element elm, String attrib, boolean required)
314 throws ConfigurationException
315 {
316
317 String value = elm.getAttribute(attrib);
318
319
320
321
322
323 if (required && value.length() == 0)
324 throw new ConfigurationException("Expected required attribute: " + attrib);
325
326 return value;
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343 static int getIntAttrib(Element elm, String attrib, boolean required)
344 throws ConfigurationException
345 {
346 String value = getAttrib(elm, attrib, required);
347 if ("".equals(value)) {
348 throw new ConfigurationException("Attribute " + attrib + " is not defined");
349 } else if ("ALL".equalsIgnoreCase(value)) {
350 return -1;
351 }
352 try {
353 return Integer.parseInt(value);
354 } catch(NumberFormatException e) {
355 throw new ConfigurationException("Illegal value for attribute " +
356 attrib+ ": " + elm.getAttribute(attrib));
357 }
358 }
359
360
361 public static boolean getBooleanAttrib(Element elm, String attrib, boolean required)
362 throws ConfigurationException
363 {
364 String strval = getAttrib(elm, attrib, required);
365 if (strval == null || strval.length() == 0)
366 return false;
367 return Boolean.valueOf(strval).booleanValue();
368 }
369
370
371
372
373
374
375
376
377
378
379
380
381
382 static class ParsingErrorHandler
383 implements ErrorHandler
384 {
385
386 public void warning(SAXParseException ex)
387 {
388 System.err.println("Warning: " + ex.getMessage());
389 }
390
391 public void error(SAXParseException ex)
392 {
393 dumpContent();
394 Abort.exit("Error: " + ex.getMessage(), 1);
395 }
396
397 public void fatalError(SAXParseException ex)
398 throws SAXException
399 {
400 dumpContent();
401 Abort.exit("Fatal error: " + ex.getMessage(), 2);
402 }
403
404 private void dumpContent()
405 {
406 System.err.println("Parsed files:");
407 for (Iterator iter = parsedFiles.iterator(); iter.hasNext(); )
408 System.err.println(" - " + iter.next());
409 System.err.println("Content of configuration map:");
410 for (Iterator iter = configMap.values().iterator(); iter.hasNext(); )
411 System.err.println(" - " + iter.next());
412 }
413
414 }
415
416 }