Added ability to PUT binary CSAR 61/32361/1
authordfilppi <dewayne@cloudify.co>
Tue, 20 Feb 2018 23:27:13 +0000 (23:27 +0000)
committerdfilppi <dewayne@cloudify.co>
Tue, 20 Feb 2018 23:27:13 +0000 (23:27 +0000)
Change-Id: Ib1dcad8b557cd543ecbf37c5e5947250ee0eb01e
Issue-ID: SO-429
Signed-off-by: DeWayne Filppi <dewayne@cloudify.co>
aria/aria-rest-java-client/src/main/java/com/gigaspaces/aria/rest/client/AriaRestClient.java
aria/aria-rest-java-client/src/main/java/com/gigaspaces/aria/rest/client/ServiceTemplate.java
aria/aria-rest-java-client/src/main/java/com/gigaspaces/aria/rest/client/ServiceTemplateImpl.java

index a4e4533..5de2203 100644 (file)
-/*\r
- * ============LICENSE_START===================================================\r
- * Copyright (c) 2017 Cloudify.co.  All rights reserved.\r
- * ===================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy\r
- * of the License at\r
- *\r
- *       http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- * ============LICENSE_END====================================================\r
-*/\r
-package com.gigaspaces.aria.rest.client;\r
-\r
-import com.gigaspaces.aria.rest.client.exceptions.StorageException;\r
-import com.gigaspaces.aria.rest.client.exceptions.ValidationException;\r
-import org.codehaus.jackson.JsonFactory;\r
-import org.codehaus.jackson.JsonNode;\r
-import org.codehaus.jackson.jaxrs.JacksonJsonProvider;\r
-import org.codehaus.jackson.map.ObjectMapper;\r
-import sun.reflect.generics.reflectiveObjects.NotImplementedException;\r
-\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.WebTarget;\r
-import javax.ws.rs.core.GenericType;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-import java.net.URI;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import static javax.ws.rs.client.Entity.entity;\r
-\r
-/**\r
- * Created by DeWayne on 7/12/2017.\r
- */\r
-public class AriaRestClient implements AriaClient {\r
-    private Client client=null;\r
-    private WebTarget base_target=null;\r
-\r
-    /**\r
-     * Construct an Aria REST client\r
-     *\r
-     * @param protocol either http or https\r
-     * @param address the IP address or host name\r
-     * @param port the port of the service\r
-     * @param version the api version\r
-     */\r
-    public AriaRestClient(String protocol, String address, int port, String version){\r
-        this.client = ClientBuilder.newBuilder().register(JacksonJsonProvider.class).build();\r
-        base_target = client.target(protocol+"://"+address+":"+port+"/api/"+version);\r
-    }\r
-\r
-    /**\r
-     * Installs a service template\r
-     *\r
-     * @param template the template object\r
-     * @throws ValidationException\r
-     * @throws StorageException\r
-     */\r
-    public void install_service_template(ServiceTemplate template) throws ValidationException, StorageException, Exception {\r
-\r
-        Response response = base_target.path("templates/"+template.getName()).request(MediaType.APPLICATION_JSON).put(Entity.entity(\r
-                "{\"service-template-path\":\""+template.getURI().toString()+"\""+\r
-                        ",\"service-template-filename\":\""+template.getFilename()+"\"", MediaType.APPLICATION_JSON));\r
-\r
-        if(response.getStatus() == 500){\r
-            throw new StorageException(response.readEntity(String.class));\r
-        }\r
-        else if(response.getStatus() == 400){\r
-            throw new ValidationException(response.readEntity(String.class));\r
-        }\r
-        else if(response.getStatus()>199 && response.getStatus() <300){\r
-            return;\r
-        }\r
-        else{\r
-            throw new Exception("Error installing template: "+response.getStatus()+" "+ response.readEntity(String.class));\r
-        }\r
-    }\r
-\r
-    public ValidationResult validate_service_template(ServiceTemplate template)throws Exception{\r
-        Response response = base_target.path("templates").request(MediaType.APPLICATION_JSON).post(Entity.entity(\r
-                "{\"service-template-path\":\""+template.getURI().toString()+"\""+\r
-                ",\"service-template-filename\":\""+template.getFilename()+"\"}", MediaType.APPLICATION_JSON));\r
-\r
-        ValidationResultImpl result = new ValidationResultImpl();\r
-        if(response.getStatus() >= 200 && response.getStatus() < 300){\r
-            result.setFailed(false);\r
-        }\r
-        else if(response.getStatus()==400){\r
-            result.setFailed(true);\r
-        }\r
-        else{\r
-            throw new Exception("received error response '"+ response.getStatus()+"':"+response.readEntity(String.class));\r
-        }\r
-        return result;\r
-\r
-    }\r
-\r
-    /**\r
-     *\r
-     * @return a list of service templates\r
-     */\r
-    public List<? extends ServiceTemplate> list_service_templates(){\r
-        List<? extends ServiceTemplate> templates = base_target.path("templates").request(MediaType.APPLICATION_JSON).get(new GenericType<List<ServiceTemplateImpl>>(){});\r
-\r
-        return templates;\r
-    }\r
-\r
-\r
-    /**\r
-     * Deletes the specified template.\r
-     *\r
-     * TODO: Error handling is a little blunt. Need to describe failures better\r
-     *\r
-     * @param template_id the template id to delete\r
-     * @throws IllegalArgumentException thrown when the template can't be deleted\r
-     * @throws Exception other server side errors\r
-     */\r
-    public void delete_service_template(int template_id) throws IllegalArgumentException, Exception{\r
-        Response response = base_target.path("templates/"+template_id).request(MediaType.APPLICATION_JSON).delete();\r
-\r
-        if(response.getStatus()>=200 && response.getStatus()<300){\r
-            return;\r
-        }\r
-        else if(response.getStatus()==400){\r
-            throw new IllegalArgumentException("Error deleting template '"+template_id+"'");\r
-        }\r
-        else{\r
-            throw new Exception("Error processing request. Return code = "+response.getStatus());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * List the node templates for a given template id\r
-     *\r
-     * @param template_id\r
-     * @return\r
-     */\r
-    public List<? extends NodeTemplate> list_nodes(int template_id) {\r
-        List<? extends NodeTemplate> nodes = base_target.path("templates/"+template_id+"/nodes").request(MediaType.APPLICATION_JSON).get(new GenericType<List<NodeTemplateImpl>>(){});\r
-        return nodes;\r
-    }\r
-\r
-    /**\r
-     * Get a specific node by id\r
-     *\r
-     * @param node_id the node id\r
-     * @return\r
-     * @throws IllegalArgumentException\r
-     */\r
-    public NodeTemplate get_node(int node_id) throws IllegalArgumentException {\r
-        NodeTemplate node = base_target.path("nodes/"+node_id).request(MediaType.APPLICATION_JSON).get(NodeTemplateImpl.class);\r
-        return node;\r
-    }\r
-\r
-    public List<? extends Service> list_services() {\r
-        List<? extends Service> services = base_target.path("services").request(MediaType.APPLICATION_JSON).get(new GenericType<List<ServiceImpl>>(){});\r
-        return services;\r
-    }\r
-\r
-    public Service get_service(int service_id) throws IllegalArgumentException {\r
-        throw new NotImplementedException();\r
-    }\r
-\r
-    public List<? extends Output> list_service_outputs(int service_id) throws IllegalArgumentException {\r
-        List<? extends Output> outputs = base_target.path("services").request(MediaType.APPLICATION_JSON).get(new GenericType<List<OutputImpl>>(){});\r
-        return outputs;\r
-    }\r
-\r
-    public List<? extends Input> list_service_inputs(int service_id) throws IllegalArgumentException {\r
-        List<? extends Input> inputs = base_target.path("services").request(MediaType.APPLICATION_JSON).get(new GenericType<List<InputImpl>>(){});\r
-        return inputs;\r
-    }\r
-\r
-    /**\r
-     * Create a service based on the supplied template\r
-     *\r
-     * @param template_id the template to create the service for\r
-     * @param service_name a name for the service\r
-     * @param inputs an optional list of inputs for the service (can be null)\r
-     * @throws Exception\r
-     */\r
-    public void create_service(int template_id, String service_name, List<Input> inputs) throws Exception {\r
-\r
-        String json="{"+inputsToJson(inputs)+"}";\r
-\r
-        Response response = base_target.path("templates/"+template_id+"/services/"+service_name).\r
-                request(MediaType.APPLICATION_JSON).post(\r
-                Entity.entity(json, MediaType.APPLICATION_JSON)\r
-        );\r
-\r
-        if( response.getStatus()< 200 || response.getStatus()>299){\r
-            throw new Exception("create service failed:"+response.getStatus()+" "+ response.readEntity(String.class));\r
-        }\r
-    }\r
-\r
-    public void delete_service(int service_id) throws Exception {\r
-        Response response = base_target.path("services/"+service_id).request(MediaType.APPLICATION_JSON).delete();\r
-        if(!responseOK(response)){\r
-            throw new Exception("delete service failed: "+response.getStatus()+" "+ response.readEntity(String.class));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * List user workflows for supplied service\r
-     *\r
-     * @param service_id\r
-     * @return\r
-     * @throws IllegalArgumentException\r
-     */\r
-    public List<? extends Workflow> list_workflows(int service_id) throws IllegalArgumentException {\r
-        List<? extends Workflow> workflows = base_target.path("services/"+service_id+"/workflows").request(MediaType.APPLICATION_JSON).get(new GenericType<List<WorkflowImpl>>(){});\r
-        return workflows;\r
-    }\r
-\r
-    public Workflow get_workflow(int workflow_id) throws IllegalArgumentException {\r
-        throw new NotImplementedException();\r
-    }\r
-\r
-    /**\r
-     * List all executions\r
-     *\r
-     * @return\r
-     * @throws Exception\r
-     */\r
-    public List<? extends Execution> list_executions() throws Exception {\r
-        List<? extends Execution> executions = base_target.path("executions").request(MediaType.APPLICATION_JSON).get(new GenericType<List<ExecutionImpl>>(){});\r
-        return executions;\r
-    }\r
-\r
-    /**\r
-     * List executions for specified service\r
-     *\r
-     * @param service_id\r
-     * @return\r
-     * @throws Exception\r
-     */\r
-    public List<? extends Execution> list_executions(int service_id) throws Exception {\r
-        List<? extends Execution> executions = base_target.path("services/"+service_id+"/executions").request(MediaType.APPLICATION_JSON).get(new GenericType<List<ExecutionImpl>>(){});\r
-        return executions;\r
-    }\r
-\r
-    /**\r
-     * Get details about a specified execution\r
-     *\r
-     * @param execution_id\r
-     * @return\r
-     * @throws IllegalArgumentException\r
-     */\r
-    public Execution get_execution(int execution_id) throws IllegalArgumentException {\r
-        Execution execution = base_target.path("executions/"+execution_id).request(MediaType.APPLICATION_JSON).get(ExecutionImpl.class);\r
-        return execution;\r
-    }\r
-\r
-    /**\r
-     * Start an execution for the specified service\r
-     *\r
-     * @param service_id the service to run the execution for\r
-     * @param workflow_name the name of the workflow to execute\r
-     * @param details details controlling execution operation\r
-     * @return the execution id\r
-     * @throws Exception\r
-     */\r
-    public int start_execution(int service_id, String workflow_name, ExecutionDetails details) throws Exception {\r
-        StringBuilder json=new StringBuilder("{");\r
-        if(details.getExecutor().length()>0){\r
-            json.append("\"executor\":\"").append(details.getExecutor()).append("\",");\r
-        }\r
-        if(details.getInputs()!=null){\r
-            json.append(inputsToJson(details.getInputs()));\r
-        }\r
-        json.append("\"task_max_attempts\":").append(details.getTaskMaxAttempts()).append(",");\r
-        json.append("\"task_retry_interval\":").append(details.getTaskRetryInterval()).append("}");\r
-\r
-        System.out.println("JSON="+json.toString());\r
-\r
-        Response response = base_target.path("services/"+service_id+"/executions/"+workflow_name).request(MediaType.APPLICATION_JSON).\r
-                post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON));\r
-\r
-        if(!responseOK(response)){\r
-            throw new Exception("start execution failed: "+response.getStatus()+" "+response.readEntity(String.class));\r
-        }\r
-\r
-        ObjectMapper mapper = new ObjectMapper(new JsonFactory());\r
-        JsonNode rootNode = mapper.readTree(response.readEntity(String.class));\r
-        int id=rootNode.get("id").asInt(-1);\r
-        return id;\r
-    }\r
-\r
-    public void resume_execution(int execution_id, ExecutionDetails details) throws IllegalArgumentException {\r
-        StringBuilder json=new StringBuilder("{");\r
-        if(details.getExecutor().length()>0){\r
-            json.append("\"executor\":\"").append(details.getExecutor()).append("\",");\r
-        }\r
-        json.append("\"retry_failed_tasks\":").append(details.isRetry_failed_tasks()).append("}");\r
-        Response response = base_target.path("executions/"+execution_id).request(MediaType.APPLICATION_JSON).\r
-                post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON));\r
-    }\r
-\r
-    public void cancel_execution(int execution_id) throws Exception {\r
-        Response response = base_target.path("executions/"+execution_id).request(MediaType.APPLICATION_JSON).delete();\r
-        if(!responseOK(response)){\r
-            throw new Exception("delete service failed: "+response.getStatus()+" "+ response.readEntity(String.class));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * -----\r
-     * ----- PRIVATE METHODS\r
-     * -----\r
-     */\r
-\r
-    private boolean responseOK(Response response){\r
-        return response.getStatus()>199 && response.getStatus()<300;\r
-    }\r
-\r
-    private String inputsToJson(List<Input> inputs){\r
-        if(inputs==null)return null;\r
-\r
-        StringBuilder sb=new StringBuilder("\"inputs\":{");\r
-        for(Input input:inputs){\r
-            sb.append("\"").append(input.getName()).append("\":\"").append(input.getValue()).append("\",");\r
-        }\r
-        if(inputs.size()>0)sb.deleteCharAt(sb.length()-1); //trim comma\r
-\r
-        return sb.toString();\r
-    }\r
-}\r
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2017 Cloudify.co.  All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END====================================================
+*/
+package com.gigaspaces.aria.rest.client;
+
+import java.util.List;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
+import org.codehaus.jackson.map.ObjectMapper;
+import com.gigaspaces.aria.rest.client.exceptions.StorageException;
+import com.gigaspaces.aria.rest.client.exceptions.ValidationException;
+
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+
+/**
+ * Created by DeWayne on 7/12/2017.
+ */
+public class AriaRestClient implements AriaClient {
+       private Client client = null;
+       private WebTarget base_target = null;
+
+       /**
+        * Construct an Aria REST client
+        *
+        * @param protocol
+        *            either http or https
+        * @param address
+        *            the IP address or host name
+        * @param port
+        *            the port of the service
+        * @param version
+        *            the api version
+        */
+       public AriaRestClient(String protocol, String address, int port, String version) {
+               this.client = ClientBuilder.newBuilder().register(JacksonJsonProvider.class).build();
+               base_target = client.target(protocol + "://" + address + ":" + port + "/api/" + version);
+       }
+
+       /**
+        * Installs a service template
+        *
+        * @param template
+        *            the template object
+        * @throws ValidationException
+        * @throws StorageException
+        */
+       public void install_service_template(ServiceTemplate template)
+                       throws ValidationException, StorageException, Exception {
+
+               byte[] csarBytes = template.getCSARBytes();
+               Response response = null;
+               if (csarBytes == null) {
+                       response = base_target.path("templates/" + template.getName()).request(MediaType.APPLICATION_JSON)
+                                       .put(Entity.entity(
+                                                       "{\"service-template-path\":\"" + template.getURI().toString() + "\""
+                                                                       + ",\"service-template-filename\":\"" + template.getFilename() + "\"",
+                                                       MediaType.APPLICATION_JSON));
+               }
+               else {
+                       
+                       response = base_target.path("templates/" + template.getName()).request("application/zip")
+                                       .put(Entity.entity(csarBytes, "application/zip"));
+               }
+
+               if (response.getStatus() == 500) {
+                       throw new StorageException(response.readEntity(String.class));
+               } else if (response.getStatus() == 400) {
+                       throw new ValidationException(response.readEntity(String.class));
+               } else if (response.getStatus() > 199 && response.getStatus() < 300) {
+                       return;
+               } else {
+                       throw new Exception(
+                                       "Error installing template: " + response.getStatus() + " " + response.readEntity(String.class));
+               }
+       }
+
+       public ValidationResult validate_service_template(ServiceTemplate template) throws Exception {
+               Response response = base_target.path("templates").request(MediaType.APPLICATION_JSON)
+                               .post(Entity.entity(
+                                               "{\"service-template-path\":\"" + template.getURI().toString() + "\""
+                                                               + ",\"service-template-filename\":\"" + template.getFilename() + "\"}",
+                                               MediaType.APPLICATION_JSON));
+
+               ValidationResultImpl result = new ValidationResultImpl();
+               if (response.getStatus() >= 200 && response.getStatus() < 300) {
+                       result.setFailed(false);
+               } else if (response.getStatus() == 400) {
+                       result.setFailed(true);
+               } else {
+                       throw new Exception(
+                                       "received error response '" + response.getStatus() + "':" + response.readEntity(String.class));
+               }
+               return result;
+
+       }
+
+       /**
+        *
+        * @return a list of service templates
+        */
+       public List<? extends ServiceTemplate> list_service_templates() {
+               List<? extends ServiceTemplate> templates = base_target.path("templates").request(MediaType.APPLICATION_JSON)
+                               .get(new GenericType<List<ServiceTemplateImpl>>() {
+                               });
+
+               return templates;
+       }
+
+       /**
+        * Deletes the specified template.
+        *
+        * TODO: Error handling is a little blunt. Need to describe failures better
+        *
+        * @param template_id
+        *            the template id to delete
+        * @throws IllegalArgumentException
+        *             thrown when the template can't be deleted
+        * @throws Exception
+        *             other server side errors
+        */
+       public void delete_service_template(int template_id) throws IllegalArgumentException, Exception {
+               Response response = base_target.path("templates/" + template_id).request(MediaType.APPLICATION_JSON).delete();
+
+               if (response.getStatus() >= 200 && response.getStatus() < 300) {
+                       return;
+               } else if (response.getStatus() == 400) {
+                       throw new IllegalArgumentException("Error deleting template '" + template_id + "'");
+               } else {
+                       throw new Exception("Error processing request. Return code = " + response.getStatus());
+               }
+       }
+
+       /**
+        * List the node templates for a given template id
+        *
+        * @param template_id
+        * @return
+        */
+       public List<? extends NodeTemplate> list_nodes(int template_id) {
+               List<? extends NodeTemplate> nodes = base_target.path("templates/" + template_id + "/nodes")
+                               .request(MediaType.APPLICATION_JSON).get(new GenericType<List<NodeTemplateImpl>>() {
+                               });
+               return nodes;
+       }
+
+       /**
+        * Get a specific node by id
+        *
+        * @param node_id
+        *            the node id
+        * @return
+        * @throws IllegalArgumentException
+        */
+       public NodeTemplate get_node(int node_id) throws IllegalArgumentException {
+               NodeTemplate node = base_target.path("nodes/" + node_id).request(MediaType.APPLICATION_JSON)
+                               .get(NodeTemplateImpl.class);
+               return node;
+       }
+
+       public List<? extends Service> list_services() {
+               List<? extends Service> services = base_target.path("services").request(MediaType.APPLICATION_JSON)
+                               .get(new GenericType<List<ServiceImpl>>() {
+                               });
+               return services;
+       }
+
+       public Service get_service(int service_id) throws IllegalArgumentException {
+               throw new NotImplementedException();
+       }
+
+       public List<? extends Output> list_service_outputs(int service_id) throws IllegalArgumentException {
+               List<? extends Output> outputs = base_target.path("services").request(MediaType.APPLICATION_JSON)
+                               .get(new GenericType<List<OutputImpl>>() {
+                               });
+               return outputs;
+       }
+
+       public List<? extends Input> list_service_inputs(int service_id) throws IllegalArgumentException {
+               List<? extends Input> inputs = base_target.path("services").request(MediaType.APPLICATION_JSON)
+                               .get(new GenericType<List<InputImpl>>() {
+                               });
+               return inputs;
+       }
+
+       /**
+        * Create a service based on the supplied template
+        *
+        * @param template_id
+        *            the template to create the service for
+        * @param service_name
+        *            a name for the service
+        * @param inputs
+        *            an optional list of inputs for the service (can be null)
+        * @throws Exception
+        */
+       public void create_service(int template_id, String service_name, List<Input> inputs) throws Exception {
+
+               String json = "{" + inputsToJson(inputs) + "}";
+
+               Response response = base_target.path("templates/" + template_id + "/services/" + service_name)
+                               .request(MediaType.APPLICATION_JSON).post(Entity.entity(json, MediaType.APPLICATION_JSON));
+
+               if (response.getStatus() < 200 || response.getStatus() > 299) {
+                       throw new Exception(
+                                       "create service failed:" + response.getStatus() + " " + response.readEntity(String.class));
+               }
+       }
+
+       public void delete_service(int service_id) throws Exception {
+               Response response = base_target.path("services/" + service_id).request(MediaType.APPLICATION_JSON).delete();
+               if (!responseOK(response)) {
+                       throw new Exception(
+                                       "delete service failed: " + response.getStatus() + " " + response.readEntity(String.class));
+               }
+       }
+
+       /**
+        * List user workflows for supplied service
+        *
+        * @param service_id
+        * @return
+        * @throws IllegalArgumentException
+        */
+       public List<? extends Workflow> list_workflows(int service_id) throws IllegalArgumentException {
+               List<? extends Workflow> workflows = base_target.path("services/" + service_id + "/workflows")
+                               .request(MediaType.APPLICATION_JSON).get(new GenericType<List<WorkflowImpl>>() {
+                               });
+               return workflows;
+       }
+
+       public Workflow get_workflow(int workflow_id) throws IllegalArgumentException {
+               throw new NotImplementedException();
+       }
+
+       /**
+        * List all executions
+        *
+        * @return
+        * @throws Exception
+        */
+       public List<? extends Execution> list_executions() throws Exception {
+               List<? extends Execution> executions = base_target.path("executions").request(MediaType.APPLICATION_JSON)
+                               .get(new GenericType<List<ExecutionImpl>>() {
+                               });
+               return executions;
+       }
+
+       /**
+        * List executions for specified service
+        *
+        * @param service_id
+        * @return
+        * @throws Exception
+        */
+       public List<? extends Execution> list_executions(int service_id) throws Exception {
+               List<? extends Execution> executions = base_target.path("services/" + service_id + "/executions")
+                               .request(MediaType.APPLICATION_JSON).get(new GenericType<List<ExecutionImpl>>() {
+                               });
+               return executions;
+       }
+
+       /**
+        * Get details about a specified execution
+        *
+        * @param execution_id
+        * @return
+        * @throws IllegalArgumentException
+        */
+       public Execution get_execution(int execution_id) throws IllegalArgumentException {
+               Execution execution = base_target.path("executions/" + execution_id).request(MediaType.APPLICATION_JSON)
+                               .get(ExecutionImpl.class);
+               return execution;
+       }
+
+       /**
+        * Start an execution for the specified service
+        *
+        * @param service_id
+        *            the service to run the execution for
+        * @param workflow_name
+        *            the name of the workflow to execute
+        * @param details
+        *            details controlling execution operation
+        * @return the execution id
+        * @throws Exception
+        */
+       public int start_execution(int service_id, String workflow_name, ExecutionDetails details) throws Exception {
+               StringBuilder json = new StringBuilder("{");
+               if (details.getExecutor().length() > 0) {
+                       json.append("\"executor\":\"").append(details.getExecutor()).append("\",");
+               }
+               if (details.getInputs() != null) {
+                       json.append(inputsToJson(details.getInputs()));
+               }
+               json.append("\"task_max_attempts\":").append(details.getTaskMaxAttempts()).append(",");
+               json.append("\"task_retry_interval\":").append(details.getTaskRetryInterval()).append("}");
+
+               System.out.println("JSON=" + json.toString());
+
+               Response response = base_target.path("services/" + service_id + "/executions/" + workflow_name)
+                               .request(MediaType.APPLICATION_JSON).post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON));
+
+               if (!responseOK(response)) {
+                       throw new Exception(
+                                       "start execution failed: " + response.getStatus() + " " + response.readEntity(String.class));
+               }
+
+               ObjectMapper mapper = new ObjectMapper(new JsonFactory());
+               JsonNode rootNode = mapper.readTree(response.readEntity(String.class));
+               int id = rootNode.get("id").asInt(-1);
+               return id;
+       }
+
+       public void resume_execution(int execution_id, ExecutionDetails details) throws IllegalArgumentException {
+               StringBuilder json = new StringBuilder("{");
+               if (details.getExecutor().length() > 0) {
+                       json.append("\"executor\":\"").append(details.getExecutor()).append("\",");
+               }
+               json.append("\"retry_failed_tasks\":").append(details.isRetry_failed_tasks()).append("}");
+               Response response = base_target.path("executions/" + execution_id).request(MediaType.APPLICATION_JSON)
+                               .post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON));
+       }
+
+       public void cancel_execution(int execution_id) throws Exception {
+               Response response = base_target.path("executions/" + execution_id).request(MediaType.APPLICATION_JSON).delete();
+               if (!responseOK(response)) {
+                       throw new Exception(
+                                       "delete service failed: " + response.getStatus() + " " + response.readEntity(String.class));
+               }
+       }
+
+       /**
+        * ----- ----- PRIVATE METHODS -----
+        */
+
+       private boolean responseOK(Response response) {
+               return response.getStatus() > 199 && response.getStatus() < 300;
+       }
+
+       private String inputsToJson(List<Input> inputs) {
+               if (inputs == null)
+                       return null;
+
+               StringBuilder sb = new StringBuilder("\"inputs\":{");
+               for (Input input : inputs) {
+                       sb.append("\"").append(input.getName()).append("\":\"").append(input.getValue()).append("\",");
+               }
+               if (inputs.size() > 0)
+                       sb.deleteCharAt(sb.length() - 1); // trim comma
+
+               return sb.toString();
+       }
+}
index 0df6d60..a2ca8cf 100644 (file)
@@ -1,31 +1,32 @@
-/*\r
- * ============LICENSE_START===================================================\r
- * Copyright (c) 2017 Cloudify.co.  All rights reserved.\r
- * ===================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy\r
- * of the License at\r
- *\r
- *       http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- * ============LICENSE_END====================================================\r
-*/\r
-package com.gigaspaces.aria.rest.client;\r
-\r
-import java.net.URI;\r
-\r
-/**\r
- * Created by DeWayne on 7/12/2017.\r
- */\r
-public interface ServiceTemplate {\r
-    String getName();\r
-    URI getURI();\r
-    int getId();\r
-    String getFilename();\r
-    String getDescription();\r
-}\r
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2017 Cloudify.co.  All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END====================================================
+*/
+package com.gigaspaces.aria.rest.client;
+
+import java.net.URI;
+
+/**
+ * Created by DeWayne on 7/12/2017.
+ */
+public interface ServiceTemplate {
+    String getName();
+    URI getURI();
+    int getId();
+    String getFilename();
+    String getDescription();
+    byte[] getCSARBytes();
+}
index 9e158a2..a41d5b7 100644 (file)
@@ -31,6 +31,7 @@ public class ServiceTemplateImpl implements ServiceTemplate {
     private URI uri;
     private String filename = DEFAULT_TEMPLATE_NAME;
     private String description;
+    private byte[] csar_blob; // for opaque binary
 
     public ServiceTemplateImpl(){}
 
@@ -40,7 +41,7 @@ public class ServiceTemplateImpl implements ServiceTemplate {
     }
 
     /**
-     * Construct an instance
+     * Construct an instance based on CSAR
      * @param name a textual name for the template
      * @param uri a URI to a CSAR
      * @param filename the filename in the CSAR representing main yaml template
@@ -51,6 +52,13 @@ public class ServiceTemplateImpl implements ServiceTemplate {
         this.filename=filename;
         this.description=description;
     }
+    
+    /**
+     * Construct an instance based on CSAR array
+     */
+    public ServiceTemplateImpl(byte[] csar_bytes) {
+       this.csar_blob = csar_bytes;
+    }
 
     public int getId(){
         return id;
@@ -76,6 +84,9 @@ public class ServiceTemplateImpl implements ServiceTemplate {
     public void setFilename(String filename){
         this.filename=filename;
     }
+    public byte[] getCSARBytes() {
+       return csar_blob;
+    }
 
     public String getDescription(){ return description;}
 }