2 * Copyright (c) 2016 Brocade Communications 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 static java.util.Objects.requireNonNull;
12 import com.google.common.base.MoreObjects;
13 import com.google.common.collect.ImmutableSet;
14 import java.util.Collection;
16 import java.util.function.Predicate;
17 import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
18 import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
19 import org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener;
20 import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
21 import org.opendaylight.mdsal.dom.api.DOMRpcService;
22 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
23 import org.opendaylight.mdsal.dom.spi.RpcRoutingStrategy;
24 import org.opendaylight.yangtools.concepts.ListenerRegistration;
25 import org.opendaylight.yangtools.yang.binding.RpcService;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
27 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
28 import org.osgi.service.blueprint.container.ComponentDefinitionException;
30 abstract class AbstractInvokableServiceMetadata extends AbstractDependentComponentFactoryMetadata {
31 private final String interfaceName;
33 private ListenerRegistration<DOMRpcAvailabilityListener> rpcListenerReg;
34 private RpcConsumerRegistry rpcRegistry;
35 private Class<RpcService> rpcInterface;
36 private Set<SchemaPath> rpcSchemaPaths;
38 AbstractInvokableServiceMetadata(final String id, final String interfaceName) {
40 this.interfaceName = requireNonNull(interfaceName);
43 Class<RpcService> rpcInterface() {
47 @SuppressWarnings({ "checkstyle:IllegalCatch", "unchecked" })
49 public final void init(final ExtendedBlueprintContainer container) {
50 super.init(container);
52 final Class<?> interfaceClass;
54 interfaceClass = container().getBundleContext().getBundle().loadClass(interfaceName);
55 } catch (final Exception e) {
56 throw new ComponentDefinitionException(String.format("%s: Error obtaining interface class %s",
57 logName(), interfaceName), e);
60 if (!RpcService.class.isAssignableFrom(interfaceClass)) {
61 throw new ComponentDefinitionException(String.format(
62 "%s: The specified interface %s is not an RpcService", logName(), interfaceName));
65 rpcInterface = (Class<RpcService>)interfaceClass;
69 protected final void startTracking() {
70 // Request RpcProviderRegistry first ...
71 retrieveService("RpcConsumerRegistry", RpcConsumerRegistry.class, this::onRpcRegistry);
74 private void onRpcRegistry(final Object service) {
75 log.debug("{}: Retrieved RpcProviderRegistry {}", logName(), service);
76 rpcRegistry = (RpcConsumerRegistry)service;
78 // Now acquire SchemaService...
79 retrieveService("SchemaService", DOMSchemaService.class, this::onSchemaService);
82 private void onSchemaService(final Object service) {
83 log.debug("{}: Retrieved SchemaService {}", logName(), service);
85 // Now get the SchemaContext and trigger RPC resolution
86 retrievedSchemaContext(((DOMSchemaService)service).getGlobalContext());
89 private void retrievedSchemaContext(final SchemaContext schemaContext) {
90 log.debug("{}: retrievedSchemaContext", logName());
92 final Collection<SchemaPath> schemaPaths = RpcUtil.decomposeRpcService(rpcInterface, schemaContext,
94 if (schemaPaths.isEmpty()) {
95 log.debug("{}: interface {} has no acceptable entries, assuming it is satisfied", logName(), rpcInterface);
100 rpcSchemaPaths = ImmutableSet.copyOf(schemaPaths);
101 log.debug("{}: Got SchemaPaths: {}", logName(), rpcSchemaPaths);
103 // First get the DOMRpcService OSGi service. This will be used to register a listener to be notified
104 // when the underlying DOM RPC service is available.
105 retrieveService("DOMRpcService", DOMRpcService.class, this::retrievedDOMRpcService);
108 private void retrievedDOMRpcService(final Object service) {
109 log.debug("{}: retrievedDOMRpcService {}", logName(), service);
110 final DOMRpcService domRpcService = (DOMRpcService)service;
112 setDependencyDesc("Available DOM RPC for binding RPC: " + rpcInterface);
113 rpcListenerReg = domRpcService.registerRpcListener(new DOMRpcAvailabilityListener() {
115 public void onRpcAvailable(final Collection<DOMRpcIdentifier> rpcs) {
116 onRpcsAvailable(rpcs);
120 public void onRpcUnavailable(final Collection<DOMRpcIdentifier> rpcs) {
125 abstract Predicate<RpcRoutingStrategy> rpcFilter();
127 @SuppressWarnings("checkstyle:IllegalCatch")
129 public final Object create() throws ComponentDefinitionException {
130 log.debug("{}: In create: interfaceName: {}", logName(), interfaceName);
135 RpcService rpcService = rpcRegistry.getRpcService(rpcInterface);
137 log.debug("{}: create returning service {}", logName(), rpcService);
140 } catch (final RuntimeException e) {
141 throw new ComponentDefinitionException("Error getting RPC service for " + interfaceName, e);
145 protected final void onRpcsAvailable(final Collection<DOMRpcIdentifier> rpcs) {
146 for (DOMRpcIdentifier identifier : rpcs) {
147 if (rpcSchemaPaths.contains(identifier.getType())) {
148 log.debug("{}: onRpcsAvailable - found SchemaPath {}", logName(), identifier.getType());
156 public final void stopTracking() {
157 super.stopTracking();
158 closeRpcListenerReg();
161 private void closeRpcListenerReg() {
162 if (rpcListenerReg != null) {
163 rpcListenerReg.close();
164 rpcListenerReg = null;
169 public final void destroy(final Object instance) {
170 super.destroy(instance);
171 closeRpcListenerReg();
175 public final String toString() {
176 return MoreObjects.toStringHelper(this).add("id", getId()).add("interfaceName", interfaceName).toString();