View Javadoc
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          // Use the default (non-validating) parser
62          SAXParserFactory factory = SAXParserFactory.newInstance();
63          try {
64              // Parse the input
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             // Checks if the class extends LiteralConverter
399             Class literalClass = ClassLoader.getSystemClassLoader().loadClass(
400                     classname);
401             if (LiteralConverter.class.isAssignableFrom(literalClass)) {
402                 // Creates the definition
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 }