]> git.basschouten.com Git - openhab-addons.git/blob
5fc4f5ad4c002827799d6f5d21aeadb6c5c2a7de
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.shelly.internal.api;
14
15 import static org.openhab.binding.shelly.internal.util.ShellyUtils.getString;
16
17 import java.net.ConnectException;
18 import java.net.MalformedURLException;
19 import java.net.NoRouteToHostException;
20 import java.net.PortUnreachableException;
21 import java.net.SocketException;
22 import java.net.SocketTimeoutException;
23 import java.net.UnknownHostException;
24 import java.text.MessageFormat;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.TimeoutException;
27
28 import org.eclipse.jdt.annotation.NonNullByDefault;
29 import org.eclipse.jdt.annotation.Nullable;
30
31 import com.google.gson.JsonSyntaxException;
32
33 /**
34  * The {@link CarNetException} implements an extension to the standard Exception class. This allows to keep also the
35  * result of the last API call (e.g. including the http status code in the message).
36  *
37  * @author Markus Michels - Initial contribution
38  */
39 @NonNullByDefault
40 public class ShellyApiException extends Exception {
41     private static final long serialVersionUID = -5809459454769761821L;
42
43     private ShellyApiResult apiResult = new ShellyApiResult();
44     private static final String NONE = "none";
45
46     public ShellyApiException(Exception exception) {
47         super(exception);
48     }
49
50     public ShellyApiException(String message) {
51         super(message);
52     }
53
54     public ShellyApiException(ShellyApiResult res) {
55         super(NONE);
56         apiResult = res;
57     }
58
59     public ShellyApiException(String message, Exception exception) {
60         super(message, exception);
61     }
62
63     public ShellyApiException(ShellyApiResult result, Exception exception) {
64         super(exception);
65         apiResult = result;
66     }
67
68     @Override
69     public @Nullable String getMessage() {
70         return isEmpty() ? "" : nonNullString(super.getMessage());
71     }
72
73     @Override
74     public String toString() {
75         String message = nonNullString(super.getMessage()).replace("java.util.concurrent.ExecutionException: ", "")
76                 .replace("java.net.", "");
77         String cause = getCauseClass().toString();
78         String url = apiResult.getUrl();
79         if (!isEmpty()) {
80             if (isUnknownHost()) {
81                 String[] string = message.split(": "); // java.net.UnknownHostException: api.rach.io
82                 message = MessageFormat.format("Unable to connect to {0} (Unknown host / Network down / Low signal)",
83                         string[1]);
84             } else if (isMalformedURL()) {
85                 message = "Invalid URL: " + url;
86             } else if (isTimeout()) {
87                 message = "API Timeout for " + url;
88             } else if (!isConnectionError()) {
89                 message = message + "(" + cause + ")";
90             }
91         } else {
92             message = apiResult.toString();
93         }
94         return message;
95     }
96
97     public boolean isJsonError() {
98         return getString(getMessage()).startsWith("Unable to create object of type");
99     }
100
101     public boolean isApiException() {
102         return getCauseClass() == ShellyApiException.class;
103     }
104
105     public boolean isTimeout() {
106         Class<?> extype = !isEmpty() ? getCauseClass() : null;
107         return (extype != null) && ((extype == TimeoutException.class) || extype == InterruptedException.class
108                 || extype == SocketTimeoutException.class
109                 || nonNullString(getMessage()).toLowerCase().contains("timeout"));
110     }
111
112     public boolean isConnectionError() {
113         Class<?> exType = getCauseClass();
114         return isUnknownHost() || isMalformedURL() || exType == ConnectException.class
115                 || exType == SocketException.class || exType == PortUnreachableException.class
116                 || exType == NoRouteToHostException.class;
117     }
118
119     public boolean isUnknownHost() {
120         return getCauseClass() == UnknownHostException.class;
121     }
122
123     public boolean isMalformedURL() {
124         return getCauseClass() == MalformedURLException.class;
125     }
126
127     public boolean isHttpAccessUnauthorized() {
128         return apiResult.isHttpAccessUnauthorized();
129     }
130
131     public boolean isJSONException() {
132         return getCauseClass() == JsonSyntaxException.class;
133     }
134
135     public ShellyApiResult getApiResult() {
136         return apiResult;
137     }
138
139     private boolean isEmpty() {
140         return NONE.equals(nonNullString(super.getMessage()));
141     }
142
143     private static String nonNullString(@Nullable String s) {
144         return s != null ? s : "";
145     }
146
147     private Class<?> getCauseClass() {
148         Throwable cause = getCause();
149         if (cause != null && cause.getClass() == ExecutionException.class) {
150             cause = cause.getCause();
151         }
152         if (cause != null) {
153             return cause.getClass();
154         }
155         return ShellyApiException.class;
156     }
157 }