Added initial Response handling code. Error handling needs more work & needs some...
[ovsdb.git] / ovsdb / src / main / java / org / opendaylight / ovsdb / lib / jsonrpc / JsonRpcEndpoint.java
1 package org.opendaylight.ovsdb.lib.jsonrpc;
2
3 import com.fasterxml.jackson.core.JsonProcessingException;
4 import com.fasterxml.jackson.databind.JsonNode;
5 import com.fasterxml.jackson.databind.ObjectMapper;
6 import com.fasterxml.jackson.databind.node.ArrayNode;
7 import com.google.common.collect.Maps;
8 import com.google.common.reflect.Reflection;
9 import com.google.common.reflect.TypeToken;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import com.google.common.util.concurrent.SettableFuture;
12
13 import org.opendaylight.controller.sal.core.Node;
14 import org.opendaylight.ovsdb.lib.message.Response;
15 import org.opendaylight.ovsdb.plugin.Connection;
16 import org.opendaylight.ovsdb.plugin.ConnectionService;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 import java.lang.reflect.InvocationHandler;
21 import java.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.UUID;
26
27 public class JsonRpcEndpoint {
28
29     protected static final Logger logger = LoggerFactory.getLogger(JsonRpcEndpoint.class);
30
31     public class CallContext {
32         Method method;
33         JsonRpc10Request request;
34         SettableFuture<Object> future;
35
36         public CallContext(JsonRpc10Request request, Method method, SettableFuture<Object> future) {
37             this.method = method;
38             this.request = request;
39             this.future = future;
40         }
41
42         public Method getMethod() {
43             return method;
44         }
45
46         public JsonRpc10Request getRequest() {
47             return request;
48         }
49
50         public SettableFuture<Object> getFuture() {
51             return future;
52         }
53     }
54
55     ObjectMapper objectMapper;
56     ConnectionService service;
57     Map<String, CallContext> methodContext = Maps.newHashMap();
58
59     public JsonRpcEndpoint(ObjectMapper objectMapper, ConnectionService service) {
60         this.objectMapper = objectMapper;
61         this.service = service;
62     }
63
64     public <T> T getClient(final Node node, Class<T> klazz) {
65
66         return Reflection.newProxy(klazz, new InvocationHandler() {
67             @Override
68             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
69
70                 JsonRpc10Request request = new JsonRpc10Request(UUID.randomUUID().toString());
71                 request.setMethod(method.getName());
72
73
74                 if (args != null && args.length != 0) {
75                     List<Object> params = null;
76
77                     if (args.length == 1) {
78                         if (args[0] instanceof Params) {
79                             params = ((Params) args[0]).params();
80                         } else if (args[0] instanceof List) {
81                             params = (List<Object>) args[0];
82                         }
83
84                         if (params == null) {
85                             throw new RuntimeException("do not understand this argument yet");
86                         }
87                         request.setParams(params);
88                     }
89                 }
90
91                 String s = objectMapper.writeValueAsString(request);
92                 logger.debug("{}", s);
93
94                 SettableFuture<Object> sf = SettableFuture.create();
95                 methodContext.put(request.getId(), new CallContext(request, method, sf));
96
97                 Connection connection = service.getConnection(node);
98                 connection.getChannel().writeAndFlush(s);
99
100                 return sf;
101             }
102         }
103         );
104     }
105
106     public void processResult(JsonNode response) throws NoSuchMethodException {
107
108         CallContext returnCtxt = methodContext.get(response.get("id").asText());
109         if (returnCtxt == null) return;
110
111         Class<?> returnType = null;
112         if (ListenableFuture.class == returnCtxt.getMethod().getReturnType()) {
113             TypeToken<?> retType = TypeToken.of(
114                     returnCtxt.getMethod().getGenericReturnType())
115                     .resolveType(ListenableFuture.class.getMethod("get").getGenericReturnType());
116
117             JsonNode result = response.get("result");
118             logger.debug("Response : {}", result.toString());
119             Object result1 = objectMapper.convertValue(result, retType.getRawType());
120             JsonNode error = response.get("error");
121             if (error != null) {
122                 logger.debug("Error : {}", error.toString());
123             }
124
125             returnCtxt.getFuture().set(result1);
126
127         } else {
128             throw new RuntimeException("donno how to deal with this");
129         }
130     }
131
132     public void processRequest(Node node, JsonNode requestJson) {
133         JsonRpc10Request request = new JsonRpc10Request(requestJson.get("id").asText());
134         request.setMethod(requestJson.get("method").asText());
135
136         // TODO : Take care of listener interested in the async message from ovsdb-server
137         // and return a result to be sent back.
138         // The following piece of code will help with ECHO handling as is.
139         JsonRpc10Response response = new JsonRpc10Response(request.getId());
140         response.setError(null);
141         try {
142             String s = objectMapper.writeValueAsString(response);
143             Connection connection = service.getConnection(node);
144             connection.getChannel().writeAndFlush(s);
145         } catch (JsonProcessingException e) {
146             e.printStackTrace();
147         }
148     }
149
150     public Map<String, CallContext> getMethodContext() {
151         return methodContext;
152     }
153 }