1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ch.qos.logback.core.net;
16
17 import java.io.IOException;
18 import java.io.ObjectOutputStream;
19 import java.io.Serializable;
20 import java.net.InetAddress;
21 import java.net.Socket;
22
23 import ch.qos.logback.core.AppenderBase;
24 import ch.qos.logback.core.CoreConstants;
25 import ch.qos.logback.core.spi.PreSerializationTransformer;
26
27
28
29
30
31
32
33
34
35 public abstract class SocketAppenderBase<E> extends AppenderBase<E> {
36
37
38
39
40 static final int DEFAULT_PORT = 4560;
41
42
43
44
45 static final int DEFAULT_RECONNECTION_DELAY = 30000;
46
47
48
49
50
51 protected String remoteHost;
52
53 protected InetAddress address;
54 protected int port = DEFAULT_PORT;
55 protected ObjectOutputStream oos;
56 protected int reconnectionDelay = DEFAULT_RECONNECTION_DELAY;
57
58 private Connector connector;
59
60 protected int counter = 0;
61
62
63
64
65 public void start() {
66 int errorCount = 0;
67 if (port == 0) {
68 errorCount++;
69 addError("No port was configured for appender"
70 + name
71 + " For more information, please visit http://logback.qos.ch/codes.html#socket_no_port");
72 }
73
74 if (address == null) {
75 errorCount++;
76 addError("No remote address was configured for appender"
77 + name
78 + " For more information, please visit http://logback.qos.ch/codes.html#socket_no_host");
79 }
80
81 connect(address, port);
82
83 if (errorCount == 0) {
84 this.started = true;
85 }
86 }
87
88
89
90
91
92
93
94
95 @Override
96 public void stop() {
97 if (!isStarted())
98 return;
99
100 this.started = false;
101 cleanUp();
102 }
103
104
105
106
107
108 public void cleanUp() {
109 if (oos != null) {
110 try {
111 oos.close();
112 } catch (IOException e) {
113 addError("Could not close oos.", e);
114 }
115 oos = null;
116 }
117 if (connector != null) {
118 addInfo("Interrupting the connector.");
119 connector.interrupted = true;
120 connector = null;
121 }
122 }
123
124 void connect(InetAddress address, int port) {
125 if (this.address == null)
126 return;
127 try {
128
129 cleanUp();
130 oos = new ObjectOutputStream(new Socket(address, port).getOutputStream());
131 } catch (IOException e) {
132
133 String msg = "Could not connect to remote logback server at ["
134 + address.getHostName() + "].";
135 if (reconnectionDelay > 0) {
136 msg += " We will try again later.";
137 fireConnector();
138 }
139 addInfo(msg, e);
140 }
141 }
142
143 @Override
144 protected void append(E event) {
145
146 if (event == null)
147 return;
148
149 if (address == null) {
150 addError("No remote host is set for SocketAppender named \""
151 + this.name
152 + "\". For more information, please visit http://logback.qos.ch/codes.html#socket_no_host");
153 return;
154 }
155
156 if (oos != null) {
157 try {
158 postProcessEvent(event);
159 Serializable serEvent = getPST().transform(event);
160 oos.writeObject(serEvent);
161 oos.flush();
162 if (++counter >= CoreConstants.OOS_RESET_FREQUENCY) {
163 counter = 0;
164
165
166
167 oos.reset();
168 }
169 } catch (IOException e) {
170 if (oos != null) {
171 try {
172 oos.close();
173 } catch (IOException ignore) {
174 }
175 }
176
177 oos = null;
178 addWarn("Detected problem with connection: " + e);
179 if (reconnectionDelay > 0) {
180 fireConnector();
181 }
182 }
183 }
184 }
185
186 protected abstract void postProcessEvent(E event);
187 protected abstract PreSerializationTransformer<E> getPST();
188
189 void fireConnector() {
190 if (connector == null) {
191 addInfo("Starting a new connector thread.");
192 connector = new Connector();
193 connector.setDaemon(true);
194 connector.setPriority(Thread.MIN_PRIORITY);
195 connector.start();
196 }
197 }
198
199 protected static InetAddress getAddressByName(String host) {
200 try {
201 return InetAddress.getByName(host);
202 } catch (Exception e) {
203
204 return null;
205 }
206 }
207
208
209
210
211 public void setRemoteHost(String host) {
212 address = getAddressByName(host);
213 remoteHost = host;
214 }
215
216
217
218
219 public String getRemoteHost() {
220 return remoteHost;
221 }
222
223
224
225
226
227 public void setPort(int port) {
228 this.port = port;
229 }
230
231
232
233
234 public int getPort() {
235 return port;
236 }
237
238
239
240
241
242
243
244
245
246
247 public void setReconnectionDelay(int delay) {
248 this.reconnectionDelay = delay;
249 }
250
251
252
253
254 public int getReconnectionDelay() {
255 return reconnectionDelay;
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271 class Connector extends Thread {
272
273 boolean interrupted = false;
274
275 public void run() {
276 Socket socket;
277 while (!interrupted) {
278 try {
279 sleep(reconnectionDelay);
280 addInfo("Attempting connection to " + address.getHostName());
281 socket = new Socket(address, port);
282 synchronized (this) {
283 oos = new ObjectOutputStream(socket.getOutputStream());
284 connector = null;
285 addInfo("Connection established. Exiting connector thread.");
286 break;
287 }
288 } catch (InterruptedException e) {
289 addInfo("Connector interrupted. Leaving loop.");
290 return;
291 } catch (java.net.ConnectException e) {
292 addInfo("Remote host " + address.getHostName()
293 + " refused connection.");
294 } catch (IOException e) {
295 addInfo("Could not connect to " + address.getHostName()
296 + ". Exception is " + e);
297 }
298 }
299
300 }
301
302
303
304
305
306 }
307
308 }