Switch KitchenServiceImpl to CompositeListener
[controller.git] / opendaylight / blueprint / src / main / java / org / opendaylight / controller / blueprint / ext / ActionProviderBean.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.blueprint.ext;
9
10 import com.google.common.collect.Collections2;
11 import com.google.common.collect.ImmutableSet;
12 import java.util.Objects;
13 import org.opendaylight.mdsal.binding.api.RpcProviderService;
14 import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
15 import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException;
16 import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
17 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
18 import org.opendaylight.yangtools.concepts.Registration;
19 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
20 import org.opendaylight.yangtools.yang.binding.RpcService;
21 import org.osgi.framework.Bundle;
22 import org.osgi.service.blueprint.container.ComponentDefinitionException;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * Blueprint bean corresponding to the "action-provider" element that registers the promise to instantiate action
28  * instances with RpcProviderRegistry.
29  *
30  * <p>
31  * This bean has two distinct facets:
32  * - if a reference bean is provided, it registers it with {@link RpcProviderService}
33  * - if a reference bean is not provided, it registers the corresponding no-op implementation with
34  *   {@link DOMRpcProviderService} for all action (Routed RPC) elements in the provided interface
35  */
36 public class ActionProviderBean {
37     static final String ACTION_PROVIDER = "action-provider";
38
39     private static final Logger LOG = LoggerFactory.getLogger(ActionProviderBean.class);
40
41     private DOMRpcProviderService domRpcProvider = null;
42     private RpcProviderService bindingRpcProvider = null;
43     private DOMSchemaService schemaService = null;
44     private RpcService implementation = null;
45     private String interfaceName = null;
46     private Registration reg;
47     private Bundle bundle = null;
48
49     public void setBundle(final Bundle bundle) {
50         this.bundle = bundle;
51     }
52
53     public void setInterfaceName(final String interfaceName) {
54         this.interfaceName = interfaceName;
55     }
56
57     public void setImplementation(final RpcService implementation) {
58         this.implementation = implementation;
59     }
60
61     public void setDomRpcProvider(final DOMRpcProviderService rpcProviderService) {
62         domRpcProvider = rpcProviderService;
63     }
64
65     public void setBindingRpcProvider(final RpcProviderService rpcProvider) {
66         bindingRpcProvider = rpcProvider;
67     }
68
69     public void setSchemaService(final DOMSchemaService schemaService) {
70         this.schemaService = schemaService;
71     }
72
73     public void init() {
74         // First resolve the interface class
75         final Class<RpcService> interfaceClass = getRpcClass();
76
77         LOG.debug("{}: resolved interface {} to {}", ACTION_PROVIDER, interfaceName, interfaceClass);
78
79         if (implementation != null) {
80             registerImplementation(interfaceClass);
81         } else {
82             registerFallback(interfaceClass);
83         }
84     }
85
86     @SuppressWarnings("checkstyle:IllegalCatch")
87     public void destroy() {
88         if (reg != null) {
89             try {
90                 reg.close();
91             } catch (final Exception e) {
92                 LOG.warn("{}: error while unregistering", ACTION_PROVIDER, e);
93             } finally {
94                 reg = null;
95             }
96         }
97     }
98
99     @SuppressWarnings("unchecked")
100     private Class<RpcService> getRpcClass() {
101         final Class<?> iface;
102
103         try {
104             iface = bundle.loadClass(interfaceName);
105         } catch (final ClassNotFoundException e) {
106             throw new ComponentDefinitionException(String.format(
107                 "The specified \"interface\" for %s \"%s\" does not refer to an available class", interfaceName,
108                 ACTION_PROVIDER), e);
109         }
110         if (!RpcService.class.isAssignableFrom(iface)) {
111             throw new ComponentDefinitionException(String.format(
112                 "The specified \"interface\" %s for \"%s\" is not an RpcService", interfaceName, ACTION_PROVIDER));
113         }
114
115         return (Class<RpcService>) iface;
116     }
117
118     private void registerFallback(final Class<RpcService> interfaceClass) {
119         final var paths = RpcUtil.decomposeRpcService(interfaceClass, schemaService.getGlobalContext(),
120             Objects::nonNull);
121         if (paths.isEmpty()) {
122             LOG.warn("{}: interface {} has no actions defined", ACTION_PROVIDER, interfaceClass);
123             return;
124         }
125
126         final var rpcs = ImmutableSet.copyOf(Collections2.transform(paths, DOMRpcIdentifier::create));
127         reg = domRpcProvider.registerRpcImplementation(
128             (rpc, input) -> FluentFutures.immediateFailedFluentFuture(new DOMRpcImplementationNotAvailableException(
129                 "Action %s has no instance matching %s", rpc, input)), rpcs);
130         LOG.debug("Registered provider for {}", interfaceName);
131     }
132
133     private void registerImplementation(final Class<RpcService> interfaceClass) {
134         if (!interfaceClass.isInstance(implementation)) {
135             throw new ComponentDefinitionException(String.format(
136                 "The specified \"interface\" %s for \"%s\" is not implemented by RpcService \"ref\" %s",
137                 interfaceName, ACTION_PROVIDER, implementation.getClass()));
138         }
139
140         reg = bindingRpcProvider.registerRpcImplementation(interfaceClass, implementation);
141         LOG.debug("Registered implementation {} for {}", implementation, interfaceName);
142     }
143 }