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 buildJSONResponse(Object... keyValues) { if ((keyValues.length % 2) != 0) throw new IllegalArgumentException("Invalid amount of arguments! " + Arrays.toString(keyValues)); Map 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(); } }