X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fblueprint%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fblueprint%2Fext%2FRpcServiceMetadata.java;h=82b1b6be157edd9f82e00b279038bfaaa4d34827;hp=7fc077d2870fa417b09168402044f610db6af2f7;hb=b9040c52d74cf4c16aeb16774f2c1056589fb203;hpb=762f30c90106b79a775478f0485e0db76ea361ff 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..82b1b6be15 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,54 +34,106 @@ 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; } @Override - public String getId() { - return id; + @SuppressWarnings("unchecked") + 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(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()); - LOG.debug("{}: In init", logName()); + rpcListenerReg = domRpcService.registerRpcListener(new DOMRpcAvailabilityListener() { + @Override + public void onRpcAvailable(Collection rpcs) { + onRpcsAvailable(rpcs); + } + + @Override + public void onRpcUnavailable(Collection rpcs) { + } + }); + } + + 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") @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); @@ -82,16 +144,26 @@ class RpcServiceMetadata implements ComponentFactoryMetadata { } @Override - public void destroy(Object instance) { + public void stopTracking() { + super.stopTracking(); + closeRpcListenerReg(); + } + + private void closeRpcListenerReg() { + if(rpcListenerReg != null) { + rpcListenerReg.close(); + rpcListenerReg = null; + } } - private String logName() { - return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") + - " (" + id + ")"; + @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 + "]"; } }