/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2008-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.eventd.processor;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.ParseException;
import javax.sql.DataSource;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.EventConstants;
import org.opennms.netmgt.eventd.EventdConstants;
import org.opennms.netmgt.eventd.EventdServiceManager;
import org.opennms.netmgt.xml.event.Event;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.Assert;
/**
* EventWriter loads the information in each 'Event' into the database.
*
* While loading mutiple values of the same element into a single DB column, the
* mutiple values are delimited by MULTIPLE_VAL_DELIM.
*
* When an element and its attribute are loaded into a single DB column, the
* value and the attribute are separated by a DB_ATTRIB_DELIM.
*
* When using delimiters to append values, if the values already have the
* delimiter, the delimiter in the value is escaped as in URLs.
*
* Values for the ' <parms>' block are loaded with each parm name and parm value
* delimited with the NAME_VAL_DELIM.
*
* @see org.opennms.netmgt.model.events.Constants#MULTIPLE_VAL_DELIM
* @see org.opennms.netmgt.model.events.Constants#DB_ATTRIB_DELIM
* @see org.opennms.netmgt.model.events.Constants#NAME_VAL_DELIM
* @see org.opennms.netmgt.model.events.Constants#MULTIPLE_VAL_DELIM
* @see org.opennms.netmgt.model.events.Constants#DB_ATTRIB_DELIM
* @see org.opennms.netmgt.model.events.Constants#NAME_VAL_DELIM
* @see org.opennms.netmgt.model.events.Constants#MULTIPLE_VAL_DELIM
* @see org.opennms.netmgt.model.events.Constants#DB_ATTRIB_DELIM
* @see org.opennms.netmgt.model.events.Constants#NAME_VAL_DELIM
* @author <A HREF="mailto:david@opennms.org">David Hustace </A>
* @author <A HREF="http://www.opennms.org">OpenNMS.org </A>
*
* Changes:
*
* - Alarm persisting added (many moons ago)
* - Alarm persisting now removes oldest events by default. Use "auto-clean" attribute
* in eventconf files.
* @author Sowmya Nataraj </A>
* @author <A HREF="mailto:david@opennms.org">David Hustace </A>
* @author <A HREF="http://www.opennms.org">OpenNMS.org </A>
*
* Changes:
*
* - Alarm persisting added (many moons ago)
* - Alarm persisting now removes oldest events by default. Use "auto-clean" attribute
* in eventconf files.
* @version $Id: $
*/
public abstract class AbstractJdbcPersister implements InitializingBean, EventProcessor {
// Field sizes in the events table
/** Constant <code>EVENT_UEI_FIELD_SIZE=256</code> */
protected static final int EVENT_UEI_FIELD_SIZE = 256;
/** Constant <code>EVENT_HOST_FIELD_SIZE=256</code> */
protected static final int EVENT_HOST_FIELD_SIZE = 256;
/**
* Constant <code>EVENT_INTERFACE_FIELD_SIZE=50</code>.
* This value must be long enough to accommodate an IPv6 address
* with scope identifier suffix (if present). Basic IPv6 addresses
* are 39 characters so this will accommodate a 10-digit scope
* identifier (any 32-bit decimal value).
*/
protected static final int EVENT_INTERFACE_FIELD_SIZE = 50;
/** Constant <code>EVENT_DPNAME_FIELD_SIZE=12</code> */
protected static final int EVENT_DPNAME_FIELD_SIZE = 12;
/** Constant <code>EVENT_SNMPHOST_FIELD_SIZE=256</code> */
protected static final int EVENT_SNMPHOST_FIELD_SIZE = 256;
/** Constant <code>EVENT_SNMP_FIELD_SIZE=256</code> */
protected static final int EVENT_SNMP_FIELD_SIZE = 256;
/** Constant <code>EVENT_LOGGRP_FIELD_SIZE=32</code> */
protected static final int EVENT_LOGGRP_FIELD_SIZE = 32;
/** Constant <code>EVENT_PATHOUTAGE_FIELD_SIZE=1024</code> */
protected static final int EVENT_PATHOUTAGE_FIELD_SIZE = 1024;
/** Constant <code>EVENT_CORRELATION_FIELD_SIZE=1024</code> */
protected static final int EVENT_CORRELATION_FIELD_SIZE = 1024;
/** Constant <code>EVENT_OPERINSTRUCT_FIELD_SIZE=1024</code> */
protected static final int EVENT_OPERINSTRUCT_FIELD_SIZE = 1024;
/** Constant <code>EVENT_AUTOACTION_FIELD_SIZE=256</code> */
protected static final int EVENT_AUTOACTION_FIELD_SIZE = 256;
/** Constant <code>EVENT_OPERACTION_FIELD_SIZE=256</code> */
protected static final int EVENT_OPERACTION_FIELD_SIZE = 256;
/** Constant <code>EVENT_OPERACTION_MENU_FIELD_SIZE=64</code> */
protected static final int EVENT_OPERACTION_MENU_FIELD_SIZE = 64;
// protected static final int EVENT_NOTIFICATION_FIELD_SIZE = 128;
/** Constant <code>EVENT_TTICKET_FIELD_SIZE=128</code> */
protected static final int EVENT_TTICKET_FIELD_SIZE = 128;
/** Constant <code>EVENT_FORWARD_FIELD_SIZE=256</code> */
protected static final int EVENT_FORWARD_FIELD_SIZE = 256;
/** Constant <code>EVENT_MOUSEOVERTEXT_FIELD_SIZE=64</code> */
protected static final int EVENT_MOUSEOVERTEXT_FIELD_SIZE = 64;
/** Constant <code>EVENT_ACKUSER_FIELD_SIZE=256</code> */
protected static final int EVENT_ACKUSER_FIELD_SIZE = 256;
/** Constant <code>EVENT_SOURCE_FIELD_SIZE=128</code> */
protected static final int EVENT_SOURCE_FIELD_SIZE = 128;
/** Constant <code>EVENT_X733_ALARMTYPE_SIZE=31</code> */
protected static final int EVENT_X733_ALARMTYPE_SIZE = 31;
/**
* The character to put in if the log or display is to be set to yes
*/
protected static final char MSG_YES = 'Y';
/**
* The character to put in if the log or display is to be set to no
*/
protected static final char MSG_NO = 'N';
private EventdServiceManager m_eventdServiceManager;
private DataSource m_dataSource;
private String m_getNextIdString;
/**
* <p>Constructor for AbstractJdbcPersister.</p>
*/
public AbstractJdbcPersister() {
}
/**
* Sets the statement up for a String value.
*
* @param stmt
* The statement to add the value to.
* @param ndx
* The ndx for the value.
* @param value
* The value to add to the statement.
* @exception java.sql.SQLException
* Thrown if there is an error adding the value to the
* statement.
* @throws java.sql.SQLException if any.
*/
protected void set(PreparedStatement stmt, int ndx, String value) throws SQLException {
if (value == null || value.length() == 0) {
stmt.setNull(ndx, Types.VARCHAR);
} else {
stmt.setString(ndx, value);
}
}
/**
* Sets the statement up for an integer type. If the integer type is less
* than zero, then it is set to null!
*
* @param stmt
* The statement to add the value to.
* @param ndx
* The ndx for the value.
* @param value
* The value to add to the statement.
* @exception java.sql.SQLException
* Thrown if there is an error adding the value to the
* statement.
* @throws java.sql.SQLException if any.
*/
protected void set(PreparedStatement stmt, int ndx, int value) throws SQLException {
if (value < 0) {
stmt.setNull(ndx, Types.INTEGER);
} else {
stmt.setInt(ndx, value);
}
}
/**
* Sets the statement up for a timestamp type.
*
* @param stmt
* The statement to add the value to.
* @param ndx
* The ndx for the value.
* @param value
* The value to add to the statement.
* @exception java.sql.SQLException
* Thrown if there is an error adding the value to the
* statement.
* @throws java.sql.SQLException if any.
*/
protected void set(PreparedStatement stmt, int ndx, Timestamp value) throws SQLException {
if (value == null) {
stmt.setNull(ndx, Types.TIMESTAMP);
} else {
stmt.setTimestamp(ndx, value);
}
}
/**
* Sets the statement up for a character value.
*
* @param stmt
* The statement to add the value to.
* @param ndx
* The ndx for the value.
* @param value
* The value to add to the statement.
* @exception java.sql.SQLException
* Thrown if there is an error adding the value to the
* statement.
* @throws java.sql.SQLException if any.
*/
protected void set(PreparedStatement stmt, int ndx, char value) throws SQLException {
stmt.setString(ndx, String.valueOf(value));
}
/**
* This method is used to convert the service name into a service id. It
* first looks up the information from a service map of Eventd and if no
* match is found, by performing a lookup in the database. If the conversion
* is successful then the corresponding integer identifier will be returned
* to the caller.
*
* @param name
* The name of the service
* @return The integer identifier for the service name.
* @exception java.sql.SQLException
* Thrown if there is an error accessing the stored data or
* the SQL text is malformed. This will also be thrown if the
* result cannot be obtained.
* @see EventdConstants#SQL_DB_SVCNAME_TO_SVCID
* @throws java.sql.SQLException if any.
*/
protected int getServiceID(String name) throws SQLException {
return m_eventdServiceManager.getServiceId(name);
}
/**
* <p>getEventTime</p>
*
* @param event a {@link org.opennms.netmgt.xml.event.Event} object.
* @return a {@link java.sql.Timestamp} object.
*/
protected Timestamp getEventTime(Event event) {
try {
return new Timestamp(EventConstants.parseToDate(event.getTime()).getTime());
} catch (ParseException e) {
log().warn("Failed to convert time " + event.getTime() + " to Timestamp, setting current time instead. Exception: " + e, e);
return new Timestamp(System.currentTimeMillis());
}
}
/**
* <p>getNextId</p>
*
* @return a int.
* @throws java.sql.SQLException if any.
*/
protected int getNextId() throws SQLException {
return new JdbcTemplate(getDataSource()).queryForInt(getGetNextIdString());
}
/**
* <p>log</p>
*
* @return a {@link org.opennms.core.utils.ThreadCategory} object.
*/
protected ThreadCategory log() {
return ThreadCategory.getInstance(getClass());
}
/**
* <p>afterPropertiesSet</p>
*
* @throws java.sql.SQLException if any.
*/
@Override
public void afterPropertiesSet() throws SQLException {
Assert.state(m_eventdServiceManager != null, "property eventdServiceManager must be set");
Assert.state(m_dataSource != null, "property dataSource must be set");
Assert.state(m_getNextIdString != null, "property getNextIdString must be set");
}
/**
* <p>getEventdServiceManager</p>
*
* @return a {@link org.opennms.netmgt.eventd.EventdServiceManager} object.
*/
public EventdServiceManager getEventdServiceManager() {
return m_eventdServiceManager;
}
/**
* <p>setEventdServiceManager</p>
*
* @param eventdServiceManager a {@link org.opennms.netmgt.eventd.EventdServiceManager} object.
*/
public void setEventdServiceManager(EventdServiceManager eventdServiceManager) {
m_eventdServiceManager = eventdServiceManager;
}
/**
* <p>getDataSource</p>
*
* @return a {@link javax.sql.DataSource} object.
*/
public DataSource getDataSource() {
return m_dataSource;
}
/**
* <p>setDataSource</p>
*
* @param dataSource a {@link javax.sql.DataSource} object.
*/
public void setDataSource(DataSource dataSource) {
m_dataSource = dataSource;
}
/**
* <p>getGetNextIdString</p>
*
* @return a {@link java.lang.String} object.
*/
public String getGetNextIdString() {
return m_getNextIdString;
}
/**
* <p>setGetNextIdString</p>
*
* @param getNextIdString a {@link java.lang.String} object.
*/
public void setGetNextIdString(String getNextIdString) {
m_getNextIdString = getNextIdString;
}
/**
* <p>checkEventSanityAndDoWeProcess</p>
*
* @param event a {@link org.opennms.netmgt.xml.event.Event} object.
* @param logPrefix a {@link java.lang.String} object.
* @return a boolean.
*/
protected boolean checkEventSanityAndDoWeProcess(Event event, String logPrefix) {
Assert.notNull(event, "event argument must not be null");
/*
* Check value of <logmsg> attribute 'dest', if set to
* "donotpersist" then simply return, the uei is not to be
* persisted to the database
*/
Assert.notNull(event.getLogmsg(), "event does not have a logmsg");
if ("donotpersist".equals(event.getLogmsg().getDest()) || "suppress".equals(event.getLogmsg().getDest())) {
if (log().isDebugEnabled()) {
log().debug(logPrefix + ": uei '" + event.getUei() + "' marked as '" + event.getLogmsg().getDest() + "'; not processing event.");
}
return false;
}
return true;
}
}