From 9adc38724fd21c30b2cf82eb24ba6d3a19a0bf7e Mon Sep 17 00:00:00 2001 From: lolodomo Date: Thu, 16 Jul 2020 21:14:52 +0200 Subject: [PATCH] [heos] Workaround for thing actions bug (#8136) Related to #8116 Signed-off-by: Laurent Garnier Signed-off-by: MPH80 --- .../heos/internal/action/HeosActions.java | 36 +++++++++++++++---- .../heos/internal/action/IHeosActions.java | 28 +++++++++++++++ 2 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/IHeosActions.java diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java index 9adb5aeb4dbd6..fbd65af2da464 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java @@ -13,6 +13,8 @@ package org.openhab.binding.heos.internal.action; import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -29,14 +31,18 @@ import org.slf4j.LoggerFactory; /** - * The class is responsible to call corresponding - * action on HEOS Handler + * The class is responsible to call corresponding action on HEOS Handler + *

+ * Note:The static method invokeMethodOf handles the case where + * the test actions instanceof HeosActions fails. This test can fail + * due to an issue in openHAB core v2.5.0 where the {@link HeosActions} class + * can be loaded by a different classloader than the actions instance. * * @author Martin van Wingerden - Initial contribution */ @ThingActionsScope(name = "heos") @NonNullByDefault -public class HeosActions implements ThingActions { +public class HeosActions implements ThingActions, IHeosActions { private final static Logger logger = LoggerFactory.getLogger(HeosActions.class); @@ -62,6 +68,7 @@ public void setThingHandler(@Nullable ThingHandler handler) { return handler.getApiConnection(); } + @Override @RuleAction(label = "Play Input", description = "Play an input from another device") public void playInputFromPlayer( @ActionInput(name = "source", label = "Source Player", description = "Player used for input") @Nullable Integer sourcePlayer, @@ -90,10 +97,25 @@ public void playInputFromPlayer( public static void playInputFromPlayer(@Nullable ThingActions actions, @Nullable Integer sourcePlayer, @Nullable String input, @Nullable Integer destinationPlayer) { - if (actions instanceof HeosActions) { - ((HeosActions) actions).playInputFromPlayer(sourcePlayer, input, destinationPlayer); - } else { - throw new IllegalArgumentException("Instance is not an HeosActionsService class."); + invokeMethodOf(actions).playInputFromPlayer(sourcePlayer, input, destinationPlayer); + } + + private static IHeosActions invokeMethodOf(@Nullable ThingActions actions) { + if (actions == null) { + throw new IllegalArgumentException("actions cannot be null"); + } + if (actions.getClass().getName().equals(HeosActions.class.getName())) { + if (actions instanceof IHeosActions) { + return (IHeosActions) actions; + } else { + return (IHeosActions) Proxy.newProxyInstance(IHeosActions.class.getClassLoader(), + new Class[] { IHeosActions.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 HeosActions"); } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/IHeosActions.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/IHeosActions.java new file mode 100644 index 0000000000000..3739292f9780a --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/IHeosActions.java @@ -0,0 +1,28 @@ +/** + * 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.heos.internal.action; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link IHeosActions} defines the interface for all thing actions supported by the binding. + * + * @author Laurent Garnier - Initial contribution + */ +@NonNullByDefault +public interface IHeosActions { + + public void playInputFromPlayer(@Nullable Integer sourcePlayer, @Nullable String input, + @Nullable Integer destinationPlayer); +}