SCL REST API server
[simantics/platform.git] / bundles / org.simantics.scl.rest / src / org / simantics / scl / rest / SCLRESTAPI.java
1 package org.simantics.scl.rest;
2
3 import java.io.BufferedWriter;
4 import java.io.ByteArrayInputStream;
5 import java.io.ByteArrayOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.io.OutputStreamWriter;
10 import java.io.Reader;
11 import java.io.Writer;
12 import java.nio.charset.StandardCharsets;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.Map;
16 import java.util.UUID;
17
18 import javax.ws.rs.GET;
19 import javax.ws.rs.POST;
20 import javax.ws.rs.PUT;
21 import javax.ws.rs.Path;
22 import javax.ws.rs.PathParam;
23 import javax.ws.rs.Produces;
24 import javax.ws.rs.core.MediaType;
25 import javax.ws.rs.core.Response;
26 import javax.ws.rs.core.StreamingOutput;
27
28 import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
29 import org.glassfish.jersey.media.multipart.FormDataParam;
30
31 @Path("SCLAPI")
32 @Produces(MediaType.APPLICATION_JSON)
33 public class SCLRESTAPI {
34
35     private SCLAPI sclAPI;
36
37     public SCLRESTAPI() {
38         sclAPI = SCLAPI.getInstance();
39     }
40     
41     private static Map<String, Object> buildJSONResponse(Object... keyValues) {
42         if ((keyValues.length % 2) != 0)
43             throw new IllegalArgumentException("Invalid amount of arguments! " + Arrays.toString(keyValues));
44         Map<String, Object> results = new HashMap<>(keyValues.length / 2);
45         for (int i = 0; i < keyValues.length; i += 2) {
46             Object key = keyValues[i];
47             Object value = keyValues[i + 1];
48             if (!(key instanceof String))
49                 throw new IllegalArgumentException("Key with index " + i + " is not String");
50             results.put((String) key, value);
51         }
52         return results;
53     }
54     
55     @Path("/sessions")
56     @POST
57     public Response sessions() {
58         String sessionId = UUID.randomUUID().toString(); 
59         sclAPI.getOrCreateCommandSession(sessionId);
60         return Response.ok(buildJSONResponse("sessionId", sessionId)).build();
61     }
62
63     @Path("/sessions/{sessionId}/modules/{moduleName:.*}")
64     @PUT
65     public Response upload(@PathParam("sessionId") String sessionId, @PathParam("moduleName") String moduleName, @FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetail) throws IOException {
66         String moduleText = getModuleText(inputStream);
67         String response = sclAPI.putModule(sessionId, moduleName, moduleText);
68         if (response == null)
69             return Response.ok().build();
70         else
71             return Response.status(422).entity(buildJSONResponse("response", response)).build();
72     }
73     
74     private static String getModuleText(InputStream inputStream) throws IOException {
75         ByteArrayOutputStream result = new ByteArrayOutputStream();
76         byte[] buffer = new byte[4096];
77         int length;
78         while ((length = inputStream.read(buffer)) != -1)
79             result.write(buffer, 0, length);
80         return result.toString(StandardCharsets.UTF_8.name());
81     }
82
83     @Path("/sessions/{sessionId}/execute")
84     @POST
85     @Produces(MediaType.TEXT_PLAIN)
86     public Response execute(@PathParam("sessionId") String sessionId, @FormDataParam("command") String command) {
87         final Reader reader = new InputStreamReader(new ByteArrayInputStream(command.getBytes(StandardCharsets.UTF_8)));
88         return Response.ok((StreamingOutput) output -> {
89             try (Writer writer = new BufferedWriter(new OutputStreamWriter(output))) {
90                 sclAPI.execute(sessionId, reader, writer);
91                 writer.flush();
92             }
93         }).build();
94     }
95
96     @Path("/sessions/{sessionId}/variables/{variableName}")
97     @GET
98     public Response variableValue(@PathParam("sessionId") String sessionId, @PathParam("variableName") String variableName) {
99         Object value = sclAPI.variableValue(sessionId, variableName);
100         return Response.ok(buildJSONResponse("sessionId", sessionId, "variableName", variableName, "variableValue", value)).build();
101     }
102
103     @Path("/sessions/{sessionId}/close")
104     @POST
105     public Response sessions(@PathParam("sessionId") String sessionId) {
106         sclAPI.deleteCommandSession(sessionId);
107         return Response.ok().build();
108     }
109
110 }