]> git.basschouten.com Git - openhab-addons.git/commitdiff
Fix SAT (#15428)
authorlsiepel <leosiepel@gmail.com>
Sat, 23 Sep 2023 15:40:31 +0000 (17:40 +0200)
committerGitHub <noreply@github.com>
Sat, 23 Sep 2023 15:40:31 +0000 (17:40 +0200)
Signed-off-by: lsiepel <leosiepel@gmail.com>
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/S3Actions.java
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/auth/AWS4SignerBase.java
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/auth/AWS4SignerForAuthorizationHeader.java
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/exception/APIException.java [new file with mode: 0644]
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/exception/AuthException.java [new file with mode: 0644]
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/util/HttpUtilException.java [new file with mode: 0644]
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/util/HttpUtils.java
bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/handler/S3BucketWatcherHandler.java

index 2ba0fd5fe0aca48e52256311af3297ded2c624a1..e876617b194e83e178102d457def5456717ec0d5 100644 (file)
@@ -15,6 +15,7 @@ package org.openhab.binding.folderwatcher.internal.api;
 import static org.eclipse.jetty.http.HttpHeader.*;
 import static org.eclipse.jetty.http.HttpMethod.*;
 
+import java.io.IOException;
 import java.io.StringReader;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -23,10 +24,13 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jetty.client.HttpClient;
@@ -34,10 +38,14 @@ import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
 import org.openhab.binding.folderwatcher.internal.api.auth.AWS4SignerBase;
 import org.openhab.binding.folderwatcher.internal.api.auth.AWS4SignerForAuthorizationHeader;
+import org.openhab.binding.folderwatcher.internal.api.exception.APIException;
+import org.openhab.binding.folderwatcher.internal.api.exception.AuthException;
+import org.openhab.binding.folderwatcher.internal.api.util.HttpUtilException;
 import org.openhab.core.io.net.http.HttpClientFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
 /**
  * The {@link S3Actions} class contains AWS S3 API implementation.
@@ -54,39 +62,44 @@ public class S3Actions {
     private String awsAccessKey;
     private String awsSecretKey;
 
-    public S3Actions(HttpClientFactory httpClientFactory, String bucketName, String region) {
+    public S3Actions(HttpClientFactory httpClientFactory, String bucketName, String region) throws APIException {
         this(httpClientFactory, bucketName, region, "", "");
     }
 
     public S3Actions(HttpClientFactory httpClientFactory, String bucketName, String region, String awsAccessKey,
-            String awsSecretKey) {
+            String awsSecretKey) throws APIException {
         this.httpClient = httpClientFactory.getCommonHttpClient();
         try {
             this.bucketUri = new URL("http://" + bucketName + ".s3." + region + ".amazonaws.com");
         } catch (MalformedURLException e) {
-            throw new RuntimeException("Unable to parse service endpoint: " + e.getMessage());
+            throw new APIException("Unable to parse service endpoint: " + e.getMessage());
         }
         this.region = region;
         this.awsAccessKey = awsAccessKey;
         this.awsSecretKey = awsSecretKey;
     }
 
-    public List<String> listBucket(String prefix) throws Exception {
+    public List<String> listBucket(String prefix) throws APIException, AuthException {
         Map<String, String> headers = new HashMap<String, String>();
         Map<String, String> params = new HashMap<String, String>();
         return listObjectsV2(prefix, headers, params);
     }
 
     private List<String> listObjectsV2(String prefix, Map<String, String> headers, Map<String, String> params)
-            throws Exception {
+            throws APIException, AuthException {
         params.put("list-type", "2");
         params.put("prefix", prefix);
         if (!awsAccessKey.isEmpty() || !awsSecretKey.isEmpty()) {
             headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256);
             AWS4SignerForAuthorizationHeader signer = new AWS4SignerForAuthorizationHeader(this.bucketUri, "GET", "s3",
                     region);
-            String authorization = signer.computeSignature(headers, params, AWS4SignerBase.EMPTY_BODY_SHA256,
-                    awsAccessKey, awsSecretKey);
+            String authorization;
+            try {
+                authorization = signer.computeSignature(headers, params, AWS4SignerBase.EMPTY_BODY_SHA256, awsAccessKey,
+                        awsSecretKey);
+            } catch (HttpUtilException e) {
+                throw new AuthException(e);
+            }
             headers.put("Authorization", authorization);
         }
 
@@ -102,15 +115,31 @@ public class S3Actions {
             request.param(paramKey, params.get(paramKey));
         }
 
-        ContentResponse contentResponse = request.send();
+        ContentResponse contentResponse;
+        try {
+            contentResponse = request.send();
+        } catch (InterruptedException | TimeoutException | ExecutionException e) {
+            throw new APIException(e);
+        }
+
         if (contentResponse.getStatus() != 200) {
-            throw new Exception("HTTP Response is not 200");
+            throw new APIException("HTTP Response is not 200");
         }
 
         DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
-        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+        DocumentBuilder docBuilder;
+        try {
+            docBuilder = docBuilderFactory.newDocumentBuilder();
+        } catch (ParserConfigurationException e) {
+            throw new APIException(e);
+        }
         InputSource is = new InputSource(new StringReader(contentResponse.getContentAsString()));
-        Document doc = docBuilder.parse(is);
+        Document doc;
+        try {
+            doc = docBuilder.parse(is);
+        } catch (SAXException | IOException e) {
+            throw new APIException(e);
+        }
         NodeList nameNodesList = doc.getElementsByTagName("Key");
         List<String> returnList = new ArrayList<>();
 
index cd872a2fa31725bc890c8a0f6c5139c33657324f..6cb2fbe6a97abf531751b44153190c2e7e47de4c 100644 (file)
@@ -28,7 +28,9 @@ import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.folderwatcher.internal.api.exception.AuthException;
 import org.openhab.binding.folderwatcher.internal.api.util.BinaryUtils;
+import org.openhab.binding.folderwatcher.internal.api.util.HttpUtilException;
 import org.openhab.binding.folderwatcher.internal.api.util.HttpUtils;
 
 /**
@@ -46,8 +48,8 @@ public abstract class AWS4SignerBase {
     public static final String SCHEME = "AWS4";
     public static final String ALGORITHM = "HMAC-SHA256";
     public static final String TERMINATOR = "aws4_request";
-    public static final String ISO8601BasicFormat = "yyyyMMdd'T'HHmmss'Z'";
-    public static final String DateStringFormat = "yyyyMMdd";
+    public static final String ISO8601_BASIC_FORMAT = "yyyyMMdd'T'HHmmss'Z'";
+    public static final String DATESTRING_FORMAT = "yyyyMMdd";
     protected URL endpointUrl;
     protected String httpMethod;
     protected String serviceName;
@@ -61,9 +63,9 @@ public abstract class AWS4SignerBase {
         this.serviceName = serviceName;
         this.regionName = regionName;
 
-        dateTimeFormat = new SimpleDateFormat(ISO8601BasicFormat);
+        dateTimeFormat = new SimpleDateFormat(ISO8601_BASIC_FORMAT);
         dateTimeFormat.setTimeZone(new SimpleTimeZone(0, "UTC"));
-        dateStampFormat = new SimpleDateFormat(DateStringFormat);
+        dateStampFormat = new SimpleDateFormat(DATESTRING_FORMAT);
         dateStampFormat.setTimeZone(new SimpleTimeZone(0, "UTC"));
     }
 
@@ -100,12 +102,12 @@ public abstract class AWS4SignerBase {
     }
 
     protected static String getCanonicalRequest(URL endpoint, String httpMethod, String queryParameters,
-            String canonicalizedHeaderNames, String canonicalizedHeaders, String bodyHash) {
+            String canonicalizedHeaderNames, String canonicalizedHeaders, String bodyHash) throws HttpUtilException {
         return httpMethod + "\n" + getCanonicalizedResourcePath(endpoint) + "\n" + queryParameters + "\n"
                 + canonicalizedHeaders + "\n" + canonicalizedHeaderNames + "\n" + bodyHash;
     }
 
-    protected static String getCanonicalizedResourcePath(URL endpoint) {
+    protected static String getCanonicalizedResourcePath(URL endpoint) throws HttpUtilException {
         if (endpoint == null) {
             return "/";
         }
@@ -122,7 +124,7 @@ public abstract class AWS4SignerBase {
         }
     }
 
-    public static String getCanonicalizedQueryString(Map<String, String> parameters) {
+    public static String getCanonicalizedQueryString(Map<String, String> parameters) throws HttpUtilException {
         if (parameters == null || parameters.isEmpty()) {
             return "";
         }
@@ -152,39 +154,39 @@ public abstract class AWS4SignerBase {
     }
 
     protected static String getStringToSign(String scheme, String algorithm, String dateTime, String scope,
-            String canonicalRequest) {
+            String canonicalRequest) throws AuthException {
         return scheme + "-" + algorithm + "\n" + dateTime + "\n" + scope + "\n"
                 + BinaryUtils.toHex(hash(canonicalRequest));
     }
 
-    public static byte[] hash(String text) {
+    public static byte[] hash(String text) throws AuthException {
         try {
             MessageDigest md = MessageDigest.getInstance("SHA-256");
             md.update(text.getBytes("UTF-8"));
             return md.digest();
         } catch (Exception e) {
-            throw new RuntimeException("Unable to compute hash while signing request: " + e.getMessage(), e);
+            throw new AuthException("Unable to compute hash while signing request: " + e.getMessage(), e);
         }
     }
 
-    public static byte[] hash(byte[] data) {
+    public static byte[] hash(byte[] data) throws AuthException {
         try {
             MessageDigest md = MessageDigest.getInstance("SHA-256");
             md.update(data);
             return md.digest();
         } catch (Exception e) {
-            throw new RuntimeException("Unable to compute hash while signing request: " + e.getMessage(), e);
+            throw new AuthException("Unable to compute hash while signing request: " + e.getMessage(), e);
         }
     }
 
-    protected static byte[] sign(String stringData, byte[] key, String algorithm) {
+    protected static byte[] sign(String stringData, byte[] key, String algorithm) throws AuthException {
         try {
             byte[] data = stringData.getBytes("UTF-8");
             Mac mac = Mac.getInstance(algorithm);
             mac.init(new SecretKeySpec(key, algorithm));
             return mac.doFinal(data);
         } catch (Exception e) {
-            throw new RuntimeException("Unable to calculate a request signature: " + e.getMessage(), e);
+            throw new AuthException("Unable to calculate a request signature: " + e.getMessage(), e);
         }
     }
 }
index db6b7cb260dc63d4fd993070825f3ba9f95a40a1..278ebf19782cff644f0e37bfe3b277c81eeada88 100644 (file)
@@ -17,7 +17,9 @@ import java.util.Date;
 import java.util.Map;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.folderwatcher.internal.api.exception.AuthException;
 import org.openhab.binding.folderwatcher.internal.api.util.BinaryUtils;
+import org.openhab.binding.folderwatcher.internal.api.util.HttpUtilException;
 
 /**
  * The {@link AWS4SignerForAuthorizationHeader} class contains methods for AWS S3 API authentication using HTTP(S)
@@ -35,7 +37,7 @@ public class AWS4SignerForAuthorizationHeader extends AWS4SignerBase {
     }
 
     public String computeSignature(Map<String, String> headers, Map<String, String> queryParameters, String bodyHash,
-            String awsAccessKey, String awsSecretKey) {
+            String awsAccessKey, String awsSecretKey) throws AuthException, HttpUtilException {
         Date now = new Date();
         String dateTimeStamp = dateTimeFormat.format(now);
         headers.put("x-amz-date", dateTimeStamp);
diff --git a/bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/exception/APIException.java b/bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/exception/APIException.java
new file mode 100644 (file)
index 0000000..645033e
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.folderwatcher.internal.api.exception;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link APIException} signal's there was a problem with interacting with the API
+ *
+ * @author Leo Siepel - initial contribution
+ * 
+ */
+@NonNullByDefault
+public class APIException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public APIException(String message) {
+        super(message);
+    }
+
+    public APIException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public APIException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/exception/AuthException.java b/bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/exception/AuthException.java
new file mode 100644 (file)
index 0000000..335763b
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.folderwatcher.internal.api.exception;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link AuthException} signal's there was a problem with authentication
+ *
+ * @author Leo Siepel - initial contribution
+ * 
+ */
+@NonNullByDefault
+public class AuthException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public AuthException(String message) {
+        super(message);
+    }
+
+    public AuthException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public AuthException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/util/HttpUtilException.java b/bundles/org.openhab.binding.folderwatcher/src/main/java/org/openhab/binding/folderwatcher/internal/api/util/HttpUtilException.java
new file mode 100644 (file)
index 0000000..22699c6
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.folderwatcher.internal.api.util;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link HttpUtilException} signal;s there was a problem with contacting the API
+ *
+ * @author Leo Siepel - initial contribution
+ * 
+ */
+@NonNullByDefault
+public class HttpUtilException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public HttpUtilException(String message) {
+        super(message);
+    }
+
+    public HttpUtilException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public HttpUtilException(Throwable cause) {
+        super(cause);
+    }
+}
index bd323a238135840210bf8d591385321801658d13..2d964f36fe24cebfa253206aed0025e8e6f5a052 100644 (file)
@@ -26,12 +26,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
  */
 @NonNullByDefault
 public class HttpUtils {
-    public static String urlEncode(String url, boolean keepPathSlash) {
+    public static String urlEncode(String url, boolean keepPathSlash) throws HttpUtilException {
         String encoded;
         try {
             encoded = URLEncoder.encode(url, "UTF-8");
         } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException("UTF-8 encoding is not supported.", e);
+            throw new HttpUtilException("UTF-8 encoding is not supported.", e);
         }
         if (keepPathSlash) {
             encoded = encoded.replace("%2F", "/");
index 9d89786bbb45b1137d9a295c91b7d3315730d5a4..c3ffe6cf49e1810be431dcab2b50d51b2503c9d6 100644 (file)
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.folderwatcher.internal.api.S3Actions;
+import org.openhab.binding.folderwatcher.internal.api.exception.APIException;
 import org.openhab.binding.folderwatcher.internal.common.WatcherCommon;
 import org.openhab.binding.folderwatcher.internal.config.S3BucketWatcherConfiguration;
 import org.openhab.core.OpenHAB;
@@ -71,12 +72,16 @@ public class S3BucketWatcherHandler extends BaseThingHandler {
     @Override
     public void initialize() {
         config = getConfigAs(S3BucketWatcherConfiguration.class);
-
-        if (config.s3Anonymous) {
-            s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion);
-        } else {
-            s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion, config.awsKey,
-                    config.awsSecret);
+        try {
+            if (config.s3Anonymous) {
+                s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion);
+            } else {
+                s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion, config.awsKey,
+                        config.awsSecret);
+            }
+        } catch (APIException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, e.getMessage());
+            return;
         }
 
         try {