Added ZeroConf support to most of the network-based appenders and receivers.
To enable ZeroConf advertising of an appender or receiver, a user can now:
- add jmdns jar to their classpath
- set the 'advertiseViaMulticastDNS' param to 'true'
Also added support for discovery of appenders in Chainsaw (Chainsaw will automatically configure a matching receiver when connected).
Supported appenders:
SocketAppender
SocketHubAppender (ZeroConfSocketHubAppender is still functional)
UDPAppender
MulticastAppender
Supported receivers:
SocketReceiver
SocketHubReceiver (also receives events from ZeroConfSocketHubAppender)
XMLSocketReceiver (can receive events sent over TCP by other logging frameworks)
UDPReceiver
MulticastReceiver
Implementation details:
- removed Zeroconf4log4j class, jmdns access is now through the ZeroConfSupport class (class provides support of JmDNS and ServiceInfo creation via reflection, and supports both jmdns 1.0 and jmdns 3.1 apis)
- ZeroConfSupport class is now used by ZeroConfSocketHubAppender, Chainsaw and all appenders & receivers that can advertise their configuration via ZeroConf
- added new 'advertiseViaMulticastDNS' param to the appenders and receivers that support ZeroConf
- updated the ZeroConf site documentation
- updated release notes
- updated the ZeroConfPlugin html file
- tested appenders with 1.0 and 3.1 jmdns jars
- updated log4j references in poms to log4j 1.2.16-snapshot where necessary
For those wanting to add ZeroConf support to third-party appenders and have Chainsaw discover the appenders, the service info naming convention is described here: https://issues.apache.org/bugzilla/show_bug.cgi?id=48907
git-svn-id: https://svn.apache.org/repos/asf/logging/log4j/companions/receivers/trunk@924176 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index c6073f2..ae0aa5b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -217,7 +217,7 @@
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>1.2.15</version>
+ <version>1.2.16-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>javax.jms</groupId>
diff --git a/src/main/java/org/apache/log4j/net/MulticastAppender.java b/src/main/java/org/apache/log4j/net/MulticastAppender.java
index b46f546..de002c5 100644
--- a/src/main/java/org/apache/log4j/net/MulticastAppender.java
+++ b/src/main/java/org/apache/log4j/net/MulticastAppender.java
@@ -22,11 +22,15 @@
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.xml.XMLLayout;
/**
@@ -54,7 +58,13 @@
The default port number for the multicast packets. (9991).
*/
static final int DEFAULT_PORT = 9991;
-
+
+ /**
+ * The MulticastDNS zone advertised by a MulticastAppender
+ * the MulticastAppender also adds a 'multicastAddress' property with the multicast address value as a string
+ */
+ public static final String ZONE = "_log4j_xml_mcast_appender.local.";
+
/**
We remember host name as String in addition to the resolved
InetAddress so that it can be returned via getOption().
@@ -69,7 +79,9 @@
private String encoding;
private boolean locationInfo = false;
-
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
+
public MulticastAppender() {
super(false);
}
@@ -100,11 +112,21 @@
if(remoteHost != null) {
address = getAddressByName(remoteHost);
} else {
- String err = "The RemoteHost property is required for SocketAppender named "+ name;
+ String err = "The RemoteHost property is required for MulticastAppender named "+ name;
LogLog.error(err);
throw new IllegalStateException(err);
}
-
+
+ if (layout == null) {
+ layout = new XMLLayout();
+ }
+
+ if (advertiseViaMulticastDNS) {
+ Map properties = new HashMap();
+ properties.put("multicastAddress", remoteHost);
+ zeroConf = new ZeroConfSupport(ZONE, port, getName(), properties);
+ zeroConf.advertise();
+ }
connect();
super.activateOptions();
}
@@ -120,6 +142,9 @@
}
this.closed = true;
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
cleanUp();
}
@@ -310,4 +335,11 @@
return true;
}
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
+
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
}
diff --git a/src/main/java/org/apache/log4j/net/MulticastReceiver.java b/src/main/java/org/apache/log4j/net/MulticastReceiver.java
index 4788b03..ebba2c2 100644
--- a/src/main/java/org/apache/log4j/net/MulticastReceiver.java
+++ b/src/main/java/org/apache/log4j/net/MulticastReceiver.java
@@ -58,6 +58,13 @@
private MulticastHandlerThread handlerThread;
private MulticastReceiverThread receiverThread;
private boolean paused;
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
+
+ /**
+ * The MulticastDNS zone advertised by a MulticastReceiver
+ */
+ public static final String ZONE = "_log4j_xml_mcast_receiver.local.";
public String getDecoder() {
return decoder;
@@ -96,6 +103,9 @@
public synchronized void shutdown() {
isActive = false;
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
handlerThread.interrupt();
receiverThread.interrupt();
socket.close();
@@ -113,12 +123,6 @@
paused = b;
}
- /**
- Returns true if this receiver is active. */
- public synchronized boolean isActive() {
- return isActive;
- }
-
public void activateOptions() {
InetAddress addr = null;
@@ -151,12 +155,25 @@
receiverThread.start();
handlerThread = new MulticastHandlerThread();
handlerThread.start();
+ if (advertiseViaMulticastDNS) {
+ zeroConf = new ZeroConfSupport(ZONE, port, getName());
+ zeroConf.advertise();
+ }
+
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
- class MulticastHandlerThread extends Thread {
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
+
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
+
+ class MulticastHandlerThread extends Thread {
private List list = new ArrayList();
public MulticastHandlerThread() {
diff --git a/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java b/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java
index 32ff8df..4dec14c 100644
--- a/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java
+++ b/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java
@@ -41,6 +41,7 @@
new PropertyDescriptor("port", MulticastReceiver.class),
new PropertyDescriptor("threshold", MulticastReceiver.class),
new PropertyDescriptor("decoder", MulticastReceiver.class),
+ new PropertyDescriptor("advertiseViaMulticastDNS", MulticastReceiver.class),
};
} catch (Exception e) {
}
diff --git a/src/main/java/org/apache/log4j/net/SocketHubReceiver.java b/src/main/java/org/apache/log4j/net/SocketHubReceiver.java
index bef1095..85058e8 100644
--- a/src/main/java/org/apache/log4j/net/SocketHubReceiver.java
+++ b/src/main/java/org/apache/log4j/net/SocketHubReceiver.java
@@ -63,6 +63,11 @@
*/
protected int reconnectionDelay = DEFAULT_RECONNECTION_DELAY;
+ /**
+ * The MulticastDNS zone advertised by a SocketHubReceiver
+ */
+ public static final String ZONE = "_log4j_obj_tcpconnect_receiver.local.";
+
/**
* Active.
*/
@@ -83,6 +88,9 @@
*/
private List listenerList = Collections.synchronizedList(new ArrayList());
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
+
/**
* Create new instance.
*/
@@ -223,14 +231,6 @@
}
/**
- Returns true if this receiver is active.
- @return true if receiver is active
- */
- public synchronized boolean isActive() {
- return active;
- }
-
- /**
Sets the flag to indicate if receiver is active or not.
@param b new value
*/
@@ -243,6 +243,11 @@
public void activateOptions() {
if (!isActive()) {
setActive(true);
+ if (advertiseViaMulticastDNS) {
+ zeroConf = new ZeroConfSupport(ZONE, port, getName());
+ zeroConf.advertise();
+ }
+
fireConnector(false);
}
}
@@ -269,6 +274,9 @@
connector.interrupted = true;
connector = null; // allow gc
}
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
}
/**
@@ -320,6 +328,14 @@
new Thread(socketNode).start();
}
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
+
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
+
/**
The Connector will reconnect when the server becomes available
again. It does this by attempting to open a new connection every
diff --git a/src/main/java/org/apache/log4j/net/SocketReceiver.java b/src/main/java/org/apache/log4j/net/SocketReceiver.java
index 8e6cfad..9d4aac9 100644
--- a/src/main/java/org/apache/log4j/net/SocketReceiver.java
+++ b/src/main/java/org/apache/log4j/net/SocketReceiver.java
@@ -75,6 +75,12 @@
* Socket list.
*/
private Vector socketList = new Vector();
+
+ /**
+ * The MulticastDNS zone advertised by a SocketReceiver
+ */
+ public static final String ZONE = "_log4j_obj_tcpaccept_receiver.local.";
+
/**
* Listener.
*/
@@ -83,6 +89,8 @@
* Listeners.
*/
private List listenerList = Collections.synchronizedList(new ArrayList());
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
/**
* Create new instance.
@@ -148,6 +156,11 @@
rThread = new Thread(this);
rThread.setDaemon(true);
rThread.start();
+ if (advertiseViaMulticastDNS) {
+ zeroConf = new ZeroConfSupport(ZONE, port, getName());
+ zeroConf.advertise();
+ }
+
active = true;
}
}
@@ -166,6 +179,9 @@
rThread.interrupt();
rThread = null;
}
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
doShutdown();
}
@@ -221,6 +237,22 @@
}
/**
+ Sets the flag to indicate if receiver is active or not.
+ @param b new value
+ */
+ protected synchronized void setActive(final boolean b) {
+ active = b;
+ }
+
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
+
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
+
+ /**
Loop, accepting new socket connections. */
public void run() {
/**
diff --git a/src/main/java/org/apache/log4j/net/UDPAppender.java b/src/main/java/org/apache/log4j/net/UDPAppender.java
index a1ce9f7..55bc6f1 100644
--- a/src/main/java/org/apache/log4j/net/UDPAppender.java
+++ b/src/main/java/org/apache/log4j/net/UDPAppender.java
@@ -20,8 +20,8 @@
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.xml.XMLLayout;
import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.xml.XMLLayout;
import java.io.IOException;
import java.net.DatagramPacket;
@@ -68,11 +68,18 @@
int port = DEFAULT_PORT;
DatagramSocket outSocket;
+ /**
+ * The MulticastDNS zone advertised by a UDPAppender
+ */
+ public static final String ZONE = "_log4j_xml_udp_appender.local.";
+
// if there is something irrecoverably wrong with the settings, there is no
// point in sending out packeets.
boolean inError = false;
-
- public UDPAppender() {
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
+
+ public UDPAppender() {
super(false);
}
@@ -129,6 +136,16 @@
LogLog.error(err);
throw new IllegalStateException(err);
}
+
+ if (layout == null) {
+ layout = new XMLLayout();
+ }
+
+ if (advertiseViaMulticastDNS) {
+ zeroConf = new ZeroConfSupport(ZONE, port, getName());
+ zeroConf.advertise();
+ }
+
super.activateOptions();
}
@@ -142,6 +159,10 @@
return;
}
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
+
this.closed = true;
cleanUp();
}
@@ -199,7 +220,6 @@
}
try {
- // TODO UDPAppender throws NullPointerException if the layout is not set
StringBuffer buf = new StringBuffer(layout.format(event));
byte[] payload;
@@ -300,4 +320,11 @@
return port;
}
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
+
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
}
diff --git a/src/main/java/org/apache/log4j/net/UDPReceiver.java b/src/main/java/org/apache/log4j/net/UDPReceiver.java
index 98567bd..63eb275 100644
--- a/src/main/java/org/apache/log4j/net/UDPReceiver.java
+++ b/src/main/java/org/apache/log4j/net/UDPReceiver.java
@@ -51,8 +51,16 @@
private int port;
private DatagramSocket socket;
UDPHandlerThread handlerThread;
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
- public int getPort() {
+ /**
+ * The MulticastDNS zone advertised by a UDPReceiver
+ */
+ public static final String ZONE = "_log4j_xml_udp_receiver.local.";
+
+
+ public int getPort() {
return port;
}
@@ -91,6 +99,14 @@
paused = b;
}
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
+
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
+
public synchronized void shutdown() {
if(closed == true) {
return;
@@ -102,6 +118,10 @@
socket.close();
}
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
+
try {
if(handlerThread != null) {
handlerThread.close();
@@ -142,6 +162,11 @@
receiverThread.start();
handlerThread = new UDPHandlerThread();
handlerThread.start();
+ if (advertiseViaMulticastDNS) {
+ zeroConf = new ZeroConfSupport(ZONE, port, getName());
+ zeroConf.advertise();
+ }
+
} catch (IOException ioe) {
ioe.printStackTrace();
}
@@ -160,7 +185,7 @@
list.notify();
}
}
-
+
/**
* Allow the UDPHandlerThread to wakeup and exit gracefully.
*/
@@ -177,7 +202,7 @@
synchronized (list) {
try {
while (!UDPReceiver.this.closed && list.size() == 0) {
- list.wait();
+ list.wait(300);
}
if (list.size() > 0) {
diff --git a/src/main/java/org/apache/log4j/net/XMLSocketReceiver.java b/src/main/java/org/apache/log4j/net/XMLSocketReceiver.java
index 55dbcca..fe18758 100644
--- a/src/main/java/org/apache/log4j/net/XMLSocketReceiver.java
+++ b/src/main/java/org/apache/log4j/net/XMLSocketReceiver.java
@@ -60,6 +60,18 @@
private Thread rThread;
public static final int DEFAULT_PORT = 4448;
protected int port = DEFAULT_PORT;
+ private boolean advertiseViaMulticastDNS;
+ private ZeroConfSupport zeroConf;
+
+ /**
+ * The MulticastDNS zone advertised by an XMLSocketReceiver
+ */
+ public static final String ZONE = "_log4j_xml_tcpaccept_receiver.local.";
+
+ /*
+ * Log4j doesn't provide an XMLSocketAppender, but the MulticastDNS zone that should be advertised by one is:
+ * _log4j_xml_tcpconnect_appender.local.
+ */
public XMLSocketReceiver() {
}
@@ -129,11 +141,13 @@
result = result * 37 + port;
return (result * 37 + (getName() != null? getName().hashCode():0));
}
-
+
/**
- Returns true if this receiver is active. */
- public synchronized boolean isActive() {
- return active;
+ Sets the flag to indicate if receiver is active or not.
+ @param b new value
+ */
+ protected synchronized void setActive(final boolean b) {
+ active = b;
}
/**
@@ -143,10 +157,24 @@
rThread = new Thread(this);
rThread.setDaemon(true);
rThread.start();
+
+ if (advertiseViaMulticastDNS) {
+ zeroConf = new ZeroConfSupport(ZONE, port, getName());
+ zeroConf.advertise();
+ }
+
active = true;
}
}
+ public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+ this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+ }
+
+ public boolean isAdvertiseViaMulticastDNS() {
+ return advertiseViaMulticastDNS;
+ }
+
/**
Called when the receiver should be stopped. Closes the
server socket and all of the open sockets. */
@@ -175,6 +203,10 @@
// close all of the accepted sockets
closeAllAcceptedSockets();
+
+ if (advertiseViaMulticastDNS) {
+ zeroConf.unadvertise();
+ }
}
/**