diff --git a/.run/MainKt.run.xml b/.run/MainKt.run.xml new file mode 100644 index 0000000000000000000000000000000000000000..9de3e67b91398aaa707c36464c9b7b019c7580fe --- /dev/null +++ b/.run/MainKt.run.xml @@ -0,0 +1,15 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="MainKt" type="JetRunConfigurationType" nameIsGenerated="true"> + <module name="mailbox.mailbox-cli" /> + <option name="VM_PARAMETERS" value="" /> + <option name="PROGRAM_PARAMETERS" value="--debug" /> + <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> + <option name="ALTERNATIVE_JRE_PATH" /> + <option name="PASS_PARENT_ENVS" value="true" /> + <option name="MAIN_CLASS_NAME" value="org.briarproject.mailbox.cli.MainKt" /> + <option name="WORKING_DIRECTORY" value="" /> + <method v="2"> + <option name="Make" enabled="true" /> + </method> + </configuration> +</component> \ No newline at end of file diff --git a/mailbox-android/build.gradle b/mailbox-android/build.gradle index 3825d95d14ac73864a93d231a0628eae1880ce70..23af48a7bdc66968523f48e0362cb2fb9024eaf7 100644 --- a/mailbox-android/build.gradle +++ b/mailbox-android/build.gradle @@ -52,6 +52,7 @@ configurations { dependencies { implementation project(path: ':mailbox-core', configuration: 'default') + implementation 'com.github.tony19:logback-android:2.0.0' implementation 'androidx.appcompat:appcompat:1.3.1' implementation "androidx.activity:activity-ktx:1.3.1" implementation "androidx.fragment:fragment-ktx:1.3.6" diff --git a/mailbox-android/src/main/assets/logback.xml b/mailbox-android/src/main/assets/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..a84fd707907a6ff4e2887484754d19f7348c7d73 --- /dev/null +++ b/mailbox-android/src/main/assets/logback.xml @@ -0,0 +1,13 @@ +<configuration> + <appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender"> + <tagEncoder> + <pattern>%logger{12}</pattern> + </tagEncoder> + <encoder> + <pattern>%msg</pattern> + </encoder> + </appender> + <root level="DEBUG"> + <appender-ref ref="logcat" /> + </root> +</configuration> diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt b/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt index 4461d87f8751fc39013749ab88dcdf8282a379a9..57c2f8260b592e0c74ce899bfe6ff4be4d9e3d8c 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt @@ -12,14 +12,16 @@ import org.briarproject.mailbox.core.lifecycle.LifecycleManager import org.briarproject.mailbox.core.lifecycle.LifecycleManager.StartResult import org.briarproject.mailbox.core.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING import org.briarproject.mailbox.core.lifecycle.LifecycleManager.StartResult.SUCCESS -import java.util.logging.Level -import java.util.logging.Logger +import org.slf4j.LoggerFactory.getLogger + import javax.inject.Inject @AndroidEntryPoint class MailboxService : Service() { companion object { + private val LOG = getLogger(MailboxService::class.java.name) + fun startService(context: Context) { val startIntent = Intent(context, MailboxService::class.java) ContextCompat.startForegroundService(context, startIntent) @@ -31,8 +33,6 @@ class MailboxService : Service() { } } - private val LOG = Logger.getLogger(MailboxService::class.java.name) - @Volatile internal var started = false @@ -60,8 +60,7 @@ class MailboxService : Service() { LOG.info("Already running") stopSelf() } else { - if (LOG.isLoggable(Level.WARNING)) - LOG.warning("Startup failed: $result") + if (LOG.isWarnEnabled) LOG.warn("Startup failed: $result") // TODO: implement this // showStartupFailure(result) stopSelf() diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/AndroidWakeLockImpl.java b/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/AndroidWakeLockImpl.java index 7d6ac25c0fdd04abd6042995c65d37a2a2be5c4f..6eaa65eb325613973ed73079f64338f800836c9c 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/AndroidWakeLockImpl.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/AndroidWakeLockImpl.java @@ -1,12 +1,12 @@ package org.briarproject.mailbox.android.system; -import static java.util.logging.Level.FINE; -import static java.util.logging.Logger.getLogger; +import static org.briarproject.mailbox.core.util.LogUtils.trace; +import static org.slf4j.LoggerFactory.getLogger; import org.briarproject.mailbox.android.api.system.AndroidWakeLock; +import org.slf4j.Logger; import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Logger; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; @@ -19,8 +19,7 @@ import javax.annotation.concurrent.ThreadSafe; @ThreadSafe class AndroidWakeLockImpl implements AndroidWakeLock { - private static final Logger LOG = - getLogger(AndroidWakeLockImpl.class.getName()); + private static final Logger LOG = getLogger(AndroidWakeLockImpl.class); private static final AtomicInteger INSTANCE_ID = new AtomicInteger(0); @@ -40,13 +39,9 @@ class AndroidWakeLockImpl implements AndroidWakeLock { public void acquire() { synchronized (lock) { if (held) { - if (LOG.isLoggable(FINE)) { - LOG.fine(tag + " already acquired"); - } + trace(LOG, () -> tag + " already acquired"); } else { - if (LOG.isLoggable(FINE)) { - LOG.fine(tag + " acquiring shared wake lock"); - } + trace(LOG, () -> tag + " acquiring shared wake lock"); held = true; sharedWakeLock.acquire(); } @@ -57,15 +52,11 @@ class AndroidWakeLockImpl implements AndroidWakeLock { public void release() { synchronized (lock) { if (held) { - if (LOG.isLoggable(FINE)) { - LOG.fine(tag + " releasing shared wake lock"); - } + trace(LOG, () -> tag + " releasing shared wake lock"); held = false; sharedWakeLock.release(); } else { - if (LOG.isLoggable(FINE)) { - LOG.fine(tag + " already released"); - } + trace(LOG, () -> tag + " already released"); } } } diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/RenewableWakeLock.java b/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/RenewableWakeLock.java index d4a910cc144bb899053608210e91f6417995bbf4..a39cbf5f53ff7759762707f4ae8a08af2edc74dd 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/RenewableWakeLock.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/android/system/RenewableWakeLock.java @@ -1,18 +1,19 @@ package org.briarproject.mailbox.android.system; +import static org.briarproject.mailbox.core.util.LogUtils.info; +import static org.briarproject.mailbox.core.util.LogUtils.trace; +import static org.briarproject.mailbox.core.util.LogUtils.warn; +import static org.slf4j.LoggerFactory.getLogger; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.logging.Level.FINE; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static java.util.logging.Logger.getLogger; import android.os.PowerManager; import android.os.PowerManager.WakeLock; +import org.slf4j.Logger; + import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; -import java.util.logging.Logger; import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; @@ -21,8 +22,7 @@ import javax.annotation.concurrent.ThreadSafe; @ThreadSafe class RenewableWakeLock implements SharedWakeLock { - private static final Logger LOG = - getLogger(RenewableWakeLock.class.getName()); + private static final Logger LOG = getLogger(RenewableWakeLock.class); private final PowerManager powerManager; private final ScheduledExecutorService scheduledExecutorService; @@ -61,9 +61,7 @@ class RenewableWakeLock implements SharedWakeLock { synchronized (lock) { refCount++; if (refCount == 1) { - if (LOG.isLoggable(INFO)) { - LOG.info("Acquiring wake lock " + tag); - } + info(LOG, () -> "Acquiring wake lock " + tag); wakeLock = powerManager.newWakeLock(levelAndFlags, tag); // We do our own reference counting so we can replace the lock // TODO: Check whether using a ref-counted wake lock affects @@ -73,26 +71,24 @@ class RenewableWakeLock implements SharedWakeLock { future = scheduledExecutorService.schedule(this::renew, durationMs, MILLISECONDS); acquired = android.os.SystemClock.elapsedRealtime(); - } else if (LOG.isLoggable(FINE)) { - LOG.fine("Wake lock " + tag + " has " + refCount + " holders"); + } else { + trace(LOG, () -> "Wake lock " + tag + " has " + refCount + " holders"); } } } private void renew() { - if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag); + info(LOG, () -> "Renewing wake lock " + tag); synchronized (lock) { if (wakeLock == null) { LOG.info("Already released"); return; } - if (LOG.isLoggable(FINE)) { - LOG.fine("Wake lock " + tag + " has " + refCount + " holders"); - } + trace(LOG, () -> "Wake lock " + tag + " has " + refCount + " holders"); long now = android.os.SystemClock.elapsedRealtime(); long expiry = acquired + durationMs + safetyMarginMs; - if (now > expiry && LOG.isLoggable(WARNING)) { - LOG.warning("Wake lock expired " + (now - expiry) + " ms ago"); + if (now > expiry) { + warn(LOG, () -> "Wake lock expired " + (now - expiry) + " ms ago"); } WakeLock oldWakeLock = wakeLock; wakeLock = powerManager.newWakeLock(levelAndFlags, tag); @@ -110,16 +106,14 @@ class RenewableWakeLock implements SharedWakeLock { synchronized (lock) { refCount--; if (refCount == 0) { - if (LOG.isLoggable(INFO)) { - LOG.info("Releasing wake lock " + tag); - } + info(LOG, () -> "Releasing wake lock " + tag); requireNonNull(future).cancel(false); future = null; requireNonNull(wakeLock).release(); wakeLock = null; acquired = 0; - } else if (LOG.isLoggable(FINE)) { - LOG.fine("Wake lock " + tag + " has " + refCount + " holders"); + } else { + trace(LOG, () -> "Wake lock " + tag + " has " + refCount + " holders"); } } } diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorModule.kt b/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorModule.kt index d1eb0cd88b383bce439f0f99c1b786976b9c75e7..b44156e1409ca3801c2e3c8a39d376c389e9b5de 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorModule.kt +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorModule.kt @@ -13,6 +13,8 @@ import org.briarproject.mailbox.core.lifecycle.LifecycleManager import org.briarproject.mailbox.core.system.Clock import org.briarproject.mailbox.core.system.LocationUtils import org.briarproject.mailbox.core.system.ResourceProvider +import org.slf4j.Logger +import org.slf4j.LoggerFactory.getLogger import java.util.concurrent.Executor import javax.inject.Singleton @@ -20,6 +22,10 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) internal class AndroidTorModule { + companion object { + private val LOG: Logger = getLogger(AndroidTorModule::class.java) + } + @Provides @Singleton fun provideResourceProvider(@ApplicationContext ctx: Context): ResourceProvider { @@ -69,7 +75,7 @@ internal class AndroidTorModule { else -> continue } } -// LOG.info("Tor is not supported on this architecture") + LOG.info("Tor is not supported on this architecture") return "" // TODO } diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorPlugin.java b/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorPlugin.java index d25ee11357e787d1e0108329863e51b9a8a7859e..b23a4d321eafc3e8c3cf3ed4675a9de74f6f1161 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorPlugin.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/core/tor/AndroidTorPlugin.java @@ -1,9 +1,9 @@ package org.briarproject.mailbox.core.tor; import static android.os.Build.VERSION.SDK_INT; +import static org.briarproject.mailbox.core.util.LogUtils.info; +import static org.slf4j.LoggerFactory.getLogger; import static java.util.Arrays.asList; -import static java.util.logging.Level.INFO; -import static java.util.logging.Logger.getLogger; import android.content.Context; import android.content.pm.PackageInfo; @@ -16,6 +16,7 @@ import org.briarproject.mailbox.android.api.system.AndroidWakeLockManager; import org.briarproject.mailbox.core.system.Clock; import org.briarproject.mailbox.core.system.LocationUtils; import org.briarproject.mailbox.core.system.ResourceProvider; +import org.slf4j.Logger; import java.io.File; import java.io.FileInputStream; @@ -25,7 +26,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; -import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -37,8 +37,7 @@ public class AndroidTorPlugin extends TorPlugin { private static final String TOR_LIB_NAME = "libtor.so"; private static final String OBFS4_LIB_NAME = "libobfs4proxy.so"; - private static final Logger LOG = - getLogger(AndroidTorPlugin.class.getName()); + private static final Logger LOG = getLogger(AndroidTorPlugin.class); private final Context ctx; private final AndroidWakeLock wakeLock; @@ -152,10 +151,8 @@ public class AndroidTorPlugin extends TorPlugin { for (ZipEntry e = zin.getNextEntry(); e != null; e = zin.getNextEntry()) { if (libPaths.contains(e.getName())) { - if (LOG.isLoggable(INFO)) { - LOG.info("Extracting " + e.getName() - + " from " + apk.getAbsolutePath()); - } + String ex = e.getName(); + info(LOG, () -> "Extracting " + ex + " from " + apk.getAbsolutePath()); extract(zin, dest); // Zip input stream will be closed return; } diff --git a/mailbox-cli/build.gradle b/mailbox-cli/build.gradle index e0c9c7d51f2858d7f9709579e9a58a236085214c..c2d1a7c948c1857df79b5ef734ed4a0a69dfac98 100644 --- a/mailbox-cli/build.gradle +++ b/mailbox-cli/build.gradle @@ -15,7 +15,7 @@ configurations { dependencies { implementation project(path: ':mailbox-core', configuration: 'default') - implementation 'org.slf4j:slf4j-simple:1.7.30' + implementation "ch.qos.logback:logback-classic:1.2.5" implementation 'com.github.ajalt:clikt:2.2.0' def jna_version = '5.8.0' diff --git a/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt b/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt index 22f7f445ba12c2c1659a721a5d3a9b8dbff308fe..e47a3d7fd7a47b953937453d8b77b877766d4e54 100644 --- a/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt +++ b/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt @@ -1,5 +1,7 @@ package org.briarproject.mailbox.cli +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.Logger import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.counted import com.github.ajalt.clikt.parameters.options.flag @@ -7,8 +9,7 @@ import com.github.ajalt.clikt.parameters.options.option import org.briarproject.mailbox.core.CoreEagerSingletons import org.briarproject.mailbox.core.JavaCliEagerSingletons import org.briarproject.mailbox.core.lifecycle.LifecycleManager -import org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY -import java.lang.System.setProperty +import org.slf4j.LoggerFactory.getLogger import java.util.logging.Level.ALL import java.util.logging.Level.INFO import java.util.logging.Level.WARNING @@ -20,7 +21,7 @@ class Main : CliktCommand( help = "Command line interface for the Briar Mailbox" ) { private val debug by option("--debug", "-d", help = "Enable printing of debug messages").flag( - default = true//false + default = false ) private val verbosity by option( "--verbose", @@ -39,19 +40,20 @@ class Main : CliktCommand( override fun run() { // logging - val levelSlf4j = if (debug) "DEBUG" else when (verbosity) { - 0 -> "WARN" - 1 -> "INFO" - else -> "DEBUG" + val levelSlf4j = if (debug) Level.DEBUG else when (verbosity) { + 0 -> Level.WARN + 1 -> Level.INFO + else -> Level.DEBUG } val level = if (debug) ALL else when (verbosity) { 0 -> WARNING 1 -> INFO else -> ALL } - setProperty(DEFAULT_LOG_LEVEL_KEY, levelSlf4j) + (getLogger(Logger.ROOT_LOGGER_NAME) as Logger).level = levelSlf4j LogManager.getLogManager().getLogger("").level = level + getLogger(this.javaClass).debug("Hello Mailbox") println("Hello Mailbox") val javaCliComponent = DaggerJavaCliComponent.builder().build() diff --git a/mailbox-cli/src/main/java/org/briarproject/mailbox/core/tor/JavaTorModule.kt b/mailbox-cli/src/main/java/org/briarproject/mailbox/core/tor/JavaTorModule.kt index 53d14fc7da85d2293c5fe2642618d7ff0eff6275..f8421ef636326b1ef85ff3e94d4ecc6e9b56f51a 100644 --- a/mailbox-cli/src/main/java/org/briarproject/mailbox/core/tor/JavaTorModule.kt +++ b/mailbox-cli/src/main/java/org/briarproject/mailbox/core/tor/JavaTorModule.kt @@ -10,6 +10,8 @@ import org.briarproject.mailbox.core.system.Clock import org.briarproject.mailbox.core.system.LocationUtils import org.briarproject.mailbox.core.system.ResourceProvider import org.briarproject.mailbox.core.util.OsUtils.isLinux +import org.slf4j.Logger +import org.slf4j.LoggerFactory import java.io.File import java.util.concurrent.Executor import javax.inject.Singleton @@ -18,6 +20,10 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) internal class JavaTorModule { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(JavaTorModule::class.java) + } + @Provides @Singleton fun provideResourceProvider() = ResourceProvider { name, extension -> @@ -56,9 +62,9 @@ internal class JavaTorModule { private val architecture: String get() { if (isLinux()) { -// if (LOG.isLoggable(Level.INFO)) { -// LOG.info("System's os.arch is $arch") -// } + if (LOG.isInfoEnabled) { + LOG.info("System's os.arch is ${System.getProperty("os.arch")}") + } when (System.getProperty("os.arch")) { "amd64" -> { return "linux-x86_64" @@ -71,7 +77,7 @@ internal class JavaTorModule { } } } -// LOG.info("Tor is not supported on this architecture") + LOG.info("Tor is not supported on this architecture") return "" // TODO } diff --git a/mailbox-core/build.gradle b/mailbox-core/build.gradle index 8dd8fb3806806261d5caa70aa58dfbbce997a6ab..7735fd50ab055516de40d8acfbc9f818df092124 100644 --- a/mailbox-core/build.gradle +++ b/mailbox-core/build.gradle @@ -21,7 +21,7 @@ dependencies { def ktorVersion = '1.6.2' implementation "io.ktor:ktor-server-core:$ktorVersion" implementation "io.ktor:ktor-server-netty:$ktorVersion" - implementation "ch.qos.logback:logback-classic:1.2.5" + api "org.slf4j:slf4j-api:1.7.32" testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version" diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.java b/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.java index 982a62ca34ca354a90e52a6ad8bddc6a15e60726..6bd84052dfbc0304e90b6a3fb6d04699be9d50d3 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.java +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.java @@ -9,23 +9,22 @@ import static org.briarproject.mailbox.core.lifecycle.LifecycleManager.Lifecycle import static org.briarproject.mailbox.core.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING; import static org.briarproject.mailbox.core.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR; import static org.briarproject.mailbox.core.lifecycle.LifecycleManager.StartResult.SUCCESS; +import static org.briarproject.mailbox.core.util.LogUtils.info; import static org.briarproject.mailbox.core.util.LogUtils.logDuration; import static org.briarproject.mailbox.core.util.LogUtils.logException; import static org.briarproject.mailbox.core.util.LogUtils.now; -import static java.util.logging.Level.FINE; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static java.util.logging.Logger.getLogger; +import static org.briarproject.mailbox.core.util.LogUtils.trace; +import static org.slf4j.LoggerFactory.getLogger; import org.briarproject.mailbox.core.db.DatabaseComponent; import org.briarproject.mailbox.core.db.MigrationListener; +import org.slf4j.Logger; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Semaphore; -import java.util.logging.Logger; import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; @@ -33,8 +32,7 @@ import javax.inject.Inject; @ThreadSafe class LifecycleManagerImpl implements LifecycleManager, MigrationListener { - private static final Logger LOG = - getLogger(LifecycleManagerImpl.class.getName()); + private static final Logger LOG = getLogger(LifecycleManagerImpl.class); private final DatabaseComponent db; private final List<Service> services; @@ -57,23 +55,19 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { @Override public void registerService(Service s) { - if (LOG.isLoggable(INFO)) - LOG.info("Registering service " + s.getClass().getSimpleName()); + info(LOG, () -> "Registering service " + s.getClass().getSimpleName()); services.add(s); } @Override public void registerOpenDatabaseHook(OpenDatabaseHook hook) { - if (LOG.isLoggable(INFO)) { - LOG.info("Registering open database hook " - + hook.getClass().getSimpleName()); - } + info(LOG, () -> "Registering open database hook " + hook.getClass().getSimpleName()); openDatabaseHooks.add(hook); } @Override public void registerForShutdown(ExecutorService e) { - LOG.info("Registering executor " + e.getClass().getSimpleName()); + info(LOG, () -> "Registering executor " + e.getClass().getSimpleName()); executors.add(e); } @@ -87,8 +81,8 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { LOG.info("Opening database"); long start = now(); boolean reopened = db.open(this); - if (reopened) logDuration(LOG, "Reopening database", start); - else logDuration(LOG, "Creating database", start); + if (reopened) logDuration(LOG, () -> "Reopening database", start); + else logDuration(LOG, () -> "Creating database", start); LOG.info("Starting services"); state = STARTING_SERVICES; @@ -97,17 +91,14 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { for (Service s : services) { start = now(); s.startService(); - if (LOG.isLoggable(FINE)) { - logDuration(LOG, "Starting service " - + s.getClass().getSimpleName(), start); - } + logDuration(LOG, () -> "Starting service " + s.getClass().getSimpleName(), start); } state = RUNNING; startupLatch.countDown(); return SUCCESS; } catch (ServiceException e) { - logException(LOG, WARNING, e); + logException(LOG, e); return SERVICE_ERROR; } finally { startStopSemaphore.release(); @@ -129,7 +120,7 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { try { startStopSemaphore.acquire(); } catch (InterruptedException e) { - LOG.warning("Interrupted while waiting to stop services"); + LOG.warn("Interrupted while waiting to stop services"); return; } try { @@ -138,24 +129,18 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { for (Service s : services) { long start = now(); s.stopService(); - if (LOG.isLoggable(FINE)) { - logDuration(LOG, "Stopping service " - + s.getClass().getSimpleName(), start); - } + logDuration(LOG, () -> "Stopping service " + s.getClass().getSimpleName(), start); } for (ExecutorService e : executors) { - if (LOG.isLoggable(FINE)) { - LOG.fine("Stopping executor " - + e.getClass().getSimpleName()); - } + trace(LOG, () -> "Stopping executor " + e.getClass().getSimpleName()); e.shutdownNow(); } long start = now(); db.close(); - logDuration(LOG, "Closing database", start); + logDuration(LOG, () -> "Closing database", start); shutdownLatch.countDown(); } catch (ServiceException e) { - logException(LOG, WARNING, e); + logException(LOG, e); } finally { startStopSemaphore.release(); } diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt index 8741eb1edb031ffd63cfcc69a9cca35520d8ccb0..335367f3a458d93bb0aec78acd685c1db9adb53b 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/server/WebServerManager.kt @@ -8,7 +8,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.briarproject.mailbox.core.lifecycle.Service -import java.util.logging.Logger.getLogger +import org.slf4j.LoggerFactory.getLogger import javax.inject.Inject import javax.inject.Singleton @@ -17,7 +17,7 @@ class WebServerManager @Inject constructor() : Service { internal companion object { private const val PORT = 8888 - private val LOG = getLogger(WebServerManager::class.java.name) + private val LOG = getLogger(WebServerManager::class.java) } private val server by lazy { diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/tor/TorPlugin.java b/mailbox-core/src/main/java/org/briarproject/mailbox/core/tor/TorPlugin.java index eff73f5e95cf65d410d7c847eaeb59f8281af93d..5adf98ddafa69ffa85ce91326c7bb9d2318840ea 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/tor/TorPlugin.java +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/tor/TorPlugin.java @@ -10,15 +10,15 @@ import static org.briarproject.mailbox.core.tor.TorPlugin.State.INACTIVE; import static org.briarproject.mailbox.core.tor.TorPlugin.State.STARTING_STOPPING; import static org.briarproject.mailbox.core.util.IoUtils.copyAndClose; import static org.briarproject.mailbox.core.util.IoUtils.tryToClose; +import static org.briarproject.mailbox.core.util.LogUtils.info; import static org.briarproject.mailbox.core.util.LogUtils.logException; +import static org.briarproject.mailbox.core.util.LogUtils.warn; import static org.briarproject.mailbox.core.util.PrivacyUtils.scrubOnion; +import static org.slf4j.LoggerFactory.getLogger; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static java.util.Objects.requireNonNull; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static java.util.logging.Logger.getLogger; import net.freehaven.tor.control.EventHandler; import net.freehaven.tor.control.TorControlConnection; @@ -29,6 +29,7 @@ import org.briarproject.mailbox.core.lifecycle.ServiceException; import org.briarproject.mailbox.core.system.Clock; import org.briarproject.mailbox.core.system.LocationUtils; import org.briarproject.mailbox.core.system.ResourceProvider; +import org.slf4j.Logger; import java.io.EOFException; import java.io.File; @@ -46,7 +47,6 @@ import java.util.Map; import java.util.Scanner; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Logger; import java.util.zip.ZipInputStream; import javax.annotation.Nullable; @@ -55,7 +55,7 @@ import javax.annotation.concurrent.ThreadSafe; abstract class TorPlugin implements Service, EventHandler { - private static final Logger LOG = getLogger(TorPlugin.class.getName()); + private static final Logger LOG = getLogger(TorPlugin.class); private static final String[] EVENTS = { "CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR" @@ -87,14 +87,14 @@ abstract class TorPlugin implements Service, EventHandler { protected abstract long getLastUpdateTime(); TorPlugin(Executor ioExecutor, - NetworkManager networkManager, - LocationUtils locationUtils, - Clock clock, - ResourceProvider resourceProvider, - CircumventionProvider circumventionProvider, - Backoff backoff, - String architecture, - File torDirectory) { + NetworkManager networkManager, + LocationUtils locationUtils, + Clock clock, + ResourceProvider resourceProvider, + CircumventionProvider circumventionProvider, + Backoff backoff, + String architecture, + File torDirectory) { this.ioExecutor = ioExecutor; this.networkManager = networkManager; this.locationUtils = locationUtils; @@ -126,14 +126,14 @@ abstract class TorPlugin implements Service, EventHandler { if (used.getAndSet(true)) throw new IllegalStateException(); if (!torDirectory.exists()) { if (!torDirectory.mkdirs()) { - LOG.warning("Could not create Tor directory."); + LOG.warn("Could not create Tor directory."); throw new ServiceException(); } } // Install or update the assets if necessary if (!assetsAreUpToDate()) installAssets(); if (cookieFile.exists() && !cookieFile.delete()) - LOG.warning("Old auth cookie not deleted"); + LOG.warn("Old auth cookie not deleted"); // Start a new Tor process LOG.info("Starting Tor"); File torFile = getTorExecutableFile(); @@ -152,7 +152,7 @@ abstract class TorPlugin implements Service, EventHandler { throw new ServiceException(e); } // Log the process's standard output until it detaches - if (LOG.isLoggable(INFO)) { + if (LOG.isInfoEnabled()) { Scanner stdout = new Scanner(torProcess.getInputStream()); Scanner stderr = new Scanner(torProcess.getErrorStream()); while (stdout.hasNextLine() || stderr.hasNextLine()) { @@ -170,16 +170,15 @@ abstract class TorPlugin implements Service, EventHandler { // Wait for the process to detach or exit int exit = torProcess.waitFor(); if (exit != 0) { - if (LOG.isLoggable(WARNING)) - LOG.warning("Tor exited with value " + exit); + warn(LOG, () -> "Tor exited with value " + exit); throw new ServiceException(); } // Wait for the auth cookie file to be created/updated long start = clock.currentTimeMillis(); while (cookieFile.length() < 32) { if (clock.currentTimeMillis() - start > COOKIE_TIMEOUT_MS) { - LOG.warning("Auth cookie not created"); - if (LOG.isLoggable(INFO)) listFiles(torDirectory); + LOG.warn("Auth cookie not created"); + if (LOG.isInfoEnabled()) listFiles(torDirectory); throw new ServiceException(); } //noinspection BusyWait @@ -187,7 +186,7 @@ abstract class TorPlugin implements Service, EventHandler { } LOG.info("Auth cookie created"); } catch (InterruptedException e) { - LOG.warning("Interrupted while starting Tor"); + LOG.warn("Interrupted while starting Tor"); Thread.currentThread().interrupt(); throw new ServiceException(); } @@ -232,7 +231,7 @@ abstract class TorPlugin implements Service, EventHandler { extract(getGeoIpInputStream(), geoIpFile); extract(getConfigInputStream(), configFile); if (!doneFile.createNewFile()) - LOG.warning("Failed to create done file"); + LOG.warn("Failed to create done file"); } catch (IOException e) { throw new ServiceException(e); } @@ -244,16 +243,14 @@ abstract class TorPlugin implements Service, EventHandler { } protected void installTorExecutable() throws IOException { - if (LOG.isLoggable(INFO)) - LOG.info("Installing Tor binary for " + architecture); + info(LOG, () -> "Installing Tor binary for " + architecture); File torFile = getTorExecutableFile(); extract(getTorInputStream(), torFile); if (!torFile.setExecutable(true, true)) throw new IOException(); } protected void installObfs4Executable() throws IOException { - if (LOG.isLoggable(INFO)) - LOG.info("Installing obfs4proxy binary for " + architecture); + info(LOG, () -> "Installing obfs4proxy binary for " + architecture); File obfs4File = getObfs4ExecutableFile(); extract(getObfs4InputStream(), obfs4File); if (!obfs4File.setExecutable(true, true)) throw new IOException(); @@ -309,7 +306,7 @@ abstract class TorPlugin implements Service, EventHandler { } return b; } finally { - tryToClose(in, LOG, WARNING); + tryToClose(in, LOG); } } @@ -333,23 +330,21 @@ abstract class TorPlugin implements Service, EventHandler { response = controlConnection.addOnion(privKey, portLines); } } catch (IOException e) { - logException(LOG, WARNING, e); + logException(LOG, e); return; } if (!response.containsKey(HS_ADDRESS)) { - LOG.warning("Tor did not return a hidden service address"); + LOG.warn("Tor did not return a hidden service address"); return; } if (privKey == null && !response.containsKey(HS_PRIVKEY)) { - LOG.warning("Tor did not return a private key"); + LOG.warn("Tor did not return a private key"); return; } String onion3 = response.get(HS_ADDRESS); - if (LOG.isLoggable(INFO)) { - LOG.info("V3 hidden service " + scrubOnion(onion3)); - } + info(LOG, () -> "V3 hidden service " + scrubOnion(onion3)); // TODO remove - LOG.warning("V3 hidden service: http://" + onion3 + ".onion"); + LOG.warn("V3 hidden service: http://" + onion3 + ".onion"); if (privKey == null) { // TODO Save the hidden service's onion hostname // p.put(PROP_ONION_V3, onion3); @@ -387,7 +382,7 @@ abstract class TorPlugin implements Service, EventHandler { @Override public void stopService() { ServerSocket ss = state.setStopped(); - tryToClose(ss, LOG, WARNING); + tryToClose(ss, LOG); if (controlSocket != null && controlConnection != null) { try { LOG.info("Stopping Tor"); @@ -395,7 +390,7 @@ abstract class TorPlugin implements Service, EventHandler { controlConnection.shutdownTor("TERM"); controlSocket.close(); } catch (IOException e) { - logException(LOG, WARNING, e); + logException(LOG, e); } } } @@ -415,8 +410,7 @@ abstract class TorPlugin implements Service, EventHandler { @Override public void orConnStatus(String status, String orName) { - if (LOG.isLoggable(INFO)) - LOG.info("OR connection " + status + " " + orName); + info(LOG, () -> "OR connection " + status + " " + orName); if (status.equals("CLOSED") || status.equals("FAILED")) { // Check whether we've lost connectivity updateConnectionStatus(networkManager.getNetworkStatus() @@ -434,7 +428,7 @@ abstract class TorPlugin implements Service, EventHandler { @Override public void message(String severity, String msg) { - if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg); + info(LOG, () -> severity + " " + msg); if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) { state.setBootstrapped(); backoff.reset(); @@ -457,7 +451,7 @@ abstract class TorPlugin implements Service, EventHandler { try { if (state.isTorRunning()) enableNetwork(false); } catch (IOException ex) { - logException(LOG, WARNING, ex); + logException(LOG, ex); } }); } @@ -473,7 +467,7 @@ abstract class TorPlugin implements Service, EventHandler { circumventionProvider.isTorProbablyBlocked(country); boolean bridgesWork = circumventionProvider.doBridgesWork(country); - if (LOG.isLoggable(INFO)) { + if (LOG.isInfoEnabled()) { LOG.info("Online: " + online + ", wifi: " + wifi + ", IPv6 only: " + ipv6Only); if (country.isEmpty()) LOG.info("Country code unknown"); @@ -512,7 +506,7 @@ abstract class TorPlugin implements Service, EventHandler { } enableNetwork(enableNetwork); } catch (IOException e) { - logException(LOG, WARNING, e); + logException(LOG, e); } }); } diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/IoUtils.java b/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/IoUtils.java index 116363f427b252ecee8ba8796460627f9c92db5f..5c9befdefb6dda6dbdfd46dfeea83e547e1a0cf8 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/IoUtils.java +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/IoUtils.java @@ -1,7 +1,10 @@ package org.briarproject.mailbox.core.util; import static org.briarproject.mailbox.core.util.LogUtils.logException; -import static java.util.logging.Level.WARNING; +import static org.briarproject.mailbox.core.util.LogUtils.warn; +import static org.slf4j.LoggerFactory.getLogger; + +import org.slf4j.Logger; import java.io.Closeable; import java.io.EOFException; @@ -11,113 +14,104 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.Nullable; public class IoUtils { - private static final Logger LOG = Logger.getLogger(IoUtils.class.getName()); - - public static void deleteFileOrDir(File f) { - if (f.isFile()) { - delete(f); - } else if (f.isDirectory()) { - File[] children = f.listFiles(); - if (children == null) { - if (LOG.isLoggable(WARNING)) { - LOG.warning("Could not list files in " - + f.getAbsolutePath()); - } - } else { - for (File child : children) deleteFileOrDir(child); - } - delete(f); - } - } - - private static void delete(File f) { - if (!f.delete() && LOG.isLoggable(WARNING)) - LOG.warning("Could not delete " + f.getAbsolutePath()); - } - - public static void copyAndClose(InputStream in, OutputStream out) { - byte[] buf = new byte[4096]; - try { - while (true) { - int read = in.read(buf); - if (read == -1) break; - out.write(buf, 0, read); - } - in.close(); - out.flush(); - out.close(); - } catch (IOException e) { - tryToClose(in, LOG, WARNING); - tryToClose(out, LOG, WARNING); - } - } - - public static void tryToClose(@Nullable Closeable c, Logger logger, - Level level) { - try { - if (c != null) c.close(); - } catch (IOException e) { - logException(logger, level, e); - } - } - - public static void tryToClose(@Nullable Socket s, Logger logger, - Level level) { - try { - if (s != null) s.close(); - } catch (IOException e) { - logException(logger, level, e); - } - } - - public static void tryToClose(@Nullable ServerSocket ss, Logger logger, - Level level) { - try { - if (ss != null) ss.close(); - } catch (IOException e) { - logException(logger, level, e); - } - } - - public static void read(InputStream in, byte[] b) throws IOException { - int offset = 0; - while (offset < b.length) { - int read = in.read(b, offset, b.length - offset); - if (read == -1) throw new EOFException(); - offset += read; - } - } - - // Workaround for a bug in Android 7, see - // https://android-review.googlesource.com/#/c/271775/ - public static InputStream getInputStream(Socket s) throws IOException { - try { - return s.getInputStream(); - } catch (NullPointerException e) { - throw new IOException(e); - } - } - - // Workaround for a bug in Android 7, see - // https://android-review.googlesource.com/#/c/271775/ - public static OutputStream getOutputStream(Socket s) throws IOException { - try { - return s.getOutputStream(); - } catch (NullPointerException e) { - throw new IOException(e); - } - } - - public static boolean isNonEmptyDirectory(File f) { - if (!f.isDirectory()) return false; - File[] children = f.listFiles(); - return children != null && children.length > 0; - } + private static final Logger LOG = getLogger(IoUtils.class); + + public static void deleteFileOrDir(File f) { + if (f.isFile()) { + delete(f); + } else if (f.isDirectory()) { + File[] children = f.listFiles(); + if (children == null) { + warn(LOG, () -> "Could not list files in " + f.getAbsolutePath()); + } else { + for (File child : children) deleteFileOrDir(child); + } + delete(f); + } + } + + private static void delete(File f) { + if (!f.delete()) warn(LOG, () -> "Could not delete " + f.getAbsolutePath()); + } + + public static void copyAndClose(InputStream in, OutputStream out) { + byte[] buf = new byte[4096]; + try { + while (true) { + int read = in.read(buf); + if (read == -1) break; + out.write(buf, 0, read); + } + in.close(); + out.flush(); + out.close(); + } catch (IOException e) { + tryToClose(in, LOG); + tryToClose(out, LOG); + } + } + + public static void tryToClose(@Nullable Closeable c, Logger logger) { + try { + if (c != null) c.close(); + } catch (IOException e) { + logException(logger, e); + } + } + + public static void tryToClose(@Nullable Socket s, Logger logger) { + try { + if (s != null) s.close(); + } catch (IOException e) { + logException(logger, e); + } + } + + public static void tryToClose(@Nullable ServerSocket ss, Logger logger) { + try { + if (ss != null) ss.close(); + } catch (IOException e) { + logException(logger, e); + } + } + + public static void read(InputStream in, byte[] b) throws IOException { + int offset = 0; + while (offset < b.length) { + int read = in.read(b, offset, b.length - offset); + if (read == -1) throw new EOFException(); + offset += read; + } + } + + // Workaround for a bug in Android 7, see + // https://android-review.googlesource.com/#/c/271775/ + public static InputStream getInputStream(Socket s) throws IOException { + try { + return s.getInputStream(); + } catch (NullPointerException e) { + throw new IOException(e); + } + } + + // Workaround for a bug in Android 7, see + // https://android-review.googlesource.com/#/c/271775/ + public static OutputStream getOutputStream(Socket s) throws IOException { + try { + return s.getOutputStream(); + } catch (NullPointerException e) { + throw new IOException(e); + } + } + + public static boolean isNonEmptyDirectory(File f) { + if (!f.isDirectory()) return false; + File[] children = f.listFiles(); + return children != null && children.length > 0; + } } diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/LogUtils.java b/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/LogUtils.java deleted file mode 100644 index 3fb3434b8337c028aef87b6b7bc8c69b4ea02e82..0000000000000000000000000000000000000000 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/LogUtils.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.briarproject.mailbox.core.util; - -import static java.util.logging.Level.FINE; - -import java.io.File; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class LogUtils { - - private static final int NANOS_PER_MILLI = 1000 * 1000; - - /** - * Returns the elapsed time in milliseconds since some arbitrary - * starting time. This is only useful for measuring elapsed time. - */ - public static long now() { - return System.nanoTime() / NANOS_PER_MILLI; - } - - /** - * Logs the duration of a task. - * - * @param logger the logger to use - * @param task a description of the task - * @param start the start time of the task, as returned by {@link #now()} - */ - public static void logDuration(Logger logger, String task, long start) { - if (logger.isLoggable(FINE)) { - long duration = now() - start; - logger.fine(task + " took " + duration + " ms"); - } - } - - public static void logException(Logger logger, Level level, Throwable t) { - if (logger.isLoggable(level)) logger.log(level, t.toString(), t); - } - - public static void logFileOrDir(Logger logger, Level level, File f) { - if (logger.isLoggable(level)) { - if (f.isFile()) { - logWithType(logger, level, f, "F"); - } else if (f.isDirectory()) { - logWithType(logger, level, f, "D"); - File[] children = f.listFiles(); - if (children != null) { - for (File child : children) - logFileOrDir(logger, level, child); - } - } else if (f.exists()) { - logWithType(logger, level, f, "?"); - } - } - } - - private static void logWithType(Logger logger, Level level, File f, - String type) { - logger.log(level, type + " " + f.getAbsolutePath() + " " + f.length()); - } -} diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/LogUtils.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/LogUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..398094bb1282c2d214ac5a215df7a695e9bb981d --- /dev/null +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/util/LogUtils.kt @@ -0,0 +1,62 @@ +package org.briarproject.mailbox.core.util + +import org.slf4j.Logger + +object LogUtils { + + private const val NANOS_PER_MILLI = 1000 * 1000 + + @JvmStatic + fun Logger.trace(msg: () -> String) { + if (isTraceEnabled) trace(msg()) + } + + @JvmStatic + fun Logger.debug(msg: () -> String) { + if (isDebugEnabled) debug(msg()) + } + + @JvmStatic + fun Logger.info(msg: () -> String) { + if (isInfoEnabled) info(msg()) + } + + @JvmStatic + fun Logger.warn(msg: () -> String) { + if (isWarnEnabled) warn(msg()) + } + + @JvmStatic + fun Logger.error(msg: () -> String) { + if (isErrorEnabled) error(msg()) + } + + /** + * Returns the elapsed time in milliseconds since some arbitrary + * starting time. This is only useful for measuring elapsed time. + */ + @JvmStatic + fun now(): Long { + return System.nanoTime() / NANOS_PER_MILLI + } + + /** + * Logs the duration of a task. + * + * @param logger the logger to use + * @param task a description of the task + * @param start the start time of the task, as returned by [.now] + */ + @JvmStatic + fun logDuration(logger: Logger, msg: () -> String, start: Long) { + logger.trace { + val duration = now() - start + "${msg()} took $duration ms" + } + } + + @JvmStatic + fun logException(logger: Logger, t: Throwable) { + if (logger.isWarnEnabled) logger.warn(t.toString(), t) + } +}