@RolesAllowed(Roles.OWNER) @POST @Consumes(MediaType.APPLICATION_JSON) @ApiOperation(value = "Create a new stream", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Internal Server Error")}) public ResponseMsg doPostNewStream(@Valid Stream stream) throws JsonProcessingException { StreamDatabaseDriver db = null; String ownerName = securityContext.getUserPrincipal().getName(); stream.setOwner(ownerName); try { db = DatabaseConnector.getStreamDatabase(); db.createStream(stream); } catch (IOException | NamingException | SQLException | ClassNotFoundException e) { throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return new ResponseMsg("Successfully created a new stream: " + stream.name); }
@RolesAllowed(Roles.OWNER) @DELETE @Path("/{stream_name}") @ApiOperation(value = "Delete a stream.", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Internal Server Error")}) public ResponseMsg doDeleteStream( @PathParam("stream_name") String streamName, @QueryParam("start_time") String startTime, @QueryParam("end_time") String endTime) throws JsonProcessingException { String ownerName = securityContext.getUserPrincipal().getName(); StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); db.deleteStream(ownerName, streamName, startTime, endTime); } catch (ClassNotFoundException | IOException | NamingException | SQLException e) { throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return new ResponseMsg("Succefully deleted stream (" + streamName + ")."); }
@RolesAllowed(Roles.OWNER) @POST @Path("/{stream_name}") @Consumes(MediaType.APPLICATION_JSON) @ApiOperation(value = "Add a new tuple to the stream.", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Interval Server Error")}) public ResponseMsg doPostStream( @PathParam("stream_name") String streamName, @ApiParam( name = "str_tuple", value = "<pre>Usage:\n" + "[ timestamp, 1st_channel, 2nd_channel, 3rd_channel, .. ]\n" + "\n" + " e.g., [ \"2013-01-01 09:20:12.12345\", 12.4, 1.2, 5.5 ]\n" + " e.g., [ null, 12.4, 1.2, 5.5 ]\n" + "\n" + "Or,\n" + "{ \"timestamp\": timestamp\n" + " \"tuple\": [ 1st_channel, 2nd_channel, 3rd_channel, .. ] }\n" + "\n" + " e.g., { \"timestamp\": \"2013-01-01 09:20:12.12345\"\n" + " \"tuple\": [ 12.4, 1.2, 5.5 ] }\n" + " e.g., { \"timestamp\": null\n" + " \"tuple\": [ 12.4, 1.2, 5.5 ] }\n" + "\n" + "If timestamp is null, current server time will be used.</pre>") String strTuple) throws JsonProcessingException { String ownerName = securityContext.getUserPrincipal().getName(); StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); db.addTuple(ownerName, streamName, strTuple); } catch (ClassNotFoundException | IOException | NamingException | SQLException e) { e.printStackTrace(); throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { e.printStackTrace(); throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return new ResponseMsg("Successfully added the tuple."); }
@RolesAllowed(Roles.OWNER) @POST @Path("/{stream_name}.csv") @Consumes(MediaType.APPLICATION_OCTET_STREAM) @ApiOperation(value = "Load csv file to a stream.", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Interval Server Error")}) public ResponseMsg doPostStreamCsv( @PathParam("stream_name") String streamName, @ApiParam( name = "str_tuple", value = "<pre>Usage:\n" + "timestamp, 1st_channel, 2nd_channel, 3rd_channel, ..\n" + "timestamp, 1st_channel, 2nd_channel, 3rd_channel, ..\n" + ".\n" + ".\n" + "\n" + "e.g.,\n" + "2013-01-01 09:20:12.12345, 12.4, 1.2, 5.5\n" + "2013-01-01 09:20:13.12345, 11.4, 3.2, 1.5\n" + "2013-01-01 09:20:14.12345, 10.4, 4.2, 7.5\n" + "</pre>") String data) throws JsonProcessingException { String ownerName = securityContext.getUserPrincipal().getName(); StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); db.bulkLoad(ownerName, streamName, data); } catch (SQLException | IOException | ClassNotFoundException | NamingException | NoSuchAlgorithmException e) { throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return new ResponseMsg("Successfully completed bulkloading."); }
@RolesAllowed({Roles.OWNER, Roles.CONSUMER}) @GET @ApiOperation(value = "Get list of streams", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Internal Server Error")}) public List<Stream> doGetAllStreams( @ApiParam( name = "stream_owner", value = "If null, get currently authenticated user's streams.") @QueryParam("stream_owner") String streamOwner) throws JsonProcessingException { if (streamOwner == null) { streamOwner = securityContext.getUserPrincipal().getName(); } List<Stream> streams = null; StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); streams = db.getStreamList(streamOwner); } catch (SQLException | ClassNotFoundException | IOException | NamingException e) { throw WebExceptionBuilder.buildInternalServerError(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return streams; }
@RolesAllowed(Roles.OWNER) @DELETE @ApiOperation(value = "Delete entire streams.", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Internal Server Error")}) public ResponseMsg doDeleteAllStreams() throws JsonProcessingException { String ownerName = securityContext.getUserPrincipal().getName(); StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); db.deleteAllStreams(ownerName); } catch (SQLException | ClassNotFoundException | IOException | NamingException e) { throw WebExceptionBuilder.buildInternalServerError(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return new ResponseMsg("Successfully deleted all streams."); }
@RolesAllowed({Roles.OWNER, Roles.CONSUMER}) @GET @Path("/{stream_name}") @ApiOperation(value = "Retrieve the stream.", notes = GET_STREAM_NOTES) @ApiResponses(value = {@ApiResponse(code = 500, message = "Internal Server Error")}) public Object doGetStream( @PathParam("stream_name") final String streamName, @ApiParam( name = "stream_owner", value = "If null, get currently authenticated user's streams.") @QueryParam("stream_owner") final String streamOwnerParam, @ApiParam(name = "start_time", value = "Expected format: YYYY-MM-DD HH:MM:SS.[SSSSS]") @QueryParam("start_time") final String startTime, @ApiParam(name = "end_time", value = "Expected format: YYYY-MM-DD HH:MM:SS.[SSSSS]") @QueryParam("end_time") final String endTime, @ApiParam(name = "filter", value = "Please refer to the above Implementation Notes.") @QueryParam("filter") final String filter, @ApiParam(name = "aggregator", value = "Please refer to the above Implementation Notes.") @QueryParam("aggregator") final String aggregator, @ApiParam(name = "limit", value = "Default value is 100.") @DefaultValue("100") @QueryParam("limit") final int limit, @ApiParam(name = "offset", value = "Default value is 0.") @QueryParam("offset") final int offset, @ApiParam(name = "http_streaming", value = "Default value is true.") @DefaultValue("false") @QueryParam("http_streaming") final boolean isHttpStreaming) throws JsonProcessingException { StreamDatabaseDriver db = null; final String requestingUser = securityContext.getUserPrincipal().getName(); final String streamOwner = streamOwnerParam == null ? requestingUser : streamOwnerParam; try { db = DatabaseConnector.getStreamDatabase(); if (!isHttpStreaming && limit > ROW_LIMIT_WITHOUT_HTTP_STREAMING) { throw WebExceptionBuilder.buildBadRequest( "Too mcuh data requested without HTTP streaming."); } if (!isHttpStreaming) { boolean isData = db.prepareQuery( requestingUser, streamOwner, streamName, startTime, endTime, aggregator, filter, limit, offset, 0, false, null); String strJson = getStreamJsonPrefix(db.getStoredStreamInfo()); if (isData) { Object[] tuple = db.getNextTuple(); if (tuple != null) { strJson += convertTupleToJsonString(tuple); while ((tuple = db.getNextTuple()) != null) { strJson += "," + convertTupleToJsonString(tuple); } } } return strJson + "]}"; } else { return new StreamingOutput() { @Override public void write(OutputStream output) throws IOException, WebApplicationException { StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); boolean isData = db.prepareQuery( requestingUser, streamOwner, streamName, startTime, endTime, aggregator, filter, limit, offset, 0, false, null); String strJson = getStreamJsonPrefix(db.getStoredStreamInfo()); IOUtils.write(strJson, output); if (isData) { Object[] tuple = db.getNextTuple(); if (tuple != null) { IOUtils.write(convertTupleToJsonString(tuple), output); while ((tuple = db.getNextTuple()) != null) { IOUtils.write("," + convertTupleToJsonString(tuple), output); } } } IOUtils.write("]}", output); } catch (SQLException | ClassNotFoundException | NamingException | UnsupportedOperationException e) { e.printStackTrace(); throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { e.printStackTrace(); throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }; } } catch (ClassNotFoundException | IOException | NamingException | SQLException | UnsupportedOperationException e) { e.printStackTrace(); throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { e.printStackTrace(); throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
@RolesAllowed({Roles.OWNER, Roles.CONSUMER}) @GET @Path("/{stream_name}.png") @Produces("image/png") @ApiOperation(value = "Retrieve the stream.", notes = GET_STREAM_NOTES) @ApiResponses(value = {@ApiResponse(code = 500, message = "Internal Server Error")}) public Response doGetStreamAsPng( @PathParam("stream_name") final String streamName, @ApiParam( name = "stream_owner", value = "If null, get currently authenticated user's streams.") @QueryParam("stream_owner") final String streamOwnerParam, @ApiParam(name = "start_time", value = "Expected format: YYYY-MM-DD HH:MM:SS.[SSSSS]") @QueryParam("start_time") final String startTime, @ApiParam(name = "end_time", value = "Expected format: YYYY-MM-DD HH:MM:SS.[SSSSS]") @QueryParam("end_time") final String endTime, @ApiParam(name = "filter", value = "Please refer to the above Implementation Notes.") @QueryParam("filter") final String filter, @ApiParam(name = "aggregator", value = "Please refer to the above Implementation Notes.") @QueryParam("aggregator") String aggregator, /*@ApiParam(name = "limit", value = "Default value is 100.") @DefaultValue("100") @QueryParam("limit") final int limit, @ApiParam(name = "offset", value = "Default value is 0.") @QueryParam("offset") final int offset,*/ @ApiParam(name = "width", value = "Chart width in pixels. Default is 500.") @DefaultValue("500") @QueryParam("width") int width, @ApiParam(name = "height", value = "Chart width in pixels. Default is 300.") @DefaultValue("300") @QueryParam("height") int height) throws IOException { StreamDatabaseDriver db = null; String requestingUser = securityContext.getUserPrincipal().getName(); String streamOwner = streamOwnerParam == null ? requestingUser : streamOwnerParam; try { db = DatabaseConnector.getStreamDatabase(); boolean isData = db.prepareQuery( requestingUser, streamOwner, streamName, startTime, endTime, aggregator, filter, 0, 0, 0, true, null); Stream stream = db.getStoredStreamInfo(); if (!isData) { return Response.ok("No data").build(); } if (stream.num_samples > width) { db.close(); db = DatabaseConnector.getStreamDatabase(); int skipEveryNth = (int) (stream.num_samples / width); isData = db.prepareQuery( requestingUser, streamOwner, streamName, startTime, endTime, aggregator, filter, 0, 0, skipEveryNth, true, null); stream = db.getStoredStreamInfo(); if (!isData) { return Response.ok("No data").build(); } } // Prepare data XYSeries[] series = null; long minTsInterval = Long.MAX_VALUE; // to determine whether to use marker on the plot. long prevTimestamp = -1; Object[] tuple = new Object[db.getStoredStreamInfo().channels.size() + 1]; while (db.getNextTuple(tuple)) { // Init XYSeries array if (series == null) { series = new XYSeries[tuple.length - 1]; for (int i = 0; i < series.length; i++) { series[i] = new XYSeries(stream.channels.get(i).name); } } long timestamp = ((Long) tuple[0]).longValue(); for (int i = 1; i < tuple.length; i++) { try { series[i - 1].add(timestamp, (Number) tuple[i]); } catch (ClassCastException e) { continue; } } long diff = timestamp - prevTimestamp; if (diff > 0 && diff < minTsInterval) { minTsInterval = diff; } prevTimestamp = timestamp; } XYSeriesCollection xyDataset = new XYSeriesCollection(); for (XYSeries s : series) { xyDataset.addSeries(s); } // Generate title string long start = (long) series[0].getMinX(); long end = (long) series[0].getMaxX(); Timestamp startTimestamp = new Timestamp(start); Timestamp endTimestamp = new Timestamp(end); String title = stream.owner + ": " + stream.name + "\n" + startTimestamp.toString() + " ~ " + endTimestamp.toString(); // Create the chart object ValueAxis xAxis = new DateAxis("Time"); // NumberAxis xAxis = new NumberAxis(""); NumberAxis yAxis = new NumberAxis("Value"); yAxis.setAutoRangeIncludesZero(false); // override default StandardXYItemRenderer renderer; long dataCount = (end - start) / minTsInterval; if (dataCount <= width) { renderer = new StandardXYItemRenderer( StandardXYItemRenderer.LINES + StandardXYItemRenderer.SHAPES); } else { renderer = new StandardXYItemRenderer(StandardXYItemRenderer.LINES); } // renderer.setShapesFilled(true); XYPlot plot = new XYPlot(xyDataset, xAxis, yAxis, renderer); JFreeChart chart = new JFreeChart(title, new Font(Font.SANS_SERIF, Font.BOLD, 12), plot, true); // JFreeChart chart = new JFreeChart(title, plot); chart.setBackgroundPaint(java.awt.Color.WHITE); ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection()); String filename = ServletUtilities.saveChartAsPNG(chart, width, height, info, session); File imageFile = new File("/tmp/" + filename); byte[] imageData = FileUtils.readFileToByteArray(imageFile); imageFile.delete(); // Send non-streamed // return Response.ok(imageData).build(); // Send streamed return Response.ok(new ByteArrayInputStream(imageData)).build(); } catch (ClassNotFoundException | IOException | NamingException | SQLException | UnsupportedOperationException e) { e.printStackTrace(); throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { e.printStackTrace(); throw WebExceptionBuilder.buildBadRequest(e); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
@RolesAllowed(Roles.OWNER) @POST @Path("/{stream_name}.zip") @Consumes("application/zip") @ApiOperation(value = "Load zip file to a stream.", notes = "TBD") @ApiResponses(value = {@ApiResponse(code = 500, message = "Interval Server Error")}) public ResponseMsg doPostStreamZip( @PathParam("stream_name") String streamName, @ApiParam( name = "str_tuple", value = "<pre>Usage: attach a zip file containing a single file with the following content:\n" + "timestamp, 1st_channel, 2nd_channel, 3rd_channel, ..\n" + "timestamp, 1st_channel, 2nd_channel, 3rd_channel, ..\n" + ".\n" + ".\n" + "\n" + "e.g.,\n" + "2013-01-01 09:20:12.12345, 12.4, 1.2, 5.5\n" + "2013-01-01 09:20:13.12345, 11.4, 3.2, 1.5\n" + "2013-01-01 09:20:14.12345, 10.4, 4.2, 7.5\n" + "</pre>") byte[] data) throws JsonProcessingException { // check if report generation is ongoing. synchronized (CreateReportRunnable.reportLock) { File lockFile = new File(CreateReportRunnable.REPORT_LOCK_FILE); if (lockFile.exists()) { throw WebExceptionBuilder.buildBadRequest("Report creation job is running.."); } } // Create temporary file DataOutputStream os = null; File file = null; String zipFileName = null; String unzipFolderName = null; try { unzipFolderName = TEMP_ZIP_FILE_PREFIX + newUUIDString(); zipFileName = unzipFolderName + ".zip"; file = new File(zipFileName); if (file.exists()) { file.delete(); } file.createNewFile(); os = new DataOutputStream(new FileOutputStream(file)); os.write(data); } catch (IOException e) { deleteTempZipFiles(zipFileName, unzipFolderName); throw WebExceptionBuilder.buildInternalServerError(e); } finally { try { if (os != null) os.close(); } catch (IOException e) { throw WebExceptionBuilder.buildInternalServerError(e); } } // Unzip the file. String unzippedFileName = null; try { unzippedFileName = unzip(zipFileName, unzipFolderName); } catch (IOException | UnsupportedOperationException e) { deleteTempZipFiles(zipFileName, unzipFolderName); throw WebExceptionBuilder.buildInternalServerError(e); } // Check unzipped filename if (unzippedFileName == null) { deleteTempZipFiles(zipFileName, unzipFolderName); throw WebExceptionBuilder.buildBadRequest("Problem with Zip file."); } // Read the file into memory. String unzippedData = null; try { unzippedData = readEntireFile(unzippedFileName); } catch (IOException e) { deleteTempZipFiles(zipFileName, unzipFolderName); throw WebExceptionBuilder.buildInternalServerError(e); } if (unzippedData.length() <= 0) { deleteTempZipFiles(zipFileName, unzipFolderName); throw WebExceptionBuilder.buildBadRequest("Empty data."); } // Pass unzipped data to database String ownerName = securityContext.getUserPrincipal().getName(); StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); db.bulkLoad(ownerName, streamName, unzippedData); } catch (SQLException | IOException | ClassNotFoundException | NamingException | NoSuchAlgorithmException e) { throw WebExceptionBuilder.buildInternalServerError(e); } catch (IllegalArgumentException e) { throw WebExceptionBuilder.buildBadRequest( e.getClass().getSimpleName() + ": " + e.getMessage()); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } deleteTempZipFiles(zipFileName, unzipFolderName); } return new ResponseMsg("Successfully completed zip bulkloading."); }