package org.graylog2.syslog4j.impl.unix.socket; import java.nio.ByteBuffer; import java.util.Collections; import java.util.List; import org.graylog2.syslog4j.SyslogRuntimeException; import org.graylog2.syslog4j.impl.AbstractSyslog; import org.graylog2.syslog4j.impl.AbstractSyslogWriter; import org.graylog2.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. * <p/> * <p>This class requires the JNA (Java Native Access) library to directly * access the native C libraries utilized on Unix platforms.</p> * <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: 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); } @Override protected List getFieldOrder() { return Collections.emptyList(); } } 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) { // } }