package org.graylog2.syslog4j;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.graylog2.syslog4j.impl.net.tcp.TCPNetSyslogConfig;
import org.graylog2.syslog4j.impl.net.udp.UDPNetSyslogConfig;
import org.graylog2.syslog4j.impl.unix.UnixSyslogConfig;
import org.graylog2.syslog4j.impl.unix.socket.UnixSocketSyslogConfig;
import org.graylog2.syslog4j.util.OSDetectUtility;
import org.graylog2.syslog4j.util.SyslogUtility;
/**
* This class provides a Singleton interface for Syslog4j client implementations.
* <p/>
* <p>Usage examples:</p>
* <p/>
* <b>Direct</b>
* <pre>
* Syslog.getInstance("udp").info("log message");
* </pre>
* <p/>
* <b>Via Instance</b>
* <pre>
* SyslogIF syslog = Syslog.getInstance("udp");
* syslog.info();
* </pre>
* <p/>
* <p>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.</p>
*
* @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.
* <p/>
* <p>First, create an implementation of SyslogConfigIF, such as UdpNetSyslogConfig.</p>
* <p/>
* <p>Second, configure that configuration instance.</p>
* <p/>
* <p>Third, call createInstance(protocol,config) using a short & simple
* String for the protocol argument.</p>
* <p/>
* <p>Fourth, either use the returned instance of SyslogIF, or in later code
* call getInstance(protocol) with the protocol chosen in the previous step.</p>
*
* @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);
}
}