diff options
author | Samuel Holland <samuel@sholland.org> | 2018-12-15 14:45:14 -0600 |
---|---|---|
committer | Samuel Holland <samuel@sholland.org> | 2018-12-15 14:46:23 -0600 |
commit | 2e8d566bd42ac747ad276eb5e328ee2303c48c26 (patch) | |
tree | 50cd35a1bc93e6668a9db982af50b7e5b70c6e1e /app/src/main/java/com/wireguard/android/util/ErrorMessages.java | |
parent | Provide semantically meaningful exceptions for translation (diff) | |
download | wireguard-android-2e8d566bd42ac747ad276eb5e328ee2303c48c26.tar.xz wireguard-android-2e8d566bd42ac747ad276eb5e328ee2303c48c26.zip |
Clean up error messages
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'app/src/main/java/com/wireguard/android/util/ErrorMessages.java')
-rw-r--r-- | app/src/main/java/com/wireguard/android/util/ErrorMessages.java | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/app/src/main/java/com/wireguard/android/util/ErrorMessages.java b/app/src/main/java/com/wireguard/android/util/ErrorMessages.java new file mode 100644 index 00000000..0f49448c --- /dev/null +++ b/app/src/main/java/com/wireguard/android/util/ErrorMessages.java @@ -0,0 +1,130 @@ +/* + * Copyright © 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 com.wireguard.android.Application; +import com.wireguard.android.R; +import com.wireguard.config.BadConfigException; +import com.wireguard.config.BadConfigException.Location; +import com.wireguard.config.BadConfigException.Reason; +import com.wireguard.config.InetEndpoint; +import com.wireguard.config.InetNetwork; +import com.wireguard.config.ParseException; +import com.wireguard.crypto.Key.Format; +import com.wireguard.crypto.KeyFormatException; +import com.wireguard.crypto.KeyFormatException.Type; + +import java.net.InetAddress; +import java.util.EnumMap; +import java.util.Map; + +import java9.util.Maps; + +public final class ErrorMessages { + private static final Map<Reason, Integer> BCE_REASON_MAP = new EnumMap<>(Maps.of( + Reason.INVALID_KEY, R.string.bad_config_reason_invalid_key, + Reason.INVALID_NUMBER, R.string.bad_config_reason_invalid_number, + Reason.INVALID_VALUE, R.string.bad_config_reason_invalid_value, + Reason.MISSING_ATTRIBUTE, R.string.bad_config_reason_missing_attribute, + Reason.MISSING_SECTION, R.string.bad_config_reason_missing_section, + Reason.MISSING_VALUE, R.string.bad_config_reason_missing_value, + Reason.SYNTAX_ERROR, R.string.bad_config_reason_syntax_error, + Reason.UNKNOWN_ATTRIBUTE, R.string.bad_config_reason_unknown_attribute, + Reason.UNKNOWN_SECTION, R.string.bad_config_reason_unknown_section + )); + private static final Map<Format, Integer> KFE_FORMAT_MAP = new EnumMap<>(Maps.of( + Format.BASE64, R.string.key_length_explanation_base64, + Format.BINARY, R.string.key_length_explanation_binary, + Format.HEX, R.string.key_length_explanation_hex + )); + private static final Map<Type, Integer> KFE_TYPE_MAP = new EnumMap<>(Maps.of( + Type.CONTENTS, R.string.key_contents_error, + Type.LENGTH, R.string.key_length_error + )); + private static final Map<Class, Integer> PE_CLASS_MAP = Maps.of( + InetAddress.class, R.string.parse_error_inet_address, + InetEndpoint.class, R.string.parse_error_inet_endpoint, + InetNetwork.class, R.string.parse_error_inet_network, + Integer.class, R.string.parse_error_integer + ); + + private ErrorMessages() { + // Prevent instantiation + } + + public static String get(@Nullable final Throwable throwable) { + final Resources resources = Application.get().getResources(); + if (throwable == null) + return resources.getString(R.string.unknown_error); + final Throwable rootCause = rootCause(throwable); + final String message; + if (rootCause instanceof BadConfigException) { + final BadConfigException bce = (BadConfigException) rootCause; + final String reason = getBadConfigExceptionReason(resources, bce); + final String context = bce.getLocation() == Location.TOP_LEVEL ? + resources.getString(R.string.bad_config_context_top_level, + bce.getSection().getName()) : + resources.getString(R.string.bad_config_context, + bce.getSection().getName(), + bce.getLocation().getName()); + final String explanation = getBadConfigExceptionExplanation(resources, bce); + message = resources.getString(R.string.bad_config_error, reason, context) + explanation; + } else if (rootCause.getMessage() != null) { + message = rootCause.getMessage(); + } else { + final String errorType = rootCause.getClass().getSimpleName(); + message = resources.getString(R.string.generic_error, errorType); + } + return message; + } + + private static String getBadConfigExceptionExplanation(final Resources resources, + final BadConfigException bce) { + if (bce.getCause() instanceof KeyFormatException) { + final KeyFormatException kfe = (KeyFormatException) bce.getCause(); + if (kfe.getType() == Type.LENGTH) + return resources.getString(KFE_FORMAT_MAP.get(kfe.getFormat())); + } else if (bce.getCause() instanceof ParseException) { + final ParseException pe = (ParseException) bce.getCause(); + if (pe.getMessage() != null) + return ": " + pe.getMessage(); + } else if (bce.getLocation() == Location.LISTEN_PORT) { + return resources.getString(R.string.bad_config_explanation_udp_port); + } else if (bce.getLocation() == Location.MTU) { + return resources.getString(R.string.bad_config_explanation_positive_number); + } else if (bce.getLocation() == Location.PERSISTENT_KEEPALIVE) { + return resources.getString(R.string.bad_config_explanation_pka); + } + return ""; + } + + private static String getBadConfigExceptionReason(final Resources resources, + final BadConfigException bce) { + if (bce.getCause() instanceof KeyFormatException) { + final KeyFormatException kfe = (KeyFormatException) bce.getCause(); + return resources.getString(KFE_TYPE_MAP.get(kfe.getType())); + } else if (bce.getCause() instanceof ParseException) { + final ParseException pe = (ParseException) bce.getCause(); + final String type = resources.getString(PE_CLASS_MAP.containsKey(pe.getParsingClass()) ? + PE_CLASS_MAP.get(pe.getParsingClass()) : R.string.parse_error_generic); + return resources.getString(R.string.parse_error_reason, type, pe.getText()); + } + return resources.getString(BCE_REASON_MAP.get(bce.getReason()), bce.getText()); + } + + private static Throwable rootCause(final Throwable throwable) { + Throwable cause = throwable; + while (cause.getCause() != null) { + if (cause instanceof BadConfigException) + break; + cause = cause.getCause(); + } + return cause; + } +} |