+package org.simantics.scl.rest;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+@Path("SCLAPI")
+@Produces(MediaType.APPLICATION_JSON)
+public class SCLRESTAPI {
+
+ private SCLAPI sclAPI;
+
+ public SCLRESTAPI() {
+ sclAPI = SCLAPI.getInstance();
+ }
+
+ private static Map<String, Object> buildJSONResponse(Object... keyValues) {
+ if ((keyValues.length % 2) != 0)
+ throw new IllegalArgumentException("Invalid amount of arguments! " + Arrays.toString(keyValues));
+ Map<String, Object> results = new HashMap<>(keyValues.length / 2);
+ for (int i = 0; i < keyValues.length; i += 2) {
+ Object key = keyValues[i];
+ Object value = keyValues[i + 1];
+ if (!(key instanceof String))
+ throw new IllegalArgumentException("Key with index " + i + " is not String");
+ results.put((String) key, value);
+ }
+ return results;
+ }
+
+ @Path("/sessions")
+ @POST
+ public Response sessions() {
+ String sessionId = UUID.randomUUID().toString();
+ sclAPI.getOrCreateCommandSession(sessionId);
+ return Response.ok(buildJSONResponse("sessionId", sessionId)).build();
+ }
+
+ @Path("/sessions/{sessionId}/modules/{moduleName:.*}")
+ @PUT
+ public Response upload(@PathParam("sessionId") String sessionId, @PathParam("moduleName") String moduleName, @FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetail) throws IOException {
+ String moduleText = getModuleText(inputStream);
+ String response = sclAPI.putModule(sessionId, moduleName, moduleText);
+ if (response == null)
+ return Response.ok().build();
+ else
+ return Response.status(422).entity(buildJSONResponse("response", response)).build();
+ }
+
+ private static String getModuleText(InputStream inputStream) throws IOException {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[4096];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1)
+ result.write(buffer, 0, length);
+ return result.toString(StandardCharsets.UTF_8.name());
+ }
+
+ @Path("/sessions/{sessionId}/execute")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response execute(@PathParam("sessionId") String sessionId, @FormDataParam("command") String command) {
+ final Reader reader = new InputStreamReader(new ByteArrayInputStream(command.getBytes(StandardCharsets.UTF_8)));
+ return Response.ok((StreamingOutput) output -> {
+ try (Writer writer = new BufferedWriter(new OutputStreamWriter(output))) {
+ sclAPI.execute(sessionId, reader, writer);
+ writer.flush();
+ }
+ }).build();
+ }
+
+ @Path("/sessions/{sessionId}/variables/{variableName}")
+ @GET
+ public Response variableValue(@PathParam("sessionId") String sessionId, @PathParam("variableName") String variableName) {
+ Object value = sclAPI.variableValue(sessionId, variableName);
+ return Response.ok(buildJSONResponse("sessionId", sessionId, "variableName", variableName, "variableValue", value)).build();
+ }
+
+ @Path("/sessions/{sessionId}/close")
+ @POST
+ public Response sessions(@PathParam("sessionId") String sessionId) {
+ sclAPI.deleteCommandSession(sessionId);
+ return Response.ok().build();
+ }
+
+}