package core; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import core.filters.ChainedLogFilter; import core.filters.LimitFilter; import core.filters.LogFilter; import core.filters.SecurityLogFilter; import core.filters.UserRegexFilter; import core.output.IrcLogOutput; import core.output.LogOutput; import core.output.PasteServiceLogOutput; import de.skuzzle.polly.sdk.AbstractDisposable; import de.skuzzle.polly.sdk.MyPolly; import de.skuzzle.polly.sdk.PersistenceManagerV2; import de.skuzzle.polly.sdk.PersistenceManagerV2.Atomic; import de.skuzzle.polly.sdk.PersistenceManagerV2.Param; import de.skuzzle.polly.sdk.PersistenceManagerV2.Write; import de.skuzzle.polly.sdk.User; import de.skuzzle.polly.sdk.exceptions.DatabaseException; import de.skuzzle.polly.sdk.exceptions.DisposingException; import de.skuzzle.polly.sdk.paste.PasteServiceManager; import entities.LogEntry; public class PollyLoggingManager extends AbstractDisposable { private PersistenceManagerV2 persistence; private PasteServiceManager pasteServiceManager; private List<LogEntry> cache; private int cacheSize; private int pasteTreshold; private int maxLogs; public PollyLoggingManager(MyPolly myPolly, int cacheSize, int pasteTreshold, int maxLogs) { this.persistence = myPolly.persistence(); this.pasteServiceManager = myPolly.pasting(); this.cacheSize = cacheSize; this.pasteTreshold = pasteTreshold; this.maxLogs = maxLogs; this.cache = new ArrayList<LogEntry>(this.cacheSize); } public void logMessage(LogEntry entry) throws DatabaseException { synchronized (this.cache) { String msg = entry.getMessage(); do { LogEntry newEntry = new LogEntry(entry); int newLen = Math.min(LogEntry.MESSAGE_LEN, msg.length()); newEntry.setMessage(msg.substring(0, newLen)); msg = msg.substring(newLen); this.cache.add(newEntry); } while (msg.length() > 0); if (this.cache.size() == cacheSize) { this.storeCache(); } } } public List<LogEntry> preFilterUser(String user) throws DatabaseException { return this.preFilterQuery(LogEntry.FIND_BY_USER, user); } public List<LogEntry> preFilterChannel(String channel) throws DatabaseException { return this.preFilterQuery(LogEntry.FIND_BY_CHANNEL, channel); } public LogEntry seenUser(String user) throws DatabaseException { List<LogEntry> seen = this.preFilterQuery(LogEntry.USER_SEEN, 1, user); if (seen.isEmpty()) { return LogEntry.forUnknown(user); } else { return seen.get(0); } } public List<LogEntry> filterUserRegex(String userRegex) throws DatabaseException { List<LogEntry> allEntries = this.preFilterQuery(LogEntry.ALL_LOG_ENTRIES); return this.postFilter(allEntries, new UserRegexFilter(userRegex)); } public List<LogEntry> getAllEntries() { try { return this.preFilterQuery(LogEntry.ALL_LOG_ENTRIES); } catch (DatabaseException e) { e.printStackTrace(); throw new RuntimeException(e); } } private List<LogEntry> preFilterQuery(String queryName, String...parameter) throws DatabaseException { this.storeCache(); final List<LogEntry> result = this.persistence.atomic().findList(LogEntry.class, queryName, new Param(parameter)); this.persistence.detachAll(result); return result; } private List<LogEntry> preFilterQuery(String queryName, int limit, String...parameter) throws DatabaseException { this.storeCache(); final List<LogEntry> result = this.persistence.atomic().findList(LogEntry.class, queryName, limit, new Param(parameter)); this.persistence.detachAll(result); return result; } public void outputLogResults(MyPolly myPolly, User executer, List<LogEntry> logs, String channel) { LogFormatter logFormatter = new DefaultLogFormatter(); LogOutput output = null; // filter messages from channels that the executer is not on LogFilter security = new SecurityLogFilter(myPolly, executer); LogFilter limitFilter = new LimitFilter(this.maxLogs); LogFilter chained = new ChainedLogFilter(security, limitFilter); int unfilteredSize = logs.size(); logs = this.postFilter(logs, chained); // the results are sorted by date, newest item on top. Reverse the order so // the items are printed in proper order Collections.reverse(logs); if (logs.size() < this.pasteTreshold) { output = new IrcLogOutput(); } else { output = new PasteServiceLogOutput( this.pasteServiceManager.getRandomService()); } output.outputLogs(myPolly.irc(), channel, logs, unfilteredSize, logFormatter, myPolly.formatting()); // clear log list logs.clear(); } public List<LogEntry> postFilter(List<LogEntry> logs, LogFilter filter) { List<LogEntry> result = new ArrayList<LogEntry>(); for (LogEntry log : logs) { if (filter.accept(log)) { result.add(log); } } return result; } public List<LogEntry> postFilter(List<LogEntry> logs, LogFilter filter, int max) { List<LogEntry> result = new ArrayList<LogEntry>(max); Iterator<LogEntry> it = logs.iterator(); while (result.size() < max && it.hasNext()) { LogEntry log = it.next(); if (filter.accept(log)) { result.add(log); } } return result; } public void storeCache() throws DatabaseException { final List<LogEntry> cpy; synchronized (this.cache) { if (this.cache.isEmpty()) { return; } cpy = new ArrayList<>(this.cache); this.cache.clear(); } this.persistence.writeAtomic(new Atomic() { @Override public void perform(Write write) { write.all(cpy); } }); } @Override protected void actualDispose() throws DisposingException { try { this.storeCache(); } catch (DatabaseException e) { throw new DisposingException(e); } } }