From c4578dc062e7610f400f33f1ad4bbdfc5aab532c Mon Sep 17 00:00:00 2001
From: Lennart Koopmann Usage examples: Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+ * of the LGPL license is available in the META-INF folder in all
+ * distributions of Syslog4j and in the base directory of the "doc" ZIP. First, create an implementation of SyslogConfigIF, such as UdpNetSyslogConfig. Second, configure that configuration instance. Third, call createInstance(protocol,config) using a short & simple
+ * String for the protocol argument. Fourth, either use the returned instance of SyslogIF, or in later code
+ * call getInstance(protocol) with the protocol chosen in the previous step. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Implementing the down(SyslogIF) method is an excellent way to add some sort of notification to
+* your application when a Syslog service is unavailable. Implementing the up(SyslogIF) method can be used to notify your application when a Syslog
+* service has returned. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+ * of the LGPL license is available in the META-INF folder in all
+ * distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. When used in "threaded" mode (see TCPNetSyslogConfig for the option),
+* a queuing mechanism is used (via LinkedList). Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Note: Syslog4jAppender does NOT extend Log4j's SyslogAppender. Example log4j.xml configuration: All available parameters are: Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+ * of the LGPL license is available in the META-INF folder in all
+ * distributions of Syslog4j and in the base directory of the "doc" ZIP. Classes which inherit Syslog4jAppenderSkeleton must implement the "initialize()" method,
+ * which sets up Syslog4j for use by the Log4j Appender. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+ * of the LGPL license is available in the META-INF folder in all
+ * distributions of Syslog4j and in the base directory of the "doc" ZIP. More information on the PCI DSS specification is available here: https://www.pcisecuritystandards.org/security_standards/pci_dss.shtml Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. This modifier is useful for applications that display log content in browsers without
+* properly escaping HTML characters. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. More information on the PCI DSS specification is available here: https://www.pcisecuritystandards.org/security_standards/pci_dss.shtml The PCI DSS specification is Copyright 2008 PCI Security Standards
+* Council LLC. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. More information on the PCI DSS specification is available here: https://www.pcisecuritystandards.org/security_standards/pci_dss.shtml The PCI DSS specification is Copyright 2008 PCI Security Standards
+* Council LLC. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Those wishing to replace (or improve upon) this implementation
+* can write a custom SyslogMessageProcessorIF and set it per
+* instance via the SyslogIF.setMessageProcessor(..) method or set it globally
+* via the SyslogMessageProcessor.setDefault(..) method. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. http://tools.ietf.org/html/draft-ietf-syslog-protocol-23 Those wishing to replace (or improve upon) this implementation
+ * can write a custom SyslogMessageProcessorIF and set it per
+ * instance via the SyslogIF.setStructuredMessageProcessor(..) method or set it globally
+ * via the StructuredSyslogMessageProcessor.setDefault(..) method.
+ * Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy of the
+ * LGPL license is available in the META-INF folder in all distributions of
+ * Syslog4j and in the base directory of the "doc" ZIP.
+ *
+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
+ *
+ * Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy of the
+ * LGPL license is available in the META-INF folder in all distributions of
+ * Syslog4j and in the base directory of the "doc" ZIP.
+ *
+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
+ *
+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
+ *
+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
+ *
+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
+ * Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP. Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy
+* of the LGPL license is available in the META-INF folder in all
+* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+ * Syslog.getInstance("udp").info("log message");
+ *
+ *
+ * Via Instance
+ *
+ * SyslogIF syslog = Syslog.getInstance("udp");
+ * syslog.info();
+ *
+ *
+ *
+ *
+ *
+ *
+ <appender name="Syslog4j" class="org.productivity.java.syslog4j.impl.log4j.Syslog4jAppender">
+ <param name="Facility" value="user"/>
+ <param name="Protocol" value="tcp"/>
+ <param name="Host" value="192.168.0.1"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m"/>
+ </layout>
+ </appender>
+ *
+ *
+ *
+ *
+ *
Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: AbstractNetSyslogConfig.java,v 1.12 2010/10/25 03:50:25 cvs Exp $ +*/ +public abstract class AbstractNetSyslogConfig extends AbstractSyslogConfig implements AbstractNetSyslogConfigIF { + private static final long serialVersionUID = 7240133962159244924L; + + protected String host = SYSLOG_HOST_DEFAULT; + protected int port = SYSLOG_PORT_DEFAULT; + + protected boolean cacheHostAddress = CACHE_HOST_ADDRESS_DEFAULT; + + protected int maxQueueSize = MAX_QUEUE_SIZE_DEFAULT; + + public AbstractNetSyslogConfig() { + // + } + + public AbstractNetSyslogConfig(int facility) { + this.facility = facility; + } + + public AbstractNetSyslogConfig(int facility, String host) { + this.facility = facility; + this.host = host; + } + + public AbstractNetSyslogConfig(String host) { + this.host = host; + } + + public AbstractNetSyslogConfig(int facility, String host, int port) { + this.facility = facility; + this.host = host; + this.port = port; + } + + public AbstractNetSyslogConfig(String host, int port) { + this.host = host; + this.port = port; + } + + public boolean isCacheHostAddress() { + return this.cacheHostAddress; + } + + public void setCacheHostAddress(boolean cacheHostAddress) { + this.cacheHostAddress = cacheHostAddress; + } + + public String getHost() { + return this.host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return this.port; + } + + public void setPort(int port) { + this.port = port; + } + + public int getMaxQueueSize() { + return maxQueueSize; + } + + public void setMaxQueueSize(int maxQueueSize) { + this.maxQueueSize = maxQueueSize; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfigIF.java b/src/main/java/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfigIF.java new file mode 100644 index 0000000..17d7940 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfigIF.java @@ -0,0 +1,19 @@ +package org.productivity.java.syslog4j.impl.net; + +import org.productivity.java.syslog4j.impl.AbstractSyslogConfigIF; + +/** +* AbstractNetSyslogConfigIF is a configuration interface supporting network-based +* Syslog implementations. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: AbstractNetSyslogConfigIF.java,v 1.4 2009/06/06 19:11:02 cvs Exp $ +*/ +public interface AbstractNetSyslogConfigIF extends AbstractSyslogConfigIF { + public boolean isCacheHostAddress(); + public void setCacheHostAddress(boolean cacheHostAddress); +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslog.java new file mode 100644 index 0000000..9d3e949 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslog.java @@ -0,0 +1,91 @@ +package org.productivity.java.syslog4j.impl.net.tcp; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; +import org.productivity.java.syslog4j.impl.net.AbstractNetSyslog; + +/** +* TCPNetSyslog is an extension of AbstractSyslog that provides support for +* TCP/IP-based syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslog.java,v 1.21 2010/11/28 04:43:31 cvs Exp $ +*/ +public class TCPNetSyslog extends AbstractNetSyslog { + private static final long serialVersionUID = -2157528355215068721L; + + protected TCPNetSyslogWriter writer = null; + + protected TCPNetSyslogConfigIF tcpNetSyslogConfig = null; + + public void initialize() throws SyslogRuntimeException { + super.initialize(); + + try { + this.tcpNetSyslogConfig = (TCPNetSyslogConfigIF) this.syslogConfig; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must implement interface TCPNetSyslogConfigIF"); + } + } + + public AbstractSyslogWriter getWriter() { + return getWriter(true); + } + + public synchronized AbstractSyslogWriter getWriter(boolean create) { + if (this.writer != null || !create) { + return this.writer; + } + + this.writer = (TCPNetSyslogWriter) createWriter(); + + if (this.tcpNetSyslogConfig.isThreaded()) { + createWriterThread(this.writer); + } + + return this.writer; + } + + protected void write(int level, byte[] message) throws SyslogRuntimeException { + AbstractSyslogWriter syslogWriter = getWriter(); + + try { + if (syslogWriter.hasThread()) { + syslogWriter.queue(level,message); + + } else { + synchronized(syslogWriter) { + syslogWriter.write(message); + } + } + + } finally { + returnWriter(syslogWriter); + } + } + + public void flush() throws SyslogRuntimeException { + AbstractSyslogWriter syslogWriter = getWriter(false); + + if (syslogWriter != null) { + syslogWriter.flush(); + } + } + + public void shutdown() throws SyslogRuntimeException { + AbstractSyslogWriter syslogWriter = getWriter(false); + + if (syslogWriter != null) { + syslogWriter.shutdown(); + } + } + + public void returnWriter(AbstractSyslogWriter syslogWriter) { + // + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfig.java new file mode 100644 index 0000000..49d8436 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfig.java @@ -0,0 +1,156 @@ +package org.productivity.java.syslog4j.impl.net.tcp; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.impl.net.AbstractNetSyslogConfig; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* TCPNetSyslogConfig is an extension of AbstractNetSyslogConfig that provides +* configuration support for TCP/IP-based syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslogConfig.java,v 1.18 2010/10/29 03:14:12 cvs Exp $ +*/ +public class TCPNetSyslogConfig extends AbstractNetSyslogConfig implements TCPNetSyslogConfigIF { + private static final long serialVersionUID = 9023152050686365460L; + + public static byte[] SYSTEM_DELIMITER_SEQUENCE = null; + + static { + String delimiterSequence = System.getProperty("line.separator"); + + SYSTEM_DELIMITER_SEQUENCE = delimiterSequence.getBytes(); + + if (SYSTEM_DELIMITER_SEQUENCE == null || SYSTEM_DELIMITER_SEQUENCE.length < 1) { + SYSTEM_DELIMITER_SEQUENCE = SyslogConstants.TCP_DELIMITER_SEQUENCE_DEFAULT; + } + } + + protected byte[] delimiterSequence = SYSTEM_DELIMITER_SEQUENCE; + + protected boolean persistentConnection = TCP_PERSISTENT_CONNECTION_DEFAULT; + + protected boolean soLinger = TCP_SO_LINGER_DEFAULT; + protected int soLingerSeconds = TCP_SO_LINGER_SECONDS_DEFAULT; + + protected boolean keepAlive = TCP_KEEP_ALIVE_DEFAULT; + + protected boolean reuseAddress = TCP_REUSE_ADDRESS_DEFAULT; + + protected boolean setBufferSize = TCP_SET_BUFFER_SIZE_DEFAULT; + + protected int freshConnectionInterval = TCP_FRESH_CONNECTION_INTERVAL_DEFAULT; + + public TCPNetSyslogConfig() { + initialize(); + } + + protected void initialize() { + // + } + + public TCPNetSyslogConfig(int facility, String host, int port) { + super(facility, host, port); + initialize(); + } + + public TCPNetSyslogConfig(int facility, String host) { + super(facility, host); + initialize(); + } + + public TCPNetSyslogConfig(int facility) { + super(facility); + initialize(); + } + + public TCPNetSyslogConfig(String host, int port) { + super(host, port); + initialize(); + } + + public TCPNetSyslogConfig(String host) { + super(host); + initialize(); + } + + public Class getSyslogClass() { + return TCPNetSyslog.class; + } + + public byte[] getDelimiterSequence() { + return this.delimiterSequence; + } + + public void setDelimiterSequence(byte[] delimiterSequence) { + this.delimiterSequence = delimiterSequence; + } + + public void setDelimiterSequence(String delimiterSequence) { + this.delimiterSequence = SyslogUtility.getBytes(this,delimiterSequence); + } + + public boolean isPersistentConnection() { + return this.persistentConnection; + } + + public void setPersistentConnection(boolean persistentConnection) { + this.persistentConnection = persistentConnection; + } + + public boolean isSoLinger() { + return this.soLinger; + } + + public void setSoLinger(boolean soLinger) { + this.soLinger = soLinger; + } + + public int getSoLingerSeconds() { + return this.soLingerSeconds; + } + + public void setSoLingerSeconds(int soLingerSeconds) { + this.soLingerSeconds = soLingerSeconds; + } + + public boolean isKeepAlive() { + return this.keepAlive; + } + + public void setKeepAlive(boolean keepAlive) { + this.keepAlive = keepAlive; + } + + public boolean isReuseAddress() { + return this.reuseAddress; + } + + public void setReuseAddress(boolean reuseAddress) { + this.reuseAddress = reuseAddress; + } + + public boolean isSetBufferSize() { + return this.setBufferSize; + } + + public void setSetBufferSize(boolean setBufferSize) { + this.setBufferSize = setBufferSize; + } + + public int getFreshConnectionInterval() { + return freshConnectionInterval; + } + + public void setFreshConnectionInterval(int freshConnectionInterval) { + this.freshConnectionInterval = freshConnectionInterval; + } + + public Class getSyslogWriterClass() { + return TCPNetSyslogWriter.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfigIF.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfigIF.java new file mode 100644 index 0000000..82318ad --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfigIF.java @@ -0,0 +1,40 @@ +package org.productivity.java.syslog4j.impl.net.tcp; + +import org.productivity.java.syslog4j.impl.net.AbstractNetSyslogConfigIF; + +/** +* TCPNetSyslogConfigIF is a configuration interface supporting TCP/IP-based +* Syslog implementations. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslogConfigIF.java,v 1.6 2010/10/29 03:14:12 cvs Exp $ +*/ +public interface TCPNetSyslogConfigIF extends AbstractNetSyslogConfigIF { + public byte[] getDelimiterSequence(); + public void setDelimiterSequence(byte[] delimiterSequence); + + public boolean isPersistentConnection(); + public void setPersistentConnection(boolean persistentConnection); + + public boolean isSoLinger(); + public void setSoLinger(boolean soLinger); + + public int getSoLingerSeconds(); + public void setSoLingerSeconds(int soLingerSeconds); + + public boolean isKeepAlive(); + public void setKeepAlive(boolean keepAlive); + + public boolean isReuseAddress(); + public void setReuseAddress(boolean reuseAddress); + + public boolean isSetBufferSize(); + public void setSetBufferSize(boolean setBufferSize); + + public int getFreshConnectionInterval(); + public void setFreshConnectionInterval(int interval); +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogWriter.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogWriter.java new file mode 100644 index 0000000..3e178af --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogWriter.java @@ -0,0 +1,226 @@ +package org.productivity.java.syslog4j.impl.net.tcp; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; + +import javax.net.SocketFactory; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslog; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* TCPNetSyslogWriter is an implementation of Runnable that supports sending +* TCP-based messages within a separate Thread. +* +*When used in "threaded" mode (see TCPNetSyslogConfig for the option), +* a queuing mechanism is used (via LinkedList).
+* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslogWriter.java,v 1.20 2010/11/28 01:38:08 cvs Exp $ +*/ +public class TCPNetSyslogWriter extends AbstractSyslogWriter { + private static final long serialVersionUID = -6388813866108482855L; + + protected TCPNetSyslog tcpNetSyslog = null; + + protected Socket socket = null; + + protected TCPNetSyslogConfigIF tcpNetSyslogConfig = null; + + protected long lastSocketCreationTimeMs = 0; + + public TCPNetSyslogWriter() { + // + } + + public void initialize(AbstractSyslog abstractSyslog) { + super.initialize(abstractSyslog); + + this.tcpNetSyslog = (TCPNetSyslog) abstractSyslog; + + this.tcpNetSyslogConfig = (TCPNetSyslogConfigIF) this.tcpNetSyslog.getConfig(); + } + + protected SocketFactory obtainSocketFactory() { + return SocketFactory.getDefault(); + } + + protected Socket createSocket(InetAddress hostAddress, int port, boolean keepalive) throws IOException { + SocketFactory socketFactory = obtainSocketFactory(); + + Socket newSocket = socketFactory.createSocket(hostAddress,port); + + if (this.tcpNetSyslogConfig.isSoLinger()) { + newSocket.setSoLinger(true,this.tcpNetSyslogConfig.getSoLingerSeconds()); + } + + if (this.tcpNetSyslogConfig.isKeepAlive()) { + newSocket.setKeepAlive(keepalive); + } + + if (this.tcpNetSyslogConfig.isReuseAddress()) { + newSocket.setReuseAddress(true); + } + + return newSocket; + } + + protected Socket getSocket() throws SyslogRuntimeException { + if (this.socket != null && this.socket.isConnected()) { + int freshConnectionInterval = this.tcpNetSyslogConfig.getFreshConnectionInterval(); + + if (freshConnectionInterval > 0) { + long currentTimeMs = System.currentTimeMillis(); + + if ((currentTimeMs - lastSocketCreationTimeMs) >= freshConnectionInterval) { + closeSocket(this.socket); + } + + } else { + return this.socket; + } + } + + if (this.socket == null) { + lastSocketCreationTimeMs = 0; + + try { + InetAddress hostAddress = this.tcpNetSyslog.getHostAddress(); + + this.socket = createSocket(hostAddress,this.syslog.getConfig().getPort(),this.tcpNetSyslogConfig.isPersistentConnection()); + lastSocketCreationTimeMs = System.currentTimeMillis(); + + } catch (IOException ioe) { + throw new SyslogRuntimeException(ioe); + } + } + + return this.socket; + } + + protected void closeSocket(Socket socketToClose) { + if (socketToClose == null) { + return; + } + + try { + socketToClose.close(); + + } catch (IOException ioe) { + if (!"Socket is closed".equalsIgnoreCase(ioe.getMessage())) { + throw new SyslogRuntimeException(ioe); + } + + } finally { + if (socketToClose == this.socket) { + this.socket = null; + } + } + } + + public void write(byte[] message) throws SyslogRuntimeException { + Socket currentSocket = null; + + int attempts = 0; + while(attempts != -1 && attempts < (this.tcpNetSyslogConfig.getWriteRetries() + 1)) { + try { + currentSocket = getSocket(); + + if (currentSocket == null) { + throw new SyslogRuntimeException("No socket available"); + } + + OutputStream os = currentSocket.getOutputStream(); + + if (this.tcpNetSyslogConfig.isSetBufferSize()) { + currentSocket.setSendBufferSize(message.length); + } + + os.write(message); + + byte[] delimiterSequence = this.tcpNetSyslogConfig.getDelimiterSequence(); + if (delimiterSequence != null && delimiterSequence.length > 0) { + os.write(delimiterSequence); + } + + this.syslog.setBackLogStatus(false); + + attempts = -1; + + if (!this.tcpNetSyslogConfig.isPersistentConnection()) { + closeSocket(currentSocket); + } + + } catch (IOException ioe) { + attempts++; + closeSocket(currentSocket); + + if (attempts >= (this.tcpNetSyslogConfig.getWriteRetries() + 1)) { + throw new SyslogRuntimeException(ioe); + } + } + } + } + + public synchronized void flush() throws SyslogRuntimeException { + if (this.socket == null) { + return; + } + + if (this.syslogConfig.isThreaded()) { + this.shutdown(); + this.syslog.createWriterThread(this); + + } else { + closeSocket(this.socket); + } + } + + public synchronized void shutdown() throws SyslogRuntimeException { + this.shutdown = true; + + if (this.syslogConfig.isThreaded()) { + long timeStart = System.currentTimeMillis(); + boolean done = false; + + while(!done) { + if (this.socket == null || this.socket.isClosed()) { + done = true; + + } else { + long now = System.currentTimeMillis(); + + if (now > (timeStart + this.tcpNetSyslogConfig.getMaxShutdownWait())) { + closeSocket(this.socket); + this.thread.interrupt(); + done = true; + } + + if (!done) { + SyslogUtility.sleep(SyslogConstants.SHUTDOWN_INTERVAL); + } + } + } + + } else { + if (this.socket == null || this.socket.isClosed()) { + return; + } + + closeSocket(this.socket); + } + } + + protected void runCompleted() { + closeSocket(this.socket); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslog.java new file mode 100644 index 0000000..c1f7884 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslog.java @@ -0,0 +1,76 @@ +package org.productivity.java.syslog4j.impl.net.tcp.pool; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslog; +import org.productivity.java.syslog4j.impl.pool.AbstractSyslogPoolFactory; +import org.productivity.java.syslog4j.impl.pool.generic.GenericSyslogPoolFactory; + +/** +* PooledTCPNetSyslog is an extension of TCPNetSyslog which provides support +* for Apache Commons Pool. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: PooledTCPNetSyslog.java,v 1.5 2008/12/10 04:30:15 cvs Exp $ +*/ +public class PooledTCPNetSyslog extends TCPNetSyslog { + private static final long serialVersionUID = 4279960451141784200L; + + protected AbstractSyslogPoolFactory poolFactory = null; + + public void initialize() throws SyslogRuntimeException { + super.initialize(); + + this.poolFactory = createSyslogPoolFactory(); + + this.poolFactory.initialize(this); + } + + protected AbstractSyslogPoolFactory createSyslogPoolFactory() { + AbstractSyslogPoolFactory syslogPoolFactory = new GenericSyslogPoolFactory(); + + return syslogPoolFactory; + } + + public AbstractSyslogWriter getWriter() { + try { + AbstractSyslogWriter syslogWriter = this.poolFactory.borrowSyslogWriter(); + + return syslogWriter; + + } catch (Exception e) { + throw new SyslogRuntimeException(e); + } + } + + public void returnWriter(AbstractSyslogWriter syslogWriter) { + try { + this.poolFactory.returnSyslogWriter(syslogWriter); + + } catch (Exception e) { + throw new SyslogRuntimeException(e); + } + } + + public void flush() throws SyslogRuntimeException { + try { + this.poolFactory.clear(); + + } catch (Exception e) { + // + } + } + + public void shutdown() throws SyslogRuntimeException { + try { + this.poolFactory.close(); + + } catch (Exception e) { + // + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslogConfig.java new file mode 100644 index 0000000..91a1ba4 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslogConfig.java @@ -0,0 +1,172 @@ +package org.productivity.java.syslog4j.impl.net.tcp.pool; + +import org.apache.commons.pool.impl.GenericObjectPool; +import org.productivity.java.syslog4j.SyslogPoolConfigIF; +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslogConfig; + +/** +* NetSyslogPoolFactory is an implementation of SyslogPoolConfigIF +* which provides configuration support for the Apache Commons Pool. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: PooledTCPNetSyslogConfig.java,v 1.3 2008/11/26 15:01:47 cvs Exp $ +*/ +public class PooledTCPNetSyslogConfig extends TCPNetSyslogConfig implements SyslogPoolConfigIF { + private static final long serialVersionUID = 2283355983363422888L; + + protected int maxActive = SYSLOG_POOL_CONFIG_MAX_ACTIVE_DEFAULT; + protected int maxIdle = SYSLOG_POOL_CONFIG_MAX_IDLE_DEFAULT; + protected long maxWait = SYSLOG_POOL_CONFIG_MAX_WAIT_DEFAULT; + protected long minEvictableIdleTimeMillis = SYSLOG_POOL_CONFIG_MIN_EVICTABLE_IDLE_TIME_MILLIS_DEFAULT; + protected int minIdle = SYSLOG_POOL_CONFIG_MIN_IDLE_DEFAULT; + protected int numTestsPerEvictionRun = SYSLOG_POOL_CONFIG_NUM_TESTS_PER_EVICTION_RUN_DEFAULT; + protected long softMinEvictableIdleTimeMillis = SYSLOG_POOL_CONFIG_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS_DEFAULT; + protected long timeBetweenEvictionRunsMillis = SYSLOG_POOL_CONFIG_TIME_BETWEEN_EVICTION_RUNS_MILLIS_DEFAULT; + protected byte whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK; + protected boolean testOnBorrow = SYSLOG_POOL_CONFIG_TEST_ON_BORROW_DEFAULT; + protected boolean testOnReturn = SYSLOG_POOL_CONFIG_TEST_ON_RETURN_DEFAULT; + protected boolean testWhileIdle = SYSLOG_POOL_CONFIG_TEST_WHILE_IDLE_DEFAULT; + + public PooledTCPNetSyslogConfig() { + // + } + + public PooledTCPNetSyslogConfig(int facility, String host, int port) { + super(facility, host, port); + } + + public PooledTCPNetSyslogConfig(int facility, String host) { + super(facility, host); + } + + public PooledTCPNetSyslogConfig(int facility) { + super(facility); + } + + public PooledTCPNetSyslogConfig(String host, int port) { + super(host, port); + } + + public PooledTCPNetSyslogConfig(String host) { + super(host); + } + + protected void configureThreadedValues(int value) { + if (isThreaded()) { + this.minIdle = value; + this.maxIdle = value; + this.maxActive = value; + } + } + + public int getMaxActive() { + return this.maxActive; + } + + public void setMaxActive(int maxActive) { + configureThreadedValues(maxActive); + + this.maxActive = maxActive; + } + + public int getMaxIdle() { + return this.maxIdle; + } + + public void setMaxIdle(int maxIdle) { + configureThreadedValues(maxIdle); + + this.maxIdle = maxIdle; + } + + public long getMaxWait() { + return this.maxWait; + } + + public void setMaxWait(long maxWait) { + this.maxWait = maxWait; + } + + public long getMinEvictableIdleTimeMillis() { + return this.minEvictableIdleTimeMillis; + } + + public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { + this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; + } + + public int getMinIdle() { + return this.minIdle; + } + + public void setMinIdle(int minIdle) { + configureThreadedValues(minIdle); + + this.minIdle = minIdle; + } + + public int getNumTestsPerEvictionRun() { + return this.numTestsPerEvictionRun; + } + + public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { + this.numTestsPerEvictionRun = numTestsPerEvictionRun; + } + + public long getSoftMinEvictableIdleTimeMillis() { + return this.softMinEvictableIdleTimeMillis; + } + + public void setSoftMinEvictableIdleTimeMillis( + long softMinEvictableIdleTimeMillis) { + this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; + } + + public long getTimeBetweenEvictionRunsMillis() { + return this.timeBetweenEvictionRunsMillis; + } + + public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { + this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; + } + + public byte getWhenExhaustedAction() { + return this.whenExhaustedAction; + } + + public void setWhenExhaustedAction(byte whenExhaustedAction) { + this.whenExhaustedAction = whenExhaustedAction; + } + + public boolean isTestOnBorrow() { + return this.testOnBorrow; + } + + public void setTestOnBorrow(boolean testOnBorrow) { + this.testOnBorrow = testOnBorrow; + } + + public boolean isTestOnReturn() { + return this.testOnReturn; + } + + public void setTestOnReturn(boolean testOnReturn) { + this.testOnReturn = testOnReturn; + } + + public boolean isTestWhileIdle() { + return this.testWhileIdle; + } + + public void setTestWhileIdle(boolean testWhileIdle) { + this.testWhileIdle = testWhileIdle; + } + + public Class getSyslogClass() { + return PooledTCPNetSyslog.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslog.java new file mode 100644 index 0000000..bb52c92 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslog.java @@ -0,0 +1,49 @@ +package org.productivity.java.syslog4j.impl.net.tcp.ssl; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslog; + +/** +* SSLTCPNetSyslog is an extension of AbstractSyslog that provides support for +* TCP/IP-based (over SSL/TLS) syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslog.java,v 1.1 2009/03/29 17:38:58 cvs Exp $ +*/ +public class SSLTCPNetSyslog extends TCPNetSyslog { + private static final long serialVersionUID = 2766654802524487317L; + + public void initialize() throws SyslogRuntimeException { + super.initialize(); + + SSLTCPNetSyslogConfigIF sslTcpNetSyslogConfig = (SSLTCPNetSyslogConfigIF) this.tcpNetSyslogConfig; + + String keyStore = sslTcpNetSyslogConfig.getKeyStore(); + + if (keyStore != null && !"".equals(keyStore.trim())) { + System.setProperty("javax.net.ssl.keyStore",keyStore); + } + + String keyStorePassword = sslTcpNetSyslogConfig.getKeyStorePassword(); + + if (keyStorePassword != null && !"".equals(keyStorePassword.trim())) { + System.setProperty("javax.net.ssl.keyStorePassword",keyStorePassword); + } + + String trustStore = sslTcpNetSyslogConfig.getTrustStore(); + + if (trustStore != null && !"".equals(trustStore.trim())) { + System.setProperty("javax.net.ssl.trustStore",trustStore); + } + + String trustStorePassword = sslTcpNetSyslogConfig.getTrustStorePassword(); + + if (trustStorePassword != null && !"".equals(trustStorePassword.trim())) { + System.setProperty("javax.net.ssl.trustStorePassword",trustStorePassword); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfig.java new file mode 100644 index 0000000..d1cf7de --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfig.java @@ -0,0 +1,88 @@ +package org.productivity.java.syslog4j.impl.net.tcp.ssl; + +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslogConfig; + +/** +* SSLTCPNetSyslogConfig is an extension of TCPNetSyslogConfig that provides +* configuration support for TCP/IP-based (over SSL/TLS) syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslogConfig.java,v 1.2 2009/03/29 17:38:58 cvs Exp $ +*/ +public class SSLTCPNetSyslogConfig extends TCPNetSyslogConfig implements SSLTCPNetSyslogConfigIF { + private static final long serialVersionUID = 5569086213824510834L; + + protected String keyStore = null; + protected String keyStorePassword = null; + + protected String trustStore = null; + protected String trustStorePassword = null; + + public SSLTCPNetSyslogConfig() { + // + } + + public SSLTCPNetSyslogConfig(int facility, String host, int port) { + super(facility, host, port); + } + + public SSLTCPNetSyslogConfig(int facility, String host) { + super(facility, host); + } + + public SSLTCPNetSyslogConfig(int facility) { + super(facility); + } + + public SSLTCPNetSyslogConfig(String host, int port) { + super(host, port); + } + + public SSLTCPNetSyslogConfig(String host) { + super(host); + } + + public String getKeyStore() { + return this.keyStore; + } + + public void setKeyStore(String keyStore) { + this.keyStore = keyStore; + } + + public String getKeyStorePassword() { + return this.keyStorePassword; + } + + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + + public String getTrustStore() { + return this.trustStore; + } + + public void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + public String getTrustStorePassword() { + return this.trustStorePassword; + } + + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + public Class getSyslogClass() { + return SSLTCPNetSyslog.class; + } + + public Class getSyslogWriterClass() { + return SSLTCPNetSyslogWriter.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfigIF.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfigIF.java new file mode 100644 index 0000000..967631a --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfigIF.java @@ -0,0 +1,28 @@ +package org.productivity.java.syslog4j.impl.net.tcp.ssl; + +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslogConfigIF; + +/** +* SSLTCPNetSyslogConfigIF is a configuration interface supporting TCP/IP-based +* (over SSL/TLS) Syslog implementations. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslogConfigIF.java,v 1.1 2009/03/29 17:38:58 cvs Exp $ +*/ +public interface SSLTCPNetSyslogConfigIF extends TCPNetSyslogConfigIF { + public String getKeyStore(); + public void setKeyStore(String keyStore); + + public String getKeyStorePassword(); + public void setKeyStorePassword(String keyStorePassword); + + public String getTrustStore(); + public void setTrustStore(String trustStore); + + public String getTrustStorePassword(); + public void setTrustStorePassword(String trustStorePassword); +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogWriter.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogWriter.java new file mode 100644 index 0000000..61a9de0 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogWriter.java @@ -0,0 +1,28 @@ +package org.productivity.java.syslog4j.impl.net.tcp.ssl; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; + +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslogWriter; + +/** +* SSLTCPNetSyslogWriter is an implementation of Runnable that supports sending +* TCP/IP-based (over SSL/TLS) messages within a separate Thread. +* +*When used in "threaded" mode (see TCPNetSyslogConfig for the option), +* a queuing mechanism is used (via LinkedList).
+* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslogWriter.java,v 1.4 2009/03/29 17:38:58 cvs Exp $ +*/ +public class SSLTCPNetSyslogWriter extends TCPNetSyslogWriter { + private static final long serialVersionUID = 8944446235285662244L; + + protected SocketFactory obtainSocketFactory() { + return SSLSocketFactory.getDefault(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/pool/PooledSSLTCPNetSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/pool/PooledSSLTCPNetSyslogConfig.java new file mode 100644 index 0000000..fb3f3fe --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/tcp/ssl/pool/PooledSSLTCPNetSyslogConfig.java @@ -0,0 +1,91 @@ +package org.productivity.java.syslog4j.impl.net.tcp.ssl.pool; + +import org.productivity.java.syslog4j.impl.net.tcp.pool.PooledTCPNetSyslogConfig; +import org.productivity.java.syslog4j.impl.net.tcp.ssl.SSLTCPNetSyslog; +import org.productivity.java.syslog4j.impl.net.tcp.ssl.SSLTCPNetSyslogConfigIF; +import org.productivity.java.syslog4j.impl.net.tcp.ssl.SSLTCPNetSyslogWriter; + +/** +* PooledSSLTCPNetSyslogConfig is an extension of PooledTCPNetSyslogConfig +* which provides configuration support for the Apache Commons Pool. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: PooledSSLTCPNetSyslogConfig.java,v 1.2 2009/03/29 17:38:58 cvs Exp $ +*/ +public class PooledSSLTCPNetSyslogConfig extends PooledTCPNetSyslogConfig implements SSLTCPNetSyslogConfigIF { + private static final long serialVersionUID = 2092268298395023976L; + + protected String keyStore = null; + protected String keyStorePassword = null; + + protected String trustStore = null; + protected String trustStorePassword = null; + + public PooledSSLTCPNetSyslogConfig() { + super(); + } + + public PooledSSLTCPNetSyslogConfig(int facility, String host, int port) { + super(facility, host, port); + } + + public PooledSSLTCPNetSyslogConfig(int facility, String host) { + super(facility, host); + } + + public PooledSSLTCPNetSyslogConfig(int facility) { + super(facility); + } + + public PooledSSLTCPNetSyslogConfig(String host, int port) { + super(host, port); + } + + public PooledSSLTCPNetSyslogConfig(String host) { + super(host); + } + + public String getKeyStore() { + return this.keyStore; + } + + public void setKeyStore(String keyStore) { + this.keyStore = keyStore; + } + + public String getKeyStorePassword() { + return this.keyStorePassword; + } + + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + + public String getTrustStore() { + return this.trustStore; + } + + public void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + public String getTrustStorePassword() { + return this.trustStorePassword; + } + + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + public Class getSyslogClass() { + return SSLTCPNetSyslog.class; + } + + public Class getSyslogWriterClass() { + return SSLTCPNetSyslogWriter.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslog.java new file mode 100644 index 0000000..9b6f813 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslog.java @@ -0,0 +1,104 @@ +package org.productivity.java.syslog4j.impl.net.udp; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; +import org.productivity.java.syslog4j.impl.net.AbstractNetSyslog; + +/** +* UDPNetSyslog is an extension of AbstractSyslog that provides support for +* UDP/IP-based syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UDPNetSyslog.java,v 1.18 2010/10/27 06:18:10 cvs Exp $ +*/ +public class UDPNetSyslog extends AbstractNetSyslog { + private static final long serialVersionUID = 5259485504549037999L; + + protected DatagramSocket socket = null; + + public void initialize() throws SyslogRuntimeException { + super.initialize(); + + createDatagramSocket(true); + } + + protected synchronized void createDatagramSocket(boolean initialize) { + try { + this.socket = new DatagramSocket(); + + } catch (SocketException se) { + if (initialize) { + if (this.syslogConfig.isThrowExceptionOnInitialize()) { + throw new SyslogRuntimeException(se); + } + + } else { + throw new SyslogRuntimeException(se); + } + } + + if (this.socket == null) { + throw new SyslogRuntimeException("Cannot seem to get a Datagram socket"); + } + } + + protected void write(int level, byte[] message) throws SyslogRuntimeException { + if (this.socket == null) { + createDatagramSocket(false); + } + + InetAddress hostAddress = getHostAddress(); + + DatagramPacket packet = new DatagramPacket( + message, + message.length, + hostAddress, + this.syslogConfig.getPort() + ); + + int attempts = 0; + + while(attempts != -1 && attempts < (this.netSyslogConfig.getWriteRetries() + 1)) { + try { + this.socket.send(packet); + attempts = -1; + + } catch (IOException ioe) { + if (attempts == (this.netSyslogConfig.getWriteRetries() + 1)) { + throw new SyslogRuntimeException(ioe); + } + } + } + } + + public void flush() throws SyslogRuntimeException { + shutdown(); + + createDatagramSocket(true); + } + + public void shutdown() throws SyslogRuntimeException { + if (this.socket != null) { + this.socket.close(); + this.socket = null; + } + } + + public AbstractSyslogWriter getWriter() { + return null; + } + + public void returnWriter(AbstractSyslogWriter syslogWriter) { + // + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslogConfig.java new file mode 100644 index 0000000..9ab98e4 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslogConfig.java @@ -0,0 +1,46 @@ +package org.productivity.java.syslog4j.impl.net.udp; + +import org.productivity.java.syslog4j.impl.net.AbstractNetSyslogConfig; + +/** +* UDPNetSyslogConfig is an extension of AbstractNetSyslogConfig that provides +* configuration support for UDP/IP-based syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UDPNetSyslogConfig.java,v 1.6 2008/11/14 04:32:00 cvs Exp $ +*/ +public class UDPNetSyslogConfig extends AbstractNetSyslogConfig { + private static final long serialVersionUID = 4465067182562754345L; + + public UDPNetSyslogConfig() { + super(); + } + + public UDPNetSyslogConfig(int facility, String host, int port) { + super(facility,host,port); + } + + public UDPNetSyslogConfig(int facility, String host) { + super(facility,host); + } + + public UDPNetSyslogConfig(int facility) { + super(facility); + } + + public UDPNetSyslogConfig(String host, int port) { + super(host,port); + } + + public UDPNetSyslogConfig(String host) { + super(host); + } + + public Class getSyslogClass() { + return UDPNetSyslog.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/pool/AbstractSyslogPoolFactory.java b/src/main/java/org/productivity/java/syslog4j/impl/pool/AbstractSyslogPoolFactory.java new file mode 100644 index 0000000..14d3dfe --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/pool/AbstractSyslogPoolFactory.java @@ -0,0 +1,84 @@ +package org.productivity.java.syslog4j.impl.pool; + +import org.apache.commons.pool.BasePoolableObjectFactory; +import org.apache.commons.pool.ObjectPool; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslog; +import org.productivity.java.syslog4j.impl.AbstractSyslogConfigIF; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; + +/** +* AbstractSyslogPoolFactory is an abstract implementation of the Apache Commons Pool +* BasePoolableObjectFactory. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: AbstractSyslogPoolFactory.java,v 1.5 2008/12/10 04:15:11 cvs Exp $ +* @see org.productivity.java.syslog4j.impl.pool.generic.GenericSyslogPoolFactory +*/ +public abstract class AbstractSyslogPoolFactory extends BasePoolableObjectFactory { + private static final long serialVersionUID = -7441569603980981508L; + + protected AbstractSyslog syslog = null; + protected AbstractSyslogConfigIF syslogConfig = null; + + protected ObjectPool pool = null; + + public AbstractSyslogPoolFactory() { + // + } + + public void initialize(AbstractSyslog abstractSyslog) throws SyslogRuntimeException { + this.syslog = abstractSyslog; + + try { + this.syslogConfig = (AbstractSyslogConfigIF) this.syslog.getConfig(); + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must implement AbstractSyslogConfigIF"); + } + + this.pool = createPool(); + } + + public Object makeObject() throws Exception { + AbstractSyslogWriter syslogWriter = this.syslog.createWriter(); + + if (this.syslogConfig.isThreaded()) { + this.syslog.createWriterThread(syslogWriter); + } + + return syslogWriter; + } + + public void destroyObject(Object obj) throws Exception { + AbstractSyslogWriter writer = (AbstractSyslogWriter) obj; + + writer.shutdown(); + + super.destroyObject(writer); + } + + public abstract ObjectPool createPool() throws SyslogRuntimeException; + + public AbstractSyslogWriter borrowSyslogWriter() throws Exception { + AbstractSyslogWriter syslogWriter = (AbstractSyslogWriter) this.pool.borrowObject(); + + return syslogWriter; + } + + public void returnSyslogWriter(AbstractSyslogWriter syslogWriter) throws Exception { + this.pool.returnObject(syslogWriter); + } + + public void clear() throws Exception { + this.pool.clear(); + } + + public void close() throws Exception { + this.pool.close(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/pool/generic/GenericSyslogPoolFactory.java b/src/main/java/org/productivity/java/syslog4j/impl/pool/generic/GenericSyslogPoolFactory.java new file mode 100644 index 0000000..039eaf7 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/pool/generic/GenericSyslogPoolFactory.java @@ -0,0 +1,52 @@ +package org.productivity.java.syslog4j.impl.pool.generic; + +import org.apache.commons.pool.ObjectPool; +import org.apache.commons.pool.impl.GenericObjectPool; +import org.productivity.java.syslog4j.SyslogPoolConfigIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.pool.AbstractSyslogPoolFactory; + +/** +* GenericSyslogPoolFactory is an implementation of the Apache Commons Pool +* BasePoolableObjectFactory using a GenericObjectPool. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: GenericSyslogPoolFactory.java,v 1.5 2008/12/10 04:15:10 cvs Exp $ +*/ +public class GenericSyslogPoolFactory extends AbstractSyslogPoolFactory { + protected void configureGenericObjectPool(GenericObjectPool genericObjectPool) throws SyslogRuntimeException { + SyslogPoolConfigIF poolConfig = null; + + try { + poolConfig = (SyslogPoolConfigIF) this.syslog.getConfig(); + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must implement interface SyslogPoolConfigIF"); + } + + genericObjectPool.setMaxActive(poolConfig.getMaxActive()); + genericObjectPool.setMaxIdle(poolConfig.getMaxIdle()); + genericObjectPool.setMaxWait(poolConfig.getMaxWait()); + genericObjectPool.setMinEvictableIdleTimeMillis(poolConfig.getMinEvictableIdleTimeMillis()); + genericObjectPool.setMinIdle(poolConfig.getMinIdle()); + genericObjectPool.setNumTestsPerEvictionRun(poolConfig.getNumTestsPerEvictionRun()); + genericObjectPool.setSoftMinEvictableIdleTimeMillis(poolConfig.getSoftMinEvictableIdleTimeMillis()); + genericObjectPool.setTestOnBorrow(poolConfig.isTestOnBorrow()); + genericObjectPool.setTestOnReturn(poolConfig.isTestOnReturn()); + genericObjectPool.setTestWhileIdle(poolConfig.isTestWhileIdle()); + genericObjectPool.setTimeBetweenEvictionRunsMillis(poolConfig.getTimeBetweenEvictionRunsMillis()); + genericObjectPool.setWhenExhaustedAction(poolConfig.getWhenExhaustedAction()); + } + + public ObjectPool createPool() throws SyslogRuntimeException { + GenericObjectPool genericPool = new GenericObjectPool(this); + + configureGenericObjectPool(genericPool); + + return genericPool; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/unix/UnixSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/unix/UnixSyslog.java new file mode 100644 index 0000000..b5e56af --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/unix/UnixSyslog.java @@ -0,0 +1,125 @@ +package org.productivity.java.syslog4j.impl.unix; + +import org.productivity.java.syslog4j.SyslogMessageProcessorIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslog; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; +import org.productivity.java.syslog4j.util.OSDetectUtility; + +import com.sun.jna.Library; +import com.sun.jna.Memory; +import com.sun.jna.Native; + +/** +* UnixSyslog is an extension of AbstractSyslog that provides support for +* Unix-based syslog clients. +* +*This class requires the JNA (Java Native Access) library to directly +* access the native C libraries utilized on Unix platforms.
+* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UnixSyslog.java,v 1.27 2010/10/25 04:21:19 cvs Exp $ +*/ +public class UnixSyslog extends AbstractSyslog { + private static final long serialVersionUID = 4973353204252276740L; + + protected UnixSyslogConfig unixSyslogConfig = null; + + protected interface CLibrary extends Library { + public void openlog(final Memory ident, int option, int facility); + public void syslog(int priority, final String format, final String message); + public void closelog(); + } + + protected static int currentFacility = -1; + protected static boolean openlogCalled = false; + + protected static CLibrary libraryInstance = null; + + protected static synchronized void loadLibrary(UnixSyslogConfig config) throws SyslogRuntimeException { + if (!OSDetectUtility.isUnix()) { + throw new SyslogRuntimeException("UnixSyslog not supported on non-Unix platforms"); + } + + if (libraryInstance == null) { + libraryInstance = (CLibrary) Native.loadLibrary(config.getLibrary(),CLibrary.class); + } + } + + public void initialize() throws SyslogRuntimeException { + try { + this.unixSyslogConfig = (UnixSyslogConfig) this.syslogConfig; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must be of type UnixSyslogConfig"); + } + + loadLibrary(this.unixSyslogConfig); + } + + protected static void write(int level, String message, UnixSyslogConfig config) throws SyslogRuntimeException { + synchronized(libraryInstance) { + if (currentFacility != config.getFacility()) { + if (openlogCalled) { + libraryInstance.closelog(); + openlogCalled = false; + } + + currentFacility = config.getFacility(); + } + + if (!openlogCalled) { + String ident = config.getIdent(); + + if (ident != null && "".equals(ident.trim())) { + ident = null; + } + + Memory identBuffer = null; + + if (ident != null) { + identBuffer = new Memory(128); + identBuffer.setString(0, ident, false); + } + + libraryInstance.openlog(identBuffer,config.getOption(),currentFacility); + openlogCalled = true; + } + + int priority = currentFacility | level; + + libraryInstance.syslog(priority,"%s",message); + } + } + + protected void write(int level, byte[] message) throws SyslogRuntimeException { + // NO-OP + } + + public void log(SyslogMessageProcessorIF messageProcessor, int level, String message) { + write(level,message,this.unixSyslogConfig); + } + + public void flush() throws SyslogRuntimeException { + synchronized(libraryInstance) { + libraryInstance.closelog(); + openlogCalled = false; + } + } + + public void shutdown() throws SyslogRuntimeException { + flush(); + } + + public AbstractSyslogWriter getWriter() { + return null; + } + + public void returnWriter(AbstractSyslogWriter syslogWriter) { + // + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/unix/UnixSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/unix/UnixSyslogConfig.java new file mode 100644 index 0000000..7db7c82 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/unix/UnixSyslogConfig.java @@ -0,0 +1,71 @@ +package org.productivity.java.syslog4j.impl.unix; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslogConfig; + +/** +* UnixSyslogConfig is an extension of AbstractNetSyslogConfig that provides +* configuration support for Unix-based syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UnixSyslogConfig.java,v 1.13 2010/10/25 03:50:25 cvs Exp $ +*/ +public class UnixSyslogConfig extends AbstractSyslogConfig { + private static final long serialVersionUID = -4805767812011660656L; + + protected String library = SYSLOG_LIBRARY_DEFAULT; + protected int option = OPTION_NONE; + + public UnixSyslogConfig() { + // Unix-based syslog does not need localName sent + this.setSendLocalName(false); + } + + public Class getSyslogClass() { + return UnixSyslog.class; + } + + public String getHost() { + return null; + } + + public int getPort() { + return 0; + } + + public void setHost(String host) throws SyslogRuntimeException { + throw new SyslogRuntimeException("Host not appropriate for class \"" + this.getClass().getName() + "\""); + } + + public void setPort(int port) throws SyslogRuntimeException { + throw new SyslogRuntimeException("Port not appropriate for class \"" + this.getClass().getName() + "\""); + } + + public String getLibrary() { + return this.library; + } + + public void setLibrary(String library) { + this.library = library; + } + + public int getOption() { + return this.option; + } + + public void setOption(int option) { + this.option = option; + } + + public int getMaxQueueSize() { + throw new SyslogRuntimeException("UnixSyslog protocol does not uses a queueing mechanism"); + } + + public void setMaxQueueSize(int maxQueueSize) { + throw new SyslogRuntimeException("UnixSyslog protocol does not uses a queueing mechanism"); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog.java new file mode 100644 index 0000000..eee1581 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog.java @@ -0,0 +1,143 @@ +package org.productivity.java.syslog4j.impl.unix.socket; + +import java.nio.ByteBuffer; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslog; +import org.productivity.java.syslog4j.impl.AbstractSyslogWriter; +import org.productivity.java.syslog4j.util.OSDetectUtility; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Structure; + +/** +* UnixSocketSyslog is an extension of AbstractSyslog that provides support for +* Unix socket-based syslog clients. +* +*This class requires the JNA (Java Native Access) library to directly +* access the native C libraries utilized on Unix platforms.
+* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UnixSocketSyslog.java,v 1.13 2010/11/16 00:52:01 cvs Exp $ +*/ +public class UnixSocketSyslog extends AbstractSyslog { + private static final long serialVersionUID = 39878807911936785L; + + protected static class SockAddr extends Structure { + public final static int SUN_PATH_SIZE = 108; + public final static byte[] ZERO_BYTE = new byte[] { 0 }; + + public short sun_family = 1; + public byte[] sun_path = new byte[SUN_PATH_SIZE]; + + public void setSunPath(String sunPath) { + System.arraycopy(sunPath.getBytes(), 0,this.sun_path, 0, sunPath.length()); + System.arraycopy(ZERO_BYTE,0,this.sun_path,sunPath.length(),1); + } + } + + protected interface CLibrary extends Library { + public int socket(int domain, int type, int protocol); + public int connect(int sockfd, SockAddr sockaddr, int addrlen); + public int write(int fd, ByteBuffer buffer, int count); + public int close(int fd); + public String strerror(int errno); + } + + protected boolean libraryLoaded = false; + protected CLibrary libraryInstance = null; + + protected UnixSocketSyslogConfig unixSocketSyslogConfig = null; + protected int fd = -1; + + protected synchronized void loadLibrary() { + if (!OSDetectUtility.isUnix()) { + throw new SyslogRuntimeException("UnixSyslog not supported on non-Unix platforms"); + } + + if (!this.libraryLoaded) { + this.libraryInstance = (CLibrary) Native.loadLibrary(this.unixSocketSyslogConfig.getLibrary(),CLibrary.class); + this.libraryLoaded = true; + } + } + + public void initialize() throws SyslogRuntimeException { + try { + this.unixSocketSyslogConfig = (UnixSocketSyslogConfig) this.syslogConfig; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must be of type UnixSocketSyslogConfig"); + } + + loadLibrary(); + + } + + protected synchronized void connect() { + if (this.fd != -1) { + return; + } + + this.fd = this.libraryInstance.socket(this.unixSocketSyslogConfig.getFamily(),this.unixSocketSyslogConfig.getType(),this.unixSocketSyslogConfig.getProtocol()); + + if (this.fd == -1) { + this.fd = -1; + return; + } + + SockAddr sockAddr = new SockAddr(); + + sockAddr.sun_family = this.unixSocketSyslogConfig.getFamily(); + sockAddr.setSunPath(this.unixSocketSyslogConfig.getPath()); + + int c = this.libraryInstance.connect(this.fd, sockAddr, sockAddr.size()); + + if (c == -1) { + this.fd = -1; + return; + } + } + + protected void write(int level, byte[] message) throws SyslogRuntimeException { + if (this.fd == -1) { + connect(); + } + + if (this.fd == -1) { + return; + } + + ByteBuffer byteBuffer = ByteBuffer.wrap(message); + + this.libraryInstance.write(this.fd,byteBuffer,message.length); + } + + public void flush() throws SyslogRuntimeException { + shutdown(); + + this.fd = this.libraryInstance.socket(this.unixSocketSyslogConfig.getFamily(),this.unixSocketSyslogConfig.getType(),this.unixSocketSyslogConfig.getProtocol()); + } + + public void shutdown() throws SyslogRuntimeException { + if (this.fd == -1) { + return; + } + + this.libraryInstance.close(this.fd); + + this.fd = -1; + } + + public AbstractSyslogWriter getWriter() { + return null; + } + + public void returnWriter(AbstractSyslogWriter syslogWriter) { + // + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslogConfig.java new file mode 100644 index 0000000..65effb5 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslogConfig.java @@ -0,0 +1,141 @@ +package org.productivity.java.syslog4j.impl.unix.socket; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslogConfig; + +/** +* UnixSocketSyslogConfig is an extension of AbstractNetSyslogConfig that provides +* configuration support for Unix socket-based syslog clients. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UnixSocketSyslogConfig.java,v 1.8 2010/11/12 03:43:12 cvs Exp $ +*/ +public class UnixSocketSyslogConfig extends AbstractSyslogConfig { + private static final long serialVersionUID = -3145794243736015707L; + + protected int type = SYSLOG_SOCKET_TYPE_DEFAULT; + protected short family = SYSLOG_SOCKET_FAMILY_DEFAULT; + protected int protocol = SYSLOG_SOCKET_PROTOCOL_DEFAULT; + protected String library = SYSLOG_SOCKET_LIBRARY_DEFAULT; + protected String path = SYSLOG_SOCKET_PATH_DEFAULT; + + public UnixSocketSyslogConfig() { + // Unix-based socket does not need localName sent + this.setSendLocalName(false); + this.setIdent("java"); + } + + public Class getSyslogClass() { + return UnixSocketSyslog.class; + } + + public UnixSocketSyslogConfig(int facility) { + this.facility = facility; + } + + public UnixSocketSyslogConfig(int facility, String path) { + this.facility = facility; + this.path = path; + } + + public UnixSocketSyslogConfig(String path) { + this.path = path; + } + + public String getHost() { + return null; + } + + public int getPort() { + return -1; + } + + public void setHost(String host) throws SyslogRuntimeException { + throw new SyslogRuntimeException("Host not appropriate for class \"" + this.getClass().getName() + "\""); + } + + public void setPort(int port) throws SyslogRuntimeException { + throw new SyslogRuntimeException("Port not appropriate for class \"" + this.getClass().getName() + "\""); + } + + public String getLibrary() { + return this.library; + } + + public void setLibrary(String library) { + this.library = library; + } + + public String getPath() { + return this.path; + } + + public void setPath(String path) { + this.path = path; + } + + public int getType() { + return this.type; + } + + public void setType(int type) { + this.type = type; + } + + public void setType(String type) { + if (type == null) { + throw new SyslogRuntimeException("Type cannot be null for class \"" + this.getClass().getName() + "\""); + } + + if ("SOCK_STREAM".equalsIgnoreCase(type.trim())) { + this.type = SOCK_STREAM; + + } else if ("SOCK_DGRAM".equalsIgnoreCase(type.trim())) { + this.type = SOCK_DGRAM; + + } else { + throw new SyslogRuntimeException("Type must be \"SOCK_STREAM\" or \"SOCK_DGRAM\" for class \"" + this.getClass().getName() + "\""); + } + } + + public short getFamily() { + return this.family; + } + + public void setFamily(short family) { + this.family = family; + } + + public void setFamily(String family) { + if (family == null) { + throw new SyslogRuntimeException("Family cannot be null for class \"" + this.getClass().getName() + "\""); + } + + if ("AF_UNIX".equalsIgnoreCase(family.trim())) { + this.family = AF_UNIX; + + } else { + throw new SyslogRuntimeException("Family must be \"AF_UNIX\" for class \"" + this.getClass().getName() + "\""); + } + } + + public int getProtocol() { + return this.protocol; + } + + public void setProtocol(int protocol) { + this.protocol = protocol; + } + + public int getMaxQueueSize() { + return -1; + } + + public void setMaxQueueSize(int maxQueueSize) { + throw new SyslogRuntimeException("UnixSyslog protocol does not uses a queueing mechanism"); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServer.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServer.java new file mode 100644 index 0000000..19a70ed --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServer.java @@ -0,0 +1,239 @@ +package org.productivity.java.syslog4j.server; + +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.productivity.java.syslog4j.Syslog4jVersion; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.server.impl.net.tcp.TCPNetSyslogServerConfig; +import org.productivity.java.syslog4j.server.impl.net.udp.UDPNetSyslogServerConfig; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** + * This class provides a Singleton-based interface for Syslog4j + * server implementations. + * + *Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy + * of the LGPL license is available in the META-INF folder in all + * distributions of Syslog4j and in the base directory of the "doc" ZIP.
+ * + * @author <syslog4j@productivity.org> + * @version $Id: SyslogServer.java,v 1.14 2011/01/23 20:49:12 cvs Exp $ + */ +public class SyslogServer implements SyslogConstants { + private static final long serialVersionUID = -2260889360828258602L; + + private static boolean SUPPRESS_RUNTIME_EXCEPTIONS = false; + + protected static final Map instances = new Hashtable(); + + static { + initialize(); + } + + private SyslogServer() { + // + } + + /** + * @return Returns the current version identifier for Syslog4j. + */ + public static final String getVersion() { + return Syslog4jVersion.VERSION; + } + + + /** + * @param suppress - true to suppress throwing SyslogRuntimeException in many methods of this class, false to throw exceptions (default) + */ + public static void setSuppressRuntimeExceptions(boolean suppress) { + SUPPRESS_RUNTIME_EXCEPTIONS = suppress; + } + + /** + * @return Returns whether or not to suppress throwing SyslogRuntimeException in many methods of this class + */ + public static boolean getSuppressRuntimeExceptions() { + return SUPPRESS_RUNTIME_EXCEPTIONS; + } + + /** + * Throws SyslogRuntimeException unless it has been suppressed via setSuppressRuntimeException(boolean). + * + * @param message + * @throws SyslogRuntimeException + */ + private static void throwRuntimeException(String message) throws SyslogRuntimeException { + if (SUPPRESS_RUNTIME_EXCEPTIONS) { + return; + + } else { + throw new SyslogRuntimeException(message.toString()); + } + } + + public static final SyslogServerIF getInstance(String protocol) throws SyslogRuntimeException { + String syslogProtocol = protocol.toLowerCase(); + + if (instances.containsKey(syslogProtocol)) { + return (SyslogServerIF) instances.get(syslogProtocol); + + } else { + throwRuntimeException("SyslogServer instance \"" + syslogProtocol + "\" not defined; use \"tcp\" or \"udp\" or call SyslogServer.createInstance(protocol,config) first"); + return null; + } + } + + public static final SyslogServerIF getThreadedInstance(String protocol) throws SyslogRuntimeException { + SyslogServerIF server = getInstance(protocol); + + if (server.getThread() == null) { + Thread thread = new Thread(server); + thread.setName("SyslogServer: " + protocol); + thread.setDaemon(server.getConfig().isUseDaemonThread()); + if (server.getConfig().getThreadPriority() > -1) { + thread.setPriority(server.getConfig().getThreadPriority()); + } + + server.setThread(thread); + thread.start(); + } + + return server; + } + + public static final boolean exists(String protocol) { + if (protocol == null || "".equals(protocol.trim())) { + return false; + } + + return instances.containsKey(protocol.toLowerCase()); + } + + public static final SyslogServerIF createInstance(String protocol, SyslogServerConfigIF config) throws SyslogRuntimeException { + if (protocol == null || "".equals(protocol.trim())) { + throwRuntimeException("Instance protocol cannot be null or empty"); + return null; + } + + if (config == null) { + throwRuntimeException("SyslogServerConfig cannot be null"); + return null; + } + + String syslogProtocol = protocol.toLowerCase(); + + SyslogServerIF syslogServer = null; + + synchronized(instances) { + if (instances.containsKey(syslogProtocol)) { + throwRuntimeException("SyslogServer instance \"" + syslogProtocol + "\" already defined."); + return null; + } + + try { + Class syslogClass = config.getSyslogServerClass(); + + syslogServer = (SyslogServerIF) syslogClass.newInstance(); + + } catch (ClassCastException cse) { + throw new SyslogRuntimeException(cse); + + } catch (IllegalAccessException iae) { + throw new SyslogRuntimeException(iae); + + } catch (InstantiationException ie) { + throw new SyslogRuntimeException(ie); + } + + syslogServer.initialize(syslogProtocol,config); + + instances.put(syslogProtocol,syslogServer); + } + + return syslogServer; + } + + public static final SyslogServerIF createThreadedInstance(String protocol, SyslogServerConfigIF config) throws SyslogRuntimeException { + createInstance(protocol,config); + + SyslogServerIF server = getThreadedInstance(protocol); + + return server; + } + + public synchronized static final void destroyInstance(String protocol) { + if (protocol == null || "".equals(protocol.trim())) { + return; + } + + String _protocol = protocol.toLowerCase(); + + if (instances.containsKey(_protocol)) { + SyslogUtility.sleep(SyslogConstants.THREAD_LOOP_INTERVAL_DEFAULT); + + SyslogServerIF syslogServer = (SyslogServerIF) instances.get(_protocol); + + try { + syslogServer.shutdown(); + + } finally { + instances.remove(_protocol); + } + + } else { + throwRuntimeException("Cannot destroy server protocol \"" + protocol + "\" instance; call shutdown instead"); + return; + } + } + + public synchronized static final void destroyInstance(SyslogServerIF syslogServer) { + if (syslogServer == null) { + return; + } + + String protocol = syslogServer.getProtocol().toLowerCase(); + + if (instances.containsKey(protocol)) { + SyslogUtility.sleep(SyslogConstants.THREAD_LOOP_INTERVAL_DEFAULT); + + try { + syslogServer.shutdown(); + + } finally { + instances.remove(protocol); + } + + } else { + throwRuntimeException("Cannot destroy server protocol \"" + protocol + "\" instance; call shutdown instead"); + } + } + + public synchronized static void initialize() { + createInstance(UDP,new UDPNetSyslogServerConfig()); + createInstance(TCP,new TCPNetSyslogServerConfig()); + } + + public synchronized static final void shutdown() throws SyslogRuntimeException { + Set protocols = instances.keySet(); + + Iterator i = protocols.iterator(); + + while(i.hasNext()) { + String protocol = (String) i.next(); + + SyslogServerIF syslogServer = (SyslogServerIF) instances.get(protocol); + + syslogServer.shutdown(); + } + + instances.clear(); + } + + public static void main(String[] args) throws Exception { + SyslogServerMain.main(args); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerConfigIF.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerConfigIF.java new file mode 100644 index 0000000..f0e5491 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerConfigIF.java @@ -0,0 +1,50 @@ +package org.productivity.java.syslog4j.server; + +import java.util.List; + +import org.productivity.java.syslog4j.SyslogCharSetIF; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; + +/** +* SyslogServerConfigIF provides a common, extensible configuration interface for all +* implementations of SyslogServerIF. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogServerConfigIF.java,v 1.12 2011/01/11 05:11:13 cvs Exp $ +*/ +public interface SyslogServerConfigIF extends SyslogConstants, SyslogCharSetIF { + public Class getSyslogServerClass(); + + public String getHost(); + public void setHost(String host) throws SyslogRuntimeException; + + public int getPort(); + public void setPort(int port) throws SyslogRuntimeException; + + public boolean isUseDaemonThread(); + public void setUseDaemonThread(boolean useDaemonThread); + + public int getThreadPriority(); + public void setThreadPriority(int threadPriority); + + public List getEventHandlers(); + + public long getShutdownWait(); + public void setShutdownWait(long shutdownWait); + + public void addEventHandler(SyslogServerEventHandlerIF eventHandler); + public void insertEventHandler(int pos, SyslogServerEventHandlerIF eventHandler); + public void removeEventHandler(SyslogServerEventHandlerIF eventHandler); + public void removeAllEventHandlers(); + + public boolean isUseStructuredData(); + public void setUseStructuredData(boolean useStructuredData); + + public Object getDateTimeFormatter(); + public void setDateTimeFormatter(Object dateTimeFormatter); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerEventHandlerIF.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerEventHandlerIF.java new file mode 100644 index 0000000..5d60558 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerEventHandlerIF.java @@ -0,0 +1,8 @@ +package org.productivity.java.syslog4j.server; + +import java.io.Serializable; + +public abstract interface SyslogServerEventHandlerIF extends Serializable { + public void initialize(SyslogServerIF syslogServer); + public void destroy(SyslogServerIF syslogServer); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerEventIF.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerEventIF.java new file mode 100644 index 0000000..cc578e0 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerEventIF.java @@ -0,0 +1,41 @@ +package org.productivity.java.syslog4j.server; + +import java.util.Date; + +import org.productivity.java.syslog4j.SyslogCharSetIF; + +/** +* SyslogServerEventIF provides an extensible interface for Syslog4j +* server events. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogServerEventIF.java,v 1.4 2010/11/28 01:38:08 cvs Exp $ +*/ +public interface SyslogServerEventIF extends SyslogCharSetIF { + /** + * Note: getRaw() may use System.arraycopy(..) each time it is called; best to call it once and store the result. + * + * @return Returns the raw data received from the client. + */ + public byte[] getRaw(); + + public int getFacility(); + public void setFacility(int facility); + + public Date getDate(); + public void setDate(Date date); + + public int getLevel(); + public void setLevel(int level); + + public String getHost(); + public void setHost(String host); + public boolean isHostStrippedFromMessage(); + + public String getMessage(); + public void setMessage(String message); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerIF.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerIF.java new file mode 100644 index 0000000..42f4433 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerIF.java @@ -0,0 +1,27 @@ +package org.productivity.java.syslog4j.server; + +import org.productivity.java.syslog4j.SyslogRuntimeException; + +/** +* SyslogServerIF provides a common interface for all Syslog4j server implementations. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogServerIF.java,v 1.5 2008/11/07 15:15:41 cvs Exp $ +*/ +public interface SyslogServerIF extends Runnable { + public void initialize(String protocol, SyslogServerConfigIF config) throws SyslogRuntimeException; + + public String getProtocol(); + public SyslogServerConfigIF getConfig(); + + public void run(); + + public Thread getThread(); + public void setThread(Thread thread); + + public void shutdown(); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerMain.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerMain.java new file mode 100644 index 0000000..6637f94 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerMain.java @@ -0,0 +1,165 @@ +package org.productivity.java.syslog4j.server; + +import org.productivity.java.syslog4j.server.impl.event.printstream.FileSyslogServerEventHandler; +import org.productivity.java.syslog4j.server.impl.event.printstream.SystemOutSyslogServerEventHandler; +import org.productivity.java.syslog4j.server.impl.net.tcp.TCPNetSyslogServerConfigIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** + * This class provides a command-line interface for Syslog4j + * server implementations. + * + *Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy + * of the LGPL license is available in the META-INF folder in all + * distributions of Syslog4j and in the base directory of the "doc" ZIP.
+ * + * @author <syslog4j@productivity.org> + * @version $Id: SyslogServerMain.java,v 1.3 2010/11/28 01:38:08 cvs Exp $ + */ +public class SyslogServerMain { + public static boolean CALL_SYSTEM_EXIT_ON_FAILURE = true; + + public static class Options { + public String protocol = null; + public String fileName = null; + public boolean append = false; + public boolean quiet = false; + + public String host = null; + public String port = null; + public String timeout = null; + + public String usage = null; + } + + public static void usage(String problem) { + if (problem != null) { + System.out.println("Error: " + problem); + System.out.println(); + } + + System.out.println("Usage:"); + System.out.println(); + System.out.println("SyslogServer [-hSyslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogServerSessionlessEventHandlerIF.java,v 1.1 2010/11/12 02:56:44 cvs Exp $ +*/ +public interface SyslogServerSessionlessEventHandlerIF extends SyslogServerEventHandlerIF { + public void event(SyslogServerIF syslogServer, SocketAddress socketAddress, SyslogServerEventIF event); + public void exception(SyslogServerIF syslogServer, SocketAddress socketAddress, Exception exception); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer.java b/src/main/java/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer.java new file mode 100644 index 0000000..d8cc44b --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer.java @@ -0,0 +1,339 @@ +package org.productivity.java.syslog4j.server.impl; + +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.productivity.java.syslog4j.SyslogCharSetIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.server.SyslogServerConfigIF; +import org.productivity.java.syslog4j.server.SyslogServerEventHandlerIF; +import org.productivity.java.syslog4j.server.SyslogServerEventIF; +import org.productivity.java.syslog4j.server.SyslogServerIF; +import org.productivity.java.syslog4j.server.SyslogServerSessionEventHandlerIF; +import org.productivity.java.syslog4j.server.SyslogServerSessionlessEventHandlerIF; +import org.productivity.java.syslog4j.server.impl.event.SyslogServerEvent; +import org.productivity.java.syslog4j.server.impl.event.structured.StructuredSyslogServerEvent; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* AbstractSyslogServer provides a base abstract implementation of the SyslogServerIF. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: AbstractSyslogServer.java,v 1.12 2011/01/11 05:11:13 cvs Exp $ +*/ +public abstract class AbstractSyslogServer implements SyslogServerIF { + public static class Sessions extends HashMap { + private static final long serialVersionUID = -4438949276263772580L; + + public static final Object syncObject = new Object(); + + public void addSocket(Socket socket) { + synchronized(syncObject) { + put(socket,new HashMap()); + } + } + + public Iterator getSockets() { + if (size() > 0) { + return keySet().iterator(); + + } else { + return null; + } + } + + public void addSession(Socket socket, SyslogServerEventHandlerIF eventHandler, Object session) { + synchronized(syncObject) { + Map handlerMap = getHandlerMap(socket); + + if (handlerMap == null) { + handlerMap = new HashMap(); + } + + handlerMap.put(eventHandler,session); + } + } + + public void removeSocket(Socket socket) { + synchronized(syncObject) { + Map handlerMap = getHandlerMap(socket); + + if (handlerMap != null) { + handlerMap.clear(); + } + } + } + + protected Map getHandlerMap(Socket socket) { + Map handlerMap = null; + + if (containsKey(socket)) { + handlerMap = (Map) get(socket); + } + + return handlerMap; + } + + public Object getSession(Socket socket, SyslogServerEventHandlerIF eventHandler) { + synchronized(syncObject) { + Map handlerMap = getHandlerMap(socket); + + Object session = handlerMap.get(eventHandler); + + return session; + } + } + } + + protected String syslogProtocol = null; + protected AbstractSyslogServerConfig syslogServerConfig = null; + protected Thread thread = null; + + protected boolean shutdown = false; + + public void initialize(String protocol, SyslogServerConfigIF config) throws SyslogRuntimeException { + this.syslogProtocol = protocol; + + try { + this.syslogServerConfig = (AbstractSyslogServerConfig) config; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException(cce); + } + + initialize(); + } + + public String getProtocol() { + return this.syslogProtocol; + } + + public SyslogServerConfigIF getConfig() { + return this.syslogServerConfig; + } + + protected abstract void initialize() throws SyslogRuntimeException; + + public void shutdown() throws SyslogRuntimeException { + this.shutdown = true; + } + + public Thread getThread() { + return this.thread; + } + + public void setThread(Thread thread) { + this.thread = thread; + } + + protected static boolean isStructuredMessage(SyslogCharSetIF syslogCharSet, byte[] receiveData) { + String receiveDataString = SyslogUtility.newString(syslogCharSet, receiveData); + + boolean isStructuredMessage = isStructuredMessage(syslogCharSet,receiveDataString); + + return isStructuredMessage; + } + + protected static boolean isStructuredMessage(SyslogCharSetIF syslogCharSet, String receiveData) { + int idx = receiveData.indexOf('>'); + + if (idx != -1) { + // If there's a numerical VERSION field after theSyslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogServerEvent.java,v 1.9 2011/01/11 06:21:15 cvs Exp $ +*/ +public class SyslogServerEvent implements SyslogServerEventIF { + private static final long serialVersionUID = 6136043067089899962L; + + public static final String DATE_FORMAT = "MMM dd HH:mm:ss yyyy"; + public static final String DATE_FORMAT_S = "MMM d HH:mm:ss yyyy"; + + protected String charSet = SyslogConstants.CHAR_SET_DEFAULT; + protected String rawString = null; + protected byte[] rawBytes = null; + protected int rawLength = -1; + protected Date date = null; + protected int level = -1; + protected int facility = -1; + protected String host = null; + protected boolean isHostStrippedFromMessage = false; + protected String message = null; + protected InetAddress inetAddress = null; + + protected SyslogServerEvent() { } + + public SyslogServerEvent(final String message, InetAddress inetAddress) { + initialize(message,inetAddress); + + parse(); + } + + public SyslogServerEvent(final byte[] message, int length, InetAddress inetAddress) { + initialize(message,length,inetAddress); + + parse(); + } + + protected void initialize(final String message, InetAddress inetAddress) { + this.rawString = message; + this.rawLength = message.length(); + this.inetAddress = inetAddress; + + this.message = message; + } + + protected void initialize(final byte[] message, int length, InetAddress inetAddress) { + this.rawBytes = message; + this.rawLength = length; + this.inetAddress = inetAddress; + } + + protected void parseHost() { + int i = this.message.indexOf(' '); + + if (i > -1) { + this.host = this.message.substring(0,i).trim(); + } + } + + protected void parseDate() { + int datelength = 16; + String dateFormatS = DATE_FORMAT; + + if (this.message.length() > datelength) { + + // http://jira.graylog2.org/browse/SERVER-287 + if (this.message.charAt(5) == ' ') { + datelength = 15; + dateFormatS = DATE_FORMAT_S; + } + + String year = Integer.toString(Calendar.getInstance().get(Calendar.YEAR)); + + String originalDate = this.message.substring(0,datelength-1) + " " + year; + DateFormat dateFormat = new SimpleDateFormat(dateFormatS); + try { + this.date = dateFormat.parse(originalDate); + + this.message = this.message.substring(datelength); + + } catch (ParseException pe) { + this.date = new Date(); + } + } + + parseHost(); + } + + protected void parsePriority() { + if (this.message.charAt(0) == '<') { + int i = this.message.indexOf(">"); + + if (i <= 4 && i > -1) { + String priorityStr = this.message.substring(1,i); + + int priority = 0; + try { + priority = Integer.parseInt(priorityStr); + this.facility = priority >> 3; + this.level = priority - (this.facility << 3); + + this.message = this.message.substring(i+1); + + parseDate(); + + } catch (NumberFormatException nfe) { + // + } + + parseHost(); + } + } + } + + protected void parse() { + if (this.message == null) { + this.message = SyslogUtility.newString(this,this.rawBytes,this.rawLength); + } + + parsePriority(); + } + + public int getFacility() { + return this.facility; + } + + public void setFacility(int facility) { + this.facility = facility; + } + + public byte[] getRaw() { + if (this.rawString != null) { + byte[] rawStringBytes = SyslogUtility.getBytes(this,this.rawString); + + return rawStringBytes; + + } else if (this.rawBytes.length == this.rawLength) { + return this.rawBytes; + + } else { + byte[] newRawBytes = new byte[this.rawLength]; + System.arraycopy(this.rawBytes,0,newRawBytes,0,this.rawLength); + + return newRawBytes; + } + } + + public int getRawLength() { + return this.rawLength; + } + + public Date getDate() { + return this.date; + } + + public void setDate(Date date) { + this.date = date; + } + + public int getLevel() { + return this.level; + } + + public void setLevel(int level) { + this.level = level; + } + + public String getHost() { + return this.host; + } + + public void setHost(String host) { + this.host = host; + } + + public boolean isHostStrippedFromMessage() { + return isHostStrippedFromMessage; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getCharSet() { + return this.charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/FileSyslogServerEventHandler.java b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/FileSyslogServerEventHandler.java new file mode 100644 index 0000000..7bf53b4 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/FileSyslogServerEventHandler.java @@ -0,0 +1,29 @@ +package org.productivity.java.syslog4j.server.impl.event.printstream; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + +public class FileSyslogServerEventHandler extends PrintStreamSyslogServerEventHandler { + private static final long serialVersionUID = -755824686809731430L; + + protected static PrintStream createPrintStream(String fileName, boolean append) throws IOException { + File file = new File(fileName); + + OutputStream os = new FileOutputStream(file,append); + + PrintStream printStream = new PrintStream(os); + + return printStream; + } + + public FileSyslogServerEventHandler(String fileName) throws IOException { + super(createPrintStream(fileName,true)); + } + + public FileSyslogServerEventHandler(String fileName, boolean append) throws IOException { + super(createPrintStream(fileName,append)); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/PrintStreamSyslogServerEventHandler.java b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/PrintStreamSyslogServerEventHandler.java new file mode 100644 index 0000000..d161916 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/PrintStreamSyslogServerEventHandler.java @@ -0,0 +1,59 @@ +package org.productivity.java.syslog4j.server.impl.event.printstream; + +import java.io.PrintStream; +import java.net.SocketAddress; +import java.util.Date; + +import org.productivity.java.syslog4j.server.SyslogServerEventIF; +import org.productivity.java.syslog4j.server.SyslogServerIF; +import org.productivity.java.syslog4j.server.SyslogServerSessionEventHandlerIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* SystemOutSyslogServerEventHandler provides a simple example implementation +* of the SyslogServerEventHandlerIF which writes the events to System.out. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: PrintStreamSyslogServerEventHandler.java,v 1.7 2010/11/28 22:07:57 cvs Exp $ +*/ +public class PrintStreamSyslogServerEventHandler implements SyslogServerSessionEventHandlerIF { + private static final long serialVersionUID = 6036415838696050746L; + + protected PrintStream stream = null; + + public PrintStreamSyslogServerEventHandler(PrintStream stream) { + this.stream = stream; + } + + public void initialize(SyslogServerIF syslogServer) { + return; + } + + public Object sessionOpened(SyslogServerIF syslogServer, SocketAddress socketAddress) { + return null; + } + + public void event(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, SyslogServerEventIF event) { + String date = (event.getDate() == null ? new Date() : event.getDate()).toString(); + String facility = SyslogUtility.getFacilityString(event.getFacility()); + String level = SyslogUtility.getLevelString(event.getLevel()); + + this.stream.println("{" + facility + "} " + date + " " + level + " " + event.getMessage()); + } + + public void exception(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, Exception exception) { + // + } + + public void sessionClosed(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, boolean timeout) { + // + } + + public void destroy(SyslogServerIF syslogServer) { + return; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/SystemErrSyslogServerEventHandler.java b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/SystemErrSyslogServerEventHandler.java new file mode 100644 index 0000000..e61052e --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/SystemErrSyslogServerEventHandler.java @@ -0,0 +1,15 @@ +package org.productivity.java.syslog4j.server.impl.event.printstream; + +import org.productivity.java.syslog4j.server.SyslogServerSessionEventHandlerIF; + +public class SystemErrSyslogServerEventHandler extends PrintStreamSyslogServerEventHandler { + private static final long serialVersionUID = -3496862887351690575L; + + public static SyslogServerSessionEventHandlerIF create() { + return new SystemErrSyslogServerEventHandler(); + } + + public SystemErrSyslogServerEventHandler() { + super(System.err); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/SystemOutSyslogServerEventHandler.java b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/SystemOutSyslogServerEventHandler.java new file mode 100644 index 0000000..bfe38b8 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/event/printstream/SystemOutSyslogServerEventHandler.java @@ -0,0 +1,15 @@ +package org.productivity.java.syslog4j.server.impl.event.printstream; + +import org.productivity.java.syslog4j.server.SyslogServerSessionEventHandlerIF; + +public class SystemOutSyslogServerEventHandler extends PrintStreamSyslogServerEventHandler { + private static final long serialVersionUID = 1690551409588182601L; + + public static SyslogServerSessionEventHandlerIF create() { + return new SystemOutSyslogServerEventHandler(); + } + + public SystemOutSyslogServerEventHandler() { + super(System.out); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/event/structured/StructuredSyslogServerEvent.java b/src/main/java/org/productivity/java/syslog4j/server/impl/event/structured/StructuredSyslogServerEvent.java new file mode 100644 index 0000000..476f3ab --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/event/structured/StructuredSyslogServerEvent.java @@ -0,0 +1,151 @@ +package org.productivity.java.syslog4j.server.impl.event.structured; + +import java.net.InetAddress; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.impl.message.structured.StructuredSyslogMessage; +import org.productivity.java.syslog4j.server.impl.event.SyslogServerEvent; + +/** + * SyslogServerStructuredEvent provides an implementation of the + * SyslogServerEventIF interface that supports receiving of structured syslog + * messages, as defined in: + * + *+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6 + *
+ * + *+ * Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy of the + * LGPL license is available in the META-INF folder in all distributions of + * Syslog4j and in the base directory of the "doc" ZIP. + *
+ * + * @author Manish Motwani + * @version $Id: StructuredSyslogServerEvent.java,v 1.6 2011/01/11 05:11:13 cvs Exp $ + */ +public class StructuredSyslogServerEvent extends SyslogServerEvent { + private static final long serialVersionUID = 1676499796406044315L; + + protected String applicationName = SyslogConstants.STRUCTURED_DATA_APP_NAME_DEFAULT_VALUE; + protected String processId = null; + protected DateTime dateTime = null; + protected DateTimeFormatter dateTimeFormatter = null; + + public StructuredSyslogServerEvent(final byte[] message, int length, InetAddress inetAddress) { + super(); + + initialize(message,length,inetAddress); + parse(); + } + + public StructuredSyslogServerEvent(final String message, InetAddress inetAddress) { + super(); + + initialize(message,inetAddress); + parse(); + } + + public DateTimeFormatter getDateTimeFormatter() { + if (dateTimeFormatter == null) { + this.dateTimeFormatter = ISODateTimeFormat.dateTime(); + } + + return dateTimeFormatter; + } + + public void setDateTimeFormatter(Object dateTimeFormatter) { + this.dateTimeFormatter = (DateTimeFormatter) dateTimeFormatter; + } + + protected void parseApplicationName() { + int i = this.message.indexOf(' '); + + if (i > -1) { + this.applicationName = this.message.substring(0, i).trim(); + this.message = this.message.substring(i + 1); + parseProcessId(); + } + + if (SyslogConstants.STRUCTURED_DATA_NILVALUE.equals(this.applicationName)) { + this.applicationName = null; + } + } + + protected void parseProcessId() { + int i = this.message.indexOf(' '); + + if (i > -1) { + this.processId = this.message.substring(0, i).trim(); + this.message = this.message.substring(i + 1); + } + + if (SyslogConstants.STRUCTURED_DATA_NILVALUE.equals(this.processId)) { + this.processId = null; + } + } + + protected void parseDate() { + // skip VERSION field + int i = this.message.indexOf(' '); + this.message = this.message.substring(i + 1); + + // parse the date + i = this.message.indexOf(' '); + + if (i > -1) { + String dateString = this.message.substring(0, i).trim(); + + try { + DateTimeFormatter formatter = getDateTimeFormatter(); + + this.dateTime = formatter.parseDateTime(dateString); + this.date = this.dateTime.toDate(); + + this.message = this.message.substring(dateString.length() + 1); + + } catch (Exception e) { + // Not structured date format, try super one + super.parseDate(); + } + } + } + + protected void parseHost() { + int i = this.message.indexOf(' '); + + if (i > -1) { + this.host = this.message.substring(0,i).trim(); + this.message = this.message.substring(i+1); + + parseApplicationName(); + } + } + + public String getApplicationName() { + return this.applicationName; + } + + public String getProcessId() { + return this.processId; + } + + public DateTime getDateTime() { + return this.dateTime; + } + + public StructuredSyslogMessage getStructuredMessage() { + try { + return StructuredSyslogMessage.fromString(getMessage()); + + } catch (IllegalArgumentException e) { + // throw new SyslogRuntimeException( + // "Message received is not a valid structured message: " + // + getMessage(), e); + return new StructuredSyslogMessage(null,null,getMessage()); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/AbstractNetSyslogServerConfig.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/AbstractNetSyslogServerConfig.java new file mode 100644 index 0000000..31067f4 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/AbstractNetSyslogServerConfig.java @@ -0,0 +1,37 @@ +package org.productivity.java.syslog4j.server.impl.net; + +import org.productivity.java.syslog4j.server.impl.AbstractSyslogServerConfig; + +/** +* AbstractNetSyslogServerConfig provides a base abstract implementation of the AbstractSyslogServerConfig +* configuration interface. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: AbstractNetSyslogServerConfig.java,v 1.4 2008/11/07 15:15:41 cvs Exp $ +*/ +public abstract class AbstractNetSyslogServerConfig extends AbstractSyslogServerConfig { + private static final long serialVersionUID = -3363374941938350263L; + + protected String host = null; + protected int port = SYSLOG_PORT_DEFAULT; + + public String getHost() { + return this.host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return this.port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer.java new file mode 100644 index 0000000..9e47937 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer.java @@ -0,0 +1,252 @@ +package org.productivity.java.syslog4j.server.impl.net.tcp; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.util.Iterator; + +import javax.net.ServerSocketFactory; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.server.SyslogServerEventIF; +import org.productivity.java.syslog4j.server.SyslogServerIF; +import org.productivity.java.syslog4j.server.impl.AbstractSyslogServer; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* TCPNetSyslogServer provides a simple threaded TCP/IP server implementation. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslogServer.java,v 1.23 2010/11/28 22:07:57 cvs Exp $ +*/ +public class TCPNetSyslogServer extends AbstractSyslogServer { + public static class TCPNetSyslogSocketHandler implements Runnable { + protected SyslogServerIF server = null; + protected Socket socket = null; + protected Sessions sessions = null; + + public TCPNetSyslogSocketHandler(Sessions sessions, SyslogServerIF server, Socket socket) { + this.sessions = sessions; + this.server = server; + this.socket = socket; + + synchronized(this.sessions) { + this.sessions.addSocket(socket); + } + } + + public void run() { + boolean timeout = false; + + try { + BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); + + String line = br.readLine(); + + if (line != null) { + AbstractSyslogServer.handleSessionOpen(this.sessions,this.server,this.socket); + } + + while (line != null && line.length() != 0) { + SyslogServerEventIF event = createEvent(this.server.getConfig(),line,this.socket.getInetAddress()); + + AbstractSyslogServer.handleEvent(this.sessions,this.server,this.socket,event); + + line = br.readLine(); + } + + } catch (SocketTimeoutException ste) { + timeout = true; + + } catch (SocketException se) { + AbstractSyslogServer.handleException(this.sessions,this.server,this.socket.getRemoteSocketAddress(),se); + + if ("Socket closed".equals(se.getMessage())) { + // + + } else { + // + } + + } catch (IOException ioe) { + AbstractSyslogServer.handleException(this.sessions,this.server,this.socket.getRemoteSocketAddress(),ioe); + } + + try { + AbstractSyslogServer.handleSessionClosed(this.sessions,this.server,this.socket,timeout); + + this.sessions.removeSocket(this.socket); + + this.socket.close(); + + } catch (IOException ioe) { + AbstractSyslogServer.handleException(this.sessions,this.server,this.socket.getRemoteSocketAddress(),ioe); + } + } + } + + protected ServerSocket serverSocket = null; + + protected final Sessions sessions = new Sessions(); + + protected TCPNetSyslogServerConfigIF tcpNetSyslogServerConfig = null; + + public void initialize() throws SyslogRuntimeException { + this.tcpNetSyslogServerConfig = null; + + try { + this.tcpNetSyslogServerConfig = (TCPNetSyslogServerConfigIF) this.syslogServerConfig; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must be of type TCPNetSyslogServerConfig"); + } + + if (this.syslogServerConfig == null) { + throw new SyslogRuntimeException("config cannot be null"); + } + + if (this.tcpNetSyslogServerConfig.getBacklog() < 1) { + this.tcpNetSyslogServerConfig.setBacklog(SyslogConstants.SERVER_SOCKET_BACKLOG_DEFAULT); + } + } + + public Sessions getSessions() { + return this.sessions; + } + + public synchronized void shutdown() { + super.shutdown(); + + try { + if (this.serverSocket != null) { + if (this.syslogServerConfig.getShutdownWait() > 0) { + SyslogUtility.sleep(this.syslogServerConfig.getShutdownWait()); + } + + this.serverSocket.close(); + } + + synchronized(this.sessions) { + Iterator i = this.sessions.getSockets(); + + if (i != null) { + while(i.hasNext()) { + Socket s = (Socket) i.next(); + + s.close(); + } + } + } + + } catch (IOException ioe) { + // + } + + if (this.thread != null) { + this.thread.interrupt(); + this.thread = null; + } + } + + protected ServerSocketFactory getServerSocketFactory() throws IOException { + ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault(); + + return serverSocketFactory; + } + + protected ServerSocket createServerSocket() throws IOException { + ServerSocket newServerSocket = null; + + ServerSocketFactory factory = getServerSocketFactory(); + + if (this.syslogServerConfig.getHost() != null) { + InetAddress inetAddress = InetAddress.getByName(this.syslogServerConfig.getHost()); + + newServerSocket = factory.createServerSocket(this.syslogServerConfig.getPort(),this.tcpNetSyslogServerConfig.getBacklog(),inetAddress); + + } else { + if (this.tcpNetSyslogServerConfig.getBacklog() < 1) { + newServerSocket = factory.createServerSocket(this.syslogServerConfig.getPort()); + + } else { + newServerSocket = factory.createServerSocket(this.syslogServerConfig.getPort(),this.tcpNetSyslogServerConfig.getBacklog()); + } + } + + return newServerSocket; + } + + public void run() { + try { + this.serverSocket = createServerSocket(); + this.shutdown = false; + + } catch (SocketException se) { + throw new SyslogRuntimeException(se); + + } catch (IOException ioe) { + throw new SyslogRuntimeException(ioe); + } + + handleInitialize(this); + + while(!this.shutdown) { + try { + Socket socket = this.serverSocket.accept(); + + if (this.tcpNetSyslogServerConfig.getTimeout() > 0) { + socket.setSoTimeout(this.tcpNetSyslogServerConfig.getTimeout()); + } + + if (this.tcpNetSyslogServerConfig.getMaxActiveSockets() > 0 && this.sessions.size() >= this.tcpNetSyslogServerConfig.getMaxActiveSockets()) { + if (this.tcpNetSyslogServerConfig.getMaxActiveSocketsBehavior() == TCPNetSyslogServerConfigIF.MAX_ACTIVE_SOCKETS_BEHAVIOR_REJECT) { + try { + socket.close(); + + } catch (Exception e) { + // + } + + socket = null; + + } else if (this.tcpNetSyslogServerConfig.getMaxActiveSocketsBehavior() == TCPNetSyslogServerConfigIF.MAX_ACTIVE_SOCKETS_BEHAVIOR_BLOCK) { + while (!this.shutdown && this.sessions.size() >= this.tcpNetSyslogServerConfig.getMaxActiveSockets() && socket.isConnected() && !socket.isClosed()) { + SyslogUtility.sleep(SyslogConstants.THREAD_LOOP_INTERVAL_DEFAULT); + } + } + } + + if (socket != null) { + TCPNetSyslogSocketHandler handler = new TCPNetSyslogSocketHandler(this.sessions,this,socket); + + Thread t = new Thread(handler); + + t.start(); + } + + } catch (SocketException se) { + if ("Socket closed".equals(se.getMessage())) { + this.shutdown = true; + + } else { + // + } + + } catch (IOException ioe) { + // + } + } + + handleDestroy(this); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfig.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfig.java new file mode 100644 index 0000000..aabe4d9 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfig.java @@ -0,0 +1,86 @@ +package org.productivity.java.syslog4j.server.impl.net.tcp; + +import org.productivity.java.syslog4j.server.impl.net.AbstractNetSyslogServerConfig; + +/** +* TCPNetSyslogServerConfig provides configuration for TCPNetSyslogServer. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslogServerConfig.java,v 1.8 2010/11/28 01:38:08 cvs Exp $ +*/ +public class TCPNetSyslogServerConfig extends AbstractNetSyslogServerConfig implements TCPNetSyslogServerConfigIF { + private static final long serialVersionUID = -1546696301177599370L; + + protected int timeout = 0; + protected int backlog = 0; + protected int maxActiveSockets = TCP_MAX_ACTIVE_SOCKETS_DEFAULT; + protected byte maxActiveSocketsBehavior = TCP_MAX_ACTIVE_SOCKETS_BEHAVIOR_DEFAULT; + + public TCPNetSyslogServerConfig() { + // + } + + public TCPNetSyslogServerConfig(int port) { + this.port = port; + } + + public TCPNetSyslogServerConfig(int port, int backlog) { + this.port = port; + this.backlog = backlog; + } + + public TCPNetSyslogServerConfig(String host) { + this.host = host; + } + + public TCPNetSyslogServerConfig(String host, int port) { + this.host = host; + this.port = port; + } + + public TCPNetSyslogServerConfig(String host, int port, int backlog) { + this.host = host; + this.port = port; + this.backlog = backlog; + } + + public Class getSyslogServerClass() { + return TCPNetSyslogServer.class; + } + + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + public int getBacklog() { + return this.backlog; + } + + public void setBacklog(int backlog) { + this.backlog = backlog; + } + + public int getMaxActiveSockets() { + return maxActiveSockets; + } + + public void setMaxActiveSockets(int maxActiveSockets) { + this.maxActiveSockets = maxActiveSockets; + } + + public byte getMaxActiveSocketsBehavior() { + return maxActiveSocketsBehavior; + } + + public void setMaxActiveSocketsBehavior(byte maxActiveSocketsBehavior) { + this.maxActiveSocketsBehavior = maxActiveSocketsBehavior; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfigIF.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfigIF.java new file mode 100644 index 0000000..090d79b --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfigIF.java @@ -0,0 +1,30 @@ +package org.productivity.java.syslog4j.server.impl.net.tcp; + +import org.productivity.java.syslog4j.server.SyslogServerConfigIF; + +/** +* TCPNetSyslogServerConfigIF provides configuration for TCPNetSyslogServer. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: TCPNetSyslogServerConfigIF.java,v 1.3 2010/11/28 01:38:08 cvs Exp $ +*/ +public interface TCPNetSyslogServerConfigIF extends SyslogServerConfigIF { + public final static byte MAX_ACTIVE_SOCKETS_BEHAVIOR_BLOCK = 0; + public final static byte MAX_ACTIVE_SOCKETS_BEHAVIOR_REJECT = 1; + + public int getTimeout(); + public void setTimeout(int timeout); + + public int getBacklog(); + public void setBacklog(int backlog); + + public int getMaxActiveSockets(); + public void setMaxActiveSockets(int maxActiveSockets); + + public byte getMaxActiveSocketsBehavior(); + public void setMaxActiveSocketsBehavior(byte maxActiveSocketsBehavior); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServer.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServer.java new file mode 100644 index 0000000..7c45993 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServer.java @@ -0,0 +1,58 @@ +package org.productivity.java.syslog4j.server.impl.net.tcp.ssl; + +import java.io.IOException; + +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLServerSocketFactory; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.server.impl.net.tcp.TCPNetSyslogServer; + +/** +* SSLTCPNetSyslogServer provides a simple threaded TCP/IP server implementation +* which uses SSL/TLS. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslogServer.java,v 1.1 2009/03/29 17:38:58 cvs Exp $ +*/ +public class SSLTCPNetSyslogServer extends TCPNetSyslogServer { + public void initialize() throws SyslogRuntimeException { + super.initialize(); + + SSLTCPNetSyslogServerConfigIF sslTcpNetSyslogServerConfig = (SSLTCPNetSyslogServerConfigIF) this.tcpNetSyslogServerConfig; + + String keyStore = sslTcpNetSyslogServerConfig.getKeyStore(); + + if (keyStore != null && !"".equals(keyStore.trim())) { + System.setProperty("javax.net.ssl.keyStore",keyStore); + } + + String keyStorePassword = sslTcpNetSyslogServerConfig.getKeyStorePassword(); + + if (keyStorePassword != null && !"".equals(keyStorePassword.trim())) { + System.setProperty("javax.net.ssl.keyStorePassword",keyStorePassword); + } + + String trustStore = sslTcpNetSyslogServerConfig.getTrustStore(); + + if (trustStore != null && !"".equals(trustStore.trim())) { + System.setProperty("javax.net.ssl.trustStore",trustStore); + } + + String trustStorePassword = sslTcpNetSyslogServerConfig.getTrustStorePassword(); + + if (trustStorePassword != null && !"".equals(trustStorePassword.trim())) { + System.setProperty("javax.net.ssl.trustStorePassword",trustStorePassword); + } + } + + protected ServerSocketFactory getServerSocketFactory() throws IOException { + ServerSocketFactory serverSocketFactory = SSLServerSocketFactory.getDefault(); + + return serverSocketFactory; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfig.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfig.java new file mode 100644 index 0000000..e0beb66 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfig.java @@ -0,0 +1,59 @@ +package org.productivity.java.syslog4j.server.impl.net.tcp.ssl; + +import org.productivity.java.syslog4j.server.impl.net.tcp.TCPNetSyslogServerConfig; + +/** +* SSLTCPNetSyslogServerConfig provides configuration for SSLTCPNetSyslogServer. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslogServerConfig.java,v 1.1 2009/03/29 17:38:58 cvs Exp $ +*/ +public class SSLTCPNetSyslogServerConfig extends TCPNetSyslogServerConfig implements SSLTCPNetSyslogServerConfigIF { + private static final long serialVersionUID = -840102682868286462L; + + protected String keyStore = null; + protected String keyStorePassword = null; + + protected String trustStore = null; + protected String trustStorePassword = null; + + public String getKeyStore() { + return this.keyStore; + } + + public void setKeyStore(String keyStore) { + this.keyStore = keyStore; + } + + public String getKeyStorePassword() { + return this.keyStorePassword; + } + + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + + public String getTrustStore() { + return this.trustStore; + } + + public void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + public String getTrustStorePassword() { + return this.trustStorePassword; + } + + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + public Class getSyslogServerClass() { + return SSLTCPNetSyslogServer.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfigIF.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfigIF.java new file mode 100644 index 0000000..cab8079 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfigIF.java @@ -0,0 +1,27 @@ +package org.productivity.java.syslog4j.server.impl.net.tcp.ssl; + +import org.productivity.java.syslog4j.server.impl.net.tcp.TCPNetSyslogServerConfigIF; + +/** +* SSLTCPNetSyslogServerConfigIF provides configuration for SSLTCPNetSyslogServer. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SSLTCPNetSyslogServerConfigIF.java,v 1.1 2009/03/29 17:38:58 cvs Exp $ +*/ +public interface SSLTCPNetSyslogServerConfigIF extends TCPNetSyslogServerConfigIF { + public String getKeyStore(); + public void setKeyStore(String keyStore); + + public String getKeyStorePassword(); + public void setKeyStorePassword(String keyStorePassword); + + public String getTrustStore(); + public void setTrustStore(String trustStore); + + public String getTrustStorePassword(); + public void setTrustStorePassword(String trustStorePassword); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServer.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServer.java new file mode 100644 index 0000000..f5b803d --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServer.java @@ -0,0 +1,102 @@ +package org.productivity.java.syslog4j.server.impl.net.udp; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.server.SyslogServerEventIF; +import org.productivity.java.syslog4j.server.impl.AbstractSyslogServer; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* UDPNetSyslogServer provides a simple non-threaded UDP/IP server implementation. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UDPNetSyslogServer.java,v 1.16 2010/11/12 03:43:15 cvs Exp $ +*/ +public class UDPNetSyslogServer extends AbstractSyslogServer { + protected DatagramSocket ds = null; + + public void initialize() throws SyslogRuntimeException { + // + } + + public void shutdown() { + super.shutdown(); + + if (this.syslogServerConfig.getShutdownWait() > 0) { + SyslogUtility.sleep(this.syslogServerConfig.getShutdownWait()); + } + + if (this.ds != null && !this.ds.isClosed()) { + this.ds.close(); + } + } + + protected DatagramSocket createDatagramSocket() throws SocketException, UnknownHostException { + DatagramSocket datagramSocket = null; + + if (this.syslogServerConfig.getHost() != null) { + InetAddress inetAddress = InetAddress.getByName(this.syslogServerConfig.getHost()); + + datagramSocket = new DatagramSocket(this.syslogServerConfig.getPort(),inetAddress); + + } else { + datagramSocket = new DatagramSocket(this.syslogServerConfig.getPort()); + } + + return datagramSocket; + } + + public void run() { + try { + this.ds = createDatagramSocket(); + this.shutdown = false; + + } catch (SocketException se) { + return; + + } catch (UnknownHostException uhe) { + return; + } + + byte[] receiveData = new byte[SyslogConstants.SYSLOG_BUFFER_SIZE]; + + handleInitialize(this); + + while(!this.shutdown) { + DatagramPacket dp = null; + + try { + dp = new DatagramPacket(receiveData,receiveData.length); + + this.ds.receive(dp); + + SyslogServerEventIF event = createEvent(this.getConfig(),receiveData,dp.getLength(),dp.getAddress()); + + handleEvent(null,this,dp,event); + + } catch (SocketException se) { + int i = se.getMessage() == null ? -1 : se.getMessage().toLowerCase().indexOf("socket closed"); + + if (i == -1) { + handleException(null,this,dp.getSocketAddress(),se); + } + + } catch (IOException ioe) { + handleException(null,this,dp.getSocketAddress(),ioe); + } + } + + handleDestroy(this); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServerConfig.java b/src/main/java/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServerConfig.java new file mode 100644 index 0000000..bd56c2f --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServerConfig.java @@ -0,0 +1,38 @@ +package org.productivity.java.syslog4j.server.impl.net.udp; + +import org.productivity.java.syslog4j.server.impl.net.AbstractNetSyslogServerConfig; + +/** +* UDPNetSyslogServerConfig provides configuration for UDPNetSyslogServer. +* +*Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: UDPNetSyslogServerConfig.java,v 1.6 2010/10/28 05:10:57 cvs Exp $ +*/ +public class UDPNetSyslogServerConfig extends AbstractNetSyslogServerConfig { + private static final long serialVersionUID = -2005919161187055486L; + + public UDPNetSyslogServerConfig() { + // + } + + public UDPNetSyslogServerConfig(int port) { + this.port = port; + } + + public UDPNetSyslogServerConfig(String host) { + this.host = host; + } + + public UDPNetSyslogServerConfig(String host, int port) { + this.host = host; + this.port = port; + } + + public Class getSyslogServerClass() { + return UDPNetSyslogServer.class; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/util/Base64.java b/src/main/java/org/productivity/java/syslog4j/util/Base64.java new file mode 100644 index 0000000..cb385e5 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/util/Base64.java @@ -0,0 +1,1815 @@ +package org.productivity.java.syslog4j.util; + +/** + *Encodes and decodes to and from Base64 notation.
+ *Homepage: http://iharder.net/base64.
+ * + *The options parameter, which appears in a few places, is used to pass + * several pieces of information to the encoder. In the "higher level" methods such as + * encodeBytes( bytes, options ) the options parameter can be used to indicate such + * things as first gzipping the bytes before encoding them, not inserting linefeeds + * (though that breaks strict Base64 compatibility), and encoding using the URL-safe + * and Ordered dialects.
+ * + *The constants defined in Base64 can be OR-ed together to combine options, so you + * might make a call like this:
+ * + *String encoded = Base64.encodeBytes( mybytes, Base64.GZIP | Base64.DONT_BREAK_LINES );
+ *
+ * to compress the data before encoding it and then making the output have no newline characters.
+ * + * + *+ * Change Log: + *
+ *+ * I am placing this code in the Public Domain. Do with it as you will. + * This software comes with no guarantees or warranties but with + * plenty of well-wishing instead! + * Please visit http://iharder.net/base64 + * periodically to check for updates or to contribute improvements. + *
+ * + * @author Robert Harder + * @author rob@iharder.net + * @version 2.2.2 + */ +public class Base64 +{ + +/* ******** P U B L I C F I E L D S ******** */ + + + /** No options specified. Value is zero. */ + public final static int NO_OPTIONS = 0; + + /** Specify encoding. */ + public final static int ENCODE = 1; + + + /** Specify decoding. */ + public final static int DECODE = 0; + + + /** Specify that data should be gzip-compressed. */ + public final static int GZIP = 2; + + + /** Don't break lines when encoding (violates strict Base64 specification) */ + public final static int DONT_BREAK_LINES = 8; + + /** + * Encode using Base64-like encoding that is URL- and Filename-safe as described + * in Section 4 of RFC3548: + * http://www.faqs.org/rfcs/rfc3548.html. + * It is important to note that data encoded this way is not officially valid Base64, + * or at the very least should not be called Base64 without also specifying that is + * was encoded using the URL- and Filename-safe dialect. + */ + public final static int URL_SAFE = 16; + + + /** + * Encode using the special "ordered" dialect of Base64 described here: + * http://www.faqs.org/qa/rfcc-1940.html. + */ + public final static int ORDERED = 32; + + +/* ******** P R I V A T E F I E L D S ******** */ + + + /** Maximum line length (76) of Base64 output. */ + private final static int MAX_LINE_LENGTH = 76; + + + /** The equals sign (=) as a byte. */ + private final static byte EQUALS_SIGN = (byte)'='; + + + /** The new line character (\n) as a byte. */ + private final static byte NEW_LINE = (byte)'\n'; + + + /** Preferred encoding. */ + private final static String PREFERRED_ENCODING = "UTF-8"; + + + // I think I end up not using the BAD_ENCODING indicator. + //private final static byte BAD_ENCODING = -9; // Indicates error in encoding + private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding + private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding + + +/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ + + /** The 64 valid Base64 values. */ + //private final static byte[] ALPHABET; + /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ + private final static byte[] _STANDARD_ALPHABET = + { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' + }; + + + /** + * Translates a Base64 value to either its 6-bit reconstruction value + * or a negative number indicating some other meaning. + **/ + private final static byte[] _STANDARD_DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + 62, // Plus sign at decimal 43 + -9,-9,-9, // Decimal 44 - 46 + 63, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9,-9,-9, // Decimal 91 - 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + +/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ + + /** + * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: + * http://www.faqs.org/rfcs/rfc3548.html. + * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash." + */ + private final static byte[] _URL_SAFE_ALPHABET = + { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_' + }; + + /** + * Used in decoding URL- and Filename-safe dialects of Base64. + */ + private final static byte[] _URL_SAFE_DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + -9, // Plus sign at decimal 43 + -9, // Decimal 44 + 62, // Minus sign at decimal 45 + -9, // Decimal 46 + -9, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9, // Decimal 91 - 94 + 63, // Underscore at decimal 95 + -9, // Decimal 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + + +/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */ + + /** + * I don't get the point of this technique, but it is described here: + * http://www.faqs.org/qa/rfcc-1940.html. + */ + private final static byte[] _ORDERED_ALPHABET = + { + (byte)'-', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', + (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'_', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z' + }; + + /** + * Used in decoding the "ordered" dialect of Base64. + */ + private final static byte[] _ORDERED_DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + -9, // Plus sign at decimal 43 + -9, // Decimal 44 + 0, // Minus sign at decimal 45 + -9, // Decimal 46 + -9, // Slash at decimal 47 + 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M' + 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z' + -9,-9,-9,-9, // Decimal 91 - 94 + 37, // Underscore at decimal 95 + -9, // Decimal 96 + 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm' + 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + +/* ******** D E T E R M I N E W H I C H A L H A B E T ******** */ + + + /** + * Returns one of the _SOMETHING_ALPHABET byte arrays depending on + * the options specified. + * It's possible, though silly, to specify ORDERED and URLSAFE + * in which case one of them will be picked, though there is + * no guarantee as to which one will be picked. + */ + private final static byte[] getAlphabet( int options ) + { + if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_ALPHABET; + else if( (options & ORDERED) == ORDERED ) return _ORDERED_ALPHABET; + else return _STANDARD_ALPHABET; + + } // end getAlphabet + + + /** + * Returns one of the _SOMETHING_DECODABET byte arrays depending on + * the options specified. + * It's possible, though silly, to specify ORDERED and URL_SAFE + * in which case one of them will be picked, though there is + * no guarantee as to which one will be picked. + */ + private final static byte[] getDecodabet( int options ) + { + if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_DECODABET; + else if( (options & ORDERED) == ORDERED ) return _ORDERED_DECODABET; + else return _STANDARD_DECODABET; + + } // end getAlphabet + + + + /** Defeats instantiation. */ + private Base64(){} + + + /** + * Encodes or decodes two files from the command line; + * feel free to delete this method (in fact you probably should) + * if you're embedding this code into a larger program. + */ + public final static void main( String[] args ) + { + if( args.length < 3 ){ + usage("Not enough arguments."); + } // end if: args.length < 3 + else { + String flag = args[0]; + String infile = args[1]; + String outfile = args[2]; + if( flag.equals( "-e" ) ){ + Base64.encodeFileToFile( infile, outfile ); + } // end if: encode + else if( flag.equals( "-d" ) ) { + Base64.decodeFileToFile( infile, outfile ); + } // end else if: decode + else { + usage( "Unknown flag: " + flag ); + } // end else + } // end else + } // end main + + /** + * Prints command line usage. + * + * @param msg A message to include with usage info. + */ + private final static void usage( String msg ) + { + System.err.println( msg ); + System.err.println( "Usage: java Base64 -e|-d inputfile outputfile" ); + } // end usage + + +/* ******** E N C O D I N G M E T H O D S ******** */ + + + /** + * Encodes up to the first three bytes of array threeBytes + * and returns a four-byte array in Base64 notation. + * The actual number of significant bytes in your array is + * given by numSigBytes. + * The array threeBytes needs only be as big as + * numSigBytes. + * Code can reuse a byte array by passing a four-byte array as b4. + * + * @param b4 A reusable byte array to reduce array instantiation + * @param threeBytes the array to convert + * @param numSigBytes the number of significant bytes in your array + * @return four byte array in Base64 notation. + * @since 1.5.1 + */ + private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes, int options ) + { + encode3to4( threeBytes, 0, numSigBytes, b4, 0, options ); + return b4; + } // end encode3to4 + + + /** + *Encodes up to three bytes of the array source + * and writes the resulting four Base64 bytes to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accomodate srcOffset + 3 for + * the source array or destOffset + 4 for + * the destination array. + * The actual number of significant bytes in your array is + * given by numSigBytes.
+ *This is the lowest level of the encoding methods with + * all possible parameters.
+ * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param numSigBytes the number of significant bytes in your array + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @return the destination array + * @since 1.3 + */ + private static byte[] encode3to4( + byte[] source, int srcOffset, int numSigBytes, + byte[] destination, int destOffset, int options ) + { + byte[] ALPHABET = getAlphabet( options ); + + // 1 2 3 + // 01234567890123456789012345678901 Bit position + // --------000000001111111122222222 Array position from threeBytes + // --------| || || || | Six bit groups to index ALPHABET + // >>18 >>12 >> 6 >> 0 Right shift necessary + // 0x3f 0x3f 0x3f Additional AND + + // Create buffer with zero-padding if there are only one or two + // significant bytes passed in the array. + // We have to shift left 24 in order to flush out the 1's that appear + // when Java treats a value as negative that is cast from a byte to an int. + int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) + | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) + | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); + + switch( numSigBytes ) + { + case 3: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; + return destination; + + case 2: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + case 1: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = EQUALS_SIGN; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + default: + return destination; + } // end switch + } // end encode3to4 + + + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. If the object + * cannot be serialized or there is another error, + * the method will return null. + * The object is not GZip-compressed before being encoded. + * + * @param serializableObject The object to encode + * @return The Base64-encoded object + * @since 1.4 + */ + public static String encodeObject( java.io.Serializable serializableObject ) + { + return encodeObject( serializableObject, NO_OPTIONS ); + } // end encodeObject + + + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. If the object + * cannot be serialized or there is another error, + * the method will return null. + *+ * Valid options:
+ * GZIP: gzip-compresses object before encoding it. + * DONT_BREAK_LINES: don't break lines at 76 characters + * Note: Technically, this makes your encoding non-compliant. + *+ *
+ * Example: encodeObject( myObj, Base64.GZIP )
or
+ *
+ * Example: encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )
+ *
+ * @param serializableObject The object to encode
+ * @param options Specified options
+ * @return The Base64-encoded object
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeObject( java.io.Serializable serializableObject, int options )
+ {
+ // Streams
+ java.io.ByteArrayOutputStream baos = null;
+ java.io.OutputStream b64os = null;
+ java.io.ObjectOutputStream oos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+
+ // Isolate options
+ int gzip = (options & GZIP);
+
+ try
+ {
+ // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream( baos, ENCODE | options );
+
+ // GZip?
+ if( gzip == GZIP )
+ {
+ gzos = new java.util.zip.GZIPOutputStream( b64os );
+ oos = new java.io.ObjectOutputStream( gzos );
+ } // end if: gzip
+ else
+ oos = new java.io.ObjectOutputStream( b64os );
+
+ oos.writeObject( serializableObject );
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try{ if (oos != null) oos.close(); } catch( Exception e ){}
+ try{ if (gzos != null) gzos.close(); } catch( Exception e ){}
+ try{ if (b64os != null) b64os.close(); } catch( Exception e ){}
+ try{ if (baos != null) baos.close(); } catch( Exception e ){}
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ if (baos != null) {
+ return new String( baos.toByteArray(), PREFERRED_ENCODING );
+ }
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ if (baos != null) {
+ return new String( baos.toByteArray() );
+ }
+ } // end catch
+
+ return null;
+ } // end encode
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source )
+ {
+ return encodeBytes( source, 0, source.length, NO_OPTIONS );
+ } // end encodeBytes
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ *
+ * Valid options:
+ * GZIP: gzip-compresses object before encoding it. + * DONT_BREAK_LINES: don't break lines at 76 characters + * Note: Technically, this makes your encoding non-compliant. + *+ *
+ * Example: encodeBytes( myData, Base64.GZIP )
or
+ *
+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )
+ *
+ *
+ * @param source The data to convert
+ * @param options Specified options
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source, int options )
+ {
+ return encodeBytes( source, 0, source.length, options );
+ } // end encodeBytes
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source, int off, int len )
+ {
+ return encodeBytes( source, off, len, NO_OPTIONS );
+ } // end encodeBytes
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ *
+ * Valid options:
+ * GZIP: gzip-compresses object before encoding it. + * DONT_BREAK_LINES: don't break lines at 76 characters + * Note: Technically, this makes your encoding non-compliant. + *+ *
+ * Example: encodeBytes( myData, Base64.GZIP )
or
+ *
+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )
+ *
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @param options Specified options -- alphabet type is pulled from this (standard, url-safe, ordered)
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source, int off, int len, int options )
+ {
+ // Isolate options
+ int dontBreakLines = ( options & DONT_BREAK_LINES );
+ int gzip = ( options & GZIP );
+
+ // Compress?
+ if( gzip == GZIP )
+ {
+ java.io.ByteArrayOutputStream baos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+ Base64.OutputStream b64os = null;
+
+
+ try
+ {
+ // GZip -> Base64 -> ByteArray
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream( baos, ENCODE | options );
+ gzos = new java.util.zip.GZIPOutputStream( b64os );
+
+ gzos.write( source, off, len );
+ gzos.close();
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try{ if (gzos != null) gzos.close(); } catch( Exception e ){}
+ try{ if (b64os != null) b64os.close(); } catch( Exception e ){}
+ try{ if (baos != null) baos.close(); } catch( Exception e ){}
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ if (baos != null) {
+ return new String( baos.toByteArray(), PREFERRED_ENCODING );
+ }
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ if (baos != null) {
+ return new String( baos.toByteArray() );
+ }
+ } // end catch
+
+ return null;
+ } // end if: compress
+
+ // Else, don't compress. Better not to use streams at all then.
+ else
+ {
+ // Convert option to boolean in way that code likes it.
+ boolean breakLines = dontBreakLines == 0;
+
+ int len43 = len * 4 / 3;
+ byte[] outBuff = new byte[ ( len43 ) // Main 4:3
+ + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding
+ + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+ int lineLength = 0;
+ for( ; d < len2; d+=3, e+=4 )
+ {
+ encode3to4( source, d+off, 3, outBuff, e, options );
+
+ lineLength += 4;
+ if( breakLines && lineLength == MAX_LINE_LENGTH )
+ {
+ outBuff[e+4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ } // end if: end of line
+ } // en dfor: each piece of array
+
+ if( d < len )
+ {
+ encode3to4( source, d+off, len - d, outBuff, e, options );
+ e += 4;
+ } // end if: some padding needed
+
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( outBuff, 0, e, PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( outBuff, 0, e );
+ } // end catch
+
+ } // end else: don't compress
+
+ } // end encodeBytes
+
+
+
+
+
+/* ******** D E C O D I N G M E T H O D S ******** */
+
+
+ /**
+ * Decodes four bytes from array source
+ * and writes the resulting bytes (up to three of them)
+ * to destination.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * srcOffset and destOffset.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate srcOffset + 4 for
+ * the source array or destOffset + 3 for
+ * the destination array.
+ * This method returns the actual number of bytes that
+ * were converted from the Base64 encoding.
+ *
This is the lowest level of the decoding methods with + * all possible parameters.
+ * + * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @param options alphabet type is pulled from this (standard, url-safe, ordered) + * @return the number of decoded bytes converted + * @since 1.3 + */ + private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset, int options ) + { + byte[] DECODABET = getDecodabet( options ); + + // Example: Dk== + if( source[ srcOffset + 2] == EQUALS_SIGN ) + { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + return 1; + } + + // Example: DkL= + else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) + { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); + return 2; + } + + // Example: DkLE + else + { + try{ + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) + // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) + | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); + + + destination[ destOffset ] = (byte)( outBuff >> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); + destination[ destOffset + 2 ] = (byte)( outBuff ); + + return 3; + }catch( Exception e){ + System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); + System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); + System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); + System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); + return -1; + } // end catch + } + } // end decodeToBytes + + + + + /** + * Very low-level access to decoding ASCII characters in + * the form of a byte array. Does not support automatically + * gunzipping or any other "fancy" features. + * + * @param source The Base64 encoded data + * @param off The offset of where to begin decoding + * @param len The length of characters to decode + * @return decoded data + * @since 1.3 + */ + public static byte[] decode( byte[] source, int off, int len, int options ) + { + byte[] DECODABET = getDecodabet( options ); + + int len34 = len * 3 / 4; + byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output + int outBuffPosn = 0; + + byte[] b4 = new byte[4]; + int b4Posn = 0; + int i = 0; + byte sbiCrop = 0; + byte sbiDecode = 0; + for( i = off; i < off+len; i++ ) + { + sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits + sbiDecode = DECODABET[ sbiCrop ]; + + if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or better + { + if( sbiDecode >= EQUALS_SIGN_ENC ) + { + b4[ b4Posn++ ] = sbiCrop; + if( b4Posn > 3 ) + { + outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn, options ); + b4Posn = 0; + + // If that was the equals sign, break out of 'for' loop + if( sbiCrop == EQUALS_SIGN ) + break; + } // end if: quartet built + + } // end if: equals sign or better + + } // end if: white space, equals sign or better + else + { + System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); + return null; + } // end else: + } // each input character + + byte[] out = new byte[ outBuffPosn ]; + System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); + return out; + } // end decode + + + + + /** + * Decodes data from Base64 notation, automatically + * detecting gzip-compressed data and decompressing it. + * + * @param s the string to decode + * @return the decoded data + * @since 1.4 + */ + public static byte[] decode( String s ) + { + return decode( s, NO_OPTIONS ); + } + + + /** + * Decodes data from Base64 notation, automatically + * detecting gzip-compressed data and decompressing it. + * + * @param s the string to decode + * @param options encode options such as URL_SAFE + * @return the decoded data + * @since 1.4 + */ + public static byte[] decode( String s, int options ) + { + byte[] bytes; + try + { + bytes = s.getBytes( PREFERRED_ENCODING ); + } // end try + catch( java.io.UnsupportedEncodingException uee ) + { + bytes = s.getBytes(); + } // end catch + // + + // Decode + bytes = decode( bytes, 0, bytes.length, options ); + + + // Check to see if it's gzip-compressed + // GZIP Magic Two-Byte Number: 0x8b1f (35615) + if( bytes != null && bytes.length >= 4 ) + { + + int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); + if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) + { + java.io.ByteArrayInputStream bais = null; + java.util.zip.GZIPInputStream gzis = null; + java.io.ByteArrayOutputStream baos = null; + byte[] buffer = new byte[2048]; + int length = 0; + + try + { + baos = new java.io.ByteArrayOutputStream(); + bais = new java.io.ByteArrayInputStream( bytes ); + gzis = new java.util.zip.GZIPInputStream( bais ); + + while( ( length = gzis.read( buffer ) ) >= 0 ) + { + baos.write(buffer,0,length); + } // end while: reading input + + // No error? Get new bytes. + bytes = baos.toByteArray(); + + } // end try + catch( java.io.IOException e ) + { + // Just return originally-decoded bytes + } // end catch + finally + { + try{ if (baos != null) baos.close(); } catch( Exception e ){} + try{ if (gzis != null) gzis.close(); } catch( Exception e ){} + try{ if (bais != null) bais.close(); } catch( Exception e ){} + } // end finally + + } // end if: gzipped + } // end if: bytes.length >= 2 + + return bytes; + } // end decode + + + + + /** + * Attempts to decode Base64 data and deserialize a Java + * Object within. Returns null if there was an error. + * + * @param encodedObject The Base64 data to decode + * @return The decoded and deserialized object + * @since 1.5 + */ + public static Object decodeToObject( String encodedObject ) + { + // Decode and gunzip if necessary + byte[] objBytes = decode( encodedObject ); + + java.io.ByteArrayInputStream bais = null; + java.io.ObjectInputStream ois = null; + Object obj = null; + + try + { + bais = new java.io.ByteArrayInputStream( objBytes ); + ois = new java.io.ObjectInputStream( bais ); + + obj = ois.readObject(); + } // end try + catch( java.io.IOException e ) + { + e.printStackTrace(); + obj = null; + } // end catch + catch( java.lang.ClassNotFoundException e ) + { + e.printStackTrace(); + obj = null; + } // end catch + finally + { + try{ if (bais != null) bais.close(); } catch( Exception e ){} + try{ if (ois != null) ois.close(); } catch( Exception e ){} + } // end finally + + return obj; + } // end decodeObject + + + + /** + * Convenience method for encoding data to a file. + * + * @param dataToEncode byte array of data to encode in base64 form + * @param filename Filename for saving encoded data + * @return true if successful, false otherwise + * + * @since 2.1 + */ + public static boolean encodeToFile( byte[] dataToEncode, String filename ) + { + boolean success = false; + Base64.OutputStream bos = null; + try + { + bos = new Base64.OutputStream( + new java.io.FileOutputStream( filename ), Base64.ENCODE ); + bos.write( dataToEncode ); + success = true; + } // end try + catch( java.io.IOException e ) + { + + success = false; + } // end catch: IOException + finally + { + try{ if (bos != null) bos.close(); } catch( Exception e ){} + } // end finally + + return success; + } // end encodeToFile + + + /** + * Convenience method for decoding data to a file. + * + * @param dataToDecode Base64-encoded data as a string + * @param filename Filename for saving decoded data + * @return true if successful, false otherwise + * + * @since 2.1 + */ + public static boolean decodeToFile( String dataToDecode, String filename ) + { + boolean success = false; + Base64.OutputStream bos = null; + try + { + bos = new Base64.OutputStream( + new java.io.FileOutputStream( filename ), Base64.DECODE ); + bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) ); + success = true; + } // end try + catch( java.io.IOException e ) + { + success = false; + } // end catch: IOException + finally + { + try{ if (bos != null) bos.close(); } catch( Exception e ){} + } // end finally + + return success; + } // end decodeToFile + + + + + /** + * Convenience method for reading a base64-encoded + * file and decoding it. + * + * @param filename Filename for reading encoded data + * @return decoded byte array or null if unsuccessful + * + * @since 2.1 + */ + public static byte[] decodeFromFile( String filename ) + { + byte[] decodedData = null; + Base64.InputStream bis = null; + try + { + // Set up some useful variables + java.io.File file = new java.io.File( filename ); + byte[] buffer = null; + int length = 0; + int numBytes = 0; + + // Check for size of file + if( file.length() > Integer.MAX_VALUE ) + { + System.err.println( "File is too big for this convenience method (" + file.length() + " bytes)." ); + return null; + } // end if: file too big for int index + buffer = new byte[ (int)file.length() ]; + + // Open a stream + bis = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( file ) ), Base64.DECODE ); + + // Read until done + while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) + length += numBytes; + + // Save in a variable to return + decodedData = new byte[ length ]; + System.arraycopy( buffer, 0, decodedData, 0, length ); + + } // end try + catch( java.io.IOException e ) + { + System.err.println( "Error decoding from file " + filename ); + } // end catch: IOException + finally + { + try{ if (bis != null) bis.close(); } catch( Exception e) {} + } // end finally + + return decodedData; + } // end decodeFromFile + + + + /** + * Convenience method for reading a binary file + * and base64-encoding it. + * + * @param filename Filename for reading binary data + * @return base64-encoded string or null if unsuccessful + * + * @since 2.1 + */ + public static String encodeFromFile( String filename ) + { + String encodedData = null; + Base64.InputStream bis = null; + try + { + // Set up some useful variables + java.io.File file = new java.io.File( filename ); + byte[] buffer = new byte[ Math.max((int)(file.length() * 1.4),40) ]; // Need max() for math on small files (v2.2.1) + int length = 0; + int numBytes = 0; + + // Open a stream + bis = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( file ) ), Base64.ENCODE ); + + // Read until done + while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) + length += numBytes; + + // Save in a variable to return + encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING ); + + } // end try + catch( java.io.IOException e ) + { + System.err.println( "Error encoding from file " + filename ); + } // end catch: IOException + finally + { + try{ if (bis != null) bis.close(); } catch( Exception e) {} + } // end finally + + return encodedData; + } // end encodeFromFile + + + + + /** + * Reads infile and encodes it to outfile. + * + * @param infile Input file + * @param outfile Output file + * @return true if the operation is successful + * @since 2.2 + */ + public static boolean encodeFileToFile( String infile, String outfile ) + { + boolean success = false; + java.io.InputStream in = null; + java.io.OutputStream out = null; + try{ + in = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( infile ) ), + Base64.ENCODE ); + out = new java.io.BufferedOutputStream( new java.io.FileOutputStream( outfile ) ); + byte[] buffer = new byte[65536]; // 64K + int read = -1; + while( ( read = in.read(buffer) ) >= 0 ){ + out.write( buffer,0,read ); + } // end while: through file + success = true; + } catch( java.io.IOException exc ){ + exc.printStackTrace(); + } finally{ + try{ if (in != null) in.close(); } catch( Exception exc ){} + try{ if (out != null) out.close(); } catch( Exception exc ){} + } // end finally + + return success; + } // end encodeFileToFile + + + + /** + * Reads infile and decodes it to outfile. + * + * @param infile Input file + * @param outfile Output file + * @return true if the operation is successful + * @since 2.2 + */ + public static boolean decodeFileToFile( String infile, String outfile ) + { + boolean success = false; + java.io.InputStream in = null; + java.io.OutputStream out = null; + try{ + in = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( infile ) ), + Base64.DECODE ); + out = new java.io.BufferedOutputStream( new java.io.FileOutputStream( outfile ) ); + byte[] buffer = new byte[65536]; // 64K + int read = -1; + while( ( read = in.read(buffer) ) >= 0 ){ + out.write( buffer,0,read ); + } // end while: through file + success = true; + } catch( java.io.IOException exc ){ + exc.printStackTrace(); + } finally{ + try{ if (in != null) in.close(); } catch( Exception exc ){} + try{ if (out != null) out.close(); } catch( Exception exc ){} + } // end finally + + return success; + } // end decodeFileToFile + + + /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ + + + + /** + * A {@link Base64.InputStream} will read data from another + * java.io.InputStream, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @since 1.3 + */ + public static class InputStream extends java.io.FilterInputStream + { + private boolean encode; // Encoding or decoding + private int position; // Current position in the buffer + private byte[] buffer; // Small buffer holding converted data + private int bufferLength; // Length of buffer (3 or 4) + private int numSigBytes; // Number of meaningful bytes in the buffer + private int lineLength; + private boolean breakLines; // Break lines at less than 80 characters + private int options; // Record options used to create the stream. + private byte[] decodabet; // Local copies to avoid extra method calls + + + /** + * Constructs a {@link Base64.InputStream} in DECODE mode. + * + * @param in the java.io.InputStream from which to read data. + * @since 1.3 + */ + public InputStream( java.io.InputStream in ) + { + this( in, DECODE ); + } // end constructor + + + /** + * Constructs a {@link Base64.InputStream} in + * either ENCODE or DECODE mode. + *+ * Valid options:
+ * ENCODE or DECODE: Encode or Decode as data is read. + * DONT_BREAK_LINES: don't break lines at 76 characters + * (only meaningful when encoding) + * Note: Technically, this makes your encoding non-compliant. + *+ *
+ * Example: new Base64.InputStream( in, Base64.DECODE )
+ *
+ *
+ * @param in the java.io.InputStream from which to read data.
+ * @param options Specified options
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public InputStream( java.io.InputStream in, int options )
+ {
+ super( in );
+ this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = this.encode ? 4 : 3;
+ this.buffer = new byte[ this.bufferLength ];
+ this.position = -1;
+ this.lineLength = 0;
+ this.options = options; // Record for later, mostly to determine which alphabet to use
+ this.decodabet = getDecodabet(options);
+ } // end constructor
+
+ /**
+ * Reads enough of the input stream to convert
+ * to/from Base64 and returns the next byte.
+ *
+ * @return next byte
+ * @since 1.3
+ */
+ public int read() throws java.io.IOException
+ {
+ // Do we need to get data?
+ if( this.position < 0 )
+ {
+ if( this.encode )
+ {
+ byte[] b3 = new byte[3];
+ int numBinaryBytes = 0;
+ for( int i = 0; i < 3; i++ )
+ {
+ try
+ {
+ int b = this.in.read();
+
+ // If end of stream, b is -1.
+ if( b >= 0 )
+ {
+ b3[i] = (byte)b;
+ numBinaryBytes++;
+ } // end if: not end of stream
+
+ } // end try: read
+ catch( java.io.IOException e )
+ {
+ // Only a problem if we got no data at all.
+ if( i == 0 )
+ throw e;
+
+ } // end catch
+ } // end for: each needed input byte
+
+ if( numBinaryBytes > 0 )
+ {
+ encode3to4( b3, 0, numBinaryBytes, this.buffer, 0, this.options );
+ this.position = 0;
+ this.numSigBytes = 4;
+ } // end if: got data
+ else
+ {
+ return -1;
+ } // end else
+ } // end if: encoding
+
+ // Else decoding
+ else
+ {
+ byte[] b4 = new byte[4];
+ int i = 0;
+ for( i = 0; i < 4; i++ )
+ {
+ // Read four "meaningful" bytes:
+ int b = 0;
+ do{ b = this.in.read(); }
+ while( b >= 0 && this.decodabet[ b & 0x7f ] <= WHITE_SPACE_ENC );
+
+ if( b < 0 )
+ break; // Reads a -1 if end of stream
+
+ b4[i] = (byte)b;
+ } // end for: each needed input byte
+
+ if( i == 4 )
+ {
+ this.numSigBytes = decode4to3( b4, 0, this.buffer, 0, this.options );
+ this.position = 0;
+ } // end if: got four characters
+ else if( i == 0 ){
+ return -1;
+ } // end else if: also padded correctly
+ else
+ {
+ // Must have broken out from above.
+ throw new java.io.IOException( "Improperly padded Base64 input." );
+ } // end
+
+ } // end else: decode
+ } // end else: get data
+
+ // Got data?
+ if( this.position >= 0 )
+ {
+ // End of relevant data?
+ if( /*!encode &&*/ this.position >= this.numSigBytes )
+ return -1;
+
+ if( this.encode && this.breakLines && this.lineLength >= MAX_LINE_LENGTH )
+ {
+ this.lineLength = 0;
+ return '\n';
+ } // end if
+ else
+ {
+ this.lineLength++; // This isn't important when decoding
+ // but throwing an extra "if" seems
+ // just as wasteful.
+
+ int b = this.buffer[ this.position++ ];
+
+ if( this.position >= this.bufferLength )
+ this.position = -1;
+
+ return b & 0xFF; // This is how you "cast" a byte that's
+ // intended to be unsigned.
+ } // end else
+ } // end if: position >= 0
+
+ // Else error
+ else
+ {
+ // When JDK1.4 is more accepted, use an assertion here.
+ throw new java.io.IOException( "Error in Base64 code reading stream." );
+ } // end else
+ } // end read
+
+
+ /**
+ * Calls {@link #read()} repeatedly until the end of stream
+ * is reached or len bytes are read.
+ * Returns number of bytes read into array or -1 if
+ * end of stream is encountered.
+ *
+ * @param dest array to hold values
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @return bytes read into array or -1 if end of stream is encountered.
+ * @since 1.3
+ */
+ public int read( byte[] dest, int off, int len ) throws java.io.IOException
+ {
+ int i;
+ int b;
+ for( i = 0; i < len; i++ )
+ {
+ b = read();
+
+ //if( b < 0 && i == 0 )
+ // return -1;
+
+ if( b >= 0 )
+ dest[off + i] = (byte)b;
+ else if( i == 0 )
+ return -1;
+ else
+ break; // Out of 'for' loop
+ } // end for: each byte read
+ return i;
+ } // end read
+
+ } // end inner class InputStream
+
+
+
+
+
+
+ /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
+
+
+
+ /**
+ * A {@link Base64.OutputStream} will write data to another
+ * java.io.OutputStream, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class OutputStream extends java.io.FilterOutputStream
+ {
+ private boolean encode;
+ private int position;
+ private byte[] buffer;
+ private int bufferLength;
+ private int lineLength;
+ private boolean breakLines;
+ private byte[] b4; // Scratch used in a few places
+ private boolean suspendEncoding;
+ private int options; // Record for later
+ private byte[] decodabet; // Local copies to avoid extra method calls
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in ENCODE mode.
+ *
+ * @param out the java.io.OutputStream to which data will be written.
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out )
+ {
+ this( out, ENCODE );
+ } // end constructor
+
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in
+ * either ENCODE or DECODE mode.
+ *
+ * Valid options:
+ * ENCODE or DECODE: Encode or Decode as data is read. + * DONT_BREAK_LINES: don't break lines at 76 characters + * (only meaningful when encoding) + * Note: Technically, this makes your encoding non-compliant. + *+ *
+ * Example: new Base64.OutputStream( out, Base64.ENCODE )
+ *
+ * @param out the java.io.OutputStream to which data will be written.
+ * @param options Specified options.
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out, int options )
+ {
+ super( out );
+ this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = this.encode ? 3 : 4;
+ this.buffer = new byte[ this.bufferLength ];
+ this.position = 0;
+ this.lineLength = 0;
+ this.suspendEncoding = false;
+ this.b4 = new byte[4];
+ this.options = options;
+ this.decodabet = getDecodabet(options);
+ } // end constructor
+
+
+ /**
+ * Writes the byte to the output stream after
+ * converting to/from Base64 notation.
+ * When encoding, bytes are buffered three
+ * at a time before the output stream actually
+ * gets a write() call.
+ * When decoding, bytes are buffered four
+ * at a time.
+ *
+ * @param theByte the byte to write
+ * @since 1.3
+ */
+ public void write(int theByte) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if( this.suspendEncoding )
+ {
+ super.out.write( theByte );
+ return;
+ } // end if: supsended
+
+ // Encode?
+ if( this.encode )
+ {
+ this.buffer[ this.position++ ] = (byte)theByte;
+ if( this.position >= this.bufferLength ) // Enough to encode.
+ {
+ this.out.write( encode3to4( this.b4, this.buffer, this.bufferLength, this.options ) );
+
+ this.lineLength += 4;
+ if( this.breakLines && this.lineLength >= MAX_LINE_LENGTH )
+ {
+ this.out.write( NEW_LINE );
+ this.lineLength = 0;
+ } // end if: end of line
+
+ this.position = 0;
+ } // end if: enough to output
+ } // end if: encoding
+
+ // Else, Decoding
+ else
+ {
+ // Meaningful Base64 character?
+ if( this.decodabet[ theByte & 0x7f ] > WHITE_SPACE_ENC )
+ {
+ this.buffer[ this.position++ ] = (byte)theByte;
+ if( this.position >= this.bufferLength ) // Enough to output.
+ {
+ int len = Base64.decode4to3( this.buffer, 0, this.b4, 0, this.options );
+ this.out.write( this.b4, 0, len );
+ //out.write( Base64.decode4to3( buffer ) );
+ this.position = 0;
+ } // end if: enough to output
+ } // end if: meaningful base64 character
+ else if( this.decodabet[ theByte & 0x7f ] != WHITE_SPACE_ENC )
+ {
+ throw new java.io.IOException( "Invalid character in Base64 data." );
+ } // end else: not white space either
+ } // end else: decoding
+ } // end write
+
+
+
+ /**
+ * Calls {@link #write(int)} repeatedly until len
+ * bytes are written.
+ *
+ * @param theBytes array from which to read bytes
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @since 1.3
+ */
+ public void write( byte[] theBytes, int off, int len ) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if( this.suspendEncoding )
+ {
+ super.out.write( theBytes, off, len );
+ return;
+ } // end if: supsended
+
+ for( int i = 0; i < len; i++ )
+ {
+ write( theBytes[ off + i ] );
+ } // end for: each byte written
+
+ } // end write
+
+
+
+ /**
+ * Method added by PHIL. [Thanks, PHIL. -Rob]
+ * This pads the buffer without closing the stream.
+ */
+ public void flushBase64() throws java.io.IOException
+ {
+ if( this.position > 0 )
+ {
+ if( this.encode )
+ {
+ this.out.write( encode3to4( this.b4, this.buffer, this.position, this.options ) );
+ this.position = 0;
+ } // end if: encoding
+ else
+ {
+ throw new java.io.IOException( "Base64 input not properly padded." );
+ } // end else: decoding
+ } // end if: buffer partially full
+
+ } // end flush
+
+
+ /**
+ * Flushes and closes (I think, in the superclass) the stream.
+ *
+ * @since 1.3
+ */
+ public void close() throws java.io.IOException
+ {
+ // 1. Ensure that pending characters are written
+ flushBase64();
+
+ // 2. Actually close the stream
+ // Base class both flushes and closes.
+ super.close();
+
+ this.buffer = null;
+ this.out = null;
+ } // end close
+
+
+
+ /**
+ * Suspends encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void suspendEncoding() throws java.io.IOException
+ {
+ flushBase64();
+ this.suspendEncoding = true;
+ } // end suspendEncoding
+
+
+ /**
+ * Resumes encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void resumeEncoding()
+ {
+ this.suspendEncoding = false;
+ } // end resumeEncoding
+
+
+
+ } // end inner class OutputStream
+
+
+} // end class Base64
diff --git a/src/main/java/org/productivity/java/syslog4j/util/OSDetectUtility.java b/src/main/java/org/productivity/java/syslog4j/util/OSDetectUtility.java
new file mode 100644
index 0000000..f76145e
--- /dev/null
+++ b/src/main/java/org/productivity/java/syslog4j/util/OSDetectUtility.java
@@ -0,0 +1,77 @@
+package org.productivity.java.syslog4j.util;
+
+/**
+* OSDetectUtility provides operating system detection used to determine
+* whether Syslog4j is running on a Unix platform.
+*
+*
Syslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: OSDetectUtility.java,v 1.4 2008/11/14 04:31:59 cvs Exp $ +*/ +public final class OSDetectUtility { + private final static String[] UNIX_PLATFORMS = { + "Linux", + "Mac OS", + "Solaris", + "SunOS", + "MPE/iX", + "HP-UX", + "AIX", + "OS/390", + "FreeBSD", + "Irix", + "Digital Unix", + "FreeBSD", + "OSF1", + "OpenVMS" + }; + + private final static String[] WINDOWS_PLATFORMS = { + "Windows", + "OS/2" + }; + + private static boolean UNIX = false; + private static boolean WINDOWS = false; + + private OSDetectUtility() { + // + } + + private static boolean isMatch(String[] platforms) { + boolean match = false; + + String osName = System.getProperty("os.name"); + + if (osName != null && !"".equals(osName.trim())) { + osName = osName.toLowerCase(); + + for(int i=0; iSyslog4j is licensed under the Lesser GNU Public License v2.1. A copy +* of the LGPL license is available in the META-INF folder in all +* distributions of Syslog4j and in the base directory of the "doc" ZIP.
+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogUtility.java,v 1.21 2010/11/28 01:38:08 cvs Exp $ +*/ +public final class SyslogUtility implements SyslogConstants { + private static final long serialVersionUID = 915031554586613648L; + + private SyslogUtility() { + // + } + + public static final InetAddress getInetAddress(String host) throws SyslogRuntimeException { + InetAddress address = null; + + try { + address = InetAddress.getByName(host); + + } catch (UnknownHostException uhe) { + throw new SyslogRuntimeException(uhe); + } + + return address; + } + + public static final String getFacilityString(int syslogFacility) { + switch(syslogFacility) { + case FACILITY_KERN: return "kern"; + case FACILITY_USER: return "user"; + case FACILITY_MAIL: return "mail"; + case FACILITY_DAEMON: return "daemon"; + case FACILITY_AUTH: return "auth"; + case FACILITY_SYSLOG: return "syslog"; + case FACILITY_LPR: return "lpr"; + case FACILITY_NEWS: return "news"; + case FACILITY_UUCP: return "uucp"; + case FACILITY_CRON: return "cron"; + case FACILITY_AUTHPRIV: return "authpriv"; + case FACILITY_FTP: return "ftp"; + case FACILITY_LOCAL0: return "local0"; + case FACILITY_LOCAL1: return "local1"; + case FACILITY_LOCAL2: return "local2"; + case FACILITY_LOCAL3: return "local3"; + case FACILITY_LOCAL4: return "local4"; + case FACILITY_LOCAL5: return "local5"; + case FACILITY_LOCAL6: return "local6"; + case FACILITY_LOCAL7: return "local7"; + + default: return "UNKNOWN"; + } + } + + public static final int getFacility(String facilityName) { + String _facilityName = facilityName; + + if (facilityName == null) { + return -1; + + } else { + _facilityName = facilityName.trim(); + } + + if("KERN".equalsIgnoreCase(_facilityName)) { return FACILITY_KERN; + } else if("USER".equalsIgnoreCase(facilityName)) { return FACILITY_USER; + } else if("MAIL".equalsIgnoreCase(facilityName)) { return FACILITY_MAIL; + } else if("DAEMON".equalsIgnoreCase(facilityName)) { return FACILITY_DAEMON; + } else if("AUTH".equalsIgnoreCase(facilityName)) { return FACILITY_AUTH; + } else if("SYSLOG".equalsIgnoreCase(facilityName)) { return FACILITY_SYSLOG; + } else if("LPR".equalsIgnoreCase(facilityName)) { return FACILITY_LPR; + } else if("NEWS".equalsIgnoreCase(facilityName)) { return FACILITY_NEWS; + } else if("UUCP".equalsIgnoreCase(facilityName)) { return FACILITY_UUCP; + } else if("CRON".equalsIgnoreCase(facilityName)) { return FACILITY_CRON; + } else if("AUTHPRIV".equalsIgnoreCase(facilityName)) { return FACILITY_AUTHPRIV; + } else if("FTP".equalsIgnoreCase(facilityName)) { return FACILITY_FTP; + } else if("LOCAL0".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL0; + } else if("LOCAL1".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL1; + } else if("LOCAL2".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL2; + } else if("LOCAL3".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL3; + } else if("LOCAL4".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL4; + } else if("LOCAL5".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL5; + } else if("LOCAL6".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL6; + } else if("LOCAL7".equalsIgnoreCase(facilityName)) { return FACILITY_LOCAL7; + } else { return -1; + } + } + + public static final int getLevel(String levelName) { + String _levelName = levelName; + + if (levelName == null) { + return -1; + + } else { + _levelName = levelName.trim(); + } + + if("DEBUG".equalsIgnoreCase(_levelName)) { return LEVEL_DEBUG; + } else if("INFO".equalsIgnoreCase(_levelName)) { return LEVEL_INFO; + } else if("NOTICE".equalsIgnoreCase(_levelName)) { return LEVEL_NOTICE; + } else if("WARN".equalsIgnoreCase(_levelName)) { return LEVEL_WARN; + } else if("ERROR".equalsIgnoreCase(_levelName)) { return LEVEL_ERROR; + } else if("CRITICAL".equalsIgnoreCase(_levelName)) { return LEVEL_CRITICAL; + } else if("ALERT".equalsIgnoreCase(_levelName)) { return LEVEL_ALERT; + } else if("EMERGENCY".equalsIgnoreCase(_levelName)) { return LEVEL_EMERGENCY; + } else { return -1; + } + } + + public static final boolean isClassExists(String className) { + try { + Class.forName(className); + return true; + + } catch (ClassNotFoundException cnfe) { + // + } + + return false; + } + + public static final String getLocalName() { + String localName = SEND_LOCAL_NAME_DEFAULT_VALUE; + + try { + InetAddress addr = InetAddress.getLocalHost(); + localName = addr.getHostName(); + + } catch (UnknownHostException uhe) { + // + } + + return localName; + } + + public static final byte[] getBytes(SyslogCharSetIF syslogCharSet, String data) { + byte[] dataBytes = null; + + try { + dataBytes = data.getBytes(syslogCharSet.getCharSet()); + + } catch (UnsupportedEncodingException uee) { + dataBytes = data.getBytes(); + } + + return dataBytes; + } + + public static final String newString(SyslogCharSetIF syslogCharSet, byte[] dataBytes) { + String data = newString(syslogCharSet,dataBytes,dataBytes.length); + + return data; + } + + public static final String newString(SyslogCharSetIF syslogCharSet, byte[] dataBytes, int dataLength) { + String data = null; + + try { + data = new String(dataBytes,0,dataLength,syslogCharSet.getCharSet()); + + } catch (UnsupportedEncodingException uee) { + data = new String(dataBytes); + } + + return data; + } + + public static final String getLevelString(int level) { + switch(level) { + case SyslogConstants.LEVEL_DEBUG: return "DEBUG"; + case SyslogConstants.LEVEL_INFO: return "INFO"; + case SyslogConstants.LEVEL_NOTICE: return "NOTICE"; + case SyslogConstants.LEVEL_WARN: return "WARN"; + case SyslogConstants.LEVEL_ERROR: return "ERROR"; + case SyslogConstants.LEVEL_CRITICAL: return "CRITICAL"; + case SyslogConstants.LEVEL_ALERT: return "ALERT"; + case SyslogConstants.LEVEL_EMERGENCY: return "EMERGENCY"; + + default: + return "UNKNOWN"; + } + } + + + public static void sleep(long duration) { + try { + Thread.sleep(duration); + + } catch (InterruptedException ie) { + // + } + } +} diff --git a/target/classes/org/productivity/java/syslog4j/Syslog.class b/target/classes/org/productivity/java/syslog4j/Syslog.class new file mode 100644 index 0000000000000000000000000000000000000000..ef637f11d34abbb36b75fa59937f8cc3851c776d GIT binary patch literal 6142 zcmbVQ33yc175;BB$(u|j5C#Q85QbPK2}y=PKobx@384%oVF_Wi;xKs$4<<9?yf;9! zwYIgjTH9LGT3U+>)YOUEK`m?yx5vq$|{S95aJH$#V2U2mf@2I1(Ij(2QO+nSRI=ThGlwFse zlM(0Fse?2ruiX47m1hLb zOfrwQqU5=FZ!qDkHU{#uh6M+q!J3$Q{x6`Tr42kGI-}COJkjl?tmeIGhIEt0;nCz4 zXQdVkvSl%2IG!d{cwrH3T~^9#MkOaG)~Cmej-8rF82vb v&;;Ft^B6|Jx2tGx) zD&fHX 6o$Bl!UHsbm}`#Vx>-p>4;7T=%7vs8qg_8DV+uhKD?$7OReNn zr|T%KQ-*N*>(oP)R<25?qemsT)G0@YG~TT97T&7!Hr~#(ctY`MY_g_vFYnO#N`gyn zFM;5qv3&4mnpxmsd_Fc&>c+ZYtV0@i2%#b#j;SOrJdn#|!$Jw7S~43RE$BQsBJ0O> zx{Hoze3i~Sd6zW1b-tQzhUrg)PumSnAZ5U2yho?|=w6+#p$Bz3M$hVW58cbO`TuvP zuC+|jbAg2LtkP-%Y&hXm<7 NaLu^`@lEHIIhEs z_UYU&xBErbW$j^|o}tg{^cDJ3oxTjwpg1_7(`)o~oe$E@Iw!=02V_N3Zc}u##)CRv z$7zi-I%hej^C6jYSRNnYqXKhA=j-_fo!`edFm>5+E}T$dF}yrHe_1$f#8LyW5rl4> z{`Rn$6mO9+!rA>sID?8Loaze?MDtmV6;TEMMxAeBklt28(xVc-e1Pj(tMe^ zy!G~M=-G5-k1+d9oo)j8bPL_8^X&{q?%+Fhz6&CwWBmU7F;`W$<9 OB?51Kv`~(si|bl%x|VL3WN?Lifmv)kudLX3P*O7eL1HSkp_gWHu|Eu z1nAv7!AxVK@Q7;09}HQ#ymHvUK6PfMH)9m)u+=KZZhOz#LWRKY=-{%VNL-Y^Ra(h_ z?FyLYO~@|n>0%xM$hFHVN{RxqwF7JgnIckezi}Osd8B)z>NDF+=HmT|KRP%Fr^D3j z!bq`cS-`d*g*XD)RDQ4X%}iG^mdM2oMNe1KrZVqjELuCGxeTm#D%4dthfYom#HnUR z-8%kcla*591uR%y>!jg2?$jHoo~RTxlg-RFaG*w{%t6XK0OPMN8nz}bITr~#nio;q z8L4IA>+I?#($M8n#_ifw%$}`prUfPTR>orC_u`G5DmO&I9Y?bUw6}JGC%JQfG`$UG zvDVG#q#9K3gvJCBB#V%II+u(g>vrt1#+eJ^VTC#Fi z71SKV1RbJ>v9C|P@zh}y#w#aIMUmCpW+BCnCmP4$I~Qig Eq?<#=k1z%anN705TI%@nFdRKXQ^Ubyoj0AVv(WKA67YOFyk zzTjla3!ceh7e&RF%D-Wnd37uK=WCYgg0HaWRiKKo!neFu8vSa|iGNE<>cu5lP*lzw z?}fUG-U?4Ema1bUSn0h0AC3IP6sG`9CxiOX@5iUAGTKjGsiV;MN-3qTsHW5v1(mv@ zfKpe~Q0j_;3D*W-pbSHM6nEE?2R)+J$VuV|pP({nJkofj@kLINe ^&C z<34zTDxSl-G9VCL2>OU-ftD~nj9rMYV6*Yf>tdQlbLb+Pi#;QB17_&fUi3b?5qDn6 z2W>iff#kthUF3Pvc5ZwXmq6p0&v!STX?h8dG^zwB;eV34TH98sCCzv`52GzbTh!TG zuw Wt&G)U$FH?kYw|XL_8%(w{X#m1XoYRkeHTy^#^B zE~7g C6xX+kH)E>U}RghaIYE6K%yVTWN>7T9nSi2S1`Vh-nFC zEQN3`g_zoD0WC-GQo0O(>!^desgrin8pTNj0$P9-x6$qBg&@K^=uXA)E}J{>A_X$| zV-$Mt$L^xiyD`U$YdF#<>TG(MCPAY^RMm5e>UP#nK1rdMBEvN0Ijr(Qt~FGPm7>P; zAV~rpKH7lsO?c7`dH2u^+Ct}p8&RQ9HHm`Q M=( z)Zrh+AX=es4W7s>QMLE06pXw;Q^neF_bi5sRoe@Kc0jc|T~&*6(*@FJK~59feV%+{ zA@>0C8bC%}AwNp@+mI_kNEyiSixj;DQxB?912XDU2ve+Cjuia#0FIw% pi}Is6=L;_ zP(7nK4xggwJDHnK(u|%6jB4hL<`J63G)(6WQKgKWKcfjZ1)is?Gnj)bI7Cz7hAx5S z&Be}(;1croH5F&%lk_QNU#*U0Tj|rVe_^wg9)_if6`?%0se1^ti33^F^a_QK(E{1} z6}sRUg={KD=t7&W*%qZug^}7ZbH 7v3umRa3{eePAbmRSWH+<; pG4$?kZ1m;HCQ!Zexlsycv zM@oPVxq$iH*nAvdPm}8{Q*;SZ#5v7psk*kId6?!7Q{)&0 zY8!?qlz%o%jR*|bURqqFCz)0uDp}dxH<4@nCEV?|6+x}mR*omT!uDj?p8iP1gdnY; zFQDha8V^kTpvpk-KH4Iet8p(`V20Zz
WS4saBS#{xB^XB0Yb*$ii m|jqPhfH8P_r zRCSEX@l;UaYBVUL)iN3^jD~cfT9*l*qDqxkuadM{Q6H)Z)d&uD0SwFHKz&fUBh;Z$ z`y? ?HjI*^lD #Cf5ny2B%hu92a$>_i^$y zJqxF0J;YgQ^Lg6*A;0zbak{uU a91cD)+ zPeEQt(|8en7}|zZdMPz f{x)75%IDa;2E9AgvQZKMT*VQ6r2+>O=8uyYqrX zFP}5-R^lte9$V;Z$h|!%*H_vupaI$UpJA;JY~!Pp&HP@7Lh}8|kr_?kItW*|c8Gkn zR}9m-f~l&+l~>~@n1!kpYa9wDI}}W|DUhds4pWd95BMr%?Z)S0_j2rJB606(^M<^~ zktM?sueYST0jJ%PZoSX0(pS~{9QjtYYqDY*gbe9#^oX;nsD~HnE~6_k2o6T5$A@gJ zqCKEQKO*JtQrbg%QRrIUxE;1kypH_5o+@|)tQe&)Z>9)up{2Z?R&Xz^Wt8>26F)!Q zMSJ;b+K1=+d9PB))nH&BSojMBtN^ehs&v;-R *H{9l@B6U`(7Uv2j1V{I_wU zyePeU=&ztIpO@)7^w+4T8S&z8unXf{y>1B)Y7~!7)O(6H?`%9tTe_R R*YEluuHP{RDTzbd^Nso%r9?REWsxH4pbwIX-Ms$>0}#qV zT90p+oABv!8xJZ$SVd8G((Tg2?f*COsl zI&k&Nw5PiXv|lqs3wx}GdnI=0;&7W!QuL)Es&{_?qRZe@>S-ojtFDWo8B5D;@Lj|? z9J9kX#n;nhz5%uDT{M$##BsZc=JL(75ciAuHXOU#;al#Y4Scs^Owx~8@N7S%e*n>K k==~$2v`D_&W;Tc;`Ok>h_+ R8Uk9R8Ukz5K+(;NJ}X%TWkRVMIMR@3JMB}3WA`1ANoIcW_M?2@6tf~_1>L3 zch3CIx#ygF?)0Iz@4SbI7SUUNT1*qAbR6w1p?%!nQ9}E @-Q3*6&Ar^* z$IXvR=%Akt(fxe!6K)Q3bA+1*xOtG9hq(Ev7q7z~@j72U%*`YAP--DxJ<83`xcRxC z9;07y^SF S4PXD3n`gLrmM8wMjDAng@#XU@ z?hiitqaT`1_~->6z38Jq393x$2}6r+(i2G|9@`k|6C_R+G<9V>mNd1Pxk-zrbnnBx z;g$owt(u_vh(4^PqGqoaK4&04vRaEpqIed92DWM2wXT$DM7suzq}d~=WLOIuQN!E? znIS>G@Tiv9pqqlKt+`PxHqy1hOc=2d%=Q`)J%*d5(Rf&kuGPkLOib#r$N*mt8e=+u z#>OG*bns *FT$To>D% zFigCl$vqy587AyuoQs>4W7 *|%~i38 zb*mEKP8is#V#sa15^(5RM33NRDyjEr`dB |m8n)nQMa-vRgyqbV~I-x1ra8DOk16RB8OGj$tZP!(PU`=`QYDxpXEG!qM4 zyv%?JP7*Ywt$mXq&&qfNrl=S&V*1+D*pQwW)P|zGG;&!sY49Fg+k+l+)WEyD2jYp5 zuJJ@X0@22HFn3AkNbX8T<0Ff=bs1yh(XJIkNi(5^%?)xC4mWJDAC!;i>7l5WgtVHr zc89;L 6la3=8$4fVGRQiBz3VoDS&4jm(z?SmO zD08C*Pprv{1sDKPU4w`6?|Irn{N7q4xj_-Zb^Id5c!guSwHioI*_qZ*8DRP|iKPq^ zvR8q0#<8ZBV5-ar$VHfE|E%50>f{Awb=rrVDXdzHL|jt^^|T$$zb%(`Js9fmVVhKp z<-S_b()TJ35xmtU4eMKH#E{h88VXw07J9EQVs5Vyj}Ia6=Q+YC6pQFP*QLyL!@coT zERxK)nat;W6F3RvvhC@llTFFesd7!h!H#uu*-fSZ>!sPHVWLJ$@``9w@dPh&-X>Lr z<;)#KvYO;-=00aHW_fNV7j(kpOq?eSyUo^ISx~#yTFKnW?0=J7$lM2Qn{t}?` z=b*~)W8BBAZ#@-sje(1kvFB|v|pzjN~sL389hS#=gnT!NMyrFOBbd1@+Vq9n~E zJT}j(0eX#J_D>oK(Ccii%bDSg0R4+E-Xu`<&@w?AkMasx9u1*JM74x6%7~ds6Cp6x zg?F3!*s4Urg2;_OY$TJBt6E`XpR8@x4Q !oGv qg5qJzV+K zBMZBYCO7y7=L51f te!GKo?x|if{KG;f_y>G1eI`88pItxH)VVo2v&J$ zf~E$m%lA^n1XZSgRPkfg+|=;AT5jrsMH5sXtfgra)EI>9Cj6d0LCq|#g`1gsz)?h} zqx~>VLpu$&Z6!XeSJGUnr( }Cu&Ei$MC870GhIBO9sdzl;LG=OX= z0K$R7AlsB60XN8*N|1BZAOSbX*#OZBfN-QTNE9BGZ;?v((nORXF^by{XDtFBsdR&k z0>mf)!YP75Vp!%Pxiq~9WcD|IFgX7XYE{UKQYo;rKIhN)oF5egFZDQ{_n>dXzmF(Y zta7V3u2eChR $RE6q4_DScErpTOp$L8#m1irrCltx~U#XIQc> zhs06r2Du)3-QWOmx*XRg0=p?{dK)BUR{+zn%T*tt^56lQy=5QG;T;?!S+sIYB>Eot z=q9SBn;nSLY)u7yf<9@By#&VMkMVQnAHnt)+)H!UbZl9Buw(vynpZ@dI}hDR{%%j_ zp+?WWdoZ;e71nf2pH4GnZ*43scp1@dB&9tNb~|c;y_mTVo8}#;3ieBcR*5wyW9&I} z5q$~}erlvoW6v+b@6XW1Hr64`W|>Pm(pYOdw{&|Bc24iuPsdE58>yn(dw|-uG @DCRUQ2WrfbRzIeYiS^nfK$F2k_Kk z6pcqv#yp4; #F(zQ%Aj6n1p)zI@)OD|9} zz38BAvDarVA4nmWBiR{1H8}xP1Nk-X0D1}j_c8+L6^Gbt0DXzBu*F_s2T*%DfI4LW zA$}GJDjY^FGz(0#P$F}0dF5 8o^=4fu#1N a;=$fds;L5m3$4Dg&yEjs@nisN1=>&=*h{ ze!mU$|B+W92!w|!aB8U&K57d6FEk5r9= zYLQfpgX-#x?emhCWqY>zy9_E(iL*r&&})HSPvv47)r$roH##itOkQb=H)bsUwT!2& zlgW&5W`bWG#(4|fe(J*iEnP>xTWR5Lg};dzR4baPL9{yjt=YDSps%Zgt|l80^1veI zLWOx!LVnQkxs-$K8fDM{l!FeS*`UKke$a_FsuAs=?ZC=*I%v~DC$PP$P9lC+Ss)fV z9?s^MZ>sAPzgtzfk62PbRX)12s^3zA)Ve{IDnYJQgVee~mI36%0wDYifI+^k1gUd_ zELVbDrv|BWgY*GpRRIwG2*DuVQC4jAZjjYVkn7bITfG}(03d4$fbdrk2DyR0i`FW! zc<;B)?~S))Qi|Mz#Cj#jji_&|hfhLw<9eq!I1?W%+#rJh*;oLCKf^G{O-hhvH^^y9 zkngKOn%y900_3a$ApHG@L4KfInkM(soUH`8S-mt(ZjcB-^a3FKL5e|cQ95gj8)Q@o z@ {-#X+q zwmp$87%WfS=`cr;ow!Tr)=aYPk$#HO*)H5~qlMTD4$vZ0@yA-#Hrq(ZFKbp2--Lay P83kzzMsJgWar^%PS#Sa> literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogConfigIF.class b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogConfigIF.class new file mode 100644 index 0000000000000000000000000000000000000000..6000938ab62837b68c7cd00934d141d66a45f339 GIT binary patch literal 919 zcmah{O>fgc5S?w^22vnR(u6?yYWZ>wU?FjW6Dd@rN(3~8O6_TDPu&f!H`-l?mY>Ff zAHa`7jMtk4QV<7w^xnLA-W|UmKfiqkfM?*B;9&_KmEbXhwHVFdTqiQ#SHhs$O1Rbx z>VCU7 CJjT9^#Idl_ zR{pV3A||a4#v $0^5J~*eSS7L$xI}_r2AaZ&hoQeAS 9L5r+fVa|FnA$V9E_BV zve1YzZ6mPJ(Kc4khk-a9CBfev7_81>_U>qiA>HfAfBcHPP7blmfWZPiixlpLM^S<$ z0IJJSvh|Xym!WL&3S6=Es>9bDuE470t5CDG?(mw!4QN{aI<#!P0XJ=3hg-JZcKD9N Vcb)#8({DJunPWQdeR?mzgI^nK^2Y!G literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogWriter.class b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogWriter.class new file mode 100644 index 0000000000000000000000000000000000000000..a065dc2798d5278bacd337e4dc1b8167d19e13c7 GIT binary patch literal 3422 zcmbVP`*Ryt75=WY);h}8Nu4;3Qxlv}T3NOu+@yIqgxYG-I>>HXCk~EF=~}v$Hd$#^ z?aEF R xj$-DzF(9j|hB{BZ?!O5wh&SMdY85=`4} zUAJw%e*4|&C;$C~Lc+i7yIxV@K+dZbGu4_`sOJM`!3i#BF4zlpCfYx6A>)**Zf11O z4{CNkm $)yXXy3Ps+NS}zkgXm#ZYJmW0na3YQcc?hh0bWtwJXKUnQ)D} zR-}Oj&O5Z@*ge=0@s6LQw06H#4+`F5g?^u>>SIpD363koQ~lElM%F86g)KR!q9^O+ zIbAzr&$(Rb%z1f6&1UR4Z!Q`^$)QI_@4=#TH7C$D+LILhOo(%ZS`MY|LDYyC9?$2= zzq=)VS=aXctnCLUF6DJKV6v&L!(Njgg|;v~j6-UCc1#4dxq3mn49>WMS&p)%5StxS z*yQUV%8Ei)szp^ZRl>fhWc$l!7*a;KZBbn1m})ARck6zMX|2^OS&x{}foAICoRa!A z3ByKFh|u*+y%IQO-RfWGTC`=o>Scy_%B$D%`lKU?>{*M@C=dGtk`_jA%wmZ@VqrfH zSa=i%EgZsO3rBFP=+GA3tEaKYbl6<4>VC1b+zd^$AjVbOYI+?6|_gd{`ZQ<+>mA zNg?X8uJEfukj>k9-M7~3WqZWsA6obkPAhD0Ez8P9U6A6m@MFAY;&lr@!D|+Nil3Qy z!@^bkT%mi_m8qcSRElGD$1Ug@Q8r;;dRoeUim2{OS@;EhDdbJ!qrZ=(o-gTwg|~3c z!mn`M#IG&<2B$6jR>%n6w(vVi#qaTsg{Se1g?I4>Ir>Knf5MW5KjSYJ&fu8B;SB=z z2~8 zPdzkRie_50^@j@sjzc8SEA)dKD}nTU(`Vqe1+ju|Nn>c z zFCqpuFqo!!ivs9SVHc4T8JqLG>bP`|1)G-vJ2~G7ZN95@RYafapEmaJZPAYy(ilJj zyD*3$DD2}SDTWLT>7)EMq?LvvyJ i_>BT1O=EJBD+prfq@gTm$9V?QC$1uv7!WgnmP1h0U zA8;f+AX?IYN2~$!1GH1g5*yfUBxgD|--LCCTWz;+pTaeCq;I2R<|ek#rW+L0MrAvw zI5K80pIyMiTupO*A9n`P&7kbT7f6Tc_WsbQJ}T~}KVYvUNuj`+;vhmkp3c_qJ%ow9Zd_baTdzJvQ^aqt#8V>q{j{hY-fknO?uvF$dt z)BLW^9SwA^ur#o }ueFp}R{+9yNyU_850=&_2Fe;ZnbgYB;tA{vdY`5d?=x zM^L1_KGPzB7awW!ie~}Faf%+v+Lw`|T!jftHhnzKxkMr%$uL&an+#V+>Hk Xv$D{3a6X0M#DKm|BR2qXc!IjUV~{Y!HEBjY9bdBJP4*>6(`-1U_;5BL+C0@ z5t%X`2}eV&9P%ifT}G@LA@&TeU1c~E*RX{HGx8b5%jzYSliAF~hk_dUyvYYzbl|fJ zgA8>0 --(^2GJp*OfwusN}HyPIO#*p Xe0O01UtuedpkHlfP*I1Z d{5dO~6-IiJeR}hORAd0)IOGQDDH6&t!tgcG}f>ER7wA<8Tx81Z|5+21T z@KzHAqluSX_#VE7ar(2GxJ0}#O{X(+zM1*XoH_mW tcVn)Ob5jPnW-fEd{W8LI|=Q6No47oeDYllk=J%!>HgK*Dl zm<;_j+coR$rf&L=x$clBU-Jy^Y;oU??9?fQuk3)~LCy0mt>t@-wh`L9cDSeQ@LjG2 zdx7IwvpbsIY&n|Fjn`yqcl99jxe;!}tIOoAdDbd-8; QtRUFC3RQNl{&? zRBLfThr5=x5&E`kRk}UJZWrx8A<0nu=VA<5$J{j?YG9T4Hq9X5R@|a45|rOhn=Nhs z0*c!mXMeic#-mOWdBbb_hPh%#O`rH%uco7F3Qi%fpdSOoWV8OTzV@WfF#IQx<+klK zOkc#Tf;rq$FpmYIKd#_578x?*&&hhhu=>9al40OChc$i2G(v{CW3nGL5!DrjnPcMG zq3vi%@FuA=e+(xrGpt3Yl#BzzP@#JC03>&Up &z5>od zO|yI_q(nYmK7?3)i)_AUF{=uPkW?YDa$g`kJwSH!6LR|y^AZU)OJX0ri(=^mGH)=M zVpMX9c{xJF*b^O?D!!v48KMJ>AV*RqQX}+?(l}kf62|Zn7h|&P389oMQ6tp3cmtf! q=i{w$iWx&sL>%L!36yOU6QpGceV;OoQI&c6t4)$7QuL*`{^g$?GDVXB literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/NullSyslogBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/NullSyslogBackLogHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..511e9bdbd2979b89a193ce0e7d2c5ab1e3025bf1 GIT binary patch literal 1170 zcmb_aQESss6#h<{E?rl3t6Fus*=-Is6@#!nbxd?x43vs=41ByzL%j7iDM?zH|4Muq zDEI^XQR2BtsDo722On~C?>XoD&Ue3ie*OOb6ToxqR#8UN!d4Xqn#;UwTiCJih){95 zz0;T7lQ)ERCyac19EF34o5-n5&h4R?3OhcJRp=iKZ8;h%yD!{Ne6+h0rFv=R6-PRu z|5gM8 Zggbebtj{~7oCc};z+#{x Jq_UR!Ga zH~#g8&$N3rETc+z{Xd4H1`8F!>fcv+*B^RrLO8sFe%^>VZEW!jm%)$2-#tyvbFTL+ znb#FQ+59K|mmgn%zVgOEEiVGraE r&fB7(Htn%QgZMhf5rYBb++;0=Q{OS}p+s4#ll=158SKm2HhHDod^`lhWxE z^bOj#=uCm8nQ5ng`%s;JD+vL{1!p{3X?H(;=bZ1d@<0Fn@h5=0kRuquY#76s HHLK2Fl)JnX;fPkOWjkg{oJm+C+D2~ncdu`ZCF^FX9!n~S9(#|Q#1xv zU=UgjcNSbwb=6vA7)llG*ELzMM~AVyts#{?#*q)2oIwwYw8aa8h?trh&=kf zqBJbk&?zE*J7>?k_gXkF`1}fo>Cv3L3U#H~lxqYZG+o^T6{B9Jyj33`Zv}WEFf4Y@ zqcfZ>xvg>hLQFnUTLXXRWTW63N_u}Wi9a uQ9&X7n*^a?j=%5_DOo#(o&>YlBLFYtm3jf?maUx}E;*9=#k zsCZUVf}z)T#uG6oQ7hUr9?q3ZBzMs>4C`;> ES3=cZ= (me#mi KUhxi+gv1f=xQMUF#!q|W7a(TF4iG$njYF`V zorS$guyLYw%Z8R5rylgU3r#@$z#&jhBJGlpY0hQGI+Ez1dAv;3u--6`A)qd%}LfUA{<{|5)5L z(sI1t7agS8q@%7)N5AcJmUPTv6$__wmiPGQJ^p!{D=*UfUXlJtym*l=cj7g5F|VNu cI4u#UWh~ME(vzND_BbuOoESbJY#%=S4{F1ErT_o{ literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/log4j/Log4jSyslogBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/log4j/Log4jSyslogBackLogHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..0ed81a721cdf4f6da49ed4ac14951bc843677cd5 GIT binary patch literal 4353 zcmb_fTT@e46#g~@5<>7oy`i8H6-fZ2h=SlPC;@6j4R~*@C*g<(lbo0firQ9NtG$ zo%X4(ed$b}tW(kIO#9fG{-{pBz0V;DoS@QHX77En_d08R>syz7{Oj+RzXRBVFTB`_ zSRMQrufqh+%BOR3I`8FlK|Wn{LcPHhf%jue& zrrfyh#ahHXFyuO2j~hsOkdi;r@ CiN^~dxvf(^i19`(^THFG~i1Tu}{ln z^z>v**K%fBKwJ`7(;ij!lUjNzbS$amasyJbp4Q2%+7MXnkP%qxd{Nn0us@#98tEye z(Q9cO(^86|l2KbmU|qRJdsnGEP~pHCnOw%OgC5Zmc{4k!%r;nN?Ja@rZ}Xx+|GzY; z@Oowb7+TV}LszTYC7%sbdY*CXnYMFmQ~PMZi9{VTs5MC|UBxJ~Os22EVJoz+NgOLd zMk51d!7Agw*2*ve%kJAKVu5AtRH-Ut1UlaygY>zY)C-(>` S&kDMjv+Kh!3sU=0?GX8SL<3yPVqO zbXcD4#vXxvvemqizE~lhH&S}BIt4Zo>U>H06IwcL=KXQqpDrYm()4~eZuxK k}ARj<#?-m(Q{-REj=3kMs7h3ea^v92+A)&T|z@UM^N$t4oOGQR2~Vr4?#iy~!f) zDi@zG)Yr(fkV@)pd8c@VF6b1B&SR)KJ~ViCm`!GMEOLr{XDAjs72_HSPlTf^f9t+j z3hQDxcGl3hoo|SZ6^79W^M?eUwv$WVMggaj0-n5SIV`Zd!WDNqYnWNyq~)FORD4=b z RyPXl}NU6cL)F46dJ#!y@;mG zMnj9TsnWWnq}xXGh|-dh?j_K4{E3EF@LX)Hdk*g(!HyTGcW~53W DnS-dkL(Ez m 5 }!EWHbi=4Bk@|8S1tN*U;IG2UUuSuzTQnGpx=QaNOUeo4?So<;r>=oUv| zcf&`mR~I4Ih&)c@I+0%^a)WrLi7Ux$NGbF|3r!Jyq=-IZqbF9Cx7GB3A64{6HlXA5 zL;Bbl{1sL6)UJ}$mfGG5$^aQQznfT%oU-S$-m>kLnw$FUusQmXtJFQQ@n_Cpf>{4# z6FtE(%yEq42*&_NFUMYv&{M2_@)V8ssOI`k*;vEp>L--5nzB{bGxY5iEBQ8KHcNKy zFs^s$-93!(qbtg9uG4r>hJ1qcBy9`I4B2>1awt9Rl3Z}OUSaLU=UCUcehwQtenXQ0 z9~w7u>g1Tira3g1X!5Gw`G}M}E=#DcVo16efMG>Q7eV!@gc`-WwsDQdW$z8x#%n4Y zZ&}jtmu$LUDZ|zk6et=F*oOHbNG7bfe}fuznYA>(z~+8lcFkQ)t~qS!ua)+jYMN>n z_|~Y>>uc2FTc*Hwyl1{wrba9!MN=(BA6pc`(xVo3hdxDYi}Kq=E$cDHbgrQ;AJd|b OJEas743!M-nSTH}t;N9r literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/PrintStreamSyslogBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/PrintStreamSyslogBackLogHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..2c8dd043df28654b23409f84127499417faf3115 GIT binary patch literal 2553 zcmb_eYf~Fl7=BLfge|n8+$w3;^g;-ic%j-7q?S?yO(BK06ufnlY~$i)Hzpgj{s4b~ z;}`t{{p^f{(az{Mo$*IGK4&)#!Gr-FKjh?`_q^wMp7(N2^5 IV{N8tuWq=;C2)tEQWC>iXLQov4p#Fwj9BG5v)Y9iudL4K?K RMS~FuSYmX=%ew=MK#ofj+HL(XC?Eu=J<8UK9{J z0-<@sGMoj0k!06n6ORM}ckH4r&@WG})ysLk`asK@w8XM@K{Fp|RYR_u#(?vgQ4`qC z+SO9JQnicqf@AC%&a<>DtM;sB+NIguv{9~@>AY6>oJ;yKfSMaXyXsBXd67<8yR@QN zMN_XblF{y3ccj=0$LzVAikE^7U8~uaKvc$VXr}QsgYhTj@#x*J3VOvcY>P1jiuRXu zTS%T1i>GsSIpgKf)T~mP LR|KX`FHFktGt&b1 zPk(5&leyC(k%Okbr4kRe^9>uhq1YY?y*w&a-EV_g-3}n|8fg(3cI_Jy+V=vs nAjrhq+O=9HXqa%E}ID<5dfqW!a9J*Hx=-nv#v- z47;7$R>j4-VHWjj7+VS+V_U%vK4gXF)TQ;UH35Y2k%Euq#wYlc#Zi;Y1$92bb{LEy zFHr+?>cgCZ0*VTBY1ld;fd6_!1XlhH^6fk?o>p+W)qt-_^FFm@!|mzu6DT~i)n&d; zCEdwYZO1OyY?1THiOwEkF1?#6Fx`!><3zI{d<)M0vsO$rZyw*lkp4woGkJ}Vgs`69 z)eBB$f^T2MvAs(wFyNvbeKOg~?z3d_2?#e^Ss?#^U!RWH7*x c%z8{}k8T>XB<@A%|(qxJq->{u;dn z^}o^7_n7Kr`>9>^4IayPgAIJs<@4H3ZSkp1K7lte+hq9;LAQC6smZbF(Le)3b3qdN zzem619St&~=TKhGhYzD0;z?j0y;xwTZ?P8_S-~ZjdBMYMF(+G*CYg)3+_;i>n=#7@ VB;Du(M2h1EZ9!_gNxKhoe*?7*OQ`?= literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/SystemErrSyslogBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/SystemErrSyslogBackLogHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..5147ac22e0cef5fc8a65a7ad26608558f158c917 GIT binary patch literal 863 zcmbVKTWb?R7(J7$n`TWf);2LoFG-(LA6x`MN{bH>i^3veG^Kr;Y=-UB&CW8rDfC}y zUji-k2lPi3zZvr&5*x_NH}l=jIh>jMhnqV9uhA}H(*r}bj2d2ea8Wm*Q9_f!4YlC8 zU^wXP2TDhNs?~5D=JHbJSN;XR jSQuZ9G% z8puR^9*+h>f8&FgD(;a?Wd4q!*xBzhtOqLOai42x+S3^)KbIN9$vk#BN@IUO axwa#^(=ixUFXb@S9qF=WcXF^OeGBLjKS-vu@1$tG+Or_#d&3{VE8`A zqQyj3@D!C2wkp`hj!AY+Xpt$4(tR=h^sGO#Twz$VPaE?jn)*j?B(!GO3~Wa#|1S)3 zvEG^4u+}#I)1xNZ^z&T$hd>c^l(0m3nX(oNwz_l+b~-`fCuQ^^6kR%jb&BK)MKk@D zwoSGC@)|{F0_PVc1v~Cppeg~^uuN66LW5YrDxC&oZ3@zbV`n`J(wyMQzbJLuYgm-( SpUEi-i0PS?#PHlQZ~O+gnA+3; literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/SystemOutSyslogBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/SystemOutSyslogBackLogHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..79484a1432159910d47e9220e82806164e6b6a7e GIT binary patch literal 863 zcmbVK-AWrl7(J70H_4i68a0||HSsFxMHfL3QF>uPT3FiBSWCT|Y=$`LW+&{<27D{^ zCZOO0_)yYsrnx93t>Dc!^ZlK3I5Q8AxAy>c(JElo14FHZHLQDZQ8%Gczy^aGCW33h zaM11qDjE3WMD?>!%Zb#N{*X_&pI)Ys8te`IuDu-d@MoX~A9&o4MDp?EkimJc`UJ5Q z$XI;JMm>?7@?Jz0_ejQ4zhlU^J7)~lK!rRy iCQARI9(WMipQY2R>n(2Mo zHr3Lb8|0lSoNG#QcHFZ-H3DA4ORAa`8pI-&=rkae8OSjlJL_4HjVWIIjZ&w*hDE9U Ro}8h8m|j^)49k{z I6eex$jtx4G95nNL6dE`2D!|HzPCl)lu< z45{k$HbZ( Y^_L8w}trj`d% zA3A&dfIHD) JyhthWm zQ*ede5S$8Pr8|^~`k8cf$B56iy9h?#ho~ZHwxJ?TG2sW}vFhnQ@dny4+&=x4lr~f+ zY>IVhHZpc{lsTijgkg-7@Bot}w9^V0=1<}(()Cp+qKa;d%2YDdR3+dc-xpehb2-eF z;9#PJieXte|8g0goxiy8MtDLipCM1bR;#A+7$yuK4|uaJx<9lnynv3)sVkQrx}di_ z^f5^{nWvj&xP}6X inbYy6V$-2L3&-Of30 zp84XyK>#yUMF912 z#KR(f{5^mV@ef(qKLhv( zhlKEBY4}8P|MKBeA3pQpbA_UW6%U6ZYpr-99E+~0U!tIvDGXU0izbqxXmV{RlCp9d zZun^7wuVo(E954&BqFg^g^Gq)ytSqy9&1iDCBqxT$t^YOLmNXicKgirHI2GsecgP8 zoN%)hO)3N%beBjd+FH|?jEAGGY|M+qnnIBkp>|8bPkqT)Q!K)4OQ +~4=1fv7U8V~J0#<& zXj3R@r3We$rxF&I#yv^Jt>z`6WJn=D91SPA$>FVns!roBE|98Y6g=e>Yq_$;v1YEm zupu0^R;1e3S@G4ObrIGC8)R?RhIm9Qrz^e5wlL>ja<~Hsw|7KpcvhLSn7MvYM~4+{ zw&IN&tcaD2MY;WfUO0uJ _eZM+D% zA$>p!Q_3|>s3X+WW~C1?(Gjj`h_&(>w=Uht_cULwj<4Om-rVwtwb9}p !!kphhM;F~-};g4 z-{@{5MsmIZnua?@Wh}^W$Cyk*2}dmNXI)Czy?<@c?%UVw1nsVUD+}54 )+q3r8Y9cYZD;!RdvSgh1o`(^YuFVn@`o3PMg;zXQeVig)q ztQN6G#99$2i#SEZsUl7jak_{zM4Tz&D vL->oD`U+f5S* zwD{B!rW&Kh`qVg6jVHb;RTF%w%v2NABvVaRQ%p6LhpNiK6RbVVM1yd6bTy)+k6m>- zMTO~ynJD9ZbcjTsSk!xXc3h)xWw@O!G*rBW^{vrZ+*%xx>samPGqW6^ts#9o>G=G~ zSdY^2{ovcINC#s#aSZ$y>mQHDc&8^1Y6-U8uh*eo6VVpBq76!w_M}q>*_BZr%}tN{ zp24VNPy_7&dZz0CYk dbKvhqCC+&t L?m!{iz zqle33^lxEg&IQ jYh|31)z zFpMU4d42yz*&Fe)t8`#(HD|sAa#|v(M4NX4Kf>yvunZ;qbo??Jm|xCsS_3QK6|cy= zR~(~G=^J%Q_o!2PNS)G2>Xd#`r*xG%rMJ{69i~p{Gj&S0sZ)ARozi*gl>SqvbfG$> z7u6{pDbuNBqqC-LW$7g{(#_zk%6(9k>LC~+JR-azazx~c@QLt?$P*C|kuSm&F+@ax zh(ZxXB8o)>D?JaP 3bMir)D26MAf zj`{qwJ`R;wifP>9Dy&2`1B~g6C5}Xx+Dv;1SdR_dXC>a5HBq*BnI6M-`cLL$!FQ3v zV0xx!L1i~i2@b97#IQ~b--*KDh;)7j{N4q7Fh4jlt8r9sqlb;-9>(ZX_u+`(m`;pk z)7aoRicXB*kJ2OV 7mA$LC}cVUWd^LJx1+x+`6bz!E@m@bqX*n|A#Rh_8hBH5DX(4N Qf;oyGb%YIgR;E8dSIyD&p{E$GHk>{!r=qi#gG zog3z4{gRV4=vZ)2Yn-Vy+S~IOX6?Yc)MpnT#jNEl1iCR^g9UoPimIeq51*}v=XXPP zJzoRKzA#6iqid@sbYYH1Hf=?9X4A}W6jzA~b3f*GVV+hoq^EL-uAHwc3%fCm{R*|- z33g5vdQ8>Wi@UJEskq3-D9T_km+sz$g?c|S7+$`~^jRLuv%HUYvk6;qE-D!8O;Ht0 zcd2{S{Y(!Tej^_h#w265F_#Z QR2Vy@sq z^#CqX2N;q+#)$j{Y*(+~GW8a&REKaCEy2}>AJ=h(*BB @`lp9s1o~P6M_9g-9aB9XSs^Y{VuQ PhAajqR+#b({)_mtJuPwGdQ~s=iqB%FN{^T$wQ8@oIBb`JE6!R z#!pOLjV{AB4fkeDQZB23yR$53PFjt^`Ph~oEC )D%1vuv zfBEX84llp6zMj_g1Pzy$y6Sm{OLo$ebmBP4?!eq>omkX~TCp>WyD?f4RxMe c;2Xx{w7O4VA)cg GGX?RIfyw=Z!$s$Az$y_7Y$_oyy)KdRhb1pBC7=4xLV;HV_>kd=JP6~yNRdCe7s z-@H^I7p~8p@i{?WC&(KEfJo>gAlqF*yiSleT|xN8>;~d>g1k)-u`Ph@b+a$8#AX6= zxhsg@3G$vR$QAA&ekaKL1o>b95D5YW xL58`4T<;EIIzdJeWb^1);;IihkF8h!bQ2LCOXI zk&h_>xzQD*zzH(h733y&kOC)21wkqY0Fkdb0lC=~q|gac?Fw>>J4m4uWClTw8URE- zCk5pDt{_EDkXf!Ex4MHAIYH(UWZnQE@;xgcKX3&pc7iN)1=;NmQtSj-M3CA6K;(m3 kKz`^75_Ezrbp_eu4ia>N)DvXc03h;3FCcqqdkoz6Kk%) !M+>7y&ygc;bW|e<&yxEAT~k>qaqenEIfeC z5XObms@S*0qKRc&i0=oW2T%*ZU>Iw1Q&aRcZZ@^Lv6^3CVAmKTnYz)m6vJ9m^cMH~ zf6x4N?9acyWjL_9w2;l^m$IZ7Eo>`0imWR}RW4bkW>n`H4wE>&S}3nCq|4d$-115> zUGCzR^TiJLkf)n1 v6eAJa`hWMUvC3~Zg&ScjYI!eQrHAAzmF!*K?YYbAR zu5yNh1 l-)mFvQb~I~Ow##Ym zHuZY-!nUl{8oFHL&8AZ2a(bg_nM%bf+0vrJrE %#~`$qkt zAvCg&D!gG4;;4lYU0hPfZp3Km`m&j=HLP8RaX0yHlqK#k_;&;{3BYDwqpuGz>904_ z&l-3?2R1dXt4>KF`)tnyje^>__lUtC=7gRri&RWbopW)*5GvJMW`*Z8fy&8&U^*+% z7e*3iXb9HHWS4$&u_&u5LvV31RjZ|%gxg6Qr51l=$t3|%8y60E!gw2V!bP27)K>GZ zJd6e&gmDRT)G}Mt)ljOXWvG0U#zzgn45JAvjF!-yvUT^nJqCJCc0|mFcofDiK4m!C z>-}m=(^WAX>|Pk3;d8Nk5yqFo>??fDkpAC;_(Dy~8{51>gLL*KZeJMXd~P48(epCA z>5k^f{z2*o5yKI$XL)K|T2)PYE}W;r8xe+yz2`tQw@Z;GVuYT6&OAu;wALsK{-CAk z JoW@pclOe{ z&Twf!nEvkcd!Cn0(06SL46kAslQ@oPI-j7Azz|+T94B$gqa#GW-bMR}exr+)h@L^h z(?3o0Y?pk9;L5~^(R!95$g~rN;XnNp>?b> 7-&j!-Dm3SH9a%Xlt#YKRO&T7KhX3Y z&-4a-R3I?%4F21v+ZcX|z%vAIKgEGILWS9mzmTnW5ixp;&XGmTv2&XssFZyn66W{y zKJpUp^W^p2eY{_Gy}yeqZrLrmJ@KDn*8eNQ#iXyRgjq_yl$2bK2 TM;q!gcA0oS}UV)n=5h;vCBZZ$a+NQrMKR_x{+XO#^ z2*$`l;3q~NfNR7p68|PimNANw7ju-P8OlRk#+V!3M_O68>>NID%f3cBLMt}=90#L^ zsIX`ohrdHWqR_rx#NO&^XUwZAhDFzJo^o 4>E1ddqrXd4q#ZN%G{6soVJ{BeJ8ckj~F-=jBRogkywd0cTKczL97-Ohue lqCh86SBg56u)CT j`>;eOzr?6(bELy?gVrJ3{1-)Qc=-ST literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifier.class new file mode 100644 index 0000000000000000000000000000000000000000..c196000df1183a1c1d1cd9d183f39fcd38c55c38 GIT binary patch literal 2066 zcmbtV-%}e^6#j0qn-EwEh6bFrw3Mn%Hfd83=?@@Esn{(6YC}=%jN=kE>0+|M-3?Rx zCwyjn@WmNl`cP*oRcGvDANse{S05d}yBnx2J2F!zGv}Uj?m6e)@0{;$p8x&(QvhRF z>&5^kQb^;29!%o06j!=wUhTrQZuDSEis>%Q$hDNjhjRT$idiYHOED)CZb O1x zUlN$j{=ZVWRRLwLwP6YLm2JmbYB$#{cg0+9(338=szhrNGwqI3@$cK7z{*kQ+Rd#- zv4g+Z>@=V_yYBg}S@k0U64=0&>3WvoG I+OB zaZV)fjCp~0Rz8L4H%Sj)wJegVTmJ113yx=VhvycCR66`n$mAyZVtvy#8+=o*Of*C^ zB`4a`Fg@RJHmnEBwb!Ed9|K94^4juo@ofkUW(_0q_(a2U>i+!zFLN^4=&->EZW%d4 zIm-{?00fRBM#5w;NPUQ3-5B16A}K^&rSBAmDNoZ{=3b0zpZ)|w7r!8;=P7;;lFm@3 znFxMy6{Psna16Z|p=U5m!&!{dVu7GMIVf4xDZYSs5H*z7A0ze~;sT+f2>c555z}Ij zha{K)^#7~y&_UrLyo>j^pOS !U-{|s6>kq^v7 zI#n(Nb|J7Y>GXF`Dj6mABSzFe(6biT;~8ZST4hbqGYYqRzuLpG%F<6L=}g)W9@FzO ztZ!1ysLUNb$W`}q)gU*lwRGVnxa$OlU?hX=<`A_L1b32MI?cbsGq^&l#4g?=&@Tzq zLKa^m2OoKSivo5THNpxvk!0*S?&dfRpV3lN89xC%@UbC5vlvV*AGA$s1!{84ySRXh zh%1VG^o$W)$HJDP&YE%hhGmEP7umE_;i>uq)c8Za5Faln<9m4PAp^pRg|xWLDO@GI eYXmkETyi8VaxlH&&h!!lE)S3KxbdLM`~Lu?SMPHG literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifierConfig.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifierConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..0cbd781d2dc7bde3802db83e58870514fc22d1e5 GIT binary patch literal 1361 zcmcIjO>YuW6g>|Z29VljT3W4I`=J$vwj Fw@Kojg4{P z)}4v}!L23|6Blkx{2%@e<9)-FHi)$wH}AgtdG5LQy&u26eglxh-2@W26+=3XI5IKl zQf6aVk#aSLH5G=6+bVJ@?l4Ta+!1EG!W~!G*539*2DZa6mbWd}GcB)Tw!2(;^z+SI z<;A=A4ABFJH^fT@t=KXTO`~mEO{45N!fM_puiI_-UbVJwI%V#WX;WCj+hPc(GZltN z-mY_o@uIN!<8G(Qon5oqCW}_IYt)BH-H;v_Bi_Dn8J-tyr)eBGcD-Bk#G&wx3?JM* za@%%uy=92bLEGqX*EO5m=-7495Zo~yR9(+8YhKw8EA`!_z)J)hLiQYQa_?zCYAT%> zMN5X117>meBs`V=Gg^|AF~{)<%FQ1SBSDT6rEGVd8ZQV*KYfm7*CgpArZK}1ntzpq zhDlo2>m;V+McLaetZpQck_s4}{jZ_Xt2x>IlWL3CXwRGfKs#dz+XaTTbEOBf+b%>F z=rt!0!UZG|!7RpbktmPT7YJd3EHoOrN91IDNkbv2QVflc&P$|~D3&IL8T|{Gu7!FC z>sq7-Mc1M|sGrCc!eu%&D%3wy1UgLsGXx2O_S10%S4m^IhPj}$K~nk@{WHQJ>C!J0 z^^LQql9fU7^^wWSaPr*9 C7Rqa5ls7K zr~9cvPgKO8qolHU27nR(D8m3*0$3pcgUaOo0w5P80hUJ6SBL4ZkEDNN(A`!*KPnlY cTA_R^zy=iDJJm>Zz%(kqjo-*ke_PAH0ct-C2LJ#7 literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifier.class new file mode 100644 index 0000000000000000000000000000000000000000..f4bcd776255195c4f13c66b782aa812057db0700 GIT binary patch literal 3980 zcmcIn+jAS$9sZ6jX=Q00yM~x3&{TwkNVc&`NP4jYC3a$>;3ULO9PB{S_3B98MBY_b zE60Ym& pGC8O)|2a7L}prmz=tJ=~r%@O%>UDHvE#U(P4-f_lGb;6e($ zxR}D%VWqGLTWw28NcAo&Rh1N$;HcH5G%ll>!ZO?xJk-?o8|vX3sHgA{7SagNP>NU7 z_KK2RRjg}@_L8EN4ZJMSUzfgPRp+E%cRcrO@rZypF3>yax%I$ugE_0(knw-N^YTC6 z|6u+<0twr5%T7hWp7#7oq2_y~h8;L7POw(EWUW|*`dYo}RSsM#ILozaVOiGeRz((; zy^>RQq+hU?q j0>b~Us{2joSA%Lzre*@ek-lgUTo4U zNrAp;$CW1=%Zt)KV=Y!m8JPBL!ekLF?jvH{_HE_Yi(BkfZ-~O-BhyD`ls&^LRi&?1 zi9?R-1WyT+b6e>{l#l!z5ek-^x qmJD?s(=+Zzl8(Cz&A}i zhA|Ug!k0}P2v^@SF^my`gPT|my`E{Xx|Ze9Ra@2q4nu*xt+2AJJPxF+w|Gg~LDsfh z*9)?XGV3;~Rb}(rCSJj-0=wE0pTYVad{^LsPgmMR!>N{}uQVMp@I4dX$7=?DVB&|k zYT`%uvB06xu()%hqxo#fll81};fm*9&R%hXrL0qDpG4h}%V&KVG<=tJpAGzmH1QLq zXk2OksfpL|hKVOJY2Zy0>x%d@6F-o`Z+`bJ+>of-J8iLc^! zCVn5f_y-ez#Gg$3S#96JRe_mJQ15&|9A2ykzGVj;D@nlmzm&H6_FhgMfy4LMr5z6~ zwyqjQ+dIq$MNg}_86ABBJ2^QuzKy`C7G82{Z3o${=A9|kBaY*x|8_b~>0)GqDwS2M z&S`UBOP?Nmnn*=`w`C$egCZxbWp?iUcS%H}l9R%!)udYzc&t+#9VU#fU)o9rUZ_N1 z+ikPcp35skPtEe{GF*3>pT#_H9$~$0z=MOwmvtEkJibW <%%R^sJ_hfMDLM6sySuN=`=D$T=i z_iYkQ7)Wu7ac_RghRor4Nyo!e`Z-^gomGL6d(5QjZi=P@@0eU|MYcV6yyM|RuCuHZ zf6}TmPIW1m Xikj8_&U;`$Z)1>Xk6PkYDvlPWTD%wTi>|KfuYDGdFACX6| z(IaK_;Lz}O#D~P+kr*0QkG~=DFXg8(KajkRo(~nFiByZ0RpzP7|yrRV_ThB72`u&Y 5nAc#DfCax30m6{S~q9Ozh)##}a&I5+BlbA5Qbn6Zku)-(eiPwB@7p z;2ClpV}TxL >p z-NHlj8J6|u#}dOgu}dHmQ&AZqi+K%wpN?9^YA~2quo+#$O?;t=?77w^jQs|fq}_MY z9|<>2?8(GGes3(vXC|r8NUO^UeY?u*gnEZ)jFJw_@_B|OJ%>l|Jma2c5x;;FxPS#* zgwMaYukau4RoEJxV?=O})MF?jK?$jGQu$nO USAR 0) mV=>ShM~vft}vT5?s~$p-#lMpU@sU77032`)Anm-GvMj>KfTFcAHFLL zUDh_Y-g-fcVWhfa?wLm5i>C2T>>8E!n@0?)<=DQk11IoEZ-XIcx!m-5Wu-Dd$H28x z)o~lfuItnT%NKjX-#0=rZ{KS=jr%)>XzezQ7WX`}!Ht$v7h8h6#&Pku)@qo)9OW&y z(};abGzcSAaq66*yDDt{DrjwT_qDm%q)1=Yv8ZX2TBmh8n6_L?(pmq7tq?h~xKw?* zBC9H9y~$lU%RCmg@D~`0S|^7~HEPb^7UXWO!Tn?B8OF%jj;E6IPN(LDM@Ge`l+;Re zP6e5ADw@(ZWG!{o30#Xm6Vg2GxZEY?PfG{}^PitGL;tyc X@E_luFu zdGw$+k3RG>to;?`;-=@jrsZGa0t2~P!#LeGm9AzIW5^*-s{*YOxPp|Vpm|Dy&{M%E z1~5n&L$rEAaYoPHBe3-&B-Rg+JVffH{)vJK4AUqtIZ#A5^*TZ`Dc()7Q7Q!*i=D*M zB$l~QY@7rp&WK$N#hA3SO}0iQWZ?n*5Q@$Y(4{92kk!jH`%Li&Zis$5z#Zyh7+F%h zf+^}!3$=%${kRcolTzpe{VZ@Z^h@?{&`S27*1w?Zq~}Z+EXRnH(3WAi6(cUR5i{qY zBF7BcGjj?g6N6-8kO@purSl-!k8yty$oz#Mx2f-F^9e|iEIM%~0(n3n4?BR!Z$dgS I6;{;#05U8~XaE2J literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/escape/HTMLEntityEscapeSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/escape/HTMLEntityEscapeSyslogMessageModifier.class new file mode 100644 index 0000000000000000000000000000000000000000..11b737974919191ae2c2a235bdb0a672e9d37020 GIT binary patch literal 2201 zcmcIl-*XdH6#j0SA4}Xq3{XjF1OY?ZB2j@V6bfzH+LV+Eg;r41?e-?!y2*y!O-Ejw zadbw;SD&gcsN?j78F9u5j5t2{U}yZJ)bH+QS|K>}#dh}YIcLxL?sw1q?#-Wn{qh@t z*We`4i}MLwNFsvs8b*^CLs1RmDl(D4q;lR$Lc^4@N*bn>b5TQC!;FSY8fI1C?IbSa ziiSDmT-9(*`SWU6P?2{MxSqfbfs`j*%dqFA>se0yT4`KBObc`uox0~6b${Nln= cjYXT0blEWpYY?1%I~ets zEl 07Iof4i_^tQrOHwr4xllPd+Q*02jT>3K#~7HZCtRk5U7ke+EY zWMS&+OnIX2vuYv;%mr05VfIWrd6-KuU1|7oTvm*x?F*dA_djdir$Ut`2^J4n+!nZ; z-yR67N~LnJEZeA83v<3})vLq(ogsmp;mVfUYf#PWC?tijJp$WYM!;LE7^Y>jSKQW; zK+Kk_(iTXxn@iMH?tg`!_vSk%?WaJJA-O5P#=6|ok~-@IBIYt@Eb_7VEDG%F$Qo-_ zD$-?dlXFhfHRYtGbThE6?LDsgqvItU5-|REF$o}ncXhmnn>yad2RerEhCt7gn-s1{ z$A<{GE$T3_#50n!{b3yv6=hd_C8yl2rlX8l?(m7z!P}@cf~0B!%Q`Hqu!*_Ds_Y|n zke_U<=%}foj+;EVTeHtDu1J##A9_Y7{zKl6VTC#+QR=lOu!o0cYofM@$zR@T8a9ve zW2y;x3@g>dZCS7S)Bvvu>MoiusoNrME*tJBnJS;+h#QTDtg}VOwxz30#q7@)J85lx z-MvM)$oUM@m#% Gy87c5hEg?4W0OF@0 HdtXKKl zrRW{N>$JK8>jW#Jq;nFd+N6f~R#}ngJvIJ|d_I_~C;YlOLj($geOKo##1JOY71NDJ z(5?@(u;T%e<*svm%KQ#L4)nF~+(
fpCXXH%bi4}CD(LYkl>*@xJ@hMvLn9%eDPH{BDaAK{l5 z)(~GuFRguR*!^VA=Mk~~_v~N`nXL`DfgUdF1Ql?K)(|(~O>V(yHvSBoI*haYAHzA6 zxg}R{o|n-DEMk<`!WceA5uailcQAo(Fo_>9g?lLBS7QB+nV`7?Y+E1h67@7&xD!7U WH{7(1pv_8qkAiuWNY4cuH1ZD)CJdSY literal 0 HcmV?d00001 diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifier.class new file mode 100644 index 0000000000000000000000000000000000000000..1558d3fc5bcf7d3ea3aa511a6146883a4ba54328 GIT binary patch literal 4184 zcmcInT~iy^8Ga5(S|OI2*zt#KOh}v9SU8rkfu!I%24iY$Ac 0K}S7y2JMoj&i`MIc8Ep3ZQyde3{_^SsY_ zzjpQa|Ni-}00!|J14}8qiq}$5cwMB=iS&7qEP3SRQApuwEO&6jHc(8WltL%Uvg0Ii zH-#^tVxTI@S|?nrq;L O2~Rx`X-&?5QKT=4!I#DUjTF9uHx0a{ z(CyovV^wb1p6|G|`RPdobxon`vRm^5s}|g{Ds?+<|KndPSO1y$w?d-e){0I^VQI$o zO4$|9U9J}bXVnSTvUjajE9 Tt~|G>N45P?-7?&c;npF@j(*v%NBpkE#1i3?aOn+BTNO2w6JA%{)M4XuZ1oB z@Zh;n9|{+oniE`PCHC*dWuhdWy2X3ce2d}ip9xFDF4R3KlsPw7FO XGrHaJa?kr3r1FbL(Ego^qti zdv}~eXXL^Pxjh(h2EJ o=zL0{hPtJNzN;qWyRU&lKN$F;S!*^`f08hF>l zH}Fk`6U{xhQ!5Mfw+y^z;xgVh@NE;{!FNr(h)X8M@jV0IH}M1fP~p&{wG|eFi67w| z6F jVjoYrrl@w^{+Rv`#O7tM{$myp8Z{{oq9D_79)?zBjC`|No;E0fU96}R%hH-$}wE{m$A~J`GG2L>` z%M0se&n`L-=*e1Hv1`i;r? D!0rD48_wr0xu|T%~1#wg!r|1bT*tPc#7yMnLBp zKs}ld5Zgdph%mr>CbTv~m**Rnk8n@4ba{p@&o;Rnid+uw1Z1=X8Y0k06VONm^!!dh z$(BH)1iH`!^nwOb@@8UeB`tqpTH5)0Ei>>C9U1jUq%s5Y_ybaZlVo)+?l&Kz>myOD z;}e^@eWDwnVguc`e~YeJu{`|{`#<_U12{y#FX9RMkdU5ZHi1is;~4Wifqj_7AzWdm zuku3Ew4SB?D?ITMtzM?)hGyMIW|z>x(z!q+a>Qpef03lb6fRO5<8LRQeDhF}JFP}{ z>QOThYm%I4B02B@ZQIa=?gq=FOg%79?E>|$a_0{BmRR1eH`qL}jZII)MjBw8x8lbY zUxkwqhpb)$abd7k=3#Z^8%d!-1fv*`sp#;3c!3njEDZb!2Ncq*&?iUZnROf-O{5d) z_&N@a8fl|Dxq-u@$q#X4G0iqek9MRx!V4c=$FbY#j&w5o4V69NVjah~_?+N{fFdtk z#sN6!;s4BMQDq^! ?|jnoiLIu2YhNTEGm`8YA*` z%rUWX;$P8$O3=#%ruiip^mU$zpGA@$`{^l1K8haz^HC%gh!rE6d3poAbD4qX*74Nu zxDE>|92)nDy`~vvLfZyIQ*#i8CT`J78!Zjore~Q&{LF~FyvrR)ey;>-fWe;Av5uu< z^mk}9o{rOf- PN3n^d}JJBE7b*wseG z<44>(R^=V{*fnh