/* * Created on Nov 23, 2004 * Copyright (C) Andrea Schweer, 2004 * * This file is part of the Greenstone Alerting Service. * Refer to the COPYING file in the base directory of this package * for licensing information. */ package org.greenstone.gsdlas; import java.sql.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.Date; import org.greenstone.gsdlas.database.DatabaseException; import org.greenstone.gsdlas.database.DatabaseManager; import org.greenstone.gsdlas.profiles.Subscription; /** * @author schweer * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class EventStore { private static EventStore instance; private EventStore() { } /** * @return */ public static EventStore getInstance() { if (instance == null) instance = new EventStore(); return instance; } public void add(Map event, Set subscriptions) throws DatabaseException, SQLException, ParseException { Connection conn = DatabaseManager.getInstance().getDatabaseConnection(); Statement statement = conn.createStatement(); int eventID = saveEventToDatabase(event); for (Iterator iter = subscriptions.iterator(); iter.hasNext();) { Subscription sub = (Subscription) iter.next(); int subID = sub.getId(); String sqlString = "INSERT INTO events_to_subs (event,subscription) " + "VALUES (" + eventID + "," + subID + ");"; statement.executeUpdate(sqlString); } } /** * @param event * @return * @throws DatabaseException * @throws SQLException * @throws ParseException */ private int saveEventToDatabase(Map event) throws DatabaseException, SQLException, ParseException { String eventString = mapAsString(event); String timestamp = (String) event.get("timestamp"); timestamp = convertToSQLDatetime(timestamp); Connection conn = DatabaseManager.getInstance().getDatabaseConnection(); Statement statement = conn.createStatement(); String query = "SELECT id FROM events WHERE timestamp = " + timestamp + " AND content = '" + eventString + "';"; ResultSet results = statement.executeQuery(query); if (results.next()) { return results.getInt("id"); } String insert = "INSERT INTO events (timestamp,content) " + "VALUES (" + timestamp + ",'" + eventString + "');"; statement.executeUpdate(insert); results = statement.executeQuery(query); if (results.next()) { return results.getInt("id"); } throw new DatabaseException("couldn't save event to database"); } /** * converts a timestamp from an event to a format recognised by MySQL * @param timestamp * @return * @throws ParseException */ private String convertToSQLDatetime(String timestamp) throws ParseException { Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").parse(timestamp); return new SimpleDateFormat("yyyyMMddHHmmss").format(date); } /** * @param event */ private String encodeSpecialChars(String string) { String encodedString = string.replace("&", "&"); encodedString = encodedString.replace("<", "<"); encodedString = encodedString.replace(">", ">"); encodedString = encodedString.replace("'", "'"); encodedString = encodedString.replace("\"", """); return encodedString; } /** * @param subscriptionID * @return * @throws DatabaseException * @throws SQLException */ public Set getEvents(Integer subscriptionID) throws DatabaseException, SQLException { Set result = new HashSet(); // can't use TreeSet, because we put Maps in there, and Map isn't instanceof Comparable Connection conn = DatabaseManager.getInstance().getDatabaseConnection(); Statement statement = conn.createStatement(); String query = "SELECT content " + "FROM events e JOIN events_to_subs ets ON (e.id = ets.event) " + "WHERE ets.subscription = " + subscriptionID.intValue() + ";"; ResultSet results = statement.executeQuery(query); while (results.next()) { Map event = stringAsMap(results.getString("content")); result.add(event); } return result; } private String mapAsString(Map map) { StringBuffer buffer = new StringBuffer(); for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { String key = (String) iter.next(); String value = (String) map.get(key); String encodedValue = encodeSpecialChars(value); buffer.append(key); buffer.append(">"); // > has been encoded to > in the original String buffer.append(encodedValue); if (iter.hasNext()) { buffer.append(">>"); } } return buffer.toString(); } private Map stringAsMap(String string) { Map map = new HashMap(); String[] lines = string.split(">>"); for (int i = 0; i < lines.length; i++) { String line = lines[i]; String[] columns = line.split(">"); String key = columns[0]; String value = null; if (columns.length > 1) { value = columns[1]; } map.put(key, value); } return map; } public void cleanUp() { // TODO implement method // delete all events that are too old (?) // delete all events that don't match any subscriptions } }