AbstractContent.java

  1. /*
  2.  * AbstractContent
  3.  */
  4. package gov.usgs.earthquake.product;

  5. import java.io.OutputStream;
  6. import java.security.DigestOutputStream;
  7. import java.security.MessageDigest;
  8. import java.util.Base64;
  9. import java.util.Date;

  10. import gov.usgs.earthquake.util.NullOutputStream;
  11. import gov.usgs.util.StreamUtils;

  12. /**
  13.  * AbstractContent is a base class for other content classes and implements
  14.  * common functionality.
  15.  */
  16. public abstract class AbstractContent implements Content {

  17.     /** The content mime type. */
  18.     private String contentType;

  19.     /** When this content was created. */
  20.     private Date lastModified;

  21.     /** How much content there is. */
  22.     private Long length;

  23.     /** Base64 encoded hash of content */
  24.     String sha256;

  25.     /**
  26.      * Null values are replaced with defaults.
  27.      *
  28.      * @param contentType
  29.      *            defaults to "text/plain".
  30.      * @param lastModified
  31.      *            defaults to new Date().
  32.      * @param length
  33.      *            defaults to -1L.
  34.      */
  35.     public AbstractContent(final String contentType, final Date lastModified,
  36.             final Long length) {
  37.         setContentType(contentType);
  38.         setLastModified(lastModified);
  39.         setLength(length);
  40.     }

  41.     /**
  42.      * Copy constructor from another content.
  43.      *
  44.      * @param content
  45.      *            the content to copy.
  46.      */
  47.     public AbstractContent(final Content content) {
  48.         this(content.getContentType(), content.getLastModified(), content
  49.                 .getLength());
  50.     }

  51.     /**
  52.      * Default Constructor which requires no arguments. Default values are used
  53.      * for all fields.
  54.      */
  55.     public AbstractContent() {
  56.         this(null, null, null);
  57.     }

  58.     /**
  59.      * @return the content mime type.
  60.      */
  61.     public String getContentType() {
  62.         return contentType;
  63.     }

  64.     /**
  65.      * Set the content mime type.
  66.      *
  67.      * @param contentType
  68.      *            the content mime type.
  69.      */
  70.     public void setContentType(final String contentType) {
  71.         if (contentType == null) {
  72.             this.contentType = "text/plain";
  73.         } else {
  74.             this.contentType = contentType;
  75.         }
  76.     }

  77.     /**
  78.      * @return the content creation date.
  79.      */
  80.     public Date getLastModified() {
  81.         return lastModified;
  82.     }

  83.     /**
  84.      * Set when this content was created.
  85.      *
  86.      * @param lastModified
  87.      *            when this content was created.
  88.      */
  89.     public void setLastModified(final Date lastModified) {
  90.         if (lastModified == null) {
  91.             this.lastModified = new Date();
  92.         } else {
  93.             this.lastModified = new Date(lastModified.getTime());
  94.         }

  95.         // Round to nearest second. Some file systems do not preserve
  96.         // milliseconds.
  97.         this.lastModified
  98.                 .setTime((this.lastModified.getTime() / 1000L) * 1000L);
  99.     }

  100.     /**
  101.      * @return the content length, or -1 if unknown.
  102.      */
  103.     public Long getLength() {
  104.         return length;
  105.     }

  106.     /**
  107.      * Set the content length.
  108.      *
  109.      * @param length long to set
  110.      */
  111.     public void setLength(final Long length) {
  112.         if (length == null) {
  113.             this.length = -1L;
  114.         } else {
  115.             this.length = length;
  116.         }
  117.     }


  118.     /** Get the Sha256 hash. */
  119.     @Override
  120.     public String getSha256() throws Exception {
  121.         return getSha256(true);
  122.     }

  123.     /**
  124.      * Get or generate the MD5 hash of content.
  125.      *
  126.      * @param computeIfMissing Use getInputStream to generate hash if missing.
  127.      * @return sha256 string
  128.      * @throws Exception if error occurs
  129.      */
  130.     public String getSha256(final boolean computeIfMissing) throws Exception {
  131.         if (sha256 == null && computeIfMissing) {
  132.             try (final DigestOutputStream contentDigest =
  133.                             new DigestOutputStream(new NullOutputStream(), MessageDigest.getInstance("SHA-256"));
  134.                     final OutputStream unclosable = new StreamUtils.UnclosableOutputStream(contentDigest)) {
  135.                 StreamUtils.transferStream(this.getInputStream(), unclosable);
  136.                 contentDigest.flush();
  137.                 setSha256(Base64.getEncoder().encodeToString(contentDigest.getMessageDigest().digest()));
  138.             }
  139.         }
  140.         return sha256;
  141.     }

  142.     /**
  143.      * Set the sha256 hash of content.
  144.      *
  145.      * @param sha256 to set
  146.      */
  147.     public void setSha256(final String sha256) {
  148.         this.sha256 = sha256;
  149.     }
  150. }