added missing payload extraction in proxy method 27/5327/15
authorMartin Bobak <mbobak@cisco.com>
Fri, 14 Feb 2014 11:50:32 +0000 (12:50 +0100)
committerMartin Bobak <mbobak@cisco.com>
Wed, 26 Feb 2014 12:28:16 +0000 (13:28 +0100)
added request type to event stream context calls

Change-Id: Ibecf4ec59f53aa1bf0dcbf1295533b23a0c5b3c4
Signed-off-by: Martin Bobak <mbobak@cisco.com>
restconf/pom.xml
restconf/restconf-client-impl/pom.xml
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/BindingToRestRpc.java
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/ConfigurationDataStoreImpl.java
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/RestListenableEventStreamContext.java [moved from restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/to/RestListenableEventStreamContext.java with 69% similarity]
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/RestconfClientImpl.java
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/to/RestRpcServiceContext.java
restconf/restconf-common/src/main/java/org/opendaylight/yangtools/restconf/common/ResourceMediaTypes.java
restconf/restconf-util/pom.xml
restconf/restconf-util/src/main/java/org/opendaylight/yangtools/restconf/utils/XmlTools.java
websocket/websocket-client/src/main/java/org/opendaylight/yangtools/websocket/client/WebSocketIClient.java

index 1cc80e70f4694e0e673b2d08eab40ff5e23df98f..c22dd7ca01cfadb7a59ebace6ee0edf5d1ac2687 100644 (file)
                 <artifactId>binding-generator-impl</artifactId>
                 <version>${project.version}</version>
             </dependency>
-
         </dependencies>
     </dependencyManagement>
 
index 42e3add3d6a37e73a10236903f71ed384b999a55..75eefd3780651bc2f5700d162ab4b628fb93ad48 100644 (file)
             <groupId>org.glassfish.jersey.ext</groupId>
             <artifactId>jersey-proxy-client</artifactId>
         </dependency>
-<!--
-      <dependency>
-          <groupId>org.jboss.resteasy</groupId>
-          <artifactId>resteasy-jaxrs</artifactId>
-      </dependency>
--->
       <dependency>
           <groupId>org.glassfish.jersey.core</groupId>
           <artifactId>jersey-client</artifactId>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>binding-generator-impl</artifactId>
       </dependency>
-<!--       <dependency> -->
-<!--           <groupId>org.opendaylight.controller.model</groupId> -->
-<!--           <artifactId>model-flow-service</artifactId> -->
-<!--           <version>1.1-SNAPSHOT</version> -->
-<!--           <scope>test</scope> -->
-<!--       </dependency> -->
   </dependencies>
     <build>
         <plugins>
index deacc8422d6689335cb2751cfdc79609b7a1c69a..6e695359daf0f2e02b8d6e9e8388fd2c0e88aa88 100644 (file)
  */
 package org.opendaylight.yangtools.restconf.client;
 
-import com.sun.jersey.api.client.Client;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.api.client.config.ClientConfig;
-import com.sun.jersey.api.client.config.DefaultClientConfig;
-import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
-import java.io.InputStream;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
-import org.opendaylight.yangtools.restconf.common.ResourceMediaTypes;
+import org.opendaylight.yangtools.restconf.client.to.RestRpcError;
+import org.opendaylight.yangtools.restconf.client.to.RestRpcResult;
 import org.opendaylight.yangtools.restconf.common.ResourceUri;
 import org.opendaylight.yangtools.restconf.utils.XmlTools;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSSerializer;
 
 public class BindingToRestRpc implements InvocationHandler {
 
-    private final Client client;
-    private final URI defaultUri;
+    private final RestconfClientImpl client;
     private static final Logger logger = LoggerFactory.getLogger(BindingToRestRpc.class);
-
-    public BindingToRestRpc(URI uri) {
-        ClientConfig config = new DefaultClientConfig();
-        this.client  = Client.create(config);
-        this.client.addFilter(new HTTPBasicAuthFilter("admin", "admin"));
-        this.defaultUri = uri;
+    private final BindingIndependentMappingService mappingService;
+    private final SchemaContext schcemaContext;
+    private final Module module;
+
+    public BindingToRestRpc(Class proxiedInterface,BindingIndependentMappingService mappingService,RestconfClientImpl client,SchemaContext schemaContext) throws Exception {
+        this.mappingService = mappingService;
+        this.client  = client;
+        this.schcemaContext = schemaContext;
+        YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(proxiedInterface);
+        this.module = schemaContext.findModuleByName(moduleInfo.getName(),org.opendaylight.yangtools.yang.common.QName.parseRevision(moduleInfo.getRevision()));
     }
 
     @Override
-    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
-
-        YangModelParser parser = new YangParserImpl();
-
-        Method getInstanceMethod = Class.forName(method.getDeclaringClass().getPackage().getName()+".$YangModuleInfoImpl").getMethod("getInstance",new Class[0]);
-
-        YangModuleInfo yangModuleInfo = (YangModuleInfo) getInstanceMethod.invoke(null,new Object[0]);
-
-                List<InputStream> moduleStreams = new ArrayList<InputStream>();
-        moduleStreams.add(yangModuleInfo.getModuleSourceStream());
-
-        Set<Module> modules = parser.parseYangModelsFromStreams(moduleStreams);
-
-        for (Module m:modules){
-            for (RpcDefinition rpcDef:m.getRpcs()){
-                if (method.getName().equals(BindingMapping.getMethodName(rpcDef.getQName()))){
-
-                    String moduleName = BindingReflections.getModuleInfo(method.getDeclaringClass()).getName();
-                    String rpcMethodName = rpcDef.getQName().getLocalName();
-
-                    WebResource resource = client.resource(defaultUri.toString() + ResourceUri.OPERATIONS.getPath() + "/"+ moduleName+":"+rpcMethodName);
-
-                    final ClientResponse response = resource.accept(ResourceMediaTypes.XML.getMediaType())
-                            .post(ClientResponse.class);
-
-
-                    if (response.getStatus() != 200) {
-                        throw new IllegalStateException("Can't get data from restconf. "+response.getClientResponseStatus());
-                    }
-                    return XmlTools.unmarshallXml(method.getReturnType(), response.getEntityInputStream());
+    public Object invoke(Object o,final Method method, Object[] objects) throws Throwable {
+        for (RpcDefinition rpcDef:module.getRpcs()){
+            if (method.getName().equals(BindingMapping.getMethodName(rpcDef.getQName()))){
+
+                String moduleName = BindingReflections.getModuleInfo(method.getDeclaringClass()).getName();
+                String rpcMethodName = rpcDef.getQName().getLocalName();
+                Document rpcInputDoc = null;
+                for (Object component:objects){
+                    CompositeNode rpcInput = mappingService.toDataDom((DataObject) component);
+                    rpcInputDoc = XmlDocumentUtils.toDocument(rpcInput,rpcDef.getInput(),XmlDocumentUtils.defaultValueCodecProvider());
                 }
+                DOMImplementationLS lsImpl = (DOMImplementationLS)rpcInputDoc.getImplementation().getFeature("LS", "3.0");
+                LSSerializer serializer = lsImpl.createLSSerializer();
+                serializer.getDomConfig().setParameter("xml-declaration", false);
+
+                String payloadString = serializer.writeToString(rpcInputDoc);
+                final Class<? extends DataContainer> desiredOutputClass = (Class<? extends DataContainer>)BindingReflections.resolveRpcOutputClass(method).get();
+                final DataSchemaNode rpcOutputSchema = rpcDef.getOutput();
+                return client.post(ResourceUri.OPERATIONS.getPath() + "/" + moduleName + ":" + rpcMethodName,payloadString,new Function<ClientResponse, Object>() {
+                    @Override
+                    public Object apply(ClientResponse clientResponse) {
+                        if (clientResponse.getStatus() != 200) {
+                            throw new IllegalStateException("Can't get data from restconf. "+clientResponse.getClientResponseStatus());
+                        }
+                        List<RpcError> errors =  new ArrayList<>();
+                        try {
+                            Document rpcOutputDocument = XmlTools.fromXml(clientResponse.getEntityInputStream());
+                            CompositeNode cn = (CompositeNode) XmlDocumentUtils.toDomNode(rpcOutputDocument.getDocumentElement(),
+                                    Optional.of(rpcOutputSchema),
+                                    Optional.of(XmlDocumentUtils.defaultValueCodecProvider()));
+                            DataContainer rpcOutputDataObject = mappingService.dataObjectFromDataDom(desiredOutputClass, cn);
+                            return new RestRpcResult(true,rpcOutputDataObject);
+                        } catch (Exception e) {
+                            logger.trace("Error while extracting rpc output in proxy method {}",e);
+                            RestRpcError error = new RestRpcError(RpcError.ErrorSeverity.ERROR, RpcError.ErrorType.APPLICATION,"Error while extracting rpc output in proxy method.",e);
+                        }
+                        return new RestRpcResult(false,errors);
+                    }
+                });
             }
         }
-        return null;
+        throw new IllegalStateException("Unexpected state of proxy method.");
     }
 
-    public static<T> T getProxy(Class<T> intf,
-                                URI uri) {
-            Object obj = (T) Proxy.newProxyInstance
+    public static<T> T getProxy(Class<T> proxiedInterface,
+                                BindingIndependentMappingService mappingService,
+                                RestconfClientImpl restconfClient,
+                                SchemaContext schemaContext) {
+        T proxiedType = null;
+        try {
+            proxiedType = (T) Proxy.newProxyInstance
                     (BindingToRestRpc.class.getClassLoader(),
-                            new Class[]{intf}, new BindingToRestRpc(uri));
+                            new Class[]{proxiedInterface}, new BindingToRestRpc(proxiedInterface, mappingService, restconfClient, schemaContext));
+        } catch (Exception e) {
+            throw new IllegalStateException(e.getMessage());
+        }
 
-            return (T) obj;
+        return proxiedType;
     }
 
 
index dc20006cbdbc132a0f5acafbb2bbfa207854ed97..9221bb331302bc95f67354bb3bdcd3e36b328179 100644 (file)
@@ -7,17 +7,21 @@
  */
 package org.opendaylight.yangtools.restconf.client;
 
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.sun.jersey.api.client.ClientResponse;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.concurrent.Callable;
 import java.util.concurrent.Executors;
-
+import javax.ws.rs.core.MediaType;
 import org.opendaylight.yangtools.restconf.client.api.data.ConfigurationDatastore;
 import org.opendaylight.yangtools.restconf.client.to.RestRpcError;
 import org.opendaylight.yangtools.restconf.client.to.RestRpcResult;
-import org.opendaylight.yangtools.restconf.common.ResourceMediaTypes;
 import org.opendaylight.yangtools.restconf.common.ResourceUri;
 import org.opendaylight.yangtools.restconf.utils.RestconfUtils;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -56,28 +60,22 @@ public class ConfigurationDataStoreImpl extends AbstractDataStore implements Con
         final BindingIndependentMappingService mappingService = getClient().getMappingService();
         final Map.Entry<String, DataSchemaNode> pathWithSchema = RestconfUtils.toRestconfIdentifier(path, mappingService, schemaContext);
         final String restconfPath = getStorePrefix() + pathWithSchema.getKey();
-
-        ListenableFuture<RpcResult<Boolean>> future = pool.submit(new Callable<RpcResult<Boolean>>() {
+        return getClient().delete(restconfPath,MediaType.APPLICATION_XML,new Function<ClientResponse, RpcResult<Boolean>>() {
             @Override
-            public RpcResult<Boolean> call() throws Exception {
+            public RpcResult<Boolean> apply(ClientResponse clientResponse) {
                 Entry<String, DataSchemaNode> restconfEntry = RestconfUtils.toRestconfIdentifier(mappingService.toDataDom(path), schemaContext);
-                WebResource resource = getClient().getRestClient().resource(getClient().constructPath(restconfPath));
-                final ClientResponse response = resource.accept(ResourceMediaTypes.XML.getMediaType())
-                        .delete(ClientResponse.class);
-
-                if (response.getStatus() != 200) {
-                    RpcError rpcError = new RestRpcError(RpcError.ErrorSeverity.ERROR,RpcError.ErrorType.RPC,null,null,"HTTP status "+response.getStatus(),null,null);
+                if (clientResponse.getStatus() != 200) {
+                    RpcError rpcError = new RestRpcError(RpcError.ErrorSeverity.ERROR,RpcError.ErrorType.RPC,null,null,"HTTP status "+clientResponse.getStatus(),null,null);
                     Collection<RpcError> errors = new ArrayList<RpcError>();
                     errors.add(rpcError);
                     RestRpcResult rpcResult = new RestRpcResult(false,null,errors);
                     return (RpcResult<Boolean>) Optional.of(rpcResult);
                 }
-                DataObject dataObject = RestconfUtils.dataObjectFromInputStream(path, response.getEntityInputStream(), schemaContext, mappingService,restconfEntry.getValue());
+                DataObject dataObject = RestconfUtils.dataObjectFromInputStream(path, clientResponse.getEntityInputStream(), schemaContext, mappingService,restconfEntry.getValue());
                 RestRpcResult rpcResult = new RestRpcResult(true,dataObject,null);
                 return (RpcResult<Boolean>) Optional.of(rpcResult);
             }
         });
-        return future;
     }
 
     @Override
@@ -87,26 +85,21 @@ public class ConfigurationDataStoreImpl extends AbstractDataStore implements Con
         final Map.Entry<String, DataSchemaNode> pathWithSchema = RestconfUtils.toRestconfIdentifier(path, mappingService, schemaContext);
         final String restconfPath = getStorePrefix() + pathWithSchema.getKey();
 
-        ListenableFuture<RpcResult<Boolean>> future = pool.submit(new Callable<RpcResult<Boolean>>() {
+        return getClient().put(restconfPath,MediaType.APPLICATION_XML,new Function<ClientResponse, RpcResult<Boolean>>() {
             @Override
-            public RpcResult<Boolean> call() throws Exception {
+            public RpcResult<Boolean> apply(ClientResponse clientResponse) {
                 Map.Entry<String, DataSchemaNode> restconfEntry = RestconfUtils.toRestconfIdentifier(mappingService.toDataDom(path), schemaContext);
-                WebResource resource = getClient().getRestClient().resource(getClient().constructPath(restconfPath));
-                final ClientResponse response = resource.accept(ResourceMediaTypes.XML.getMediaType())
-                        .put(ClientResponse.class);
-
-                if (response.getStatus() != 200) {
-                    RpcError rpcError = new RestRpcError(RpcError.ErrorSeverity.ERROR,RpcError.ErrorType.RPC,null,null,"HTTP status "+response.getStatus(),null,null);
+                if (clientResponse.getStatus() != 200) {
+                    RpcError rpcError = new RestRpcError(RpcError.ErrorSeverity.ERROR,RpcError.ErrorType.RPC,null,null,"HTTP status "+clientResponse.getStatus(),null,null);
                     Collection<RpcError> errors = new ArrayList<RpcError>();
                     errors.add(rpcError);
                     RestRpcResult rpcResult = new RestRpcResult(false,null,errors);
                     return (RpcResult<Boolean>) Optional.of(rpcResult);
                 }
-                DataObject dataObject = RestconfUtils.dataObjectFromInputStream(path, response.getEntityInputStream(),schemaContext,mappingService,restconfEntry.getValue());
+                DataObject dataObject = RestconfUtils.dataObjectFromInputStream(path, clientResponse.getEntityInputStream(),schemaContext,mappingService,restconfEntry.getValue());
                 RestRpcResult rpcResult = new RestRpcResult(true,dataObject);
                 return (RpcResult<Boolean>) Optional.of(rpcResult);
             }
         });
-        return future;
     }
 }
@@ -5,18 +5,15 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.yangtools.restconf.client.to;
+package org.opendaylight.yangtools.restconf.client;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
-import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.api.client.config.ClientConfig;
-import com.sun.jersey.api.client.config.DefaultClientConfig;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.InvocationTargetException;
@@ -25,13 +22,15 @@ import java.net.URI;
 import java.net.URLEncoder;
 import java.util.Date;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import javax.ws.rs.core.MediaType;
-import javax.xml.bind.annotation.XmlRootElement;
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo;
 import org.opendaylight.yangtools.restconf.client.api.event.EventStreamReplay;
 import org.opendaylight.yangtools.restconf.client.api.event.ListenableEventStreamContext;
+import org.opendaylight.yangtools.restconf.client.to.RestRpcResult;
 import org.opendaylight.yangtools.restconf.common.ResourceUri;
 import org.opendaylight.yangtools.websocket.client.WebSocketIClient;
 import org.opendaylight.yangtools.websocket.client.callback.ClientMessageCallback;
@@ -43,25 +42,19 @@ import org.slf4j.LoggerFactory;
 
 
 
-@XmlRootElement
-public class RestListenableEventStreamContext<L extends NotificationListener> implements ListenableEventStreamContext,ClientMessageCallback {
 
-    private final URI defaultUri;
-    private final Client client;
+public class RestListenableEventStreamContext<L extends NotificationListener> implements ListenableEventStreamContext,ClientMessageCallback {
 
     private static final Logger logger = LoggerFactory.getLogger(RestListenableEventStreamContext.class.toString());
     private final ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
-
-    private URI websocketServerUri;
     private WebSocketIClient wsClient;
-    private String streamName;
-
     private Method listenerCallbackMethod;
+    private final RestconfClientImpl restconfClient;
+    private final EventStreamInfo streamInfo;
 
-    public RestListenableEventStreamContext(URI uri){
-        this.defaultUri = uri;
-        ClientConfig config = new DefaultClientConfig();
-        client  = Client.create(config);
+    public RestListenableEventStreamContext(EventStreamInfo streamInfo,RestconfClientImpl restconfClient){
+        this.restconfClient = restconfClient;
+        this.streamInfo = streamInfo;
     }
     @Override
     public <L extends NotificationListener> ListenerRegistration<L> registerNotificationListener(L listener) {
@@ -84,7 +77,19 @@ public class RestListenableEventStreamContext<L extends NotificationListener> im
     public ListenableFuture<RpcResult<Void>> startListening() {
 
 
-        ClientResponse response = extractWebSocketUriFromRpc(this.streamName);
+        ClientResponse response = null;
+        try {
+            response = extractWebSocketUriFromRpc(this.streamInfo.getIdentifier());
+        } catch (ExecutionException e) {
+            logger.trace("Execution exception while extracting stream name {}",e);
+            throw new IllegalStateException(e);
+        } catch (InterruptedException e) {
+            logger.trace("InterruptedException while extracting stream name {}",e);
+            throw new IllegalStateException(e);
+        } catch (UnsupportedEncodingException e) {
+            logger.trace("UnsupportedEncodingException while extracting stream name {}",e);
+            throw new IllegalStateException(e);
+        }
         boolean success = true;
         if (response.getStatus() != 200) {
             success = false;
@@ -111,7 +116,7 @@ public class RestListenableEventStreamContext<L extends NotificationListener> im
 
     @Override
     public void stopListening() {
-        this.wsClient.writeAndFlush(new CloseWebSocketFrame(42,this.streamName));
+        this.wsClient.writeAndFlush(new CloseWebSocketFrame(42,this.streamInfo.getIdentifier()));
     }
 
     @Override
@@ -125,27 +130,24 @@ public class RestListenableEventStreamContext<L extends NotificationListener> im
         this.stopListening();
     }
 
-    private ClientResponse extractWebSocketUriFromRpc(String streamName){
-        String uri = null;
-        try {
-            uri = this.createUri(defaultUri+"/streams/stream/", streamName);
-        } catch (UnsupportedEncodingException e) {
-            logger.trace("Unsupported encoding.");
-        }
-
-        WebResource resource = client.resource(defaultUri.toString() + ResourceUri.STREAMS.getPath());
-        final ClientResponse response = resource.accept(MediaType.APPLICATION_XML)
-                .get(ClientResponse.class);
+    private ClientResponse extractWebSocketUriFromRpc(String methodName) throws ExecutionException, InterruptedException, UnsupportedEncodingException {
+        ListenableFuture<ClientResponse> clientFuture = restconfClient.get(ResourceUri.STREAM.getPath()+"/"+encodeUri(this.streamInfo.getIdentifier()),MediaType.APPLICATION_XML,new Function<ClientResponse, ClientResponse>(){
 
-        this.websocketServerUri = response.getLocation();
-        return response;
+            @Override
+            public ClientResponse apply(ClientResponse clientResponse) {
+                return clientResponse;
+            }
+        });
+        while (!clientFuture.isDone()){
+            //noop
+        }
+        return clientFuture.get();
     }
     private void createWebsocketClient(URI websocketServerUri){
         this.wsClient = new WebSocketIClient(websocketServerUri,this);
     }
-
-    private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
-        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
+    private String encodeUri(String encodedPart) throws UnsupportedEncodingException {
+        return URI.create(URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
     }
 
     @Override
@@ -161,4 +163,5 @@ public class RestListenableEventStreamContext<L extends NotificationListener> im
             throw new IllegalStateException(e.getMessage());
         }
     }
+
 }
index 9f3f2e3f401c30c8608cbc8007565adfc7dffb68..dab7f9b197192abb00874736230c7160d0c0c52f 100644 (file)
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executors;
+import javax.ws.rs.core.MediaType;
 import org.opendaylight.yangtools.restconf.client.api.RestconfClientContext;
 import org.opendaylight.yangtools.restconf.client.api.auth.AuthenticationHolder;
 import org.opendaylight.yangtools.restconf.client.api.data.ConfigurationDatastore;
@@ -36,7 +37,6 @@ import org.opendaylight.yangtools.restconf.client.api.dto.RestModule;
 import org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo;
 import org.opendaylight.yangtools.restconf.client.api.event.ListenableEventStreamContext;
 import org.opendaylight.yangtools.restconf.client.api.rpc.RpcServiceContext;
-import org.opendaylight.yangtools.restconf.client.to.RestListenableEventStreamContext;
 import org.opendaylight.yangtools.restconf.client.to.RestRpcServiceContext;
 import org.opendaylight.yangtools.restconf.common.ResourceMediaTypes;
 import org.opendaylight.yangtools.restconf.common.ResourceUri;
@@ -73,7 +73,7 @@ public class RestconfClientImpl implements RestconfClientContext, SchemaContextL
         Preconditions.checkArgument(mappingService != null, "Mapping service must not be null.");
         Preconditions.checkNotNull(schemaContextHolder, "Schema Context Holder must not be null.");
         ClientConfig config = new DefaultClientConfig();
-        restClient  = Client.create(config);
+        this.restClient  = Client.create(config);
         URI uri = null;
         try {
             uri = url.toURI();
@@ -103,62 +103,56 @@ public class RestconfClientImpl implements RestconfClientContext, SchemaContextL
 
     @Override
     public ListenableFuture<Set<Class<? extends RpcService>>> getRpcServices() {
-        ListenableFuture<Set<Class<? extends RpcService>>> future = pool.submit(new Callable<Set<Class<? extends RpcService>>>() {
+        return get(ResourceUri.MODULES.getPath(), ResourceMediaTypes.XML.getMediaType(),new Function<ClientResponse, Set<Class<? extends RpcService>>>() {
             @Override
-            public Set<Class<? extends RpcService>> call() throws Exception {
-                WebResource resource = restClient.resource(defaultUri.toString() + ResourceUri.MODULES.getPath());
-                final ClientResponse response = resource.accept(ResourceMediaTypes.XML.getMediaType())
-                        .get(ClientResponse.class);
-                if (response.getStatus() != 200) {
+            public Set<Class<? extends RpcService>> apply(ClientResponse clientResponse) {
+                if (clientResponse.getStatus() != 200) {
                     throw new RuntimeException("Failed : HTTP error code : "
-                            + response.getStatus());
+                            + clientResponse.getStatus());
                 }
-
-                return RestconfUtils.rpcServicesFromInputStream(response.getEntityInputStream(),mappingService,schemaContextHolder.getSchemaContext());
+                return RestconfUtils.rpcServicesFromInputStream(clientResponse.getEntityInputStream(),mappingService,schemaContextHolder.getSchemaContext());
             }
         });
-        return future;
     }
 
     @Override
     public <T extends RpcService> RpcServiceContext<T> getRpcServiceContext(Class<T> rpcService) {
-        RestRpcServiceContext restRpcServiceContext = new RestRpcServiceContext(rpcService,this.defaultUri);
+        RestRpcServiceContext restRpcServiceContext = new RestRpcServiceContext(rpcService,this.mappingService,this,schemaContextHolder.getSchemaContext());
         return restRpcServiceContext;
     }
 
     @Override
     public ListenableFuture<Set<EventStreamInfo>> getAvailableEventStreams() {
-        ListenableFuture<Set<org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo>> future = pool.submit(new Callable<Set<org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo>>() {
+        return get(ResourceUri.MODULES.getPath(), ResourceMediaTypes.XML.getMediaType(),new Function<ClientResponse, Set<EventStreamInfo>>() {
             @Override
-            public Set<org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo> call() throws Exception {
-                // when restconf will support discovery by /restconf/streams change ResourceUri.MODULES to ResourceUri.STREAMS
-                WebResource resource = restClient.resource(defaultUri.toString() + ResourceUri.MODULES.getPath());
-                final ClientResponse response = resource.accept(ResourceMediaTypes.XML.getMediaType())
-                        .get(ClientResponse.class);
-
-                if (response.getStatus() != 200) {
+            public Set<EventStreamInfo> apply(ClientResponse clientResponse) {
+                if (clientResponse.getStatus() != 200) {
                     throw new RuntimeException("Failed : HTTP error code : "
-                            + response.getStatus());
+                            + clientResponse.getStatus());
+                }
+                List<RestModule> modules = null;
+                try {
+                    modules = XmlTools.getModulesFromInputStream(clientResponse.getEntityInputStream());
+                } catch (Exception e) {
+                    logger.trace("");
                 }
-                List<RestModule> modules = XmlTools.getModulesFromInputStream(response.getEntityInputStream());
                 // when restconf will support discovery by /restconf/streams use this  instead of next iteration
                 //return XmlTools.evenStreamsFromInputStream(response.getEntityInputStream());
                 Set<EventStreamInfo> evtStreamInfos = new HashSet<EventStreamInfo>();
                 for (RestModule module:modules){
                     RestEventStreamInfo esi = new RestEventStreamInfo();
-                    esi.setIdentifier(module.getName());
-                    esi.setDescription(module.getNamespace()+" "+module.getRevision());
+                    esi.setIdentifier(module.getName()+":"+module.getName());
+                    esi.setDescription(module.getNamespace());
                     evtStreamInfos.add(esi);
                 }
                 return evtStreamInfos;
             }
         });
-        return future;
     }
 
     @Override
     public ListenableEventStreamContext getEventStreamContext(EventStreamInfo info) {
-        RestListenableEventStreamContext listenableEventStream = new RestListenableEventStreamContext(defaultUri);
+        RestListenableEventStreamContext listenableEventStream = new RestListenableEventStreamContext(info,this);
         return listenableEventStream;
     }
 
@@ -198,56 +192,109 @@ public class RestconfClientImpl implements RestconfClientContext, SchemaContextL
 
     }
 
-    protected Client getRestClient() {
-        return restClient;
-    }
-
     public SchemaContext getSchemaContext() {
         return this.schemaContextHolder.getSchemaContext();
     }
 
     protected <T> ListenableFuture<T> get(final String path, final Function<ClientResponse, T> processingFunction) {
-        return pool.submit(new GetAndTransformTask<T>(constructPath(path),processingFunction));
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path), RestOperation.GET, processingFunction));
     }
 
     protected <T> ListenableFuture<T> get(final String path,final String mediaType, final Function<ClientResponse, T> processingFunction) {
-        return pool.submit(new GetAndTransformTask<T>(constructPath(path),mediaType,processingFunction));
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),mediaType,RestOperation.GET,processingFunction));
+    }
+
+    protected <T> ListenableFuture<T> post(final String path, String payload, final Function<ClientResponse, T> processingFunction) {
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),payload,RestOperation.POST,processingFunction));
+    }
+
+    protected <T> ListenableFuture<T> post(final String path,String payload,final String mediaType, final Function<ClientResponse, T> processingFunction) {
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),payload,RestOperation.POST,mediaType,processingFunction));
+    }
+
+    protected <T> ListenableFuture<T> put(final String path, String payload, final Function<ClientResponse, T> processingFunction) {
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),RestOperation.PUT,payload,processingFunction));
+    }
+
+    protected <T> ListenableFuture<T> put(final String path,String payload,final String mediaType, final Function<ClientResponse, T> processingFunction) {
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),payload,RestOperation.PUT,mediaType,processingFunction));
+    }
+    protected <T> ListenableFuture<T> delete(final String path, final Function<ClientResponse, T> processingFunction) {
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),RestOperation.DELETE,processingFunction));
+    }
+
+    protected <T> ListenableFuture<T> delete(final String path,final String mediaType, final Function<ClientResponse, T> processingFunction) {
+        return pool.submit(new ExecuteOperationAndTransformTask<T>(constructPath(path),RestOperation.DELETE,mediaType,processingFunction));
     }
 
     protected String constructPath(String path) {
         return getDefaultUri().toString() + path;
     }
 
-    //, RestRestconfService {
-
-    private class GetAndTransformTask<T> implements Callable<T> {
+    private enum RestOperation{
+        PUT,POST,GET,DELETE;
+    }
 
+    private class ExecuteOperationAndTransformTask<T> implements Callable<T> {
         private final Function<ClientResponse, T> transformation;
         private final String path;
         private final String acceptType;
+        private final String payload;
+        private final RestOperation restOperation;
 
-        public GetAndTransformTask(String path, Function<ClientResponse, T> processingFunction) {
+        public ExecuteOperationAndTransformTask(String path, String payload, RestOperation operation, Function<ClientResponse, T> processingFunction) {
             this.path = path;
             this.transformation = processingFunction;
-            this.acceptType = ResourceMediaTypes.XML.getMediaType();
+            this.acceptType = MediaType.APPLICATION_XML; //ResourceMediaTypes.XML.getMediaType();
+            this.payload = payload;
+            this.restOperation = operation;
         }
 
-        public GetAndTransformTask(String path, String mediaType, Function<ClientResponse, T> processingFunction) {
+        public ExecuteOperationAndTransformTask(String path,String payload, RestOperation operation,String mediaType, Function<ClientResponse, T> processingFunction) {
+            this.path = path;
+            this.transformation = processingFunction;
+            this.acceptType = mediaType;
+            this.payload = payload;
+            this.restOperation = operation;
+        }
+        public ExecuteOperationAndTransformTask(String path, RestOperation operation,String mediaType, Function<ClientResponse, T> processingFunction) {
             this.path = path;
             this.transformation = processingFunction;
             this.acceptType = mediaType;
+            this.payload = null;
+            this.restOperation = operation;
+        }
+        public ExecuteOperationAndTransformTask(String path, RestOperation operation, Function<ClientResponse, T> processingFunction) {
+            this.path = path;
+            this.transformation = processingFunction;
+            this.acceptType =  MediaType.APPLICATION_XML;
+            this.payload = null;
+            this.restOperation = operation;
         }
 
         @Override
         public T call() {
+            ClientResponse response = null;
+            try {
+                WebResource resource = restClient.resource(path);
+                switch (restOperation){
+                    case PUT: response = resource.type(MediaType.APPLICATION_XML).accept(acceptType).put(ClientResponse.class, payload);
+                        break;
+                    case POST : response = resource.type(MediaType.APPLICATION_XML).accept(acceptType).post(ClientResponse.class, payload);
+                         break;
+                    case GET: response = resource.type(MediaType.APPLICATION_XML).accept(acceptType).get(ClientResponse.class);
+                        break;
+                    case DELETE: response = resource.type(MediaType.APPLICATION_XML).accept(acceptType).delete(ClientResponse.class);
+                        break;
+                }
+
+            } catch (Exception e){
+                logger.trace("Exception occured while posting data to client {}",e);
+            }
 
-            WebResource resource = restClient.resource(path);
-            ClientResponse response = resource.accept(acceptType).get(ClientResponse.class);
 
-            // Applies the specific transformation for supplied resource.
             return transformation.apply(response);
         }
-
     }
 
 }
index 925e770ed17288822d2c4332a339770d86a32935..da285e3b041c61971e264199a308716cc7b0dc23 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.yangtools.restconf.client.to;
 
-import java.net.URI;
 import org.opendaylight.yangtools.restconf.client.BindingToRestRpc;
+import org.opendaylight.yangtools.restconf.client.RestconfClientImpl;
 import org.opendaylight.yangtools.restconf.client.api.rpc.RpcServiceContext;
 import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -19,8 +21,9 @@ public class RestRpcServiceContext <T extends RpcService> implements RpcServiceC
     private static final Logger logger = LoggerFactory.getLogger(RestRpcServiceContext.class);
     private T rpcServiceProxy;
 
-    public RestRpcServiceContext(Class<T> rpcService,URI uri){
-        this.rpcServiceProxy = BindingToRestRpc.getProxy(rpcService,uri);
+    public RestRpcServiceContext(Class<T> rpcService,BindingIndependentMappingService mappingService, RestconfClientImpl
+            restconfClient,SchemaContext schemaContext){
+        this.rpcServiceProxy = BindingToRestRpc.getProxy(rpcService,mappingService,restconfClient,schemaContext);
     }
 
     @Override
index 40eecee99535f760d27624d30038018b7ee33d2e..3fedc963492b255cfd1d24731ce9963a7865967d 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.yangtools.restconf.common;
 public enum ResourceMediaTypes {
 
     XML("application/yang.api+xml"),
-    JSON("application/yang.api+json");
+    JSON("application/yang.api+json"),
+    TEXT_EVT("text/event-stream");
 
     private final String mediaType;
 
index 503cc774157a2884d6e3a83192a028dcc2a8dd1a..830957179d2ce67392dea9c6caba7bad9178e79d 100644 (file)
           <groupId>commons-io</groupId>
           <artifactId>commons-io</artifactId>
       </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.model</groupId>
-            <artifactId>ietf-topology-isis</artifactId>
-            <version>2013.10.21.2-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
+      <dependency>
+          <groupId>xml-apis</groupId>
+          <artifactId>xml-apis</artifactId>
+          <version>2.0.2</version>
+      </dependency>
+      <dependency>
+          <groupId>junit</groupId>
+          <artifactId>junit</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools.model</groupId>
+          <artifactId>ietf-topology-isis</artifactId>
+          <version>2013.10.21.2-SNAPSHOT</version>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
 </project>
index ecbd5cfb4f10ec0ad7ed3d3895c29e644b50e61d..9d74db971ff655eb43576d8dfa9b8705956c0116 100644 (file)
@@ -13,14 +13,16 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.datatype.DatatypeFactory;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.stream.StreamSource;
 import org.opendaylight.yangtools.restconf.client.api.dto.RestEventStreamInfo;
+import org.opendaylight.yangtools.restconf.client.api.dto.RestModule;
 import org.opendaylight.yangtools.restconf.client.api.dto.RestRpcService;
 import org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo;
-import org.opendaylight.yangtools.restconf.client.api.dto.RestModule;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,24 +34,26 @@ import org.w3c.dom.NodeList;
 public class XmlTools {
 
     private static final Logger logger = LoggerFactory.getLogger(XmlTools.class.toString());
+    static final String JAXP_SCHEMA_LOCATION =
+            "http://java.sun.com/xml/jaxp/properties/schemaSource";
 
-
-    public static Object unmarshallXml(Class<?> clazz,InputStream xmlStream) throws Exception{
+    public static Object unmarshallXml(Class<?> clazz,InputStream xmlStream,String namespace) throws Exception{
         if (null == xmlStream){
             throw new Exception("XML input stream can't be null");
         }
-        JAXBContext jc = null;
-        jc = JAXBContext.newInstance(clazz);
+        JAXBContext jc = JAXBContext.newInstance(clazz);
 
-        Unmarshaller unmarshaller = null;
-        Object o = null;
-        unmarshaller = jc.createUnmarshaller();
-        return unmarshaller.unmarshal(xmlStream);
+        Unmarshaller unmarshaller = jc.createUnmarshaller();
+        StreamSource xmlInputSource = new StreamSource(xmlStream);
+        JAXBElement<?> obj = unmarshaller.unmarshal(xmlInputSource, clazz);
+        return obj;
     }
 
     public static Document fromXml(InputStream is) throws Exception {
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+        dbFactory.setNamespaceAware(true);
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+
         Document doc = dBuilder.parse(is);
         doc.getDocumentElement().normalize();
         return doc;
index 54eb954a6b57579c95ec942f2bc4aa774dfdc080..9091b211d116444797df3a3f1a97fbd614d7052a 100644 (file)
@@ -48,7 +48,7 @@ public class WebSocketIClient  {
     private void initialize(){
 
         String protocol = uri.getScheme();
-        if (!"ws".equals(protocol)) {
+        if (!"ws".equals(protocol) && !"http".equals(protocol)) {
             throw new IllegalArgumentException("Unsupported protocol: " + protocol);
         }