package app.revanced.library.logging import java.util.logging.Handler import java.util.logging.Level import java.util.logging.LogRecord import java.util.logging.SimpleFormatter @Suppress("MemberVisibilityCanBePrivate", "unused") object Logger { /** * Rules for allowed loggers. */ private val allowedLoggersRules = arrayOf Boolean>( // ReVanced loggers. { startsWith("app.revanced") }, // Logs warnings when compiling resources (Logger in class brut.util.OS). { this == "" }, ) private val rootLogger = java.util.logging.Logger.getLogger("") /** * Sets the format for the logger. * * @param format The format to use. */ fun setFormat(format: String = "%4\$s: %5\$s %n") { System.setProperty("java.util.logging.SimpleFormatter.format", format) } /** * Removes all handlers from the logger. */ fun removeAllHandlers() { rootLogger.let { logger -> logger.handlers.forEach { handler -> handler.close() logger.removeHandler(handler) } } } /** * Adds a handler to the logger. * * @param publishHandler The handler for publishing the log. * @param flushHandler The handler for flushing the log. * @param closeHandler The handler for closing the log. */ fun addHandler( publishHandler: (log: String, level: Level, loggerName: String?) -> Unit, flushHandler: () -> Unit, closeHandler: () -> Unit, ) = object : Handler() { override fun publish(record: LogRecord) = publishHandler( formatter.format(record), record.level, record.loggerName, ) override fun flush() = flushHandler() override fun close() = closeHandler() }.also { it.level = Level.ALL it.formatter = SimpleFormatter() }.let(rootLogger::addHandler) /** * Log to "standard" (error) output streams. */ fun setDefault() { setFormat() removeAllHandlers() val publishHandler = handler@{ log: String, level: Level, loggerName: String? -> loggerName?.let { name -> if (allowedLoggersRules.none { it(name) }) return@handler } log.toByteArray().let { if (level.intValue() > Level.WARNING.intValue()) { System.err.write(it) } else { System.out.write(it) } } } val flushHandler = { System.out.flush() System.err.flush() } addHandler(publishHandler, flushHandler, flushHandler) } }