Move blueprint code into place
[mdsal.git] / blueprint / mdsal-blueprint-binding / src / main / java / org / opendaylight / controller / blueprint / ext / RoutedRpcMetadata.java
1 /*
2  * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.blueprint.ext;
9
10 import java.util.Arrays;
11 import java.util.List;
12 import org.apache.aries.blueprint.ext.ComponentFactoryMetadata;
13 import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
14 import org.opendaylight.mdsal.binding.api.RpcProviderService;
15 import org.opendaylight.yangtools.yang.binding.RpcService;
16 import org.osgi.service.blueprint.container.ComponentDefinitionException;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * Factory metadata corresponding to the "routed-rpc-implementation" element that registers an RPC
22  * implementation with the RpcProviderRegistry and provides the RoutedRpcRegistration instance to the
23  * Blueprint container.
24  *
25  * @author Thomas Pantelis
26  */
27 class RoutedRpcMetadata implements ComponentFactoryMetadata {
28     private static final Logger LOG = LoggerFactory.getLogger(RoutedRpcMetadata.class);
29     static final String ROUTED_RPC_IMPLEMENTATION = "routed-rpc-implementation";
30
31     private final String id;
32     private final String interfaceName;
33     private final String implementationRefId;
34     private ExtendedBlueprintContainer container;
35
36     RoutedRpcMetadata(final String id, final String interfaceName, final String implementationRefId) {
37         this.id = id;
38         this.interfaceName = interfaceName;
39         this.implementationRefId = implementationRefId;
40     }
41
42     @Override
43     public String getId() {
44         return id;
45     }
46
47     @Override
48     public int getActivation() {
49         return ACTIVATION_LAZY;
50     }
51
52     @Override
53     public List<String> getDependsOn() {
54         return Arrays.asList(OpendaylightNamespaceHandler.BINDING_RPC_PROVIDER_SERVICE_NAME, implementationRefId);
55     }
56
57     @Override
58     public void init(final ExtendedBlueprintContainer newContainer) {
59         this.container = newContainer;
60
61         LOG.debug("{}: In init", logName());
62     }
63
64     @SuppressWarnings("checkstyle:IllegalCatch")
65     @Override
66     public Object create() throws ComponentDefinitionException {
67         RpcProviderService rpcRegistry = (RpcProviderService) container.getComponentInstance(
68                 OpendaylightNamespaceHandler.BINDING_RPC_PROVIDER_SERVICE_NAME);
69
70         Object implementation = container.getComponentInstance(implementationRefId);
71
72         try {
73             if (!RpcService.class.isAssignableFrom(implementation.getClass())) {
74                 throw new ComponentDefinitionException(String.format(
75                         "Implementation \"ref\" instance %s for \"%s\" is not an RpcService",
76                         implementation.getClass(), ROUTED_RPC_IMPLEMENTATION));
77             }
78
79             List<Class<RpcService>> rpcInterfaces = RpcImplementationBean.getImplementedRpcServiceInterfaces(
80                     interfaceName, implementation.getClass(), container.getBundleContext().getBundle(),
81                     ROUTED_RPC_IMPLEMENTATION);
82
83             if (rpcInterfaces.size() > 1) {
84                 throw new ComponentDefinitionException(String.format(
85                         "Implementation \"ref\" instance %s for \"%s\" implements more than one RpcService "
86                         + "interface (%s). Please specify the exact \"interface\"", implementation.getClass(),
87                         ROUTED_RPC_IMPLEMENTATION, rpcInterfaces));
88             }
89
90             Class<RpcService> rpcInterface = rpcInterfaces.iterator().next();
91
92             LOG.debug("{}: create - adding routed implementation {} for RpcService {}", logName(),
93                     implementation, rpcInterface);
94
95             return rpcRegistry.addRoutedRpcImplementation(rpcInterface, (RpcService)implementation);
96         } catch (final ComponentDefinitionException e) {
97             throw e;
98         } catch (final Exception e) {
99             throw new ComponentDefinitionException(String.format(
100                     "Error processing \"%s\" for %s", ROUTED_RPC_IMPLEMENTATION, implementation.getClass()), e);
101         }
102     }
103
104     @Override
105     public void destroy(final Object instance) {
106         LOG.debug("{}: In destroy: instance: {}", logName(), instance);
107
108         ((RoutedRpcRegistration<?>)instance).close();
109     }
110
111     private String logName() {
112         return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") + " (" + id + ")";
113     }
114 }