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 'converterMap'.
92       *
93       * @param kn
94       * @return
95       */
96      @SuppressWarnings("unchecked")
97      DynamicConverter<E> createConverter(SimpleKeywordNode kn) {
98          String keyword = (String) kn.getValue();
99          String converterClassStr = (String) converterMap.get(keyword);
100 
101         if (converterClassStr != null) {
102             try {
103                 return (DynamicConverter<E>) OptionHelper.instantiateByClassName(converterClassStr,
104                         DynamicConverter.class, context);
105             } catch (Exception e) {
106                 addError("Failed to instantiate converter class [" + converterClassStr + "] for keyword [" + keyword
107                         + "]", e);
108                 return null;
109             }
110         } else {
111             addError("There is no conversion class registered for conversion word [" + keyword + "]");
112             return null;
113         }
114     }
115 
116     /**
117      * Attempt to create a converter using the information found in
118      * 'compositeConverterMap'.
119      *
120      * @param cn
121      * @return
122      */
123     @SuppressWarnings("unchecked")
124     CompositeConverter<E> createCompositeConverter(CompositeNode cn) {
125         String keyword = (String) cn.getValue();
126         String converterClassStr = (String) converterMap.get(keyword);
127 
128         if (converterClassStr != null) {
129             try {
130                 return (CompositeConverter<E>) OptionHelper.instantiateByClassName(converterClassStr,
131                         CompositeConverter.class, context);
132             } catch (Exception e) {
133                 addError("Failed to instantiate converter class [" + converterClassStr
134                         + "] as a composite converter for keyword [" + keyword + "]", e);
135                 return null;
136             }
137         } else {
138             addError("There is no conversion class registered for composite conversion word [" + keyword + "]");
139             return null;
140         }
141     }
142 
143     // public void setStatusManager(StatusManager statusManager) {
144     // this.statusManager = statusManager;
145     // }
146     //
147     // void addStatus(Status status) {
148     // if(statusManager != null) {
149     // statusManager.add(status);
150     // }
151     // }
152 }