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 org.apache.log4j.plugins.Plugin;
21 import org.apache.log4j.plugins.Receiver;
22 import org.apache.log4j.spi.LoggerRepository;
23
24 import java.io.IOException;
25 import java.net.Socket;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.List;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class SocketHubReceiver
45 extends Receiver implements SocketNodeEventListener, PortBased {
46
47
48
49
50 static final int DEFAULT_RECONNECTION_DELAY = 30000;
51
52
53
54
55 protected String host;
56
57
58
59
60 protected int port;
61
62
63
64 protected int reconnectionDelay = DEFAULT_RECONNECTION_DELAY;
65
66
67
68
69 public static final String ZONE = "_log4j_obj_tcpconnect_receiver.local.";
70
71
72
73
74 protected boolean active = false;
75
76
77
78
79 protected Connector connector;
80
81
82
83
84 protected SocketNode13 socketNode;
85
86
87
88
89 private List listenerList = Collections.synchronizedList(new ArrayList());
90
91 private boolean advertiseViaMulticastDNS;
92 private ZeroConfSupport zeroConf;
93
94
95
96
97 public SocketHubReceiver() {
98 super();
99 }
100
101
102
103
104
105
106 public SocketHubReceiver(final String h,
107 final int p) {
108 super();
109 host = h;
110 port = p;
111 }
112
113
114
115
116
117
118
119 public SocketHubReceiver(final String h,
120 final int p,
121 final LoggerRepository repo) {
122 super();
123 host = h;
124 port = p;
125 repository = repo;
126 }
127
128
129
130
131
132
133 public void addSocketNodeEventListener(final SocketNodeEventListener l) {
134 listenerList.add(l);
135 }
136
137
138
139
140
141
142 public void removeSocketNodeEventListener(
143 final SocketNodeEventListener l) {
144 listenerList.remove(l);
145 }
146
147
148
149
150
151 public String getHost() {
152 return host;
153 }
154
155
156
157
158
159
160 public void setHost(final String remoteHost) {
161 this.host = remoteHost;
162 }
163
164
165
166
167
168 public void setPort(final String remoteHost) {
169 host = remoteHost;
170 }
171
172
173
174
175
176 public int getPort() {
177 return port;
178 }
179
180
181
182
183
184 public void setPort(final int p) {
185 this.port = p;
186 }
187
188
189
190
191
192
193
194
195
196
197
198 public void setReconnectionDelay(final int delay) {
199 int oldValue = this.reconnectionDelay;
200 this.reconnectionDelay = delay;
201 firePropertyChange("reconnectionDelay", oldValue, this.reconnectionDelay);
202 }
203
204
205
206
207
208 public int getReconnectionDelay() {
209 return reconnectionDelay;
210 }
211
212
213
214
215
216
217
218
219
220
221 public boolean isEquivalent(final Plugin testPlugin) {
222 if (testPlugin != null && testPlugin instanceof SocketHubReceiver) {
223 SocketHubReceiver sReceiver = (SocketHubReceiver) testPlugin;
224
225 return (port == sReceiver.getPort()
226 && host.equals(sReceiver.getHost())
227 && reconnectionDelay == sReceiver.getReconnectionDelay()
228 && super.isEquivalent(testPlugin));
229 }
230 return false;
231 }
232
233
234
235
236
237 protected synchronized void setActive(final boolean b) {
238 active = b;
239 }
240
241
242
243 public void activateOptions() {
244 if (!isActive()) {
245 setActive(true);
246 if (advertiseViaMulticastDNS) {
247 zeroConf = new ZeroConfSupport(ZONE, port, getName());
248 zeroConf.advertise();
249 }
250
251 fireConnector(false);
252 }
253 }
254
255
256
257 public synchronized void shutdown() {
258
259 active = false;
260
261
262 try {
263 if (socketNode != null) {
264 socketNode.close();
265 socketNode = null;
266 }
267 } catch (Exception e) {
268 getLogger().info("Excpetion closing socket", e);
269
270 }
271
272
273 if (connector != null) {
274 connector.interrupted = true;
275 connector = null;
276 }
277 if (advertiseViaMulticastDNS) {
278 zeroConf.unadvertise();
279 }
280 }
281
282
283
284
285
286
287 public void socketClosedEvent(final Exception e) {
288
289
290
291
292 if (e != null) {
293 connector = null;
294 fireConnector(true);
295 }
296 }
297
298
299
300
301
302 private synchronized void fireConnector(final boolean isReconnect) {
303 if (active && connector == null) {
304 getLogger().debug("Starting a new connector thread.");
305 connector = new Connector(isReconnect);
306 connector.setDaemon(true);
307 connector.setPriority(Thread.MIN_PRIORITY);
308 connector.start();
309 }
310 }
311
312
313
314
315
316 private synchronized void setSocket(final Socket newSocket) {
317 connector = null;
318 socketNode = new SocketNode13(newSocket, this);
319 socketNode.addSocketNodeEventListener(this);
320
321 synchronized (listenerList) {
322 for (Iterator iter = listenerList.iterator(); iter.hasNext();) {
323 SocketNodeEventListener listener =
324 (SocketNodeEventListener) iter.next();
325 socketNode.addSocketNodeEventListener(listener);
326 }
327 }
328 new Thread(socketNode).start();
329 }
330
331 public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
332 this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
333 }
334
335 public boolean isAdvertiseViaMulticastDNS() {
336 return advertiseViaMulticastDNS;
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350 private final class Connector extends Thread {
351
352
353
354
355 boolean interrupted = false;
356
357
358
359 boolean doDelay;
360
361
362
363
364
365 public Connector(final boolean isReconnect) {
366 super();
367 doDelay = isReconnect;
368 }
369
370
371
372
373 public void run() {
374 while (!interrupted) {
375 try {
376 if (doDelay) {
377 getLogger().debug("waiting for " + reconnectionDelay
378 + " milliseconds before reconnecting.");
379 sleep(reconnectionDelay);
380 }
381 doDelay = true;
382 getLogger().debug("Attempting connection to " + host);
383 Socket s = new Socket(host, port);
384 setSocket(s);
385 getLogger().debug(
386 "Connection established. Exiting connector thread.");
387 break;
388 } catch (InterruptedException e) {
389 getLogger().debug("Connector interrupted. Leaving loop.");
390 return;
391 } catch (java.net.ConnectException e) {
392 getLogger().debug("Remote host {} refused connection.", host);
393 } catch (IOException e) {
394 getLogger().debug("Could not connect to {}. Exception is {}.",
395 host, e);
396 }
397 }
398 }
399 }
400
401
402
403
404
405 public void socketOpened(final String remoteInfo) {
406
407
408 }
409 }