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 final 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)
96 || nonNullString(getMessage()).toLowerCase().contains("timeout"));
99 public boolean isHttpAccessUnauthorized() {
100 return apiResult.isHttpAccessUnauthorized();
103 public boolean isUnknownHost() {
104 return getCauseClass() == MalformedURLException.class;
107 public boolean isMalformedURL() {
108 return getCauseClass() == UnknownHostException.class;
111 public boolean isJSONException() {
112 return getCauseClass() == JsonSyntaxException.class;
115 public ShellyApiResult getApiResult() {
119 private boolean isEmpty() {
120 return NONE.equals(nonNullString(super.getMessage()));
123 private static String nonNullString(@Nullable String s) {
124 return s != null ? s : "";
127 private Class<?> getCauseClass() {
128 Throwable cause = getCause();
130 return cause.getClass();
132 return ShellyApiException.class;