2 * Copyright (c) 2010-2022 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.ConnectException;
16 import java.net.MalformedURLException;
17 import java.net.NoRouteToHostException;
18 import java.net.PortUnreachableException;
19 import java.net.SocketException;
20 import java.net.SocketTimeoutException;
21 import java.net.UnknownHostException;
22 import java.text.MessageFormat;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.TimeoutException;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
29 import com.google.gson.JsonSyntaxException;
32 * The {@link CarNetException} implements an extension to the standard Exception class. This allows to keep also the
33 * result of the last API call (e.g. including the http status code in the message).
35 * @author Markus Michels - Initial contribution
38 public class ShellyApiException extends Exception {
39 private static final long serialVersionUID = -5809459454769761821L;
41 private ShellyApiResult apiResult = new ShellyApiResult();
42 private static final String NONE = "none";
44 public ShellyApiException(Exception exception) {
48 public ShellyApiException(String message) {
52 public ShellyApiException(ShellyApiResult res) {
57 public ShellyApiException(String message, Exception exception) {
58 super(message, exception);
61 public ShellyApiException(ShellyApiResult result, Exception exception) {
67 public @Nullable String getMessage() {
68 return isEmpty() ? "" : nonNullString(super.getMessage());
72 public String toString() {
73 String message = nonNullString(super.getMessage()).replace("java.util.concurrent.ExecutionException: ", "")
74 .replace("java.net.", "");
75 String cause = getCauseClass().toString();
76 String url = apiResult.getUrl();
78 if (isUnknownHost()) {
79 String[] string = message.split(": "); // java.net.UnknownHostException: api.rach.io
80 message = MessageFormat.format("Unable to connect to {0} (Unknown host / Network down / Low signal)",
82 } else if (isMalformedURL()) {
83 message = "Invalid URL: " + url;
84 } else if (isTimeout()) {
85 message = "API Timeout for " + url;
86 } else if (!isConnectionError()) {
87 message = message + "(" + cause + ")";
90 message = apiResult.toString();
95 public boolean isApiException() {
96 return getCauseClass() == ShellyApiException.class;
99 public boolean isTimeout() {
100 Class<?> extype = !isEmpty() ? getCauseClass() : null;
101 return (extype != null) && ((extype == TimeoutException.class) || extype == InterruptedException.class
102 || extype == SocketTimeoutException.class
103 || nonNullString(getMessage()).toLowerCase().contains("timeout"));
106 public boolean isConnectionError() {
107 Class<?> exType = getCauseClass();
108 return isUnknownHost() || isMalformedURL() || exType == ConnectException.class
109 || exType == SocketException.class || exType == PortUnreachableException.class
110 || exType == NoRouteToHostException.class;
113 public boolean isUnknownHost() {
114 return getCauseClass() == UnknownHostException.class;
117 public boolean isMalformedURL() {
118 return getCauseClass() == MalformedURLException.class;
121 public boolean isHttpAccessUnauthorized() {
122 return apiResult.isHttpAccessUnauthorized();
125 public boolean isJSONException() {
126 return getCauseClass() == JsonSyntaxException.class;
129 public ShellyApiResult getApiResult() {
133 private boolean isEmpty() {
134 return NONE.equals(nonNullString(super.getMessage()));
137 private static String nonNullString(@Nullable String s) {
138 return s != null ? s : "";
141 private Class<?> getCauseClass() {
142 Throwable cause = getCause();
143 if (cause != null && cause.getClass() == ExecutionException.class) {
144 cause = cause.getCause();
147 return cause.getClass();
149 return ShellyApiException.class;