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.net.ServerSocket;
21 import java.net.Socket;
22 import java.util.List;
23 import java.util.Vector;
24
25 import org.apache.log4j.plugins.Pauseable;
26 import org.apache.log4j.plugins.Plugin;
27 import org.apache.log4j.plugins.Receiver;
28 import org.apache.log4j.spi.LoggerRepository;
29 import org.apache.log4j.spi.LoggingEvent;
30
31
32 /***
33 XMLSocketReceiver receives a remote logging event via XML on a configured
34 socket and "posts" it to a LoggerRepository as if the event were
35 generated locally. This class is designed to receive events from
36 the XMLSocketAppender class (or classes that send compatible events).
37
38 <p>Once the event has been "posted", it will be handled by the
39 appenders currently configured in the LoggerRespository.
40
41 @author Mark Womack
42 @author Scott Deboy <sdeboy@apache.org>
43
44 */
45 public class XMLSocketReceiver extends Receiver implements Runnable, PortBased, Pauseable {
46 protected boolean active = false;
47 private boolean paused;
48
49 protected String decoder = "org.apache.log4j.xml.XMLDecoder";
50 private ServerSocket serverSocket;
51 private List socketList = new Vector();
52 private Thread rThread;
53 public static final int DEFAULT_PORT = 4448;
54 protected int port = DEFAULT_PORT;
55
56 public XMLSocketReceiver() {
57 }
58
59 public XMLSocketReceiver(int _port) {
60 port = _port;
61 }
62
63 public XMLSocketReceiver(int _port, LoggerRepository _repository) {
64 port = _port;
65 repository = _repository;
66 }
67
68 /***
69 Get the port to receive logging events on. */
70 public int getPort() {
71 return port;
72 }
73
74 /***
75 Set the port to receive logging events on. */
76 public void setPort(int _port) {
77 port = _port;
78 }
79
80 public String getDecoder() {
81 return decoder;
82 }
83
84 public void setDecoder(String _decoder) {
85 decoder = _decoder;
86 }
87
88 public boolean isPaused() {
89 return paused;
90 }
91
92 public void setPaused(boolean b) {
93 paused = b;
94 }
95
96 /***
97 * Returns true if the receiver is the same class and they are
98 * configured for the same properties, and super class also considers
99 * them to be equivalent. This is used by PluginRegistry when determining
100 * if the a similarly configured receiver is being started.
101 *
102 * @param testPlugin The plugin to test equivalency against.
103 * @return boolean True if the testPlugin is equivalent to this plugin.
104 */
105 public boolean isEquivalent(Plugin testPlugin) {
106 if ((testPlugin != null) && testPlugin instanceof XMLSocketReceiver) {
107 XMLSocketReceiver sReceiver = (XMLSocketReceiver) testPlugin;
108
109 return (port == sReceiver.getPort() && super.isEquivalent(testPlugin));
110 }
111
112 return false;
113 }
114
115 public int hashCode() {
116
117 int result = 37 * (repository != null? repository.hashCode():0);
118 result = result * 37 + port;
119 return (result * 37 + (getName() != null? getName().hashCode():0));
120 }
121
122 /***
123 Returns true if this receiver is active. */
124 public synchronized boolean isActive() {
125 return active;
126 }
127
128 /***
129 Starts the SocketReceiver with the current options. */
130 public void activateOptions() {
131 if (!isActive()) {
132 rThread = new Thread(this);
133 rThread.setDaemon(true);
134 rThread.start();
135 active = true;
136 }
137 }
138
139 /***
140 Called when the receiver should be stopped. Closes the
141 server socket and all of the open sockets. */
142 public synchronized void shutdown() {
143
144 active = false;
145
146 if (rThread != null) {
147 rThread.interrupt();
148 rThread = null;
149 }
150 doShutdown();
151 }
152
153 /***
154 * Does the actual shutting down by closing the server socket
155 * and any connected sockets that have been created.
156 */
157 private synchronized void doShutdown() {
158 active = false;
159
160 getLogger().debug("{} doShutdown called", getName());
161
162
163 closeServerSocket();
164
165
166 closeAllAcceptedSockets();
167 }
168
169 /***
170 * Closes the server socket, if created.
171 */
172 private void closeServerSocket() {
173 getLogger().debug("{} closing server socket", getName());
174
175 try {
176 if (serverSocket != null) {
177 serverSocket.close();
178 }
179 } catch (Exception e) {
180
181 }
182
183 serverSocket = null;
184 }
185
186 /***
187 * Closes all the connected sockets in the List.
188 */
189 private synchronized void closeAllAcceptedSockets() {
190 for (int x = 0; x < socketList.size(); x++) {
191 try {
192 ((Socket) socketList.get(x)).close();
193 } catch (Exception e) {
194
195 }
196 }
197
198
199 socketList.clear();
200 }
201
202 /***
203 Loop, accepting new socket connections. */
204 public void run() {
205 /***
206 * Ensure we start fresh.
207 */
208 getLogger().debug("performing socket cleanup prior to entering loop for {}", name);
209 closeServerSocket();
210 closeAllAcceptedSockets();
211 getLogger().debug("socket cleanup complete for {}", name);
212 active = true;
213
214
215 try {
216 serverSocket = new ServerSocket(port);
217 } catch (Exception e) {
218 getLogger().error(
219 "error starting SocketReceiver (" + this.getName()
220 + "), receiver did not start", e);
221 active = false;
222 doShutdown();
223
224 return;
225 }
226
227 Socket socket = null;
228
229 try {
230 getLogger().debug("in run-about to enter while isactiveloop");
231
232 active = true;
233
234 while (!rThread.isInterrupted()) {
235
236 if (socket != null) {
237 getLogger().debug("socket not null - creating and starting socketnode");
238 socketList.add(socket);
239
240 XMLSocketNode node = new XMLSocketNode(decoder, socket, this);
241 node.setLoggerRepository(this.repository);
242 new Thread(node).start();
243 socket = null;
244 }
245
246 getLogger().debug("waiting to accept socket");
247
248
249 socket = serverSocket.accept();
250 getLogger().debug("accepted socket");
251 }
252
253
254
255 if (socket != null) {
256 socket.close();
257 }
258 } catch (Exception e) {
259 getLogger().warn(
260 "socket server disconnected, stopping");
261 }
262 }
263
264
265
266
267 public void doPost(LoggingEvent event) {
268 if(!isPaused()){
269 super.doPost(event);
270 }
271 }
272
273
274 }