diff --git a/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt b/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt index 931ec48..4ea13d2 100644 --- a/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt @@ -11,10 +11,13 @@ import app.revanced.patcher.patch.PatchOption import picocli.CommandLine.* import picocli.CommandLine.Help.Visibility.ALWAYS import java.io.File +import java.util.logging.Logger @Command(name = "list-patches", description = ["List patches from supplied patch bundles"]) internal object ListPatchesCommand : Runnable { + private val logger = Logger.getLogger(ListPatchesCommand::class.java.name) + @Parameters( description = ["Paths to patch bundles"], arity = "1..*" diff --git a/src/main/kotlin/app/revanced/cli/command/MainCommand.kt b/src/main/kotlin/app/revanced/cli/command/MainCommand.kt index 49ae32d..20c6a47 100644 --- a/src/main/kotlin/app/revanced/cli/command/MainCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/MainCommand.kt @@ -1,20 +1,47 @@ package app.revanced.cli.command -import app.revanced.cli.logging.impl.DefaultCliLogger import app.revanced.patcher.patch.PatchClass import picocli.CommandLine import picocli.CommandLine.Command import picocli.CommandLine.IVersionProvider import java.util.* +import java.util.logging.* + fun main(args: Array) { + System.setProperty("java.util.logging.SimpleFormatter.format", "%4\$s: %5\$s %n") + Logger.getLogger("").apply { + handlers.forEach { + it.close() + removeHandler(it) + } + + object : Handler() { + override fun publish(record: LogRecord) = formatter.format(record).let { + if (record.level.intValue() > Level.INFO.intValue()) { + System.err.write(it.toByteArray()) + } else { + System.out.write(it.toByteArray()) + } + } + + override fun flush() { + System.out.flush() + System.err.flush() + } + + override fun close() = flush() + }.also { + it.level = Level.ALL + it.formatter = SimpleFormatter() + }.let(::addHandler) + } + CommandLine(MainCommand).execute(*args) } internal typealias PatchList = List -internal val logger = DefaultCliLogger() - object CLIVersionProvider : IVersionProvider { override fun getVersion(): Array { Properties().apply { diff --git a/src/main/kotlin/app/revanced/cli/command/OptionsCommand.kt b/src/main/kotlin/app/revanced/cli/command/OptionsCommand.kt index 0d0b020..ed623d6 100644 --- a/src/main/kotlin/app/revanced/cli/command/OptionsCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/OptionsCommand.kt @@ -6,12 +6,15 @@ import app.revanced.utils.Options.setOptions import picocli.CommandLine import picocli.CommandLine.Help.Visibility.ALWAYS import java.io.File +import java.util.logging.Logger @CommandLine.Command( name = "options", description = ["Generate options file from patches"], ) internal object OptionsCommand : Runnable { + private val logger = Logger.getLogger(OptionsCommand::class.java.name) + @CommandLine.Parameters( description = ["Paths to patch bundles"], arity = "1..*" @@ -41,10 +44,10 @@ internal object OptionsCommand : Runnable { override fun run() = if (!path.exists() || overwrite) with(PatchBundleLoader.Jar(*patchBundles)) { - if (update) setOptions(path, logger) + if (update) setOptions(path) Options.serialize(this, prettyPrint = true) .let(path::writeText) } - else logger.error("Options file already exists, use --override to override it") + else logger.severe("Options file already exists, use --override to override it") } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/cli/command/PatchCommand.kt b/src/main/kotlin/app/revanced/cli/command/PatchCommand.kt index f1ccbd3..3b6ce68 100644 --- a/src/main/kotlin/app/revanced/cli/command/PatchCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/PatchCommand.kt @@ -1,6 +1,5 @@ package app.revanced.cli.command -import app.revanced.cli.patcher.logging.impl.PatcherLogger import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherOptions @@ -20,6 +19,7 @@ import kotlinx.coroutines.runBlocking import picocli.CommandLine import picocli.CommandLine.Help.Visibility.ALWAYS import java.io.File +import java.util.logging.Logger @CommandLine.Command( @@ -27,6 +27,8 @@ import java.io.File description = ["Patch the supplied APK file with the supplied patches and integrations"] ) internal object PatchCommand: Runnable { + private val logger = Logger.getLogger(PatchCommand::class.java.name) + @CommandLine.Parameters( description = ["APK file to be patched"], arity = "1..1" @@ -144,15 +146,13 @@ internal object PatchCommand: Runnable { // region Prepare if (!apk.exists()) { - logger.error("Input file ${apk.name} does not exist") + logger.severe("Input file ${apk.name} does not exist") return } val adbManager = deviceSerial?.let { serial -> - if (mount) AdbManager.RootAdbManager(serial, logger) else AdbManager.UserAdbManager( - serial, - logger - ) + if (mount) AdbManager.RootAdbManager(serial) + else AdbManager.UserAdbManager(serial) } // endregion @@ -167,7 +167,7 @@ internal object PatchCommand: Runnable { logger.info("Setting patch options") optionsFile.let { - if (it.exists()) patches.setOptions(it, logger) + if (it.exists()) patches.setOptions(it) else Options.serialize(patches, prettyPrint = true).let(it::writeText) } @@ -181,7 +181,6 @@ internal object PatchCommand: Runnable { resourceCachePath, aaptBinaryPath.path, resourceCachePath.absolutePath, - PatcherLogger ) ) @@ -193,7 +192,7 @@ internal object PatchCommand: Runnable { runBlocking { apply(false).collect { patchResult -> patchResult.exception?.let { - logger.error("${patchResult.patchName} failed:\n${patchResult.exception}") + logger.severe("${patchResult.patchName} failed:\n${patchResult.exception}") } ?: logger.info("${patchResult.patchName} succeeded") } } @@ -288,7 +287,7 @@ internal object PatchCommand: Runnable { it.isEmpty() || it.any { version -> version == packageVersion } } - if (!matchesVersion) return@patch logger.warn( + if (!matchesVersion) return@patch logger.warning( "${patch.patchName} is incompatible with version $packageVersion. " + "This patch is only compatible with version " + packages.joinToString(";") { pkg -> @@ -296,14 +295,14 @@ internal object PatchCommand: Runnable { } ) - } ?: return@patch logger.trace( + } ?: return@patch logger.fine( "${patch.patchName} is incompatible with $packageName. " + "This patch is only compatible with " + packages.joinToString(", ") { `package` -> `package`.name } ) return@let - } ?: logger.trace("$formattedPatchName: No constraint on packages.") + } ?: logger.fine("$formattedPatchName: No constraint on packages.") /** * Check if the patch is explicitly included. @@ -329,7 +328,7 @@ internal object PatchCommand: Runnable { val included = implicitlyIncluded || exclusivelyIncluded if (!included) return@patch logger.info("${patch.patchName} excluded by default") // Case 1. - logger.trace("Adding $formattedPatchName") + logger.fine("Adding $formattedPatchName") add(patch) } diff --git a/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt b/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt index 84e673a..a0f7f8d 100644 --- a/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt @@ -3,6 +3,7 @@ package app.revanced.cli.command import app.revanced.utils.adb.AdbManager import picocli.CommandLine.* import picocli.CommandLine.Help.Visibility.ALWAYS +import java.util.logging.Logger @Command( @@ -10,6 +11,8 @@ import picocli.CommandLine.Help.Visibility.ALWAYS description = ["Uninstall a patched APK file from the devices with the supplied ADB device serials"] ) internal object UninstallCommand : Runnable { + private val logger = Logger.getLogger(UninstallCommand::class.java.name) + @Parameters( description = ["ADB device serials"], arity = "1..*" @@ -33,12 +36,12 @@ internal object UninstallCommand : Runnable { override fun run() = try { deviceSerials.forEach {deviceSerial -> if (unmount) { - AdbManager.RootAdbManager(deviceSerial, logger) + AdbManager.RootAdbManager(deviceSerial) } else { - AdbManager.UserAdbManager(deviceSerial, logger) + AdbManager.UserAdbManager(deviceSerial) }.uninstall(packageName) } } catch (e: AdbManager.DeviceNotFoundException) { - logger.error(e.toString()) + logger.severe(e.toString()) } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/cli/logging/CliLogger.kt b/src/main/kotlin/app/revanced/cli/logging/CliLogger.kt deleted file mode 100644 index 06849b1..0000000 --- a/src/main/kotlin/app/revanced/cli/logging/CliLogger.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.cli.logging - -internal interface CliLogger { - fun error(msg: String) - fun info(msg: String) - fun trace(msg: String) - fun warn(msg: String) -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/cli/logging/impl/DefaultCliLogger.kt b/src/main/kotlin/app/revanced/cli/logging/impl/DefaultCliLogger.kt deleted file mode 100644 index db9306a..0000000 --- a/src/main/kotlin/app/revanced/cli/logging/impl/DefaultCliLogger.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.cli.logging.impl - -import app.revanced.cli.command.MainCommand -import app.revanced.cli.logging.CliLogger -import java.util.logging.Logger -import java.util.logging.SimpleFormatter - -internal class DefaultCliLogger( - private val logger: Logger = Logger.getLogger(MainCommand::class.java.name), - private val errorLogger: Logger = Logger.getLogger(logger.name + "Err") -) : CliLogger { - - init { - logger.useParentHandlers = false - if (logger.handlers.isEmpty()) { - logger.addHandler(FlushingStreamHandler(System.out, SimpleFormatter())) - } - } - - companion object { - init { - System.setProperty("java.util.logging.SimpleFormatter.format", "%4\$s: %5\$s %n") - } - } - - override fun error(msg: String) = errorLogger.severe(msg) - override fun info(msg: String) = logger.info(msg) - override fun trace(msg: String) = logger.finest(msg) - override fun warn(msg: String) = errorLogger.warning(msg) -} diff --git a/src/main/kotlin/app/revanced/cli/logging/impl/FlushingStreamHandler.kt b/src/main/kotlin/app/revanced/cli/logging/impl/FlushingStreamHandler.kt deleted file mode 100644 index 4bfb394..0000000 --- a/src/main/kotlin/app/revanced/cli/logging/impl/FlushingStreamHandler.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.cli.logging.impl - -import java.io.OutputStream -import java.util.logging.Formatter -import java.util.logging.LogRecord -import java.util.logging.StreamHandler - -internal class FlushingStreamHandler(out: OutputStream, format: Formatter) : StreamHandler(out, format) { - override fun publish(record: LogRecord) { - super.publish(record) - flush() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/cli/patcher/logging/impl/PatcherLogger.kt b/src/main/kotlin/app/revanced/cli/patcher/logging/impl/PatcherLogger.kt deleted file mode 100644 index 11c04a7..0000000 --- a/src/main/kotlin/app/revanced/cli/patcher/logging/impl/PatcherLogger.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.cli.patcher.logging.impl - -import app.revanced.cli.logging.impl.DefaultCliLogger -import java.util.logging.Logger - -internal object PatcherLogger : app.revanced.patcher.logging.Logger{ - private val logger = DefaultCliLogger(Logger.getLogger(app.revanced.patcher.Patcher::class.java.name)) - - override fun error(msg: String) = logger.error(msg) - override fun info(msg: String) = logger.info(msg) - override fun warn(msg: String)= logger.warn(msg) - override fun trace(msg: String)= logger.trace(msg) -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/utils/Options.kt b/src/main/kotlin/app/revanced/utils/Options.kt index 4e07d85..534e32b 100644 --- a/src/main/kotlin/app/revanced/utils/Options.kt +++ b/src/main/kotlin/app/revanced/utils/Options.kt @@ -1,16 +1,18 @@ package app.revanced.utils import app.revanced.cli.command.PatchList -import app.revanced.cli.logging.CliLogger import app.revanced.patcher.extensions.PatchExtensions.options import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.patch.NoSuchOptionException import app.revanced.utils.Options.PatchOption.Option import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import java.io.File +import java.util.logging.Logger internal object Options { + private val logger = Logger.getLogger(Options::class.java.name) + private var mapper = jacksonObjectMapper() /** @@ -53,9 +55,8 @@ internal object Options { * Sets the options for the patches in the list. * * @param json The JSON string containing the options. - * @param logger The logger to use for logging. */ - fun PatchList.setOptions(json: String, logger: CliLogger? = null) { + fun PatchList.setOptions(json: String) { filter { it.options?.any() == true }.let { patches -> if (patches.isEmpty()) return @@ -66,9 +67,9 @@ internal object Options { it.options.forEach { option -> try { patch.options?.set(option.key, option.value) - ?: logger?.warn("${patch.patchName} has no options") + ?: logger.warning("${patch.patchName} has no options") } catch (e: NoSuchOptionException) { - logger?.error(e.message ?: "Unknown error") + logger.info(e.message ?: "Unknown error") } } } @@ -80,10 +81,9 @@ internal object Options { * Sets the options for the patches in the list. * * @param file The file containing the JSON string containing the options. - * @param logger The logger to use for logging. * @see setOptions */ - fun PatchList.setOptions(file: File, logger: CliLogger? = null) = setOptions(file.readText(), logger) + fun PatchList.setOptions(file: File) = setOptions(file.readText()) /** * Data class for a patch and its [Option]s. diff --git a/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt b/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt index 2044f51..b54249a 100644 --- a/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt +++ b/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt @@ -1,6 +1,5 @@ package app.revanced.utils.adb -import app.revanced.cli.logging.CliLogger import app.revanced.utils.adb.AdbManager.Apk import app.revanced.utils.adb.Constants.COMMAND_CREATE_DIR import app.revanced.utils.adb.Constants.COMMAND_DELETE @@ -19,18 +18,21 @@ import se.vidstige.jadb.managers.Package import se.vidstige.jadb.managers.PackageManager import java.io.Closeable import java.io.File +import java.util.logging.Logger /** * Adb manager. Used to install and uninstall [Apk] files. * * @param deviceSerial The serial of the device. */ -internal sealed class AdbManager(deviceSerial: String? = null, protected val logger: CliLogger? = null) : Closeable { +internal sealed class AdbManager(deviceSerial: String? = null) : Closeable { + protected val logger: Logger = Logger.getLogger(AdbManager::class.java.name) + protected val device = JadbConnection().devices.find { device -> device.serial == deviceSerial } ?: throw DeviceNotFoundException(deviceSerial) init { - logger?.trace("Established connection to $deviceSerial") + logger.fine("Established connection to $deviceSerial") } /** @@ -39,7 +41,7 @@ internal sealed class AdbManager(deviceSerial: String? = null, protected val log * @param apk The [Apk] file. */ open fun install(apk: Apk) { - logger?.info("Finished installing ${apk.file.name}") + logger.info("Finished installing ${apk.file.name}") } /** @@ -48,23 +50,23 @@ internal sealed class AdbManager(deviceSerial: String? = null, protected val log * @param packageName The package name. */ open fun uninstall(packageName: String) { - logger?.info("Finished uninstalling $packageName") + logger.info("Finished uninstalling $packageName") } /** * Closes the [AdbManager] instance. */ override fun close() { - logger?.trace("Closed") + logger.fine("Closed") } - class RootAdbManager(deviceSerial: String, logger: CliLogger? = null) : AdbManager(deviceSerial, logger) { + class RootAdbManager(deviceSerial: String) : AdbManager(deviceSerial) { init { if (!device.hasSu()) throw IllegalArgumentException("Root required on $deviceSerial. Task failed") } override fun install(apk: Apk) { - logger?.info("Installing by mounting") + logger.info("Installing by mounting") val applyReplacement = getPlaceholderReplacement( apk.packageName ?: throw IllegalArgumentException("Package name is required") @@ -86,7 +88,7 @@ internal sealed class AdbManager(deviceSerial: String? = null, protected val log } override fun uninstall(packageName: String) { - logger?.info("Uninstalling $packageName by unmounting and deleting the package") + logger.info("Uninstalling $packageName by unmounting and deleting the package") val applyReplacement = getPlaceholderReplacement(packageName) @@ -103,7 +105,7 @@ internal sealed class AdbManager(deviceSerial: String? = null, protected val log } } - class UserAdbManager(deviceSerial: String, logger: CliLogger? = null) : AdbManager(deviceSerial, logger) { + class UserAdbManager(deviceSerial: String) : AdbManager(deviceSerial) { private val packageManager = PackageManager(device) override fun install(apk: Apk) { @@ -113,7 +115,7 @@ internal sealed class AdbManager(deviceSerial: String? = null, protected val log } override fun uninstall(packageName: String) { - logger?.info("Uninstalling $packageName") + logger.info("Uninstalling $packageName") packageManager.uninstall(Package(packageName)) diff --git a/src/main/kotlin/app/revanced/utils/signing/ApkSigner.kt b/src/main/kotlin/app/revanced/utils/signing/ApkSigner.kt index a6bf337..f864490 100644 --- a/src/main/kotlin/app/revanced/utils/signing/ApkSigner.kt +++ b/src/main/kotlin/app/revanced/utils/signing/ApkSigner.kt @@ -1,6 +1,5 @@ package app.revanced.utils.signing -import app.revanced.cli.command.logger import com.android.apksig.ApkSigner import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo @@ -16,10 +15,13 @@ import java.math.BigInteger import java.security.* import java.security.cert.X509Certificate import java.util.* +import java.util.logging.Logger internal class ApkSigner( private val signingOptions: SigningOptions ) { + private val logger = Logger.getLogger(ApkSigner::class.java.name) + private val signer: ApkSigner.Builder private val passwordCharArray = signingOptions.password.toCharArray()