]> git.basschouten.com Git - openhab-addons.git/commitdiff
Reduce dependency on commons-io and commons-codec (#10614)
authorWouter Born <github@maindrain.net>
Fri, 30 Apr 2021 14:53:44 +0000 (16:53 +0200)
committerGitHub <noreply@github.com>
Fri, 30 Apr 2021 14:53:44 +0000 (16:53 +0200)
Signed-off-by: Wouter Born <github@maindrain.net>
20 files changed:
bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java
bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/handler/BlueGigaBridgeHandler.java
bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaSerialHandler.java
bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java
bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java
bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/IhcClient.java
bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/projectfile/ProjectFileUtils.java
bundles/org.openhab.binding.logreader/pom.xml
bundles/org.openhab.binding.minecraft/pom.xml
bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoAlbumArt.java
bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoConnection.java
bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/AbstractServlet.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/net/HttpResponse.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java
bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java
bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java
bundles/org.openhab.voice.mactts/src/test/java/org/openhab/voice/mactts/internal/MacTTSVoiceTest.java
bundles/org.openhab.voice.marytts/pom.xml
bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java

index bba44c4c4753c558c83d4ed40dc81bcb008ad65d..c3e7032e18d3553a856ced928d42718d6624ac0c 100644 (file)
@@ -23,7 +23,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.commons.io.IOUtils;
 import org.openhab.binding.allplay.internal.AllPlayBindingConstants;
 import org.openhab.binding.allplay.internal.AllPlayBindingProperties;
 import org.openhab.core.common.ThreadPoolManager;
@@ -538,7 +537,7 @@ public class AllPlayHandler extends BaseThingHandler
     private byte[] getRawDataFromUrl(String urlString) throws Exception {
         URL url = new URL(urlString);
         URLConnection connection = url.openConnection();
-        return IOUtils.toByteArray(connection.getInputStream());
+        return connection.getInputStream().readAllBytes();
     }
 
     private int convertPercentToAbsoluteVolume(PercentType percentVolume) throws SpeakerException {
index 7bd7cdb16823770598ddf6072de0f0826a9ac781..2e07e665b24caf481bcc6144cae994b6e303e539 100644 (file)
@@ -30,7 +30,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.bluetooth.AbstractBluetoothBridgeHandler;
@@ -411,10 +410,16 @@ public class BlueGigaBridgeHandler extends AbstractBluetoothBridgeHandler<BlueGi
             // Ignore all as RXTX seems to send arbitrary exceptions when BlueGiga module is detached
         } finally {
             outputStream.ifPresent(output -> {
-                IOUtils.closeQuietly(output);
+                try {
+                    output.close();
+                } catch (IOException e) {
+                }
             });
             inputStream.ifPresent(input -> {
-                IOUtils.closeQuietly(input);
+                try {
+                    input.close();
+                } catch (IOException e) {
+                }
             });
             sp.close();
             logger.debug("Closed serial port.");
index be2fad17b61bfd1f78063ed8972047b832ffe05a..8c6d803018285184182438c24565650bb68f8cdb 100644 (file)
  */
 package org.openhab.binding.bluetooth.bluegiga.internal;
 
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.openhab.binding.bluetooth.bluegiga.internal.command.gap.BlueGigaEndProcedureCommand;
 import org.slf4j.Logger;
@@ -96,7 +96,7 @@ public class BlueGigaSerialHandler {
             // Wait BlueGiga controller have stopped all activity
             Thread.sleep(100);
             logger.trace("Bytes available: {}", inputStream.available());
-            IOUtils.skipFully(inputStream, inputStream.available());
+            skipFully(inputStream, inputStream.available());
         } catch (InterruptedException e) {
             close = true;
         } catch (IOException e) {
@@ -105,6 +105,28 @@ public class BlueGigaSerialHandler {
         logger.trace("Flush done");
     }
 
+    private void skipFully(final InputStream input, final long toSkip) throws IOException {
+        if (toSkip < 0) {
+            throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip);
+        }
+
+        long remain = toSkip;
+
+        final byte[] byteArray = new byte[8192];
+        while (remain > 0) {
+            final long n = input.read(byteArray, 0, (int) Math.min(remain, byteArray.length));
+            if (n < 0) { // EOF
+                break;
+            }
+            remain -= n;
+        }
+
+        long skipped = toSkip - remain;
+        if (skipped != toSkip) {
+            throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
+        }
+    }
+
     /**
      * Requests parser thread to shutdown. Waits forever while the parser thread is getting shut down.
      */
@@ -123,8 +145,14 @@ public class BlueGigaSerialHandler {
             parserThread.interrupt();
             // Give a fair chance to shutdown nicely
             Thread.sleep(50);
-            IOUtils.closeQuietly(outputStream);
-            IOUtils.closeQuietly(inputStream);
+            try {
+                outputStream.close();
+            } catch (IOException e) {
+            }
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+            }
             parserThread.join(0);
         } catch (InterruptedException e) {
             logger.warn("Interrupted in packet parser thread shutdown join.");
index f43745c1dab0e96af6a9dba536d071623d601a8c..31fa274cca13395a110171b075e6ac1f56fd1928 100644 (file)
@@ -33,7 +33,6 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.util.StreamReaderDelegate;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.Response;
@@ -310,7 +309,8 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
                 XMLInputFactory xif = XMLInputFactory.newInstance();
                 xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
                 xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
-                XMLStreamReader xsr = xif.createXMLStreamReader(IOUtils.toInputStream(result));
+                XMLStreamReader xsr = xif
+                        .createXMLStreamReader(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
                 xsr = new PropertyRenamerDelegate(xsr);
 
                 @SuppressWarnings("unchecked")
@@ -344,7 +344,8 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
                 JAXBContext jcResponse = JAXBContext.newInstance(response);
 
                 @SuppressWarnings("unchecked")
-                T obj = (T) jcResponse.createUnmarshaller().unmarshal(IOUtils.toInputStream(result));
+                T obj = (T) jcResponse.createUnmarshaller()
+                        .unmarshal(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
 
                 return obj;
             }
index f8a7369764d5faf3c51d4e61fc53322cbab2b8a0..26c4125214f0f2a32055ae98d865eb3e46f0c8ba 100644 (file)
@@ -12,6 +12,7 @@
  */
 package org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -42,7 +43,6 @@ import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.openhab.binding.digitalstrom.internal.lib.config.Config;
 import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
@@ -459,7 +459,7 @@ public class HttpTransportImpl implements HttpTransport {
                 correctedPath = correctedPath + "/";
             }
         }
-        InputStream certInputStream = IOUtils.toInputStream(cert);
+        InputStream certInputStream = new ByteArrayInputStream(cert.getBytes(StandardCharsets.UTF_8));
         X509Certificate trustedCert;
         try {
             trustedCert = (X509Certificate) CertificateFactory.getInstance("X.509")
@@ -488,7 +488,7 @@ public class HttpTransportImpl implements HttpTransport {
     private SSLSocketFactory generateSSLContextFromPEMCertString(String pemCert) {
         if (pemCert != null && !pemCert.isBlank() && pemCert.startsWith(BEGIN_CERT)) {
             try {
-                InputStream certInputStream = IOUtils.toInputStream(pemCert);
+                InputStream certInputStream = new ByteArrayInputStream(pemCert.getBytes(StandardCharsets.UTF_8));
                 final X509Certificate trustedCert = (X509Certificate) CertificateFactory.getInstance("X.509")
                         .generateCertificate(certInputStream);
 
index 930bd00f82299578ae5a0d7ec103110cd084e53f..a1e384f9e251f5c434d94182adc51e3512c6b7fe 100644 (file)
@@ -16,7 +16,9 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
 import java.net.SocketTimeoutException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Base64;
 import java.util.HashMap;
@@ -25,7 +27,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.zip.GZIPInputStream;
 
-import org.apache.commons.io.IOUtils;
 import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
 import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
 import org.openhab.binding.ihc.internal.ws.datatypes.WSLoginResult;
@@ -325,10 +326,13 @@ public class IhcClient {
                 }
                 byte[] decodedBytes = Base64.getDecoder().decode(byteStream.toString());
                 logger.debug("File size after base64 encoding: {} bytes", decodedBytes.length);
-                try (GZIPInputStream gzis = new GZIPInputStream(new ByteArrayInputStream(decodedBytes))) {
-                    try (InputStreamReader in = new InputStreamReader(gzis, "ISO-8859-1")) {
-                        return IOUtils.toByteArray(in, "ISO-8859-1");
-                    }
+                try (GZIPInputStream gzis = new GZIPInputStream(new ByteArrayInputStream(decodedBytes));
+                        InputStreamReader reader = new InputStreamReader(gzis, StandardCharsets.ISO_8859_1);
+                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                        OutputStreamWriter writer = new OutputStreamWriter(baos)) {
+                    reader.transferTo(writer);
+                    writer.flush();
+                    return baos.toByteArray();
                 }
             }
         } catch (IOException | IllegalArgumentException e) {
index 38352b2424e5a657a600b612d067b5195125cf82..ab1e428c99fefd9f66114405f514928fc3fc7bab 100644 (file)
@@ -14,6 +14,7 @@ package org.openhab.binding.ihc.internal.ws.projectfile;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -24,7 +25,6 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.apache.commons.io.FileUtils;
 import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
 import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
 import org.slf4j.Logger;
@@ -76,7 +76,10 @@ public class ProjectFileUtils {
      */
     public static void saveToFile(String filePath, byte[] data) throws IhcExecption {
         try {
-            FileUtils.writeByteArrayToFile(new File(filePath), data);
+            try (FileOutputStream stream = new FileOutputStream(filePath)) {
+                stream.write(data);
+                stream.flush();
+            }
         } catch (IOException e) {
             throw new IhcExecption(e);
         }
index e29594a902b02500c30564a749bc377dfc90ae97..571d96e1a4b6257f5a49a92c498320d4975acfcb 100644 (file)
     </plugins>
   </build>
 
+  <dependencies>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.8.0</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+
 </project>
index 1f6939172e05255b18b49fb9b7b0f2283ab3c79d..d698abad09037ce9a6abba912cc7421c8a12fafc 100644 (file)
   </properties>
 
   <dependencies>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.15</version>
+    </dependency>
     <dependency>
       <groupId>io.reactivex</groupId>
       <artifactId>rxjava</artifactId>
index 02b1add69f40ddc9672b14bdfe68474e8fd38953..5ba4785f8cd5709cd6cc1a83f41a3eddb5799b1c 100644 (file)
@@ -19,7 +19,6 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.util.Arrays;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.NonNull;
 import org.openhab.core.util.HexUtils;
 import org.slf4j.Logger;
@@ -182,11 +181,8 @@ public class OnkyoAlbumArt {
         try {
             URL url = new URL(albumArtUrl);
             URLConnection connection = url.openConnection();
-            InputStream inputStream = connection.getInputStream();
-            try {
-                return IOUtils.toByteArray(inputStream);
-            } finally {
-                IOUtils.closeQuietly(inputStream);
+            try (InputStream inputStream = connection.getInputStream()) {
+                return inputStream.readAllBytes();
             }
         } catch (MalformedURLException e) {
             logger.warn("Album Art download failed from url '{}', reason {}", albumArtUrl, e.getMessage());
index ab9a4d61bb86eaaffa422d5fb2beebf2638302b4..1336241aca62a8efb946d5f9e6a56ba9ffa712b0 100644 (file)
@@ -24,7 +24,6 @@ import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;
 
-import org.apache.commons.io.IOUtils;
 import org.openhab.binding.onkyo.internal.eiscp.EiscpCommand;
 import org.openhab.binding.onkyo.internal.eiscp.EiscpException;
 import org.openhab.binding.onkyo.internal.eiscp.EiscpMessage;
@@ -222,17 +221,26 @@ public class OnkyoConnection {
                 logger.debug("closed connection tester!");
             }
             if (inStream != null) {
-                IOUtils.closeQuietly(inStream);
+                try {
+                    inStream.close();
+                } catch (IOException e) {
+                }
                 inStream = null;
                 logger.debug("closed input stream!");
             }
             if (outStream != null) {
-                IOUtils.closeQuietly(outStream);
+                try {
+                    outStream.close();
+                } catch (IOException e) {
+                }
                 outStream = null;
                 logger.debug("closed output stream!");
             }
             if (eiscpSocket != null) {
-                IOUtils.closeQuietly(eiscpSocket);
+                try {
+                    eiscpSocket.close();
+                } catch (IOException e) {
+                }
                 eiscpSocket = null;
                 logger.debug("closed socket!");
             }
index 93d6ddb575a227e6f0738df45a7bb17bdfe9ec74..3fcdb171319ea6bfa6584f1ee1ffb27a0e54f0db 100644 (file)
@@ -19,7 +19,6 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.sonos.internal.handler.ZonePlayerHandler;
@@ -118,7 +117,10 @@ public class SonosAudioSink implements AudioSink {
                 logger.warn("We do not have any callback url, so Sonos cannot play the audio stream!");
             }
         } else {
-            IOUtils.closeQuietly(audioStream);
+            try {
+                audioStream.close();
+            } catch (IOException e) {
+            }
             throw new UnsupportedAudioStreamException(
                     "Sonos can only handle FixedLengthAudioStreams and URLAudioStreams.", audioStream.getClass());
             // Instead of throwing an exception, we could ourselves try to wrap it into a
index 4fbc6c674e3d2a6a125440680a7b35e074c020b1..ddf35503c65e5440f6066c29e5b853adc66faa12 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.io.neeo.internal;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -22,7 +23,6 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -136,7 +136,8 @@ public abstract class AbstractServlet extends HttpServlet implements AutoCloseab
 
         if (logger.isDebugEnabled()) {
             req.getReader().mark(150000);
-            logger.debug("doPost: {} with {}", getFullURL(req), IOUtils.toString(req.getReader()));
+            logger.debug("doPost: {} with {}", getFullURL(req),
+                    new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
             req.getReader().reset();
         }
 
index c6904271a8d22d76bd12644a9f8cdd033da4107d..99b89dcac08c89d8447fd6df84b700a7f09e1ba4 100644 (file)
@@ -21,7 +21,6 @@ import java.util.Objects;
 
 import javax.ws.rs.core.Response;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 
@@ -58,8 +57,7 @@ public class HttpResponse {
         httpReason = response.getStatusInfo().getReasonPhrase();
 
         if (response.hasEntity()) {
-            InputStream is = response.readEntity(InputStream.class);
-            contents = IOUtils.toByteArray(is);
+            contents = response.readEntity(InputStream.class).readAllBytes();
         } else {
             contents = null;
         }
index dd41472e7015d3661fd391a8e5a68738af3db170..e3ab21b5dc367c1d1f0a8575e49531a2e2733e30 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.io.neeo.internal.servletservices;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -20,7 +21,6 @@ import java.util.Objects;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.io.IOUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.io.neeo.NeeoService;
@@ -155,7 +155,8 @@ public class ThingDashboardService extends DefaultServletService {
 
                 NeeoUtil.write(resp, gson.toJson(ReturnStatus.SUCCESS));
             } else if (paths[0].equalsIgnoreCase("restoredevice")) {
-                final NeeoThingUID uid = new NeeoThingUID(IOUtils.toString(req.getReader()));
+                final NeeoThingUID uid = new NeeoThingUID(
+                        new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
                 context.getDefinitions().remove(uid);
                 final NeeoDevice device = context.getDefinitions().getDevice(uid);
                 if (device == null) {
@@ -164,7 +165,8 @@ public class ThingDashboardService extends DefaultServletService {
                     NeeoUtil.write(resp, gson.toJson(new ReturnStatus(device)));
                 }
             } else if (paths[0].equalsIgnoreCase("refreshdevice")) {
-                final NeeoThingUID uid = new NeeoThingUID(IOUtils.toString(req.getReader()));
+                final NeeoThingUID uid = new NeeoThingUID(
+                        new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
                 final NeeoDevice device = context.getDefinitions().getDevice(uid);
                 if (device == null) {
                     NeeoUtil.write(resp, gson.toJson(new ReturnStatus("Device no longer exists in openHAB!")));
@@ -172,12 +174,14 @@ public class ThingDashboardService extends DefaultServletService {
                     NeeoUtil.write(resp, gson.toJson(new ReturnStatus(device)));
                 }
             } else if (paths[0].equalsIgnoreCase("deletedevice")) {
-                final NeeoThingUID uid = new NeeoThingUID(IOUtils.toString(req.getReader()));
+                final NeeoThingUID uid = new NeeoThingUID(
+                        new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
                 final boolean deleted = context.getDefinitions().remove(uid);
                 NeeoUtil.write(resp, gson.toJson(new ReturnStatus(
                         deleted ? null : "Device " + uid + " was not found (possibly already deleted?)")));
             } else if (paths[0].equalsIgnoreCase("exportrules")) {
-                final NeeoThingUID uid = new NeeoThingUID(IOUtils.toString(req.getReader()));
+                final NeeoThingUID uid = new NeeoThingUID(
+                        new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
                 final NeeoDevice device = context.getDefinitions().getDevice(uid);
                 if (device == null) {
                     NeeoUtil.write(resp, gson.toJson(new ReturnStatus("Device " + uid + " was not found")));
@@ -228,7 +232,7 @@ public class ThingDashboardService extends DefaultServletService {
 
         resp.setContentType("text/plain");
         resp.setHeader("Content-disposition", "attachment; filename=\"" + device.getName() + ".rules\"");
-        IOUtils.write(sb, resp.getOutputStream());
+        resp.getOutputStream().write(sb.toString().getBytes(StandardCharsets.UTF_8));
     }
 
     /**
index 00383b1e2452b0638e78e66a4968b99f5a1eff99..99dce0e8f75ff5d2bbf8105b882e825954681b42 100644 (file)
@@ -19,11 +19,15 @@ import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Comparator;
 import java.util.Locale;
 import java.util.Properties;
 import java.util.concurrent.Callable;
+import java.util.stream.Stream;
 
-import org.apache.commons.io.FileUtils;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -82,13 +86,26 @@ public class MapTransformationServiceTest {
     public void setUp() throws IOException {
         processor = new TestableMapTransformationService();
         processor.activate(bundleContext);
-        FileUtils.copyDirectory(new File(SRC_FOLDER), new File(CONFIG_FOLDER));
+        copyDirectory(SRC_FOLDER, CONFIG_FOLDER);
     }
 
     @AfterEach
     public void tearDown() throws IOException {
         processor.deactivate();
-        FileUtils.deleteDirectory(new File(CONFIG_FOLDER));
+
+        try (Stream<Path> walk = Files.walk(Path.of(CONFIG_FOLDER))) {
+            walk.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
+        }
+    }
+
+    private void copyDirectory(String from, String to) throws IOException {
+        Files.walk(Paths.get(from)).forEach(fromPath -> {
+            Path toPath = Paths.get(to, fromPath.toString().substring(from.length()));
+            try {
+                Files.copy(fromPath, toPath);
+            } catch (IOException e) {
+            }
+        });
     }
 
     @Test
index f1546110e1c59945fbef50a0f4fdb08e8389c001..731144cdf8e0848c8a8b3eb335a786d6e0964c4e 100644 (file)
@@ -15,12 +15,12 @@ package org.openhab.voice.mactts.internal;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Locale;
 import java.util.Set;
+import java.util.stream.Collectors;
 
-import org.apache.commons.io.IOUtils;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.core.audio.AudioException;
 import org.openhab.core.audio.AudioFormat;
 import org.openhab.core.audio.AudioStream;
@@ -39,6 +39,7 @@ import org.slf4j.LoggerFactory;
  * @author Kelly Davis
  */
 @Component
+@NonNullByDefault
 public class MacTTSService implements TTSService {
 
     private final Logger logger = LoggerFactory.getLogger(MacTTSService.class);
@@ -51,34 +52,30 @@ public class MacTTSService implements TTSService {
     /**
      * Set of supported audio formats
      */
-    private final Set<AudioFormat> audioFormats = initAudioFormats();
+    private final Set<AudioFormat> audioFormats = Set.of(
+            new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, null, (long) 44100));
 
     @Override
     public Set<Voice> getAvailableVoices() {
-        return this.voices;
+        return voices;
     }
 
     @Override
     public Set<AudioFormat> getSupportedFormats() {
-        return this.audioFormats;
+        return audioFormats;
     }
 
     @Override
     public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException {
         // Validate arguments
-        if ((null == text) || text.isEmpty()) {
+        if (text.isEmpty()) {
             throw new TTSException("The passed text is null or empty");
         }
-        if (!this.voices.contains(voice)) {
+        if (!voices.contains(voice)) {
             throw new TTSException("The passed voice is unsupported");
         }
-        boolean isAudioFormatSupported = false;
-        for (AudioFormat currentAudioFormat : this.audioFormats) {
-            if (currentAudioFormat.isCompatible(requestedFormat)) {
-                isAudioFormatSupported = true;
-                break;
-            }
-        }
+        boolean isAudioFormatSupported = audioFormats.stream()
+                .anyMatch(audioFormat -> audioFormat.isCompatible(requestedFormat));
         if (!isAudioFormatSupported) {
             throw new TTSException("The passed AudioFormat is unsupported");
         }
@@ -96,35 +93,16 @@ public class MacTTSService implements TTSService {
      * @return The voices of this instance
      */
     private final Set<Voice> initVoices() {
-        Set<Voice> voices = new HashSet<>();
-        InputStreamReader inputStreamReader = null;
-        BufferedReader bufferedReader = null;
         try {
             Process process = Runtime.getRuntime().exec("say -v ?");
-            inputStreamReader = new InputStreamReader(process.getInputStream());
-            bufferedReader = new BufferedReader(inputStreamReader);
-
-            String nextLine;
-            while ((nextLine = bufferedReader.readLine()) != null) {
-                voices.add(new MacTTSVoice(nextLine));
+            try (InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
+                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
+                return bufferedReader.lines().map(MacTTSVoice::new).collect(Collectors.toSet());
             }
         } catch (IOException e) {
             logger.error("Error while executing the 'say -v ?' command: {}", e.getMessage());
-        } finally {
-            IOUtils.closeQuietly(bufferedReader);
+            return Set.of();
         }
-        return voices;
-    }
-
-    /**
-     * Initializes this.audioFormats
-     *
-     * @return The audio formats of this instance
-     */
-    private final Set<AudioFormat> initAudioFormats() {
-        AudioFormat audioFormat = new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16,
-                null, (long) 44100);
-        return Collections.singleton(audioFormat);
     }
 
     @Override
@@ -133,7 +111,7 @@ public class MacTTSService implements TTSService {
     }
 
     @Override
-    public String getLabel(Locale locale) {
+    public String getLabel(@Nullable Locale locale) {
         return "macOS TTS";
     }
 }
index 5c0dbabd7be698054d42e4bd186b7dd671e3edbe..8816b9881893876f46ebeecddbf2c808c05b5c6e 100644 (file)
@@ -19,7 +19,6 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 
-import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -39,17 +38,12 @@ public class MacTTSVoiceTest {
     @Test
     public void testConstructor() throws IOException {
         assumeTrue("Mac OS X".equals(System.getProperty("os.name")));
-        BufferedReader bufferedReader = null;
-        try {
-            Process process = Runtime.getRuntime().exec("say -v ?");
-            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
-            bufferedReader = new BufferedReader(inputStreamReader);
-
+        Process process = Runtime.getRuntime().exec("say -v ?");
+        try (InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
+                BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
             String nextLine = bufferedReader.readLine();
             MacTTSVoice voiceMacOS = new MacTTSVoice(nextLine);
             assertNotNull(voiceMacOS, "The MacTTSVoice(String) constructor failed");
-        } finally {
-            IOUtils.closeQuietly(bufferedReader);
         }
     }
 
@@ -59,17 +53,12 @@ public class MacTTSVoiceTest {
     @Test
     public void getUIDTest() throws IOException {
         assumeTrue("Mac OS X".equals(System.getProperty("os.name")));
-        BufferedReader bufferedReader = null;
-        try {
-            Process process = Runtime.getRuntime().exec("say -v ?");
-            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
-            bufferedReader = new BufferedReader(inputStreamReader);
-
+        Process process = Runtime.getRuntime().exec("say -v ?");
+        try (InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
+                BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
             String nextLine = bufferedReader.readLine();
             MacTTSVoice macTTSVoice = new MacTTSVoice(nextLine);
             assertTrue(0 == macTTSVoice.getUID().indexOf("mactts:"), "The VoiceMacOS UID has an incorrect format");
-        } finally {
-            IOUtils.closeQuietly(bufferedReader);
         }
     }
 
@@ -79,17 +68,12 @@ public class MacTTSVoiceTest {
     @Test
     public void getLabelTest() throws IOException {
         assumeTrue("Mac OS X".equals(System.getProperty("os.name")));
-        BufferedReader bufferedReader = null;
-        try {
-            Process process = Runtime.getRuntime().exec("say -v ?");
-            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
-            bufferedReader = new BufferedReader(inputStreamReader);
-
+        Process process = Runtime.getRuntime().exec("say -v ?");
+        try (InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
+                BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
             String nextLine = bufferedReader.readLine();
             MacTTSVoice voiceMacOS = new MacTTSVoice(nextLine);
             assertNotNull(voiceMacOS.getLabel(), "The MacTTSVoice label has an incorrect format");
-        } finally {
-            IOUtils.closeQuietly(bufferedReader);
         }
     }
 
@@ -99,17 +83,12 @@ public class MacTTSVoiceTest {
     @Test
     public void getLocaleTest() throws IOException {
         assumeTrue("Mac OS X" == System.getProperty("os.name"));
-        BufferedReader bufferedReader = null;
-        try {
-            Process process = Runtime.getRuntime().exec("say -v ?");
-            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
-            bufferedReader = new BufferedReader(inputStreamReader);
-
+        Process process = Runtime.getRuntime().exec("say -v ?");
+        try (InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
+                BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
             String nextLine = bufferedReader.readLine();
             MacTTSVoice voiceMacOS = new MacTTSVoice(nextLine);
             assertNotNull(voiceMacOS.getLocale(), "The MacTTSVoice locale has an incorrect format");
-        } finally {
-            IOUtils.closeQuietly(bufferedReader);
         }
     }
 }
index e59cd5117847c57c48cf72991310d1e1958778d6..711bb814ea03b2a7ded0278c39fa6688b7a4d58c 100644 (file)
@@ -34,7 +34,7 @@
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
-      <version>2.5</version>
+      <version>2.8.0</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
index 61cd026529df35f01f84374fdeb49697fe6b864b..af4254b3194182ab163e3f9e77bdb9ddca21a3a7 100644 (file)
 package org.openhab.voice.marytts.internal;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.SequenceInputStream;
 
 import javax.sound.sampled.AudioInputStream;
 
-import org.apache.commons.io.IOUtils;
 import org.openhab.core.audio.AudioException;
 import org.openhab.core.audio.AudioFormat;
 import org.openhab.core.audio.AudioSource;
@@ -54,12 +54,23 @@ class MaryTTSAudioStream extends FixedLengthAudioStream {
      * @throws IOException
      */
     public MaryTTSAudioStream(AudioInputStream inputStream, AudioFormat audioFormat) throws IOException {
-        rawAudio = IOUtils.toByteArray(inputStream);
+        // The length of an AudioInputStream is expressed in sample frames, not bytes so readAllBytes() cannot be used.
+        rawAudio = inputStreamToBytes(inputStream);
         this.length = rawAudio.length + 36;
         this.inputStream = new SequenceInputStream(getWavHeaderInputStream(length), new ByteArrayInputStream(rawAudio));
         this.audioFormat = audioFormat;
     }
 
+    private byte[] inputStreamToBytes(InputStream inputStream) throws IOException {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        int n = 0;
+        byte[] buffer = new byte[4096];
+        while (-1 != (n = inputStream.read(buffer))) {
+            output.write(buffer, 0, n);
+        }
+        return output.toByteArray();
+    }
+
     @Override
     public AudioFormat getFormat() {
         return this.audioFormat;
@@ -146,7 +157,10 @@ class MaryTTSAudioStream extends FixedLengthAudioStream {
 
     @Override
     public synchronized void reset() throws IOException {
-        IOUtils.closeQuietly(inputStream);
+        try {
+            inputStream.close();
+        } catch (IOException e) {
+        }
         this.inputStream = new SequenceInputStream(getWavHeaderInputStream(length), new ByteArrayInputStream(rawAudio));
     }