ContentListener.java

  1. package gov.usgs.earthquake.distribution;

  2. import java.io.File;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.util.Iterator;
  6. import java.util.Map;
  7. import java.util.logging.Logger;

  8. import gov.usgs.earthquake.product.Content;
  9. import gov.usgs.earthquake.product.Product;
  10. import gov.usgs.earthquake.product.ProductId;
  11. import gov.usgs.util.Config;
  12. import gov.usgs.util.StreamUtils;

  13. /**
  14.  * A listener that listens for a specific content path.
  15.  *
  16.  * This is intended for users who wish to output specific pieces of product
  17.  * content, such as "quakeml.xml", for products that otherwise meet their
  18.  * configured NotificationListener criteria.
  19.  */
  20. public class ContentListener extends DefaultNotificationListener {

  21.   private static final Logger LOGGER = Logger.getLogger(ContentListener.class.getName());

  22.   /** configuration property for includePaths - output directory. */
  23.   public static final String OUTPUT_DIRECTORY_PROPERTY = "outputDirectory";
  24.   /** property for temporary directory */
  25.   public static final String TEMP_DIRECTORY_PROPERTY = "tempDirectory";
  26.   /** property for output format */
  27.   public static final String OUTPUT_FORMAT_PROPERTY = "outputFormat";

  28.   /** property for default output format */
  29.   public static final String DEFAULT_OUTPUT_FORMAT = "SOURCE_TYPE_CODE_UPDATETIME_PATH";

  30.   /** Directory where content is output. */
  31.   private File outputDirectory = null;

  32.   /**
  33.    * Temporary directory where content is written before moving to
  34.    * outputDirectory, defaults to system temp directory when null.
  35.    */
  36.   private File tempDirectory = null;

  37.   /** Output format for files inside outputDirectory. */
  38.   private String outputFormat = DEFAULT_OUTPUT_FORMAT;

  39.   /** empty constructor for ContentListener */
  40.   public ContentListener() {
  41.   }

  42.   @Override
  43.   public void configure(final Config config) throws Exception {
  44.     super.configure(config);

  45.     if (getIncludePaths().size() == 0) {
  46.       throw new ConfigurationException("[" + getName() + "] ContentListener requires 'includePaths' be non-empty");
  47.     }

  48.     outputDirectory = new File(config.getProperty(OUTPUT_DIRECTORY_PROPERTY));
  49.     LOGGER.config("[" + getName() + "] output directory = " + outputDirectory);

  50.     String tempDirectoryString = config.getProperty(TEMP_DIRECTORY_PROPERTY);
  51.     if (tempDirectoryString != null) {
  52.       tempDirectory = new File(tempDirectoryString);
  53.     }
  54.     LOGGER.config("[" + getName() + "] temp directory = " + tempDirectory);

  55.     outputFormat = config.getProperty(OUTPUT_FORMAT_PROPERTY, DEFAULT_OUTPUT_FORMAT);
  56.     LOGGER.config("[" + getName() + "] output format = " + outputFormat);
  57.   }

  58.   @Override
  59.   public void onProduct(final Product product) throws Exception {
  60.     Map<String, Content> contents = product.getContents();
  61.     Iterator<String> iter = getIncludePaths().iterator();
  62.     while (iter.hasNext()) {
  63.       String path = iter.next();
  64.       Content content = contents.get(path);
  65.       if (content != null) {
  66.         // product has content at this path
  67.         writeContent(product.getId(), path, content);
  68.       }
  69.     }
  70.   }

  71.   /**
  72.    * Generate an output path based on product id and content path.
  73.    *
  74.    * @param id   the product id.
  75.    * @param path the content path.
  76.    * @return relative path to write content within output directory.
  77.    */
  78.   protected String getOutputPath(final ProductId id, final String path) {
  79.     return outputFormat.replace("SOURCE", id.getSource()).replace("TYPE", id.getType()).replace("CODE", id.getCode())
  80.         .replace("UPDATETIME", Long.toString(id.getUpdateTime().getTime())).replace("PATH", path);
  81.   }

  82.   /**
  83.    * Output a product content that was in includePaths.
  84.    *
  85.    * @param id      the product id.
  86.    * @param path    the content path.
  87.    * @param content the content.
  88.    * @throws Exception when unable to output the content.
  89.    */
  90.   protected void writeContent(final ProductId id, final String path, final Content content) throws Exception {
  91.     String outputPath = getOutputPath(id, path);
  92.     if (tempDirectory != null && !tempDirectory.exists()) {
  93.       // make sure parent directories exist
  94.       tempDirectory.mkdirs();
  95.     }
  96.     File tempFile = File.createTempFile(outputPath, null, tempDirectory);

  97.     File outputFile = new File(outputDirectory, outputPath);
  98.     File outputFileParent = outputFile.getParentFile();
  99.     if (!outputFileParent.exists()) {
  100.       // make sure parent directories exist
  101.       outputFileParent.mkdirs();
  102.     }

  103.     // write, then move into place
  104.     InputStream in = null;
  105.     OutputStream out = null;
  106.     try {
  107.       if (!tempFile.getParentFile().exists()) {
  108.         tempFile.getParentFile().mkdirs();
  109.       }
  110.       if (!outputFile.getParentFile().exists()) {
  111.         outputFile.getParentFile().mkdirs();
  112.       }
  113.       in = content.getInputStream();
  114.       out = StreamUtils.getOutputStream(tempFile);
  115.       // write to temp file
  116.       StreamUtils.transferStream(in, out);
  117.       // move to output file
  118.       tempFile.renameTo(outputFile);
  119.     } finally {
  120.       StreamUtils.closeStream(in);
  121.       StreamUtils.closeStream(out);
  122.       // clean up temp file if it wasn't renamed
  123.       if (tempFile.exists()) {
  124.         tempFile.delete();
  125.       }
  126.     }
  127.   }

  128.   /**
  129.    * @return the outputDirectory
  130.    */
  131.   public File getOutputDirectory() {
  132.     return outputDirectory;
  133.   }

  134.   /**
  135.    * @param outputDirectory the outputDirectory to set
  136.    */
  137.   public void setOutputDirectory(File outputDirectory) {
  138.     this.outputDirectory = outputDirectory;
  139.   }

  140.   /**
  141.    * @return the tempDirectory
  142.    */
  143.   public File getTempDirectory() {
  144.     return tempDirectory;
  145.   }

  146.   /**
  147.    * @param tempDirectory the tempDirectory to set
  148.    */
  149.   public void setTempDirectory(File tempDirectory) {
  150.     this.tempDirectory = tempDirectory;
  151.   }

  152.   /**
  153.    * @return the outputFormat
  154.    */
  155.   public String getOutputFormat() {
  156.     return outputFormat;
  157.   }

  158.   /**
  159.    * @param outputFormat the outputFormat to set
  160.    */
  161.   public void setOutputFormat(String outputFormat) {
  162.     this.outputFormat = outputFormat;
  163.   }

  164. }