001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.encoder; 015 016import java.nio.charset.Charset; 017 018import ch.qos.logback.core.CoreConstants; 019import ch.qos.logback.core.Layout; 020import ch.qos.logback.core.OutputStreamAppender; 021import ch.qos.logback.core.spi.ContextAware; 022 023public class LayoutWrappingEncoder<E> extends EncoderBase<E> { 024 025 protected Layout<E> layout; 026 027 /** 028 * The charset to use when converting a String into bytes. 029 * <p> 030 * By default this property has the value {@code null} which corresponds to the 031 * system's default charset. 032 */ 033 private Charset charset; 034 035 ContextAware parent; 036 Boolean immediateFlush = null; 037 038 public Layout<E> getLayout() { 039 return layout; 040 } 041 042 public void setLayout(Layout<E> layout) { 043 this.layout = layout; 044 } 045 046 public Charset getCharset() { 047 return charset; 048 } 049 050 /** 051 * Set the charset to use when converting the string returned by the layout into 052 * bytes. 053 * <p> 054 * By default this property has the value {@code null} which corresponds to the 055 * system's default charset. 056 * 057 * @param charset 058 */ 059 public void setCharset(Charset charset) { 060 this.charset = charset; 061 } 062 063 /** 064 * Sets the immediateFlush option. The default value for immediateFlush is 065 * 'true'. If set to true, the doEncode() method will immediately flush the 066 * underlying OutputStream. Although immediate flushing is safer, it also 067 * significantly degrades logging throughput. 068 * 069 * @since 1.0.3 070 */ 071 public void setImmediateFlush(boolean immediateFlush) { 072 addWarn("As of version 1.2.0 \"immediateFlush\" property should be set within the enclosing Appender."); 073 addWarn("Please move \"immediateFlush\" property into the enclosing appender."); 074 this.immediateFlush = immediateFlush; 075 } 076 077 @Override 078 public byte[] headerBytes() { 079 if (layout == null) 080 return null; 081 082 StringBuilder sb = new StringBuilder(); 083 appendIfNotNull(sb, layout.getFileHeader()); 084 appendIfNotNull(sb, layout.getPresentationHeader()); 085 if (sb.length() > 0) { 086 // If at least one of file header or presentation header were not 087 // null, then append a line separator. 088 // This should be useful in most cases and should not hurt. 089 sb.append(CoreConstants.LINE_SEPARATOR); 090 } 091 return convertToBytes(sb.toString()); 092 } 093 094 @Override 095 public byte[] footerBytes() { 096 if (layout == null) 097 return null; 098 099 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}