diff --git a/src/io/calimero/serial/ConnectionFactory.java b/src/io/calimero/serial/ConnectionFactory.java index 412b86f3..57094344 100644 --- a/src/io/calimero/serial/ConnectionFactory.java +++ b/src/io/calimero/serial/ConnectionFactory.java @@ -1,6 +1,6 @@ /* Calimero 2 - A library for KNX network access - Copyright (c) 2022, 2024 B. Malinowsky + Copyright (c) 2022, 2025 B. Malinowsky This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +40,11 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.lang.invoke.MethodHandles; +import java.util.ArrayList; import java.util.Objects; import java.util.Optional; import java.util.ServiceLoader; import java.util.ServiceLoader.Provider; -import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import io.calimero.KNXException; @@ -71,30 +71,35 @@ public ConnectionFactory(final Class

service) { svcName = service.getName(); } - public C open(final ThrowingFunction openFunc) throws KNXException, IOException { - final var tref = new AtomicReference(); - final var optC = providers().map(provider -> { + public C open(final String name, final ThrowingFunction openFunc) throws KNXException, IOException { + final var providerExceptions = new ArrayList(); + final var connOpt = providers().map(provider -> { try { final var conn = openFunc.open(provider); logger.log(Level.DEBUG, "{0} port setup: {1}", provider, conn); return Optional.of(conn); } - catch (KNXException | IOException | RuntimeException t) { - tref.set(t); + catch (KNXException | IOException | RuntimeException | ExceptionInInitializerError t) { + logger.log(Level.DEBUG, "{0} unsuccessful: {1}", provider, t.getMessage()); + providerExceptions.add(t); return Optional.empty(); } }).flatMap(Optional::stream).findFirst(); - if (optC.isPresent()) - return optC.get(); + if (connOpt.isPresent()) + return connOpt.get(); - final var t = tref.get(); - if (t == null) + if (providerExceptions.isEmpty()) throw new KNXException("no service provider available for " + svcName); - if (t instanceof KNXException exception) - throw exception; - if (t instanceof IOException exception) - throw exception; - throw new KNXException("failed to open connection", t); + if (providerExceptions.size() == 1) { + final var x = providerExceptions.get(0); + if (x instanceof final KNXException e) + throw e; + if (x instanceof final IOException e) + throw e; + } + final var t = new KNXException("failed to open connection '" + name + "'"); + providerExceptions.forEach(t::addSuppressed); + throw t; } public Stream

providers() { diff --git a/src/io/calimero/serial/SerialConnectionFactory.java b/src/io/calimero/serial/SerialConnectionFactory.java index 8d2b5980..00f8c1d7 100644 --- a/src/io/calimero/serial/SerialConnectionFactory.java +++ b/src/io/calimero/serial/SerialConnectionFactory.java @@ -92,7 +92,7 @@ public static SerialCom open(final String portId, final int baudrate, final Dura flowControl, readIntervalTimeout, receiveTimeout); try { - return factory.open(p -> p.open(settings)); + return factory.open(portId, p -> p.open(settings)); } catch (final IOException e) { throw new KNXException("opening device " + portId, e); diff --git a/src/io/calimero/serial/usb/UsbConnectionFactory.java b/src/io/calimero/serial/usb/UsbConnectionFactory.java index c155b3c9..b44e463b 100644 --- a/src/io/calimero/serial/usb/UsbConnectionFactory.java +++ b/src/io/calimero/serial/usb/UsbConnectionFactory.java @@ -1,6 +1,6 @@ /* Calimero 2 - A library for KNX network access - Copyright (c) 2022, 2024 B. Malinowsky + Copyright (c) 2022, 2025 B. Malinowsky This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,7 +53,7 @@ private UsbConnectionFactory() {} @SuppressWarnings("resource") public static UsbConnection open(final Device device) throws KNXException { try { - return factory.open(p -> p.open(device)); + return factory.open(device.toString(), p -> p.open(device)); } catch (final IOException e) { throw new KNXException(String.format("open USB connection %s", device), e); @@ -63,7 +63,7 @@ public static UsbConnection open(final Device device) throws KNXException { @SuppressWarnings("resource") public static UsbConnection open(final String device) throws KNXException { try { - return factory.open(p -> p.open(device)); + return factory.open(device, p -> p.open(device)); } catch (final IOException e) { throw new KNXException(String.format("open USB connection %s", device), e);