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%2FRpcServiceMetadata.java;h=030a6840a8263099bea60ee0120806b1b6c0599a;hb=47788b7b68045c46994bd3f8a0aecc0df27037ed;hp=7fc077d2870fa417b09168402044f610db6af2f7;hpb=762f30c90106b79a775478f0485e0db76ea361ff;p=controller.git diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/RpcServiceMetadata.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/RpcServiceMetadata.java index 7fc077d287..030a6840a8 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/RpcServiceMetadata.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/RpcServiceMetadata.java @@ -7,13 +7,23 @@ */ package org.opendaylight.controller.blueprint.ext; -import com.google.common.base.Preconditions; -import java.util.Collections; -import java.util.List; -import org.apache.aries.blueprint.ext.ComponentFactoryMetadata; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import org.apache.aries.blueprint.services.ExtendedBlueprintContainer; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.binding.util.BindingReflections; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.osgi.service.blueprint.container.ComponentDefinitionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,74 +34,142 @@ import org.slf4j.LoggerFactory; * * @author Thomas Pantelis */ -class RpcServiceMetadata implements ComponentFactoryMetadata { +class RpcServiceMetadata extends AbstractDependentComponentFactoryMetadata { private static final Logger LOG = LoggerFactory.getLogger(RpcServiceMetadata.class); - private final String id; private final String interfaceName; - private ExtendedBlueprintContainer container; + private volatile Set rpcSchemaPaths; + private volatile RpcProviderRegistry rpcRegistry; + private volatile ListenerRegistration rpcListenerReg; + private volatile Class rpcInterface; RpcServiceMetadata(String id, String interfaceName) { - this.id = id; + super(id); this.interfaceName = interfaceName; } + @SuppressWarnings({ "checkstyle:IllegalCatch", "unchecked" }) @Override - public String getId() { - return id; + public void init(ExtendedBlueprintContainer container) { + super.init(container); + + try { + Class interfaceClass = container().getBundleContext().getBundle().loadClass(interfaceName); + if (!RpcService.class.isAssignableFrom(interfaceClass)) { + throw new ComponentDefinitionException(String.format( + "%s: The specified interface %s is not an RpcService", logName(), interfaceName)); + } + + rpcInterface = (Class)interfaceClass; + } catch (ComponentDefinitionException e) { + throw e; + } catch (Exception e) { + throw new ComponentDefinitionException(String.format("%s: Error obtaining interface class %s", + logName(), interfaceName), e); + } } @Override - public int getActivation() { - return ACTIVATION_LAZY; + protected void startTracking() { + // First get the SchemaContext. This will be used to get the RPC SchemaPaths. + + retrieveService("SchemaService", SchemaService.class, + service -> retrievedSchemaContext(((SchemaService)service).getGlobalContext())); } - @Override - public List getDependsOn() { - return Collections.singletonList(OpendaylightNamespaceHandler.RPC_REGISTRY_NAME); + private void retrievedSchemaContext(SchemaContext schemaContext) { + LOG.debug("{}: retrievedSchemaContext", logName()); + + QNameModule moduleName = BindingReflections.getQNameModule(rpcInterface); + Module module = schemaContext.findModuleByNamespaceAndRevision(moduleName.getNamespace(), + moduleName.getRevision()); + + LOG.debug("{}: Got Module: {}", logName(), module); + + rpcSchemaPaths = new HashSet<>(); + for (RpcDefinition rpcDef : module.getRpcs()) { + rpcSchemaPaths.add(rpcDef.getPath()); + } + + LOG.debug("{}: Got SchemaPaths: {}", logName(), rpcSchemaPaths); + + // First get the DOMRpcService OSGi service. This will be used to register a listener to be notified + // when the underlying DOM RPC service is available. + + retrieveService("DOMRpcService", DOMRpcService.class, + service -> retrievedDOMRpcService((DOMRpcService)service)); } - @Override - public void init(ExtendedBlueprintContainer container) { - this.container = container; + private void retrievedDOMRpcService(DOMRpcService domRpcService) { + LOG.debug("{}: retrievedDOMRpcService", logName()); + + setDependendencyDesc("Available DOM RPC for binding RPC: " + rpcInterface); + rpcListenerReg = domRpcService.registerRpcListener(new DOMRpcAvailabilityListener() { + @Override + public void onRpcAvailable(Collection rpcs) { + onRpcsAvailable(rpcs); + } + + @Override + public void onRpcUnavailable(Collection rpcs) { + } + }); + } - LOG.debug("{}: In init", logName()); + protected void onRpcsAvailable(Collection rpcs) { + for (DOMRpcIdentifier identifier : rpcs) { + if (rpcSchemaPaths.contains(identifier.getType())) { + LOG.debug("{}: onRpcsAvailable - found SchemaPath {}", logName(), identifier.getType()); + + retrieveService("RpcProviderRegistry", RpcProviderRegistry.class, service -> { + rpcRegistry = (RpcProviderRegistry)service; + setSatisfied(); + }); + + break; + } + } } - @SuppressWarnings("unchecked") + @SuppressWarnings("checkstyle:IllegalCatch") @Override public Object create() throws ComponentDefinitionException { LOG.debug("{}: In create: interfaceName: {}", logName(), interfaceName); - RpcProviderRegistry rpcRegistry = (RpcProviderRegistry) container.getComponentInstance( - OpendaylightNamespaceHandler.RPC_REGISTRY_NAME); + super.onCreate(); try { - Class rpcInterface = container.getBundleContext().getBundle().loadClass(interfaceName); - Preconditions.checkArgument(RpcService.class.isAssignableFrom(rpcInterface), - "Specified interface %s is not an RpcService", interfaceName); - - RpcService rpcService = rpcRegistry.getRpcService((Class)rpcInterface); + RpcService rpcService = rpcRegistry.getRpcService(rpcInterface); LOG.debug("{}: create returning service {}", logName(), rpcService); return rpcService; - } catch(Exception e) { + } catch (RuntimeException e) { throw new ComponentDefinitionException("Error getting RPC service for " + interfaceName, e); } } @Override - public void destroy(Object instance) { + public void stopTracking() { + super.stopTracking(); + closeRpcListenerReg(); } - private String logName() { - return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") + - " (" + id + ")"; + private void closeRpcListenerReg() { + if (rpcListenerReg != null) { + rpcListenerReg.close(); + rpcListenerReg = null; + } + } + + @Override + public void destroy(Object instance) { + super.destroy(instance); + closeRpcListenerReg(); } @Override public String toString() { - return "RpcServiceMetadata [id=" + id + ", interfaceName=" + interfaceName + ", container=" + container + "]"; + return "RpcServiceMetadata [id=" + getId() + ", interfaceName=" + interfaceName + "]"; } }