2 * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.blueprint.ext;
10 import com.google.common.collect.Collections2;
11 import com.google.common.collect.ImmutableSet;
12 import com.google.common.util.concurrent.Futures;
13 import java.util.Collection;
15 import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
16 import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException;
17 import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
18 import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
19 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
20 import org.opendaylight.controller.sal.core.api.model.SchemaService;
21 import org.opendaylight.yangtools.concepts.Registration;
22 import org.opendaylight.yangtools.yang.binding.RpcService;
23 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
24 import org.osgi.framework.Bundle;
25 import org.osgi.service.blueprint.container.ComponentDefinitionException;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Blueprint bean corresponding to the "action-provider" element that registers the promise to instantiate action
31 * instances with RpcProviderRegistry.
34 * This bean has two distinct facets:
35 * - if a reference bean is provided, it registers it with {@link RpcProviderRegistry}
36 * - if a reference bean is not provided, it registers the corresponding no-op implementation with
37 * {@link DOMRpcProviderService} for all action (Routed RPC) elements in the provided interface
39 * @author Robert Varga
41 public class ActionProviderBean {
42 static final String ACTION_PROVIDER = "action-provider";
44 private static final Logger LOG = LoggerFactory.getLogger(ActionProviderBean.class);
46 private DOMRpcProviderService rpcProviderService;
47 private RpcProviderRegistry rpcRegistry;
48 private SchemaService schemaService;
49 private RpcService implementation;
50 private String interfaceName;
51 private Registration reg;
52 private Bundle bundle;
54 public void setBundle(final Bundle bundle) {
58 public void setInterfaceName(final String interfaceName) {
59 this.interfaceName = interfaceName;
62 public void setImplementation(final RpcService implementation) {
63 this.implementation = implementation;
66 public void setRpcProviderService(final DOMRpcProviderService rpcProviderService) {
67 this.rpcProviderService = rpcProviderService;
70 public void setRpcRegistry(final RpcProviderRegistry rpcRegistry) {
71 this.rpcRegistry = rpcRegistry;
74 public void setSchemaService(final SchemaService schemaService) {
75 this.schemaService = schemaService;
79 // First resolve the interface class
80 final Class<RpcService> interfaceClass = getRpcClass(interfaceName);
82 LOG.debug("{}: resolved interface {} to {}", ACTION_PROVIDER, interfaceName, interfaceClass);
84 if (implementation != null) {
85 registerImplementation(interfaceClass);
87 registerFallback(interfaceClass);
91 @SuppressWarnings("checkstyle:IllegalCatch")
92 public void destroy() {
96 } catch (Exception e) {
97 LOG.warn("{}: error while unregistering", ACTION_PROVIDER, e);
104 @SuppressWarnings("unchecked")
105 private Class<RpcService> getRpcClass(final String interfaceName) {
106 final Class<?> iface;
109 iface = bundle.loadClass(interfaceName);
110 } catch (ClassNotFoundException e) {
111 throw new ComponentDefinitionException(String.format(
112 "The specified \"interface\" for %s \"%s\" does not refer to an available class", interfaceName,
113 ACTION_PROVIDER), e);
115 if (!RpcService.class.isAssignableFrom(iface)) {
116 throw new ComponentDefinitionException(String.format(
117 "The specified \"interface\" %s for \"%s\" is not an RpcService", interfaceName, ACTION_PROVIDER));
120 return (Class<RpcService>) iface;
123 private void registerFallback(final Class<RpcService> interfaceClass) {
124 final Collection<SchemaPath> paths = RpcUtil.decomposeRpcService(interfaceClass,
125 schemaService.getGlobalContext(), RpcRoutingStrategy::isContextBasedRouted);
126 if (paths.isEmpty()) {
127 LOG.warn("{}: interface {} has no actions defined", ACTION_PROVIDER, interfaceClass);
131 final Set<DOMRpcIdentifier> rpcs = ImmutableSet.copyOf(Collections2.transform(paths, DOMRpcIdentifier::create));
132 reg = rpcProviderService.registerRpcImplementation((rpc, input) -> {
133 return Futures.immediateFailedCheckedFuture(new DOMRpcImplementationNotAvailableException(
134 "Action %s has no instance matching %s", rpc, input));
136 LOG.debug("Registered provider for {}", interfaceName);
139 private void registerImplementation(final Class<RpcService> interfaceClass) {
140 if (!interfaceClass.isInstance(implementation)) {
141 throw new ComponentDefinitionException(String.format(
142 "The specified \"interface\" %s for \"%s\" is not implemented by RpcService \"ref\" %s",
143 interfaceName, ACTION_PROVIDER, implementation.getClass()));
146 reg = rpcRegistry.addRpcImplementation(interfaceClass, implementation);
147 LOG.debug("Registered implementation {} for {}", implementation, interfaceName);