2 * Copyright (c) 2013 Cisco 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.yangtools.restconf.client;
10 import java.lang.reflect.InvocationHandler;
11 import java.lang.reflect.Method;
12 import java.lang.reflect.Proxy;
13 import java.util.ArrayList;
14 import java.util.List;
16 import org.opendaylight.yangtools.restconf.client.to.RestRpcError;
17 import org.opendaylight.yangtools.restconf.client.to.RestRpcResult;
18 import org.opendaylight.yangtools.restconf.common.ResourceUri;
19 import org.opendaylight.yangtools.restconf.utils.XmlTools;
20 import org.opendaylight.yangtools.yang.binding.BindingMapping;
21 import org.opendaylight.yangtools.yang.binding.DataContainer;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
24 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
25 import org.opendaylight.yangtools.yang.common.RpcError;
26 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
27 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
28 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.w3c.dom.Document;
36 import org.w3c.dom.ls.DOMImplementationLS;
37 import org.w3c.dom.ls.LSSerializer;
39 import com.google.common.base.Function;
40 import com.google.common.base.Optional;
41 import com.sun.jersey.api.client.ClientResponse;
43 public class BindingToRestRpc implements InvocationHandler {
45 private final RestconfClientImpl client;
46 private static final Logger logger = LoggerFactory.getLogger(BindingToRestRpc.class);
47 private final BindingIndependentMappingService mappingService;
48 private final SchemaContext schcemaContext;
49 private final Module module;
51 public BindingToRestRpc(final Class<?> proxiedInterface,final BindingIndependentMappingService mappingService,final RestconfClientImpl client,final SchemaContext schemaContext) throws Exception {
52 this.mappingService = mappingService;
54 this.schcemaContext = schemaContext;
55 YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(proxiedInterface);
56 this.module = schemaContext.findModuleByName(moduleInfo.getName(),org.opendaylight.yangtools.yang.common.QName.parseRevision(moduleInfo.getRevision()));
60 public Object invoke(final Object o,final Method method, final Object[] objects) throws Exception {
61 for (RpcDefinition rpcDef:module.getRpcs()){
62 if (method.getName().equals(BindingMapping.getMethodName(rpcDef.getQName()))){
64 String moduleName = BindingReflections.getModuleInfo(method.getDeclaringClass()).getName();
65 String rpcMethodName = rpcDef.getQName().getLocalName();
66 Document rpcInputDoc = null;
67 for (Object component:objects){
68 CompositeNode rpcInput = mappingService.toDataDom((DataObject) component);
69 rpcInputDoc = XmlDocumentUtils.toDocument(rpcInput,rpcDef.getInput(),XmlDocumentUtils.defaultValueCodecProvider());
71 DOMImplementationLS lsImpl = (DOMImplementationLS)rpcInputDoc.getImplementation().getFeature("LS", "3.0");
72 LSSerializer serializer = lsImpl.createLSSerializer();
73 serializer.getDomConfig().setParameter("xml-declaration", false);
75 String payloadString = serializer.writeToString(rpcInputDoc);
76 final Class<? extends DataContainer> desiredOutputClass = (Class<? extends DataContainer>)BindingReflections.resolveRpcOutputClass(method).get();
77 final DataSchemaNode rpcOutputSchema = rpcDef.getOutput();
78 return client.post(ResourceUri.OPERATIONS.getPath() + "/" + moduleName + ":" + rpcMethodName,payloadString,new Function<ClientResponse, Object>() {
80 public Object apply(final ClientResponse clientResponse) {
81 if (clientResponse.getStatus() != 200) {
82 throw new IllegalStateException("Can't get data from restconf. "+clientResponse.getClientResponseStatus());
84 List<RpcError> errors = new ArrayList<>();
86 Document rpcOutputDocument = XmlTools.fromXml(clientResponse.getEntityInputStream());
87 CompositeNode cn = (CompositeNode) XmlDocumentUtils.toDomNode(rpcOutputDocument.getDocumentElement(),
88 Optional.of(rpcOutputSchema),
89 Optional.of(XmlDocumentUtils.defaultValueCodecProvider()));
90 DataContainer rpcOutputDataObject = mappingService.dataObjectFromDataDom(desiredOutputClass, cn);
91 return new RestRpcResult(true,rpcOutputDataObject);
92 } catch (Exception e) {
93 logger.trace("Error while extracting rpc output in proxy method {}",e);
94 RestRpcError error = new RestRpcError(RpcError.ErrorSeverity.ERROR, RpcError.ErrorType.APPLICATION,"Error while extracting rpc output in proxy method.",e);
96 return new RestRpcResult(false,errors);
101 throw new IllegalStateException("Unexpected state of proxy method.");
104 public static<T> T getProxy(final Class<T> proxiedInterface,
105 final BindingIndependentMappingService mappingService,
106 final RestconfClientImpl restconfClient,
107 final SchemaContext schemaContext) {
108 T proxiedType = null;
110 proxiedType = (T) Proxy.newProxyInstance
111 (BindingToRestRpc.class.getClassLoader(),
112 new Class[]{proxiedInterface}, new BindingToRestRpc(proxiedInterface, mappingService, restconfClient, schemaContext));
113 } catch (Exception e) {
114 throw new IllegalStateException(e.getMessage());