From 81ecfedf4b0fefe992d77e5b204d50cfa9092e54 Mon Sep 17 00:00:00 2001 From: lolodomo Date: Thu, 16 Jul 2020 21:17:37 +0200 Subject: [PATCH] [onkyo] Workaround for thing actions bug (#8134) Related to #8116 Signed-off-by: Laurent Garnier Signed-off-by: Daan Meijer --- .../automation/modules/OnkyoThingActions.java | 27 +++++++++++++++ .../modules/OnkyoThingActionsService.java | 34 ++++++++++++++++--- 2 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActions.java diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActions.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActions.java new file mode 100644 index 0000000000000..6386f7fe369ec --- /dev/null +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActions.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 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.onkyo.internal.automation.modules; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link OnkyoThingActions} defines the interface for all thing actions supported by the binding. + * + * @author Laurent Garnier - initial contribution + */ +@NonNullByDefault +public interface OnkyoThingActions { + + public void sendRawCommand(@Nullable String command, @Nullable String value); +} diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActionsService.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActionsService.java index a1a78a9dbc3e1..fd45d8cb5c58a 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActionsService.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/automation/modules/OnkyoThingActionsService.java @@ -12,6 +12,9 @@ */ package org.openhab.binding.onkyo.internal.automation.modules; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.binding.ThingActions; @@ -25,18 +28,24 @@ /** * Some automation actions to be used with a {@link OnkyoThingActionsService} + *

+ * Note:The static method invokeMethodOf handles the case where + * the test actions instanceof OnkyoThingActionsService fails. This test can fail + * due to an issue in openHAB core v2.5.0 where the {@link OnkyoThingActionsService} class + * can be loaded by a different classloader than the actions instance. * * @author David Masshardt - initial contribution * */ @ThingActionsScope(name = "onkyo") @NonNullByDefault -public class OnkyoThingActionsService implements ThingActions { +public class OnkyoThingActionsService implements ThingActions, OnkyoThingActions { private final Logger logger = LoggerFactory.getLogger(OnkyoThingActionsService.class); private @Nullable OnkyoHandler handler; + @Override @SuppressWarnings("null") @RuleAction(label = "Onkyo sendRawCommand", description = "Action that sends raw command to the receiver") public void sendRawCommand(@ActionInput(name = "command") @Nullable String command, @@ -51,11 +60,26 @@ public void sendRawCommand(@ActionInput(name = "command") @Nullable String comma public static void sendRawCommand(@Nullable ThingActions actions, @Nullable String command, @Nullable String value) { - if (actions instanceof OnkyoThingActionsService) { - ((OnkyoThingActionsService) actions).sendRawCommand(command, value); - } else { - throw new IllegalArgumentException("Instance is not an OnkyoThingActionsService class."); + invokeMethodOf(actions).sendRawCommand(command, value); + } + + private static OnkyoThingActions invokeMethodOf(@Nullable ThingActions actions) { + if (actions == null) { + throw new IllegalArgumentException("actions cannot be null"); + } + if (actions.getClass().getName().equals(OnkyoThingActionsService.class.getName())) { + if (actions instanceof OnkyoThingActions) { + return (OnkyoThingActions) actions; + } else { + return (OnkyoThingActions) Proxy.newProxyInstance(OnkyoThingActions.class.getClassLoader(), + new Class[] { OnkyoThingActions.class }, (Object proxy, Method method, Object[] args) -> { + Method m = actions.getClass().getDeclaredMethod(method.getName(), + method.getParameterTypes()); + return m.invoke(actions, args); + }); + } } + throw new IllegalArgumentException("Actions is not an instance of OnkyoThingActionsService"); } @Override