View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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    //default to log4j xml decoder
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     // mark this as no longer running
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       // close the server socket
163       closeServerSocket();
164 
165       // close all of the accepted sockets
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          // ignore for now
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            // ignore for now
195          }
196        }
197 
198        // clear member variables
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     // start the server socket
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         // if we have a socket, start watching it
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         // wait for a socket to open, then loop to start it
249         socket = serverSocket.accept();
250         getLogger().debug("accepted socket");
251       }
252 
253       // socket not watched because we a no longer running
254       // so close it now.
255       if (socket != null) {
256         socket.close();
257       }
258     } catch (Exception e) {
259       getLogger().warn(
260         "socket server disconnected, stopping");
261     }
262   }
263 
264   /* (non-Javadoc)
265    * @see org.apache.log4j.plugins.Receiver#doPost(org.apache.log4j.spi.LoggingEvent)
266    */
267   public void doPost(LoggingEvent event) {
268     if(!isPaused()){
269       super.doPost(event);
270     }
271   }
272 
273 
274 }