package org.graylog2.syslog4j.impl; import org.graylog2.syslog4j.SyslogBackLogHandlerIF; import org.graylog2.syslog4j.SyslogConfigIF; import org.graylog2.syslog4j.SyslogIF; import org.graylog2.syslog4j.SyslogMessageIF; import org.graylog2.syslog4j.SyslogMessageModifierIF; import org.graylog2.syslog4j.SyslogMessageProcessorIF; import org.graylog2.syslog4j.SyslogRuntimeException; import org.graylog2.syslog4j.impl.message.processor.SyslogMessageProcessor; import org.graylog2.syslog4j.impl.message.processor.structured.StructuredSyslogMessageProcessor; import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessage; import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessageIF; import org.graylog2.syslog4j.util.SyslogUtility; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * 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 < this.notifiedBackLogHandlers.size(); i++) { SyslogBackLogHandlerIF backLogHandler = (SyslogBackLogHandlerIF) this.notifiedBackLogHandlers.get(i); backLogHandler.up(this); } this.notifiedBackLogHandlers.clear(); } this.backLogStatus = backLogStatus; } } } public void initialize(String protocol, SyslogConfigIF config) throws SyslogRuntimeException { this.syslogProtocol = protocol; try { this.syslogConfig = (AbstractSyslogConfigIF) config; } catch (ClassCastException cce) { throw new SyslogRuntimeException("provided config must implement AbstractSyslogConfigIF"); } initialize(); } public SyslogMessageProcessorIF getMessageProcessor() { if (this.syslogMessageProcessor == null) { this.syslogMessageProcessor = SyslogMessageProcessor.getDefault(); } return this.syslogMessageProcessor; } public SyslogMessageProcessorIF getStructuredMessageProcessor() { if (this.structuredSyslogMessageProcessor == null) { this.structuredSyslogMessageProcessor = StructuredSyslogMessageProcessor.getDefault(); } return this.structuredSyslogMessageProcessor; } public void setMessageProcessor(SyslogMessageProcessorIF messageProcessor) { this.syslogMessageProcessor = messageProcessor; } public void setStructuredMessageProcessor(SyslogMessageProcessorIF messageProcessor) { this.structuredSyslogMessageProcessor = messageProcessor; } public String getProtocol() { return this.syslogProtocol; } public SyslogConfigIF getConfig() { return this.syslogConfig; } public void log(int level, String message) { if (this.syslogConfig.isUseStructuredData()) { StructuredSyslogMessageIF structuredMessage = new StructuredSyslogMessage(null, null, null, message); log(getStructuredMessageProcessor(), level, structuredMessage.createMessage()); } else { log(getMessageProcessor(), level, message); } } public void log(int level, String message, Date datetime) { if (this.syslogConfig.isUseStructuredData()) { StructuredSyslogMessageIF structuredMessage = new StructuredSyslogMessage(null, null, null, message); log(getStructuredMessageProcessor(), level, structuredMessage.createMessage(), datetime); } else { log(getMessageProcessor(), level, message, datetime); } } public void log(int level, SyslogMessageIF message) { if (message instanceof StructuredSyslogMessageIF) { if (getMessageProcessor() instanceof StructuredSyslogMessageProcessor) { log(getMessageProcessor(), level, message.createMessage()); } else { log(getStructuredMessageProcessor(), level, message.createMessage()); } } else { log(getMessageProcessor(), level, message.createMessage()); } } public void debug(String message) { log(LEVEL_DEBUG, message); } public void notice(String message) { log(LEVEL_NOTICE, message); } public void info(String message) { log(LEVEL_INFO, message); } public void warn(String message) { log(LEVEL_WARN, message); } public void error(String message) { log(LEVEL_ERROR, message); } public void critical(String message) { log(LEVEL_CRITICAL, message); } public void alert(String message) { log(LEVEL_ALERT, message); } public void emergency(String message) { log(LEVEL_EMERGENCY, message); } public void debug(SyslogMessageIF message) { log(LEVEL_DEBUG, message); } public void notice(SyslogMessageIF message) { log(LEVEL_NOTICE, message); } public void info(SyslogMessageIF message) { log(LEVEL_INFO, message); } public void warn(SyslogMessageIF message) { log(LEVEL_WARN, message); } public void error(SyslogMessageIF message) { log(LEVEL_ERROR, message); } public void critical(SyslogMessageIF message) { log(LEVEL_CRITICAL, message); } public void alert(SyslogMessageIF message) { log(LEVEL_ALERT, message); } public void emergency(SyslogMessageIF message) { log(LEVEL_EMERGENCY, message); } protected String prefixMessage(String message, String suffix) { String ident = this.syslogConfig.getIdent(); String _message = ((ident == null || "".equals(ident.trim())) ? "" : (ident + suffix)) + message; return _message; } public void log(SyslogMessageProcessorIF messageProcessor, int level, String message) { String _message = null; if (this.syslogConfig.isIncludeIdentInMessageModifier()) { _message = prefixMessage(message, IDENT_SUFFIX_DEFAULT); _message = modifyMessage(level, _message); } else { _message = modifyMessage(level, message); _message = prefixMessage(_message, IDENT_SUFFIX_DEFAULT); } try { String header = messageProcessor.createSyslogHeader(this.syslogConfig.getFacility(), level, this.syslogConfig.getLocalName(), this.syslogConfig.isSendLocalTimestamp(), this.syslogConfig.isSendLocalName()); write(messageProcessor, level, _message, header); } catch (SyslogRuntimeException sre) { if (sre.getCause() != null) { backLog(level, _message, sre.getCause()); } else { backLog(level, _message, sre); } if (this.syslogConfig.isThrowExceptionOnWrite()) { throw sre; } } } public void log(SyslogMessageProcessorIF messageProcessor, int level, String message, Date datetime) { String _message = null; if (this.syslogConfig.isIncludeIdentInMessageModifier()) { _message = prefixMessage(message, IDENT_SUFFIX_DEFAULT); _message = modifyMessage(level, _message); } else { _message = modifyMessage(level, message); _message = prefixMessage(_message, IDENT_SUFFIX_DEFAULT); } try { String header = messageProcessor.createSyslogHeader(this.syslogConfig.getFacility(), level, this.syslogConfig.getLocalName(), this.syslogConfig.isSendLocalName(), datetime); write(messageProcessor, level, _message, header); } catch (SyslogRuntimeException sre) { if (sre.getCause() != null) { backLog(level, _message, sre.getCause()); } else { backLog(level, _message, sre); } if (this.syslogConfig.isThrowExceptionOnWrite()) { throw sre; } } } protected void write(SyslogMessageProcessorIF messageProcessor, int level, String message, String header) throws SyslogRuntimeException { byte[] h = SyslogUtility.getBytes(this.syslogConfig, header); byte[] m = SyslogUtility.getBytes(this.syslogConfig, message); int mLength = m.length; int availableLen = this.syslogConfig.getMaxMessageLength() - h.length; if (this.syslogConfig.isTruncateMessage()) { if (availableLen > 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 < backLogHandlers.size(); i++) { SyslogBackLogHandlerIF backLogHandler = (SyslogBackLogHandlerIF) backLogHandlers.get(i); try { if (!status) { backLogHandler.down(this, reason); this.notifiedBackLogHandlers.add(backLogHandler); } backLogHandler.log(this, level, message, reason); break; } catch (Exception e) { // Ignore this Exception and go onto next backLogHandler } } } public abstract AbstractSyslogWriter getWriter(); public abstract void returnWriter(AbstractSyslogWriter syslogWriter); public Thread createWriterThread(AbstractSyslogWriter syslogWriter) { Thread newWriterThread = new Thread(syslogWriter); newWriterThread.setName("SyslogWriter: " + getProtocol()); newWriterThread.setDaemon(syslogConfig.isUseDaemonThread()); if (syslogConfig.getThreadPriority() > -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; } }