diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/I18nException.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/I18nException.java new file mode 100644 index 0000000000000..eca4c397f9c8b --- /dev/null +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/I18nException.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2010-2021 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.sonyprojector.internal; + +import java.util.Locale; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.i18n.TranslationProvider; +import org.osgi.framework.Bundle; + +/** + * The {@link I18nException} class is a generic exception class implementing the internationalization of + * exception message in the context of openHAB. + * + * @author Laurent Garnier - Initial contribution + */ +@NonNullByDefault +public class I18nException extends Exception { + private static final long serialVersionUID = 1L; + + private String msgKey; + private @Nullable Object @Nullable [] msgParams; + private @Nullable Bundle bundle; + private @Nullable TranslationProvider i18nProvider; + private @Nullable Locale locale; + + public I18nException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + this.msgKey = ""; + } + + public I18nException(@Nullable Throwable cause, String msgKey, @Nullable Object @Nullable... msgParams) { + super(null, cause); + this.msgKey = msgKey; + this.msgParams = msgParams; + } + + public void setupI18n(Bundle bundle, TranslationProvider i18nProvider) { + setupI18n(bundle, i18nProvider, null); + } + + public void setupI18n(Bundle bundle, TranslationProvider i18nProvider, @Nullable Locale locale) { + this.bundle = bundle; + this.i18nProvider = i18nProvider; + this.locale = locale; + } + + @Override + public @Nullable String getMessage() { + Bundle localeBundle = this.bundle; + TranslationProvider localI18nProvider = this.i18nProvider; + if (msgKey.isBlank() || localeBundle == null || localI18nProvider == null) { + return getMessage(); + } else { + return localI18nProvider.getText(localeBundle, msgKey, null, Locale.ENGLISH, msgParams); + } + } + + @Override + public @Nullable String getLocalizedMessage() { + Bundle localeBundle = this.bundle; + TranslationProvider localI18nProvider = this.i18nProvider; + Locale localLocale = this.locale; + if (msgKey.isBlank() || localeBundle == null || localI18nProvider == null || localLocale == null) { + return getMessage(); + } else { + return localI18nProvider.getText(localeBundle, msgKey, null, localLocale, msgParams); + } + } + + public @Nullable String getMessageOrKeyWithParams() { + if (msgKey.isBlank()) { + return getMessage(); + } + String result = "@text/" + msgKey; + Object @Nullable [] params = msgParams; + if (params != null && params.length > 0) { + result += " ["; + boolean first = true; + for (Object param : params) { + if (first) { + first = false; + } else { + result += ","; + } + result += String.format(" \"%s\"", param == null ? "" : param.toString()); + } + result += " ]"; + } + return result; + } +} diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorException.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorException.java index 6743dd761a595..4080531582367 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorException.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorException.java @@ -14,22 +14,33 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.i18n.TranslationProvider; +import org.osgi.framework.FrameworkUtil; /** * The {@link SonyProjectorException} class is used for any exception thrown by the binding * * @author Markus Wehrle - Initial contribution + * @author Laurent Garnier - use I18nException for message internationalization */ @NonNullByDefault -public class SonyProjectorException extends Exception { +public class SonyProjectorException extends I18nException { + private static final long serialVersionUID = 1L; - // Parameterless Constructor - public SonyProjectorException() { + public SonyProjectorException(String message) { + super(message, null); + } + + public SonyProjectorException(String message, Throwable cause) { + super(message, cause); + } + + public SonyProjectorException(@Nullable Throwable cause, String msgKey, @Nullable Object @Nullable... msgParams) { + super(cause, msgKey, msgParams); } - // Constructor that accepts a message - public SonyProjectorException(@Nullable String message) { - super(message); + public void setupI18n(TranslationProvider i18nProvider) { + setupI18n(FrameworkUtil.getBundle(getClass()).getBundleContext().getBundle(), i18nProvider); } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java index ad85245fcf886..c830dec372164 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java @@ -22,6 +22,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.sonyprojector.internal.handler.SonyProjectorHandler; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.io.transport.serial.SerialPortManager; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; @@ -49,12 +50,15 @@ public class SonyProjectorHandlerFactory extends BaseThingHandlerFactory { private final SerialPortManager serialPortManager; private final SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider; + private final TranslationProvider i18nProvider; @Activate public SonyProjectorHandlerFactory(final @Reference SerialPortManager serialPortManager, - final @Reference SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider) { + final @Reference SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider, + final @Reference TranslationProvider i18nProvider) { this.serialPortManager = serialPortManager; this.stateDescriptionProvider = stateDescriptionProvider; + this.i18nProvider = i18nProvider; } @Override @@ -67,7 +71,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { - return new SonyProjectorHandler(thing, stateDescriptionProvider, serialPortManager); + return new SonyProjectorHandler(thing, stateDescriptionProvider, serialPortManager, i18nProvider); } return null; diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorConnector.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorConnector.java index c319217ade22a..d923109beb992 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorConnector.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorConnector.java @@ -898,8 +898,7 @@ protected byte[] getSetting(SonyProjectorItem item) throws SonyProjectorExceptio return result; } catch (SonyProjectorException e) { - logger.debug("Get setting {} failed: {}", item.getName(), e.getMessage()); - throw new SonyProjectorException("Get setting " + item.getName() + " failed: " + e.getMessage()); + throw new SonyProjectorException("Get setting " + item.getName() + " failed", e); } } @@ -917,8 +916,7 @@ private void setSetting(SonyProjectorItem item, byte[] data) throws SonyProjecto try { executeCommand(item, false, data); } catch (SonyProjectorException e) { - logger.debug("Set setting {} failed: {}", item.getName(), e.getMessage()); - throw new SonyProjectorException("Set setting " + item.getName() + " failed: " + e.getMessage()); + throw new SonyProjectorException("Set setting " + item.getName() + " failed", e); } logger.debug("Set setting {} succeeded", item.getName()); @@ -951,12 +949,10 @@ private synchronized void sendIR(SonyProjectorItem item) throws SonyProjectorExc close(); } } catch (SonyProjectorException e) { - logger.debug("Send IR {} failed: {}", item.getName(), e.getMessage()); - throw new SonyProjectorException("Send IR " + item.getName() + " failed: " + e.getMessage()); + throw new SonyProjectorException("Send IR " + item.getName() + " failed", e); } catch (InterruptedException e) { - logger.debug("Send IR {} interrupted: {}", item.getName(), e.getMessage()); Thread.currentThread().interrupt(); - throw new SonyProjectorException("Send IR " + item.getName() + " interrupted: " + e.getMessage()); + throw new SonyProjectorException("Send IR " + item.getName() + " interrupted", e); } logger.debug("Send IR {} succeeded", item.getName()); @@ -975,28 +971,24 @@ private synchronized void sendIR(SonyProjectorItem item) throws SonyProjectorExc */ private synchronized byte[] executeCommand(SonyProjectorItem item, boolean getCommand, byte[] data) throws SonyProjectorException { - try { - boolean runningSession = connected; + boolean runningSession = connected; - open(); + open(); - // Build the message and send it - writeCommand(buildMessage(item, getCommand, data)); + // Build the message and send it + writeCommand(buildMessage(item, getCommand, data)); - // Read the response - byte[] responseMessage = readResponse(); + // Read the response + byte[] responseMessage = readResponse(); - if (!runningSession) { - close(); - } + if (!runningSession) { + close(); + } - // Validate the content of the response - validateResponse(responseMessage, item); + // Validate the content of the response + validateResponse(responseMessage, item); - return responseMessage; - } catch (SonyProjectorException e) { - throw new SonyProjectorException(e.getMessage()); - } + return responseMessage; } /** @@ -1065,7 +1057,7 @@ protected int readInput(byte[] dataBuffer) throws SonyProjectorException { return dataIn.read(dataBuffer); } catch (IOException e) { logger.debug("readInput failed: {}", e.getMessage()); - throw new SonyProjectorException("readInput failed: " + e.getMessage()); + throw new SonyProjectorException("readInput failed", e); } } @@ -1090,7 +1082,7 @@ protected void writeCommand(byte[] message) throws SonyProjectorException { dataOut.flush(); } catch (IOException e) { logger.debug("writeCommand failed: {}", e.getMessage()); - throw new SonyProjectorException("writeCommand failed: " + e.getMessage()); + throw new SonyProjectorException("writeCommand failed", e); } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/sdcp/SonyProjectorSdcpConnector.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/sdcp/SonyProjectorSdcpConnector.java index 21d7a39417791..1635244c09b89 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/sdcp/SonyProjectorSdcpConnector.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/sdcp/SonyProjectorSdcpConnector.java @@ -130,8 +130,7 @@ public synchronized void open() throws SonyProjectorException { logger.debug("SDCP connection opened"); } catch (IOException | SecurityException | IllegalArgumentException e) { - logger.debug("Opening SDCP connection failed: {}", e.getMessage()); - throw new SonyProjectorException("Opening SDCP connection failed: " + e.getMessage()); + throw new SonyProjectorException(e, "exception.opening-sdcp-connection-failed"); } } } @@ -197,7 +196,7 @@ protected int readInput(byte[] dataBuffer) throws SonyProjectorException { return 0; } catch (IOException e) { logger.debug("readInput failed: {}", e.getMessage()); - throw new SonyProjectorException("readInput failed: " + e.getMessage()); + throw new SonyProjectorException("readInput failed", e); } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java index 673c86182d184..0ace3df9a85be 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.TooManyListenersException; import java.util.concurrent.TimeUnit; @@ -97,8 +96,7 @@ public synchronized void open() throws SonyProjectorException { try { SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(serialPortName); if (portIdentifier == null) { - logger.debug("Opening serial connection failed: No Such Port: {}", serialPortName); - throw new SonyProjectorException("Opening serial connection failed: No Such Port"); + throw new SonyProjectorException(null, "exception.invalid-serial-port", serialPortName); } SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000); @@ -139,20 +137,8 @@ public synchronized void open() throws SonyProjectorException { connected = true; logger.debug("Serial connection opened"); - } catch (PortInUseException e) { - logger.debug("Opening serial connection failed: Port in Use Exception: {}", e.getMessage(), e); - throw new SonyProjectorException("Opening serial connection failed: Port in Use Exception"); - } catch (UnsupportedCommOperationException e) { - logger.debug("Opening serial connection failed: Unsupported Comm Operation Exception: {}", - e.getMessage(), e); - throw new SonyProjectorException( - "Opening serial connection failed: Unsupported Comm Operation Exception"); - } catch (UnsupportedEncodingException e) { - logger.debug("Opening serial connection failed: Unsupported Encoding Exception: {}", e.getMessage(), e); - throw new SonyProjectorException("Opening serial connection failed: Unsupported Encoding Exception"); - } catch (IOException e) { - logger.debug("Opening serial connection failed: IO Exception: {}", e.getMessage(), e); - throw new SonyProjectorException("Opening serial connection failed: IO Exception"); + } catch (PortInUseException | UnsupportedCommOperationException | IOException e) { + throw new SonyProjectorException(e, "exception.opening-serial-connection-failed"); } } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java index 6487941b0b89b..79b2e62bb79f7 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java @@ -75,8 +75,7 @@ public synchronized void open() throws SonyProjectorException { logger.debug("Serial over IP connection opened"); } catch (IOException | SecurityException | IllegalArgumentException e) { - logger.debug("Opening serial over IP connection failed: {}", e.getMessage()); - throw new SonyProjectorException("Opening serial over IP connection failed: " + e.getMessage()); + throw new SonyProjectorException(e, "exception.opening-serial-over-ip-connection-failed"); } } } @@ -122,7 +121,7 @@ protected int readInput(byte[] dataBuffer) throws SonyProjectorException { return 0; } catch (IOException e) { logger.debug("readInput failed: {}", e.getMessage()); - throw new SonyProjectorException("readInput failed: " + e.getMessage()); + throw new SonyProjectorException("readInput failed", e); } } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/handler/SonyProjectorHandler.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/handler/SonyProjectorHandler.java index d4d5f7996002e..7e929ecdf9abb 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/handler/SonyProjectorHandler.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/handler/SonyProjectorHandler.java @@ -33,6 +33,7 @@ import org.openhab.binding.sonyprojector.internal.configuration.SonyProjectorSerialConfiguration; import org.openhab.binding.sonyprojector.internal.configuration.SonyProjectorSerialOverIpConfiguration; import org.openhab.core.cache.ExpiringCacheMap; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.io.transport.serial.SerialPortManager; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; @@ -60,11 +61,15 @@ @NonNullByDefault public class SonyProjectorHandler extends BaseThingHandler { - private final Logger logger = LoggerFactory.getLogger(SonyProjectorHandler.class); - private static final SonyProjectorModel DEFAULT_MODEL = SonyProjectorModel.VW520; private static final long POLLING_INTERVAL = TimeUnit.SECONDS.toSeconds(15); + private final Logger logger = LoggerFactory.getLogger(SonyProjectorHandler.class); + + private final TranslationProvider i18nProvider; + + private final ExpiringCacheMap cache; + private @Nullable ScheduledFuture refreshJob; private boolean identifyProjector; @@ -78,13 +83,12 @@ public class SonyProjectorHandler extends BaseThingHandler { private final Object commandLock = new Object(); - private final ExpiringCacheMap cache; - public SonyProjectorHandler(Thing thing, SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider, - SerialPortManager serialPortManager) { + SerialPortManager serialPortManager, TranslationProvider i18nProvider) { super(thing); this.stateDescriptionProvider = stateDescriptionProvider; this.serialPortManager = serialPortManager; + this.i18nProvider = i18nProvider; this.cache = new ExpiringCacheMap<>(TimeUnit.SECONDS.toMillis(POLLING_INTERVAL)); } @@ -103,8 +107,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { try { connector.open(); } catch (SonyProjectorException e) { + e.setupI18n(i18nProvider); logger.debug("Command {} from channel {} failed: {}", command, channel, e.getMessage()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessageOrKeyWithParams()); return; } try { @@ -282,6 +287,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { } logger.debug("Command {} from channel {} succeeded", command, channel); } catch (SonyProjectorException e) { + e.setupI18n(i18nProvider); logger.debug("Command {} from channel {} failed: {}", command, channel, e.getMessage()); refreshChannel(channel, true); } @@ -406,8 +412,9 @@ private void pollProjector() { try { connector.open(); } catch (SonyProjectorException e) { - logger.debug("Poll projector failed: {}", e.getMessage()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + e.setupI18n(i18nProvider); + logger.debug("Poll projector failed: {}", e.getMessage(), e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessageOrKeyWithParams()); return; } @@ -458,6 +465,7 @@ private void refreshModel() { identifyProjector = false; switchToModel(modelName, false); } catch (SonyProjectorException e) { + e.setupI18n(i18nProvider); logger.debug("getModelName failed: {}", e.getMessage()); } } @@ -524,6 +532,7 @@ private boolean refreshPowerState() { on = value.isOn(); state = new StringType(value.name()); } catch (SonyProjectorException e) { + e.setupI18n(i18nProvider); logger.debug("Get Status Power failed: {}", e.getMessage()); } updateChannelStateAndCache(CHANNEL_POWER, on ? OnOffType.ON : OnOffType.OFF); @@ -699,6 +708,7 @@ private boolean refreshPowerState() { } logger.debug("Refresh channel {} with value {}", channel, state); } catch (SonyProjectorException e) { + e.setupI18n(i18nProvider); logger.debug("Refresh channel {} failed: {}", channel, e.getMessage()); } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector.properties b/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector.properties index 1f6e51989db6d..70dad31f4d20e 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector.properties +++ b/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector.properties @@ -296,3 +296,10 @@ offline.config-error-unknown-port = Undefined port configuration setting offline.config-error-invalid-port = Invalid port configuration setting offline.config-error-unknown-model = Undefined model configuration setting offline.config-error-invalid-thing-type = Use serial over IP connection thing type + + Exceptions + +exception.invalid-serial-port = Opening serial connection failed: no port {0} +exception.opening-serial-connection-failed = Opening serial connection failed +exception.opening-serial-over-ip-connection-failed = Opening serial over IP connection failed +exception.opening-sdcp-connection-failed = Opening SDCP connection failed diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector_fr.properties b/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector_fr.properties index c41a02a839308..1c1dcf1874fc8 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector_fr.properties +++ b/bundles/org.openhab.binding.sonyprojector/src/main/resources/OH-INF/i18n/sonyprojector_fr.properties @@ -296,3 +296,10 @@ offline.config-error-unknown-port = Paramètre de port indéfini offline.config-error-invalid-port = Paramètre de port invalide offline.config-error-unknown-model = Paramètre de modèle indéfini offline.config-error-invalid-thing-type = Utiliser le type connexion série sur IP + + Exceptions + +exception.invalid-serial-port = Echec de l''ouverture de la connexion série: pas de port {0} +exception.opening-serial-connection-failed = Echec de l''ouverture de la connexion série +exception.opening-serial-over-ip-connection-failed = Echec de l''ouverture de la connexion série sur IP +exception.opening-sdcp-connection-failed = Echec de l''ouverture de la connexion SDCP