/** * This file is part of Skript. * * Skript 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. * * Skript 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 Skript. If not, see <http://www.gnu.org/licenses/>. * * * Copyright 2011-2017 Peter Güttinger and contributors */ package ch.njol.skript.log; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Deque; import java.util.LinkedList; import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.eclipse.jdt.annotation.Nullable; import ch.njol.skript.Skript; /** * @author Peter Güttinger */ public class RetainingLogHandler extends LogHandler { private final Deque<LogEntry> log = new LinkedList<LogEntry>(); private int numErrors = 0; boolean printedErrorOrLog = false; @Override public LogResult log(final LogEntry entry) { log.add(entry); if (entry.getLevel().intValue() >= Level.SEVERE.intValue()) numErrors++; printedErrorOrLog = false; return LogResult.CACHED; } @Override public void onStop() { if (!printedErrorOrLog && Skript.testing()) SkriptLogger.LOGGER.warning("Retaining log wasn't instructed to print anything at " + SkriptLogger.getCaller()); } public final boolean printErrors() { return printErrors(null); } /** * Prints all retained errors or the given one if no errors were retained. * <p> * This handler is stopped if not already done. * * @param def Error to print if no errors were logged, can be null to not print any error if there are none * @return Whether there were any errors */ public final boolean printErrors(final @Nullable String def) { return printErrors(def, ErrorQuality.SEMANTIC_ERROR); } public final boolean printErrors(final @Nullable String def, final ErrorQuality quality) { assert !printedErrorOrLog; printedErrorOrLog = true; stop(); boolean hasError = false; for (final LogEntry e : log) { if (e.getLevel().intValue() >= Level.SEVERE.intValue()) { SkriptLogger.log(e); hasError = true; } else { e.discarded("not printed"); } } if (!hasError && def != null) SkriptLogger.log(SkriptLogger.SEVERE, def); return hasError; } /** * Sends all retained error messages to the given recipient. * <p> * This handler is stopped if not already done. * * @param recipient * @param def Error to send if no errors were logged, can be null to not print any error if there are none * @return Whether there were any errors to send */ public final boolean printErrors(final CommandSender recipient, final @Nullable String def) { assert !printedErrorOrLog; printedErrorOrLog = true; stop(); final boolean console = recipient == Bukkit.getConsoleSender(); // log as SEVERE instead of INFO boolean hasError = false; for (final LogEntry e : log) { if (e.getLevel().intValue() >= Level.SEVERE.intValue()) { if (console) SkriptLogger.LOGGER.severe(e.getMessage()); else recipient.sendMessage(e.getMessage()); e.logged(); hasError = true; } else { e.discarded("not printed"); } } if (!hasError && def != null) { if (console) SkriptLogger.LOGGER.severe(def); else recipient.sendMessage(def); } return hasError; } /** * Prints all retained log messages. * <p> * This handler is stopped if not already done. */ public final void printLog() { assert !printedErrorOrLog; printedErrorOrLog = true; stop(); SkriptLogger.logAll(log); } public boolean hasErrors() { return numErrors != 0; } @Nullable public LogEntry getFirstError() { for (final LogEntry e : log) { if (e.getLevel().intValue() >= Level.SEVERE.intValue()) return e; } return null; } public LogEntry getFirstError(final String def) { for (final LogEntry e : log) { if (e.getLevel().intValue() >= Level.SEVERE.intValue()) return e; } return new LogEntry(SkriptLogger.SEVERE, def); } /** * Clears the list of retained log messages. */ public void clear() { for (final LogEntry e : log) e.discarded("cleared"); log.clear(); numErrors = 0; } public int size() { return log.size(); } @SuppressWarnings("null") public Collection<LogEntry> getLog() { return Collections.unmodifiableCollection(log); } public Collection<LogEntry> getErrors() { final Collection<LogEntry> r = new ArrayList<LogEntry>(); for (final LogEntry e : log) { if (e.getLevel().intValue() >= Level.SEVERE.intValue()) r.add(e); } return r; } public int getNumErrors() { return numErrors; } }