201 lines
		
	
	
		
			No EOL
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			No EOL
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
package InnaIrcBot.LogDriver;
 | 
						|
 | 
						|
import org.sqlite.SQLiteConfig;
 | 
						|
import org.sqlite.SQLiteOpenMode;
 | 
						|
 | 
						|
import java.io.File;
 | 
						|
import java.sql.*;
 | 
						|
 | 
						|
public class BotSQLiteWorker implements Worker {
 | 
						|
 | 
						|
    private Connection connection;
 | 
						|
    private boolean consistent = false;
 | 
						|
    private PreparedStatement preparedStatement;
 | 
						|
/**
 | 
						|
 * Don't even think of changing this balalaika.
 | 
						|
 * */
 | 
						|
    public BotSQLiteWorker(String server, String[] driverParameters,  String channel){    // TODO: threads on SQLite level // remember: One file one DB
 | 
						|
        driverParameters[0] = driverParameters[0].trim();
 | 
						|
        File dir = new File(driverParameters[0]);
 | 
						|
        dir.mkdirs();
 | 
						|
        if (!dir.exists()) {
 | 
						|
            System.out.println("Unable to create directory to store DB file: " + driverParameters[0]);      //TODO: notify requester
 | 
						|
            this.consistent = false;
 | 
						|
        }
 | 
						|
        String connectionURL;
 | 
						|
        if (driverParameters[0].endsWith(File.separator))
 | 
						|
            connectionURL = "jdbc:sqlite:"+driverParameters[0]+server+".db";
 | 
						|
        else
 | 
						|
            connectionURL = "jdbc:sqlite:"+driverParameters[0]+File.separator+server+".db";
 | 
						|
 | 
						|
        String safeChanName = channel.trim().replaceAll("\"","\\\"");           // TODO: use trim in every driver/worker?
 | 
						|
        try {
 | 
						|
            SQLiteConfig sqlConfig = new SQLiteConfig();
 | 
						|
            sqlConfig.setOpenMode(SQLiteOpenMode.NOMUTEX);      //SQLITE_OPEN_NOMUTEX : multithreaded mode
 | 
						|
 | 
						|
            this.connection = DriverManager.getConnection(connectionURL, sqlConfig.toProperties());
 | 
						|
            if (connection != null){
 | 
						|
                // Create table if not created
 | 
						|
                Statement statement = connection.createStatement();
 | 
						|
                String query = "CREATE TABLE IF NOT EXISTS \""+safeChanName+"\" ("
 | 
						|
                        + "	id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
 | 
						|
                        + "	unixtime INTEGER,"
 | 
						|
                        + "	event TEXT,"
 | 
						|
                        + "	subject TEXT,"
 | 
						|
                        + "	message TEXT,"
 | 
						|
                        + "	object TEXT"
 | 
						|
                        +");";
 | 
						|
                statement.executeUpdate(query);
 | 
						|
 | 
						|
                // Check table representation
 | 
						|
                ResultSet rs = statement.executeQuery("PRAGMA table_info(\""+safeChanName+"\");");  // executeQuery never null
 | 
						|
                boolean[] schemaResultCheck = {false, false, false, false, false, false};
 | 
						|
 | 
						|
                while (rs.next()) {
 | 
						|
                    switch (rs.getInt("cid")) {
 | 
						|
                        case 0:
 | 
						|
                            if (rs.getString("name").equals("id")
 | 
						|
                                    && rs.getString("type").equals("INTEGER")
 | 
						|
                                    && (rs.getInt("notnull") == 1)
 | 
						|
                                    && (rs.getString("dflt_value") == null)
 | 
						|
                                    && (rs.getInt("pk") == 1))
 | 
						|
                                schemaResultCheck[0] = true;
 | 
						|
                            //System.out.println("Got 0");
 | 
						|
                            break;
 | 
						|
                        case 1:
 | 
						|
                            if (rs.getString("name").equals("unixtime")
 | 
						|
                                    && rs.getString("type").equals("INTEGER")
 | 
						|
                                    && (rs.getInt("notnull") == 0)
 | 
						|
                                    && (rs.getString("dflt_value") == null)
 | 
						|
                                    && (rs.getInt("pk") == 0))
 | 
						|
                                schemaResultCheck[1] = true;
 | 
						|
                            //System.out.println("Got 1");
 | 
						|
                            break;
 | 
						|
                        case 2:
 | 
						|
                            if (rs.getString("name").equals("event")
 | 
						|
                                    && rs.getString("type").equals("TEXT")
 | 
						|
                                    && (rs.getInt("notnull") == 0)
 | 
						|
                                    && (rs.getString("dflt_value") == null)
 | 
						|
                                    && (rs.getInt("pk") == 0))
 | 
						|
                                schemaResultCheck[2] = true;
 | 
						|
                            //System.out.println("Got 2");
 | 
						|
                            break;
 | 
						|
                        case 3:
 | 
						|
                            if (rs.getString("name").equals("subject")
 | 
						|
                                    && rs.getString("type").equals("TEXT")
 | 
						|
                                    && (rs.getInt("notnull") == 0)
 | 
						|
                                    && (rs.getString("dflt_value") == null)
 | 
						|
                                    && (rs.getInt("pk") == 0))
 | 
						|
                                schemaResultCheck[3] = true;
 | 
						|
                            //System.out.println("Got 3");
 | 
						|
                            break;
 | 
						|
                        case 4:
 | 
						|
                            if (rs.getString("name").equals("message")
 | 
						|
                                    && rs.getString("type").equals("TEXT")
 | 
						|
                                    && (rs.getInt("notnull") == 0)
 | 
						|
                                    && (rs.getString("dflt_value") == null)
 | 
						|
                                    && (rs.getInt("pk") == 0))
 | 
						|
                                schemaResultCheck[4] = true;
 | 
						|
                            //System.out.println("Got 4");
 | 
						|
                            break;
 | 
						|
                        case 5:
 | 
						|
                            if (rs.getString("name").equals("object")
 | 
						|
                                    && rs.getString("type").equals("TEXT")
 | 
						|
                                    && (rs.getInt("notnull") == 0)
 | 
						|
                                    && (rs.getString("dflt_value") == null)
 | 
						|
                                    && (rs.getInt("pk") == 0))
 | 
						|
                                schemaResultCheck[5] = true;
 | 
						|
                            //System.out.println("Got 5");
 | 
						|
                            break;
 | 
						|
                        default:
 | 
						|
                            for (int i = 0; i <= 5; i++) {
 | 
						|
                                schemaResultCheck[i] = false;       // If more then 5 elements, ruin results
 | 
						|
                            }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                    // Validating result: it table in DB have expected schema. If not, removing and recreating table.
 | 
						|
                for (boolean element: schemaResultCheck) {
 | 
						|
                    if (!element) {
 | 
						|
                        System.out.println("BotSQLiteWorker: Found already existing table for channel with incoorect syntax: removing table and re-creating.");
 | 
						|
                        statement.executeUpdate("DROP TABLE \"" + safeChanName + "\";");
 | 
						|
                        statement.executeUpdate(query);
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                this.consistent = true;
 | 
						|
 | 
						|
                this.preparedStatement = connection.prepareStatement(
 | 
						|
                        "INSERT INTO \""+safeChanName
 | 
						|
                        +"\" (unixtime, event, subject, message, object) "
 | 
						|
                        +"VALUES (?, ?, ?, ?, ?);");
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                this.consistent = false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        catch (SQLException e){
 | 
						|
            System.out.println("Internal issue: BotSQLiteWorker->constructor() failed\n\t"+e);
 | 
						|
            this.consistent = false;
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    private long getDate(){
 | 
						|
        return System.currentTimeMillis() / 1000L;                      // UNIX time
 | 
						|
    }
 | 
						|
    @Override
 | 
						|
    public boolean isConsistent() {return consistent; }
 | 
						|
 | 
						|
    @Override
 | 
						|
    public void logAdd(String event, String initiatorArg, String messageArg) {
 | 
						|
        try {
 | 
						|
            preparedStatement.setLong(1, getDate());
 | 
						|
            preparedStatement.setString(2, event);
 | 
						|
            preparedStatement.setString(3, initiatorArg);
 | 
						|
            switch (event) {
 | 
						|
                case "NICK":
 | 
						|
                case "JOIN":
 | 
						|
                    preparedStatement.setString(4, messageArg);
 | 
						|
                    preparedStatement.setString(5, null);
 | 
						|
                    break;
 | 
						|
                case "PART":
 | 
						|
                case "QUIT":
 | 
						|
                case "TOPIC":
 | 
						|
                    preparedStatement.setString(4, messageArg.replaceAll("^.+?:", ""));
 | 
						|
                    preparedStatement.setString(5, null);
 | 
						|
                    break;
 | 
						|
                case "MODE":
 | 
						|
                    preparedStatement.setString(4, messageArg.replaceAll("(^(.+?\\s){1})|(\\s.+$)",""));
 | 
						|
                    preparedStatement.setString(5, messageArg.replaceAll("^(.+?\\s){2}", ""));
 | 
						|
                    break;
 | 
						|
                case "KICK":
 | 
						|
                    preparedStatement.setString(4,messageArg.replaceAll("^.+?:", ""));
 | 
						|
                    preparedStatement.setString(5,messageArg.replaceAll("(^.+?\\s)|(\\s.+$)", ""));
 | 
						|
                    break;
 | 
						|
                case "PRIVMSG":
 | 
						|
                    preparedStatement.setString(4,messageArg.replaceAll("^:", ""));
 | 
						|
                    preparedStatement.setString(5,null);
 | 
						|
                    break;
 | 
						|
                default:
 | 
						|
                    preparedStatement.setString(4,messageArg);
 | 
						|
                    preparedStatement.setString(5,null);
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
            preparedStatement.executeUpdate();
 | 
						|
        }
 | 
						|
        catch (SQLException e){
 | 
						|
            System.out.println("Internal issue: BotSQLiteWorker->logAdd() failed\n\t"+e);
 | 
						|
            this.consistent = false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    @Override
 | 
						|
    public void close() {
 | 
						|
        try {
 | 
						|
            //System.out.println("SQLite drier closed");
 | 
						|
            this.connection.close();
 | 
						|
        }
 | 
						|
        catch (SQLException e){
 | 
						|
                System.out.println("Internal issue: BotSQLiteWorker->close() failed\n\t" + e);
 | 
						|
        }
 | 
						|
    }
 | 
						|
} |