Author: psmith
Date: Sun Nov 13 18:42:22 2005
New Revision: 344022

URL: http://svn.apache.org/viewcvs?rev=344022&view=rev
Log:
Added basic workings of a Zeroconf-enabled SocketHubAppender.

Right now this is being treated as a separate source folder
for consideration for adding to the main log4j repo (as optional)
after discussions with the group and further testing.

Chainsaw will be configured to listen for these Zeroconf events
and be able to provide the user with a dead-simple connection mechanism
(double click on an icon to auto-create the approriate Receiver).

At this stage I am not clear whether the approach should be a subclass
as I have done here, if there are more Appenders that might benefit from
something like this, then perhaps a central factory object can be
used to manufacture the events (log4j plugin?), but how it is currently
is probably useful for the time being.

Added:
    logging/chainsaw/trunk/tests/org/apache/log4j/net/
    logging/chainsaw/trunk/tests/org/apache/log4j/net/ModifiableBoolean.java
    
logging/chainsaw/trunk/tests/org/apache/log4j/net/ZeroConfSocketHubAppenderTest.java
    logging/chainsaw/trunk/zeroconf/
    logging/chainsaw/trunk/zeroconf/org/
    logging/chainsaw/trunk/zeroconf/org/apache/
    logging/chainsaw/trunk/zeroconf/org/apache/log4j/
    logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/
    
logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/ZeroConfSocketHubAppender.java
    logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/Zeroconf4log4j.java

Added: logging/chainsaw/trunk/tests/org/apache/log4j/net/ModifiableBoolean.java
URL: 
http://svn.apache.org/viewcvs/logging/chainsaw/trunk/tests/org/apache/log4j/net/ModifiableBoolean.java?rev=344022&view=auto
==============================================================================
--- logging/chainsaw/trunk/tests/org/apache/log4j/net/ModifiableBoolean.java 
(added)
+++ logging/chainsaw/trunk/tests/org/apache/log4j/net/ModifiableBoolean.java 
Sun Nov 13 18:42:22 2005
@@ -0,0 +1,26 @@
+package org.apache.log4j.net;
+
+/**
+ * A wrapper class that allows modifiable values, totally <b>not</b> 
Thread-safe.
+ * 
+ * Useful if you want to hold a reference to a value in a final block for 
inner classes
+ * and flip the value for later testing.
+ * @author paulsmith
+ *
+ */
+public class ModifiableBoolean {
+
+    private boolean value = false;
+    
+    public void setValue(boolean value) {
+        this.value = value;
+    }
+    
+    public boolean isSet() {
+        return value;
+    }
+    
+    public void flip() {
+        this.value = !this.value;
+    }
+}

Added: 
logging/chainsaw/trunk/tests/org/apache/log4j/net/ZeroConfSocketHubAppenderTest.java
URL: 
http://svn.apache.org/viewcvs/logging/chainsaw/trunk/tests/org/apache/log4j/net/ZeroConfSocketHubAppenderTest.java?rev=344022&view=auto
==============================================================================
--- 
logging/chainsaw/trunk/tests/org/apache/log4j/net/ZeroConfSocketHubAppenderTest.java
 (added)
+++ 
logging/chainsaw/trunk/tests/org/apache/log4j/net/ZeroConfSocketHubAppenderTest.java
 Sun Nov 13 18:42:22 2005
@@ -0,0 +1,68 @@
+package org.apache.log4j.net;
+
+import javax.jmdns.JmDNS;
+import javax.jmdns.ServiceEvent;
+import javax.jmdns.ServiceListener;
+
+import junit.framework.TestCase;
+
+/**
+ * Some test methods to validate that the ZeroConf stuff works as 
expected/advertised
+ * 
+ * @author psmith
+ *
+ */
+public class ZeroConfSocketHubAppenderTest extends TestCase {
+
+    private static final int DEFAULT_TIMEOUT_FOR_ZEROCONF_EVENTS_TO_APPEAR = 
2000;
+
+    /**
+     * This does a simple test, as a test harness, to make sure the Appender 
can be created
+     * and that it can shutdown appropriately.  in older versions of JmDNS a 
non-daemon thread
+     * could hold the JVM open preventing it from shutting down.
+     * 
+     * @see com.strangeberry.jmdns.tools.Main for a ZeroConf Network browser 
in Swing allowing you to see the broadcasts
+     * 
+     * @throws Exception
+     */
+    public void testSimpleTest() throws Exception {
+        JmDNS jmdns = Zeroconf4log4j.getInstance();
+        
+        final ModifiableBoolean addedFlag = new ModifiableBoolean();
+        final ModifiableBoolean removedFlag = new ModifiableBoolean();
+        
+        /**
+         * This is just a test to make sure I'm not stupid.
+         */
+        assertTrue(!addedFlag.isSet());
+        assertTrue(!removedFlag.isSet());
+        
+        
jmdns.addServiceListener(ZeroConfSocketHubAppender.DEFAULT_ZEROCONF_ZONE, new 
ServiceListener() {
+
+            public void serviceAdded(ServiceEvent event) {
+                addedFlag.setValue(true);
+               
+            }
+
+            public void serviceRemoved(ServiceEvent event) {
+                removedFlag.setValue(true);
+            }
+
+            public void serviceResolved(ServiceEvent event) {
+                
+            }});
+        ZeroConfSocketHubAppender appender = new ZeroConfSocketHubAppender();
+        appender.setZeroConfDeviceName("SimpleTest");
+        appender.activateOptions();
+        
+        Thread.sleep(DEFAULT_TIMEOUT_FOR_ZEROCONF_EVENTS_TO_APPEAR);
+        
+        assertTrue("Should have detected the addition", addedFlag.isSet());
+        
+        appender.close();
+        Zeroconf4log4j.shutdown();
+        
+        Thread.sleep(DEFAULT_TIMEOUT_FOR_ZEROCONF_EVENTS_TO_APPEAR);
+        
+    }
+}

Added: 
logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/ZeroConfSocketHubAppender.java
URL: 
http://svn.apache.org/viewcvs/logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/ZeroConfSocketHubAppender.java?rev=344022&view=auto
==============================================================================
--- 
logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/ZeroConfSocketHubAppender.java
 (added)
+++ 
logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/ZeroConfSocketHubAppender.java
 Sun Nov 13 18:42:22 2005
@@ -0,0 +1,87 @@
+package org.apache.log4j.net;
+
+import java.io.IOException;
+
+import javax.jmdns.JmDNS;
+import javax.jmdns.ServiceInfo;
+
+
+/**
+ * A sub-class of SocketHubAppender that broadcasts its configuration via 
Zeroconf.
+ * 
+ * This allows Zeroconf aware applications such as Chainsaw to be able to 
detect them, and automatically configure
+ * themselves to be able to connect to them.
+ * 
+ * @author psmith
+ *
+ */
+public class ZeroConfSocketHubAppender extends SocketHubAppender {
+
+    public static final String DEFAULT_ZEROCONF_ZONE="_log4j._tcp.local.";
+    private String zeroConfZone = DEFAULT_ZEROCONF_ZONE;
+    
+    private String zeroConfDeviceName = "SocketHubAppender";
+    
+    public void activateOptions() {
+        super.activateOptions();
+        
+        try {
+            JmDNS jmDNS = Zeroconf4log4j.getInstance();
+            ServiceInfo info = new ServiceInfo(zeroConfZone, 
zeroConfDeviceName, getPort(), "SocketHubAppender on port " + getPort() );
+            getLogger().info("Registering this SocketHubAppender as :" + info);
+            jmDNS.registerService(info);
+        } catch (IOException e) {
+            getLogger().error("Failed to instantiate JmDNS to broadcast via 
ZeroConf, will now operate in simple SocketHubAppender mode");
+        }
+        
+    }
+
+    /**
+     * Sets the name of this appender as it would appear in a ZeroConf browser.
+     * @see #setZeroConfDeviceName(String)
+     * @return String deviceName
+     */
+    public String getZeroConfDeviceName() {
+        return zeroConfDeviceName;
+    }
+
+
+
+
+    /**
+     * Configures the name/label of this appender so that it will appear 
nicely in a ZeroConf browser, the default
+     * being "SocketHubAppender"
+     * @param zeroConfDeviceName
+     */
+    public void setZeroConfDeviceName(String zeroConfDeviceName) {
+        this.zeroConfDeviceName = zeroConfDeviceName;
+    }
+
+
+
+
+    /**
+     * Returns the ZeroConf domain that will be used to register this 'device'.
+     * 
+     * @return String ZeroConf zone
+     */
+    public String getZeroConfZone() {
+        return zeroConfZone;
+    }
+
+
+    /**
+     * Sets the ZeroConf zone to register this device under, BE CAREFUL with 
this value
+     * as ZeroConf has some weird naming conventions, it should start with an 
"_" and end in a ".",
+     * if you're not sure about this value might I suggest that you leave it 
at the default value
+     * which is specified in [EMAIL PROTECTED] #DEFAULT_ZEROCONF_ZONE }.
+     * 
+     * This method does NO(0, zero, pun not intended) checks on this value.
+     * 
+     * @param zeroConfZone
+     */
+    public void setZeroConfZone(String zeroConfZone) {
+//        TODO work out a sane checking mechanism that verifies the value is a 
correct ZeroConf zone
+        this.zeroConfZone = zeroConfZone;
+    }
+}

Added: logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/Zeroconf4log4j.java
URL: 
http://svn.apache.org/viewcvs/logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/Zeroconf4log4j.java?rev=344022&view=auto
==============================================================================
--- logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/Zeroconf4log4j.java 
(added)
+++ logging/chainsaw/trunk/zeroconf/org/apache/log4j/net/Zeroconf4log4j.java 
Sun Nov 13 18:42:22 2005
@@ -0,0 +1,58 @@
+package org.apache.log4j.net;
+
+import javax.jmdns.JmDNS;
+
+/**
+ * This singleton holds the single instance of the JmDNS instance that is used 
to broadcast
+ * Appender related information via ZeroConf.  Once referenced, a single JmDNS 
instance is created
+ * and held.  To ensure your JVM exits cleanly you should ensure that you call 
the [EMAIL PROTECTED] #shutdown() } method
+ * to broadcast the disappearance of your devices, and cleanup sockets.  
(alternatively you can call the close() 
+ * method on the JmDNS instead, totally up to you...)
+ * 
+ * See http://jmdns.sf.net for more information about JmDNS and ZeroConf.
+ * 
+ * @author psmith
+ *
+ */
+public class Zeroconf4log4j {
+
+    private static final JmDNS instance;
+
+    static {
+        try {
+            instance = new JmDNS();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Failed to initialize JmDNS");
+        }
+    }
+
+    /**
+     * Returns the current instance of the JmDNS being used by log4j.
+     * 
+     * @throws IllegalStateException if JmDNS was not correctly initialized.
+     * 
+     * @return
+     */
+    public static JmDNS getInstance() {
+        checkState();
+        return instance;
+    }
+
+    private static void checkState() {
+        if (instance == null) {
+            throw new IllegalStateException(
+                    "JmDNS did not initialize correctly");
+        }
+    }
+    
+    /**
+     * Ensures JmDNS cleanly broadcasts 'goodbye' and closes any sockets, and 
(more imporantly)
+     * ensures some Threads exit so your JVM can exit.
+     *
+     */
+    public static void shutdown() {
+        checkState();
+        instance.close();
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to