1 package net.logAnalyzer.config;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.Hashtable;
6
7 import javax.xml.parsers.ParserConfigurationException;
8 import javax.xml.parsers.SAXParser;
9 import javax.xml.parsers.SAXParserFactory;
10
11 import net.logAnalyzer.analysis.AnalyzerDefinition;
12 import net.logAnalyzer.converters.ConverterDefinition;
13 import net.logAnalyzer.converters.LiteralConverter;
14 import net.logAnalyzer.gui.ViewDefinition;
15 import net.logAnalyzer.patternParser.PatternDefinition;
16 import net.logAnalyzer.reports.RendererDefinition;
17
18 import org.xml.sax.Attributes;
19 import org.xml.sax.SAXException;
20 import org.xml.sax.helpers.DefaultHandler;
21
22 /***
23 * This class uses an xml File to load the configuration. The "logAnalyzer" file
24 * must be well-formed as specified in "logAnalyzer.dtd".
25 *
26 * @author Karim REFEYTON
27 * @version 0.1
28 */
29 class XMLConfigurationLoader extends DefaultHandler {
30 /***
31 * Default configuration file.
32 */
33 private static String xmlFilename = "logAnalyzer.xml";
34
35 private Hashtable convertersDef;
36
37 private Hashtable analyzersDef;
38
39 private Hashtable patternsDef;
40
41 private Hashtable renderersDef;
42
43 private Hashtable viewsDef;
44
45 /***
46 * Loads the xml file "LAAnalyzer.xml".
47 *
48 * @return Configuration.
49 */
50 public ConfigurationManager loadConfiguration() {
51 File xmlFile = new File(xmlFilename);
52 if (!xmlFile.exists()) {
53 System.err.println("File not found : " + xmlFile.getAbsolutePath());
54 System.exit(1);
55 }
56 convertersDef = new Hashtable();
57 analyzersDef = new Hashtable();
58 patternsDef = new Hashtable();
59 renderersDef = new Hashtable();
60 viewsDef = new Hashtable();
61
62 SAXParserFactory factory = SAXParserFactory.newInstance();
63 try {
64
65 SAXParser saxParser = factory.newSAXParser();
66 saxParser.parse(xmlFile, this);
67 } catch (ParserConfigurationException pce) {
68 pce.printStackTrace();
69 System.exit(1);
70 } catch (SAXException spe) {
71 spe.printStackTrace();
72 System.exit(1);
73 } catch (IOException ioe) {
74 ioe.printStackTrace();
75 System.exit(1);
76 }
77 return new ConfigurationManager(patternsDef, convertersDef,
78 analyzersDef, renderersDef, viewsDef);
79 }
80
81 private static final int STATE_START = 0;
82
83 private static final int STATE_CONFIG = 1;
84
85 private static final int STATE_CONVERTERS = 10;
86
87 private static final int STATE_LITERAL = 100;
88
89 private static final int STATE_CONVERTER = 101;
90
91 private static final int STATE_GROUP = 102;
92
93 private static final int STATE_GROUPED_CONVERTER = 103;
94
95 private static final int STATE_ANALYZERS = 11;
96
97 private static final int STATE_ANALYZER = 110;
98
99 private static final int STATE_PATTERNS = 12;
100
101 private static final int STATE_PATTERN = 120;
102
103 private static final int STATE_RENDERERS = 13;
104
105 private static final int STATE_RENDERER = 130;
106
107 private static final int STATE_VIEWS = 14;
108
109 private static final int STATE_VIEW = 140;
110
111 private static final int STATE_VIEW_ATTRIBUTE = 1400;
112
113 private static final int STATE_END = 2;
114
115 private int currentState = -1;
116
117 private static final String BADFORMAT_EXCEPTION = "Unexpected content, see LogAnalyzer.dtd";
118
119 /***
120 * Modification to the inherited behavior.
121 *
122 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
123 */
124 public void characters(char[] chars, int start, int length)
125 throws SAXException {
126 switch (currentState) {
127 case STATE_PATTERN:
128 addPatternContent(new String(chars, start, length));
129 break;
130 default:
131 throw new SAXException(BADFORMAT_EXCEPTION);
132 }
133 }
134
135 /***
136 * Modification to the inherited behavior.
137 *
138 * @see org.xml.sax.helpers.DefaultHandler#endDocument()
139 */
140 public void endDocument() throws SAXException {
141 switch (currentState) {
142 case STATE_END:
143 currentState = -1;
144 break;
145 default:
146 throw new SAXException(BADFORMAT_EXCEPTION);
147 }
148 }
149
150 /***
151 * Modification to the inherited behavior.
152 *
153 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
154 * java.lang.String, java.lang.String)
155 */
156 public void endElement(String uri, String localName, String qName)
157 throws SAXException {
158 switch (currentState) {
159 case STATE_CONFIG:
160 if ("config".equals(qName)) {
161 currentState = STATE_END;
162 }
163 break;
164 case STATE_CONVERTERS:
165 if ("converters".equals(qName)) {
166 currentState = STATE_CONFIG;
167 }
168 break;
169 case STATE_LITERAL:
170 if ("literal".equals(qName)) {
171 currentState = STATE_CONVERTERS;
172 }
173 break;
174 case STATE_CONVERTER:
175 if ("converter".equals(qName)) {
176 currentState = STATE_CONVERTERS;
177 }
178 break;
179 case STATE_GROUP:
180 if ("group".equals(qName)) {
181 currentState = STATE_CONVERTERS;
182 currentGroupLetter = null;
183 }
184 break;
185 case STATE_GROUPED_CONVERTER:
186 if ("groupedconverter".equals(qName)) {
187 currentState = STATE_GROUP;
188 }
189 break;
190 case STATE_ANALYZERS:
191 if ("analyzers".equals(qName)) {
192 currentState = STATE_CONFIG;
193 }
194 break;
195 case STATE_ANALYZER:
196 if ("analyzer".equals(qName)) {
197 currentState = STATE_ANALYZERS;
198 }
199 break;
200 case STATE_PATTERNS:
201 if ("patterns".equals(qName)) {
202 currentState = STATE_CONFIG;
203 }
204 break;
205 case STATE_PATTERN:
206 if ("pattern".equals(qName)) {
207 currentState = STATE_PATTERNS;
208 addPattern(patternName, patternContent, patternLabel);
209 }
210 break;
211 case STATE_RENDERERS:
212 if ("renderers".equals(qName)) {
213 currentState = STATE_CONFIG;
214 }
215 break;
216 case STATE_RENDERER:
217 if ("renderer".equals(qName)) {
218 currentState = STATE_RENDERERS;
219 }
220 break;
221 case STATE_VIEWS:
222 if ("views".equals(qName)) {
223 currentState = STATE_CONFIG;
224 }
225 break;
226 case STATE_VIEW:
227 if ("view".equals(qName)) {
228 currentState = STATE_VIEWS;
229 addView(viewName, viewClassname, viewLabel, viewAttributes);
230 }
231 break;
232 case STATE_VIEW_ATTRIBUTE:
233 if ("attribute".equals(qName)) {
234 currentState = STATE_VIEW;
235 }
236 break;
237 default:
238 throw new SAXException(BADFORMAT_EXCEPTION);
239 }
240 }
241
242 /***
243 * Modification to the inherited behavior.
244 *
245 * @see org.xml.sax.helpers.DefaultHandler#startDocument()
246 */
247 public void startDocument() throws SAXException {
248 currentState = STATE_START;
249 }
250
251 /***
252 * Modification to the inherited behavior.
253 *
254 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
255 * java.lang.String, java.lang.String, org.xml.sax.Attributes)
256 */
257 public void startElement(String uri, String localName, String qName,
258 Attributes attributes) throws SAXException {
259 switch (currentState) {
260 case STATE_START:
261 if ("config".equals(qName)) {
262 currentState = STATE_CONFIG;
263 } else {
264 throw new SAXException(BADFORMAT_EXCEPTION);
265 }
266 break;
267 case STATE_CONFIG:
268 if ("converters".equals(qName)) {
269 currentState = STATE_CONVERTERS;
270 } else if ("analyzers".equals(qName)) {
271 currentState = STATE_ANALYZERS;
272 } else if ("patterns".equals(qName)) {
273 currentState = STATE_PATTERNS;
274 } else if ("renderers".equals(qName) && analyzersDef.size() > 0) {
275 currentState = STATE_RENDERERS;
276 } else if ("views".equals(qName) && convertersDef.size() > 0) {
277 currentState = STATE_VIEWS;
278 } else {
279 throw new SAXException(BADFORMAT_EXCEPTION);
280 }
281 break;
282 case STATE_CONVERTERS:
283 if ("converter".equals(qName)) {
284 currentState = STATE_CONVERTER;
285 addConverter(attributes.getValue("letter"), attributes
286 .getValue("classname"), attributes
287 .getValue("hasoption"), attributes
288 .getValue("ismessage"), attributes.getValue("label"));
289 } else if ("literal".equals(qName)) {
290 currentState = STATE_LITERAL;
291 setLiteral(attributes.getValue("classname"));
292 } else if ("group".equals(qName)) {
293 currentState = STATE_GROUP;
294 addGroup(attributes.getValue("letter"));
295 } else {
296 throw new SAXException(BADFORMAT_EXCEPTION);
297 }
298 break;
299 case STATE_GROUP:
300 if ("groupedconverter".equals(qName)) {
301 currentState = STATE_GROUPED_CONVERTER;
302 addGroupedConverter(currentGroupLetter, attributes
303 .getValue("option"), attributes.getValue("classname"),
304 attributes.getValue("label"));
305 } else {
306 throw new SAXException(BADFORMAT_EXCEPTION);
307 }
308 break;
309 case STATE_ANALYZERS:
310 if ("analyzer".equals(qName)) {
311 currentState = STATE_ANALYZER;
312 addAnalyzer(attributes.getValue("name"), attributes
313 .getValue("period"), attributes.getValue("classname"),
314 attributes.getValue("label"));
315 } else {
316 throw new SAXException(BADFORMAT_EXCEPTION);
317 }
318 break;
319 case STATE_PATTERNS:
320 if ("pattern".equals(qName)) {
321 currentState = STATE_PATTERN;
322 preparePattern(attributes.getValue("name"), attributes
323 .getValue("label"));
324 } else {
325 throw new SAXException(BADFORMAT_EXCEPTION);
326 }
327 break;
328 case STATE_RENDERERS:
329 if ("renderer".equals(qName)) {
330 currentState = STATE_RENDERER;
331 addRenderer(attributes.getValue("name"), attributes
332 .getValue("classname"), attributes.getValue("label"));
333 } else {
334 throw new SAXException(BADFORMAT_EXCEPTION);
335 }
336 break;
337 case STATE_VIEWS:
338 if ("view".equals(qName) && convertersDef.size() > 0) {
339 currentState = STATE_VIEW;
340 prepareView(attributes.getValue("name"), attributes
341 .getValue("classname"), attributes.getValue("label"));
342 } else {
343 throw new SAXException(BADFORMAT_EXCEPTION);
344 }
345 break;
346 case STATE_VIEW:
347 if ("attribute".equals(qName)) {
348 currentState = STATE_VIEW_ATTRIBUTE;
349 addViewAttribute(attributes.getValue("name"), attributes
350 .getValue("value"));
351 } else {
352 throw new SAXException(BADFORMAT_EXCEPTION);
353 }
354 break;
355 default:
356 throw new SAXException(BADFORMAT_EXCEPTION);
357 }
358 }
359
360 private void addConverter(String letter, String classname,
361 String hasOption, String isMessage, String label) {
362 if (label == null || label.trim().length() == 0) {
363 label = letter;
364 }
365 if ((letter == null || letter.length() != 1 || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
366 .indexOf(letter.charAt(0)) < 0)
367 || (classname == null || classname.trim().length() == 0)
368 || (hasOption == null || hasOption.trim().length() == 0)) {
369 System.err
370 .print("Bad converter definition for converter [letter='");
371 if (letter != null) {
372 System.err.print(letter);
373 }
374 System.err.println("']'");
375
376 System.exit(1);
377 }
378 try {
379 ConverterDefinition definition = new ConverterDefinition(letter,
380 classname, "true".equalsIgnoreCase(hasOption), "true"
381 .equalsIgnoreCase(isMessage), label);
382 convertersDef.put(definition.getKey(), definition);
383 } catch (ClassNotFoundException nsme) {
384 System.err.println("No such class " + classname
385 + " for converter [letter='" + letter + "']");
386 System.exit(1);
387 }
388 }
389
390 private void setLiteral(String classname) {
391 if (classname == null || classname.trim().length() == 0) {
392 System.err
393 .println("You must declare a <literal classname=...> converter with by default the class ["
394 + LiteralConverter.class.getName() + "].");
395 System.exit(1);
396 }
397 try {
398
399 Class literalClass = ClassLoader.getSystemClassLoader().loadClass(
400 classname);
401 if (LiteralConverter.class.isAssignableFrom(literalClass)) {
402
403 ConverterDefinition definition = new ConverterDefinition(
404 LiteralConverter.LITERAL_NAME, classname, false, false,
405 LiteralConverter.LITERAL_NAME);
406 convertersDef.put(LiteralConverter.LITERAL_NAME, definition);
407 } else {
408 System.err.println("Bad class specified for literal: class ["
409 + classname + "] doesn't extends the class ["
410 + LiteralConverter.class.getName() + "].");
411 System.exit(1);
412 }
413 } catch (ClassNotFoundException nsme) {
414 System.err.println("No such class " + classname
415 + " for literal converter");
416 System.exit(1);
417 }
418 }
419
420 private String currentGroupLetter = null;
421
422 private void addGroup(String letter) {
423 if (letter == null
424 || letter.length() != 1
425 || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
426 .indexOf(letter.charAt(0)) < 0) {
427 System.err
428 .println("Bad group definition : attribute [letter] missing or bad (must be [A-Za-z]).");
429 System.exit(1);
430 }
431 currentGroupLetter = letter;
432 }
433
434 private void addGroupedConverter(String letter, String option,
435 String classname, String label) {
436 if (label == null || label.trim().length() == 0) {
437 label = letter + '{' + option + '}';
438 }
439 if ((classname == null || classname.trim().length() == 0)
440 || (option == null || option.trim().length() == 0)) {
441 System.err
442 .print("Bad converter definition for grouped converter [letter='");
443 if (letter != null) {
444 System.err.print(letter);
445 }
446 System.err.print("'][option='");
447 if (option != null) {
448 System.err.print(option);
449 }
450 System.err.println("']");
451 System.exit(1);
452 }
453 try {
454 String key = letter + '{' + option + '}';
455 ConverterDefinition definition = new ConverterDefinition(key,
456 classname, false, false, label);
457 convertersDef.put(definition.getKey(), definition);
458 } catch (ClassNotFoundException nsme) {
459 System.err.println("No such class " + classname
460 + " for converter [letter='" + letter + "'][option='"
461 + option + "']");
462 System.exit(1);
463 }
464 }
465
466 private void addAnalyzer(String name, String period, String classname,
467 String label) {
468 if (label == null || label.trim().length() == 0) {
469 label = name;
470 }
471 if ((name == null || name.trim().length() == 0)
472 || (classname == null || classname.trim().length() == 0)
473 || (label == null || label.trim().length() == 0)) {
474 System.err.print("Bad analyzer definition for analyzer [name='");
475 if (name != null) {
476 System.err.print(name);
477 }
478 System.err.println("']");
479 System.exit(1);
480 }
481
482 try {
483 AnalyzerDefinition definition = new AnalyzerDefinition(name,
484 period, classname, label);
485 analyzersDef.put(definition.getName(), definition);
486 } catch (ClassNotFoundException nsme) {
487 System.err.print("No such class " + classname
488 + " for analyzer [name='");
489 if (name != null) {
490 System.err.print(name);
491 }
492 System.err.println("']");
493 System.exit(1);
494 }
495 }
496
497 private String patternName = null;
498
499 private String patternContent = null;
500
501 private String patternLabel = null;
502
503 private void preparePattern(String name, String label) {
504 patternName = name;
505 patternContent = "";
506 patternLabel = label;
507 }
508
509 private void addPatternContent(String content) {
510 patternContent += content;
511 }
512
513 private void addPattern(String name, String patternString, String label) {
514 if ((name == null || name.trim().length() == 0)
515 || (patternString == null || patternString.trim().length() == 0)
516 || (label == null || label.trim().length() == 0)) {
517 System.err.print("Bad pattern definition for pattern [name='");
518 if (name != null) {
519 System.err.print(name);
520 }
521 System.err.println("']");
522 System.exit(1);
523 }
524 patternsDef.put(name, new PatternDefinition(name, patternString));
525 patternName = null;
526 patternContent = null;
527 patternLabel = null;
528 }
529
530 private void addRenderer(String name, String classname, String label) {
531 if (label == null || label.trim().length() == 0) {
532 label = name;
533 }
534 if ((name == null || name.trim().length() == 0)
535 || (classname == null || classname.trim().length() == 0)) {
536 System.err.print("Bad renderer definition for renderer [name='");
537 if (name != null) {
538 System.err.print(name);
539 }
540 System.err.println("']");
541 System.exit(1);
542 }
543 try {
544 RendererDefinition definition = new RendererDefinition(name,
545 classname, label);
546 renderersDef.put(definition.getName(), definition);
547 } catch (ClassNotFoundException nsme) {
548 System.err.print("No such class " + classname
549 + " for renderer [name='");
550 if (name != null) {
551 System.err.print(name);
552 }
553 System.err.println("']");
554 System.exit(1);
555 }
556 }
557
558 private String viewName;
559
560 private String viewClassname;
561
562 private String viewLabel;
563
564 private Hashtable viewAttributes;
565
566 private void prepareView(String name, String classname, String label) {
567 viewName = name;
568 viewClassname = classname;
569 viewLabel = label;
570 viewAttributes = new Hashtable();
571 }
572
573 private void addViewAttribute(String name, String value) {
574 viewAttributes.put(name, value);
575 }
576
577 private void addView(String name, String classname, String label,
578 Hashtable attributes) {
579 if (label == null || label.trim().length() == 0) {
580 label = name;
581 }
582 if ((name == null || name.trim().length() == 0)
583 || (classname == null || classname.trim().length() == 0)) {
584 System.err.print("Bad view definition for view [name='");
585 if (name != null) {
586 System.err.print(name);
587 }
588 System.err.println("']");
589 System.exit(1);
590 }
591 try {
592 ViewDefinition definition = new ViewDefinition(name, classname,
593 label, attributes);
594 viewsDef.put(definition.getName(), definition);
595 } catch (ClassNotFoundException cnfe) {
596 System.err
597 .print("No such class " + classname + " for view [name='");
598 if (name != null) {
599 System.err.print(name);
600 }
601 System.err.println("']");
602 System.exit(1);
603 }
604
605 viewName = null;
606 viewClassname = null;
607 viewLabel = null;
608 viewAttributes = null;
609 }
610 }