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
  22.             .getName());

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

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

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

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

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

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

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

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

  50.         outputDirectory = new File(
  51.                 config.getProperty(OUTPUT_DIRECTORY_PROPERTY));
  52.         LOGGER.config("[" + getName() + "] output directory = "
  53.                 + outputDirectory);

  54.         String tempDirectoryString = config
  55.                 .getProperty(TEMP_DIRECTORY_PROPERTY);
  56.         if (tempDirectoryString != null) {
  57.             tempDirectory = new File(tempDirectoryString);
  58.         }
  59.         LOGGER.config("[" + getName() + "] temp directory = " + tempDirectory);

  60.         outputFormat = config.getProperty(OUTPUT_FORMAT_PROPERTY,
  61.                 DEFAULT_OUTPUT_FORMAT);
  62.         LOGGER.config("[" + getName() + "] output format = " + outputFormat);
  63.     }

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

  77.     /**
  78.      * Generate an output path based on product id and content path.
  79.      *
  80.      * @param id
  81.      *            the product id.
  82.      * @param path
  83.      *            the content path.
  84.      * @return relative path to write content within output directory.
  85.      */
  86.     protected String getOutputPath(final ProductId id, final String path) {
  87.         return outputFormat
  88.                 .replace("SOURCE", id.getSource())
  89.                 .replace("TYPE", id.getType())
  90.                 .replace("CODE", id.getCode())
  91.                 .replace("UPDATETIME",
  92.                         Long.toString(id.getUpdateTime().getTime()))
  93.                 .replace("PATH", path);
  94.     }

  95.     /**
  96.      * Output a product content that was in includePaths.
  97.      *
  98.      * @param id
  99.      *            the product id.
  100.      * @param path
  101.      *            the content path.
  102.      * @param content
  103.      *            the content.
  104.      * @throws Exception
  105.      *             when unable to output the content.
  106.      */
  107.     protected void writeContent(final ProductId id, final String path,
  108.             final Content content) throws Exception {
  109.         String outputPath = getOutputPath(id, path);
  110.         if (tempDirectory != null && !tempDirectory.exists()) {
  111.             // make sure parent directories exist
  112.             tempDirectory.mkdirs();
  113.         }
  114.         File tempFile = File.createTempFile(outputPath, null, tempDirectory);

  115.         File outputFile = new File(outputDirectory, outputPath);
  116.         File outputFileParent = outputFile.getParentFile();
  117.         if (!outputFileParent.exists()) {
  118.             // make sure parent directories exist
  119.             outputFileParent.mkdirs();
  120.         }

  121.         // write, then move into place
  122.         InputStream in = null;
  123.         OutputStream out = null;
  124.         try {
  125.             if (!tempFile.getParentFile().exists()) {
  126.                 tempFile.getParentFile().mkdirs();
  127.             }
  128.             if (!outputFile.getParentFile().exists()) {
  129.                 outputFile.getParentFile().mkdirs();
  130.             }
  131.             in = content.getInputStream();
  132.             out = StreamUtils.getOutputStream(tempFile);
  133.             // write to temp file
  134.             StreamUtils.transferStream(in, out);
  135.             // move to output file
  136.             tempFile.renameTo(outputFile);
  137.         } finally {
  138.             StreamUtils.closeStream(in);
  139.             StreamUtils.closeStream(out);
  140.             // clean up temp file if it wasn't renamed
  141.             if (tempFile.exists()) {
  142.                 tempFile.delete();
  143.             }
  144.         }
  145.     }

  146.     /**
  147.      * @return the outputDirectory
  148.      */
  149.     public File getOutputDirectory() {
  150.         return outputDirectory;
  151.     }

  152.     /**
  153.      * @param outputDirectory
  154.      *            the outputDirectory to set
  155.      */
  156.     public void setOutputDirectory(File outputDirectory) {
  157.         this.outputDirectory = outputDirectory;
  158.     }

  159.     /**
  160.      * @return the tempDirectory
  161.      */
  162.     public File getTempDirectory() {
  163.         return tempDirectory;
  164.     }

  165.     /**
  166.      * @param tempDirectory
  167.      *            the tempDirectory to set
  168.      */
  169.     public void setTempDirectory(File tempDirectory) {
  170.         this.tempDirectory = tempDirectory;
  171.     }

  172.     /**
  173.      * @return the outputFormat
  174.      */
  175.     public String getOutputFormat() {
  176.         return outputFormat;
  177.     }

  178.     /**
  179.      * @param outputFormat
  180.      *            the outputFormat to set
  181.      */
  182.     public void setOutputFormat(String outputFormat) {
  183.         this.outputFormat = outputFormat;
  184.     }

  185. }