Here is the latest edition of the new Watchdog design and implementation. I have gone through a number of iterations since the original version and I think I have incorporated all of the initial feedback. I gave up on my earlier thoughts on "passive" vs "active" watchdogs. I decided that there was no reason to introduce that confusion to the design. But I did make some changes to accomadate both types, as I hope you will see.
Watchdog.java - Now implemented as an interface. Requires implementations to support name and configurator class name properties as well as startWatching() and stopWatching() methods. WatchdogBase.java - Abstract base implementation of Watchdog interface using threads and the Runnable interface. This is the base implementation used for all of the current watchdogs implemented for log4j, but developers can create their own to suit their needs. This implementation requires subclasses to implement the methods reconfigure() and checkForReconfiguration(). The checkForReconfiguration() generalizes the concept of "get modification time". It should return "true" if the watchdog has found updated configuration data. The subclass can now do whatever is required to check for new configuration data. It might depend on a modification date, or it might depend on something else altogether. This class also implements three helper methods that subclasses can take advantage of: getConfiguratorClass(), reconfigureByURL(), and reconfigureByInputStream(). I am remaining agnostic on the topic of whether a URL and/or an InputStream is required to reconfigure. Both options are available to subclasses as they need them, the base class does not enforce one over the other. URLWatchdogBase.java - Abstract base implementation that extends WatchdogBase to include the setting of url, interval, and modification time properties. It also implements the reconfigure() method to call the reconfigureByURL() helper method. This class is the base class that can be used to implement a watchdog that watches a url entity, where ever, what ever it might be. FileWatchdog.java - Implementation that extends URLWatchdogBase to watch a configuration file located on the file system. Implements the checkForReconfiguration() method in the usual way that has been implemented before. Please note that the wait interval is handled at the end of this method if the watched file has not been modified. The wait interval is no longer handled in the main loop (now implemented in WatchdogBase.java). It is up to subclasses of WatchdogBase to handle the wait interval. This class also overrides the setup() and cleanup() methods (defined in WatchdogBase.java) to create and release the file object used to describe the configuration file to watch. HttpWatchdog.java - Implementation that extends URLWatchdogBase to watch a configuration file located on a web server. Pretty much the same as FileWatchdog, but checks the Last-Modified time in the response header for the modification time. SocketWatchdog.java - Implementation that extends WatchdogBase to implement a new kind of Watchdog. It creates a ServerSocket on a given port number and then watches for new sockets opened on it. When a socket is accepted, the socket's InputStream is used to reconfigure log4j. The setup() and cleanup() methods are written to create and close the ServerSocket. checkForReconfiguration() is written to call the accept() method of the ServerSocket, waiting for new sockets to be opened. reconfigure() has been written to grab the InputStream from the socket and call the reconfigureByInputStream() method to reconfigure log4j. DOMConfigurator.java - Same modifications as before, but now added some code to convert the file name to a URL, prepending "file:" to the start of it. PropertyConfigurator.java - Ditto plus the added doConfigure(InputStream) method. WatchdogTester.java - This is some very rough code that I have been using to test the watchdog implementation and functionality. You'll have to look at the code to figure out the command line you can use to test each watchdog. Or you can write your own code to do it. ReconfigureViaSocket.java - This is some rough code I use to test the SocketWatchdog. It basically opens a socket and stuffs configuration data (from a specified file) into an OutputStream. If you have a SocketWatchdog configured to watch the same socket port, it gets the data and reconfigures. This class could morph into an example of sending configuration data via sockets. Issues: 1) I have removed the static methods that were being used to keep track of and stop all the active watchdogs. Do we want to have a WatchdogManager? If so, then how do we guarantee that Watchdogs get added to the active list if Watchdog.java is an interface? Seems to me that it would require that Watchdog.java be an abstract class with final methods for startWatching() and stopWatching(). These methods could then make calls to the Watchdog manager statc methods to add/remove watchdogs. I would appreciate some feedback on this. We really only need the manager class if it is ever planned to include watchdogs in configuration files. Otherwise, it can be left as an effort for the developer to keep track of their watchdogs any way they want. 2) If Watchdog.java remains an interface, what should be its package name? org.apache.log4j.spi? 3) I would like the Watchdog interface to contain the reconfigure() method definition, but then it will be required to be public. reconfigure() should not be public as it should only be called after it has been decided that new configuration data is available. So, unless there are other ideas, I'm going to leave it out of the interface. 4) I am hoping that the SocketWatchdog class will help explain why I feel just having a doConfigure(URL) method in the Configurator interface is not sufficient. A URL will not work in this case, right? All it has is a socket with the InputStream of data. There is no url...or can I somehow specify the socket as a url? And if the configurator supports url (as it is now required), it could also support an InputStream with little trouble, I think. And if doConfigure(InputStream) is in the Configurator interface, then the Watchdog would not need to use reflection to find the right method. But either way, I am fine with it. 5) I have tested and used FileWatchdog, HttpWatchdog, and SocketWatchdog. They seem to work as advertised, but there may still be more lingering bugs. Use with care. I would also like more feedback regarding the design and implementation. Thanks, -Mark
watchdog.zip
Description: Binary data
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>