FileTrackingListener.java

  1. package gov.usgs.earthquake.aws;

  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.util.Base64;
  5. import java.util.logging.Level;
  6. import java.util.logging.Logger;

  7. import javax.json.Json;
  8. import javax.json.JsonObject;
  9. import javax.naming.ConfigurationException;

  10. import gov.usgs.earthquake.distribution.NotificationEvent;
  11. import gov.usgs.earthquake.distribution.NotificationListener;
  12. import gov.usgs.util.Config;
  13. import gov.usgs.util.DefaultConfigurable;
  14. import gov.usgs.util.FileUtils;
  15. import gov.usgs.util.StreamUtils;

  16. /**
  17.  * This class is a stop-gap to store file-based tracking information in a
  18.  * TrackingIndex.
  19.  *
  20.  * It implements the NotificationListener interface so it can hook into
  21.  * startup/shutdown lifecycle calls used by ProductClient.  Listeners are
  22.  * started before and shutdown after Receivers, and can put a tracking file
  23.  * in place before the receiver starts and save its state after a receiver stops.
  24.  */
  25. public class FileTrackingListener extends DefaultConfigurable implements NotificationListener {

  26.   /** Initialzation of logger. For us later in file. */
  27.   private static final Logger LOGGER = Logger.getLogger(FileTrackingListener.class.getName());

  28.   /** Tracking index property */
  29.   public static final String TRACKING_INDEX_PROPERTY = "trackingIndex";
  30.   /** Tracking index file property */
  31.   public static final String TRACKING_INDEX_FILE_PROPERTY = "trackingIndexFile";

  32.   /** Tracking file property */
  33.   public static final String TRACKING_FILE_PROEPRTY = "trackingFile";

  34.   /** File being tracked. */
  35.   private File trackingFile;
  36.   /** Tracking Index where contents are stored */
  37.   private TrackingIndex trackingIndex;

  38.   /** FileTrackingListener constructor */
  39.   public FileTrackingListener() {
  40.   }

  41.   /** Initializable FileTrackingListener
  42.    * @param trackingFile file to be traacked
  43.    * @param trackingIndex Index where contents are stored
  44.    */
  45.   public FileTrackingListener(final File trackingFile, final TrackingIndex trackingIndex) {
  46.     this.trackingFile = trackingFile;
  47.     this.trackingIndex = trackingIndex;
  48.   }

  49.   /** Getter for trackingFile
  50.    * @return trackingFile
  51.    */
  52.   public File getTrackingFile() { return this.trackingFile; }

  53.   /** Setter for trackingFile
  54.    * @param trackingFile File to be tracked
  55.    */
  56.   public void setTrackingFile(final File trackingFile) {
  57.     this.trackingFile = trackingFile;
  58.   }

  59.   /** Getter for trackingIndex
  60.    * @return trackingIndex
  61.    */
  62.   public TrackingIndex getTrackingIndex() { return this.trackingIndex; }

  63.   /** Setter for trackingIndex
  64.    * @param trackingIndex Index where contents are stored
  65.    */
  66.   public void setTrackingIndex(final TrackingIndex trackingIndex) {
  67.     this.trackingIndex = trackingIndex;
  68.   }

  69.   @Override
  70.   public void configure(Config config) throws Exception {
  71.     super.configure(config);

  72.     // configure tracking index
  73.     final String trackingIndexName = config.getProperty(TRACKING_INDEX_PROPERTY);
  74.     if (trackingIndexName != null) {
  75.       LOGGER.config("[" + getName() + "] loading tracking index "
  76.           + trackingIndexName);
  77.       try {
  78.         // read object from global config
  79.         trackingIndex = (TrackingIndex) Config.getConfig().getObject(trackingIndexName);
  80.       } catch (Exception e) {
  81.         LOGGER.log(
  82.             Level.WARNING,
  83.             "[" + getName() + "] error loading tracking index "
  84.                 + trackingIndexName,
  85.             e);
  86.       }
  87.     } else {
  88.       final String trackingIndexFileName = config.getProperty(TRACKING_INDEX_FILE_PROPERTY);
  89.       if (trackingIndexFileName != null) {
  90.         LOGGER.config("[" + getName() + "] creating tracking index at"
  91.             + trackingIndexFileName);
  92.         trackingIndex = new TrackingIndex(
  93.             TrackingIndex.DEFAULT_DRIVER,
  94.             "jdbc:sqlite:" + trackingIndexFileName);
  95.       }
  96.     }

  97.     // configure tracking file
  98.     final String trackingFileName = config.getProperty(TRACKING_FILE_PROEPRTY);
  99.     if (trackingFileName == null) {
  100.       throw new ConfigurationException(TRACKING_FILE_PROEPRTY + " is required");
  101.     }
  102.     trackingFile = new File(trackingFileName);
  103.   }

  104.   /**
  105.    * When starting, call loadTrackingFile to create/update file on disk.
  106.    */
  107.   @Override
  108.   public void startup() throws Exception {
  109.     super.startup();
  110.     trackingIndex.startup();
  111.     loadTrackingFile();
  112.   }

  113.   /**
  114.    * When shutting down, call storeTrackingFile to read from file on disk.
  115.    */
  116.   @Override
  117.   public void shutdown() throws Exception {
  118.     storeTrackingFile();
  119.     trackingIndex.shutdown();
  120.     super.shutdown();
  121.   }

  122.   /**
  123.    * Read trackingIndex and write trackingFile.
  124.    *
  125.    * @throws Exception Exception
  126.    */
  127.   public void loadTrackingFile() throws Exception {
  128.     final String name = trackingFile.getAbsolutePath();
  129.     final JsonObject trackingData = trackingIndex.getTrackingData(name);
  130.     if (trackingData == null) {
  131.       LOGGER.info("[" + getName() + "] tracking data not found in index, ignoring");
  132.       return;
  133.     }
  134.     final byte[] data = Base64.getDecoder().decode(trackingData.getString("data"));
  135.     FileUtils.writeFile(trackingFile, data);
  136.   }

  137.   /**
  138.    * Read trackingFile and write into trackingIndex.
  139.    *
  140.    * @throws Exception Exception
  141.    */
  142.   public void storeTrackingFile() throws Exception {
  143.     try {
  144.       // use absolute path as name
  145.       final String name = trackingFile.getAbsolutePath();
  146.       final byte[] data = StreamUtils.readStream(trackingFile);
  147.       final JsonObject trackingData = Json.createObjectBuilder()
  148.           .add("name", name)
  149.           .add("data", Base64.getEncoder().encodeToString(data))
  150.           .build();
  151.       trackingIndex.setTrackingData(trackingFile.getAbsolutePath(), trackingData);
  152.     } catch (FileNotFoundException fnf) {
  153.       LOGGER.info("[" + getName() + "] tracking file not found, ignoring");
  154.     }
  155.   }

  156.   /**
  157.    * Notification Listener method stubs.
  158.    * These are used only to gain access to lifecycle hooks above.
  159.    */

  160.   @Override
  161.   public void onNotification(NotificationEvent event) throws Exception {
  162.     // ignore
  163.   }

  164.   @Override
  165.   public int getMaxTries() {
  166.     return 1;
  167.   }

  168.   @Override
  169.   public long getTimeout() {
  170.     return 1;
  171.   }
  172. }