1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.net;
19
20 import java.io.IOException;
21 import java.io.InterruptedIOException;
22 import java.io.ObjectOutputStream;
23 import java.net.InetAddress;
24 import java.net.ServerSocket;
25 import java.net.Socket;
26 import java.net.SocketException;
27 import java.util.Vector;
28
29 import org.apache.log4j.AppenderSkeleton;
30 import org.apache.log4j.helpers.CyclicBuffer;
31 import org.apache.log4j.helpers.LogLog;
32 import org.apache.log4j.spi.LoggingEvent;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 public class SocketHubAppender extends AppenderSkeleton {
109
110
111
112 static final int DEFAULT_PORT = 4560;
113
114 private int port = DEFAULT_PORT;
115 private Vector oosList = new Vector();
116 private ServerMonitor serverMonitor = null;
117 private boolean locationInfo = false;
118 private CyclicBuffer buffer = null;
119 private String application;
120 private boolean advertiseViaMulticastDNS;
121 private ZeroConfSupport zeroConf;
122
123
124
125
126 public static final String ZONE = "_log4j_obj_tcpaccept_appender.local.";
127 private ServerSocket serverSocket;
128
129
130 public SocketHubAppender() { }
131
132
133
134 public
135 SocketHubAppender(int _port) {
136 port = _port;
137 startServer();
138 }
139
140
141
142 public
143 void activateOptions() {
144 if (advertiseViaMulticastDNS) {
145 zeroConf = new ZeroConfSupport(ZONE, port, getName());
146 zeroConf.advertise();
147 }
148 startServer();
149 }
150
151
152
153
154
155 synchronized
156 public
157 void close() {
158 if(closed)
159 return;
160
161 LogLog.debug("closing SocketHubAppender " + getName());
162 this.closed = true;
163 if (advertiseViaMulticastDNS) {
164 zeroConf.unadvertise();
165 }
166 cleanUp();
167
168 LogLog.debug("SocketHubAppender " + getName() + " closed");
169 }
170
171
172
173
174 public
175 void cleanUp() {
176
177 LogLog.debug("stopping ServerSocket");
178 serverMonitor.stopMonitor();
179 serverMonitor = null;
180
181
182 LogLog.debug("closing client connections");
183 while (oosList.size() != 0) {
184 ObjectOutputStream oos = (ObjectOutputStream)oosList.elementAt(0);
185 if(oos != null) {
186 try {
187 oos.close();
188 } catch(InterruptedIOException e) {
189 Thread.currentThread().interrupt();
190 LogLog.error("could not close oos.", e);
191 } catch(IOException e) {
192 LogLog.error("could not close oos.", e);
193 }
194
195 oosList.removeElementAt(0);
196 }
197 }
198 }
199
200
201
202 public
203 void append(LoggingEvent event) {
204 if (event != null) {
205
206 if (locationInfo) {
207 event.getLocationInformation();
208 }
209 if (application != null) {
210 event.setProperty("application", application);
211 }
212 event.getNDC();
213 event.getThreadName();
214 event.getMDCCopy();
215 event.getRenderedMessage();
216 event.getThrowableStrRep();
217
218 if (buffer != null) {
219 buffer.add(event);
220 }
221 }
222
223
224 if ((event == null) || (oosList.size() == 0)) {
225 return;
226 }
227
228
229 for (int streamCount = 0; streamCount < oosList.size(); streamCount++) {
230
231 ObjectOutputStream oos = null;
232 try {
233 oos = (ObjectOutputStream)oosList.elementAt(streamCount);
234 }
235 catch (ArrayIndexOutOfBoundsException e) {
236
237
238
239 }
240
241
242 if (oos == null)
243 break;
244
245 try {
246 oos.writeObject(event);
247 oos.flush();
248
249
250
251 oos.reset();
252 }
253 catch(IOException e) {
254 if (e instanceof InterruptedIOException) {
255 Thread.currentThread().interrupt();
256 }
257
258 oosList.removeElementAt(streamCount);
259 LogLog.debug("dropped connection");
260
261
262 streamCount--;
263 }
264 }
265 }
266
267
268
269
270 public
271 boolean requiresLayout() {
272 return false;
273 }
274
275
276
277
278 public
279 void setPort(int _port) {
280 port = _port;
281 }
282
283
284
285
286
287 public
288 void setApplication(String lapp) {
289 this.application = lapp;
290 }
291
292
293
294
295 public
296 String getApplication() {
297 return application;
298 }
299
300
301
302 public
303 int getPort() {
304 return port;
305 }
306
307
308
309
310
311 public
312 void setBufferSize(int _bufferSize) {
313 buffer = new CyclicBuffer(_bufferSize);
314 }
315
316
317
318
319 public
320 int getBufferSize() {
321 if (buffer == null) {
322 return 0;
323 } else {
324 return buffer.getMaxSize();
325 }
326 }
327
328
329
330
331
332 public
333 void setLocationInfo(boolean _locationInfo) {
334 locationInfo = _locationInfo;
335 }
336
337
338
339 public
340 boolean getLocationInfo() {
341 return locationInfo;
342 }
343
344 public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
345 this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
346 }
347
348 public boolean isAdvertiseViaMulticastDNS() {
349 return advertiseViaMulticastDNS;
350 }
351
352
353
354 private
355 void startServer() {
356 serverMonitor = new ServerMonitor(port, oosList);
357 }
358
359
360
361
362
363
364
365 protected ServerSocket createServerSocket(final int socketPort) throws IOException {
366 return new ServerSocket(socketPort);
367 }
368
369
370
371
372
373 private class ServerMonitor implements Runnable {
374 private int port;
375 private Vector oosList;
376 private boolean keepRunning;
377 private Thread monitorThread;
378
379
380
381 public
382 ServerMonitor(int _port, Vector _oosList) {
383 port = _port;
384 oosList = _oosList;
385 keepRunning = true;
386 monitorThread = new Thread(this);
387 monitorThread.setDaemon(true);
388 monitorThread.setName("SocketHubAppender-Monitor-" + port);
389 monitorThread.start();
390 }
391
392
393
394
395 public synchronized void stopMonitor() {
396 if (keepRunning) {
397 LogLog.debug("server monitor thread shutting down");
398 keepRunning = false;
399 try {
400 if (serverSocket != null) {
401 serverSocket.close();
402 serverSocket = null;
403 }
404 } catch (IOException ioe) {}
405
406 try {
407 monitorThread.join();
408 }
409 catch (InterruptedException e) {
410 Thread.currentThread().interrupt();
411
412 }
413
414
415 monitorThread = null;
416 LogLog.debug("server monitor thread shut down");
417 }
418 }
419
420 private
421 void sendCachedEvents(ObjectOutputStream stream) throws IOException {
422 if (buffer != null) {
423 for (int i = 0; i < buffer.length(); i++) {
424 stream.writeObject(buffer.get(i));
425 }
426 stream.flush();
427 stream.reset();
428 }
429 }
430
431
432
433
434 public
435 void run() {
436 serverSocket = null;
437 try {
438 serverSocket = createServerSocket(port);
439 serverSocket.setSoTimeout(1000);
440 }
441 catch (Exception e) {
442 if (e instanceof InterruptedIOException || e instanceof InterruptedException) {
443 Thread.currentThread().interrupt();
444 }
445 LogLog.error("exception setting timeout, shutting down server socket.", e);
446 keepRunning = false;
447 return;
448 }
449
450 try {
451 try {
452 serverSocket.setSoTimeout(1000);
453 }
454 catch (SocketException e) {
455 LogLog.error("exception setting timeout, shutting down server socket.", e);
456 return;
457 }
458
459 while (keepRunning) {
460 Socket socket = null;
461 try {
462 socket = serverSocket.accept();
463 }
464 catch (InterruptedIOException e) {
465
466 }
467 catch (SocketException e) {
468 LogLog.error("exception accepting socket, shutting down server socket.", e);
469 keepRunning = false;
470 }
471 catch (IOException e) {
472 LogLog.error("exception accepting socket.", e);
473 }
474
475
476 if (socket != null) {
477 try {
478 InetAddress remoteAddress = socket.getInetAddress();
479 LogLog.debug("accepting connection from " + remoteAddress.getHostName()
480 + " (" + remoteAddress.getHostAddress() + ")");
481
482
483 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
484 if (buffer != null && buffer.length() > 0) {
485 sendCachedEvents(oos);
486 }
487
488
489 oosList.addElement(oos);
490 } catch (IOException e) {
491 if (e instanceof InterruptedIOException) {
492 Thread.currentThread().interrupt();
493 }
494 LogLog.error("exception creating output stream on socket.", e);
495 }
496 }
497 }
498 }
499 finally {
500
501 try {
502 serverSocket.close();
503 } catch(InterruptedIOException e) {
504 Thread.currentThread().interrupt();
505 } catch (IOException e) {
506
507 }
508 }
509 }
510 }
511 }
512