1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core;
15
16 import static ch.qos.logback.core.CoreConstants.CODES_URL;
17
18 import java.io.IOException;
19 import java.io.OutputStream;
20
21 import ch.qos.logback.core.encoder.Encoder;
22 import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
23 import ch.qos.logback.core.spi.DeferredProcessingAware;
24 import ch.qos.logback.core.status.ErrorStatus;
25
26
27
28
29
30
31
32
33
34
35 public class OutputStreamAppender<E> extends UnsynchronizedAppenderBase<E> {
36
37
38
39
40
41
42 protected Encoder<E> encoder;
43
44
45
46
47 protected Object lock = new Object();
48
49
50
51
52 private OutputStream outputStream;
53
54
55
56
57
58
59 public OutputStream getOutputStream() {
60 return outputStream;
61 }
62
63
64
65
66
67 public void start() {
68 int errors = 0;
69 if (this.encoder == null) {
70 addStatus(new ErrorStatus("No encoder set for the appender named \""
71 + name + "\".", this));
72 errors++;
73 }
74
75 if (this.outputStream == null) {
76 addStatus(new ErrorStatus(
77 "No output stream set for the appender named \"" + name + "\".", this));
78 errors++;
79 }
80
81 if (errors == 0) {
82 super.start();
83 }
84 }
85
86 public void setLayout(Layout<E> layout) {
87 addWarn("This appender no longer admits a layout as a sub-component, set an encoder instead.");
88 addWarn("To ensure compatibility, wrapping your layout in LayoutWrappingEncoder.");
89 addWarn("See also "+CODES_URL+"#layoutInsteadOfEncoder for details");
90 LayoutWrappingEncoder<E> lwe = new LayoutWrappingEncoder<E>();
91 lwe.setLayout(layout);
92 lwe.setContext(context);
93 this.encoder = lwe;
94 }
95
96 @Override
97 protected void append(E eventObject) {
98 if (!isStarted()) {
99 return;
100 }
101
102 subAppend(eventObject);
103 }
104
105
106
107
108
109
110
111
112 public void stop() {
113 synchronized (lock) {
114 closeOutputStream();
115 super.stop();
116 }
117 }
118
119
120
121
122 protected void closeOutputStream() {
123 if (this.outputStream != null) {
124 try {
125
126 encoderClose();
127 this.outputStream.close();
128 this.outputStream = null;
129 } catch (IOException e) {
130 addStatus(new ErrorStatus(
131 "Could not close output stream for OutputStreamAppender.", this, e));
132 }
133 }
134 }
135
136 void encoderInit() {
137 if (encoder != null && this.outputStream != null) {
138 try {
139 encoder.init(outputStream);
140 } catch (IOException ioe) {
141 this.started = false;
142 addStatus(new ErrorStatus(
143 "Failed to initialize encoder for appender named [" + name + "].",
144 this, ioe));
145 }
146 }
147 }
148
149 void encoderClose() {
150 if (encoder != null && this.outputStream != null) {
151 try {
152 encoder.close();
153 } catch (IOException ioe) {
154 this.started = false;
155 addStatus(new ErrorStatus("Failed to write footer for appender named ["
156 + name + "].", this, ioe));
157 }
158 }
159 }
160
161
162
163
164
165
166
167
168
169
170
171 public void setOutputStream(OutputStream outputStream) {
172 synchronized (lock) {
173
174 closeOutputStream();
175
176 this.outputStream = outputStream;
177 if (encoder == null) {
178 addWarn("Encoder has not been set. Cannot invoke its init method.");
179 return;
180 }
181
182 encoderInit();
183 }
184 }
185
186 protected void writeOut(E event) throws IOException {
187 this.encoder.doEncode(event);
188 }
189
190
191
192
193
194
195
196
197
198 protected void subAppend(E event) {
199 if (!isStarted()) {
200 return;
201 }
202 try {
203
204 if (event instanceof DeferredProcessingAware) {
205 ((DeferredProcessingAware) event).prepareForDeferredProcessing();
206 }
207
208
209
210 synchronized (lock) {
211 writeOut(event);
212 }
213 } catch (IOException ioe) {
214
215
216 this.started = false;
217 addStatus(new ErrorStatus("IO failure in appender", this, ioe));
218 }
219 }
220
221 public Encoder<E> getEncoder() {
222 return encoder;
223 }
224
225 public void setEncoder(Encoder<E> encoder) {
226 this.encoder = encoder;
227 }
228
229 }