KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > logging > Log4jSocketServer


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.logging;
23
24 import java.net.Socket JavaDoc;
25 import java.net.ServerSocket JavaDoc;
26 import java.net.InetAddress JavaDoc;
27
28 import org.apache.log4j.LogManager;
29 import org.apache.log4j.MDC;
30 import org.apache.log4j.spi.LoggerRepository;
31 import org.apache.log4j.net.SocketNode;
32
33 import org.jboss.system.ServiceMBeanSupport;
34 import org.jboss.system.MissingAttributeException;
35
36 import org.jboss.logging.Logger;
37
38 /**
39  * A Log4j SocketServer service. Listens for client connections on the
40  * specified port and creates a new thread and SocketNode to process the
41  * incoming client log messages.
42  *
43  * <p>
44  * The LoggerRepository can be changed based on the clients address
45  * by using a custom LoggerRepositoryFactory. The default factory
46  * will simply return the current repository.
47  *
48  * @jmx:mbean extends="org.jboss.system.ServiceMBean"
49  *
50  * @version <tt>$Revision: 37459 $</tt>
51  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
52  */

53 public class Log4jSocketServer
54    extends ServiceMBeanSupport
55    implements Log4jSocketServerMBean
56 {
57    /** The port number where the server listens. */
58    protected int port = -1;
59
60    /** The listen backlog count. */
61    protected int backlog = 50;
62
63    /** The address to bind to. */
64    protected InetAddress JavaDoc bindAddress;
65    
66    /** True if the socket listener is enabled. */
67    protected boolean listenerEnabled = true;
68
69    /** The socket listener thread. */
70    protected SocketListenerThread listenerThread;
71
72    /** The server socket which the listener listens on. */
73    protected ServerSocket JavaDoc serverSocket;
74
75    /** The factory to create LoggerRepository's for client connections. */
76    protected LoggerRepositoryFactory loggerRepositoryFactory;
77    
78    /**
79     * @jmx:managed-constructor
80     */

81    public Log4jSocketServer()
82    {
83       super();
84    }
85
86    /**
87     * @jmx:managed-attribute
88     */

89    public void setPort(final int port)
90    {
91       this.port = port;
92    }
93
94    /**
95     * @jmx:managed-attribute
96     */

97    public int getPort()
98    {
99       return port;
100    }
101
102    /**
103     * @jmx:managed-attribute
104     */

105    public void setBacklog(final int backlog)
106    {
107       this.backlog = backlog;
108    }
109
110    /**
111     * @jmx:managed-attribute
112     */

113    public int getBacklog()
114    {
115       return backlog;
116    }
117
118    /**
119     * @jmx:managed-attribute
120     */

121    public void setBindAddress(final InetAddress JavaDoc addr)
122    {
123       this.bindAddress = addr;
124    }
125
126    /**
127     * @jmx:managed-attribute
128     */

129    public InetAddress JavaDoc getBindAddress()
130    {
131       return bindAddress;
132    }
133    
134    /**
135     * @jmx:managed-attribute
136     */

137    public void setListenerEnabled(final boolean enabled)
138    {
139       listenerEnabled = enabled;
140    }
141
142    /**
143     * @jmx:managed-attribute
144     */

145    public boolean setListenerEnabled()
146    {
147       return listenerEnabled;
148    }
149
150    /**
151     * @jmx:managed-attribute
152     */

153    public void setLoggerRepositoryFactoryType(final Class JavaDoc type)
154       throws InstantiationException JavaDoc, IllegalAccessException JavaDoc, ClassCastException JavaDoc
155    {
156       this.loggerRepositoryFactory = (LoggerRepositoryFactory)type.newInstance();
157    }
158
159    /**
160     * @jmx:managed-attribute
161     */

162    public Class JavaDoc getLoggerRepositoryFactoryType()
163    {
164       if (loggerRepositoryFactory == null)
165          return null;
166       return loggerRepositoryFactory.getClass();
167    }
168
169    /**
170     * @jmx:managed-operation
171     */

172    public LoggerRepository getLoggerRepository(final InetAddress JavaDoc addr)
173    {
174       return loggerRepositoryFactory.create(addr);
175    }
176    
177
178    ///////////////////////////////////////////////////////////////////////////
179
// Socket Listener //
180
///////////////////////////////////////////////////////////////////////////
181

182    protected class SocketListenerThread
183       extends Thread JavaDoc
184    {
185       protected Logger log = Logger.getLogger(SocketListenerThread.class);
186       protected boolean enabled;
187       protected boolean shuttingDown;
188       protected Object JavaDoc lock = new Object JavaDoc();
189       
190       public SocketListenerThread(final boolean enabled)
191       {
192          super("SocketListenerThread");
193
194          this.enabled = enabled;
195       }
196
197       public void setEnabled(boolean enabled)
198       {
199          this.enabled = enabled;
200
201          synchronized (lock)
202          {
203             lock.notifyAll();
204          }
205          log.debug("Notified that enabled: " + enabled);
206       }
207
208       public void shutdown()
209       {
210          enabled = false;
211          shuttingDown = true;
212
213          synchronized (lock)
214          {
215             lock.notifyAll();
216          }
217          log.debug("Notified to shutdown");
218       }
219       
220       public void run()
221       {
222          while (!shuttingDown)
223          {
224             
225             if (!enabled)
226             {
227                try
228                {
229                   log.debug("Disabled, waiting for notification");
230                   synchronized (lock)
231                   {
232                      lock.wait();
233                   }
234                }
235                catch (InterruptedException JavaDoc ignore)
236                {
237                }
238             }
239
240             try
241             {
242                doRun();
243             }
244             catch (Throwable JavaDoc e)
245             {
246                log.error("Exception caught from main loop; ignoring", e);
247             }
248          }
249       }
250
251       protected void doRun() throws Exception JavaDoc
252       {
253          while (enabled)
254          {
255             Socket JavaDoc socket = serverSocket.accept();
256             InetAddress JavaDoc addr = socket.getInetAddress();
257             log.debug("Connected to client at " + addr);
258
259             LoggerRepository repo = getLoggerRepository(addr);
260             log.debug("Using repository: " + repo);
261
262             //
263
// jason: may want to expose socket node as an MBean for management
264
//
265

266             log.debug("Starting new socket node");
267             SocketNode node = new SocketNode(socket, repo);
268             /* Create a thread with and MDC.host value set to the client
269             hostname to allow for distiguished output
270             */

271             String JavaDoc clientHost = addr.getHostName();
272             SocketThread thread = new SocketThread(node, clientHost);
273             thread.start();
274             log.debug("Socket node started");
275          }
276       }
277    }
278
279    static class SocketThread
280       extends Thread JavaDoc
281    {
282       String JavaDoc host;
283
284       SocketThread(Runnable JavaDoc target, String JavaDoc host)
285       {
286          super(target, host+" LoggingEvent Thread");
287          this.host = host;
288       }
289       public void run()
290       {
291          MDC.put("host", host);
292          super.run();
293       }
294    }
295
296    ///////////////////////////////////////////////////////////////////////////
297
// LoggerRepositoryFactory //
298
///////////////////////////////////////////////////////////////////////////
299

300    public static interface LoggerRepositoryFactory
301    {
302       public LoggerRepository create(InetAddress JavaDoc addr);
303    }
304
305    /**
306     * A simple LoggerRepository factory which simply returns
307     * the current repository from the LogManager.
308     */

309    public static class DefaultLoggerRepositoryFactory
310       implements LoggerRepositoryFactory
311    {
312       private LoggerRepository repo;
313       
314       public LoggerRepository create(final InetAddress JavaDoc addr)
315       {
316          if (repo == null)
317             repo = LogManager.getLoggerRepository();
318          return repo;
319       }
320    }
321    
322    ///////////////////////////////////////////////////////////////////////////
323
// Service Overrides //
324
///////////////////////////////////////////////////////////////////////////
325

326    protected void createService() throws Exception JavaDoc
327    {
328       listenerThread = new SocketListenerThread(false);
329       listenerThread.setDaemon(true);
330       listenerThread.start();
331       log.debug("Socket listener thread started");
332
333       if (loggerRepositoryFactory == null)
334       {
335          log.debug("Using default logger repository factory");
336          loggerRepositoryFactory = new DefaultLoggerRepositoryFactory();
337       }
338    }
339       
340    protected void startService() throws Exception JavaDoc
341    {
342       if (port == -1)
343          throw new MissingAttributeException("Port");
344
345       // create a new server socket to handle port number changes
346
if (bindAddress == null)
347       {
348          serverSocket = new ServerSocket JavaDoc(port, backlog);
349       }
350       else
351       {
352          serverSocket = new ServerSocket JavaDoc(port, backlog, bindAddress);
353       }
354
355       log.info("Listening on " + serverSocket);
356       
357       listenerThread.setEnabled(listenerEnabled);
358    }
359
360    protected void stopService() throws Exception JavaDoc
361    {
362       listenerThread.setEnabled(false);
363    }
364
365    protected void destroyService() throws Exception JavaDoc
366    {
367       listenerThread.shutdown();
368       listenerThread = null;
369       serverSocket = null;
370    }
371 }
372
Popular Tags