commit c4578dc062e7610f400f33f1ad4bbdfc5aab532c Author: Lennart Koopmann Date: Thu Mar 14 22:08:21 2013 +0100 initial diff --git a/README b/README new file mode 100644 index 0000000..63ca26a --- /dev/null +++ b/README @@ -0,0 +1 @@ +The syslog4j fork from Graylog2. This is used since 0.10.0. The original code was very "special" and no actions were taken to improve it. This is planned to be replaced completely in future versions. \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..05c9175 --- /dev/null +++ b/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + org.productivity.java + syslog4j-graylog2 + 0.9.48-graylog2 + jar + + syslog4j-graylog2 + http://maven.apache.org + + + UTF-8 + + + + + joda-time + joda-time + 1.6.2 + + + commons-pool + commons-pool + 1.5.4 + true + + + log4j + log4j + 1.2.14 + true + + + com.sun.jna + jna + 3.0.9 + true + + + junit + junit + 3.8.1 + test + + + diff --git a/src/main/java/org/productivity/java/syslog4j/Syslog.java b/src/main/java/org/productivity/java/syslog4j/Syslog.java new file mode 100644 index 0000000..23681bb --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/Syslog.java @@ -0,0 +1,318 @@ +package org.productivity.java.syslog4j; + +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslogConfig; +import org.productivity.java.syslog4j.impl.net.udp.UDPNetSyslogConfig; +import org.productivity.java.syslog4j.impl.unix.UnixSyslogConfig; +import org.productivity.java.syslog4j.impl.unix.socket.UnixSocketSyslogConfig; +import org.productivity.java.syslog4j.util.OSDetectUtility; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** + * This class provides a Singleton interface for Syslog4j client implementations. + * + *

Usage examples:

+ * + * Direct + *
+ * Syslog.getInstance("udp").info("log message");
+ * 
+ * + * Via Instance + *
+ * SyslogIF syslog = Syslog.getInstance("udp");
+ * syslog.info();
+ * 
+ * + *

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: Syslog.java,v 1.23 2011/01/23 20:49:12 cvs Exp $ + */ +public final class Syslog implements SyslogConstants { + private static final long serialVersionUID = -4662318148650646144L; + + private static boolean SUPPRESS_RUNTIME_EXCEPTIONS = false; + + protected static final Map instances = new Hashtable(); + + static { + initialize(); + } + + /** + * Syslog is a singleton. + */ + private Syslog() { + // + } + + /** + * @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()); + } + } + + /** + * Use getInstance(protocol) as the starting point for Syslog4j. + * + * @param protocol - the Syslog protocol to use, e.g. "udp", "tcp", "unix_syslog", "unix_socket", or a custom protocol + * @return Returns an instance of SyslogIF. + * @throws SyslogRuntimeException + */ + public static final SyslogIF getInstance(String protocol) throws SyslogRuntimeException { + String _protocol = protocol.toLowerCase(); + + if (instances.containsKey(_protocol)) { + return (SyslogIF) instances.get(_protocol); + + } else { + StringBuffer message = new StringBuffer("Syslog protocol \"" + protocol + "\" not defined; call Syslogger.createSyslogInstance(protocol,config) first"); + + if (instances.size() > 0) { + message.append(" or use one of the following instances: "); + + Iterator i = instances.keySet().iterator(); + while (i.hasNext()) { + String k = (String) i.next(); + + message.append(k); + if (i.hasNext()) { + message.append(' '); + } + } + } + + throwRuntimeException(message.toString()); + return null; + } + } + + /** + * Use createInstance(protocol,config) to create your own Syslog instance. + * + *

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.

+ * + * @param protocol + * @param config + * @return Returns an instance of SyslogIF. + * @throws SyslogRuntimeException + */ + public static final SyslogIF createInstance(String protocol, SyslogConfigIF config) throws SyslogRuntimeException { + if (protocol == null || "".equals(protocol.trim())) { + throwRuntimeException("Instance protocol cannot be null or empty"); + return null; + } + + if (config == null) { + throwRuntimeException("SyslogConfig cannot be null"); + return null; + } + + String syslogProtocol = protocol.toLowerCase(); + + SyslogIF syslog = null; + + synchronized(instances) { + if (instances.containsKey(syslogProtocol)) { + throwRuntimeException("Syslog protocol \"" + protocol + "\" already defined"); + return null; + } + + try { + Class syslogClass = config.getSyslogClass(); + + syslog = (SyslogIF) syslogClass.newInstance(); + + } catch (ClassCastException cse) { + if (!config.isThrowExceptionOnInitialize()) { + throw new SyslogRuntimeException(cse); + + } else { + return null; + } + + } catch (IllegalAccessException iae) { + if (!config.isThrowExceptionOnInitialize()) { + throw new SyslogRuntimeException(iae); + + } else { + return null; + } + + } catch (InstantiationException ie) { + if (!config.isThrowExceptionOnInitialize()) { + throw new SyslogRuntimeException(ie); + + } else { + return null; + } + } + + syslog.initialize(syslogProtocol,config); + + instances.put(syslogProtocol,syslog); + } + + return syslog; + } + + /** + * initialize() sets up the default TCP and UDP Syslog protocols, as + * well as UNIX_SYSLOG and UNIX_SOCKET (if running on a Unix-based system). + */ + public synchronized static final void initialize() { + createInstance(UDP,new UDPNetSyslogConfig()); + createInstance(TCP,new TCPNetSyslogConfig()); + + if (OSDetectUtility.isUnix() && SyslogUtility.isClassExists(JNA_NATIVE_CLASS)) { + createInstance(UNIX_SYSLOG,new UnixSyslogConfig()); + createInstance(UNIX_SOCKET,new UnixSocketSyslogConfig()); + } + } + + /** + * @param protocol - Syslog protocol + * @return Returns whether the protocol has been previously defined. + */ + public static final boolean exists(String protocol) { + if (protocol == null || "".equals(protocol.trim())) { + return false; + } + + return instances.containsKey(protocol.toLowerCase()); + } + + /** + * shutdown() gracefully shuts down all defined Syslog protocols, + * which includes flushing all queues and connections and finally + * clearing all instances (including those initialized by default). + */ + public synchronized static final void shutdown() { + Set protocols = instances.keySet(); + + if (protocols.size() > 0) { + Iterator i = protocols.iterator(); + + SyslogUtility.sleep(SyslogConstants.THREAD_LOOP_INTERVAL_DEFAULT); + + while(i.hasNext()) { + String protocol = (String) i.next(); + + SyslogIF syslog = (SyslogIF) instances.get(protocol); + + syslog.shutdown(); + } + + instances.clear(); + } + } + + /** + * destroyInstance() gracefully shuts down the specified Syslog protocol and + * removes the instance from Syslog4j. + * + * @param protocol - the Syslog protocol to destroy + * @throws SyslogRuntimeException + */ + public synchronized static final void destroyInstance(String protocol) throws SyslogRuntimeException { + if (protocol == null || "".equals(protocol.trim())) { + return; + } + + String _protocol = protocol.toLowerCase(); + + if (instances.containsKey(_protocol)) { + SyslogUtility.sleep(SyslogConstants.THREAD_LOOP_INTERVAL_DEFAULT); + + SyslogIF syslog = (SyslogIF) instances.get(_protocol); + + try { + syslog.shutdown(); + + } finally { + instances.remove(_protocol); + } + + } else { + throwRuntimeException("Cannot destroy protocol \"" + protocol + "\" instance; call shutdown instead"); + return; + } + } + + /** + * destroyInstance() gracefully shuts down the specified Syslog instance and + * removes it from Syslog4j. + * + * @param syslog - the Syslog instance to destroy + * @throws SyslogRuntimeException + */ + public synchronized static final void destroyInstance(SyslogIF syslog) throws SyslogRuntimeException { + if (syslog == null) { + return; + } + + String protocol = syslog.getProtocol().toLowerCase(); + + if (instances.containsKey(protocol)) { + try { + syslog.shutdown(); + + } finally { + instances.remove(protocol); + } + + } else { + throwRuntimeException("Cannot destroy protocol \"" + protocol + "\" instance; call shutdown instead"); + return; + } + } + + public static void main(String[] args) throws Exception { + SyslogMain.main(args); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/Syslog4jVersion.java b/src/main/java/org/productivity/java/syslog4j/Syslog4jVersion.java new file mode 100644 index 0000000..077855d --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/Syslog4jVersion.java @@ -0,0 +1,16 @@ +package org.productivity.java.syslog4j; + +/** +* Syslog4jVersion provides a unique version identifier that is created during +* the build process. +* +*

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: Syslog4jVersion.java,v 1.2 2008/10/28 01:07:06 cvs Exp $ +*/ +public final class Syslog4jVersion { + public static final String VERSION = "Syslog4j 0.9.46 2011-01-23 14:49:24 jpy"; +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogBackLogHandlerIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogBackLogHandlerIF.java new file mode 100644 index 0000000..d88a5c6 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogBackLogHandlerIF.java @@ -0,0 +1,51 @@ +package org.productivity.java.syslog4j; + +/** +* SyslogBackLogHandlerIF provides a last-chance mechanism to log messages that fail +* (for whatever reason) within the rest of Syslog. +* +*

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.

+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogBackLogHandlerIF.java,v 1.2 2009/01/28 15:13:52 cvs Exp $ +*/ +public interface SyslogBackLogHandlerIF { + /** + * Implement initialize() to handle one-time set-up for this backLog handler. + * + * @throws SyslogRuntimeException + */ + public void initialize() throws SyslogRuntimeException; + + /** + * Implement down(syslog,reason) to notify/log when the syslog protocol is unavailable. + * + * @param syslog - SyslogIF instance causing this down condition + * @param reason - reason given for the down condition + */ + public void down(SyslogIF syslog, String reason); + + /** + * Implement up(syslog) to notify/log when the syslog protocol becomes available after a down condition. + * + * @param syslog - SyslogIF instance which is now available + */ + public void up(SyslogIF syslog); + + /** + * @param syslog - SyslogIF instance which cannot handle this log event + * @param level - message level + * @param message - message (in String form) + * @param reason - reason given for why this message could not be handled + * @throws SyslogRuntimeException - throwing this Exception activates the next backlogHandler in the chain + */ + public void log(SyslogIF syslog, int level, String message, String reason) throws SyslogRuntimeException; +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogCharSetIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogCharSetIF.java new file mode 100644 index 0000000..62a6bb6 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogCharSetIF.java @@ -0,0 +1,19 @@ +package org.productivity.java.syslog4j; + +import java.io.Serializable; + +/** +* SyslogCharSetIF provides control of the encoding character set within +* several class of Syslog4j. +* +*

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: SyslogCharSetIF.java,v 1.3 2008/11/07 15:15:41 cvs Exp $ +*/ +public interface SyslogCharSetIF extends Serializable { + public String getCharSet(); + public void setCharSet(String charSet); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogConfigIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogConfigIF.java new file mode 100644 index 0000000..ac4ed64 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogConfigIF.java @@ -0,0 +1,69 @@ +package org.productivity.java.syslog4j; + +/** +* SyslogConfigIF provides a common, extensible configuration interface for all +* implementations of SyslogIF. +* +*

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: SyslogConfigIF.java,v 1.19 2010/11/28 04:15:18 cvs Exp $ +*/ +public interface SyslogConfigIF extends SyslogConstants, SyslogCharSetIF { + public Class getSyslogClass(); + + public int getFacility(); + public void setFacility(int facility); + public void setFacility(String facilityName); + + public int getPort(); + public void setPort(int port) throws SyslogRuntimeException; + + public String getLocalName(); + public void setLocalName(String localName) throws SyslogRuntimeException; + + public String getHost(); + public void setHost(String host) throws SyslogRuntimeException; + + public String getIdent(); + public void setIdent(String ident); + + public String getCharSet(); + public void setCharSet(String charSet); + + public boolean isIncludeIdentInMessageModifier(); + public void setIncludeIdentInMessageModifier(boolean throwExceptionOnInitialize); + + public boolean isThrowExceptionOnInitialize(); + public void setThrowExceptionOnInitialize(boolean throwExceptionOnInitialize); + + public boolean isThrowExceptionOnWrite(); + public void setThrowExceptionOnWrite(boolean throwExceptionOnWrite); + + public boolean isSendLocalTimestamp(); + public void setSendLocalTimestamp(boolean sendLocalTimestamp); + + public boolean isSendLocalName(); + public void setSendLocalName(boolean sendLocalName); + + public boolean isTruncateMessage(); + public void setTruncateMessage(boolean truncateMessage); + + public boolean isUseStructuredData(); + public void setUseStructuredData(boolean useStructuredData); + + public int getMaxMessageLength(); + public void setMaxMessageLength(int maxMessageLength); + + public void addMessageModifier(SyslogMessageModifierIF messageModifier); + public void insertMessageModifier(int index, SyslogMessageModifierIF messageModifier); + public void removeMessageModifier(SyslogMessageModifierIF messageModifier); + public void removeAllMessageModifiers(); + + public void addBackLogHandler(SyslogBackLogHandlerIF backLogHandler); + public void insertBackLogHandler(int index, SyslogBackLogHandlerIF backLogHandler); + public void removeBackLogHandler(SyslogBackLogHandlerIF backLogHandler); + public void removeAllBackLogHandlers(); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogConstants.java b/src/main/java/org/productivity/java/syslog4j/SyslogConstants.java new file mode 100644 index 0000000..175f4e8 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogConstants.java @@ -0,0 +1,164 @@ +package org.productivity.java.syslog4j; + +import java.io.Serializable; + +/** +* SyslogConstants provides several global constant values for several +* classes within Syslog4j. +* +*

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: SyslogConstants.java,v 1.33 2011/01/11 05:11:13 cvs Exp $ +*/ +public interface SyslogConstants extends Serializable { + public static final String SYSLOG_PATH_DEFAULT = "/dev/log"; + public static final String SYSLOG_HOST_DEFAULT = "localhost"; + public static final int SYSLOG_PORT_DEFAULT = 514; + public static final int SYSLOG_BUFFER_SIZE = 1024; + public static final int SERVER_SOCKET_BACKLOG_DEFAULT = 50; + + public static final String SYSLOG_DATEFORMAT = "MMM dd HH:mm:ss "; + + public static final String STRUCTURED_DATA_NILVALUE = "-"; + public static final String STRUCTURED_DATA_EMPTY_VALUE = "[0@0]"; + + public static final String CHAR_SET_DEFAULT = "UTF-8"; + + public static final byte[] LF = "\n".getBytes(); + public static final byte[] CRLF = "\r\n".getBytes(); + + public static final byte[] TCP_DELIMITER_SEQUENCE_DEFAULT = LF; + + public static final boolean THREADED_DEFAULT = true; + public static final long THREAD_LOOP_INTERVAL_DEFAULT = 500; + + public static final boolean SEND_LOCAL_NAME_DEFAULT = true; + public static final boolean SEND_LOCAL_TIMESTAMP_DEFAULT = true; + public static final boolean CACHE_HOST_ADDRESS_DEFAULT = true; + + public static final int MAX_MESSAGE_LENGTH_DEFAULT = 1024; + + public static final boolean INCLUDE_IDENT_IN_MESSAGE_MODIFIER_DEFAULT = false; + public static final boolean THROW_EXCEPTION_ON_INITIALIZE_DEFAULT = true; + public static final boolean THROW_EXCEPTION_ON_WRITE_DEFAULT = false; + public static final boolean USE_STRUCTURED_DATA_DEFAULT = false; + public static final String STRUCTURED_DATA_APP_NAME_DEFAULT_VALUE = "unknown"; + public static final String STRUCTURED_DATA_PROCESS_ID_DEFAULT_VALUE = STRUCTURED_DATA_NILVALUE; + + public static final boolean USE_DAEMON_THREAD_DEFAULT = true; + public static final int THREAD_PRIORITY_DEFAULT = -1; + + public static final boolean TRUNCATE_MESSAGE_DEFAULT = false; + + public static final String SPLIT_MESSAGE_BEGIN_TEXT_DEFAULT = "..."; + public static final String SPLIT_MESSAGE_END_TEXT_DEFAULT = "..."; + + public static final String SEND_LOCAL_NAME_DEFAULT_VALUE = "unknown"; + + public static final String TCP = "tcp"; + public static final String UDP = "udp"; + public static final String UNIX_SYSLOG = "unix_syslog"; + public static final String UNIX_SOCKET = "unix_socket"; + + public static final boolean TCP_PERSISTENT_CONNECTION_DEFAULT = true; + public static final boolean TCP_SO_LINGER_DEFAULT = true; + public static final int TCP_SO_LINGER_SECONDS_DEFAULT = 1; + public static final boolean TCP_KEEP_ALIVE_DEFAULT = true; + public static final boolean TCP_REUSE_ADDRESS_DEFAULT = true; + public static final boolean TCP_SET_BUFFER_SIZE_DEFAULT = true; + public static final int TCP_FRESH_CONNECTION_INTERVAL_DEFAULT = -1; + + public static final int TCP_MAX_ACTIVE_SOCKETS_DEFAULT = 0; + public static final byte TCP_MAX_ACTIVE_SOCKETS_BEHAVIOR_DEFAULT = 0; + + public static final int FACILITY_KERN = 0; + public static final int FACILITY_USER = 1<<3; + public static final int FACILITY_MAIL = 2<<3; + public static final int FACILITY_DAEMON = 3<<3; + public static final int FACILITY_AUTH = 4<<3; + public static final int FACILITY_SYSLOG = 5<<3; + + public static final int FACILITY_LPR = 6<<3; + public static final int FACILITY_NEWS = 7<<3; + public static final int FACILITY_UUCP = 8<<3; + public static final int FACILITY_CRON = 9<<3; + public static final int FACILITY_AUTHPRIV = 10<<3; + public static final int FACILITY_FTP = 11<<3; + + public static final int FACILITY_LOCAL0 = 16<<3; + public static final int FACILITY_LOCAL1 = 17<<3; + public static final int FACILITY_LOCAL2 = 18<<3; + public static final int FACILITY_LOCAL3 = 19<<3; + public static final int FACILITY_LOCAL4 = 20<<3; + public static final int FACILITY_LOCAL5 = 21<<3; + public static final int FACILITY_LOCAL6 = 22<<3; + public static final int FACILITY_LOCAL7 = 23<<3; + + public static final int SYSLOG_FACILITY_DEFAULT = FACILITY_USER; + + public static final int LEVEL_DEBUG = 7; + public static final int LEVEL_INFO = 6; + public static final int LEVEL_NOTICE = 5; + public static final int LEVEL_WARN = 4; + public static final int LEVEL_ERROR = 3; + public static final int LEVEL_CRITICAL = 2; + public static final int LEVEL_ALERT = 1; + public static final int LEVEL_EMERGENCY = 0; + + public static final int OPTION_NONE = 0; + public static final int OPTION_LOG_CONS = 1; + public static final int OPTION_LOG_NDELAY = 2; + public static final int OPTION_LOG_NOWAIT = 4; + public static final int OPTION_LOG_ODELAY = 8; + public static final int OPTION_LOG_PERROR = 16; + public static final int OPTION_LOG_PID = 32; + + public static final int SOCK_STREAM = 1; + public static final int SOCK_DGRAM = 2; + + public static final short AF_UNIX = 1; + + public static final int WRITE_RETRIES_DEFAULT = 2; + public static final int MAX_SHUTDOWN_WAIT_DEFAULT = 30000; + public static final long SHUTDOWN_INTERVAL = 100; + public static final int MAX_QUEUE_SIZE_DEFAULT = -1; + + public static final long SERVER_SHUTDOWN_WAIT_DEFAULT = 500; + + public static final String SYSLOG_LIBRARY_DEFAULT = "c"; + + public static final int SYSLOG_SOCKET_TYPE_DEFAULT = SOCK_DGRAM; + public static final short SYSLOG_SOCKET_FAMILY_DEFAULT = AF_UNIX; + public static final String SYSLOG_SOCKET_LIBRARY_DEFAULT = "c"; + public static final int SYSLOG_SOCKET_PROTOCOL_DEFAULT = 0; + public static final String SYSLOG_SOCKET_PATH_DEFAULT = "/dev/log"; + + public static final String JNA_NATIVE_CLASS = "com.sun.jna.Native"; + + public static final String IDENT_SUFFIX_DEFAULT = ": "; + + public static final String SYSLOG_MESSAGE_MODIFIER_PREFIX_DEFAULT = " {"; + public static final String SYSLOG_MESSAGE_MODIFIER_SUFFIX_DEFAULT = "}"; + + public static final String SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_PREFIX_DEFAULT = " #"; + public static final String SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_SUFFIX_DEFAULT = ""; + public static final long SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_FIRST_NUMBER_DEFAULT = 0; + public static final long SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_LAST_NUMBER_DEFAULT = 9999; + public static final char SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_PAD_CHAR_DEFAULT = '0'; + public static final boolean SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_USE_PADDING_DEFAULT = true; + + public static final int SYSLOG_POOL_CONFIG_MAX_ACTIVE_DEFAULT = 4; + public static final int SYSLOG_POOL_CONFIG_MAX_IDLE_DEFAULT = 4; + public static final int SYSLOG_POOL_CONFIG_MAX_WAIT_DEFAULT = 1000; + public static final int SYSLOG_POOL_CONFIG_NUM_TESTS_PER_EVICTION_RUN_DEFAULT = 0; + public static final int SYSLOG_POOL_CONFIG_MIN_IDLE_DEFAULT = 4; + public static final int SYSLOG_POOL_CONFIG_MIN_EVICTABLE_IDLE_TIME_MILLIS_DEFAULT = 0; + public static final int SYSLOG_POOL_CONFIG_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS_DEFAULT = 0; + public static final int SYSLOG_POOL_CONFIG_TIME_BETWEEN_EVICTION_RUNS_MILLIS_DEFAULT = 0; + public static final boolean SYSLOG_POOL_CONFIG_TEST_ON_BORROW_DEFAULT = false; + public static final boolean SYSLOG_POOL_CONFIG_TEST_ON_RETURN_DEFAULT = false; + public static final boolean SYSLOG_POOL_CONFIG_TEST_WHILE_IDLE_DEFAULT = false; +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogIF.java new file mode 100644 index 0000000..b69a995 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogIF.java @@ -0,0 +1,52 @@ +package org.productivity.java.syslog4j; + +/** +* SyslogIF provides a common interface for all Syslog4j client 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: SyslogIF.java,v 1.9 2010/02/11 04:59:22 cvs Exp $ +*/ +public interface SyslogIF extends SyslogConstants { + public void initialize(String protocol, SyslogConfigIF config) throws SyslogRuntimeException; + + public String getProtocol(); + public SyslogConfigIF getConfig(); + + public void backLog(int level, String message, Throwable reasonThrowable); + public void backLog(int level, String message, String reason); + + public void log(int level, String message); + + public void debug(String message); + public void info(String message); + public void notice(String message); + public void warn(String message); + public void error(String message); + public void critical(String message); + public void alert(String message); + public void emergency(String message); + + public void log(int level, SyslogMessageIF message); + + public void debug(SyslogMessageIF message); + public void info(SyslogMessageIF message); + public void notice(SyslogMessageIF message); + public void warn(SyslogMessageIF message); + public void error(SyslogMessageIF message); + public void critical(SyslogMessageIF message); + public void alert(SyslogMessageIF message); + public void emergency(SyslogMessageIF message); + + public void flush() throws SyslogRuntimeException; + public void shutdown() throws SyslogRuntimeException; + + public void setMessageProcessor(SyslogMessageProcessorIF messageProcessor); + public SyslogMessageProcessorIF getMessageProcessor(); + + public void setStructuredMessageProcessor(SyslogMessageProcessorIF messageProcessor); + public SyslogMessageProcessorIF getStructuredMessageProcessor(); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogMain.java b/src/main/java/org/productivity/java/syslog4j/SyslogMain.java new file mode 100644 index 0000000..69a6e51 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogMain.java @@ -0,0 +1,198 @@ +package org.productivity.java.syslog4j; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; + +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: SyslogMain.java,v 1.4 2010/11/28 01:38:08 cvs Exp $ + */ +public class SyslogMain { + public static boolean CALL_SYSTEM_EXIT_ON_FAILURE = true; + + public static class Options { + public String host = null; + public String port = null; + public String level = "INFO"; + public String facility = "USER"; + public String protocol = null; + public String message = null; + public String fileName = null; + + public boolean quiet = false; + + 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("Syslog [-h ] [-p ] [-l ] [-f ]"); + System.out.println(" "); + System.out.println(); + System.out.println("Syslog [-h ] [-p ] [-l ] [-f ]"); + System.out.println(" [message...]"); + System.out.println(); + System.out.println("Syslog [-h ] [-p ] [-l ] [-f ]"); + System.out.println(" -i "); + System.out.println(); + System.out.println("-h host or IP to send message (default: localhost)"); + System.out.println("-p port to send message (default: 514)"); + System.out.println("-l syslog level to use (default: INFO)"); + System.out.println("-f syslog facility to use (default: USER)"); + System.out.println("-i input taken from the specified file"); + System.out.println(); + System.out.println("-q do not write anything to standard out"); + System.out.println(); + System.out.println("protocol Syslog4j protocol implementation"); + System.out.println("message syslog message text"); + System.out.println(); + System.out.println("Notes:"); + System.out.println(); + System.out.println("Additional message arguments will be concatenated into the same"); + System.out.println("syslog message; calling SyslogMain will only send one message per call."); + System.out.println(); + System.out.println("If the message argument is ommited, lines will be taken from the"); + System.out.println("standard input."); + } + + public static Options parseOptions(String[] args) { + Options options = new Options(); + + int i = 0; + while(i < args.length) { + String arg = args[i++]; + boolean match = false; + + if ("-h".equals(arg)) { if (i == args.length) { options.usage = "Must specify host with -h"; return options; } match = true; options.host = args[i++]; } + if ("-p".equals(arg)) { if (i == args.length) { options.usage = "Must specify port with -p"; return options; } match = true; options.port = args[i++]; } + if ("-l".equals(arg)) { if (i == args.length) { options.usage = "Must specify level with -l"; return options; } match = true; options.level = args[i++]; } + if ("-f".equals(arg)) { if (i == args.length) { options.usage = "Must specify facility with -f"; return options; } match = true; options.facility = args[i++]; } + if ("-i".equals(arg)) { if (i == args.length) { options.usage = "Must specify file with -i"; return options; } match = true; options.fileName = args[i++]; } + + if ("-q".equals(arg)) { match = true; options.quiet = true; } + + if (options.protocol == null && !match) { + match = true; + options.protocol = arg; + } + + if (!match) { + if (options.message == null) { + options.message = arg; + + } else { + options.message += " " + arg; + } + } + } + + if (options.protocol == null) { + options.usage = "Must specify protocol"; + return options; + } + + if (options.message != null && options.fileName != null) { + options.usage = "Must specify either -i or , not both"; + return options; + } + + return options; + } + + public static void main(String[] args) throws Exception { + main(args,true); + } + + public static void main(String[] args, boolean shutdown) throws Exception { + Options options = parseOptions(args); + + if (options.usage != null) { + usage(options.usage); + if (CALL_SYSTEM_EXIT_ON_FAILURE) { System.exit(1); } else { return; } + } + + if (!options.quiet) { + System.out.println("Syslog " + Syslog.getVersion()); + } + + if (!Syslog.exists(options.protocol)) { + usage("Protocol \"" + options.protocol + "\" not supported"); + if (CALL_SYSTEM_EXIT_ON_FAILURE) { System.exit(1); } else { return; } + } + + SyslogIF syslog = Syslog.getInstance(options.protocol); + + SyslogConfigIF syslogConfig = syslog.getConfig(); + + if (options.host != null) { + syslogConfig.setHost(options.host); + if (!options.quiet) { + System.out.println("Sending to host: " + options.host); + } + } + + if (options.port != null) { + syslogConfig.setPort(Integer.parseInt(options.port)); + if (!options.quiet) { + System.out.println("Sending to port: " + options.port); + } + } + + int level = SyslogUtility.getLevel(options.level); + + syslogConfig.setFacility(options.facility); + + if (options.message != null) { + if (!options.quiet) { + System.out.println("Sending " + options.facility + "." + options.level + " message \"" + options.message + "\""); + } + + syslog.log(level,options.message); + + } else { + InputStream is = null; + + if (options.fileName != null) { + is = new FileInputStream(options.fileName); + + } else { + is = System.in; + } + + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + + String line = br.readLine(); + + while(line != null && line.length() > 0) { + if (!options.quiet) { + System.out.println("Sending " + options.facility + "." + options.level + " message \"" + line + "\""); + } + + syslog.log(level,line); + + line = br.readLine(); + } + } + + if (shutdown) { + Syslog.shutdown(); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogMessageIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogMessageIF.java new file mode 100644 index 0000000..0007a94 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogMessageIF.java @@ -0,0 +1,17 @@ +package org.productivity.java.syslog4j; + +import java.io.Serializable; + +/** +* SyslogMessageIF provides a common interface for all Syslog4j event 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: SyslogMessageIF.java,v 1.1 2008/11/10 04:38:37 cvs Exp $ +*/ +public interface SyslogMessageIF extends Serializable { + public String createMessage(); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogMessageModifierConfigIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogMessageModifierConfigIF.java new file mode 100644 index 0000000..08e51ab --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogMessageModifierConfigIF.java @@ -0,0 +1,20 @@ +package org.productivity.java.syslog4j; + +/** +* SyslogMessageModifierConfigIF provides a common configuration interface for all +* Syslog4j message modifier 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: SyslogMessageModifierConfigIF.java,v 1.3 2010/10/28 05:10:57 cvs Exp $ +*/ +public interface SyslogMessageModifierConfigIF extends SyslogConstants, SyslogCharSetIF { + public String getPrefix(); + public void setPrefix(String prefix); + + public String getSuffix(); + public void setSuffix(String suffix); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogMessageModifierIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogMessageModifierIF.java new file mode 100644 index 0000000..4d68756 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogMessageModifierIF.java @@ -0,0 +1,17 @@ +package org.productivity.java.syslog4j; + +/** +* SyslogMessageModifierIF provides a common interface for all +* Syslog4j message modifier 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: SyslogMessageModifierIF.java,v 1.4 2010/10/28 05:10:57 cvs Exp $ +*/ +public interface SyslogMessageModifierIF extends SyslogConstants { + public String modify(SyslogIF syslog, int facility, int level, String message); + public boolean verify(String message); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogMessageProcessorIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogMessageProcessorIF.java new file mode 100644 index 0000000..c886dd8 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogMessageProcessorIF.java @@ -0,0 +1,22 @@ +package org.productivity.java.syslog4j; + +import java.io.Serializable; + +/** +* SyslogMessageProcessorIF provides an extensible interface for writing custom +* Syslog4j message processors. +* +*

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: SyslogMessageProcessorIF.java,v 1.4 2010/11/28 04:15:18 cvs Exp $ +*/ +public interface SyslogMessageProcessorIF extends Serializable { + public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalTimestamp, boolean sendLocalName); + + public byte[] createPacketData(byte[] header, byte[] message, int start, int length); + + public byte[] createPacketData(byte[] header, byte[] message, int start, int length, byte[] splitBeginText, byte[] splitEndText); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogPoolConfigIF.java b/src/main/java/org/productivity/java/syslog4j/SyslogPoolConfigIF.java new file mode 100644 index 0000000..18c4404 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogPoolConfigIF.java @@ -0,0 +1,52 @@ +package org.productivity.java.syslog4j; + +import java.io.Serializable; + +/** +* SyslogPoolConfigIF is an interface 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: SyslogPoolConfigIF.java,v 1.2 2009/03/29 17:38:58 cvs Exp $ +*/ +public interface SyslogPoolConfigIF extends Serializable { + public int getMaxActive(); + public void setMaxActive(int maxActive); + + public int getMaxIdle(); + public void setMaxIdle(int maxIdle); + + public long getMaxWait(); + public void setMaxWait(long maxWait); + + public long getMinEvictableIdleTimeMillis(); + public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis); + + public int getMinIdle(); + public void setMinIdle(int minIdle); + + public int getNumTestsPerEvictionRun(); + public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun); + + public long getSoftMinEvictableIdleTimeMillis(); + public void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis); + + public boolean isTestOnBorrow(); + public void setTestOnBorrow(boolean testOnBorrow); + + public boolean isTestOnReturn(); + public void setTestOnReturn(boolean testOnReturn); + + public boolean isTestWhileIdle(); + public void setTestWhileIdle(boolean testWhileIdle); + + public long getTimeBetweenEvictionRunsMillis(); + public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis); + + public byte getWhenExhaustedAction(); + public void setWhenExhaustedAction(byte whenExhaustedAction); +} diff --git a/src/main/java/org/productivity/java/syslog4j/SyslogRuntimeException.java b/src/main/java/org/productivity/java/syslog4j/SyslogRuntimeException.java new file mode 100644 index 0000000..2c4f311 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/SyslogRuntimeException.java @@ -0,0 +1,24 @@ +package org.productivity.java.syslog4j; + +/** +* SyslogRuntimeException provides an extension of RuntimeException thrown +* by the majority of the classes within Syslog4j. +* +*

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: SyslogRuntimeException.java,v 1.3 2008/11/13 14:48:36 cvs Exp $ +*/ +public class SyslogRuntimeException extends RuntimeException { + private static final long serialVersionUID = 7278123987654320379L; + + public SyslogRuntimeException(String arg0) { + super(arg0); + } + + public SyslogRuntimeException(Throwable arg0) { + super(arg0); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslog.java new file mode 100644 index 0000000..86ed89c --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslog.java @@ -0,0 +1,394 @@ +package org.productivity.java.syslog4j.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.productivity.java.syslog4j.SyslogBackLogHandlerIF; +import org.productivity.java.syslog4j.SyslogConfigIF; +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; +import org.productivity.java.syslog4j.SyslogMessageProcessorIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.message.processor.SyslogMessageProcessor; +import org.productivity.java.syslog4j.impl.message.processor.structured.StructuredSyslogMessageProcessor; +import org.productivity.java.syslog4j.impl.message.structured.StructuredSyslogMessage; +import org.productivity.java.syslog4j.impl.message.structured.StructuredSyslogMessageIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* AbstractSyslog provides a base abstract implementation of the SyslogIF. +* +*

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: AbstractSyslog.java,v 1.29 2011/01/11 04:58:52 cvs Exp $ +*/ +public abstract class AbstractSyslog implements SyslogIF { + private static final long serialVersionUID = 2632017043774808264L; + + protected String syslogProtocol = null; + + protected AbstractSyslogConfigIF syslogConfig = null; + + protected SyslogMessageProcessorIF syslogMessageProcessor = null; + protected SyslogMessageProcessorIF structuredSyslogMessageProcessor = null; + + protected Object backLogStatusSyncObject = new Object(); + + protected boolean backLogStatus = false; + protected List notifiedBackLogHandlers = new ArrayList(); + + protected boolean getBackLogStatus() { + synchronized(this.backLogStatusSyncObject) { + return this.backLogStatus; + } + } + + /** + * @param backLogStatus - true if in a "down" backLog state, false if in an "up" (operational) non-backLog state + */ + public void setBackLogStatus(boolean backLogStatus) { + if (this.backLogStatus != backLogStatus) { + synchronized(this.backLogStatusSyncObject) { + if (!backLogStatus) { + for(int i=0; i 0 && mLength > availableLen) { + mLength = availableLen; + } + } + + if (mLength <= availableLen) { + byte[] data = messageProcessor.createPacketData(h,m,0,mLength); + + write(level,data); + + } else { + byte[] splitBeginText = this.syslogConfig.getSplitMessageBeginText(); + byte[] splitEndText = this.syslogConfig.getSplitMessageEndText(); + + int pos = 0; + int left = mLength; + + while(left > 0) { + boolean firstTime = (pos == 0); + + boolean doSplitBeginText = splitBeginText != null && !firstTime; + boolean doSplitEndText = splitBeginText != null && (firstTime || (left > (availableLen - splitBeginText.length))); + + int actualAvailableLen = availableLen; + + actualAvailableLen -= (splitBeginText != null && doSplitBeginText) ? splitBeginText.length : 0; + actualAvailableLen -= (splitEndText != null && doSplitEndText) ? splitEndText.length : 0; + + if (actualAvailableLen > left) { + actualAvailableLen = left; + } + + if (actualAvailableLen < 0) { + throw new SyslogRuntimeException("Message length < 0; recommendation: increase the size of maxMessageLength"); + } + + byte[] data = messageProcessor.createPacketData(h,m,pos,actualAvailableLen,doSplitBeginText ? splitBeginText : null,doSplitEndText ? splitEndText : null); + + write(level,data); + + pos += actualAvailableLen; + left -= actualAvailableLen; + } + } + } + + protected abstract void initialize() throws SyslogRuntimeException; + + protected abstract void write(int level, byte[] message) throws SyslogRuntimeException; + + protected String modifyMessage(int level, String message) { + List _messageModifiers = this.syslogConfig.getMessageModifiers(); + + if (_messageModifiers == null || _messageModifiers.size() < 1) { + return message; + } + + String _message = message; + + int facility = this.syslogConfig.getFacility(); + + for(int i=0; i<_messageModifiers.size(); i++) { + SyslogMessageModifierIF messageModifier = (SyslogMessageModifierIF) _messageModifiers.get(i); + + _message = messageModifier.modify(this, facility, level, _message); + } + + return _message; + } + + public void backLog(int level, String message, Throwable reasonThrowable) { + backLog(level,message,reasonThrowable != null ? reasonThrowable.toString() : "UNKNOWN"); + } + + public void backLog(int level, String message, String reason) { + boolean status = getBackLogStatus(); + + if (!status) { + setBackLogStatus(true); + } + + List backLogHandlers = this.syslogConfig.getBackLogHandlers(); + + for(int i=0; i -1) { + newWriterThread.setPriority(syslogConfig.getThreadPriority()); + } + syslogWriter.setThread(newWriterThread); + newWriterThread.start(); + + return newWriterThread; + } + + + public AbstractSyslogWriter createWriter(){ + Class clazz = this.syslogConfig.getSyslogWriterClass(); + + AbstractSyslogWriter newWriter = null; + + try { + newWriter = (AbstractSyslogWriter) clazz.newInstance(); + newWriter.initialize(this); + + } catch (InstantiationException ie) { + if (this.syslogConfig.isThrowExceptionOnInitialize()) { + throw new SyslogRuntimeException(ie); + } + + } catch (IllegalAccessException iae) { + if (this.syslogConfig.isThrowExceptionOnInitialize()) { + throw new SyslogRuntimeException(iae); + } + } + + return newWriter; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogConfig.java new file mode 100644 index 0000000..ff602f7 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogConfig.java @@ -0,0 +1,378 @@ +package org.productivity.java.syslog4j.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.productivity.java.syslog4j.SyslogBackLogHandlerIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.backlog.printstream.SystemErrSyslogBackLogHandler; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* AbstractSyslog provides a base abstract implementation of the SyslogConfigIF +* 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: AbstractSyslogConfig.java,v 1.24 2010/11/28 04:43:31 cvs Exp $ +*/ +public abstract class AbstractSyslogConfig implements AbstractSyslogConfigIF { + private static final long serialVersionUID = -3728308557871358111L; + + protected final static List defaultBackLogHandlers = new ArrayList(); + + static { + defaultBackLogHandlers.add(new SystemErrSyslogBackLogHandler()); + } + + protected int facility = SYSLOG_FACILITY_DEFAULT; + + protected String charSet = CHAR_SET_DEFAULT; + + protected String ident = ""; + + protected String localName = null; + + protected boolean sendLocalTimestamp = SEND_LOCAL_TIMESTAMP_DEFAULT; + protected boolean sendLocalName = SEND_LOCAL_NAME_DEFAULT; + + protected boolean includeIdentInMessageModifier = INCLUDE_IDENT_IN_MESSAGE_MODIFIER_DEFAULT; + protected boolean throwExceptionOnWrite = THROW_EXCEPTION_ON_WRITE_DEFAULT; + protected boolean throwExceptionOnInitialize = THROW_EXCEPTION_ON_INITIALIZE_DEFAULT; + + protected int maxMessageLength = MAX_MESSAGE_LENGTH_DEFAULT; + protected byte[] splitMessageBeginText = SPLIT_MESSAGE_BEGIN_TEXT_DEFAULT.getBytes(); + protected byte[] splitMessageEndText = SPLIT_MESSAGE_END_TEXT_DEFAULT.getBytes(); + + protected List messageModifiers = null; + protected List backLogHandlers = null; + + protected boolean threaded = THREADED_DEFAULT; + protected boolean useDaemonThread = USE_DAEMON_THREAD_DEFAULT; + protected int threadPriority = THREAD_PRIORITY_DEFAULT; + protected long threadLoopInterval = THREAD_LOOP_INTERVAL_DEFAULT; + + protected int writeRetries = WRITE_RETRIES_DEFAULT; + protected long maxShutdownWait = MAX_SHUTDOWN_WAIT_DEFAULT; + + protected boolean truncateMessage = TRUNCATE_MESSAGE_DEFAULT; + protected boolean useStructuredData = USE_STRUCTURED_DATA_DEFAULT; + + public abstract Class getSyslogClass(); + + public String getCharSet() { + return this.charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } + + public String getLocalName() { + return localName; + } + + public void setLocalName(String localName) { + this.localName = localName; + } + + public boolean isThrowExceptionOnWrite() { + return this.throwExceptionOnWrite; + } + + public void setThrowExceptionOnWrite(boolean throwExceptionOnWrite) { + this.throwExceptionOnWrite = throwExceptionOnWrite; + } + + public boolean isThrowExceptionOnInitialize() { + return this.throwExceptionOnInitialize; + } + + public void setThrowExceptionOnInitialize(boolean throwExceptionOnInitialize) { + this.throwExceptionOnInitialize = throwExceptionOnInitialize; + } + + public byte[] getSplitMessageBeginText() { + return this.splitMessageBeginText; + } + + public void setSplitMessageBeginText(byte[] splitMessageBeginText) { + this.splitMessageBeginText = splitMessageBeginText; + } + + public void setSplitMessageBeginText(String splitMessageBeginText) throws SyslogRuntimeException { + this.splitMessageBeginText = SyslogUtility.getBytes(this,splitMessageBeginText); + } + + public byte[] getSplitMessageEndText() { + return this.splitMessageEndText; + } + + public void setSplitMessageEndText(byte[] splitMessageEndText) { + this.splitMessageEndText = splitMessageEndText; + } + + public void setSplitMessageEndText(String splitMessageEndText) throws SyslogRuntimeException { + this.splitMessageEndText = SyslogUtility.getBytes(this,splitMessageEndText); + } + + public int getMaxMessageLength() { + return this.maxMessageLength; + } + + public void setMaxMessageLength(int maxMessageLength) { + this.maxMessageLength = maxMessageLength; + } + + public boolean isSendLocalTimestamp() { + return this.sendLocalTimestamp; + } + + public void setSendLocalTimestamp(boolean sendLocalTimestamp) { + this.sendLocalTimestamp = sendLocalTimestamp; + } + + public boolean isSendLocalName() { + return this.sendLocalName; + } + + public void setSendLocalName(boolean sendLocalName) { + this.sendLocalName = sendLocalName; + } + + public int getFacility() { + return this.facility; + } + + public void setFacility(int facility) { + this.facility = facility; + } + + public void setFacility(String facilityName) { + this.facility = SyslogUtility.getFacility(facilityName); + } + + public String getIdent() { + return this.ident; + } + + public void setIdent(String ident) { + this.ident = ident; + } + + protected synchronized List _getMessageModifiers() { + if (this.messageModifiers == null) { + this.messageModifiers = new ArrayList(); + } + + return this.messageModifiers; + } + + public void addMessageModifier(SyslogMessageModifierIF messageModifier) { + if (messageModifier == null) { + return; + } + + List _messageModifiers = _getMessageModifiers(); + + synchronized(_messageModifiers) { + _messageModifiers.add(messageModifier); + } + } + + public void insertMessageModifier(int index, SyslogMessageModifierIF messageModifier) { + if (messageModifier == null) { + return; + } + + List _messageModifiers = _getMessageModifiers(); + + synchronized(_messageModifiers) { + try { + _messageModifiers.add(index,messageModifier); + + } catch (IndexOutOfBoundsException ioobe) { + throw new SyslogRuntimeException(ioobe); + } + } + } + + public void removeMessageModifier(SyslogMessageModifierIF messageModifier) { + if (messageModifier == null) { + return; + } + + List _messageModifiers = _getMessageModifiers(); + + synchronized(_messageModifiers) { + _messageModifiers.remove(messageModifier); + } + } + + public List getMessageModifiers() { + return this.messageModifiers; + } + + public void setMessageModifiers(List messageModifiers) { + this.messageModifiers = messageModifiers; + } + + public void removeAllMessageModifiers() { + if (this.messageModifiers == null || this.messageModifiers.isEmpty()) { + return; + } + + this.messageModifiers.clear(); + } + + protected synchronized List _getBackLogHandlers() { + if (this.backLogHandlers == null) { + this.backLogHandlers = new ArrayList(); + } + + return this.backLogHandlers; + } + + public void addBackLogHandler(SyslogBackLogHandlerIF backLogHandler) { + if (backLogHandler == null) { + return; + } + + List _backLogHandlers = _getBackLogHandlers(); + + synchronized(_backLogHandlers) { + backLogHandler.initialize(); + _backLogHandlers.add(backLogHandler); + } + } + + public void insertBackLogHandler(int index, SyslogBackLogHandlerIF backLogHandler) { + if (backLogHandler == null) { + return; + } + + List _backLogHandlers = _getBackLogHandlers(); + + synchronized(_backLogHandlers) { + try { + backLogHandler.initialize(); + _backLogHandlers.add(index,backLogHandler); + + } catch (IndexOutOfBoundsException ioobe) { + throw new SyslogRuntimeException(ioobe); + } + } + } + + public void removeBackLogHandler(SyslogBackLogHandlerIF backLogHandler) { + if (backLogHandler == null) { + return; + } + + List _backLogHandlers = _getBackLogHandlers(); + + synchronized(_backLogHandlers) { + _backLogHandlers.remove(backLogHandler); + } + } + + public List getBackLogHandlers() { + if (this.backLogHandlers == null || this.backLogHandlers.size() < 1) { + return defaultBackLogHandlers; + } + + return this.backLogHandlers; + } + + public void setBackLogHandlers(List backLogHandlers) { + this.backLogHandlers = backLogHandlers; + } + + public void removeAllBackLogHandlers() { + if (this.backLogHandlers == null || this.backLogHandlers.isEmpty()) { + return; + } + + this.backLogHandlers.clear(); + } + + public boolean isIncludeIdentInMessageModifier() { + return this.includeIdentInMessageModifier; + } + + public void setIncludeIdentInMessageModifier(boolean includeIdentInMessageModifier) { + this.includeIdentInMessageModifier = includeIdentInMessageModifier; + } + + public boolean isThreaded() { + return this.threaded; + } + + public void setThreaded(boolean threaded) { + this.threaded = threaded; + } + + public boolean isUseDaemonThread() { + return useDaemonThread; + } + + public void setUseDaemonThread(boolean useDaemonThread) { + this.useDaemonThread = useDaemonThread; + } + + public int getThreadPriority() { + return threadPriority; + } + + public void setThreadPriority(int threadPriority) { + this.threadPriority = threadPriority; + } + + public long getThreadLoopInterval() { + return this.threadLoopInterval; + } + + public void setThreadLoopInterval(long threadLoopInterval) { + this.threadLoopInterval = threadLoopInterval; + } + + public long getMaxShutdownWait() { + return this.maxShutdownWait; + } + + public void setMaxShutdownWait(long maxShutdownWait) { + this.maxShutdownWait = maxShutdownWait; + } + + public int getWriteRetries() { + return this.writeRetries; + } + + public void setWriteRetries(int writeRetries) { + this.writeRetries = writeRetries; + } + + public boolean isTruncateMessage() { + return this.truncateMessage; + } + + public void setTruncateMessage(boolean truncateMessage) { + this.truncateMessage = truncateMessage; + } + + public boolean isUseStructuredData() { + return this.useStructuredData; + } + + public void setUseStructuredData(boolean useStructuredData) { + this.useStructuredData = useStructuredData; + } + + public Class getSyslogWriterClass() { + return null; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogConfigIF.java b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogConfigIF.java new file mode 100644 index 0000000..cc3ed03 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogConfigIF.java @@ -0,0 +1,56 @@ +package org.productivity.java.syslog4j.impl; + +import java.util.List; + +import org.productivity.java.syslog4j.SyslogConfigIF; + +/** +* AbstractSyslogConfigIF provides an interface for all Abstract Syslog +* configuration 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: AbstractSyslogConfigIF.java,v 1.7 2010/10/29 03:14:20 cvs Exp $ +*/ +public interface AbstractSyslogConfigIF extends SyslogConfigIF { + public Class getSyslogWriterClass(); + + public List getBackLogHandlers(); + + public List getMessageModifiers(); + + public byte[] getSplitMessageBeginText(); + public void setSplitMessageBeginText(byte[] beginText); + + public byte[] getSplitMessageEndText(); + public void setSplitMessageEndText(byte[] endText); + + public boolean isThreaded(); + public void setThreaded(boolean threaded); + + public boolean isUseDaemonThread(); + public void setUseDaemonThread(boolean useDaemonThread); + + public int getThreadPriority(); + public void setThreadPriority(int threadPriority); + + public long getThreadLoopInterval(); + public void setThreadLoopInterval(long threadLoopInterval); + + public long getMaxShutdownWait(); + public void setMaxShutdownWait(long maxShutdownWait); + + public int getWriteRetries(); + public void setWriteRetries(int writeRetries); + + public int getMaxQueueSize(); + /** + * Use the (default) value of -1 to allow for a queue of indefinite depth (size). + * + * @param maxQueueSize + */ + public void setMaxQueueSize(int maxQueueSize); +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogWriter.java b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogWriter.java new file mode 100644 index 0000000..5386105 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/AbstractSyslogWriter.java @@ -0,0 +1,109 @@ +package org.productivity.java.syslog4j.impl; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* AbstractSyslogWriter is an implementation of Runnable that supports sending +* syslog messages within a separate Thread or an object pool. +* +*

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: AbstractSyslogWriter.java,v 1.9 2010/10/25 03:50:25 cvs Exp $ +*/ +public abstract class AbstractSyslogWriter implements Runnable, Serializable { + private static final long serialVersionUID = 836468466009035847L; + + protected AbstractSyslog syslog = null; + + protected List queuedMessages = null; + + protected Thread thread = null; + + protected AbstractSyslogConfigIF syslogConfig = null; + + protected boolean shutdown = false; + + public void initialize(AbstractSyslog abstractSyslog) { + this.syslog = abstractSyslog; + + try { + this.syslogConfig = (AbstractSyslogConfigIF) this.syslog.getConfig(); + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must implement interface AbstractSyslogConfigIF"); + } + + if (this.syslogConfig.isThreaded()) { + this.queuedMessages = new LinkedList(); + } + } + + public void queue(int level, byte[] message) { + synchronized(this.queuedMessages) { + if (this.syslogConfig.getMaxQueueSize() == -1 || this.queuedMessages.size() < this.syslogConfig.getMaxQueueSize()) { + this.queuedMessages.add(message); + + } else { + this.syslog.backLog(level,SyslogUtility.newString(syslogConfig,message),"MaxQueueSize (" + this.syslogConfig.getMaxQueueSize() + ") reached"); + } + } + } + + public void setThread(Thread thread) { + this.thread = thread; + } + + public boolean hasThread() { + return this.thread != null && this.thread.isAlive(); + } + + public abstract void write(byte[] message); + + public abstract void flush(); + + public abstract void shutdown(); + + protected abstract void runCompleted(); + + public void run() { + while(!this.shutdown || !this.queuedMessages.isEmpty()) { + List queuedMessagesCopy = null; + + synchronized(this.queuedMessages) { + queuedMessagesCopy = new LinkedList(this.queuedMessages); + this.queuedMessages.clear(); + } + + if (queuedMessagesCopy != null) { + while(!queuedMessagesCopy.isEmpty()) { + byte[] message = (byte[]) queuedMessagesCopy.remove(0); + + try { + write(message); + + this.syslog.setBackLogStatus(false); + + } catch (SyslogRuntimeException sre) { + this.syslog.backLog(SyslogConstants.LEVEL_INFO,SyslogUtility.newString(this.syslog.getConfig(),message),sre); + } + } + } + + SyslogUtility.sleep(this.syslogConfig.getThreadLoopInterval()); + } + + runCompleted(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/AbstractSyslogBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/AbstractSyslogBackLogHandler.java new file mode 100644 index 0000000..09dd6a6 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/AbstractSyslogBackLogHandler.java @@ -0,0 +1,36 @@ +package org.productivity.java.syslog4j.impl.backlog; + +import org.productivity.java.syslog4j.SyslogBackLogHandlerIF; +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* AbstractSyslogBackLogHandler is an implementation of SyslogBackLogHandlerIF +* that mainly provides the helpful "combine" method for handling the "reason" +* why a BackLog has occurred. +* +*

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: AbstractSyslogBackLogHandler.java,v 1.1 2009/01/24 22:00:18 cvs Exp $ +*/ +public abstract class AbstractSyslogBackLogHandler implements SyslogBackLogHandlerIF { + protected boolean appendReason = true; + + protected String combine(SyslogIF syslog, int level, String message, String reason) { + // Note: syslog is explicitly ignored by default + + String _message = message != null ? message : "UNKNOWN"; + String _reason = reason != null ? reason : "UNKNOWN"; + + String combinedMessage = SyslogUtility.getLevelString(level) + " " + _message; + + if (this.appendReason) { + combinedMessage += " [" + _reason + "]"; + } + + return combinedMessage; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/NullSyslogBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/NullSyslogBackLogHandler.java new file mode 100644 index 0000000..74ddab2 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/NullSyslogBackLogHandler.java @@ -0,0 +1,35 @@ +package org.productivity.java.syslog4j.impl.backlog; + +import org.productivity.java.syslog4j.SyslogBackLogHandlerIF; +import org.productivity.java.syslog4j.SyslogIF; + +/** +* NullSyslogBackLogHandler can be used if there's no need for a last-chance +* logging mechanism whenever the Syslog protocol fails. +* +*

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: NullSyslogBackLogHandler.java,v 1.2 2010/10/25 03:50:25 cvs Exp $ +*/ +public class NullSyslogBackLogHandler implements SyslogBackLogHandlerIF { + public static final NullSyslogBackLogHandler INSTANCE = new NullSyslogBackLogHandler(); + + public void initialize() { + // + } + + public void down(SyslogIF syslog, String reason) { + // + } + + public void up(SyslogIF syslog) { + // + } + + public void log(SyslogIF syslog, int level, String message, String reason) { + // + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/Syslog4jBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/Syslog4jBackLogHandler.java new file mode 100644 index 0000000..bf819ec --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/Syslog4jBackLogHandler.java @@ -0,0 +1,67 @@ +package org.productivity.java.syslog4j.impl.backlog; + +import org.productivity.java.syslog4j.Syslog; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; + +/** +* Syslog4jBackLogHandler is used to send Syslog backLog messages to +* another Syslog4j protocol whenever the main Syslog protocol fails. +* +*

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: Syslog4jBackLogHandler.java,v 1.1 2009/07/25 18:42:47 cvs Exp $ +*/ +public class Syslog4jBackLogHandler extends AbstractSyslogBackLogHandler { + protected SyslogIF syslog = null; + protected int downLevel = SyslogConstants.LEVEL_WARN; + protected int upLevel = SyslogConstants.LEVEL_WARN; + + public Syslog4jBackLogHandler(String protocol) { + this.syslog = Syslog.getInstance(protocol); + } + + public Syslog4jBackLogHandler(String protocol, boolean appendReason) { + this.syslog = Syslog.getInstance(protocol); + this.appendReason = appendReason; + } + + public Syslog4jBackLogHandler(SyslogIF syslog) { + this.syslog = syslog; + } + + public Syslog4jBackLogHandler(SyslogIF syslog, boolean appendReason) { + this.syslog = syslog; + this.appendReason = appendReason; + } + + public void initialize() throws SyslogRuntimeException { + // NO-OP + } + + public void log(SyslogIF syslog, int level, String message, String reason) throws SyslogRuntimeException { + if (this.syslog.getProtocol().equals(syslog.getProtocol())) { + throw new SyslogRuntimeException("Ignoring this log entry since the backLog protocol \"" + this.syslog.getProtocol() + "\" is the same as the main protocol"); + } + + String combinedMessage = combine(syslog,level,message,reason); + + this.syslog.log(level,combinedMessage); + } + + public void down(SyslogIF syslog, String reason) { + if (!this.syslog.getProtocol().equals(syslog.getProtocol())) { + this.syslog.log(this.downLevel,"Syslog protocol \"" + syslog.getProtocol() + "\" is down: " + reason); + } + } + + public void up(SyslogIF syslog) { + if (!this.syslog.getProtocol().equals(syslog.getProtocol())) { + this.syslog.log(this.downLevel,"Syslog protocol \"" + syslog.getProtocol() + "\" is up"); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/log4j/Log4jSyslogBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/log4j/Log4jSyslogBackLogHandler.java new file mode 100644 index 0000000..b05cecc --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/log4j/Log4jSyslogBackLogHandler.java @@ -0,0 +1,148 @@ +package org.productivity.java.syslog4j.impl.backlog.log4j; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.spi.LoggerFactory; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.backlog.AbstractSyslogBackLogHandler; + +/** +* Log4jSyslogBackLogHandler is used to send Syslog backLog messages to +* Log4j whenever the Syslog protocol fails. +* +*

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: Log4jSyslogBackLogHandler.java,v 1.2 2009/07/22 15:54:23 cvs Exp $ +*/ +public class Log4jSyslogBackLogHandler extends AbstractSyslogBackLogHandler { + protected Logger logger = null; + protected Level downLevel = Level.WARN; + protected Level upLevel = Level.WARN; + + public Log4jSyslogBackLogHandler(Logger logger) throws SyslogRuntimeException { + this.logger = logger; + + initialize(); + } + + public Log4jSyslogBackLogHandler(Logger logger, boolean appendReason) { + this.logger = logger; + this.appendReason = appendReason; + + initialize(); + } + + public Log4jSyslogBackLogHandler(Class loggerClass) { + if (loggerClass == null) { + throw new SyslogRuntimeException("loggerClass cannot be null"); + } + + this.logger = Logger.getLogger(loggerClass); + + initialize(); + } + + public Log4jSyslogBackLogHandler(Class loggerClass, boolean appendReason) { + if (loggerClass == null) { + throw new SyslogRuntimeException("loggerClass cannot be null"); + } + + this.logger = Logger.getLogger(loggerClass); + this.appendReason = appendReason; + + initialize(); + } + + public Log4jSyslogBackLogHandler(String loggerName) { + if (loggerName == null) { + throw new SyslogRuntimeException("loggerName cannot be null"); + } + + this.logger = Logger.getLogger(loggerName); + + initialize(); + } + + public Log4jSyslogBackLogHandler(String loggerName, boolean appendReason) { + if (loggerName == null) { + throw new SyslogRuntimeException("loggerName cannot be null"); + } + + this.logger = Logger.getLogger(loggerName); + this.appendReason = appendReason; + + initialize(); + } + + public Log4jSyslogBackLogHandler(String loggerName, LoggerFactory loggerFactory) { + if (loggerName == null) { + throw new SyslogRuntimeException("loggerName cannot be null"); + } + + if (loggerFactory == null) { + throw new SyslogRuntimeException("loggerFactory cannot be null"); + } + + this.logger = Logger.getLogger(loggerName,loggerFactory); + + initialize(); + } + + public Log4jSyslogBackLogHandler(String loggerName, LoggerFactory loggerFactory, boolean appendReason) { + if (loggerName == null) { + throw new SyslogRuntimeException("loggerName cannot be null"); + } + + if (loggerFactory == null) { + throw new SyslogRuntimeException("loggerFactory cannot be null"); + } + + this.logger = Logger.getLogger(loggerName,loggerFactory); + this.appendReason = appendReason; + + initialize(); + } + + public void initialize() throws SyslogRuntimeException { + if (this.logger == null) { + throw new SyslogRuntimeException("logger cannot be null"); + } + } + + protected static Level getLog4jLevel(int level) { + switch(level) { + case SyslogConstants.LEVEL_DEBUG: return Level.DEBUG; + case SyslogConstants.LEVEL_INFO: return Level.INFO; + case SyslogConstants.LEVEL_NOTICE: return Level.INFO; + case SyslogConstants.LEVEL_WARN: return Level.WARN; + case SyslogConstants.LEVEL_ERROR: return Level.ERROR; + case SyslogConstants.LEVEL_CRITICAL: return Level.ERROR; + case SyslogConstants.LEVEL_ALERT: return Level.ERROR; + case SyslogConstants.LEVEL_EMERGENCY: return Level.FATAL; + + default: + return Level.WARN; + } + } + + public void down(SyslogIF syslog, String reason) { + this.logger.log(this.downLevel,"Syslog protocol \"" + syslog.getProtocol() + "\" is down: " + reason); + } + + public void up(SyslogIF syslog) { + this.logger.log(this.upLevel,"Syslog protocol \"" + syslog.getProtocol() + "\" is up"); + } + + public void log(SyslogIF syslog, int level, String message, String reason) throws SyslogRuntimeException { + Level log4jLevel = getLog4jLevel(level); + + String combinedMessage = combine(syslog,level,message,reason); + + this.logger.log(log4jLevel,combinedMessage); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/PrintStreamSyslogBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/PrintStreamSyslogBackLogHandler.java new file mode 100644 index 0000000..d9fc80c --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/PrintStreamSyslogBackLogHandler.java @@ -0,0 +1,69 @@ +package org.productivity.java.syslog4j.impl.backlog.printstream; + +import java.io.PrintStream; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.backlog.AbstractSyslogBackLogHandler; + +/** +* PrintStreamSyslogBackLogHandler provides a last-chance mechanism to log messages that fail +* (for whatever reason) within the rest of Syslog to a PrintStream. +* +*

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: PrintStreamSyslogBackLogHandler.java,v 1.1 2009/01/24 22:00:18 cvs Exp $ +*/ +public class PrintStreamSyslogBackLogHandler extends AbstractSyslogBackLogHandler { + protected PrintStream printStream = null; + protected boolean appendLinefeed = false; + + public PrintStreamSyslogBackLogHandler(PrintStream printStream) { + this.printStream = printStream; + + initialize(); + } + + public PrintStreamSyslogBackLogHandler(PrintStream printStream, boolean appendLinefeed) { + this.printStream = printStream; + this.appendLinefeed = appendLinefeed; + + initialize(); + } + + public PrintStreamSyslogBackLogHandler(PrintStream printStream, boolean appendLinefeed, boolean appendReason) { + this.printStream = printStream; + this.appendLinefeed = appendLinefeed; + this.appendReason = appendReason; + + initialize(); + } + + public void initialize() throws SyslogRuntimeException { + if (this.printStream == null) { + throw new SyslogRuntimeException("PrintStream cannot be null"); + } + } + + public void down(SyslogIF syslog, String reason) { + this.printStream.println(syslog.getProtocol() + ": DOWN" + (reason != null && !"".equals(reason.trim()) ? " (" + reason + ")" : "")); + } + + public void up(SyslogIF syslog) { + this.printStream.println(syslog.getProtocol() + ": UP"); + } + + public void log(SyslogIF syslog, int level, String message, String reason) { + String combinedMessage = combine(syslog,level,message,reason); + + if (this.appendLinefeed) { + this.printStream.println(combinedMessage); + + } else { + this.printStream.print(combinedMessage); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/SystemErrSyslogBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/SystemErrSyslogBackLogHandler.java new file mode 100644 index 0000000..814e5eb --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/SystemErrSyslogBackLogHandler.java @@ -0,0 +1,27 @@ +package org.productivity.java.syslog4j.impl.backlog.printstream; + +import org.productivity.java.syslog4j.SyslogBackLogHandlerIF; + +/** +* SystemErrSyslogBackLogHandler provides a last-chance mechanism to log messages that fail +* (for whatever reason) within the rest of Syslog to System.err. +* +*

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: SystemErrSyslogBackLogHandler.java,v 1.2 2009/03/29 17:38:59 cvs Exp $ +*/ +public class SystemErrSyslogBackLogHandler extends PrintStreamSyslogBackLogHandler { + public static final SyslogBackLogHandlerIF create() { + return new SystemErrSyslogBackLogHandler(); + } + + public SystemErrSyslogBackLogHandler() { + super(System.err,true); + } + public SystemErrSyslogBackLogHandler(boolean appendReason) { + super(System.err,true,appendReason); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/SystemOutSyslogBackLogHandler.java b/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/SystemOutSyslogBackLogHandler.java new file mode 100644 index 0000000..48e0062 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/backlog/printstream/SystemOutSyslogBackLogHandler.java @@ -0,0 +1,27 @@ +package org.productivity.java.syslog4j.impl.backlog.printstream; + +import org.productivity.java.syslog4j.SyslogBackLogHandlerIF; + +/** +* SystemOutSyslogBackLogHandler provides a last-chance mechanism to log messages that fail +* (for whatever reason) within the rest of Syslog 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: SystemOutSyslogBackLogHandler.java,v 1.2 2009/03/29 17:38:59 cvs Exp $ +*/ +public class SystemOutSyslogBackLogHandler extends PrintStreamSyslogBackLogHandler { + public static final SyslogBackLogHandlerIF create() { + return new SystemOutSyslogBackLogHandler(); + } + + public SystemOutSyslogBackLogHandler() { + super(System.out,true); + } + public SystemOutSyslogBackLogHandler(boolean appendReason) { + super(System.out,true,appendReason); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppender.java b/src/main/java/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppender.java new file mode 100644 index 0000000..604530b --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppender.java @@ -0,0 +1,79 @@ +package org.productivity.java.syslog4j.impl.log4j; + +import org.apache.log4j.helpers.LogLog; + +/** + * Syslog4jAppender provides a Log4j Appender wrapper for Syslog4j. + * + *

Note: Syslog4jAppender does NOT extend Log4j's SyslogAppender.

+ * + *

Example log4j.xml configuration:

+ * + *
+ * 
+   <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>
+ * 
+ * 
+ * + *

All available parameters are:

+ * + *
    + *
  • ident
  • + *
  • localName
  • + *
  • protocol
  • + *
  • facility
  • + *
  • host
  • + *
  • port
  • + *
  • charSet
  • + *
  • threaded
  • + *
  • threadLoopInterval
  • + *
  • splitMessageBeginText
  • + *
  • splitMessageEndText
  • + *
  • maxMessageLength
  • + *
  • maxShutdownWait
  • + *
  • writeRetries
  • + *
  • truncateMessage
  • + *
  • useStructuredData
  • + *
+ * + *

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: Syslog4jAppender.java,v 1.2 2011/01/23 20:49:12 cvs Exp $ + */ +public class Syslog4jAppender extends Syslog4jAppenderSkeleton { + private static final long serialVersionUID = -6072552977605816670L; + + public String initialize() { + if (this.protocol == null) { + this.protocol = UDP; + } + + return this.protocol; + } + + public boolean getHeader() { + return false; + } + + public void setHeader(boolean header) { + LogLog.warn("Syslog4jAppender ignores the \"Header\" parameter."); + } + + public String getSyslogHost() { + return this.host; + } + + public void setSyslogHost(String host) { + this.host = host; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppenderSkeleton.java b/src/main/java/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppenderSkeleton.java new file mode 100644 index 0000000..cc7f7e7 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppenderSkeleton.java @@ -0,0 +1,331 @@ +package org.productivity.java.syslog4j.impl.log4j; + +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.helpers.LogLog; +import org.apache.log4j.spi.LoggingEvent; +import org.productivity.java.syslog4j.Syslog; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.AbstractSyslogConfigIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** + * Syslog4jAppenderSkeleton provides an extensible Log4j Appender wrapper for Syslog4j. + * + *

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.

+ * + * @author <syslog4j@productivity.org> + * @version $Id: Syslog4jAppenderSkeleton.java,v 1.8 2011/01/23 20:49:12 cvs Exp $ + */ +public abstract class Syslog4jAppenderSkeleton extends AppenderSkeleton implements SyslogConstants { + private static final long serialVersionUID = 5520555788232095628L; + + protected SyslogIF syslog = null; + + protected String ident = null; + protected String localName = null; + protected String protocol = null; + protected String facility = null; + protected String host = null; + protected String port = null; + protected String charSet = null; + protected String threaded = null; + protected String threadLoopInterval = null; + protected String splitMessageBeginText = null; + protected String splitMessageEndText = null; + protected String maxMessageLength = null; + protected String maxShutdownWait = null; + protected String writeRetries = null; + protected String truncateMessage = null; + protected String useStructuredData = null; + + protected boolean initialized = false; + + public abstract String initialize() throws SyslogRuntimeException; + + protected static boolean isTrueOrOn(String value) { + boolean trueOrOn = false; + + if (value != null) { + if ("true".equalsIgnoreCase(value.trim()) || "on".equalsIgnoreCase(value.trim())) { + trueOrOn = true; + + } else if ("false".equalsIgnoreCase(value.trim()) || "off".equalsIgnoreCase(value.trim())) { + trueOrOn = false; + + } else { + LogLog.error("Value \"" + value + "\" not true, on, false, or off -- assuming false"); + } + } + + return trueOrOn; + } + + protected void _initialize() { + String initializedProtocol = initialize(); + + if (initializedProtocol != null && this.protocol == null) { + this.protocol = initializedProtocol; + } + + if (this.protocol != null) { + try { + this.syslog = Syslog.getInstance(this.protocol); + if (this.host != null) { + this.syslog.getConfig().setHost(this.host); + } + if (this.facility != null) { + this.syslog.getConfig().setFacility(SyslogUtility.getFacility(this.facility)); + } + if (this.port != null) { + try { + int i = Integer.parseInt(this.port); + this.syslog.getConfig().setPort(i); + + } catch (NumberFormatException nfe) { + LogLog.error(nfe.toString()); + } + } + if (this.charSet != null) { + this.syslog.getConfig().setCharSet(this.charSet); + } + if (this.ident != null) { + this.syslog.getConfig().setIdent(this.ident); + } + if (this.localName != null) { + this.syslog.getConfig().setLocalName(this.localName); + } + if (this.truncateMessage != null && !"".equals(this.truncateMessage.trim())) { + this.syslog.getConfig().setTruncateMessage(isTrueOrOn(this.truncateMessage)); + } + if (this.maxMessageLength != null && this.maxMessageLength.length() > 0) { + try { + int i = Integer.parseInt(this.maxMessageLength.trim()); + this.syslog.getConfig().setMaxMessageLength(i); + + } catch (NumberFormatException nfe) { + LogLog.error(nfe.toString()); + } + } + if (this.useStructuredData != null) { + this.syslog.getConfig().setUseStructuredData(isTrueOrOn(this.useStructuredData)); + } + if (this.syslog.getConfig() instanceof AbstractSyslogConfigIF) { + AbstractSyslogConfigIF abstractSyslogConfig = (AbstractSyslogConfigIF) this.syslog.getConfig(); + + if (this.threaded != null && !"".equals(this.threaded.trim())) { + abstractSyslogConfig.setThreaded(isTrueOrOn(this.threaded)); + } + + if (this.threadLoopInterval != null && this.threadLoopInterval.length() > 0) { + try { + long l = Long.parseLong(this.threadLoopInterval.trim()); + abstractSyslogConfig.setThreadLoopInterval(l); + + } catch (NumberFormatException nfe) { + LogLog.error(nfe.toString()); + } + } + + if (this.splitMessageBeginText != null) { + abstractSyslogConfig.setSplitMessageBeginText(SyslogUtility.getBytes(abstractSyslogConfig,this.splitMessageBeginText)); + } + + if (this.splitMessageEndText != null) { + abstractSyslogConfig.setSplitMessageEndText(SyslogUtility.getBytes(abstractSyslogConfig,this.splitMessageEndText)); + } + + if (this.maxShutdownWait != null && this.maxShutdownWait.length() > 0) { + try { + int i = Integer.parseInt(this.maxShutdownWait.trim()); + abstractSyslogConfig.setMaxShutdownWait(i); + + } catch (NumberFormatException nfe) { + LogLog.error(nfe.toString()); + } + } + + if (this.writeRetries != null && this.writeRetries.length() > 0) { + try { + int i = Integer.parseInt(this.writeRetries.trim()); + abstractSyslogConfig.setWriteRetries(i); + + } catch (NumberFormatException nfe) { + LogLog.error(nfe.toString()); + } + } + } + + this.initialized = true; + + } catch (SyslogRuntimeException sre) { + LogLog.error(sre.toString()); + } + } + } + + public String getProtocol() { + return this.protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + protected void append(LoggingEvent event) { + if (!this.initialized) { + _initialize(); + } + + if (this.initialized) { + int level = event.getLevel().getSyslogEquivalent(); + + if (this.layout != null) { + String message = this.layout.format(event); + + this.syslog.log(level,message); + + } else { + String message = event.getRenderedMessage(); + + this.syslog.log(level,message); + } + } + } + + public void close() { + if (this.syslog != null) { + this.syslog.flush(); + } + } + + public String getFacility() { + return this.facility; + } + + public void setFacility(String facility) { + this.facility = facility; + } + + public String getHost() { + return this.host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getLocalName() { + return localName; + } + + public void setLocalName(String localName) { + this.localName = localName; + } + + public String getPort() { + return this.port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getCharSet() { + return this.charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } + + public String getIdent() { + return this.ident; + } + + public void setIdent(String ident) { + this.ident = ident; + } + + public String getThreaded() { + return this.threaded; + } + + public void setThreaded(String threaded) { + this.threaded = threaded; + } + + public boolean requiresLayout() { + return false; + } + + public String getThreadLoopInterval() { + return this.threadLoopInterval; + } + + public void setThreadLoopInterval(String threadLoopInterval) { + this.threadLoopInterval = threadLoopInterval; + } + + public String getSplitMessageBeginText() { + return this.splitMessageBeginText; + } + + public void setSplitMessageBeginText(String splitMessageBeginText) { + this.splitMessageBeginText = splitMessageBeginText; + } + + public String getSplitMessageEndText() { + return this.splitMessageEndText; + } + + public void setSplitMessageEndText(String splitMessageEndText) { + this.splitMessageEndText = splitMessageEndText; + } + + public String getMaxMessageLength() { + return this.maxMessageLength; + } + + public void setMaxMessageLength(String maxMessageLength) { + this.maxMessageLength = maxMessageLength; + } + + public String getMaxShutdownWait() { + return this.maxShutdownWait; + } + + public void setMaxShutdownWait(String maxShutdownWait) { + this.maxShutdownWait = maxShutdownWait; + } + + public String getWriteRetries() { + return this.writeRetries; + } + + public void setWriteRetries(String writeRetries) { + this.writeRetries = writeRetries; + } + + public String getTruncateMessage() { + return this.truncateMessage; + } + + public void setTruncateMessage(String truncateMessage) { + this.truncateMessage = truncateMessage; + } + + public String getUseStructuredData() { + return useStructuredData; + } + + public void setUseStructuredData(String useStructuredData) { + this.useStructuredData = useStructuredData; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/AbstractSyslogMessage.java b/src/main/java/org/productivity/java/syslog4j/impl/message/AbstractSyslogMessage.java new file mode 100644 index 0000000..f6cee50 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/AbstractSyslogMessage.java @@ -0,0 +1,101 @@ +package org.productivity.java.syslog4j.impl.message; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.productivity.java.syslog4j.SyslogMessageIF; + +/** +* AbstractSyslogMessage provides support for turning POJO (Plain Ol' +* Java Objects) into Syslog messages. +* +*

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.

+* +* @author <syslog4j@productivity.org> +* @version $Id: AbstractSyslogMessage.java,v 1.2 2009/04/17 02:37:04 cvs Exp $ +*/ +public abstract class AbstractSyslogMessage implements SyslogMessageIF { + private static final long serialVersionUID = 414124277626756491L; + + public static final String UNDEFINED = "undefined"; + + public static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd"; + public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss"; + + public static final char DEFAULT_DELIMITER = ' '; + public static final String DEFAULT_REPLACE_DELIMITER = "_"; + + protected char getDelimiter() { + return DEFAULT_DELIMITER; + } + + protected String getReplaceDelimiter() { + return DEFAULT_REPLACE_DELIMITER; + } + + protected String getDateFormat() { + return DEFAULT_DATE_FORMAT; + } + + protected String getTimeFormat() { + return DEFAULT_TIME_FORMAT; + } + + protected String generateDate() { + String date = new SimpleDateFormat(getDateFormat()).format(new Date()); + + return date; + } + + protected String generateTime() { + String time = new SimpleDateFormat(getTimeFormat()).format(new Date()); + + return time; + } + + protected String[] generateDateAndTime(Date date) { + String[] dateAndTime = new String[2]; + + dateAndTime[0] = new SimpleDateFormat(getDateFormat()).format(date); + dateAndTime[1] = new SimpleDateFormat(getTimeFormat()).format(date); + + return dateAndTime; + } + + protected String generateLocalHostName() { + String localHostName = UNDEFINED; + + try { + localHostName = InetAddress.getLocalHost().getHostName(); + + } catch (UnknownHostException uhe) { + // + } + + return localHostName; + } + + protected boolean nullOrEmpty(String value) { + return (value == null || "".equals(value.trim())); + } + + protected String replaceDelimiter(String fieldName, String fieldValue, char delimiter, String replaceDelimiter) { + if (replaceDelimiter == null || replaceDelimiter.length() < 1 || fieldValue == null || fieldValue.length() < 1) { + return fieldValue; + } + + String newFieldValue = fieldValue.replaceAll("\\" + delimiter, replaceDelimiter); + + return newFieldValue; + } + + public abstract String createMessage(); +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifier.java new file mode 100644 index 0000000..33b586b --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifier.java @@ -0,0 +1,63 @@ +package org.productivity.java.syslog4j.impl.message.modifier; + +import org.productivity.java.syslog4j.SyslogMessageModifierConfigIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; + +public abstract class AbstractSyslogMessageModifier implements SyslogMessageModifierIF { + private static final long serialVersionUID = 7632959170109372003L; + + protected SyslogMessageModifierConfigIF messageModifierConfig = null; + + public AbstractSyslogMessageModifier(SyslogMessageModifierConfigIF messageModifierConfig) { + this.messageModifierConfig = messageModifierConfig; + } + + public String[] parseInlineModifier(String message) { + return parseInlineModifier(message,this.messageModifierConfig.getPrefix(),this.messageModifierConfig.getSuffix()); + } + + public static String[] parseInlineModifier(String message, String prefix, String suffix) { + String[] messageAndModifier = null; + + if (message == null || "".equals(message.trim())) { + return null; + } + + if (prefix == null || "".equals(prefix)) { + prefix = " "; + } + + if (suffix == null || "".equals(suffix)) { + int pi = message.lastIndexOf(prefix); + + if (pi > -1) { + messageAndModifier = new String[] { message.substring(0,pi), message.substring(pi+prefix.length()) }; + } + + } else { + int si = message.lastIndexOf(suffix); + + if (si > -1) { + int pi = message.lastIndexOf(prefix,si); + + if (pi > -1) { + messageAndModifier = new String[] { message.substring(0,pi), message.substring(pi+prefix.length(),si) }; + } + } + } + + return messageAndModifier; + } + + protected abstract boolean verify(String message, String modifier); + + public boolean verify(String message) { + String[] messageAndModifier = parseInlineModifier(message); + + if (messageAndModifier == null || messageAndModifier.length != 2) { + return false; + } + + return verify(messageAndModifier[0],messageAndModifier[1]); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifierConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifierConfig.java new file mode 100644 index 0000000..cb97b71 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifierConfig.java @@ -0,0 +1,58 @@ +package org.productivity.java.syslog4j.impl.message.modifier; + +import org.productivity.java.syslog4j.SyslogCharSetIF; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogMessageModifierConfigIF; + +/** +* AbstractSyslogMessageModifierConfig provides a base abstract implementation of the +* SyslogMessageModifierConfigIF. +* +*

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: AbstractSyslogMessageModifierConfig.java,v 1.4 2010/10/28 05:10:57 cvs Exp $ +*/ +public abstract class AbstractSyslogMessageModifierConfig implements SyslogMessageModifierConfigIF, SyslogCharSetIF { + private static final long serialVersionUID = 5036574188079124884L; + + protected String prefix = SYSLOG_MESSAGE_MODIFIER_PREFIX_DEFAULT; + protected String suffix = SYSLOG_MESSAGE_MODIFIER_SUFFIX_DEFAULT; + protected String charSet = SyslogConstants.CHAR_SET_DEFAULT; + + public String getPrefix() { + return this.prefix; + } + + public String getSuffix() { + return this.suffix; + } + + public void setPrefix(String prefix) { + if (prefix == null) { + this.prefix = ""; + + } else { + this.prefix = prefix; + } + } + + public void setSuffix(String suffix) { + if (suffix == null) { + this.suffix = ""; + + } else { + this.suffix = suffix; + } + } + + public String getCharSet() { + return charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifier.java new file mode 100644 index 0000000..55b7f6b --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifier.java @@ -0,0 +1,101 @@ +package org.productivity.java.syslog4j.impl.message.modifier.checksum; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifier; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* ChecksumSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that provides support for Java Checksum algorithms (java.util.zip.Checksum). +* +*

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: ChecksumSyslogMessageModifier.java,v 1.5 2010/10/28 05:10:57 cvs Exp $ +*/ +public class ChecksumSyslogMessageModifier extends AbstractSyslogMessageModifier { + private static final long serialVersionUID = -3268914290497005065L; + + protected ChecksumSyslogMessageModifierConfig config = null; + + public static final ChecksumSyslogMessageModifier createCRC32() { + ChecksumSyslogMessageModifier crc32 = new ChecksumSyslogMessageModifier(ChecksumSyslogMessageModifierConfig.createCRC32()); + + return crc32; + } + public static final ChecksumSyslogMessageModifier createADLER32() { + ChecksumSyslogMessageModifier adler32 = new ChecksumSyslogMessageModifier(ChecksumSyslogMessageModifierConfig.createADLER32()); + + return adler32; + } + + public ChecksumSyslogMessageModifier(ChecksumSyslogMessageModifierConfig config) { + super(config); + + this.config = config; + + if (this.config == null) { + throw new SyslogRuntimeException("Checksum config object cannot be null"); + } + + if (this.config.getChecksum() == null) { + throw new SyslogRuntimeException("Checksum object cannot be null"); + } + } + + public ChecksumSyslogMessageModifierConfig getConfig() { + return this.config; + } + + protected void continuousCheckForVerify() { + if (this.config.isContinuous()) { + throw new SyslogRuntimeException(this.getClass().getName() + ".verify(..) does not work with isContinuous() returning true"); + } + + } + + public boolean verify(String message, String hexChecksum) { + continuousCheckForVerify(); + + long checksum = Long.parseLong(hexChecksum,16); + + return verify(message,checksum); + } + + public boolean verify(String message, long checksum) { + continuousCheckForVerify(); + + synchronized(this.config.getChecksum()) { + this.config.getChecksum().reset(); + + byte[] messageBytes = SyslogUtility.getBytes(this.config,message); + + this.config.getChecksum().update(messageBytes,0,message.length()); + + return this.config.getChecksum().getValue() == checksum; + } + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + synchronized(this.config.getChecksum()) { + StringBuffer messageBuffer = new StringBuffer(message); + + byte[] messageBytes = SyslogUtility.getBytes(syslog.getConfig(),message); + + if (!this.config.isContinuous()) { + this.config.getChecksum().reset(); + } + + this.config.getChecksum().update(messageBytes,0,message.length()); + + messageBuffer.append(this.config.getPrefix()); + messageBuffer.append(Long.toHexString(this.config.getChecksum().getValue()).toUpperCase()); + messageBuffer.append(this.config.getSuffix()); + + return messageBuffer.toString(); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifierConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifierConfig.java new file mode 100644 index 0000000..ebf2cc9 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifierConfig.java @@ -0,0 +1,57 @@ +package org.productivity.java.syslog4j.impl.message.modifier.checksum; + +import java.util.zip.Adler32; +import java.util.zip.CRC32; +import java.util.zip.Checksum; + +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifierConfig; + +/** +* ChecksumSyslogMessageModifierConfig is an implementation of AbstractSyslogMessageModifierConfig +* that provides configuration for ChecksumSyslogMessageModifier. +* +*

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: ChecksumSyslogMessageModifierConfig.java,v 1.2 2010/02/04 03:41:38 cvs Exp $ +*/ +public class ChecksumSyslogMessageModifierConfig extends AbstractSyslogMessageModifierConfig { + private static final long serialVersionUID = -8298600135683882489L; + + protected Checksum checksum = null; + protected boolean continuous = false; + + public static final ChecksumSyslogMessageModifierConfig createCRC32() { + ChecksumSyslogMessageModifierConfig crc32 = new ChecksumSyslogMessageModifierConfig(new CRC32()); + + return crc32; + } + + public static final ChecksumSyslogMessageModifierConfig createADLER32() { + ChecksumSyslogMessageModifierConfig adler32 = new ChecksumSyslogMessageModifierConfig(new Adler32()); + + return adler32; + } + + public ChecksumSyslogMessageModifierConfig(Checksum checksum) { + this.checksum = checksum; + } + + public Checksum getChecksum() { + return this.checksum; + } + + public void setChecksum(Checksum checksum) { + this.checksum = checksum; + } + + public boolean isContinuous() { + return continuous; + } + + public void setContinuous(boolean continuous) { + this.continuous = continuous; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/escape/HTMLEntityEscapeSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/escape/HTMLEntityEscapeSyslogMessageModifier.java new file mode 100644 index 0000000..762ee98 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/escape/HTMLEntityEscapeSyslogMessageModifier.java @@ -0,0 +1,80 @@ +package org.productivity.java.syslog4j.impl.message.modifier.escape; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; + +/** +* HTMLEntityEscapeSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that safely escapes HTML entity characters. +* +*

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.

+* +* @author <syslog4j@productivity.org> +* @version $Id: HTMLEntityEscapeSyslogMessageModifier.java,v 1.4 2010/10/28 05:10:57 cvs Exp $ +*/ +public class HTMLEntityEscapeSyslogMessageModifier implements SyslogMessageModifierIF { + private static final long serialVersionUID = -8481773209240762293L; + + public static final SyslogMessageModifierIF createDefault() { + return new HTMLEntityEscapeSyslogMessageModifier(); + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + if (message != null && !"".equals(message.trim())) { + String escapedMessage = escapeHtml(message); + + return escapedMessage; + } + + return message; + } + + public boolean verify(String message) { + // NO-OP + + return true; + } + + /** + * escapeHtml(String) is based partly on the article posted here: http://www.owasp.org/index.php/How_to_perform_HTML_entity_encoding_in_Java + * with the addition of common characters and modifications for Java 1.4 support. + * + * @param message + * @return Returns a message where any HTML entity characters are escaped. + */ + public static String escapeHtml(String message) { + StringBuffer b = new StringBuffer(message.length()); + + for (int i = 0; i < message.length(); i++) { + char ch = message.charAt(i); + + if (ch == '<') { + b.append("<"); + } else if (ch == '>') { + b.append(">"); + } else if (ch == '"') { + b.append("""); + } else if (ch == '\'') { + b.append("'"); + } else if (ch == '&') { + b.append("&"); + } else if (ch >= ' ' && ch <= '~') { + b.append(ch); + } else if (Character.isWhitespace(ch)) { + b.append("&#").append((int) ch).append(";"); + } else if (Character.isISOControl(ch)) { + // Ignore character + } else if (Character.isDefined(ch)) { + b.append("&#").append((int) ch).append(";"); + } + } + + return b.toString(); + } + +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifier.java new file mode 100644 index 0000000..300e8ce --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifier.java @@ -0,0 +1,132 @@ +package org.productivity.java.syslog4j.impl.message.modifier.hash; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifier; +import org.productivity.java.syslog4j.util.Base64; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* HashSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that provides support for Java Cryptographic hashes (MD5, SHA1, SHA256, etc.). +* +*

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: HashSyslogMessageModifier.java,v 1.5 2010/10/28 05:10:57 cvs Exp $ +*/ +public class HashSyslogMessageModifier extends AbstractSyslogMessageModifier { + private static final long serialVersionUID = 7335757344826206953L; + + protected HashSyslogMessageModifierConfig config = null; + + public static final HashSyslogMessageModifier createMD5() { + HashSyslogMessageModifier md5 = new HashSyslogMessageModifier(HashSyslogMessageModifierConfig.createMD5()); + + return md5; + } + + public static final HashSyslogMessageModifier createSHA1() { + HashSyslogMessageModifier sha1 = new HashSyslogMessageModifier(HashSyslogMessageModifierConfig.createSHA1()); + + return sha1; + } + + public static final HashSyslogMessageModifier createSHA160() { + return createSHA1(); + } + + public static final HashSyslogMessageModifier createSHA256() { + HashSyslogMessageModifier sha256 = new HashSyslogMessageModifier(HashSyslogMessageModifierConfig.createSHA256()); + + return sha256; + } + + public static final HashSyslogMessageModifier createSHA384() { + HashSyslogMessageModifier sha384 = new HashSyslogMessageModifier(HashSyslogMessageModifierConfig.createSHA384()); + + return sha384; + } + + public static final HashSyslogMessageModifier createSHA512() { + HashSyslogMessageModifier sha512 = new HashSyslogMessageModifier(HashSyslogMessageModifierConfig.createSHA512()); + + return sha512; + } + + public HashSyslogMessageModifier(HashSyslogMessageModifierConfig config) throws SyslogRuntimeException { + super(config); + + this.config = config; + + if (this.config == null) { + throw new SyslogRuntimeException("Hash config object cannot be null"); + } + + if (this.config.getHashAlgorithm() == null) { + throw new SyslogRuntimeException("Hash algorithm cannot be null"); + } + + try { + MessageDigest.getInstance(config.getHashAlgorithm()); + + } catch (NoSuchAlgorithmException nsae){ + throw new SyslogRuntimeException(nsae); + } + } + + protected MessageDigest obtainMessageDigest() { + MessageDigest digest = null; + + try { + digest = MessageDigest.getInstance(this.config.getHashAlgorithm()); + + } catch (NoSuchAlgorithmException nsae) { + throw new SyslogRuntimeException(nsae); + } + + return digest; + } + + public HashSyslogMessageModifierConfig getConfig() { + return this.config; + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + byte[] messageBytes = SyslogUtility.getBytes(syslog.getConfig(),message); + + MessageDigest digest = obtainMessageDigest(); + byte[] digestBytes = digest.digest(messageBytes); + + String digestString = Base64.encodeBytes(digestBytes,Base64.DONT_BREAK_LINES); + + StringBuffer buffer = new StringBuffer(message); + + buffer.append(this.config.getPrefix()); + buffer.append(digestString); + buffer.append(this.config.getSuffix()); + + return buffer.toString(); + } + + public boolean verify(String message, String base64Hash) { + byte[] hash = Base64.decode(base64Hash); + + return verify(message,hash); + } + + public boolean verify(String message, byte[] hash) { + byte[] messageBytes = SyslogUtility.getBytes(this.config,message); + + MessageDigest digest = obtainMessageDigest(); + byte[] digestBytes = digest.digest(messageBytes); + + return Arrays.equals(digestBytes,hash); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifierConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifierConfig.java new file mode 100644 index 0000000..4dd0c8d --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifierConfig.java @@ -0,0 +1,66 @@ +package org.productivity.java.syslog4j.impl.message.modifier.hash; + +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifierConfig; + +/** +* HashSyslogMessageModifierConfig is an implementation of AbstractSyslogMessageModifierConfig +* that provides configuration for HashSyslogMessageModifier. +* +*

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: HashSyslogMessageModifierConfig.java,v 1.1 2008/11/10 04:38:37 cvs Exp $ +*/ +public class HashSyslogMessageModifierConfig extends AbstractSyslogMessageModifierConfig { + private static final long serialVersionUID = -3148300281439874231L; + + protected String hashAlgorithm = null; + + public static final HashSyslogMessageModifierConfig createMD5() { + HashSyslogMessageModifierConfig md5 = new HashSyslogMessageModifierConfig("MD5"); + + return md5; + } + + public static final HashSyslogMessageModifierConfig createSHA1() { + HashSyslogMessageModifierConfig sha1 = new HashSyslogMessageModifierConfig("SHA1"); + + return sha1; + } + + public static final HashSyslogMessageModifierConfig createSHA160() { + return createSHA1(); + } + + public static final HashSyslogMessageModifierConfig createSHA256() { + HashSyslogMessageModifierConfig sha256 = new HashSyslogMessageModifierConfig("SHA-256"); + + return sha256; + } + + public static final HashSyslogMessageModifierConfig createSHA384() { + HashSyslogMessageModifierConfig sha384 = new HashSyslogMessageModifierConfig("SHA-384"); + + return sha384; + } + + public static final HashSyslogMessageModifierConfig createSHA512() { + HashSyslogMessageModifierConfig sha512 = new HashSyslogMessageModifierConfig("SHA-512"); + + return sha512; + } + + public HashSyslogMessageModifierConfig(String hashAlgorithm) { + this.hashAlgorithm = hashAlgorithm; + } + + public String getHashAlgorithm() { + return this.hashAlgorithm; + } + + public void setHashAlgorithm(String hashAlgorithm) { + this.hashAlgorithm = hashAlgorithm; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifier.java new file mode 100644 index 0000000..492ec7b --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifier.java @@ -0,0 +1,120 @@ +package org.productivity.java.syslog4j.impl.message.modifier.mac; + +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Mac; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifier; +import org.productivity.java.syslog4j.util.Base64; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* MacSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that provides support for Java Cryptographic signed hashes (HmacSHA1, etc.) +* +*

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: MacSyslogMessageModifier.java,v 1.5 2010/10/28 05:10:57 cvs Exp $ +*/ +public class MacSyslogMessageModifier extends AbstractSyslogMessageModifier { + private static final long serialVersionUID = 5054979194802197540L; + + protected MacSyslogMessageModifierConfig config = null; + + protected Mac mac = null; + + public MacSyslogMessageModifier(MacSyslogMessageModifierConfig config) throws SyslogRuntimeException { + super(config); + + this.config = config; + + try { + this.mac = Mac.getInstance(config.getMacAlgorithm()); + this.mac.init(config.getKey()); + + } catch (NoSuchAlgorithmException nsae) { + throw new SyslogRuntimeException(nsae); + + } catch (InvalidKeyException ike) { + throw new SyslogRuntimeException(ike); + } + } + + public static MacSyslogMessageModifier createHmacSHA1(Key key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacSHA1(key)); + } + + public static MacSyslogMessageModifier createHmacSHA1(String base64Key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacSHA1(base64Key)); + } + + public static MacSyslogMessageModifier createHmacSHA256(Key key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacSHA256(key)); + } + + public static MacSyslogMessageModifier createHmacSHA256(String base64Key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacSHA256(base64Key)); + } + + public static MacSyslogMessageModifier createHmacSHA512(Key key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacSHA512(key)); + } + + public static MacSyslogMessageModifier createHmacSHA512(String base64Key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacSHA512(base64Key)); + } + + public static MacSyslogMessageModifier createHmacMD5(Key key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacMD5(key)); + } + + public static MacSyslogMessageModifier createHmacMD5(String base64Key) { + return new MacSyslogMessageModifier(MacSyslogMessageModifierConfig.createHmacMD5(base64Key)); + } + + public MacSyslogMessageModifierConfig getConfig() { + return this.config; + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + synchronized(this.mac) { + byte[] messageBytes = SyslogUtility.getBytes(syslog.getConfig(),message); + + StringBuffer buffer = new StringBuffer(message); + + byte[] macBytes = this.mac.doFinal(messageBytes); + + String macString = Base64.encodeBytes(macBytes,Base64.DONT_BREAK_LINES); + + buffer.append(this.config.getPrefix()); + buffer.append(macString); + buffer.append(this.config.getSuffix()); + + return buffer.toString(); + } + } + + public boolean verify(String message, String base64Signature) { + byte[] signature = Base64.decode(base64Signature); + + return verify(message,signature); + } + + public boolean verify(String message, byte[] signature) { + synchronized(this.mac) { + byte[] messageBytes = SyslogUtility.getBytes(this.config,message); + + byte[] macBytes = this.mac.doFinal(messageBytes); + + return Arrays.equals(macBytes,signature); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifierConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifierConfig.java new file mode 100644 index 0000000..ce055da --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifierConfig.java @@ -0,0 +1,108 @@ +package org.productivity.java.syslog4j.impl.message.modifier.mac; + +import java.security.Key; + +import javax.crypto.spec.SecretKeySpec; + +import org.productivity.java.syslog4j.SyslogRuntimeException; +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifierConfig; +import org.productivity.java.syslog4j.util.Base64; + +/** +* MacSyslogMessageModifierConfig is an implementation of AbstractSyslogMessageModifierConfig +* that provides configuration for HashSyslogMessageModifier. +* +*

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: MacSyslogMessageModifierConfig.java,v 1.3 2009/04/17 02:37:04 cvs Exp $ +*/ +public class MacSyslogMessageModifierConfig extends AbstractSyslogMessageModifierConfig { + private static final long serialVersionUID = 4524180892377960695L; + + protected String macAlgorithm = null; + protected String keyAlgorithm = null; + protected Key key = null; + + public MacSyslogMessageModifierConfig(String macAlgorithm, String keyAlgorithm, Key key) { + this.macAlgorithm = macAlgorithm; + this.keyAlgorithm = keyAlgorithm; + this.key = key; + } + + public MacSyslogMessageModifierConfig(String macAlgorithm, String keyAlgorithm, byte[] keyBytes) { + this.macAlgorithm = macAlgorithm; + this.keyAlgorithm = keyAlgorithm; + + try { + this.key = new SecretKeySpec(keyBytes,keyAlgorithm); + + } catch (IllegalArgumentException iae) { + throw new SyslogRuntimeException(iae); + } + } + + public MacSyslogMessageModifierConfig(String macAlgorithm, String keyAlgorithm, String base64Key) { + this.macAlgorithm = macAlgorithm; + this.keyAlgorithm = keyAlgorithm; + + byte[] keyBytes = Base64.decode(base64Key); + + try { + this.key = new SecretKeySpec(keyBytes,keyAlgorithm); + + } catch (IllegalArgumentException iae) { + throw new SyslogRuntimeException(iae); + } + } + + public static MacSyslogMessageModifierConfig createHmacSHA1(Key key) { + return new MacSyslogMessageModifierConfig("HmacSHA1","SHA1",key); + } + + public static MacSyslogMessageModifierConfig createHmacSHA1(String base64Key) { + return new MacSyslogMessageModifierConfig("HmacSHA1","SHA1",base64Key); + } + + public static MacSyslogMessageModifierConfig createHmacSHA256(Key key) { + return new MacSyslogMessageModifierConfig("HmacSHA256","SHA-256",key); + } + + public static MacSyslogMessageModifierConfig createHmacSHA256(String base64Key) { + return new MacSyslogMessageModifierConfig("HmacSHA256","SHA-256",base64Key); + } + + public static MacSyslogMessageModifierConfig createHmacSHA512(Key key) { + return new MacSyslogMessageModifierConfig("HmacSHA512","SHA-512",key); + } + + public static MacSyslogMessageModifierConfig createHmacSHA512(String base64Key) { + return new MacSyslogMessageModifierConfig("HmacSHA512","SHA-512",base64Key); + } + + public static MacSyslogMessageModifierConfig createHmacMD5(Key key) { + return new MacSyslogMessageModifierConfig("HmacMD5","MD5",key); + } + + public static MacSyslogMessageModifierConfig createHmacMD5(String base64Key) { + return new MacSyslogMessageModifierConfig("HmacMD5","MD5",base64Key); + } + + public String getMacAlgorithm() { + return this.macAlgorithm; + } + + public String getKeyAlgorithm() { + return this.keyAlgorithm; + } + + public Key getKey() { + return this.key; + } + + public void setKey(Key key) { + this.key = key; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifier.java new file mode 100644 index 0000000..4ac5364 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifier.java @@ -0,0 +1,101 @@ +package org.productivity.java.syslog4j.impl.message.modifier.sequential; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; + +/** +* SequentialSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that adds an incremented number at the end. +* +*

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: SequentialSyslogMessageModifier.java,v 1.8 2010/11/28 04:43:31 cvs Exp $ +*/ +public class SequentialSyslogMessageModifier implements SyslogMessageModifierIF { + private static final long serialVersionUID = 6107735010240030785L; + + protected SequentialSyslogMessageModifierConfig config = null; + + protected long currentSequence[] = new long[LEVEL_DEBUG + 1]; + + public static final SequentialSyslogMessageModifier createDefault() { + SequentialSyslogMessageModifier modifier = new SequentialSyslogMessageModifier(SequentialSyslogMessageModifierConfig.createDefault()); + + return modifier; + } + + public SequentialSyslogMessageModifier(SequentialSyslogMessageModifierConfig config) { + this.config = config; + + for(int i=0; i<(LEVEL_DEBUG + 1); i++) { + this.currentSequence[i] = config.getFirstNumber(); + } + } + + protected String pad(long number) { + StringBuffer buffer = new StringBuffer(Long.toString(number)); + + while (buffer.length() < this.config.getLastNumberDigits()) { + buffer.insert(0,this.config.getPadChar()); + } + + return buffer.toString(); + } + + public void setNextSequence(int level, long nextSequence) { + if (nextSequence >= this.config.getFirstNumber() && nextSequence < this.config.getLastNumber()) { + synchronized(this) { + this.currentSequence[level] = nextSequence; + } + } + } + + protected String nextSequence(int level) { + long sequence = -1; + + synchronized(this) { + sequence = this.currentSequence[level]; + + if (this.currentSequence[level] >= this.config.getLastNumber()) { + this.currentSequence[level] = this.config.getFirstNumber(); + + } else { + this.currentSequence[level]++; + } + } + + String _sequence = null; + + if (this.config.isUsePadding()) { + _sequence = pad(sequence); + + } else { + _sequence = Long.toString(sequence); + } + + return _sequence; + } + + public SequentialSyslogMessageModifierConfig getConfig() { + return this.config; + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + StringBuffer buffer = new StringBuffer(message); + + buffer.append(this.config.getPrefix()); + buffer.append(nextSequence(level)); + buffer.append(this.config.getSuffix()); + + return buffer.toString(); + } + + public boolean verify(String message) { + // NO-OP + + return true; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifierConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifierConfig.java new file mode 100644 index 0000000..307ae86 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifierConfig.java @@ -0,0 +1,74 @@ +package org.productivity.java.syslog4j.impl.message.modifier.sequential; + +import org.productivity.java.syslog4j.impl.message.modifier.AbstractSyslogMessageModifierConfig; + +/** +* SequentialSyslogMessageModifierConfig is an implementation of AbstractSyslogMessageModifierConfig +* that provides configuration for SequentialSyslogMessageModifier. +* +*

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: SequentialSyslogMessageModifierConfig.java,v 1.4 2009/03/29 17:38:58 cvs Exp $ +*/ +public class SequentialSyslogMessageModifierConfig extends AbstractSyslogMessageModifierConfig { + private static final long serialVersionUID = 1570930406228960303L; + + protected long firstNumber = SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_FIRST_NUMBER_DEFAULT; + protected long lastNumber = SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_LAST_NUMBER_DEFAULT; + protected char padChar = SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_PAD_CHAR_DEFAULT; + protected boolean usePadding = SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_USE_PADDING_DEFAULT; + + public static final SequentialSyslogMessageModifierConfig createDefault() { + SequentialSyslogMessageModifierConfig modifierConfig = new SequentialSyslogMessageModifierConfig(); + + return modifierConfig; + } + + public SequentialSyslogMessageModifierConfig() { + setPrefix(SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_PREFIX_DEFAULT); + setSuffix(SYSLOG_SEQUENTIAL_MESSAGE_MODIFIER_SUFFIX_DEFAULT); + } + + public long getLastNumberDigits() { + return Long.toString(this.lastNumber).length(); + } + + public long getFirstNumber() { + return this.firstNumber; + } + + public void setFirstNumber(long firstNumber) { + if (firstNumber < this.lastNumber) { + this.firstNumber = firstNumber; + } + } + + public long getLastNumber() { + return this.lastNumber; + } + + public void setLastNumber(long lastNumber) { + if (lastNumber > this.firstNumber) { + this.lastNumber = lastNumber; + } + } + + public boolean isUsePadding() { + return this.usePadding; + } + + public void setUsePadding(boolean usePadding) { + this.usePadding = usePadding; + } + + public char getPadChar() { + return this.padChar; + } + + public void setPadChar(char padChar) { + this.padChar = padChar; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/PrefixSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/PrefixSyslogMessageModifier.java new file mode 100644 index 0000000..32afee0 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/PrefixSyslogMessageModifier.java @@ -0,0 +1,59 @@ +package org.productivity.java.syslog4j.impl.message.modifier.text; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; + +/** +* PrefixSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that provides support for adding static text to the beginning of a Syslog message. +* +*

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: PrefixSyslogMessageModifier.java,v 1.5 2010/10/28 05:10:57 cvs Exp $ +*/ +public class PrefixSyslogMessageModifier implements SyslogMessageModifierIF { + private static final long serialVersionUID = 6718826215583513972L; + + protected String prefix = null; + protected String delimiter = " "; + + public PrefixSyslogMessageModifier() { + // + } + + public PrefixSyslogMessageModifier(String prefix) { + this.prefix = prefix; + } + + public PrefixSyslogMessageModifier(String prefix, String delimiter) { + this.prefix = prefix; + if (delimiter != null) { + this.delimiter = delimiter; + } + } + + public String getPrefix() { + return this.prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + if (this.prefix == null || "".equals(this.prefix.trim())) { + return message; + } + + return this.prefix + this.delimiter + message; + } + + public boolean verify(String message) { + // NO-OP + + return true; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/StringCaseSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/StringCaseSyslogMessageModifier.java new file mode 100644 index 0000000..bc76773 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/StringCaseSyslogMessageModifier.java @@ -0,0 +1,58 @@ +package org.productivity.java.syslog4j.impl.message.modifier.text; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; + +/** +* StringCaseSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that provides support for shifting a Syslog message to all upper case or all +* lower case. +* +*

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: StringCaseSyslogMessageModifier.java,v 1.3 2010/10/28 05:10:57 cvs Exp $ +*/ +public class StringCaseSyslogMessageModifier implements SyslogMessageModifierIF { + private static final long serialVersionUID = 8383234811585957460L; + + public static final byte LOWER_CASE = 0; + public static final byte UPPER_CASE = 1; + + public static final StringCaseSyslogMessageModifier LOWER = new StringCaseSyslogMessageModifier(LOWER_CASE); + public static final StringCaseSyslogMessageModifier UPPER = new StringCaseSyslogMessageModifier(UPPER_CASE); + + protected byte stringCase = LOWER_CASE; + + public StringCaseSyslogMessageModifier(byte stringCase) { + this.stringCase = stringCase; + + if (stringCase < LOWER_CASE || stringCase > UPPER_CASE) { + throw new SyslogRuntimeException("stringCase must be LOWER_CASE (0) or UPPER_CASE (1)"); + } + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + String _message = message; + + if (message != null) { + if (this.stringCase == LOWER_CASE) { + _message = _message.toLowerCase(); + + } else if (this.stringCase == UPPER_CASE) { + _message = _message.toUpperCase(); + } + } + + return _message; + } + + public boolean verify(String message) { + // NO-OP + + return true; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/SuffixSyslogMessageModifier.java b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/SuffixSyslogMessageModifier.java new file mode 100644 index 0000000..7f20a23 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/modifier/text/SuffixSyslogMessageModifier.java @@ -0,0 +1,59 @@ +package org.productivity.java.syslog4j.impl.message.modifier.text; + +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageModifierIF; + +/** +* SuffixSyslogMessageModifier is an implementation of SyslogMessageModifierIF +* that provides support for adding static text to the end of a Syslog message. +* +*

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: SuffixSyslogMessageModifier.java,v 1.5 2010/10/28 05:10:57 cvs Exp $ +*/ +public class SuffixSyslogMessageModifier implements SyslogMessageModifierIF { + private static final long serialVersionUID = 7160593302741507576L; + + protected String suffix = null; + protected String delimiter = " "; + + public SuffixSyslogMessageModifier() { + // + } + + public SuffixSyslogMessageModifier(String suffix) { + this.suffix = suffix; + } + + public SuffixSyslogMessageModifier(String suffix, String delimiter) { + this.suffix = suffix; + if (delimiter != null) { + this.delimiter = delimiter; + } + } + + public String getSuffix() { + return this.suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + public String modify(SyslogIF syslog, int facility, int level, String message) { + if (this.suffix == null || "".equals(this.suffix.trim())) { + return message; + } + + return message + this.delimiter + this.suffix; + } + + public boolean verify(String message) { + // NO-OP + + return true; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessage.java b/src/main/java/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessage.java new file mode 100644 index 0000000..78afb42 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessage.java @@ -0,0 +1,256 @@ +package org.productivity.java.syslog4j.impl.message.pci; + +import java.util.Date; +import java.util.Map; + +import org.productivity.java.syslog4j.impl.message.AbstractSyslogMessage; + +/** +* PCISyslogMessage provides support for audit trails defined by section +* 10.3 of the PCI Data Security Standard (PCI DSS) versions 1.1 and 1.2. +* +*

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.

+* +* @author <syslog4j@productivity.org> +* @version $Id: PCISyslogMessage.java,v 1.3 2008/11/14 04:32:00 cvs Exp $ +*/ +public class PCISyslogMessage extends AbstractSyslogMessage implements PCISyslogMessageIF { + private static final long serialVersionUID = 3571696218386879119L; + + public static final String USER_ID = "userId"; + public static final String EVENT_TYPE = "eventType"; + public static final String DATE = "date"; + public static final String TIME = "time"; + public static final String STATUS = "status"; + public static final String ORIGINATION = "origination"; + public static final String AFFECTED_RESOURCE = "affectedResource"; + + protected String userId = UNDEFINED; // 10.3.1 "User Identification" + protected String eventType = UNDEFINED; // 10.3.2 "Type of event" + protected String date = null; // 10.3.3 "Date and time" (date) + protected String time = null; // 10.3.3 "Date and time" (time) + protected String status = UNDEFINED; // 10.3.4 "Success or failure indication" + protected String origination = null; // 10.3.5 "Origination of Event" + protected String affectedResource = UNDEFINED; // 10.3.6 "Identity or name of affected data, system component, or resource" + + public PCISyslogMessage() { + // + } + + public PCISyslogMessage(PCISyslogMessageIF message) { + init(message); + } + + public PCISyslogMessage(Map fields) { + init(fields); + } + + protected void init(PCISyslogMessageIF message) { + this.userId = message.getUserId(); + this.eventType = message.getEventType(); + this.date = message.getDate(); + this.time = message.getTime(); + this.status = message.getStatus(); + this.origination = message.getOrigination(); + this.affectedResource = message.getAffectedResource(); + } + + protected void init(Map fields) { + if (fields.containsKey(USER_ID)) { this.userId = (String) fields.get(USER_ID); }; + if (fields.containsKey(EVENT_TYPE)) { this.eventType = (String) fields.get(EVENT_TYPE); }; + if (fields.containsKey(DATE) && fields.get(DATE) instanceof String) { this.date = (String) fields.get(DATE); }; + if (fields.containsKey(DATE) && fields.get(DATE) instanceof Date) { setDate((Date) fields.get(DATE)); }; + if (fields.containsKey(TIME)) { this.time = (String) fields.get(TIME); }; + if (fields.containsKey(STATUS)) { this.status = (String) fields.get(STATUS); }; + if (fields.containsKey(ORIGINATION)) { this.origination = (String) fields.get(ORIGINATION); }; + if (fields.containsKey(AFFECTED_RESOURCE)) { this.affectedResource = (String) fields.get(AFFECTED_RESOURCE); }; + } + + public PCISyslogMessage(String userId, String eventType, String status, String affectedResource) { + this.userId = userId; + this.eventType = eventType; + this.status = status; + this.affectedResource = affectedResource; + } + + public PCISyslogMessage(String userId, String eventType, String status, String origination, String affectedResource) { + this.userId = userId; + this.eventType = eventType; + this.status = status; + this.origination = origination; + this.affectedResource = affectedResource; + } + + public PCISyslogMessage(String userId, String eventType, String date, String time, String status, String affectedResource) { + this.userId = userId; + this.eventType = eventType; + this.date = date; + this.time = time; + this.status = status; + this.affectedResource = affectedResource; + } + + public PCISyslogMessage(String userId, String eventType, String date, String time, String status, String origination, String affectedResource) { + this.userId = userId; + this.eventType = eventType; + this.date = date; + this.time = time; + this.status = status; + this.origination = origination; + this.affectedResource = affectedResource; + } + + public PCISyslogMessage(String userId, String eventType, Date date, String status, String affectedResource) { + this.userId = userId; + this.eventType = eventType; + + String[] dateAndTime = generateDateAndTime(date); + this.date = dateAndTime[0]; + this.time = dateAndTime[1]; + + this.status = status; + this.affectedResource = affectedResource; + } + + public PCISyslogMessage(String userId, String eventType, Date date, String status, String origination, String affectedResource) { + this.userId = userId; + this.eventType = eventType; + + String[] dateAndTime = generateDateAndTime(date); + this.date = dateAndTime[0]; + this.time = dateAndTime[1]; + + this.status = status; + this.origination = origination; + this.affectedResource = affectedResource; + } + + public String getUserId() { + if (nullOrEmpty(this.userId)) { + return UNDEFINED; + } + + return this.userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getEventType() { + if (nullOrEmpty(this.eventType)) { + return UNDEFINED; + } + + return this.eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public String getDate() { + if (nullOrEmpty(this.date)) { + String dateNow = generateDate(); + + return dateNow; + } + + return this.date; + } + + public void setDate(String date) { + this.date = date; + } + + public void setDate(Date date) { + String[] d = generateDateAndTime(date); + + this.date = d[0]; + this.time = d[1]; + } + + public String getTime() { + if (nullOrEmpty(this.time)) { + String timeNow = generateTime(); + + return timeNow; + } + + return this.time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getStatus() { + if (nullOrEmpty(this.status)) { + return UNDEFINED; + } + + return this.status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getOrigination() { + if (nullOrEmpty(this.origination)) { + String originationHere = generateLocalHostName(); + + return originationHere; + } + + return this.origination; + } + + public void setOrigination(String origination) { + this.origination = origination; + } + + public String getAffectedResource() { + if (nullOrEmpty(this.affectedResource)) { + return UNDEFINED; + } + + return this.affectedResource; + } + + public void setAffectedResource(String affectedResource) { + this.affectedResource = affectedResource; + } + + public String createMessage() { + StringBuffer buffer = new StringBuffer(); + + char delimiter = getDelimiter(); + String replaceDelimiter = getReplaceDelimiter(); + + buffer.append(replaceDelimiter(USER_ID,getUserId(),delimiter,replaceDelimiter)); + buffer.append(delimiter); + buffer.append(replaceDelimiter(EVENT_TYPE,getEventType(),delimiter,replaceDelimiter)); + buffer.append(delimiter); + buffer.append(replaceDelimiter(DATE,getDate(),delimiter,replaceDelimiter)); + buffer.append(delimiter); + buffer.append(replaceDelimiter(TIME,getTime(),delimiter,replaceDelimiter)); + buffer.append(delimiter); + buffer.append(replaceDelimiter(STATUS,getStatus(),delimiter,replaceDelimiter)); + buffer.append(delimiter); + buffer.append(replaceDelimiter(ORIGINATION,getOrigination(),delimiter,replaceDelimiter)); + buffer.append(delimiter); + buffer.append(replaceDelimiter(AFFECTED_RESOURCE,getAffectedResource(),delimiter,replaceDelimiter)); + + return buffer.toString(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessageIF.java b/src/main/java/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessageIF.java new file mode 100644 index 0000000..31499d6 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessageIF.java @@ -0,0 +1,30 @@ +package org.productivity.java.syslog4j.impl.message.pci; + +/** +* PCISyslogMessageIF provides a definition of the fields for audit trails +* defined by section 10.3 of the PCI Data Security Standard (PCI DSS) +* versions 1.1 and 1.2. +* +*

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.

+* +* @author <syslog4j@productivity.org> +* @version $Id: PCISyslogMessageIF.java,v 1.1 2008/11/10 04:38:37 cvs Exp $ +*/ +public interface PCISyslogMessageIF { + public String getUserId(); + public String getEventType(); + public String getDate(); + public String getTime(); + public String getStatus(); + public String getOrigination(); + public String getAffectedResource(); +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/processor/AbstractSyslogMessageProcessor.java b/src/main/java/org/productivity/java/syslog4j/impl/message/processor/AbstractSyslogMessageProcessor.java new file mode 100644 index 0000000..b21c23f --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/processor/AbstractSyslogMessageProcessor.java @@ -0,0 +1,118 @@ +package org.productivity.java.syslog4j.impl.message.processor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogMessageProcessorIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* AbstractSyslogMessageProcessor provides the ability to split a syslog message +* into multiple messages when the message is greater than the syslog +* maximum message length (1024 bytes including the header). +* +*

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: AbstractSyslogMessageProcessor.java,v 1.2 2010/11/28 04:15:18 cvs Exp $ +*/ +public abstract class AbstractSyslogMessageProcessor implements SyslogMessageProcessorIF, SyslogConstants { + private static final long serialVersionUID = -5413127301924500938L; + protected String localName = null; + + public AbstractSyslogMessageProcessor() { + this.localName = SyslogUtility.getLocalName(); + } + + public byte[] createPacketData(byte[] header, byte[] message, int start, int length) { + return createPacketData(header,message,start,length,null,null); + } + + public byte[] createPacketData(byte[] header, byte[] message, int start, int length, byte[] splitBeginText, byte[] splitEndText) { + if (header == null || message == null || start < 0 || length < 0) { + return null; + } + + int dataLength = header.length + length; + + if (splitBeginText != null) { + dataLength += splitBeginText.length; + } + if (splitEndText != null) { + dataLength += splitEndText.length; + } + + byte[] data = new byte[dataLength]; + + System.arraycopy(header,0,data,0,header.length); + int pos = header.length; + + if (splitBeginText != null) { + System.arraycopy(splitBeginText,0,data,pos,splitBeginText.length); + pos += splitBeginText.length; + } + + System.arraycopy(message,start,data,pos,length); + pos += length; + + if (splitEndText != null) { + System.arraycopy(splitEndText,0,data,pos,splitEndText.length); + } + + return data; + } + + protected void appendPriority(StringBuffer buffer, int facility, int level) { + int priority = facility | level; + + buffer.append("<"); + buffer.append(priority); + buffer.append(">"); + } + + protected void appendLocalTimestamp(StringBuffer buffer) { + SimpleDateFormat dateFormat = new SimpleDateFormat(SYSLOG_DATEFORMAT,Locale.ENGLISH); + + String datePrefix = dateFormat.format(new Date()); + + int pos = buffer.length() + 4; + + buffer.append(datePrefix); + + // RFC 3164 requires leading space for days 1-9 + if (buffer.charAt(pos) == '0') { + buffer.setCharAt(pos,' '); + } + } + + protected void appendLocalName(StringBuffer buffer, String localName) { + if (localName != null) { + buffer.append(localName); + + } else { + buffer.append(this.localName); + } + + buffer.append(' '); + } + + public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalTimestamp, boolean sendLocalName) { + StringBuffer buffer = new StringBuffer(); + + appendPriority(buffer,facility,level); + + if (sendLocalTimestamp) { + appendLocalTimestamp(buffer); + } + + if (sendLocalName) { + appendLocalName(buffer,localName); + } + + return buffer.toString(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/processor/SyslogMessageProcessor.java b/src/main/java/org/productivity/java/syslog4j/impl/message/processor/SyslogMessageProcessor.java new file mode 100644 index 0000000..da3ce3d --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/processor/SyslogMessageProcessor.java @@ -0,0 +1,35 @@ +package org.productivity.java.syslog4j.impl.message.processor; + + +/** +* SyslogMessageProcessor wraps AbstractSyslogMessageProcessor. +* +*

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.

+* +* @author <syslog4j@productivity.org> +* @version $Id: SyslogMessageProcessor.java,v 1.7 2010/02/04 03:41:37 cvs Exp $ +*/ +public class SyslogMessageProcessor extends AbstractSyslogMessageProcessor { + private static final long serialVersionUID = -4232803978024990353L; + + private static final SyslogMessageProcessor INSTANCE = new SyslogMessageProcessor(); + + protected static SyslogMessageProcessor defaultInstance = INSTANCE; + + public static void setDefault(SyslogMessageProcessor messageProcessor) { + if (messageProcessor != null) { + defaultInstance = messageProcessor; + } + } + + public static SyslogMessageProcessor getDefault() { + return defaultInstance; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/processor/structured/StructuredSyslogMessageProcessor.java b/src/main/java/org/productivity/java/syslog4j/impl/message/processor/structured/StructuredSyslogMessageProcessor.java new file mode 100644 index 0000000..0d5b769 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/processor/structured/StructuredSyslogMessageProcessor.java @@ -0,0 +1,106 @@ +package org.productivity.java.syslog4j.impl.message.processor.structured; + +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.productivity.java.syslog4j.impl.message.processor.AbstractSyslogMessageProcessor; +import org.productivity.java.syslog4j.impl.message.structured.StructuredSyslogMessage; + +/** + * SyslogStructuredMessageProcessor extends SyslogMessageProcessor's ability to + * split a syslog message into multiple messages when the message is greater + * than the syslog maximum message length (1024 bytes including the header). It + * adds support for structured syslog messages as specified by + * draft-ietf-syslog-protocol-23. More information here: + * + *

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. + *

+ * + * @author Manish Motwani + * @version $Id: StructuredSyslogMessageProcessor.java,v 1.4 2011/01/11 05:11:13 cvs Exp $ + */ +public class StructuredSyslogMessageProcessor extends AbstractSyslogMessageProcessor { + private static final long serialVersionUID = -1563777226913475257L; + + public static String VERSION = "1"; + + private static final StructuredSyslogMessageProcessor INSTANCE = new StructuredSyslogMessageProcessor(); + protected static StructuredSyslogMessageProcessor defaultInstance = INSTANCE; + + private String applicationName = STRUCTURED_DATA_APP_NAME_DEFAULT_VALUE; + private String processId = STRUCTURED_DATA_PROCESS_ID_DEFAULT_VALUE; + + private DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); + + public static void setDefault(StructuredSyslogMessageProcessor messageProcessor) { + if (messageProcessor != null) { + defaultInstance = messageProcessor; + } + } + + public static StructuredSyslogMessageProcessor getDefault() { + return defaultInstance; + } + + public StructuredSyslogMessageProcessor() { + super(); + } + + public StructuredSyslogMessageProcessor(final String applicationName) { + super(); + this.applicationName = applicationName; + } + + public DateTimeFormatter getDateTimeFormatter() { + return dateTimeFormatter; + } + + public void setDateTimeFormatter(DateTimeFormatter dateTimeFormatter) { + this.dateTimeFormatter = dateTimeFormatter; + } + + public String getApplicationName() { + return this.applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public String getProcessId() { + return this.processId; + } + + public void setProcessId(String processId) { + this.processId = processId; + } + + public String createSyslogHeader(final int facility, final int level, String localName, final boolean sendLocalTimestamp, final boolean sendLocalName) { + final StringBuffer buffer = new StringBuffer(); + + appendPriority(buffer,facility,level); + buffer.append(VERSION); + buffer.append(' '); + + getDateTimeFormatter().printTo(buffer,System.currentTimeMillis()); + buffer.append(' '); + + appendLocalName(buffer,localName); + + buffer.append(StructuredSyslogMessage.nilProtect(this.applicationName)) + .append(' '); + + buffer.append(StructuredSyslogMessage.nilProtect(this.processId)).append(' '); + + return buffer.toString(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessage.java b/src/main/java/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessage.java new file mode 100644 index 0000000..2f71909 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessage.java @@ -0,0 +1,391 @@ +package org.productivity.java.syslog4j.impl.message.structured; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.impl.message.AbstractSyslogMessage; + +/** + * SyslogStructuredMessage extends AbstractSyslogMessage's ability to provide + * support for turning POJO (Plain Ol' Java Objects) into Syslog messages. It + * adds support for structured syslog messages as specified by + * draft-ietf-syslog-protocol-23. More information here: + * + *

+ * 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: StructuredSyslogMessage.java,v 1.5 2010/09/11 16:49:24 cvs Exp $ + */ +public class StructuredSyslogMessage extends AbstractSyslogMessage implements StructuredSyslogMessageIF { + private static final long serialVersionUID = 3669887659567965965L; + + private String messageId; + private Map structuredData; + private String message; + + private StructuredSyslogMessage() { + this.messageId = null; + this.message = null; + this.structuredData = null; + } + + /** + * Constructs the {@link StructuredSyslogMessage} using MSGID, + * STRUCTURED-DATA and MSG fields, as described in: + * + *

+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6 + *

+ * + * The Map must be a String -> (Map of String -> String), which encompasses + * the STRUCTURED-DATA field described in above document. + * + * @param messageId + * @param structuredData + * @param message + */ + public StructuredSyslogMessage(final String messageId, + final Map structuredData, final String message) { + super(); + this.messageId = messageId; + this.structuredData = structuredData; + this.message = message; + + ensureCorrectMapType(); + } + + private void ensureCorrectMapType() { + if (!(getStructuredData() == null)) { + Set sdEntrySet = getStructuredData().entrySet(); + for (Iterator it = sdEntrySet.iterator(); it.hasNext();) { + Map.Entry sdEntry = (Map.Entry) it.next(); + if (!(sdEntry.getKey() instanceof String)) { + throw new IllegalArgumentException( + "Structured data map must be a map of String -> (Map of String,String)"); + } + if (!(sdEntry.getValue() instanceof Map)) { + throw new IllegalArgumentException( + "Structured data map must be a map of String -> (Map of String,String)"); + } + + Set entrySet = ((Map) sdEntry.getValue()).entrySet(); + for (Iterator it2 = entrySet.iterator(); it2.hasNext();) { + Map.Entry entry = (Map.Entry) it2.next(); + + if (!(entry.getKey() instanceof String)) { + throw new IllegalArgumentException( + "Structured data map must be a map of String -> (Map of String,String)"); + } + if (!(entry.getValue() instanceof String)) { + throw new IllegalArgumentException( + "Structured data map must be a map of String -> (Map of String,String)"); + } + } + } + + } + } + + /** + * Parses and loads a {@link StructuredSyslogMessage} from string. + * + * @param syslogMessageStr + * @return Returns an instance of StructuredSyslogMessage. + */ + public static StructuredSyslogMessage fromString( + final String syslogMessageStr) { + final StructuredSyslogMessage syslogMessage = new StructuredSyslogMessage(); + syslogMessage.deserialize(syslogMessageStr); + return syslogMessage; + } + + private void deserialize(final String stringMessage) { + // Check correct format + if (stringMessage.indexOf('[') <= 0) + throw new IllegalArgumentException("Invalid Syslog string format: " + + stringMessage); + + // Divide the string in 2 sections + final String syslogHeader = stringMessage.substring(0, stringMessage + .indexOf('[')); + String structuredDataString = stringMessage.substring(stringMessage + .indexOf('['), stringMessage.lastIndexOf(']') + 1); + + if ((stringMessage.lastIndexOf(']') + 2) <= stringMessage.length()) + this.message = stringMessage.substring(stringMessage.lastIndexOf(']') + 2); + + else { + this.message = ""; + } + + // Split into tokens + final String[] tokens = syslogHeader.split(" "); + + // Check number of tokens must be 1 -- rest of the header should already + // be stripped + if (tokens.length != 1) { + throw new IllegalArgumentException("Invalid Syslog string format: " + + stringMessage); + } + + this.messageId = SyslogConstants.STRUCTURED_DATA_NILVALUE.equals(tokens[0]) ? null + : tokens[0]; + + this.structuredData = new HashMap(); + if (!SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE.equals(structuredDataString)) { + while (!"".equals(structuredDataString)) { + if (!structuredDataString.startsWith("[") + || structuredDataString.indexOf(']') == -1) { + throw new IllegalArgumentException( + "Invalid structured data format in Syslog message: " + + stringMessage); + } + + final String structuredDataIteration = structuredDataString + .substring(1, structuredDataString.indexOf(']')); + + final Map iterMap = new HashMap(); + + final String[] params = structuredDataIteration.split(" "); + + for (int i = 1; i < params.length; i++) { + final String[] paramIter = params[i].split("="); + if (paramIter.length != 2) { + throw new IllegalArgumentException( + "Invalid structured data format in Syslog message: " + + stringMessage); + } + + if (!paramIter[1].startsWith("\"") + || !paramIter[1].endsWith("\"")) { + throw new IllegalArgumentException( + "Invalid structured data format in Syslog message: " + + stringMessage); + } + + iterMap.put(paramIter[0], paramIter[1].substring(1, + paramIter[1].length() - 1)); + } + + this.structuredData.put(params[0], iterMap); + + if (structuredDataString.indexOf(']') != structuredDataString + .lastIndexOf(']')) { + structuredDataString = structuredDataString + .substring(structuredDataString.indexOf(']') + 1); + } else { + structuredDataString = ""; + } + } + } + } + + /** + * Returns the MSGID field of the structured message format, as described + * in: + * + *

+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6 + *

+ * + * @return Returns the MSG ID field. + */ + public String getMessageId() { + return this.messageId; + } + + /** + * Returns the structured data map. The Map is a String -> (Map of String -> + * String), which encompasses the STRUCTURED-DATA field, as described in: + * + *

+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6 + *

+ * + * @return Returns a Map object containing structured data. + */ + public Map getStructuredData() { + return this.structuredData; + } + + /** + * Returns the MSG field of the structured message format, as described in: + * + *

+ * http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6 + *

+ * + * @return Returns the MSG field. + */ + public String getMessage() { + return this.message; + } + + /* + * (non-Javadoc) + * + * @seeorg.productivity.java.syslog4j.impl.message.AbstractSyslogMessage# + * createMessage() + */ + public String createMessage() { + return serialize(); + } + + private String serialize() { + if (!StructuredSyslogMessage.checkIsPrintable(getMessageId())) + throw new IllegalArgumentException("Invalid message id: " + + getMessageId()); + + final StringBuffer sb = new StringBuffer(); + + sb.append(StructuredSyslogMessage.nilProtect(getMessageId())); + sb.append(' '); + + if (getStructuredData() == null || getStructuredData().size() == 0) { + // This is not desired, but rsyslogd does not store version 1 syslog + // message correctly if + // there is no + // structured data present + sb.append(SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE); + } else { + Set sdEntrySet = getStructuredData().entrySet(); + for (Iterator it = sdEntrySet.iterator(); it.hasNext();) { + final Map.Entry sdElement = (Map.Entry) it.next(); + final String sdId = (String) sdElement.getKey(); + + if (sdId == null || sdId.length() == 0 + || !StructuredSyslogMessage.checkIsPrintable(sdId)) { + throw new IllegalArgumentException( + "Illegal structured data id: " + sdId); + } + + sb.append('[').append(sdId); + + final Map sdParams = (Map) sdElement.getValue(); + + if (sdParams != null) { + Set entrySet = sdParams.entrySet(); + for (Iterator it2 = entrySet.iterator(); it2.hasNext();) { + Map.Entry entry = (Map.Entry) it2.next(); + final String paramName = (String) entry.getKey(); + final String paramValue = (String) entry.getValue(); + + if (paramName == null + || paramName.length() == 0 + || !StructuredSyslogMessage + .checkIsPrintable(paramName)) + throw new IllegalArgumentException( + "Illegal structured data parameter name: " + + paramName); + + if (paramValue == null) + throw new IllegalArgumentException( + "Null structured data parameter value for parameter name: " + + paramName); + + sb.append(' '); + sb.append(paramName); + sb.append('=').append('"'); + StructuredSyslogMessage.sdEscape(sb, paramValue); + sb.append('"'); + } + } + + sb.append(']'); + } + } + + if (getMessage() != null && getMessage().length() != 0) { + sb.append(' '); + sb.append(StructuredSyslogMessage.nilProtect(getMessage())); + } + + return sb.toString(); + + } + + public static void sdEscape(final StringBuffer sb, final String value) { + for (int i = 0; i < value.length(); i++) { + final char c = value.charAt(i); + + if (c == '"' || c == '\\' || c == ']') { + sb.append('\\'); + } + + sb.append(c); + } + } + + public static boolean checkIsPrintable(final String value) { + if (value == null) + return true; + + for (int i = 0; i < value.length(); i++) { + final char c = value.charAt(i); + + if (c < 33 || c > 126) + return false; + } + + return true; + } + + public static String nilProtect(final String value) { + if (value == null || value.trim().length() == 0) { + return SyslogConstants.STRUCTURED_DATA_NILVALUE; + } + + return value; + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((message == null) ? 0 : message.hashCode()); + result = prime * result + + ((messageId == null) ? 0 : messageId.hashCode()); + result = prime * result + + ((structuredData == null) ? 0 : structuredData.hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + StructuredSyslogMessage other = (StructuredSyslogMessage) obj; + + if (message == null) { + if (other.message != null) return false; + + } else if (!message.equals(other.message)) return false; + + if (messageId == null) { + if (other.messageId != null) return false; + + } else if (!messageId.equals(other.messageId)) return false; + + if (structuredData == null) { + if (other.structuredData != null) return false; + + } else if (!structuredData.equals(other.structuredData)) return false; + + return true; + } + + public String toString() { + return serialize(); + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessageIF.java b/src/main/java/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessageIF.java new file mode 100644 index 0000000..480120c --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessageIF.java @@ -0,0 +1,18 @@ +package org.productivity.java.syslog4j.impl.message.structured; + +import org.productivity.java.syslog4j.SyslogMessageIF; + +/** +* StructuredSyslogMessageIF is a "marker" interface to identify structured +* SyslogMessageIF 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: StructuredSyslogMessageIF.java,v 1.1 2009/07/22 15:54:23 cvs Exp $ +*/ +public interface StructuredSyslogMessageIF extends SyslogMessageIF { + // +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/multiple/MultipleSyslog.java b/src/main/java/org/productivity/java/syslog4j/impl/multiple/MultipleSyslog.java new file mode 100644 index 0000000..70e632f --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/multiple/MultipleSyslog.java @@ -0,0 +1,174 @@ +package org.productivity.java.syslog4j.impl.multiple; + +import org.productivity.java.syslog4j.Syslog; +import org.productivity.java.syslog4j.SyslogConfigIF; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogIF; +import org.productivity.java.syslog4j.SyslogMessageIF; +import org.productivity.java.syslog4j.SyslogMessageProcessorIF; +import org.productivity.java.syslog4j.SyslogRuntimeException; + +/** +* MultipleSyslog is an aggregator Syslog implementation for allowing a single +* Syslog call to send to multiple 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: MultipleSyslog.java,v 1.10 2010/02/11 05:00:55 cvs Exp $ +*/ +public class MultipleSyslog implements SyslogIF { + private static final long serialVersionUID = 587308197526365108L; + + protected String syslogProtocol = null; + protected MultipleSyslogConfig multipleSyslogConfig = null; + + public void initialize(String protocol, SyslogConfigIF config) throws SyslogRuntimeException { + this.syslogProtocol = protocol; + + try { + this.multipleSyslogConfig = (MultipleSyslogConfig) config; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must be of type MultipleSyslogConfig"); + } + } + + public SyslogConfigIF getConfig() { + return this.multipleSyslogConfig; + } + + public void debug(String message) { + log(SyslogConstants.LEVEL_DEBUG,message); + } + + public void debug(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_DEBUG,message); + } + + public void critical(String message) { + log(SyslogConstants.LEVEL_CRITICAL,message); + } + + public void critical(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_CRITICAL,message); + } + + public void error(String message) { + log(SyslogConstants.LEVEL_ERROR,message); + } + + public void error(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_ERROR,message); + } + + public void alert(String message) { + log(SyslogConstants.LEVEL_ALERT,message); + } + + public void alert(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_ALERT,message); + } + + public void notice(String message) { + log(SyslogConstants.LEVEL_NOTICE,message); + } + + public void notice(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_NOTICE,message); + } + + public void emergency(String message) { + log(SyslogConstants.LEVEL_EMERGENCY,message); + } + + public void emergency(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_EMERGENCY,message); + } + + public void info(String message) { + log(SyslogConstants.LEVEL_INFO,message); + } + + public void info(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_INFO,message); + } + + public void warn(String message) { + log(SyslogConstants.LEVEL_WARN,message); + } + + public void warn(SyslogMessageIF message) { + log(SyslogConstants.LEVEL_WARN,message); + } + + public void log(int level, String message) { + 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: MultipleSyslogConfig.java,v 1.8 2010/11/28 04:15:18 cvs Exp $ +*/ +public class MultipleSyslogConfig implements SyslogConfigIF { + private static final long serialVersionUID = 753704522364959612L; + + protected List syslogProtocols = null; + + public MultipleSyslogConfig() { + this.syslogProtocols = new ArrayList(); + } + + public MultipleSyslogConfig(List protocols) { + if (protocols != null) { + this.syslogProtocols = protocols; + + } else { + this.syslogProtocols = new ArrayList(); + } + } + + public MultipleSyslogConfig(String[] protocols) { + if (protocols != null) { + this.syslogProtocols = new ArrayList(protocols.length); + + 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: AbstractNetSyslog.java,v 1.7 2009/01/24 22:00:18 cvs Exp $ +*/ +public abstract class AbstractNetSyslog extends AbstractSyslog { + private static final long serialVersionUID = -3250858945515853967L; + + protected static final Object cachedHostAddressSyncObject = new Object(); + + protected InetAddress cachedHostAddress = null; + + protected AbstractNetSyslogConfigIF netSyslogConfig = null; + + protected void initialize() throws SyslogRuntimeException { + try { + this.netSyslogConfig = (AbstractNetSyslogConfigIF) this.syslogConfig; + + } catch (ClassCastException cce) { + throw new SyslogRuntimeException("config must implement interface AbstractNetSyslogConfigIF"); + } + } + + /** + * @return Returns an object of InetAddress of the local host, using caching if so directed. + */ + public InetAddress getHostAddress() { + InetAddress hostAddress = null; + + if (this.netSyslogConfig.isCacheHostAddress()) { + if (this.cachedHostAddress == null) { + synchronized(cachedHostAddressSyncObject) { + if (this.cachedHostAddress == null) { + this.cachedHostAddress = SyslogUtility.getInetAddress(this.syslogConfig.getHost()); + } + } + } + + hostAddress = this.cachedHostAddress; + + } else { + hostAddress = SyslogUtility.getInetAddress(this.syslogConfig.getHost()); + } + + return hostAddress; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfig.java b/src/main/java/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfig.java new file mode 100644 index 0000000..c829b70 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfig.java @@ -0,0 +1,85 @@ +package org.productivity.java.syslog4j.impl.net; + +import org.productivity.java.syslog4j.impl.AbstractSyslogConfig; + +/** +* AbstractNetSyslogConfig is an abstract extension of AbstractSyslogConfig +* that provides configuration support for network-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: 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 [-h ] [-p ] [-o ] [-a] [-q] "); + System.out.println(); + System.out.println("-h host or IP to bind"); + System.out.println("-p port to bind"); + System.out.println("-t socket timeout (in milliseconds)"); + System.out.println("-o file to write entries (overwrites by default)"); + System.out.println(); + System.out.println("-a append to file (instead of overwrite)"); + System.out.println("-q do not write anything to standard out"); + System.out.println(); + System.out.println("protocol Syslog4j protocol implementation (tcp, udp, ...)"); + } + + public static Options parseOptions(String[] args) { + Options options = new Options(); + + int i = 0; + while(i < args.length) { + String arg = args[i++]; + boolean match = false; + + if ("-h".equals(arg)) { if (i == args.length) { options.usage = "Must specify host with -h"; return options; } match = true; options.host = args[i++]; } + if ("-p".equals(arg)) { if (i == args.length) { options.usage = "Must specify port with -p"; return options; } match = true; options.port = args[i++]; } + if ("-t".equals(arg)) { if (i == args.length) { options.usage = "Must specify value (in milliseconds)"; return options; } match = true; options.timeout = args[i++]; } + if ("-o".equals(arg)) { if (i == args.length) { options.usage = "Must specify file with -o"; return options; } match = true; options.fileName = args[i++]; } + + if ("-a".equals(arg)) { match = true; options.append = true; } + if ("-q".equals(arg)) { match = true; options.quiet = true; } + + if (!match) { + if (options.protocol != null) { + options.usage = "Only one protocol definition allowed"; + return options; + } + + options.protocol = arg; + } + } + + if (options.protocol == null) { + options.usage = "Must specify protocol"; + return options; + } + + if (options.fileName == null && options.append) { + options.usage = "Cannot specify -a without specifying -f "; + return options; + } + + return options; + } + + public static void main(String[] args) throws Exception { + Options options = parseOptions(args); + + if (options.usage != null) { + usage(options.usage); + if (CALL_SYSTEM_EXIT_ON_FAILURE) { System.exit(1); } else { return; } + } + + if (!options.quiet) { + System.out.println("SyslogServer " + SyslogServer.getVersion()); + } + + if (!SyslogServer.exists(options.protocol)) { + usage("Protocol \"" + options.protocol + "\" not supported"); + if (CALL_SYSTEM_EXIT_ON_FAILURE) { System.exit(1); } else { return; } + } + + SyslogServerIF syslogServer = SyslogServer.getInstance(options.protocol); + + SyslogServerConfigIF syslogServerConfig = syslogServer.getConfig(); + + if (options.host != null) { + syslogServerConfig.setHost(options.host); + if (!options.quiet) { + System.out.println("Listening on host: " + options.host); + } + } + + if (options.port != null) { + syslogServerConfig.setPort(Integer.parseInt(options.port)); + if (!options.quiet) { + System.out.println("Listening on port: " + options.port); + } + } + + if (options.timeout != null) { + if (syslogServerConfig instanceof TCPNetSyslogServerConfigIF) { + ((TCPNetSyslogServerConfigIF) syslogServerConfig).setTimeout(Integer.parseInt(options.timeout)); + if (!options.quiet) { + System.out.println("Timeout: " + options.timeout); + } + + } else { + System.err.println("Timeout not supported for protocol \"" + options.protocol + "\" (ignored)"); + } + } + + if (options.fileName != null) { + SyslogServerEventHandlerIF eventHandler = new FileSyslogServerEventHandler(options.fileName,options.append); + syslogServerConfig.addEventHandler(eventHandler); + if (!options.quiet) { + System.out.println((options.append ? "Appending" : "Writing") + " to file: " + options.fileName); + } + } + + if (!options.quiet) { + SyslogServerEventHandlerIF eventHandler = SystemOutSyslogServerEventHandler.create(); + syslogServerConfig.addEventHandler(eventHandler); + } + + if (!options.quiet) { + System.out.println(); + } + + SyslogServer.getThreadedInstance(options.protocol); + + while(true) { + SyslogUtility.sleep(1000); + } + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerSessionEventHandlerIF.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerSessionEventHandlerIF.java new file mode 100644 index 0000000..f1b7374 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerSessionEventHandlerIF.java @@ -0,0 +1,10 @@ +package org.productivity.java.syslog4j.server; + +import java.net.SocketAddress; + +public interface SyslogServerSessionEventHandlerIF extends SyslogServerEventHandlerIF { + public Object sessionOpened(SyslogServerIF syslogServer, SocketAddress socketAddress); + public void event(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, SyslogServerEventIF event); + public void exception(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, Exception exception); + public void sessionClosed(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, boolean timeout); +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/SyslogServerSessionlessEventHandlerIF.java b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerSessionlessEventHandlerIF.java new file mode 100644 index 0000000..e9c2bb2 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/SyslogServerSessionlessEventHandlerIF.java @@ -0,0 +1,20 @@ +package org.productivity.java.syslog4j.server; + +import java.net.SocketAddress; + + +/** +* SyslogServerEventHandlerIF provides an extensible interface for Syslog4j +* server event handlers. +* +*

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: 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 the , return true. + if (receiveData.length() > idx + 1 && Character.isDigit(receiveData.charAt(idx + 1))) { + return true; + } + } + + return false; + } + + protected static SyslogServerEventIF createEvent(SyslogServerConfigIF serverConfig, byte[] lineBytes, int lineBytesLength, InetAddress inetAddr) { + SyslogServerEventIF event = null; + + if (serverConfig.isUseStructuredData() && AbstractSyslogServer.isStructuredMessage(serverConfig,lineBytes)) { + event = new StructuredSyslogServerEvent(lineBytes,lineBytesLength,inetAddr); + + if (serverConfig.getDateTimeFormatter() != null) { + ((StructuredSyslogServerEvent) event).setDateTimeFormatter(serverConfig.getDateTimeFormatter()); + } + + } else { + event = new SyslogServerEvent(lineBytes,lineBytesLength,inetAddr); + } + + return event; + } + + protected static SyslogServerEventIF createEvent(SyslogServerConfigIF serverConfig, String line, InetAddress inetAddr) { + SyslogServerEventIF event = null; + + if (serverConfig.isUseStructuredData() && AbstractSyslogServer.isStructuredMessage(serverConfig,line)) { + event = new StructuredSyslogServerEvent(line,inetAddr); + + } else { + event = new SyslogServerEvent(line,inetAddr); + } + + return event; + } + + public static void handleInitialize(SyslogServerIF syslogServer) { + List eventHandlers = syslogServer.getConfig().getEventHandlers(); + + 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: AbstractSyslogServerConfig.java,v 1.9 2011/01/11 05:11:13 cvs Exp $ +*/ +public abstract class AbstractSyslogServerConfig implements SyslogServerConfigIF { + private static final long serialVersionUID = 870248648801259856L; + + public abstract Class getSyslogServerClass(); + + protected String charSet = CHAR_SET_DEFAULT; + + protected long shutdownWait = SyslogConstants.SERVER_SHUTDOWN_WAIT_DEFAULT; + + protected List eventHandlers = new ArrayList(); + + protected boolean useStructuredData = USE_STRUCTURED_DATA_DEFAULT; + + protected Object dateTimeFormatter = null; + + protected boolean useDaemonThread = USE_DAEMON_THREAD_DEFAULT; + protected int threadPriority = THREAD_PRIORITY_DEFAULT; + + public String getCharSet() { + return this.charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } + + public long getShutdownWait() { + return this.shutdownWait; + } + + public void setShutdownWait(long shutdownWait) { + this.shutdownWait = shutdownWait; + } + + public List getEventHandlers() { + return this.eventHandlers; + } + + public void addEventHandler(SyslogServerEventHandlerIF eventHandler) { + this.eventHandlers.add(eventHandler); + } + + public void insertEventHandler(int pos, SyslogServerEventHandlerIF eventHandler) { + this.eventHandlers.add(pos, eventHandler); + } + + public void removeEventHandler(SyslogServerEventHandlerIF eventHandler) { + this.eventHandlers.remove(eventHandler); + } + + public void removeAllEventHandlers() { + this.eventHandlers.clear(); + } + + public boolean isUseStructuredData() { + return useStructuredData; + } + + public void setUseStructuredData(boolean useStructuredData) { + this.useStructuredData = useStructuredData; + } + + public boolean isUseDaemonThread() { + return useDaemonThread; + } + + public Object getDateTimeFormatter() { + return dateTimeFormatter; + } + + public void setDateTimeFormatter(Object dateTimeFormatter) { + this.dateTimeFormatter = dateTimeFormatter; + } + + public void setUseDaemonThread(boolean useDaemonThread) { + this.useDaemonThread = useDaemonThread; + } + + public int getThreadPriority() { + return threadPriority; + } + + public void setThreadPriority(int threadPriority) { + this.threadPriority = threadPriority; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/server/impl/event/SyslogServerEvent.java b/src/main/java/org/productivity/java/syslog4j/server/impl/event/SyslogServerEvent.java new file mode 100644 index 0000000..bd63bde --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/server/impl/event/SyslogServerEvent.java @@ -0,0 +1,213 @@ +package org.productivity.java.syslog4j.server.impl.event; + +import java.net.InetAddress; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.server.SyslogServerEventIF; +import org.productivity.java.syslog4j.util.SyslogUtility; + +/** +* SyslogServerEvent provides an implementation of the SyslogServerEventIF 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: 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: + *

+ *
    + *
  • [Small code cleanup/fixes for inclusion into Syslog4j]
  • + *
  • v2.2.2 - Fixed encodeFileToFile and decodeFileToFile to use the + * Base64.InputStream class to encode and decode on the fly which uses + * less memory than encoding/decoding an entire file into memory before writing.
  • + *
  • v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug + * when using very small files (~< 40 bytes).
  • + *
  • v2.2 - Added some helper methods for encoding/decoding directly from + * one file to the next. Also added a main() method to support command line + * encoding/decoding from one file to the next. Also added these Base64 dialects: + *
      + *
    1. The default is RFC3548 format.
    2. + *
    3. Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates + * URL and file name friendly format as described in Section 4 of RFC3548. + * http://www.faqs.org/rfcs/rfc3548.html
    4. + *
    5. Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates + * URL and file name friendly format that preserves lexical ordering as described + * in http://www.faqs.org/qa/rfcc-1940.html
    6. + *
    + * Special thanks to Jim Kellerman at http://www.powerset.com/ + * for contributing the new Base64 dialects. + *
  • + * + *
  • v2.1 - Cleaned up javadoc comments and unused variables and methods. Added + * some convenience methods for reading and writing to and from files.
  • + *
  • v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems + * with other encodings (like EBCDIC).
  • + *
  • v2.0.1 - Fixed an error when decoding a single byte, that is, when the + * encoded data was a single byte.
  • + *
  • v2.0 - I got rid of methods that used booleans to set options. + * Now everything is more consolidated and cleaner. The code now detects + * when data that's being decoded is gzip-compressed and will decompress it + * automatically. Generally things are cleaner. You'll probably have to + * change some method calls that you were making to support the new + * options format (ints that you "OR" together).
  • + *
  • v1.5.1 - Fixed bug when decompressing and decoding to a + * byte[] using decode( String s, boolean gzipCompressed ). + * Added the ability to "suspend" encoding in the Output Stream so + * you can turn on and off the encoding if you need to embed base64 + * data in an otherwise "normal" stream (like an XML file).
  • + *
  • v1.5 - Output stream pases on flush() command but doesn't do anything itself. + * This helps when using GZIP streams. + * Added the ability to GZip-compress objects before encoding them.
  • + *
  • v1.4 - Added helper methods to read/write files.
  • + *
  • v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.
  • + *
  • v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream + * where last buffer being read, if not completely full, was not returned.
  • + *
  • v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.
  • + *
  • v1.3.3 - Fixed I/O streams which were totally messed up.
  • + *
+ * + *

+ * 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; i -1) { + match = true; + break; + } + } + } + + return match; + } + + static { + UNIX = isMatch(UNIX_PLATFORMS); + WINDOWS = isMatch(WINDOWS_PLATFORMS); + } + + public static boolean isUnix() { + return UNIX; + } + + public static boolean isWindows() { + return WINDOWS; + } +} diff --git a/src/main/java/org/productivity/java/syslog4j/util/SyslogUtility.java b/src/main/java/org/productivity/java/syslog4j/util/SyslogUtility.java new file mode 100644 index 0000000..0ee5aa7 --- /dev/null +++ b/src/main/java/org/productivity/java/syslog4j/util/SyslogUtility.java @@ -0,0 +1,208 @@ +package org.productivity.java.syslog4j.util; + +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.productivity.java.syslog4j.SyslogCharSetIF; +import org.productivity.java.syslog4j.SyslogConstants; +import org.productivity.java.syslog4j.SyslogRuntimeException; + +/** +* SyslogUtility provides several common utility methods used within +* Syslog4j. +* +*

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: 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 0000000..ef637f1 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/Syslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/Syslog4jVersion.class b/target/classes/org/productivity/java/syslog4j/Syslog4jVersion.class new file mode 100644 index 0000000..8ee1177 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/Syslog4jVersion.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogBackLogHandlerIF.class b/target/classes/org/productivity/java/syslog4j/SyslogBackLogHandlerIF.class new file mode 100644 index 0000000..11b49ed Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogBackLogHandlerIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogCharSetIF.class b/target/classes/org/productivity/java/syslog4j/SyslogCharSetIF.class new file mode 100644 index 0000000..7cfed83 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogCharSetIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogConfigIF.class b/target/classes/org/productivity/java/syslog4j/SyslogConfigIF.class new file mode 100644 index 0000000..8436b78 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogConstants.class b/target/classes/org/productivity/java/syslog4j/SyslogConstants.class new file mode 100644 index 0000000..ff9cc01 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogConstants.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogIF.class b/target/classes/org/productivity/java/syslog4j/SyslogIF.class new file mode 100644 index 0000000..3cb56ea Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogMain$Options.class b/target/classes/org/productivity/java/syslog4j/SyslogMain$Options.class new file mode 100644 index 0000000..bbaedb9 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogMain$Options.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogMain.class b/target/classes/org/productivity/java/syslog4j/SyslogMain.class new file mode 100644 index 0000000..52f8f44 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogMain.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogMessageIF.class b/target/classes/org/productivity/java/syslog4j/SyslogMessageIF.class new file mode 100644 index 0000000..89572ff Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogMessageIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogMessageModifierConfigIF.class b/target/classes/org/productivity/java/syslog4j/SyslogMessageModifierConfigIF.class new file mode 100644 index 0000000..43d31df Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogMessageModifierConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogMessageModifierIF.class b/target/classes/org/productivity/java/syslog4j/SyslogMessageModifierIF.class new file mode 100644 index 0000000..7b67d0c Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogMessageModifierIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogMessageProcessorIF.class b/target/classes/org/productivity/java/syslog4j/SyslogMessageProcessorIF.class new file mode 100644 index 0000000..426bf36 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogMessageProcessorIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogPoolConfigIF.class b/target/classes/org/productivity/java/syslog4j/SyslogPoolConfigIF.class new file mode 100644 index 0000000..4e8c1b3 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogPoolConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/SyslogRuntimeException.class b/target/classes/org/productivity/java/syslog4j/SyslogRuntimeException.class new file mode 100644 index 0000000..b8f1519 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/SyslogRuntimeException.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslog.class new file mode 100644 index 0000000..4d4d64b Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogConfig.class new file mode 100644 index 0000000..2acdb13 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogConfig.class differ 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 0000000..6000938 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogConfigIF.class differ 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 0000000..a065dc2 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/AbstractSyslogWriter.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/AbstractSyslogBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/AbstractSyslogBackLogHandler.class new file mode 100644 index 0000000..2448297 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/AbstractSyslogBackLogHandler.class differ 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 0000000..511e9bd Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/NullSyslogBackLogHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/backlog/Syslog4jBackLogHandler.class b/target/classes/org/productivity/java/syslog4j/impl/backlog/Syslog4jBackLogHandler.class new file mode 100644 index 0000000..083128f Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/Syslog4jBackLogHandler.class differ 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 0000000..0ed81a7 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/log4j/Log4jSyslogBackLogHandler.class differ 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 0000000..2c8dd04 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/PrintStreamSyslogBackLogHandler.class differ 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 0000000..5147ac2 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/SystemErrSyslogBackLogHandler.class differ 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 0000000..79484a1 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/backlog/printstream/SystemOutSyslogBackLogHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppender.class b/target/classes/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppender.class new file mode 100644 index 0000000..4ae888c Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppender.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppenderSkeleton.class b/target/classes/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppenderSkeleton.class new file mode 100644 index 0000000..c351c1f Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/log4j/Syslog4jAppenderSkeleton.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/AbstractSyslogMessage.class b/target/classes/org/productivity/java/syslog4j/impl/message/AbstractSyslogMessage.class new file mode 100644 index 0000000..051fb11 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/AbstractSyslogMessage.class differ 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 0000000..c196000 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifier.class differ 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 0000000..0cbd781 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/AbstractSyslogMessageModifierConfig.class differ 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 0000000..f4bcd77 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifierConfig.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifierConfig.class new file mode 100644 index 0000000..e5476d7 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/checksum/ChecksumSyslogMessageModifierConfig.class differ 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 0000000..11b7379 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/escape/HTMLEntityEscapeSyslogMessageModifier.class differ 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 0000000..1558d3f Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifierConfig.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifierConfig.class new file mode 100644 index 0000000..e7566c4 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/hash/HashSyslogMessageModifierConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifier.class new file mode 100644 index 0000000..e8886a7 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifierConfig.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifierConfig.class new file mode 100644 index 0000000..57d3fa3 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/mac/MacSyslogMessageModifierConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifier.class new file mode 100644 index 0000000..a0cb415 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifierConfig.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifierConfig.class new file mode 100644 index 0000000..0abde74 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/sequential/SequentialSyslogMessageModifierConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/PrefixSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/PrefixSyslogMessageModifier.class new file mode 100644 index 0000000..de0a2dc Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/PrefixSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/StringCaseSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/StringCaseSyslogMessageModifier.class new file mode 100644 index 0000000..9a8ae95 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/StringCaseSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/SuffixSyslogMessageModifier.class b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/SuffixSyslogMessageModifier.class new file mode 100644 index 0000000..3cc7e24 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/modifier/text/SuffixSyslogMessageModifier.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessage.class b/target/classes/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessage.class new file mode 100644 index 0000000..e6f8d87 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessage.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessageIF.class b/target/classes/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessageIF.class new file mode 100644 index 0000000..8fc7437 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/pci/PCISyslogMessageIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/processor/AbstractSyslogMessageProcessor.class b/target/classes/org/productivity/java/syslog4j/impl/message/processor/AbstractSyslogMessageProcessor.class new file mode 100644 index 0000000..ef40679 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/processor/AbstractSyslogMessageProcessor.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/processor/SyslogMessageProcessor.class b/target/classes/org/productivity/java/syslog4j/impl/message/processor/SyslogMessageProcessor.class new file mode 100644 index 0000000..219a129 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/processor/SyslogMessageProcessor.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/processor/structured/StructuredSyslogMessageProcessor.class b/target/classes/org/productivity/java/syslog4j/impl/message/processor/structured/StructuredSyslogMessageProcessor.class new file mode 100644 index 0000000..00a3f37 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/processor/structured/StructuredSyslogMessageProcessor.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessage.class b/target/classes/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessage.class new file mode 100644 index 0000000..95f1fd5 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessage.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessageIF.class b/target/classes/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessageIF.class new file mode 100644 index 0000000..faaf1b7 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/message/structured/StructuredSyslogMessageIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/multiple/MultipleSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/multiple/MultipleSyslog.class new file mode 100644 index 0000000..258f79a Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/multiple/MultipleSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/multiple/MultipleSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/multiple/MultipleSyslogConfig.class new file mode 100644 index 0000000..5bcb186 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/multiple/MultipleSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslog.class new file mode 100644 index 0000000..b582da1 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfig.class new file mode 100644 index 0000000..0e0b90a Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfigIF.class b/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfigIF.class new file mode 100644 index 0000000..06fcb98 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/AbstractNetSyslogConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslog.class new file mode 100644 index 0000000..256d1c7 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfig.class new file mode 100644 index 0000000..d21413b Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfigIF.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfigIF.class new file mode 100644 index 0000000..bcd9463 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogWriter.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogWriter.class new file mode 100644 index 0000000..1f2e61b Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/TCPNetSyslogWriter.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslog.class new file mode 100644 index 0000000..04f4045 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslogConfig.class new file mode 100644 index 0000000..5a1475c Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/pool/PooledTCPNetSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslog.class new file mode 100644 index 0000000..e1f3ff5 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfig.class new file mode 100644 index 0000000..535131e Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfigIF.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfigIF.class new file mode 100644 index 0000000..a4c80e8 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogWriter.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogWriter.class new file mode 100644 index 0000000..c3adf49 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/SSLTCPNetSyslogWriter.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/pool/PooledSSLTCPNetSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/pool/PooledSSLTCPNetSyslogConfig.class new file mode 100644 index 0000000..bbbabc4 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/tcp/ssl/pool/PooledSSLTCPNetSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslog.class new file mode 100644 index 0000000..731eaaa Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslogConfig.class new file mode 100644 index 0000000..3e9b0ca Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/net/udp/UDPNetSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/pool/AbstractSyslogPoolFactory.class b/target/classes/org/productivity/java/syslog4j/impl/pool/AbstractSyslogPoolFactory.class new file mode 100644 index 0000000..38cb3ca Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/pool/AbstractSyslogPoolFactory.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/pool/generic/GenericSyslogPoolFactory.class b/target/classes/org/productivity/java/syslog4j/impl/pool/generic/GenericSyslogPoolFactory.class new file mode 100644 index 0000000..07fc357 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/pool/generic/GenericSyslogPoolFactory.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslog$CLibrary.class b/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslog$CLibrary.class new file mode 100644 index 0000000..5307cf4 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslog$CLibrary.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslog.class new file mode 100644 index 0000000..3329554 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslogConfig.class new file mode 100644 index 0000000..4e15762 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/UnixSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog$CLibrary.class b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog$CLibrary.class new file mode 100644 index 0000000..3930ec8 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog$CLibrary.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog$SockAddr.class b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog$SockAddr.class new file mode 100644 index 0000000..aba04c3 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog$SockAddr.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog.class b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog.class new file mode 100644 index 0000000..0fdd077 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslog.class differ diff --git a/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslogConfig.class b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslogConfig.class new file mode 100644 index 0000000..6aace1d Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/impl/unix/socket/UnixSocketSyslogConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServer.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServer.class new file mode 100644 index 0000000..1744168 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServer.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerConfigIF.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerConfigIF.class new file mode 100644 index 0000000..3ec69f7 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerEventHandlerIF.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerEventHandlerIF.class new file mode 100644 index 0000000..a8ee304 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerEventHandlerIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerEventIF.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerEventIF.class new file mode 100644 index 0000000..40a1e88 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerEventIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerIF.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerIF.class new file mode 100644 index 0000000..f0b1a48 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerMain$Options.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerMain$Options.class new file mode 100644 index 0000000..962b9d3 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerMain$Options.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerMain.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerMain.class new file mode 100644 index 0000000..b2acc3b Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerMain.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerSessionEventHandlerIF.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerSessionEventHandlerIF.class new file mode 100644 index 0000000..560accd Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerSessionEventHandlerIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/SyslogServerSessionlessEventHandlerIF.class b/target/classes/org/productivity/java/syslog4j/server/SyslogServerSessionlessEventHandlerIF.class new file mode 100644 index 0000000..7a8c8f1 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/SyslogServerSessionlessEventHandlerIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer$Sessions.class b/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer$Sessions.class new file mode 100644 index 0000000..1ec6d3c Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer$Sessions.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer.class b/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer.class new file mode 100644 index 0000000..c9e8901 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServer.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServerConfig.class b/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServerConfig.class new file mode 100644 index 0000000..c6799e8 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/AbstractSyslogServerConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/event/SyslogServerEvent.class b/target/classes/org/productivity/java/syslog4j/server/impl/event/SyslogServerEvent.class new file mode 100644 index 0000000..789318c Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/event/SyslogServerEvent.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/FileSyslogServerEventHandler.class b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/FileSyslogServerEventHandler.class new file mode 100644 index 0000000..c4dcb20 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/FileSyslogServerEventHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/PrintStreamSyslogServerEventHandler.class b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/PrintStreamSyslogServerEventHandler.class new file mode 100644 index 0000000..3c79c0e Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/PrintStreamSyslogServerEventHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/SystemErrSyslogServerEventHandler.class b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/SystemErrSyslogServerEventHandler.class new file mode 100644 index 0000000..5a91bf5 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/SystemErrSyslogServerEventHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/SystemOutSyslogServerEventHandler.class b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/SystemOutSyslogServerEventHandler.class new file mode 100644 index 0000000..46b616e Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/event/printstream/SystemOutSyslogServerEventHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/event/structured/StructuredSyslogServerEvent.class b/target/classes/org/productivity/java/syslog4j/server/impl/event/structured/StructuredSyslogServerEvent.class new file mode 100644 index 0000000..d7db926 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/event/structured/StructuredSyslogServerEvent.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/AbstractNetSyslogServerConfig.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/AbstractNetSyslogServerConfig.class new file mode 100644 index 0000000..e3a24d8 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/AbstractNetSyslogServerConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer$TCPNetSyslogSocketHandler.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer$TCPNetSyslogSocketHandler.class new file mode 100644 index 0000000..176180b Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer$TCPNetSyslogSocketHandler.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer.class new file mode 100644 index 0000000..6b8ca90 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServer.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfig.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfig.class new file mode 100644 index 0000000..beda12a Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfigIF.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfigIF.class new file mode 100644 index 0000000..299025a Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/TCPNetSyslogServerConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServer.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServer.class new file mode 100644 index 0000000..9c8e4c0 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServer.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfig.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfig.class new file mode 100644 index 0000000..e25a1cc Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfigIF.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfigIF.class new file mode 100644 index 0000000..d2bc099 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/tcp/ssl/SSLTCPNetSyslogServerConfigIF.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServer.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServer.class new file mode 100644 index 0000000..6da1637 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServer.class differ diff --git a/target/classes/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServerConfig.class b/target/classes/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServerConfig.class new file mode 100644 index 0000000..ea6db62 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/server/impl/net/udp/UDPNetSyslogServerConfig.class differ diff --git a/target/classes/org/productivity/java/syslog4j/util/Base64$InputStream.class b/target/classes/org/productivity/java/syslog4j/util/Base64$InputStream.class new file mode 100644 index 0000000..1153c51 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/util/Base64$InputStream.class differ diff --git a/target/classes/org/productivity/java/syslog4j/util/Base64$OutputStream.class b/target/classes/org/productivity/java/syslog4j/util/Base64$OutputStream.class new file mode 100644 index 0000000..293a22d Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/util/Base64$OutputStream.class differ diff --git a/target/classes/org/productivity/java/syslog4j/util/Base64.class b/target/classes/org/productivity/java/syslog4j/util/Base64.class new file mode 100644 index 0000000..0a7fece Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/util/Base64.class differ diff --git a/target/classes/org/productivity/java/syslog4j/util/OSDetectUtility.class b/target/classes/org/productivity/java/syslog4j/util/OSDetectUtility.class new file mode 100644 index 0000000..40187b2 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/util/OSDetectUtility.class differ diff --git a/target/classes/org/productivity/java/syslog4j/util/SyslogUtility.class b/target/classes/org/productivity/java/syslog4j/util/SyslogUtility.class new file mode 100644 index 0000000..c574eb0 Binary files /dev/null and b/target/classes/org/productivity/java/syslog4j/util/SyslogUtility.class differ diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 0000000..e903f05 --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Tue Feb 19 00:49:45 CET 2013 +version=0.9.48-graylog2 +groupId=org.productivity.java +artifactId=syslog4j-graylog2 diff --git a/target/syslog4j-graylog2-0.9.48-graylog2.jar b/target/syslog4j-graylog2-0.9.48-graylog2.jar new file mode 100644 index 0000000..81a5113 Binary files /dev/null and b/target/syslog4j-graylog2-0.9.48-graylog2.jar differ