View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, 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.CompositeConverter;
19  import ch.qos.logback.core.pattern.Converter;
20  import ch.qos.logback.core.pattern.DynamicConverter;
21  import ch.qos.logback.core.pattern.LiteralConverter;
22  import ch.qos.logback.core.spi.ContextAwareBase;
23  import ch.qos.logback.core.status.ErrorStatus;
24  import ch.qos.logback.core.util.OptionHelper;
25  
26  class Compiler<E> extends ContextAwareBase {
27  
28      Converter<E> head;
29      Converter<E> tail;
30      final Node top;
31      final Map<String, String> converterMap;
32  
33      Compiler(final Node top, final Map<String, String> converterMap) {
34          this.top = top;
35          this.converterMap = converterMap;
36      }
37  
38      Converter<E> compile() {
39          head = tail = null;
40          for (Node n = top; n != null; n = n.next) {
41              switch (n.type) {
42              case Node.LITERAL:
43                  addToList(new LiteralConverter<E>((String) n.getValue()));
44                  break;
45              case Node.COMPOSITE_KEYWORD:
46                  CompositeNode cn = (CompositeNode) n;
47                  CompositeConverter<E> compositeConverter = createCompositeConverter(cn);
48                  if (compositeConverter == null) {
49                      addError("Failed to create converter for [%" + cn.getValue() + "] keyword");
50                      addToList(new LiteralConverter<E>("%PARSER_ERROR[" + cn.getValue() + "]"));
51                      break;
52                  }
53                  compositeConverter.setFormattingInfo(cn.getFormatInfo());
54                  compositeConverter.setOptionList(cn.getOptions());
55                  Compiler<E> childCompiler = new Compiler<E>(cn.getChildNode(), converterMap);
56                  childCompiler.setContext(context);
57                  Converter<E> childConverter = childCompiler.compile();
58                  compositeConverter.setChildConverter(childConverter);
59                  addToList(compositeConverter);
60                  break;
61              case Node.SIMPLE_KEYWORD:
62                  SimpleKeywordNode kn = (SimpleKeywordNode) n;
63                  DynamicConverter<E> dynaConverter = createConverter(kn);
64                  if (dynaConverter != null) {
65                      dynaConverter.setFormattingInfo(kn.getFormatInfo());
66                      dynaConverter.setOptionList(kn.getOptions());
67                      addToList(dynaConverter);
68                  } else {
69                      // if the appropriate dynaconverter cannot be found, then replace
70                      // it with a dummy LiteralConverter indicating an error.
71                      Converter<E> errConveter = new LiteralConverter<E>("%PARSER_ERROR[" + kn.getValue() + "]");
72                      addStatus(new ErrorStatus("[" + kn.getValue() + "] 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<E>) OptionHelper.instantiateByClassName(converterClassStr, DynamicConverter.class, context);
105             } catch (Exception e) {
106                 addError("Failed to instantiate converter class [" + converterClassStr + "] for keyword [" + keyword + "]", e);
107                 return null;
108             }
109         } else {
110             addError("There is no conversion class registered for conversion word [" + keyword + "]");
111             return null;
112         }
113     }
114 
115     /**
116      * Attempt to create a converter using the information found in
117      * 'compositeConverterMap'.
118      *
119      * @param cn
120      * @return
121      */
122     @SuppressWarnings("unchecked")
123     CompositeConverter<E> createCompositeConverter(CompositeNode cn) {
124         String keyword = (String) cn.getValue();
125         String converterClassStr = (String) converterMap.get(keyword);
126 
127         if (converterClassStr != null) {
128             try {
129                 return (CompositeConverter<E>) OptionHelper.instantiateByClassName(converterClassStr, CompositeConverter.class, context);
130             } catch (Exception e) {
131                 addError("Failed to instantiate converter class [" + converterClassStr + "] as a composite converter for keyword [" + keyword + "]", e);
132                 return null;
133             }
134         } else {
135             addError("There is no conversion class registered for composite conversion word [" + keyword + "]");
136             return null;
137         }
138     }
139 
140     // public void setStatusManager(StatusManager statusManager) {
141     // this.statusManager = statusManager;
142     // }
143     //
144     // void addStatus(Status status) {
145     // if(statusManager != null) {
146     // statusManager.add(status);
147     // }
148     // }
149 }