aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/app/src/main/java/com/wireguard/android/util/ExceptionLoggers.java
blob: 199b1fbddb5810238b94368c79cb44d1f330438a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * Copyright © 2017-2018 WireGuard LLC. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

package com.wireguard.android.util;

import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.util.Log;

import com.wireguard.android.Application;
import com.wireguard.android.R;
import com.wireguard.config.ParseException;
import com.wireguard.crypto.Key;

import java9.util.concurrent.CompletionException;
import java9.util.function.BiConsumer;

/**
 * Helpers for logging exceptions from asynchronous tasks. These can be passed to
 * {@code CompletionStage.whenComplete()} at the end of an asynchronous future chain.
 */

public enum ExceptionLoggers implements BiConsumer<Object, Throwable> {
    D(Log.DEBUG),
    E(Log.ERROR);

    private static final String TAG = "WireGuard/" + ExceptionLoggers.class.getSimpleName();

    private final int priority;

    ExceptionLoggers(final int priority) {
        this.priority = priority;
    }

    public static Throwable unwrap(final Throwable throwable) {
        if (throwable instanceof CompletionException && throwable.getCause() != null)
            return throwable.getCause();
        return throwable;
    }

    public static String unwrapMessage(final Throwable throwable) {
        final Throwable innerThrowable = unwrap(throwable);
        final Resources resources = Application.get().getResources();
        String message;
        if (innerThrowable instanceof ParseException) {
            final ParseException parseException = (ParseException) innerThrowable;
            message = resources.getString(R.string.parse_error, parseException.getText(), parseException.getContext());
            if (parseException.getMessage() != null)
                message += ": " + parseException.getMessage();
        } else if (innerThrowable instanceof Key.KeyFormatException) {
            final Key.KeyFormatException keyFormatException = (Key.KeyFormatException) innerThrowable;
            switch (keyFormatException.getFormat()) {
                case BASE64:
                    message = resources.getString(R.string.key_length_base64_exception_message);
                    break;
                case BINARY:
                    message = resources.getString(R.string.key_length_exception_message);
                    break;
                case HEX:
                    message = resources.getString(R.string.key_length_hex_exception_message);
                    break;
                default:
                    // Will never happen, as getFormat is not nullable.
                    message = null;
            }
        } else {
            message = throwable.getMessage();
        }
        return message != null ? message : innerThrowable.getClass().getSimpleName();
    }

    @Override
    public void accept(final Object result, @Nullable final Throwable throwable) {
        if (throwable != null)
            Log.println(Log.ERROR, TAG, Log.getStackTraceString(throwable));
        else if (priority <= Log.DEBUG)
            Log.println(priority, TAG, "Future completed successfully");
    }
}