2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.shelly.internal.api;
15 import java.net.MalformedURLException;
16 import java.net.UnknownHostException;
17 import java.text.MessageFormat;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.TimeoutException;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
24 import com.google.gson.JsonSyntaxException;
27 * The {@link CarNetException} implements an extension to the standard Exception class. This allows to keep also the
28 * result of the last API call (e.g. including the http status code in the message).
30 * @author Markus Michels - Initial contribution
33 public class ShellyApiException extends Exception {
34 private static final long serialVersionUID = -5809459454769761821L;
36 private ShellyApiResult apiResult = new ShellyApiResult();
37 private static String NONE = "none";
39 public ShellyApiException(Exception exception) {
43 public ShellyApiException(String message) {
47 public ShellyApiException(ShellyApiResult res) {
52 public ShellyApiException(String message, Exception exception) {
53 super(message, exception);
56 public ShellyApiException(ShellyApiResult result, Exception exception) {
62 public @Nullable String getMessage() {
63 return isEmpty() ? "" : nonNullString(super.getMessage());
67 public String toString() {
68 String message = nonNullString(super.getMessage());
69 String cause = getCauseClass().toString();
71 if (isUnknownHost()) {
72 String[] string = message.split(": "); // java.net.UnknownHostException: api.rach.io
73 message = MessageFormat.format("Unable to connect to {0} (Unknown host / Network down / Low signal)",
75 } else if (isMalformedURL()) {
76 message = MessageFormat.format("Invalid URL: {0}", apiResult.getUrl());
77 } else if (isTimeout()) {
78 message = MessageFormat.format("Device unreachable or API Timeout ({0})", apiResult.getUrl());
80 message = MessageFormat.format("{0} ({1})", message, cause);
83 message = apiResult.toString();
88 public boolean isApiException() {
89 return getCauseClass() == ShellyApiException.class;
92 public boolean isTimeout() {
93 Class<?> extype = !isEmpty() ? getCauseClass() : null;
94 return (extype != null) && ((extype == TimeoutException.class) || (extype == ExecutionException.class)
95 || (extype == InterruptedException.class) || getMessage().toLowerCase().contains("timeout"));
98 public boolean isHttpAccessUnauthorized() {
99 return apiResult.isHttpAccessUnauthorized();
102 public boolean isUnknownHost() {
103 return getCauseClass() == MalformedURLException.class;
106 public boolean isMalformedURL() {
107 return getCauseClass() == UnknownHostException.class;
110 public boolean isJSONException() {
111 return getCauseClass() == JsonSyntaxException.class;
114 public ShellyApiResult getApiResult() {
118 private boolean isEmpty() {
119 return nonNullString(super.getMessage()).equals(NONE);
122 private static String nonNullString(@Nullable String s) {
123 return s != null ? s : "";
126 private Class<?> getCauseClass() {
127 Throwable cause = getCause();
128 if (getCause() != null) {
129 return cause.getClass();
131 return ShellyApiException.class;