package play.modules.s3blobs; import java.io.InputStream; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.StringType; import org.hibernate.usertype.UserType; import play.db.Model.BinaryField; import play.libs.Codec; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.S3Object; public class S3Blob implements BinaryField, UserType, Serializable { static String s3Bucket; static AmazonS3 s3Client; static boolean serverSideEncryption; private String bucket; private String key; private long contentLength; private String keyPrefix; public S3Blob() { } public S3Blob(String keyPrefix) { this.keyPrefix = keyPrefix; } public S3Blob(long contentLength) { this.contentLength = contentLength; } public S3Blob(String keyPrefix, long contentLength) { this.keyPrefix = keyPrefix; this.contentLength = contentLength; } private S3Blob(String bucket, String s3Key) { this.bucket = bucket; this.key = s3Key; } @Override public InputStream get() { S3Object s3Object = s3Client.getObject(bucket, key); return s3Object.getObjectContent(); } @Override public void set(InputStream is, String type) { this.bucket = s3Bucket; this.key = (keyPrefix != null ? keyPrefix : "") + Codec.UUID(); ObjectMetadata om = new ObjectMetadata(); om.setContentType(type); if (contentLength != 0) { om.setContentLength(contentLength); } if (serverSideEncryption) { om.setServerSideEncryption(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION); } s3Client.putObject(bucket, key, is, om); } public void delete () { s3Client.deleteObject(s3Bucket, key); } @Override public long length() { ObjectMetadata om = s3Client.getObjectMetadata(bucket, key); return om.getContentLength(); } @Override public String type() { ObjectMetadata om = s3Client.getObjectMetadata(bucket, key); return om.getContentType(); } @Override public boolean exists() { if (bucket == null || bucket.isEmpty() || key == null || key.isEmpty()) { return false; } ObjectMetadata om = s3Client.getObjectMetadata(bucket, key); return om != null; } @Override public int[] sqlTypes() { return new int[] { Types.VARCHAR }; } @Override public Class returnedClass() { return S3Blob.class; } @Override public boolean equals(Object o, Object o1) throws HibernateException { return o == null ? false : o.equals(o1); } @Override public int hashCode(Object o) throws HibernateException { return o.hashCode(); } @Override public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor sessionImplementor, Object o) throws HibernateException, SQLException { String val = StringType.INSTANCE.nullSafeGet(rs, names[0], sessionImplementor); if (val == null || val.length() == 0 || !val.contains("|")) { return new S3Blob(); } return new S3Blob(val.split("[|]")[0], val.split("[|]")[1]); } @Override public void nullSafeSet(PreparedStatement ps, Object o, int i, SessionImplementor sessionImplementor) throws HibernateException, SQLException { if (o != null) { ps.setString(i, ((S3Blob) o).bucket + "|" + ((S3Blob) o).key); } else { ps.setNull(i, Types.VARCHAR); } } @Override public Object deepCopy(Object o) throws HibernateException { if (o == null) { return null; } return new S3Blob(this.bucket, this.key); } @Override public boolean isMutable() { return true; } @Override public Serializable disassemble(Object o) throws HibernateException { throw new UnsupportedOperationException("Not supported yet."); } @Override public Object assemble(Serializable srlzbl, Object o) throws HibernateException { throw new UnsupportedOperationException("Not supported yet."); } @Override public Object replace(Object o, Object o1, Object o2) throws HibernateException { throw new UnsupportedOperationException("Not supported yet."); } }