private List<Range> getUnsharedRanges(String streamOwner, String streamName) throws ClassNotFoundException, SQLException, IOException, NamingException, NoSuchAlgorithmException { /*double start = 1392883208801.0; double end = 1392936762729.0; double d = (end - start) / 24; resultRanges.add(new Range(start, start + d)); resultRanges.add(new Range(start + 2*d, start + 3*d)); resultRanges.add(new Range(start + 4*d, start + 5*d)); resultRanges.add(new Range(start + 6*d, start + 7*d)); resultRanges.add(new Range(start + 8*d, start + 9*d));*/ prepareDummyStream(streamOwner, streamName); int[] shareflags = queryUsingDummyStreamAsOtherUser(streamOwner, streamName); // dump share flags StringBuilder sb = new StringBuilder(); sb.append("flags = ["); for (int f : shareflags) { sb.append(f); sb.append(","); } sb.deleteCharAt(sb.length() - 1); sb.append("]"); Log.info(sb.toString()); // Generate unshared ranges List<Range> resultRanges = new ArrayList<Range>(); int prevflag = shareflags[0]; double curStartTime = -1; if (shareflags[0] == 0) { curStartTime = startDate.getMillis(); } for (int i = 1; i < shareflags.length; i++) { int curflag = shareflags[i]; if (prevflag == curflag) { continue; } else if (prevflag == 0 && curflag == 1) { if (curStartTime < 0) { Log.error("invalid curStartTime at " + i); } double endTime = startDate.getMillis() + i * DUMMY_STREAM_INTERVAL * 1000; resultRanges.add(new Range(curStartTime, endTime)); curStartTime = -1; } else if (prevflag == 1 && curflag == 0) { curStartTime = startDate.getMillis() + i * DUMMY_STREAM_INTERVAL * 1000; } prevflag = shareflags[i]; } if (curStartTime > 0) { double endTime = startDate.getMillis() + shareflags.length * DUMMY_STREAM_INTERVAL * 1000; resultRanges.add(new Range(curStartTime, endTime)); } return resultRanges; }
private void sendEmailToOwner(String username, String reportIdxFileName) { String link = basePath + REPORTS_URL + "/" + reportIdxFileName; link = "<a href=\"" + link + "\">" + link + "</a>"; String title = EMAIL_TITLE + " (" + titleFmt.print(startDate) + " ~ " + titleFmt.print(endDate) + ")"; String body = "Your data reports are ready for your review at the following address:<br/><br/>" + link; body += "<br/><br/>Please access the above link and provide us your feedback!<br/><br/>"; body += "Regards,<br/>SensorPrivacy Research Team"; // Get email address UserDatabaseDriver db = null; String email = null; try { db = DatabaseConnector.getUserDatabase(); email = db.getUserEmail(username); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } if (email == null) { Log.error("No email address for " + username); return; } try { MailSender.send(email, title, body); } catch (MessagingException e) { e.printStackTrace(); Log.error("Error while sending email.."); return; } Log.info("Done sending email!"); }
@Override public void run() { try { if (!checkLock()) { return; } Log.info("Report thread running.."); // Fetch GPS data Log.info("Fetching GPS data.."); boolean isGPS = generateGPSInitScript(); if (!isGPS) { Log.error("Generating GPS samples failed.."); } else { Log.info("Fetching GPS data done"); } // Read report template String reportTemplate = FileUtils.readFileToString(new File(REPORT_TEMPLATE_PATH)); if (reportTemplate == null) { Log.error("Error reading report template."); return; } for (String curSensor : REPORT_SENSORS) { generateReportForSensor(curSensor, reportTemplate); } String reportIdxFileName = generateReportIndexPage(); if (reportIdxFileName == null) { Log.error("Error generating report index."); return; } sendEmailToOwner(owner, reportIdxFileName); Log.info("Report thread done!."); } catch (IOException e) { e.printStackTrace(); } finally { releaseLock(); } }
private void prepareDummyStream(String streamOwner, String streamName) throws ClassNotFoundException, SQLException, IOException, NamingException, NoSuchAlgorithmException { // Check if dummy stream exists List<Stream> streams = null; StreamDatabaseDriver db = null; try { db = DatabaseConnector.getStreamDatabase(); streams = db.getStreamList(streamOwner); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } boolean isFound = false; for (Stream stream : streams) { if (stream.name.equals(DUMMY_STREAM_NAME)) { isFound = true; } } if (!isFound) { createDummyStream(streamOwner); } // Check if dummy stream has desired amount of data on today. DateTime day = simpleFmt.parseDateTime(startDate.toString(simpleFmt)); int targetNumSamples = MAX_SEC_A_DAY / DUMMY_STREAM_INTERVAL; while (day.isBefore(endDate)) { Log.info("current day: " + fmt.print(day)); String startTime = fmt.print(day); String endTime = fmt.print(day.plusDays(1).minusMillis(1)); try { db = DatabaseConnector.getStreamDatabase(); boolean isData = db.prepareQuery( streamOwner, streamOwner, DUMMY_STREAM_NAME, startTime, endTime, null, null, 0, 0, 0, true, null); Stream stream = db.getStoredStreamInfo(); if (!isData) { Log.error("isData false"); throw new UnsupportedOperationException("idData false."); } if (stream.num_samples != targetNumSamples) { Log.info("dummy stream is no good. Bulkloading dummy stream.."); bulkloadDummyStreamData(streamOwner, day); } else { Log.info("dummy stream is good."); } } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } day = day.plusDays(1); } }
private int[] queryUsingDummyStreamAsOtherUser(String streamOwner, String streamName) throws ClassNotFoundException, SQLException, IOException, NamingException { StreamDatabaseDriver db = null; String startTime = fmt.print(startDate); String endTime = fmt.print(endDate.minusMillis(1)); Log.info("startTime: " + startTime + ", endTime: " + endTime); long durationInSecs = (endDate.getMillis() / 1000) - (startDate.getMillis() / 1000); int size = (int) (durationInSecs / DUMMY_STREAM_INTERVAL); if (size <= 0) { size = 1; } int[] shareflags = new int[size]; Log.info("size: " + (int) (durationInSecs / DUMMY_STREAM_INTERVAL)); try { db = DatabaseConnector.getStreamDatabase(); boolean isData = db.prepareQuery( OTHER_USER_NAME, streamOwner, DUMMY_STREAM_NAME, startTime, endTime, null, null, 0, 0, 0, false, streamName); if (!isData) { Log.info("No data shared with " + OTHER_USER_NAME + " for " + streamName); return shareflags; } Object[] tuple = new Object[db.getStoredStreamInfo().channels.size() + 1]; long todayMillis = startDate.getMillis(); while (db.getNextTuple(tuple)) { long timestamp = (Long) tuple[0]; // Log.info("timestamp: " + timestamp); int idx = (int) ((timestamp - todayMillis) / 1000 / DUMMY_STREAM_INTERVAL); if (idx >= size) { Log.error( "idx >= size, timestamp = " + fmt.print(new DateTime(timestamp)) + ", idx = " + idx + ", size = " + size); } else { shareflags[idx] = 1; } } return shareflags; } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
private File createPNG( String streamName, int width, int height, String outputPath, boolean isLine, boolean isShape) { StreamDatabaseDriver db = null; String requestingUser = owner; String streamOwner = owner; String startTime = fmt.print(startDate); String endTime = fmt.print(endDate); try { db = DatabaseConnector.getStreamDatabase(); boolean isData = db.prepareQuery( requestingUser, streamOwner, streamName, startTime, endTime, null, null, 0, 0, 0, true, null); Stream stream = db.getStoredStreamInfo(); if (!isData) { Log.error("isData null"); return null; } 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, null, null, 0, 0, skipEveryNth, false, null); stream = db.getStoredStreamInfo(); if (!isData) { Log.error("isData null"); return null; } } // 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; } db.close(); db = null; if (series == null) { throw new UnsupportedOperationException("No data for " + streamName); } 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 DateAxis xAxis = new DateAxis("Time"); xAxis.setDateFormatOverride(new SimpleDateFormat("hh:mm aa")); // NumberAxis xAxis = new NumberAxis(""); long margin = (endDate.getMillis() - startDate.getMillis()) / 24; xAxis.setRange( new Date(startDate.getMillis() - margin), new Date(endDate.getMillis() + margin)); NumberAxis yAxis = new NumberAxis("Value"); yAxis.setAutoRangeIncludesZero(false); // override default if (streamName.equals(ACTIVITY_SENSOR)) { yAxis.setTickUnit(new NumberTickUnit(1.0)); yAxis.setRange(0.0, 4.0); } else if (streamName.equals(STRESS_SENSOR)) { yAxis.setTickUnit(new NumberTickUnit(1.0)); yAxis.setRange(0.0, 1.0); } else if (streamName.equals(CONVERSATION_SENSOR)) { yAxis.setTickUnit(new NumberTickUnit(1.0)); yAxis.setRange(0.0, 2.0); } StandardXYItemRenderer renderer; // long dataCount = (end - start) / minTsInterval; // if (dataCount <= width) { // renderer = new StandardXYItemRenderer(StandardXYItemRenderer.LINES + // StandardXYItemRenderer.SHAPES); // } else { // renderer = new StandardXYItemRenderer(StandardXYItemRenderer.LINES); // } if (isLine && isShape) { renderer = new StandardXYItemRenderer( StandardXYItemRenderer.LINES + StandardXYItemRenderer.SHAPES); } else if (isLine && !isShape) { renderer = new StandardXYItemRenderer(StandardXYItemRenderer.LINES); } else if (!isLine && isShape) { renderer = new StandardXYItemRenderer(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); chart.removeLegend(); // Marker final Color c = new Color(255, 60, 24, 63); List<Range> markerRanges = getUnsharedRanges(streamOwner, streamName); for (Range range : markerRanges) { Marker marker = new IntervalMarker( range.startTimeInMillis, range.endTimeInMillis, c, new BasicStroke(2.0f), null, null, 1.0f); plot.addDomainMarker(marker, Layer.BACKGROUND); } ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection()); String filename = ServletUtilities.saveChartAsPNG(chart, width, height, info, null); File imageFile = new File("/tmp/" + filename); File toFile = new File(outputPath + "/" + streamName + "_" + fileFmt.print(startDate) + ".png"); imageFile.renameTo(toFile); return toFile; } catch (ClassNotFoundException | IOException | NamingException | SQLException | UnsupportedOperationException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return null; }
private boolean generateGPSInitScript() { StreamDatabaseDriver db = null; String requestingUser = owner; String streamOwner = owner; String startTime = fmt.print(startDate); String endTime = fmt.print(endDate); long startTimestamp = startDate.getMillis(); try { db = DatabaseConnector.getStreamDatabase(); boolean isData = db.prepareQuery( requestingUser, streamOwner, GPS_STREAM_NAME, startTime, endTime, null, null, 0, 0, 0, true, null); if (!isData) { Log.error("No GPS data.."); return false; } Stream stream = db.getStoredStreamInfo(); long numSamples = stream.num_samples; if (numSamples <= 0) { Log.error("numSamples <= 0 on " + GPS_STREAM_NAME); return false; } Object[] tuple = new Object[db.getStoredStreamInfo().channels.size() + 1]; int timestamp; Coord coords[] = new Coord[(int) numSamples]; int idx = 0; while (db.getNextTuple(tuple)) { timestamp = (int) (((Long) tuple[0] - startTimestamp) / 1000); coords[idx] = new Coord(timestamp, (Double) tuple[1], (Double) tuple[2]); idx++; } List<Coord> clusteredCoords = gpsClustering(coords); // Generate all shared gps poitns. StringBuilder sb = new StringBuilder(); for (Coord coord : clusteredCoords) { sb.append("gps["); sb.append(coord.timestampInSecs); sb.append("] = new google.maps.Marker({ position: new google.maps.LatLng("); sb.append(coord.lat); sb.append(", "); sb.append(coord.lon); sb.append("), icon: sharedCircle, draggable: false, map: null });\n"); } mGPSSamplesAllShared = sb.toString(); // Generate based on rule processing. List<Range> unsharedRanges = getUnsharedRanges(streamOwner, GPS_STREAM_NAME); sb = new StringBuilder(); for (Coord coord : clusteredCoords) { sb.append("gps["); sb.append(coord.timestampInSecs); sb.append("] = new google.maps.Marker({ position: new google.maps.LatLng("); sb.append(coord.lat); sb.append(", "); sb.append(coord.lon); sb.append("), icon: "); if (isCoordUnshared(coord, unsharedRanges)) { sb.append("nonSharedCircle"); } else { sb.append("sharedCircle"); } sb.append(", draggable: false, map: null });\n"); } mGPSSamplesSharingFlagged = sb.toString(); return true; } catch (JsonProcessingException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { if (db != null) { try { db.close(); } catch (SQLException e) { e.printStackTrace(); } } } return false; }