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