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.encoder;
15  
16  import java.nio.charset.Charset;
17  
18  import ch.qos.logback.core.CoreConstants;
19  import ch.qos.logback.core.Layout;
20  import ch.qos.logback.core.OutputStreamAppender;
21  import ch.qos.logback.core.spi.ContextAware;
22  
23  public class LayoutWrappingEncoder<E> extends EncoderBase<E> {
24  
25      protected Layout<E> layout;
26  
27      /**
28       * The charset to use when converting a String into bytes.
29       * <p>
30       * By default this property has the value {@code null} which corresponds to the
31       * system's default charset.
32       */
33      private Charset charset;
34  
35      ContextAware parent;
36      Boolean immediateFlush = null;
37  
38      public Layout<E> getLayout() {
39          return layout;
40      }
41  
42      public void setLayout(Layout<E> layout) {
43          this.layout = layout;
44      }
45  
46      public Charset getCharset() {
47          return charset;
48      }
49  
50      /**
51       * Set the charset to use when converting the string returned by the layout into
52       * bytes.
53       * <p>
54       * By default this property has the value {@code null} which corresponds to the
55       * system's default charset.
56       *
57       * @param charset
58       */
59      public void setCharset(Charset charset) {
60          this.charset = charset;
61      }
62  
63      /**
64       * Sets the immediateFlush option. The default value for immediateFlush is
65       * 'true'. If set to true, the doEncode() method will immediately flush the
66       * underlying OutputStream. Although immediate flushing is safer, it also
67       * significantly degrades logging throughput.
68       *
69       * @since 1.0.3
70       */
71      public void setImmediateFlush(boolean immediateFlush) {
72          addWarn("As of version 1.2.0 \"immediateFlush\" property should be set within the enclosing Appender.");
73          addWarn("Please move \"immediateFlush\" property into the enclosing appender.");
74          this.immediateFlush = immediateFlush;
75      }
76  
77      @Override
78      public byte[] headerBytes() {
79          if (layout == null)
80              return null;
81  
82          StringBuilder sb = new StringBuilder();
83          appendIfNotNull(sb, layout.getFileHeader());
84          appendIfNotNull(sb, layout.getPresentationHeader());
85          if (sb.length() > 0) {
86              // If at least one of file header or presentation header were not
87              // null, then append a line separator.
88              // This should be useful in most cases and should not hurt.
89              sb.append(CoreConstants.LINE_SEPARATOR);
90          }
91          return convertToBytes(sb.toString());
92      }
93  
94      @Override
95      public byte[] footerBytes() {
96          if (layout == null)
97              return null;
98  
99          StringBuilder sb = new StringBuilder();
100         appendIfNotNull(sb, layout.getPresentationFooter());
101         appendIfNotNull(sb, layout.getFileFooter());
102         return convertToBytes(sb.toString());
103     }
104 
105     private byte[] convertToBytes(String s) {
106         if (charset == null) {
107             return s.getBytes();
108         } else {
109             return s.getBytes(charset);
110         }
111     }
112 
113     public byte[] encode(E event) {
114         String txt = layout.doLayout(event);
115         return convertToBytes(txt);
116     }
117 
118     public boolean isStarted() {
119         return started;
120     }
121 
122     public void start() {
123         if (immediateFlush != null) {
124             if (parent instanceof OutputStreamAppender) {
125                 addWarn("Setting the \"immediateFlush\" property of the enclosing appender to " + immediateFlush);
126                 @SuppressWarnings("unchecked")
127                 OutputStreamAppender<E> parentOutputStreamAppender = (OutputStreamAppender<E>) parent;
128                 parentOutputStreamAppender.setImmediateFlush(immediateFlush);
129             } else {
130                 addError("Could not set the \"immediateFlush\" property of the enclosing appender.");
131             }
132         }
133         started = true;
134     }
135 
136     public void stop() {
137         started = false;
138     }
139 
140     private void appendIfNotNull(StringBuilder sb, String s) {
141         if (s != null) {
142             sb.append(s);
143         }
144     }
145 
146     /**
147      * This method allows RollingPolicy implementations to be aware of their
148      * containing appender.
149      * 
150      * @param parent
151      */
152     public void setParent(ContextAware parent) {
153         this.parent = parent;
154     }
155 }