BinaryProductHandler.java

  1. package gov.usgs.earthquake.product.io;

  2. import gov.usgs.earthquake.product.ByteContent;
  3. import gov.usgs.earthquake.product.Content;
  4. import gov.usgs.earthquake.product.ProductId;
  5. import gov.usgs.util.StreamUtils;
  6. import gov.usgs.util.CryptoUtils.Version;

  7. import java.io.InputStream;
  8. import java.io.OutputStream;
  9. import java.net.URI;
  10. import java.net.URL;

  11. /**
  12.  * Generator of binary format for product data.
  13.  *
  14.  * Binary representation of data types:
  15.  * <dl>
  16.  * <dt>Integer</dt>
  17.  * <dd>4-bytes</dd>
  18.  * <dt>Long</dt>
  19.  * <dd>8-bytes</dd>
  20.  * <dt>Date</dt>
  21.  * <dd>Long (Date.getTime())</dd>
  22.  * <dt>byte[]</dt>
  23.  * <dd>Integer length, raw bytes</dd>
  24.  * <dt>String</dt>
  25.  * <dd>byte[] (String.getBytes(StandardCharsets.UTF_8))</dd>
  26.  * <dt>URL/URI</dt>
  27.  * <dd>String (URL.toString())</dd>
  28.  * </dl>
  29.  *
  30.  *
  31.  * Product is stored in this order:
  32.  *
  33.  * <ol>
  34.  *
  35.  * <li>Header, exactly 1
  36.  * <ol>
  37.  * <li>"BEGINPRODUCT" (string)</li>
  38.  * <li>ProductId (String)</li>
  39.  * <li>Status (String)</li>
  40.  * <li>TrackerURL (URL)</li>
  41.  * </ol>
  42.  * </li>
  43.  *
  44.  * <li>Properties, 0 to many:
  45.  * <ol>
  46.  * <li>"PROPERTY" (String)</li>
  47.  * <li>name (String)</li>
  48.  * <li>value (String)</li>
  49.  * </ol>
  50.  * </li>
  51.  *
  52.  * <li>Links, 0 to many:
  53.  * <ol>
  54.  * <li>"LINK" (String)</li>
  55.  * <li>relation (String)</li>
  56.  * <li>href (URI)</li>
  57.  * </ol>
  58.  * </li>
  59.  *
  60.  * <li>Contents, 0 to many:
  61.  * <ol>
  62.  * <li>"CONTENT" (String)</li>
  63.  * <li>path (String)</li>
  64.  * <li>contentType (String)</li>
  65.  * <li>lastModified (Date)</li>
  66.  * <li>length (Long)</li>
  67.  * <li>raw bytes</li>
  68.  * </ol>
  69.  * </li>
  70.  *
  71.  * <li>Signature Version, 0 or 1.
  72.  * <em>Note, only sent when version != SIGNATURE_V1 for backward compatibility</em>
  73.  * <ol>
  74.  * <li>"SIGNATUREVERSION" (String)</li>
  75.  * <li>version (String)</li>
  76.  * </ol>
  77.  * </li>
  78.  *
  79.  * <li>Signature, 0 or 1:
  80.  * <ol>
  81.  * <li>"SIGNATURE" (String)</li>
  82.  * <li>signature (String)</li>
  83.  * </ol>
  84.  * </li>
  85.  *
  86.  * <li>Footer, exactly 1:
  87.  * <ol>
  88.  * <li>"ENDPRODUCT" (String)</li>
  89.  * </ol>
  90.  * </li>
  91.  *
  92.  * </ol>
  93.  */
  94. public class BinaryProductHandler implements ProductHandler {

  95.     /** HEADER - BEGINPRODUCT */
  96.     public static final String HEADER = "BEGINPRODUCT";
  97.     /** PROPERTY */
  98.     public static final String PROPERTY = "PROPERTY";
  99.     /** LINK */
  100.     public static final String LINK = "LINK";
  101.     /** CONTENT */
  102.     public static final String CONTENT = "CONTENT";
  103.     /** SIGNATURE VERSION */
  104.     public static final String SIGNATUREVERSION = "SIGNATUREVERSION";
  105.     /** SIGNATURE */
  106.     public static final String SIGNATURE = "SIGNATURE";
  107.     /** ENDPRODUCT */
  108.     public static final String FOOTER = "ENDPRODUCT";

  109.     private OutputStream out;
  110.     private BinaryIO io;

  111.     /**
  112.      * Constructor. Sets up a new BinaryIO
  113.      * @param out an OutputStream
  114.      */
  115.     public BinaryProductHandler(final OutputStream out) {
  116.         this.out = out;
  117.         this.io = new BinaryIO();
  118.     }

  119.     @Override
  120.     public void onBeginProduct(ProductId id, String status, URL trackerURL)
  121.             throws Exception {
  122.         io.writeString(HEADER, out);
  123.         io.writeString(id.toString(), out);
  124.         io.writeString(status, out);
  125.         // allow trackerURL to be null
  126.         if (trackerURL == null) {
  127.             io.writeString("null", out);
  128.         } else {
  129.             io.writeString(trackerURL.toString(), out);
  130.         }
  131.     }

  132.     @Override
  133.     public void onProperty(ProductId id, String name, String value)
  134.             throws Exception {
  135.         io.writeString(PROPERTY, out);
  136.         io.writeString(name, out);
  137.         io.writeString(value, out);
  138.     }

  139.     @Override
  140.     public void onLink(ProductId id, String relation, URI href)
  141.             throws Exception {
  142.         io.writeString(LINK, out);
  143.         io.writeString(relation, out);
  144.         io.writeString(href.toString(), out);
  145.     }

  146.     @Override
  147.     public void onContent(ProductId id, String path, Content content)
  148.             throws Exception {
  149.         if (content.getLength() == null || content.getLength() < 0) {
  150.             // binary io only handles streams with length, convert to content
  151.             // with length
  152.             content = new ByteContent(content);
  153.         }

  154.         io.writeString(CONTENT, out);
  155.         io.writeString(path, out);

  156.         io.writeString(content.getContentType(), out);
  157.         io.writeDate(content.getLastModified(), out);
  158.         InputStream contentInputStream = content.getInputStream();
  159.         try {
  160.             io.writeStream(content.getLength().longValue(), contentInputStream, out);
  161.         } finally {
  162.             StreamUtils.closeStream(contentInputStream);
  163.         }
  164.     }

  165.     @Override
  166.     public void onSignatureVersion(ProductId id, Version version) throws Exception {
  167.         if (version != Version.SIGNATURE_V1) {
  168.             io.writeString(SIGNATUREVERSION, out);
  169.             io.writeString(version.toString(), out);
  170.         }
  171.     }

  172.     @Override
  173.     public void onSignature(ProductId id, String signature) throws Exception {
  174.         // allow signature to be null
  175.         if (signature == null) {
  176.             return;
  177.         }

  178.         io.writeString(SIGNATURE, out);
  179.         io.writeString(signature, out);
  180.     }

  181.     @Override
  182.     public void onEndProduct(ProductId id) throws Exception {
  183.         io.writeString(FOOTER, out);

  184.         out.flush();
  185.         out.close();
  186.     }

  187.     /**
  188.      * Free any resources associated with this source.
  189.      */
  190.     @Override
  191.     public void close() {
  192.         StreamUtils.closeStream(out);
  193.         out = null;
  194.     }

  195. }