AbstractContent.java
/*
* AbstractContent
*/
package gov.usgs.earthquake.product;
import java.io.OutputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.Date;
import gov.usgs.earthquake.util.NullOutputStream;
import gov.usgs.util.StreamUtils;
/**
* AbstractContent is a base class for other content classes and implements
* common functionality.
*/
public abstract class AbstractContent implements Content {
/** The content mime type. */
private String contentType;
/** When this content was created. */
private Date lastModified;
/** How much content there is. */
private Long length;
/** Base64 encoded hash of content */
String sha256;
/**
* Null values are replaced with defaults.
*
* @param contentType
* defaults to "text/plain".
* @param lastModified
* defaults to new Date().
* @param length
* defaults to -1L.
*/
public AbstractContent(final String contentType, final Date lastModified,
final Long length) {
setContentType(contentType);
setLastModified(lastModified);
setLength(length);
}
/**
* Copy constructor from another content.
*
* @param content
* the content to copy.
*/
public AbstractContent(final Content content) {
this(content.getContentType(), content.getLastModified(), content
.getLength());
}
/**
* Default Constructor which requires no arguments. Default values are used
* for all fields.
*/
public AbstractContent() {
this(null, null, null);
}
/**
* @return the content mime type.
*/
public String getContentType() {
return contentType;
}
/**
* Set the content mime type.
*
* @param contentType
* the content mime type.
*/
public void setContentType(final String contentType) {
if (contentType == null) {
this.contentType = "text/plain";
} else {
this.contentType = contentType;
}
}
/**
* @return the content creation date.
*/
public Date getLastModified() {
return lastModified;
}
/**
* Set when this content was created.
*
* @param lastModified
* when this content was created.
*/
public void setLastModified(final Date lastModified) {
if (lastModified == null) {
this.lastModified = new Date();
} else {
this.lastModified = new Date(lastModified.getTime());
}
// Round to nearest second. Some file systems do not preserve
// milliseconds.
this.lastModified
.setTime((this.lastModified.getTime() / 1000L) * 1000L);
}
/**
* @return the content length, or -1 if unknown.
*/
public Long getLength() {
return length;
}
/**
* Set the content length.
*
* @param length long to set
*/
public void setLength(final Long length) {
if (length == null) {
this.length = -1L;
} else {
this.length = length;
}
}
/** Get the Sha256 hash. */
@Override
public String getSha256() throws Exception {
return getSha256(true);
}
/**
* Get or generate the MD5 hash of content.
*
* @param computeIfMissing Use getInputStream to generate hash if missing.
* @return sha256 string
* @throws Exception if error occurs
*/
public String getSha256(final boolean computeIfMissing) throws Exception {
if (sha256 == null && computeIfMissing) {
try (final DigestOutputStream contentDigest =
new DigestOutputStream(new NullOutputStream(), MessageDigest.getInstance("SHA-256"));
final OutputStream unclosable = new StreamUtils.UnclosableOutputStream(contentDigest)) {
StreamUtils.transferStream(this.getInputStream(), unclosable);
contentDigest.flush();
setSha256(Base64.getEncoder().encodeToString(contentDigest.getMessageDigest().digest()));
}
}
return sha256;
}
/**
* Set the sha256 hash of content.
*
* @param sha256 to set
*/
public void setSha256(final String sha256) {
this.sha256 = sha256;
}
}