package io.lumify.flightTrack; import com.google.inject.Inject; import io.lumify.core.cmdline.CommandLineBase; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.io.IOUtils; import org.json.JSONException; import org.json.JSONObject; import org.securegraph.Visibility; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; public class Replay extends CommandLineBase { public static final String CMD_OPT_INDIR = "in"; public static final String CMD_OPT_SPEED = "speed"; public static final double DEFAULT_REPLAY_SPEED = 1.0; private FlightRepository flightRepository; public static void main(String[] args) throws Exception { int res = new Replay().run(args); if (res != 0) { System.exit(res); } } @Override protected Options getOptions() { Options opts = super.getOptions(); opts.addOption( OptionBuilder .withLongOpt(CMD_OPT_INDIR) .withDescription("Input directory") .hasArg() .isRequired() .create("i") ); opts.addOption( OptionBuilder .withLongOpt(CMD_OPT_SPEED) .withDescription("The speed to replay (default: " + DEFAULT_REPLAY_SPEED + ")") .hasArg() .create("s") ); return opts; } @Override protected int run(CommandLine cmd) throws Exception { File inDir = new File(cmd.getOptionValue(CMD_OPT_INDIR)); if (!inDir.exists()) { System.err.println(cmd.getOptionValue(CMD_OPT_INDIR) + " does not exist"); return 1; } double replaySpeed = DEFAULT_REPLAY_SPEED; if (cmd.hasOption(CMD_OPT_SPEED)) { replaySpeed = Double.parseDouble(cmd.getOptionValue(CMD_OPT_SPEED)); } ArrayList<File> files = toOrdered(inDir.listFiles()); if (files.size() == 0) { return 2; } Date lastFileTime = null; Date startTime = new Date(); for (int i = 0; i < files.size(); i++) { File f = files.get(i); Date t = parseDateFromFileName(f); if (i > 0) { long sleepTime = calculateSleepTime(startTime, lastFileTime, replaySpeed, t); LOGGER.debug("Sleeping for " + (((double) sleepTime) / 1000.0) + "s"); Thread.sleep(sleepTime); } try { replayFile(f); } catch (Exception ex) { LOGGER.error("Could not replay file %s", f.getAbsolutePath(), ex); } lastFileTime = parseDateFromFileName(f); } return 0; } private void replayFile(File file) throws Exception { LOGGER.debug("Replaying file: " + file.getName()); JSONObject json = readFile(file); Visibility visibility = new Visibility(""); this.flightRepository.save(json, visibility, getAuthorizations()); } private static JSONObject readFile(File file) throws IOException, JSONException { FileInputStream in = new FileInputStream(file); try { String s = IOUtils.toString(in); return new JSONObject(s); } finally { in.close(); } } private static long calculateSleepTime(Date startTime, Date lastFileTime, double replaySpeed, Date fileTime) { double timeSinceStart = new Date().getTime() - startTime.getTime(); double fileTimeDiff = fileTime.getTime() - lastFileTime.getTime(); double t = (fileTimeDiff - timeSinceStart) / replaySpeed; return (long) Math.max(t, 0); } private static Date parseDateFromFileName(File file) throws java.text.ParseException { String dateStr = file.getName(); int extIndex = dateStr.lastIndexOf('.'); dateStr = dateStr.substring(0, extIndex); return FlightRepository.ISO8601DATEFORMAT.parse(dateStr); } private static ArrayList<File> toOrdered(File[] files) { ArrayList<File> results = new ArrayList<File>(); for (File f : files) { if (f.getName().endsWith(".json")) { results.add(f); } } Collections.sort(results, new Comparator<File>() { @Override public int compare(File o1, File o2) { return o1.getName().compareTo(o2.getName()); } }); return results; } @Inject public void setFlightRepository(FlightRepository flightRepository) { this.flightRepository = flightRepository; } }