X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fblueprint%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fblueprint%2Fext%2FActionProviderBean.java;fp=opendaylight%2Fblueprint%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fblueprint%2Fext%2FActionProviderBean.java;h=bbd989b633a00cd36885f2d27dabc4dd6bb36b4c;hb=88330d2f3ff048ab4e2e6f348ec3ea56e4c02cd4;hp=0000000000000000000000000000000000000000;hpb=aa342f77a044988c1f6a0deaf9f7e94373f2dfb5;p=controller.git diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/ActionProviderBean.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/ActionProviderBean.java new file mode 100644 index 0000000000..bbd989b633 --- /dev/null +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/ActionProviderBean.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.blueprint.ext; + +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Futures; +import java.util.Collection; +import java.util.Set; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService; +import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.osgi.framework.Bundle; +import org.osgi.service.blueprint.container.ComponentDefinitionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Blueprint bean corresponding to the "action-provider" element that registers the promise to instantiate action + * instances with RpcProviderRegistry. + * + *

+ * This bean has two distinct facets: + * - if a reference bean is provided, it registers it with {@link RpcProviderRegistry} + * - if a reference bean is not provided, it registers the corresponding no-op implementation with + * {@link DOMRpcProviderService} for all action (Routed RPC) elements in the provided interface + * + * @author Robert Varga + */ +public class ActionProviderBean { + static final String ACTION_PROVIDER = "action-provider"; + + private static final Logger LOG = LoggerFactory.getLogger(ActionProviderBean.class); + + private DOMRpcProviderService rpcProviderService; + private RpcProviderRegistry rpcRegistry; + private SchemaService schemaService; + private RpcService implementation; + private String interfaceName; + private Registration reg; + private Bundle bundle; + + public void setBundle(final Bundle bundle) { + this.bundle = bundle; + } + + public void setInterfaceName(final String interfaceName) { + this.interfaceName = interfaceName; + } + + public void setImplementation(final RpcService implementation) { + this.implementation = implementation; + } + + public void setRpcProviderService(final DOMRpcProviderService rpcProviderService) { + this.rpcProviderService = rpcProviderService; + } + + public void setRpcRegistry(final RpcProviderRegistry rpcRegistry) { + this.rpcRegistry = rpcRegistry; + } + + public void setSchemaService(final SchemaService schemaService) { + this.schemaService = schemaService; + } + + public void init() { + // First resolve the interface class + final Class interfaceClass = getRpcClass(interfaceName); + + LOG.debug("{}: resolved interface {} to {}", ACTION_PROVIDER, interfaceName, interfaceClass); + + if (implementation != null) { + registerImplementation(interfaceClass); + } else { + registerFallback(interfaceClass); + } + } + + @SuppressWarnings("checkstyle:IllegalCatch") + public void destroy() { + if (reg != null) { + try { + reg.close(); + } catch (Exception e) { + LOG.warn("{}: error while unregistering", ACTION_PROVIDER, e); + } finally { + reg = null; + } + } + } + + @SuppressWarnings("unchecked") + private Class getRpcClass(final String interfaceName) { + final Class iface; + + try { + iface = bundle.loadClass(interfaceName); + } catch (ClassNotFoundException e) { + throw new ComponentDefinitionException(String.format( + "The specified \"interface\" for %s \"%s\" does not refer to an available class", interfaceName, + ACTION_PROVIDER), e); + } + if (!RpcService.class.isAssignableFrom(iface)) { + throw new ComponentDefinitionException(String.format( + "The specified \"interface\" %s for \"%s\" is not an RpcService", interfaceName, ACTION_PROVIDER)); + } + + return (Class) iface; + } + + private void registerFallback(final Class interfaceClass) { + final Collection paths = RpcUtil.decomposeRpcService(interfaceClass, + schemaService.getGlobalContext(), RpcRoutingStrategy::isContextBasedRouted); + if (paths.isEmpty()) { + LOG.warn("{}: interface {} has no actions defined", ACTION_PROVIDER, interfaceClass); + return; + } + + final Set rpcs = ImmutableSet.copyOf(Collections2.transform(paths, DOMRpcIdentifier::create)); + reg = rpcProviderService.registerRpcImplementation((rpc, input) -> { + return Futures.immediateFailedCheckedFuture(new DOMRpcImplementationNotAvailableException( + "Action %s has no instance matching %s", rpc, input)); + }, rpcs); + LOG.debug("Registered provider for {}", interfaceName); + } + + private void registerImplementation(final Class interfaceClass) { + if (!interfaceClass.isInstance(implementation)) { + throw new ComponentDefinitionException(String.format( + "The specified \"interface\" %s for \"%s\" is not implemented by RpcService \"ref\" %s", + interfaceName, ACTION_PROVIDER, implementation.getClass())); + } + + reg = rpcRegistry.addRpcImplementation(interfaceClass, implementation); + LOG.debug("Registered implementation {} for {}", implementation, interfaceName); + } +}