Package com.wesabe.grendel.entities

Source Code of com.wesabe.grendel.entities.Document

package com.wesabe.grendel.entities;

import static com.google.common.base.Objects.*;

import java.io.Serializable;
import java.security.SecureRandom;
import java.util.Set;

import javax.persistence.*;
import javax.ws.rs.core.MediaType;

import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import com.google.common.collect.Sets;
import com.wesabe.grendel.openpgp.CryptographicException;
import com.wesabe.grendel.openpgp.KeySet;
import com.wesabe.grendel.openpgp.MessageReader;
import com.wesabe.grendel.openpgp.MessageWriter;
import com.wesabe.grendel.openpgp.UnlockedKeySet;
import com.wesabe.grendel.util.HashCode;

/**
* A document with an abritrary body, stored as an encrypted+signed OpenPGP
* message.
*
* @author coda
*/
@Entity
@Table(name="documents")
@IdClass(DocumentPK.class)
@NamedQueries({
  @NamedQuery(
    name="com.wesabe.grendel.entities.Document.ByOwnerAndName",
    query="SELECT d FROM Document AS d WHERE d.name = :name AND d.owner = :owner"
  )
})
public class Document implements Serializable {
  private static final long serialVersionUID = 5699449595549234402L;

  @Id
  private String name;
 
  @Id
  private User owner;
 
  @Column(name="content_type", nullable=false, length=40)
  private String contentType;
 
  @Column(name="body", nullable=false)
  @Lob
  private byte[] body;
 
  @Column(name="created_at", nullable=false)
  @Type(type="org.joda.time.contrib.hibernate.PersistentDateTime")
  private DateTime createdAt;
 
  @Column(name="modified_at", nullable=false)
  @Type(type="org.joda.time.contrib.hibernate.PersistentDateTime")
  private DateTime modifiedAt;
 
  @ManyToMany(fetch=FetchType.LAZY, mappedBy="linkedDocuments", cascade={CascadeType.ALL})
  @JoinTable(name="links")
  private Set<User> linkedUsers = Sets.newHashSet();
 
  @Version
  @Column(name="version", nullable=false)
  private long version = 0;
 
  @Deprecated
  public Document() {
    // for Hibernate usage only
  }
 
  /**
   * Creates a new {@link Document}, owned by the given {@link User} and with
   * the given name.
   *
   * @param owner the new document's owner
   * @param name the new document's name
   * @param contentType the document's content type
   */
  public Document(User owner, String name, MediaType contentType) {
    this.owner = owner;
    this.name = name;
    this.contentType = contentType.toString();
   
    this.createdAt = new DateTime(DateTimeZone.UTC);
    this.modifiedAt = new DateTime(DateTimeZone.UTC);
  }
 
  /**
   * Returns the document's owner.
   */
  public User getOwner() {
    return owner;
  }
 
  /**
   * Returns the document's name.
   */
  public String getName() {
    return name;
  }
 
  /**
   * Returns a set of {@link User}s who have read-only access to this
   * document.
   */
  public Set<User> getLinkedUsers() {
    return linkedUsers;
  }
 
  /**
   * Provide a {@link User} with read-only access to this document.
   */
  public void linkUser(User user) {
    linkedUsers.add(user);
    user.getLinkedDocuments().add(this);
  }
 
  /**
   * Remove a {@link User}'s read-only access to this document.
   */
  public void unlinkUser(User user) {
    linkedUsers.remove(user);
    user.getLinkedDocuments().remove(this);
  }
 
  /**
   * Returns {@code true} if the given {@link User} has read-only access to
   * this document.
   */
  public boolean isLinked(User user) {
    return linkedUsers.contains(user);
  }
 
  /**
   * Returns the document's content type.
   */
  public MediaType getContentType() {
    return MediaType.valueOf(contentType);
  }
 
  /**
   * Returns a UTC timestamp of when this document was created.
   */
  public DateTime getCreatedAt() {
    return toUTC(createdAt);
  }
 
  /**
   * Sets a UTC timestamp of when this document was created.
   */
  public void setCreatedAt(DateTime createdAt) {
    this.createdAt = toUTC(createdAt);
  }
 
  /**
   * Returns a UTC timestamp of when this document was last modified.
   */
  public DateTime getModifiedAt() {
    return toUTC(modifiedAt);
  }
 
  /**
   * Sets a UTC timestamp of when this document was last modified.
   */
  public void setModifiedAt(DateTime modifiedAt) {
    this.modifiedAt = toUTC(modifiedAt);
  }
 
  /**
   * Sets the {@link Document}'s body to an encrypted+signed OpenPGP message
   * containing {@code body}.
   *
   * @param keySet
   *            the {@link UnlockedKeySet} of the {@link User} that owns this
   *            {@link Document}
   * @param random
   *            a {@link SecureRandom} instance
   * @param body
   *            the unencrypted document body
   * @throws CryptographicException
   *             if the owner's {@link KeySet} cannot be unlocked with {@code
   *             ownerPassphrase}
   * @see MessageWriter
   */
  public void encryptAndSetBody(UnlockedKeySet keySet, SecureRandom random,
    byte[] body) throws CryptographicException {
   
    final Set<KeySet> recipients = Sets.newHashSetWithExpectedSize(linkedUsers.size());
    for (User linkedUser : linkedUsers) {
      recipients.add(linkedUser.getKeySet());
    }
   
    final MessageWriter writer = new MessageWriter(keySet, recipients, random);
    this.body = writer.write(body);
  }
 
  /**
   * Decrypts the document's body using the {@link UnlockedKeySet} of the
   * owner or a recipient;
   *
   * @param unlockedKeySet
   *             an {@link UnlockedKeySet} belonging to either the
   *             {@link Document}'s owner or a recipient
   * @return the decrypted document body
   * @throws CryptographicException
   *             if there is an error decrypting and verifying the
   *             encrypted+signed OpenPGP message
   * @see MessageReader
   */
  public byte[] decryptBody(UnlockedKeySet unlockedKeySet) throws CryptographicException {
    final MessageReader reader = new MessageReader(owner.getKeySet(), unlockedKeySet);
    return reader.read(body);
  }
 
  private DateTime toUTC(DateTime dateTime) {
    return dateTime.toDateTime(DateTimeZone.UTC);
  }

  @Override
  public int hashCode() {
    return HashCode.calculate(
      getClass(), body, contentType, createdAt, modifiedAt, name, owner
    );
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
   
    if (!(obj instanceof Document)) {
      return false;
    }
   
    final Document that = (Document) obj;
    return equal(name, that.name) && equal(owner, that.owner) &&
        equal(body, that.body) && equal(createdAt, that.createdAt) &&
        equal(contentType, that.contentType) &&
        equal(modifiedAt, that.modifiedAt);
  }
 
  @Override
  public String toString() {
    return name;
  }
 
  /**
   * Returns an opaque string indicating the {@link Document}'s name and
   * version.
   */
  public String getEtag() {
    return new StringBuilder("doc-").append(name).append('-').append(version).toString();
  }
}
TOP

Related Classes of com.wesabe.grendel.entities.Document

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.