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;
15  
16  import java.util.HashMap;
17  import java.util.Map;
18  
19  import ch.qos.logback.core.Context;
20  import ch.qos.logback.core.CoreConstants;
21  import ch.qos.logback.core.LayoutBase;
22  import ch.qos.logback.core.pattern.parser.Node;
23  import ch.qos.logback.core.pattern.parser.Parser;
24  import ch.qos.logback.core.pattern.parser.ScanException;
25  import ch.qos.logback.core.spi.ContextAware;
26  import ch.qos.logback.core.status.ErrorStatus;
27  import ch.qos.logback.core.status.StatusManager;
28  
29  abstract public class PatternLayoutBase<E> extends LayoutBase<E> {
30  
31    Converter<E> head;
32    String pattern;
33    protected PostCompileProcessor<E> postCompileProcessor;
34  
35  
36    Map<String, String> instanceConverterMap = new HashMap<String, String>();
37    protected boolean outputPatternAsHeader = false;
38  
39    /**
40     * Concrete implementations of this class are responsible for elaborating the
41     * mapping between pattern words and converters.
42     * 
43     * @return A map associating pattern words to the names of converter classes
44     */
45    abstract public Map<String, String> getDefaultConverterMap();
46  
47    /**
48     * Returns a map where the default converter map is merged with the map
49     * contained in the context.
50     */
51    public Map<String, String> getEffectiveConverterMap() {
52      Map<String, String> effectiveMap = new HashMap<String, String>();
53  
54      // add the least specific map fist
55      Map<String, String> defaultMap = getDefaultConverterMap();
56      if (defaultMap != null) {
57        effectiveMap.putAll(defaultMap);
58      }
59  
60      // contextMap is more specific than the default map
61      Context context = getContext();
62      if (context != null) {
63        @SuppressWarnings("unchecked")
64        Map<String, String> contextMap = (Map<String, String>) context
65            .getObject(CoreConstants.PATTERN_RULE_REGISTRY);
66        if (contextMap != null) {
67          effectiveMap.putAll(contextMap);
68        }
69      }
70      // set the most specific map last
71      effectiveMap.putAll(instanceConverterMap);
72      return effectiveMap;
73    }
74  
75    public void start() {
76      if(pattern == null || pattern.length() == 0) {
77        addError("Empty or null pattern.");
78        return;
79      }
80      try { 
81        Parser<E> p = new Parser<E>(pattern);
82        if (getContext() != null) {
83          p.setContext(getContext());
84        }
85        Node t = p.parse();
86        this.head = p.compile(t, getEffectiveConverterMap());
87        if (postCompileProcessor != null) {
88          postCompileProcessor.process(head);
89        }
90        setContextForConverters(head);
91        ConverterUtil.startConverters(this.head);
92        super.start();
93      } catch (ScanException sce) {
94        StatusManager sm = getContext().getStatusManager();
95        sm.add(new ErrorStatus("Failed to parse pattern \"" + getPattern()
96            + "\".", this, sce));
97      }
98    }
99  
100   public void setPostCompileProcessor(
101       PostCompileProcessor<E> postCompileProcessor) {
102     this.postCompileProcessor = postCompileProcessor;
103   }
104 
105   protected void setContextForConverters(Converter<E> head) {
106     Context context = getContext();
107     Converter c = head;
108     while (c != null) {
109       if (c instanceof ContextAware) {
110         ((ContextAware) c).setContext(context);
111       }
112       c = c.getNext();
113     }
114   }
115 
116   protected String writeLoopOnConverters(E event) {
117     StringBuilder buf = new StringBuilder(128);
118     Converter<E> c = head;
119     while (c != null) {
120       c.write(buf, event);
121       c = c.getNext();
122     }
123     return buf.toString();
124   }
125 
126   public String getPattern() {
127     return pattern;
128   }
129 
130   public void setPattern(String pattern) {
131     this.pattern = pattern;
132   }
133 
134   public String toString() {
135     return this.getClass().getName() + "(\"" + getPattern() + "\")";
136   }
137 
138   public Map<String, String> getInstanceConverterMap() {
139     return instanceConverterMap;
140   }
141 
142   
143   protected String getPresentationHeaderPrefix() {
144     return CoreConstants.EMPTY_STRING;
145   }
146 
147   public boolean isOutputPatternAsHeader() {
148     return outputPatternAsHeader;
149   }
150 
151   public void setOutputPatternAsHeader(boolean outputPatternAsHeader) {
152     this.outputPatternAsHeader = outputPatternAsHeader;
153   }
154 
155   @Override
156   public String getPresentationHeader() {
157     if(outputPatternAsHeader)
158       return getPresentationHeaderPrefix()+pattern;
159     else
160       return super.getPresentationHeader();
161   }
162 }