--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2018 Politecnico di Torino and others.\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Apache License, Version 2.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *******************************************************************************/\r
+\r
+package it.polito.verigraph.tosca;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.StringReader;\r
+import java.io.StringWriter;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.NoSuchElementException;\r
+import java.util.Scanner;\r
+import java.util.regex.Pattern;\r
+\r
+import javax.ws.rs.ProcessingException;\r
+import javax.ws.rs.client.Client;\r
+import javax.ws.rs.client.ClientBuilder;\r
+import javax.ws.rs.client.Entity;\r
+import javax.ws.rs.client.Invocation.Builder;\r
+import javax.ws.rs.client.WebTarget;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import javax.xml.bind.JAXBContext;\r
+import javax.xml.bind.JAXBException;\r
+import javax.xml.bind.Marshaller;\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Source;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.stream.StreamResult;\r
+import javax.xml.transform.stream.StreamSource;\r
+\r
+import com.fasterxml.jackson.annotation.JsonInclude;\r
+import com.fasterxml.jackson.core.JsonProcessingException;\r
+import com.fasterxml.jackson.databind.ObjectMapper;\r
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;\r
+import com.sun.research.ws.wadl.ObjectFactory;\r
+\r
+import it.polito.tosca.jaxb.Configuration;\r
+import it.polito.tosca.jaxb.Definitions;\r
+import it.polito.tosca.jaxb.TDefinitions;\r
+import it.polito.verigraph.grpc.GraphGrpc;\r
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;\r
+import it.polito.verigraph.grpc.ToscaPolicy;\r
+import it.polito.verigraph.grpc.client.ToscaClient;\r
+import it.polito.verigraph.grpc.server.GrpcUtils;\r
+import it.polito.verigraph.model.Graph;\r
+import it.polito.verigraph.tosca.converter.grpc.GraphToGrpc;\r
+import it.polito.verigraph.tosca.converter.grpc.GrpcToGraph;\r
+import it.polito.verigraph.tosca.converter.grpc.GrpcToXml;\r
+import it.polito.verigraph.tosca.converter.grpc.GrpcToYaml;\r
+import it.polito.verigraph.tosca.converter.grpc.XmlToGrpc;\r
+import it.polito.verigraph.tosca.converter.grpc.YamlToGrpc;\r
+import it.polito.verigraph.tosca.yaml.beans.ServiceTemplateYaml;\r
+\r
+\r
+public class ToscaCLI {\r
+\r
+ private static final String helper = "./README_CLI.txt";\r
+\r
+ //Service parameters.\r
+ private String host;\r
+ private int port;\r
+\r
+ //New media type for yaml rest request\r
+ private static final MediaType yamlMedia = new MediaType("application", "x-yaml");\r
+ private static final String defaultHost = "localhost";\r
+ private static final int defaultRestPort = 8080;\r
+ private static final int defaultGrpcPort = 50051;\r
+\r
+ //Input validation patterns\r
+ private static final Pattern yamlSource = Pattern.compile(".*\\.yaml$");\r
+ private static final Pattern xmlSource = Pattern.compile(".*\\.xml");\r
+ private static final Pattern jsonSource = Pattern.compile(".*\\.json$");\r
+ private static final Pattern configOpt = Pattern.compile("-use|-format|-port|-host", Pattern.CASE_INSENSITIVE);\r
+ private static final Pattern useOpt = Pattern.compile("grpc|rest", Pattern.CASE_INSENSITIVE);\r
+ private static final Pattern formatOpt = Pattern.compile("yaml|json|xml", Pattern.CASE_INSENSITIVE);\r
+ private static final Pattern policies = Pattern.compile("reachability|isolation|traversal", Pattern.CASE_INSENSITIVE);\r
+\r
+ //Configuration parameters\r
+ private Boolean useRest;\r
+ private String mediatype;\r
+ private Client restClient;\r
+ private ToscaClient grpcClient;\r
+\r
+ public ToscaCLI(){\r
+ //Variables representing the client environment\r
+ this.useRest = true;\r
+ this.port = defaultRestPort;\r
+ this.host = defaultHost;\r
+ this.mediatype = MediaType.APPLICATION_XML;\r
+ this.restClient = null;\r
+ this.grpcClient = null;\r
+ }\r
+\r
+\r
+ public static void main(String[] args) {\r
+ ToscaCLI myclient = new ToscaCLI();\r
+ try {\r
+ myclient.clientStart();\r
+ } catch (Exception e) {\r
+ System.out.println("-- Unexpected error, service closing.");\r
+ }\r
+ return;\r
+ }\r
+\r
+ //Build base Uri for REST service\r
+ private String buildBaseUri() {\r
+ return "http://" + this.host + ":" + String.valueOf(this.port) + "/verigraph/api/graphs";\r
+ }\r
+\r
+ //Function iterating getting user commands.\r
+ public void clientStart(){\r
+ System.out.println("++ Welcome to Verigraph Verification Service...");\r
+ System.out.println("++ Type HELP for instructions on client use...");\r
+\r
+ Scanner reader = null;\r
+ InputStream input = System.in;\r
+ Scanner scan = new Scanner(System.in);\r
+ String commandline;\r
+\r
+ while(true) {\r
+ System.out.print("++ Please insert command : ");\r
+ try{\r
+\r
+ while(input.available()!=0) input.skip(input.available());\r
+ commandline = scan.nextLine();\r
+ reader = new Scanner(commandline);\r
+\r
+ switch (reader.next().toUpperCase()) {\r
+ case "GETALL":\r
+ if(useRest) this.restGetAll(reader);\r
+ else this.grpcGetAll(reader);\r
+ break;\r
+ case "GET":\r
+ if(useRest) this.restGet(reader);\r
+ else this.grpcGet(reader);\r
+ break;\r
+ case "CREATE":\r
+ if(useRest) this.restCreate(reader);\r
+ else this.grpcCreate(reader);\r
+ break;\r
+ case "DELETE":\r
+ if(useRest) this.restDelete(reader);\r
+ else grpcDelete(reader);\r
+ break;\r
+ case "UPDATE":\r
+ if(useRest) this.restUpdate(reader);\r
+ else this.grpcUpdate(reader);\r
+ break;\r
+ case "VERIFY":\r
+ if(useRest) this.restVerify(reader);\r
+ else this.grpcVerify(reader);\r
+ break;\r
+ case "HELP":\r
+ this.printHelper();\r
+ break;\r
+ case "CONFIGURE":\r
+ this.setConfig(reader);\r
+ break;\r
+ case "EXIT":\r
+ System.out.println("++ Client closing...");\r
+ scan.close();\r
+ input.close();\r
+ reader.close();\r
+ if(grpcClient != null) this.grpcClient.shutdown();\r
+ if(restClient != null) this.restClient.close();\r
+ System.out.println("++ Goodbye!");\r
+ System.exit(0);\r
+ break;\r
+ default:\r
+ System.out.println("-- Unknown or bad formed command, type HELP to show commands documentation.");\r
+ break;\r
+ }\r
+\r
+ }catch(NoSuchElementException ex) {\r
+ System.err.println("-- Unrecognized or incorrect command,"\r
+ + " type help to know how to use the client...");\r
+ continue;\r
+ }catch(IOException | InterruptedException ex){\r
+ handleError(ex);\r
+ }finally {\r
+ reader.close();\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+\r
+ public void printHelper() {\r
+ Scanner filereader = null;\r
+ try {\r
+ File inputfile = new File(helper);\r
+ filereader = new Scanner(inputfile).useDelimiter("\\Z");\r
+ String content = filereader.next();\r
+ if (filereader.ioException() != null) {\r
+ throw new IOException(filereader.ioException());\r
+ }\r
+ if(content != null) System.out.println(content);\r
+ } catch (IOException e) {\r
+ handleError(e);\r
+ }finally {\r
+ if(filereader != null) filereader.close();\r
+ }\r
+\r
+ }\r
+\r
+ public void setConfig(Scanner reader) throws InterruptedException {\r
+ if(!reader.hasNext(configOpt)) {\r
+ System.out.println("-- No or bad formed configuration options provided.");\r
+ return;\r
+ }\r
+ while(reader.hasNext(configOpt)) {\r
+ switch(reader.next().toLowerCase()) {\r
+ case "-use":\r
+ if(reader.hasNext(useOpt)) {\r
+ if(reader.next().toLowerCase().equals("rest")) {\r
+ if(grpcClient != null) {\r
+ grpcClient.shutdown();\r
+ grpcClient = null;\r
+ }\r
+ this.port = defaultRestPort;\r
+ restClient = ClientBuilder.newClient();\r
+ useRest = true;\r
+ }\r
+ else {\r
+ if(restClient != null) {\r
+ restClient.close();\r
+ restClient = null;\r
+ }\r
+ this.port = defaultGrpcPort;\r
+ grpcClient = new ToscaClient(host, port);\r
+ useRest = false;\r
+ }\r
+ }else {\r
+ System.out.println("-- Unrecognized values for option -use, accepted values are: rest, grpc.");\r
+ }\r
+ break;\r
+ case "-format":\r
+ if(reader.hasNext(formatOpt)) {\r
+ String command = reader.next();\r
+ if(command.toLowerCase().equals("json")) mediatype = MediaType.APPLICATION_JSON;\r
+ else if(command.toLowerCase().equals("xml")) mediatype = MediaType.APPLICATION_XML;\r
+ else if(command.toLowerCase().equals("yaml")) mediatype = "application/x-yaml";\r
+ }else {\r
+ System.out.println("-- Unrecognized values for option -format, accepted formats are: json, xml, yaml.");\r
+ }\r
+ break;\r
+ case "-host":\r
+ if(reader.hasNext()) {\r
+ this.host = reader.next();\r
+ if(grpcClient != null) {\r
+ grpcClient.shutdown();\r
+ grpcClient = new ToscaClient(host, port);\r
+ System.out.println("++ Host configuration changed restarting grpc client...");\r
+ }\r
+ }\r
+ else {\r
+ System.out.println("-- Provide a valid hostname.");\r
+ }\r
+ break;\r
+ case "-port":\r
+ if(reader.hasNextInt()) {\r
+ int newvalue = reader.nextInt();\r
+ if(0 > newvalue || 65535 < newvalue) {\r
+ System.out.println("-- The provided port number is not valid, port has not been modified.");\r
+ }else {\r
+ this.port = newvalue;\r
+ if(grpcClient != null) {\r
+ grpcClient.shutdown();\r
+ grpcClient = new ToscaClient(host, port);\r
+ System.out.println("++ Port configuration changed restarting grpc client...");\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ System.out.println("-- Provide a port as an integer.");\r
+ }\r
+ break;\r
+ default:\r
+ System.out.println("-- Unrecognized option!");\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ //Utility function used only to print exception message\r
+ public void handleError(Exception e) {\r
+ String errMsg = e.getMessage();\r
+ if(errMsg == null) {\r
+ System.out.println("-- Error: unexpected error occurred.");\r
+ }else {\r
+ System.out.println("-- Error: " + errMsg);\r
+ }\r
+ return;\r
+ }\r
+\r
+\r
+ // RESTful service interface CRUD and Verify functions\r
+ public void restGetAll(Scanner reader) {\r
+ try {\r
+ // Build a new client if it does not exist\r
+ if (restClient == null)\r
+ restClient = ClientBuilder.newClient();\r
+\r
+ // targeting the graphs resource\r
+ WebTarget target = restClient.target(this.buildBaseUri());\r
+\r
+ // Performing the request and reading the response\r
+ Response res = target.request(mediatype).get();\r
+ this.readResponseRest("GETALL", res);\r
+\r
+ }catch(ProcessingException e) {\r
+ System.out.println("-- Error: the provided host address is not valid.");\r
+ }catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+ return;\r
+ }\r
+\r
+\r
+ public void restGet(Scanner reader) {\r
+\r
+ try {\r
+ // Build a new client if it does not exist\r
+ if (restClient == null)\r
+ restClient = ClientBuilder.newClient();\r
+\r
+ if (!reader.hasNextLong()) {\r
+ System.out.println("-- Provide the integer Id for the requested graph.");\r
+ return;\r
+ }\r
+\r
+ // Targeting the specified graph resource\r
+ WebTarget target = restClient.target(this.buildBaseUri() + "/" + String.valueOf(reader.nextLong()));\r
+\r
+ // Performing the request and reading the response\r
+ Response res = target.request(mediatype).get();\r
+ this.readResponseRest("GET", res);\r
+\r
+ }catch(ProcessingException e) {\r
+ System.out.println("-- Error: the provided host address is not valid.");\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ }\r
+\r
+\r
+\r
+ public void restCreate(Scanner reader) {\r
+\r
+ try {\r
+ // Getting file content\r
+ String content = readFile(reader);\r
+ if (content == null) {\r
+ System.out.println("-- The required operation can't be performed.");\r
+ return;\r
+ }\r
+\r
+ // Build a new client if it does not exist\r
+ if (restClient == null)\r
+ restClient = ClientBuilder.newClient();\r
+\r
+ // Targeting the resource\r
+ WebTarget target = restClient.target(this.buildBaseUri());\r
+\r
+ // Performing the request and reading the response\r
+ Builder mypost = target.request(mediatype);\r
+ Response res = null;\r
+ switch (mediatype) {\r
+ case MediaType.APPLICATION_JSON:\r
+ res = mypost.post(Entity.json(content));\r
+ break;\r
+ case MediaType.APPLICATION_XML:\r
+ res = mypost.post(Entity.xml(content));\r
+ break;\r
+ case "application/x-yaml":\r
+ res = mypost.post(Entity.entity(content, yamlMedia));\r
+ break;\r
+ }\r
+\r
+ this.readResponseRest("CREATE", res);\r
+ }catch(ProcessingException e) {\r
+ System.out.println("-- Error: the provided host address is not valid.");\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+\r
+\r
+ public void restDelete(Scanner reader) {\r
+ try {\r
+ // Build a new client if it does not exist\r
+ if (restClient == null)\r
+ restClient = ClientBuilder.newClient();\r
+\r
+ if (!reader.hasNextLong()) {\r
+ System.out.println("-- Provide the integer Id of the graph you want to delete.");\r
+ return;\r
+ }\r
+\r
+ // Targeting the specified graph resource\r
+ WebTarget target = restClient.target(this.buildBaseUri() + "/" + String.valueOf(reader.nextLong()));\r
+\r
+ // Performing the request and reading the response\r
+ Response res = target.request(mediatype).delete();\r
+ this.readResponseRest("DELETE", res);\r
+ }catch(ProcessingException e) {\r
+ System.out.println("-- Error: the provided host address is not valid.");\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+\r
+ public void restUpdate(Scanner reader) {\r
+ try {\r
+\r
+ //Getting the target graph\r
+ if(!reader.hasNextLong()) {\r
+ System.out.println("-- Please provide a valid id for the graph to be update");\r
+ return;\r
+ }\r
+\r
+ // Build a new client if it does not exist\r
+ if (restClient == null)\r
+ restClient = ClientBuilder.newClient();\r
+\r
+ // Targeting the resource\r
+ WebTarget target = restClient.target(this.buildBaseUri() + "/" + reader.next());\r
+\r
+ // Getting file content\r
+ String content = readFile(reader);\r
+ if (content == null) {\r
+ System.out.println("-- The required operation can't be performed.");\r
+ return;\r
+ }\r
+\r
+ // Performing the request and reading the resonse\r
+ Builder myupdate = target.request(mediatype);\r
+ Response res = null;\r
+ switch (mediatype) {\r
+ case MediaType.APPLICATION_JSON:\r
+ res = myupdate.put(Entity.json(content));\r
+ break;\r
+ case MediaType.APPLICATION_XML:\r
+ res = myupdate.put(Entity.xml(content));\r
+ break;\r
+ case "application/x-yaml":\r
+ res = myupdate.put(Entity.entity(content, yamlMedia));\r
+ break;\r
+ }\r
+\r
+ this.readResponseRest("UPDATE", res);\r
+\r
+ }catch(ProcessingException e) {\r
+ System.out.println("-- Error: the provided host address is not valid.");\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ }\r
+\r
+\r
+ public void restVerify(Scanner reader) {\r
+ String whichpolicy = null;\r
+ String graphId, source, destination, middlebox = null;\r
+\r
+ try {\r
+ if(!reader.hasNextLong()) {\r
+ System.out.println("-- Provide the graph on which you want to perform verification.");\r
+ return;\r
+ }\r
+ graphId = reader.next();\r
+\r
+ if (!reader.hasNext(policies)) {\r
+ System.out.println("-- Provide the requested type of verfication.");\r
+ return;\r
+ }\r
+ whichpolicy = reader.next().toLowerCase();\r
+\r
+ try {\r
+ source = reader.next();\r
+ destination = reader.next();\r
+ if(!whichpolicy.equals("reachability")) {\r
+ middlebox = reader.next();\r
+ }\r
+ }catch(NoSuchElementException ex) {\r
+ System.out.println("-- Wrong or missing verification parameters.");\r
+ return;\r
+ }\r
+\r
+ // Build a new client if it does not exist\r
+ if (restClient == null)\r
+ restClient = ClientBuilder.newClient();\r
+\r
+ // Targeting the resource\r
+ WebTarget target = restClient.target(this.buildBaseUri() + "/" + graphId + "/policy")\r
+ .queryParam("source", source)\r
+ .queryParam("destination", destination)\r
+ .queryParam("type", whichpolicy);\r
+ if(!whichpolicy.equals("reachability")) {\r
+ target = target.queryParam("middlebox", middlebox);\r
+ }\r
+\r
+ Response res = target.request(mediatype).get();\r
+ this.readResponseRest("VERIFY", res);\r
+ }catch(ProcessingException e) {\r
+ System.out.println("-- Error: the provided host address is not valid.");\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ }\r
+\r
+ //gRPC service interface CRUD and Verify functions\r
+ public void grpcGetAll(Scanner reader) {\r
+\r
+ try {\r
+ if(grpcClient == null)\r
+ grpcClient = new ToscaClient(host, port);\r
+\r
+ //Added for backward compatibility with JSON grpc\r
+ if(mediatype == MediaType.APPLICATION_JSON) {\r
+ List<GraphGrpc> receivedGraphsGrpc = grpcClient.getGraphs();\r
+\r
+ if(receivedGraphsGrpc == null) {\r
+ System.out.println("-- GET Failed : was not possible to perform the required operations.");\r
+ return;\r
+ }\r
+ else if(receivedGraphsGrpc.isEmpty()) {\r
+ System.out.println("++ GET Success no graph was returned.");\r
+ return;\r
+ }\r
+\r
+ List<Graph> receivedGraphs = new ArrayList<Graph>();\r
+ for(GraphGrpc curr : receivedGraphsGrpc) {\r
+ receivedGraphs.add(GrpcUtils.deriveGraph(curr));\r
+ }\r
+ this.marshallToJson(receivedGraphs);\r
+ return;\r
+ }\r
+\r
+ //Code for the Tosca compliant implementation\r
+ List<TopologyTemplateGrpc> templates;\r
+ templates = grpcClient.getTopologyTemplates();\r
+\r
+ if(templates == null) {\r
+ System.out.println("-- GET Failed : was not possible to perform the required operations.");\r
+ return;\r
+ }\r
+ else if(templates.isEmpty()) {\r
+ System.out.println("++ GET Success no graph was returned.");\r
+ return;\r
+ }\r
+\r
+ switch(mediatype) {\r
+ case MediaType.APPLICATION_XML:\r
+ List<Definitions> receivedDefs = new ArrayList<Definitions>();\r
+ for(TopologyTemplateGrpc curr : templates) {\r
+ receivedDefs.add(GrpcToXml.mapGraph(curr));\r
+ }\r
+ this.marshallToXml(receivedDefs);\r
+ break;\r
+\r
+ case "application/x-yaml":\r
+ List<ServiceTemplateYaml> receivedTempls = new ArrayList<ServiceTemplateYaml>();\r
+ for(TopologyTemplateGrpc curr : templates) {\r
+ receivedTempls.add(GrpcToYaml.mapGraphYaml(curr));\r
+ }\r
+ this.marshallToYaml(receivedTempls);\r
+ break;\r
+\r
+ }\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ }\r
+\r
+\r
+ public void grpcGet(Scanner reader) {\r
+\r
+ try {\r
+ if (grpcClient == null)\r
+ grpcClient = new ToscaClient(host, port);\r
+\r
+ if (!reader.hasNextLong()) {\r
+ System.out.println("-- Provide the integer Id for the requested graph.");\r
+ return;\r
+ }\r
+\r
+ //Added for backward compatibility with JSON grpc\r
+ if(mediatype == MediaType.APPLICATION_JSON) {\r
+ GraphGrpc graph = grpcClient.getGraph(reader.nextLong());\r
+ if(graph == null || !graph.getErrorMessage().equals(""));\r
+ List<Graph> receivedGraphs = new ArrayList<Graph>();\r
+ receivedGraphs.add(GrpcUtils.deriveGraph(graph));\r
+ this.marshallToJson(receivedGraphs);\r
+ return;\r
+ }\r
+\r
+ //Code for Tosca compliant implementation\r
+ TopologyTemplateGrpc templ = grpcClient.getTopologyTemplate(reader.next());\r
+ if(templ == null || !templ.getErrorMessage().equals("")) {\r
+ return;\r
+ }\r
+ switch(mediatype) {\r
+ // case MediaType.APPLICATION_JSON:\r
+ // Graph obt = GrpcToGraph.deriveGraph(templ);\r
+ // List<Graph> list = new ArrayList<Graph>();\r
+ // list.add(obt);\r
+ // marshallToJson(list);\r
+ // break;\r
+ case MediaType.APPLICATION_XML:\r
+ List<Definitions> receivedDefs = new ArrayList<Definitions>();\r
+ receivedDefs.add(GrpcToXml.mapGraph(templ));\r
+ this.marshallToXml(receivedDefs);\r
+ break;\r
+\r
+ case "application/x-yaml":\r
+ List<ServiceTemplateYaml> receivedTempls = new ArrayList<ServiceTemplateYaml>();\r
+ receivedTempls.add(GrpcToYaml.mapGraphYaml(templ));\r
+ this.marshallToYaml(receivedTempls);\r
+ break;\r
+ }\r
+\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+ }\r
+\r
+ public void grpcCreate(Scanner reader) {\r
+ try {\r
+ if (grpcClient == null)\r
+ grpcClient = new ToscaClient(host, port);\r
+\r
+ switch (mediatype) {\r
+ case MediaType.APPLICATION_JSON:\r
+ if(reader.hasNext(jsonSource)) {\r
+ ObjectMapper mapper = new ObjectMapper();\r
+ Graph modelGraph = mapper.readValue(readFile(reader), Graph.class);\r
+ GraphGrpc graph = GrpcUtils.obtainGraph(modelGraph);\r
+ grpcClient.createGraph(graph);\r
+ }else {\r
+ System.out.println("-- The provided file is not compatible with the current configuration [json].");\r
+ return;\r
+ }\r
+ break;\r
+ case MediaType.APPLICATION_XML:\r
+ if (reader.hasNext(xmlSource)) {\r
+ grpcClient.createTopologyTemplate(XmlToGrpc.obtainTopologyTemplateGrpc(reader.next()));\r
+ } else {\r
+ System.out.println("-- The provided file is not compatible with the current configuration [xml].");\r
+ return;\r
+ }\r
+ break;\r
+\r
+ case "application/x-yaml":\r
+ if (reader.hasNext(yamlSource)) {\r
+ grpcClient.createTopologyTemplate(YamlToGrpc.obtainTopologyTemplateGrpc(reader.next()));\r
+ } else {\r
+ System.out.println("-- The provided file is not compatible with the current configuration [yaml].");\r
+ return;\r
+ }\r
+ break;\r
+ }\r
+\r
+ } catch (JAXBException je) {\r
+ System.out.println("-- Error while parsing xml : " + je.getMessage());\r
+ } catch (IOException ie) {\r
+ System.out.println("-- Error reading the file : " + ie.getMessage());\r
+ } catch(Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+\r
+ public void grpcDelete(Scanner reader) {\r
+\r
+ try {\r
+ if (grpcClient == null)\r
+ grpcClient = new ToscaClient(host, port);\r
+\r
+ if (!reader.hasNextLong()) {\r
+ System.out.println("-- Provide the integer Id of the graph you want to delete.");\r
+ return;\r
+ }\r
+\r
+ grpcClient.deleteTopologyTemplate(reader.next());\r
+\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+\r
+ public void grpcUpdate(Scanner reader) {\r
+ try {\r
+ if (grpcClient == null)\r
+ grpcClient = new ToscaClient(host, port);\r
+\r
+ //Checking if user ha provided the id of the graph to be updated and retrieving it\r
+ if(!reader.hasNextLong()) {\r
+ System.out.println("-- Please provide a valid id for the graph to be update");\r
+ return;\r
+ }\r
+ String id = reader.next();\r
+\r
+ //Reading the file and performing the request according to current configuration\r
+ switch (mediatype) {\r
+ case MediaType.APPLICATION_JSON:\r
+ if(reader.hasNext(jsonSource)) {\r
+ ObjectMapper mapper = new ObjectMapper();\r
+ Graph modelGraph = mapper.readValue(readFile(reader), Graph.class);\r
+ GraphGrpc graph = GrpcUtils.obtainGraph(modelGraph);\r
+ grpcClient.updateGraph(new Long(id), graph);\r
+ }else {\r
+ System.out.println("-- The provided file is not compatible with the current configuration [json].");\r
+ return;\r
+ }\r
+ break;\r
+ case MediaType.APPLICATION_XML:\r
+ if (reader.hasNext(xmlSource)) {\r
+ grpcClient.updateTopologyTemplate(XmlToGrpc.obtainTopologyTemplateGrpc(reader.next()), id);\r
+ } else {\r
+ System.out.println("-- The provided file is not compatible with the current configuration.");\r
+ return;\r
+ }\r
+ break;\r
+\r
+ case "application/x-yaml":\r
+ if (reader.hasNext(yamlSource)) {\r
+ grpcClient.updateTopologyTemplate(YamlToGrpc.obtainTopologyTemplateGrpc(reader.next()), id);\r
+ } else {\r
+ System.out.println("-- The provided file is not compatible with the current configuration.");\r
+ return;\r
+ }\r
+ break;\r
+ }\r
+ } catch (JAXBException je) {\r
+ System.out.println("-- Error while parsing xml : " + je.getMessage());\r
+ } catch (IOException ie) {\r
+ System.out.println("-- Error reading the file : " + ie.getMessage());\r
+ } catch(Exception e) {\r
+ handleError(e);\r
+ }\r
+ }\r
+\r
+\r
+ public void grpcVerify(Scanner reader) {\r
+ ToscaPolicy.Builder policyBuilder = ToscaPolicy.newBuilder();\r
+ String graphId, whichPolicy, source, destination, middlebox = null;\r
+\r
+ try {\r
+ if(!reader.hasNextLong()) {\r
+ System.out.println("-- Provide the graph on which you want to perform verification.");\r
+ return;\r
+ }\r
+ graphId = reader.next();\r
+\r
+ if (!reader.hasNext(policies)) {\r
+ System.out.println("-- Provide the requested type of verfication.");\r
+ return;\r
+ }\r
+ whichPolicy = reader.next().toLowerCase();\r
+\r
+ try {\r
+ source = reader.next();\r
+ destination = reader.next();\r
+ if(!whichPolicy.equals("reachability")) {\r
+ middlebox = reader.next();\r
+ }\r
+ }catch(NoSuchElementException ex) {\r
+ System.out.println("-- Wrong or missing verification parameters.");\r
+ return;\r
+ }\r
+\r
+ policyBuilder.setIdTopologyTemplate(graphId);\r
+ policyBuilder.setDestination(destination);\r
+ policyBuilder.setSource(source);\r
+ switch(whichPolicy) {\r
+ case "reachability":\r
+ policyBuilder.setType(ToscaPolicy.PolicyType.forNumber(0));\r
+ break;\r
+ case "isolation":\r
+ policyBuilder.setType(ToscaPolicy.PolicyType.forNumber(1));\r
+ policyBuilder.setMiddlebox(middlebox);\r
+ break;\r
+ case "traversal":\r
+ policyBuilder.setType(ToscaPolicy.PolicyType.forNumber(2));\r
+ policyBuilder.setMiddlebox(middlebox);\r
+ break;\r
+ }\r
+\r
+ if (grpcClient == null)\r
+ grpcClient = new ToscaClient(host, port);\r
+\r
+ //Sending verification request\r
+ grpcClient.verifyPolicy(policyBuilder.build());\r
+\r
+ } catch (Exception e) {\r
+ handleError(e);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+\r
+ public void readResponseRest(String responseOf, Response res) {\r
+ switch(responseOf) {\r
+ case "GETALL":\r
+ switch (res.getStatus()) {\r
+ case 200:\r
+ System.out.println("++ GET success :");\r
+ break;\r
+ case 500:\r
+ System.out.println("-- GET failed : internal server error.");\r
+ break;\r
+ default:\r
+ System.out.println("** Unexpected response");\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case "GET":\r
+ switch (res.getStatus()) {\r
+ case 200:\r
+ System.out.println("++ GET success :");\r
+ break;\r
+ case 404:\r
+ System.out.println("-- GET failed : graph not found.");\r
+ break;\r
+ case 500:\r
+ System.out.println("-- GET failed : internal server error.");\r
+ break;\r
+ default:\r
+ System.out.println("** Unexpected response **");\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case "CREATE":\r
+ switch (res.getStatus()) {\r
+ case 201:\r
+ System.out.println("++ POST success : graph created.");\r
+ break;\r
+ case 400:\r
+ System.out.println("-- POST failed : bad request.");\r
+ break;\r
+ case 500:\r
+ System.out.println("-- POST failed : internal server error.");\r
+ break;\r
+ default:\r
+ System.out.println("** Unexpected response **");\r
+ break;\r
+ }\r
+ break;\r
+ case "DELETE":\r
+ switch (res.getStatus()) {\r
+ case 204:\r
+ System.out.println("++ DELETE success : graph deleted.");\r
+ break;\r
+ case 403:\r
+ System.out.println("-- DELETE failed : invalid graph ID.");\r
+ break;\r
+ case 404:\r
+ System.out.println("-- DELETE failed : invalid graph id.");\r
+ break;\r
+ case 500:\r
+ System.out.println("-- DELETE failed : internal server error.");\r
+ break;\r
+ default:\r
+ System.out.println("** Unexpected response **");\r
+ break;\r
+ }\r
+ break;\r
+ case "UPDATE":\r
+ switch (res.getStatus()) {\r
+ case 200:\r
+ System.out.println("++ PUT success : graph correctly updated.");\r
+ break;\r
+ case 400:\r
+ System.out.println("-- PUT failed : invalid graph object.");\r
+ break;\r
+ case 403:\r
+ System.out.println("-- PUT failed : invalid graph ID.");\r
+ break;\r
+ case 404:\r
+ System.out.println("-- PUT failed : graph not found.");\r
+ break;\r
+ case 500:\r
+ System.out.println("-- PUT failed : internal server error.");\r
+ break;\r
+ default:\r
+ System.out.println("** Unexpected response **");\r
+ break;\r
+ }\r
+ break;\r
+\r
+ default:\r
+\r
+ }\r
+\r
+ //In case of errors we do not read the message body\r
+ if(res.hasEntity() && res.getStatus() <= 300) {\r
+ String responseBody = prettyFormat(res.readEntity(String.class));\r
+ if(responseBody != null) System.out.println(responseBody);\r
+ }\r
+ else {\r
+ System.out.println("++ No content in the message body");\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+\r
+ public void marshallToXml(List<Definitions> defs) {\r
+ try {\r
+ JAXBContext jc = JAXBContext.newInstance(ObjectFactory.class, TDefinitions.class, Configuration.class);\r
+ Marshaller m = jc.createMarshaller();\r
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);\r
+ for (Definitions def : defs) {\r
+ // To be tested, in case of problems def must be converted to a JAXBElement\r
+ m.marshal(def, System.out);\r
+ System.out.println("\n");\r
+ }\r
+\r
+ } catch (JAXBException je) {\r
+ System.out.println("-- Error while marshalling : " + je.getMessage());\r
+ }\r
+ return;\r
+ }\r
+\r
+ public void marshallToYaml(List<ServiceTemplateYaml> templates) {\r
+ try {\r
+ YAMLMapper mapper = new YAMLMapper();\r
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\r
+ for (ServiceTemplateYaml templ : templates) {\r
+ System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(templ));\r
+ System.out.println("\n");\r
+ }\r
+\r
+ } catch (JsonProcessingException je) {\r
+ System.out.println("-- Error while marshalling : " + je.getMessage());\r
+\r
+ }\r
+ return;\r
+ }\r
+\r
+ public void marshallToJson(List<Graph> templates) {\r
+ try {\r
+ ObjectMapper mapper = new ObjectMapper();\r
+ //mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\r
+ for (Graph templ : templates) {\r
+ System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(templ));\r
+ System.out.println("\n");\r
+ }\r
+\r
+ } catch (JsonProcessingException je) {\r
+ System.out.println("-- Error while marshalling : " + je.getMessage());\r
+\r
+ }\r
+ return;\r
+ }\r
+\r
+\r
+ // Reads the whole file into a string and performs a minimum validation on file type\r
+ public String readFile(Scanner reader) {\r
+\r
+ String content = null;\r
+ Scanner filereader = null;\r
+ if ((mediatype.equals("application/x-yaml") && reader.hasNext(yamlSource))\r
+ || (mediatype.equals(MediaType.APPLICATION_XML) && reader.hasNext(xmlSource))\r
+ || (mediatype.equals(MediaType.APPLICATION_JSON) && reader.hasNext(jsonSource))) {\r
+ try {\r
+ File inputfile = new File(reader.next());\r
+ filereader = new Scanner(inputfile).useDelimiter("\\Z");\r
+ content = filereader.next();\r
+ if (filereader.ioException() != null) {\r
+ throw new IOException(filereader.ioException());\r
+ } else {\r
+ System.out.println("++ File correctly read.");\r
+ }\r
+ } catch (FileNotFoundException ex) {\r
+ System.out.println("-- Error : the provided file does not exist!");\r
+ }catch (IOException ex) {\r
+ System.out.println("-- Error : an error occurred reading the input file!");\r
+ }catch (Exception e) {\r
+ handleError(e);\r
+ }finally {\r
+ if(filereader != null) filereader.close();\r
+ }\r
+\r
+ } else {\r
+ System.out.println("-- Error : the file provided in input does not match with the current client configuration.");\r
+ }\r
+\r
+ return content;\r
+ }\r
+\r
+\r
+ public String prettyFormat(String input) {\r
+ String formattedString = null;\r
+\r
+ try {\r
+ switch(mediatype) {\r
+ case MediaType.APPLICATION_XML:\r
+ Source xmlInput = new StreamSource(new StringReader(input));\r
+ StringWriter stringWriter = new StringWriter();\r
+ StreamResult xmlOutput = new StreamResult(stringWriter);\r
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();\r
+ transformerFactory.setAttribute("indent-number", 2);\r
+ Transformer transformer = transformerFactory.newTransformer();\r
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+ transformer.transform(xmlInput, xmlOutput);\r
+ formattedString = xmlOutput.getWriter().toString();\r
+ break;\r
+ case MediaType.APPLICATION_JSON:\r
+ ObjectMapper mapper = new ObjectMapper();\r
+ Object jsonObj = mapper.readValue(input, Object.class);\r
+ formattedString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObj);\r
+ break;\r
+ case "application/x-yaml":\r
+ formattedString = input;\r
+ break;\r
+ }\r
+ } catch (Exception e) {\r
+ formattedString = e.getCause().toString();\r
+ }\r
+\r
+ return formattedString;\r
+ }\r
+\r
+\r
+}\r