View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.pattern.parser;
15  
16  import java.util.Map;
17  
18  import ch.qos.logback.core.pattern.*;
19  import ch.qos.logback.core.spi.ContextAwareBase;
20  import ch.qos.logback.core.status.ErrorStatus;
21  import ch.qos.logback.core.util.OptionHelper;
22  
23  class Compiler<E> extends ContextAwareBase {
24  
25    Converter<E> head;
26    Converter<E> tail;
27    final Node top;
28    final Map converterMap;
29  
30    Compiler(final Node top, final Map converterMap) {
31      this.top = top;
32      this.converterMap = converterMap;
33    }
34  
35    Converter<E> compile() {
36      head = tail = null;
37      for (Node n = top; n != null; n = n.next) {
38        switch (n.type) {
39          case Node.LITERAL:
40            addToList(new LiteralConverter<E>((String) n.getValue()));
41            break;
42          case Node.COMPOSITE_KEYWORD:
43            CompositeNode cn = (CompositeNode) n;
44            CompositeConverter<E> compositeConverter = createCompositeConverter(cn);
45            if(compositeConverter == null) {
46              addError("Failed to create converter for [%"+cn.getValue()+"] keyword");
47              addToList(new LiteralConverter<E>("%PARSER_ERROR["+cn.getValue()+"]"));
48              break;
49            }
50            compositeConverter.setFormattingInfo(cn.getFormatInfo());
51            compositeConverter.setOptionList(cn.getOptions());
52            Compiler<E> childCompiler = new Compiler<E>(cn.getChildNode(),
53                    converterMap);
54            childCompiler.setContext(context);
55            Converter<E> childConverter = childCompiler.compile();
56            compositeConverter.setChildConverter(childConverter);
57            addToList(compositeConverter);
58            break;
59          case Node.SIMPLE_KEYWORD:
60            SimpleKeywordNode kn = (SimpleKeywordNode) n;
61            DynamicConverter<E> dynaConverter = createConverter(kn);
62            if (dynaConverter != null) {
63              dynaConverter.setFormattingInfo(kn.getFormatInfo());
64              dynaConverter.setOptionList(kn.getOptions());
65              addToList(dynaConverter);
66            } else {
67              // if the appropriate dynaconverter cannot be found, then replace
68              // it with a dummy LiteralConverter indicating an error.
69              Converter<E> errConveter = new LiteralConverter<E>("%PARSER_ERROR["
70                      + kn.getValue() + "]");
71              addStatus(new ErrorStatus("[" + kn.getValue()
72                      + "] is not a valid conversion word", this));
73              addToList(errConveter);
74            }
75  
76        }
77      }
78      return head;
79    }
80  
81    private void addToList(Converter<E> c) {
82      if (head == null) {
83        head = tail = c;
84      } else {
85        tail.setNext(c);
86        tail = c;
87      }
88    }
89  
90    /**
91     * Attempt to create a converter using the information found in
92     * 'converterMap'.
93     *
94     * @param kn
95     * @return
96     */
97    @SuppressWarnings("unchecked")
98    DynamicConverter<E> createConverter(SimpleKeywordNode kn) {
99      String keyword = (String) kn.getValue();
100     String converterClassStr = (String) converterMap.get(keyword);
101 
102     if (converterClassStr != null) {
103       try {
104         return (DynamicConverter) OptionHelper.instantiateByClassName(
105                 converterClassStr, DynamicConverter.class, context);
106       } catch (Exception e) {
107         addError("Failed to instantiate converter class [" + converterClassStr
108                 + "] for keyword ["+keyword+"]", e);
109         return null;
110       }
111     } else {
112       addError("There is no conversion class registered for conversion word ["
113               + keyword + "]");
114       return null;
115     }
116   }
117 
118   /**
119    * Attempt to create a converter using the information found in
120    * 'compositeConverterMap'.
121    *
122    * @param cn
123    * @return
124    */
125   @SuppressWarnings("unchecked")
126   CompositeConverter<E> createCompositeConverter(CompositeNode cn) {
127     String keyword = (String) cn.getValue();
128     String converterClassStr = (String) converterMap.get(keyword);
129 
130     if (converterClassStr != null) {
131       try {
132         return (CompositeConverter) OptionHelper.instantiateByClassName(
133                 converterClassStr, CompositeConverter.class, context);
134       } catch (Exception e) {
135         addError("Failed to instantiate converter class [" + converterClassStr
136                 + "] as a composite converter for keyword ["+keyword+"]", e);
137         return null;
138       }
139     } else {
140       addError("There is no conversion class registered for composite conversion word ["
141               + keyword + "]");
142       return null;
143     }
144   }
145 
146 
147   // public void setStatusManager(StatusManager statusManager) {
148   // this.statusManager = statusManager;
149   // }
150   //  
151   // void addStatus(Status status) {
152   // if(statusManager != null) {
153   // statusManager.add(status);
154   // }
155   // }
156 }