diff --git a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java index bba44c4c475..c3e7032e18d 100644 --- a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java +++ b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java @@ -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 { diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/handler/BlueGigaBridgeHandler.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/handler/BlueGigaBridgeHandler.java index 7bd7cdb1682..2e07e665b24 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/handler/BlueGigaBridgeHandler.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/handler/BlueGigaBridgeHandler.java @@ -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 { - 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."); diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaSerialHandler.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaSerialHandler.java index be2fad17b61..8c6d8030182 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaSerialHandler.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaSerialHandler.java @@ -12,13 +12,13 @@ */ 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."); diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java index f43745c1dab..31fa274cca1 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java @@ -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; } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java index f8a7369764d..26c4125214f 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java @@ -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); diff --git a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/IhcClient.java b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/IhcClient.java index 930bd00f822..a1e384f9e25 100644 --- a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/IhcClient.java +++ b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/IhcClient.java @@ -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) { diff --git a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/projectfile/ProjectFileUtils.java b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/projectfile/ProjectFileUtils.java index 38352b2424e..ab1e428c99f 100644 --- a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/projectfile/ProjectFileUtils.java +++ b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/projectfile/ProjectFileUtils.java @@ -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); } diff --git a/bundles/org.openhab.binding.logreader/pom.xml b/bundles/org.openhab.binding.logreader/pom.xml index e29594a902b..571d96e1a4b 100644 --- a/bundles/org.openhab.binding.logreader/pom.xml +++ b/bundles/org.openhab.binding.logreader/pom.xml @@ -36,4 +36,13 @@ + + + commons-io + commons-io + 2.8.0 + compile + + + diff --git a/bundles/org.openhab.binding.minecraft/pom.xml b/bundles/org.openhab.binding.minecraft/pom.xml index 1f6939172e0..d698abad090 100644 --- a/bundles/org.openhab.binding.minecraft/pom.xml +++ b/bundles/org.openhab.binding.minecraft/pom.xml @@ -19,6 +19,11 @@ + + commons-codec + commons-codec + 1.15 + io.reactivex rxjava diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoAlbumArt.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoAlbumArt.java index 02b1add69f4..5ba4785f8cd 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoAlbumArt.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoAlbumArt.java @@ -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()); diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoConnection.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoConnection.java index ab9a4d61bb8..1336241aca6 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoConnection.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoConnection.java @@ -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!"); } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java index 93d6ddb575a..3fcdb171319 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java @@ -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 diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/AbstractServlet.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/AbstractServlet.java index 4fbc6c674e3..ddf35503c65 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/AbstractServlet.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/AbstractServlet.java @@ -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(); } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/net/HttpResponse.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/net/HttpResponse.java index c6904271a8d..99b89dcac08 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/net/HttpResponse.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/net/HttpResponse.java @@ -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; } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java index dd41472e701..e3ab21b5dc3 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java @@ -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)); } /** diff --git a/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java b/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java index 00383b1e245..99dce0e8f75 100644 --- a/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java +++ b/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java @@ -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 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 diff --git a/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java b/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java index f1546110e1c..731144cdf8e 100644 --- a/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java +++ b/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java @@ -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 audioFormats = initAudioFormats(); + private final Set audioFormats = Set.of( + new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, null, (long) 44100)); @Override public Set getAvailableVoices() { - return this.voices; + return voices; } @Override public Set 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 initVoices() { - Set 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 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"; } } diff --git a/bundles/org.openhab.voice.mactts/src/test/java/org/openhab/voice/mactts/internal/MacTTSVoiceTest.java b/bundles/org.openhab.voice.mactts/src/test/java/org/openhab/voice/mactts/internal/MacTTSVoiceTest.java index 5c0dbabd7be..8816b988189 100644 --- a/bundles/org.openhab.voice.mactts/src/test/java/org/openhab/voice/mactts/internal/MacTTSVoiceTest.java +++ b/bundles/org.openhab.voice.mactts/src/test/java/org/openhab/voice/mactts/internal/MacTTSVoiceTest.java @@ -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); } } } diff --git a/bundles/org.openhab.voice.marytts/pom.xml b/bundles/org.openhab.voice.marytts/pom.xml index e59cd511784..711bb814ea0 100644 --- a/bundles/org.openhab.voice.marytts/pom.xml +++ b/bundles/org.openhab.voice.marytts/pom.xml @@ -34,7 +34,7 @@ commons-io commons-io - 2.5 + 2.8.0 compile diff --git a/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java b/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java index 61cd026529d..af4254b3194 100644 --- a/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java +++ b/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java @@ -13,13 +13,13 @@ 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)); }