1 package org.opendaylight.controller.sal.binding.impl;
4 import java.util.Map.Entry;
5 import java.util.HashMap;
7 import java.util.WeakHashMap;
9 import javax.swing.tree.ExpandVetoException;
11 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
12 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
13 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
14 import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
15 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
16 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
17 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
18 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
19 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
20 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper;
21 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
22 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
23 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
24 import org.opendaylight.yangtools.concepts.Identifiable;
25 import org.opendaylight.yangtools.concepts.ListenerRegistration;
26 import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
27 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.opendaylight.yangtools.yang.binding.RpcService;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import static com.google.common.base.Preconditions.*;
35 public class RpcProviderRegistryImpl implements //
36 RpcProviderRegistry, //
37 RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
39 private RuntimeCodeGenerator rpcFactory = SingletonHolder.RPC_GENERATOR_IMPL;
41 private final Map<Class<? extends RpcService>, RpcService> publicProxies = new WeakHashMap<>();
42 private final Map<Class<? extends RpcService>, RpcRouter<?>> rpcRouters = new WeakHashMap<>();
43 private final ListenerRegistry<RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> routeChangeListeners = ListenerRegistry
46 private final static Logger LOG = LoggerFactory.getLogger(RpcProviderRegistryImpl.class);
48 private final String name;
50 public String getName() {
54 public RpcProviderRegistryImpl(String name) {
60 public final <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type,
61 T implementation) throws IllegalStateException {
62 return getRpcRouter(type).addRoutedRpcImplementation(implementation);
66 public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
67 throws IllegalStateException {
68 @SuppressWarnings("unchecked")
69 RpcRouter<T> potentialRouter = (RpcRouter<T>) rpcRouters.get(type);
70 if (potentialRouter != null) {
71 checkState(potentialRouter.getDefaultService() == null,
72 "Default service for routed RPC already registered.");
73 return potentialRouter.registerDefaultService(implementation);
75 T publicProxy = getRpcService(type);
76 RpcService currentDelegate = RuntimeCodeHelper.getDelegate(publicProxy);
77 checkState(currentDelegate == null, "Rpc service is already registered");
78 LOG.debug("Registering {} as global implementation of {} in {}",implementation,type.getSimpleName(),this);
79 RuntimeCodeHelper.setDelegate(publicProxy, implementation);
80 return new RpcProxyRegistration<T>(type, implementation, this);
83 @SuppressWarnings("unchecked")
85 public final <T extends RpcService> T getRpcService(Class<T> type) {
87 @SuppressWarnings("unchecked")
88 T potentialProxy = (T) publicProxies.get(type);
89 if (potentialProxy != null) {
90 return potentialProxy;
94 * Potential proxy could be instantiated by other thread while we were
95 * waiting for the lock.
98 potentialProxy = (T) publicProxies.get(type);
99 if (potentialProxy != null) {
100 return (T) potentialProxy;
102 T proxy = rpcFactory.getDirectProxyFor(type);
103 LOG.debug("Created {} as public proxy for {} in {}",proxy,type.getSimpleName(),this);
104 publicProxies.put(type, proxy);
109 private <T extends RpcService> RpcRouter<T> getRpcRouter(Class<T> type) {
110 RpcRouter<?> potentialRouter = rpcRouters.get(type);
111 if (potentialRouter != null) {
112 return (RpcRouter<T>) potentialRouter;
116 * Potential Router could be instantiated by other thread while we were
117 * waiting for the lock.
119 potentialRouter = rpcRouters.get(type);
120 if (potentialRouter != null) {
121 return (RpcRouter<T>) potentialRouter;
123 RpcRouter<T> router = rpcFactory.getRouterFor(type,name);
124 router.registerRouteChangeListener(new RouteChangeForwarder(type));
125 LOG.debug("Registering router {} as global implementation of {} in {}",router,type.getSimpleName(),this);
126 RuntimeCodeHelper.setDelegate(getRpcService(type), router.getInvocationProxy());
127 rpcRouters.put(type, router);
133 public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
135 return (ListenerRegistration<L>) routeChangeListeners.register(listener);
138 public RuntimeCodeGenerator getRpcFactory() {
142 public void setRpcFactory(RuntimeCodeGenerator rpcFactory) {
143 this.rpcFactory = rpcFactory;
146 private class RouteChangeForwarder<T extends RpcService> implements
147 RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
149 private final Class<T> type;
151 public RouteChangeForwarder(Class<T> type) {
156 public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
157 Map<RpcContextIdentifier, Set<InstanceIdentifier<?>>> announcements = new HashMap<>();
158 for (Entry<Class<? extends BaseIdentity>, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements()
160 RpcContextIdentifier key = RpcContextIdentifier.contextFor(type, entry.getKey());
161 announcements.put(key, entry.getValue());
163 Map<RpcContextIdentifier, Set<InstanceIdentifier<?>>> removals = new HashMap<>();
164 for (Entry<Class<? extends BaseIdentity>, Set<InstanceIdentifier<?>>> entry : change.getRemovals()
166 RpcContextIdentifier key = RpcContextIdentifier.contextFor(type, entry.getKey());
167 removals.put(key, entry.getValue());
169 RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> toPublish = RoutingUtils
170 .<RpcContextIdentifier, InstanceIdentifier<?>> change(announcements, removals);
171 for (ListenerRegistration<RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> listener : routeChangeListeners) {
173 listener.getInstance().onRouteChange(toPublish);
174 } catch (Exception e) {
181 public static class RpcProxyRegistration<T extends RpcService> extends AbstractObjectRegistration<T> implements
184 private final Class<T> serviceType;
185 private RpcProviderRegistryImpl registry;
187 public RpcProxyRegistration(Class<T> type, T service, RpcProviderRegistryImpl registry) {
193 public Class<T> getServiceType() {
198 protected void removeRegistration() {
199 if (registry != null) {
200 T publicProxy = registry.getRpcService(serviceType);
201 RpcService currentDelegate = RuntimeCodeHelper.getDelegate(publicProxy);
202 if (currentDelegate == getInstance()) {
203 RuntimeCodeHelper.setDelegate(publicProxy, null);