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