package org.cagrid.tools.events;
import gov.nih.nci.cagrid.common.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.cagrid.tools.database.Database;
import org.cagrid.tools.database.DatabaseException;
/**
* @author <A href="mailto:langella@bmi.osu.edu">Stephen Langella </A>
* @author <A href="mailto:oster@bmi.osu.edu">Scott Oster </A>
* @author <A href="mailto:hastings@bmi.osu.edu">Shannon Hastings </A>
* @author <A href="mailto:ervin@bmi.osu.edu">David Ervin</A>
*/
public class EventAuditor extends BaseEventHandler implements Auditor {
private Database db;
private boolean dbBuilt = false;
private final static String EVENT_ID = "EVENT_ID";
private final static String TARGET_ID = "TARGET_ID";
private final static String REPORTING_PARTY_ID = "REPORTING_PARTY_ID";
private final static String EVENT_TYPE = "EVENT_TYPE";
private final static String OCCURRED_AT = "OCCURRED_AT";
private final static String MESSAGE = "MESSAGE";
private String table;
public EventAuditor(String name, Database db, String tableName) throws EventHandlerInitializationException {
super(name);
try {
this.db = db;
db.createDatabaseIfNeeded();
this.table = tableName;
} catch (Exception e) {
throw new EventHandlerInitializationException("Error initializing the event handler, " + name + ": "
+ e.getMessage(), e);
}
}
public void handleEvent(Event event) throws EventHandlingException {
try {
insertEvent(event);
} catch (DatabaseException e) {
getLog().error(e.getMessage(), e);
throw new EventHandlingException("An unexpected database error occurred.", e);
}
}
public boolean eventExists(long eventId) throws DatabaseException {
return db.exists(table, EVENT_ID, eventId);
}
public Event getEvent(long eventId) throws DatabaseException {
Event event = null;
buildDatabase();
Connection c = null;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("select * from " + table + " WHERE " + EVENT_ID + "= ?");
s.setLong(1, eventId);
ResultSet rs = s.executeQuery();
if (rs.next()) {
event = new Event();
event.setEventId(rs.getLong(EVENT_ID));
event.setTargetId(rs.getString(TARGET_ID));
event.setReportingPartyId(rs.getString(REPORTING_PARTY_ID));
event.setEventType(rs.getString(EVENT_TYPE));
event.setOccurredAt(rs.getLong(OCCURRED_AT));
event.setMessage(rs.getString(MESSAGE));
}
rs.close();
s.close();
} catch (Exception e) {
getLog().error(e.getMessage(), e);
throw new DatabaseException("An unexpected database error occurred.", e);
} finally {
db.releaseConnection(c);
}
return event;
}
public void deleteEvent(long eventId) throws DatabaseException {
buildDatabase();
try {
db.update("delete from " + this.table + " where " + EVENT_ID + "=" + eventId);
} catch (Exception e) {
getLog().error(e.getMessage(), e);
throw new DatabaseException("An unexpected database error occurred.", e);
}
}
private boolean appendToSQLBuffer(StringBuffer sql, boolean whereAppended, String field) {
return appendToSQLBuffer(sql, whereAppended, field, "=");
}
private boolean appendToSQLBuffer(StringBuffer sql, boolean whereAppended, String field, String operator) {
if (whereAppended) {
sql.append(" AND " + field + " " + operator + " ?");
} else {
sql.append(" WHERE " + field + " " + operator + " ?");
whereAppended = true;
}
return whereAppended;
}
public List<Event> findEvents(String targetId, String reportingPartyId, String eventType, Date start, Date end,
String message) throws EventAuditingException {
try {
buildDatabase();
} catch (DatabaseException e) {
throw new EventAuditingException("Unexpected error finding events.", e);
}
List<Event> events = new ArrayList<Event>();
Connection c = null;
try {
c = db.getConnection();
StringBuffer sql = new StringBuffer();
sql.append("select * from " + table);
boolean whereAppended = false;
if (targetId != null) {
whereAppended = appendToSQLBuffer(sql, whereAppended, TARGET_ID);
}
if (reportingPartyId != null) {
whereAppended = appendToSQLBuffer(sql, whereAppended, REPORTING_PARTY_ID);
}
if (eventType != null) {
whereAppended = appendToSQLBuffer(sql, whereAppended, EVENT_TYPE);
}
if (start != null) {
whereAppended = appendToSQLBuffer(sql, whereAppended, OCCURRED_AT, ">=");
}
if (end != null) {
whereAppended = appendToSQLBuffer(sql, whereAppended, OCCURRED_AT, "<=");
}
if (message != null) {
whereAppended = appendToSQLBuffer(sql, whereAppended, MESSAGE, "LIKE");
}
PreparedStatement s = c.prepareStatement(sql.toString());
int count = 1;
if (targetId != null) {
s.setString(count, targetId);
count = count + 1;
}
if (reportingPartyId != null) {
s.setString(count, reportingPartyId);
count = count + 1;
}
if (eventType != null) {
s.setString(count, eventType);
count = count + 1;
}
if (start != null) {
s.setLong(count, start.getTime());
count = count + 1;
}
if (end != null) {
s.setLong(count, end.getTime());
count = count + 1;
}
if (message != null) {
s.setString(count, "%" + message + "%");
count = count + 1;
}
ResultSet rs = s.executeQuery();
while (rs.next()) {
Event event = new Event();
event.setEventId(rs.getLong(EVENT_ID));
event.setTargetId(rs.getString(TARGET_ID));
event.setReportingPartyId(rs.getString(REPORTING_PARTY_ID));
event.setEventType(rs.getString(EVENT_TYPE));
event.setOccurredAt(rs.getLong(OCCURRED_AT));
event.setMessage(rs.getString(MESSAGE));
events.add(event);
}
rs.close();
s.close();
} catch (Exception e) {
getLog().error(e.getMessage(), e);
throw new EventAuditingException("An unexpected database error occurred.", e);
} finally {
db.releaseConnection(c);
}
return events;
}
private Event insertEvent(Event event) throws DatabaseException, EventHandlingException {
buildDatabase();
if (Utils.clean(event.getTargetId()) == null) {
throw new EventHandlingException("Could not audit event, no target id was specified.");
}
if (Utils.clean(event.getReportingPartyId()) == null) {
throw new EventHandlingException("Could not audit event, no reporting party was specified.");
}
if (Utils.clean(event.getEventType()) == null) {
throw new EventHandlingException("Could not audit event, no event type was specified.");
}
if (Utils.clean(event.getMessage()) == null) {
throw new EventHandlingException("Could not audit event, no event message was specified.");
}
if (event.getOccurredAt() <= 0) {
throw new EventHandlingException("Could not audit event, no occurred at date was specified.");
}
Connection c = null;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("INSERT INTO " + this.table + " SET " + TARGET_ID + "= ?, "
+ REPORTING_PARTY_ID + "= ?, " + EVENT_TYPE + "= ?, " + OCCURRED_AT + "= ?, " + MESSAGE + "= ?");
s.setString(1, event.getTargetId());
s.setString(2, event.getReportingPartyId());
s.setString(3, event.getEventType());
s.setLong(4, event.getOccurredAt());
s.setString(5, event.getMessage());
s.execute();
event.setEventId(db.getLastAutoId(c));
s.close();
} catch (Exception e) {
getLog().error(e.getMessage(), e);
throw new DatabaseException("An unexpected database error occurred.", e);
} finally {
if (c != null) {
db.releaseConnection(c);
}
}
return event;
}
public void clear() throws EventHandlingException {
try {
this.clearDatabase();
} catch (Exception e) {
throw new EventHandlingException(Utils.getExceptionMessage(e), e);
}
}
public void clearDatabase() throws DatabaseException {
buildDatabase();
db.update("DROP TABLE IF EXISTS " + this.table);
dbBuilt = false;
}
private void buildDatabase() throws DatabaseException {
if (!dbBuilt) {
if (!this.db.tableExists(table)) {
String trust = "CREATE TABLE " + this.table + " (" + EVENT_ID
+ " INT NOT NULL AUTO_INCREMENT PRIMARY KEY," + TARGET_ID + " VARCHAR(255) NOT NULL,"
+ REPORTING_PARTY_ID + " VARCHAR(255) NOT NULL," + EVENT_TYPE + " VARCHAR(50) NOT NULL,"
+ OCCURRED_AT + " BIGINT NOT NULL," + MESSAGE + " TEXT NOT NULL,"
+ "INDEX document_index (EVENT_ID));";
db.update(trust);
}
dbBuilt = true;
}
}
}