Package cave.nice.testMessage.data

Source Code of cave.nice.testMessage.data.DataManager

/*
* Copyright 2011 Michele Mancioppi [michele.mancioppi@gmail.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cave.nice.testMessage.data;

import java.io.Closeable;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.Header;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;

import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import cave.nice.testMessage.data.ReportingPolicy.ReportingPolicyType;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Text;

public class DataManager implements Closeable {

  private final class AccountByRegistrationDateComparator implements
      Comparator<Account> {
    @Override
    public int compare(Account o1, Account o2) {
      return o1.getRegistrationDate().compareTo(o2.getRegistrationDate());
    }
  }

  private static final Logger LOGGER = Logger.getLogger(DataManager.class
      .getName());

  private static final DateTimeZone TIME_ZONE = DateTimeZone
      .forID("Europe/Berlin");

  private static final EntityManagerFactory ENTITY_MANAGER_FACTORY = Persistence
      .createEntityManagerFactory("transactions-optional");

  public static DataManager getInstance() {
    return new DataManager();
  }

  private final EntityManager entityManager;

  boolean closed = false;

  private DataManager() {
    entityManager = ENTITY_MANAGER_FACTORY.createEntityManager();
  }

  @Override
  public void close() {
    this.entityManager.close();
    closed = true;
  }

  @Override
  protected void finalize() throws Throwable {
    try {
      if (!closed) {
        close();
      }
    } finally {
      super.finalize();
    }
  }

  public Test createTest(InternetAddress accountEMailAddress, Date testDate,
      UUID challenge) throws UnknownVerifiedAccountException {
    return createTest(getVerifiedAccount(accountEMailAddress), testDate,
        challenge);
  }

  public Test createTest(VerifiedAccount account, Date testDate,
      UUID challenge) {
    Test newTest = new Test();
    newTest.setAccount(account);
    newTest.setDate(testDate);
    newTest.setChallenge(challenge.toString());

    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      entityManager.persist(newTest);
      transaction.commit();
      return newTest;
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public UnverifiedAccount createUnverifiedAccount(
      InternetAddress emailAddress) {
    UnverifiedAccount newAccount = new UnverifiedAccount();
    newAccount.setEmailAddress(emailAddress.getAddress());
    newAccount.setRegistrationDate(new Date());
    newAccount.setChallenge(UUID.randomUUID().toString());

    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      entityManager.persist(newAccount);
      transaction.commit();
      return newAccount;
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public VerifiedAccount createVerifiedAccount(InternetAddress emailAddress,
      List<ReportingPolicy> reportingPolicies) {
    VerifiedAccount newAccount = new VerifiedAccount();
    newAccount.setEmailAddress(emailAddress.getAddress());
    newAccount.setRegistrationDate(new Date());
    newAccount.setReportingPolicies(reportingPolicies);

    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      entityManager.persist(newAccount);
      transaction.commit();
      return newAccount;
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public <T extends Account> T getAccount(InternetAddress emailAddress,
      Class<T> clazz) throws UnknownEmailAddressException {
    try {
      return clazz.cast(entityManager.createQuery(
          "select from " + clazz.getName() + " where emailAddress='"
              + emailAddress.toString() + "'").getSingleResult());
    } catch (Exception e) {
      throw new UnknownEmailAddressException(e);
    }
  }

  public List<Test> getClosedTests(VerifiedAccount account)
      throws CannotRetrieveEntitiesException {
    return getTests(account, true);
  }

  public DateTime getCurrentTime() {
    return new DateTime(TIME_ZONE);
  }

  public List<Test> getOpenTests(VerifiedAccount account)
      throws CannotRetrieveEntitiesException {
    return getTests(account, false);
  }

  public Test getTest(Key testIdentifier)
      throws UnknownTestIdentifierException {
    Test test = entityManager.find(Test.class, testIdentifier);

    if (test == null) {
      throw new UnknownTestIdentifierException();
    }

    return test;
  }

  public Test getTestByChallenge(UUID challenge)
      throws UknownTestChallengeException {
    try {
      return (Test) entityManager.createQuery(
          "select from " + Test.class.getName()
              + " where challenge = '" + challenge + "'")
          .getSingleResult();
    } catch (Exception e) {
      throw new UknownTestChallengeException(e);
    }
  }

  public Test getTestOfAccount(VerifiedAccount account, UUID testChallenge)
      throws UnknownVerifiedAccountException,
      UknownTestChallengeException, WrongAccountForTestException {
    try {
      Test test = getTestByChallenge(testChallenge);

      if (!test.getAccount().equals(account)) {
        throw new WrongAccountForTestException(
            "The test with challenge '"
                + testChallenge
                + "' (id: "
                + test.getIdentifier()
                + ") is not associated with the account with email address '"
                + account.getEmailAddress() + "'");
      }

      return test;
    } catch (NoResultException e) {
      throw new UknownTestChallengeException(e);
    }
  }

  public List<Test> getTests(VerifiedAccount account, boolean answered)
      throws CannotRetrieveEntitiesException {
    try {
      @SuppressWarnings("unchecked")
      List<Test> openTests = entityManager
          .createQuery(
              "select from " + Test.class.getName()
                  + " where account=?1 and answeredOn is "
                  + ((answered) ? "not" : "") + " null")
          .setParameter(1, account).getResultList();
      Collections.sort(openTests, new Test.TestComparatorByDate());

      return openTests;
    } catch (Exception e) {
      throw new CannotRetrieveEntitiesException(e);
    }
  }

  public UnverifiedAccount getUnverifiedAccount(InternetAddress address)
      throws UnknownUnverifiedAccountException {
    try {
      return getAccount(address, UnverifiedAccount.class);
    } catch (UnknownEmailAddressException e) {
      throw new UnknownUnverifiedAccountException(e);
    }
  }

  public UnverifiedAccount getUnverifiedAccount(Key accountIdentifier)
      throws UnknownVerifiedAccountException {
    try {
      return entityManager.find(UnverifiedAccount.class,
          accountIdentifier);
    } catch (IllegalArgumentException e) {
      throw new UnknownVerifiedAccountException(e);
    }
  }

  public List<UnverifiedAccount> getUnverifiedAccounts()
      throws CannotRetrieveEntitiesException {
    return getAccounts(UnverifiedAccount.class);
  }

  public VerifiedAccount getVerifiedAccount(InternetAddress address)
      throws UnknownVerifiedAccountException {
    try {
      return getAccount(address, VerifiedAccount.class);
    } catch (UnknownEmailAddressException e) {
      throw new UnknownVerifiedAccountException(e);
    }
  }

  public VerifiedAccount getVerifiedAccount(Key accountIdentifier)
      throws UnknownVerifiedAccountException {
    try {
      return entityManager.find(VerifiedAccount.class, accountIdentifier);
    } catch (IllegalArgumentException e) {
      throw new UnknownVerifiedAccountException(e);
    }
  }

  public List<VerifiedAccount> getVerifiedAccounts()
      throws CannotRetrieveEntitiesException {
    return getAccounts(VerifiedAccount.class);
  }

  private <T extends Account> List<T> getAccounts(Class<T> clazz)
      throws CannotRetrieveEntitiesException {
    try {
      @SuppressWarnings("unchecked")
      List<T> accounts = entityManager.createQuery(
          "select from " + clazz.getName()).getResultList();
      Collections.sort(accounts,
          new AccountByRegistrationDateComparator());

      return accounts;
    } catch (Exception e) {
      throw new CannotRetrieveEntitiesException(e);
    }
  }

  public void markTestAsAnswered(Test test, Date answerTime)
      throws CannotUpdateEntityException, TestAlreadyAnsweredException {
    if (test.isAnswered()) {
      throw new TestAlreadyAnsweredException();
    }

    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      test.setAnsweredOn(answerTime);
      transaction.commit();
    } catch (Exception e) {
      throw new CannotUpdateEntityException(e);
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public void removeAccount(Account account) {
    EntityTransaction transaction = entityManager.getTransaction();
    try {
      /*
       * FIXME! Re-enable the line below and remove the second transaction
       * as soon as Google rolls-out the Cross-group transactions
       */
      // entityManager.remove(unverifiedAccount);
      transaction.begin();
      /*
      entityManager.createQuery(
          "delete from " + account.getClass().getName()
              + " where emailAddress='"
              + account.getEmailAddress() + "'").executeUpdate();
      */
      entityManager.remove(account);
      //
      transaction.commit();
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public void removeExpiredUnverifiedAccounts() {
    DateTime currentDate = getCurrentTime();
    Date threshold = currentDate.minus(UnverifiedAccount.EXPIRATION_PERIOD)
        .toDate();

    int removedAccounts = entityManager
        .createQuery(
            "delete " + UnverifiedAccount.class.getName()
                + " where registrationDate < $1")
        .setParameter(1, threshold).executeUpdate();
    LOGGER.info("Deleted " + removedAccounts
        + " unverified accounts past validity date");
  }

  public void removeTest(Test... tests) {
    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      for (Test test : tests) {
        entityManager.remove(test);
      }
      transaction.commit();
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public UnprocessedEMail storeUnprocessedEMail(MimeMessage message)
      throws IOException {
    UnprocessedEMail unprocessedEMail = new UnprocessedEMail();

    try {
      StringWriter sw = new StringWriter();
      @SuppressWarnings("rawtypes")
      Enumeration headers = message.getAllHeaders();
      while (headers.hasMoreElements()) {
        Header header = (Header) headers.nextElement();
        sw.append(header.getName());
        sw.append('=');
        sw.append(header.getValue());
        sw.append('\r');
      }

      unprocessedEMail.setHeaders(new Text(sw.toString()));
      unprocessedEMail.setSubject(new Text(message.getSubject()));
      unprocessedEMail.setContent(new Text(IOUtils.toString(message
          .getInputStream())));

      EntityTransaction transaction = entityManager.getTransaction();
      try {
        transaction.begin();
        entityManager.persist(unprocessedEMail);
        transaction.commit();
        return unprocessedEMail;
      } finally {
        if (transaction.isActive()) {
          transaction.rollback();
        }
      }
    } catch (Exception e) {
      LOGGER.log(Level.SEVERE, "Cannot store unprocessed message: "
          + message, e);
      throw new IOException("Cannot store unprocessed message: "
          + message, e);
    }
  }

  public VerifiedAccount verifyAccount(InternetAddress emailAddress,
      UUID challenge) throws VerificationChallengeNotMetException {
    UnverifiedAccount unverifiedAccount = null;
    try {
      unverifiedAccount = (UnverifiedAccount) entityManager.createQuery(
          "select from " + UnverifiedAccount.class.getName()
              + " where emailAddress='"
              + emailAddress.getAddress() + "' and challenge='"
              + challenge + "'").getSingleResult();
    } catch (NoResultException e) {
      throw new VerificationChallengeNotMetException();
    }

    VerifiedAccount newAccount = new VerifiedAccount();
    newAccount.setEmailAddress(unverifiedAccount.getEmailAddress());
    newAccount.setRegistrationDate(unverifiedAccount.getRegistrationDate());

    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      /*
       * FIXME! Re-enable the line below and remove the second transaction
       * as soon as Google rolls-out the Cross-group transactions
       */
      // entityManager.remove(unverifiedAccount);
      entityManager.persist(newAccount);
      transaction.commit();

      transaction.begin();
      entityManager.createQuery(
          "delete from " + UnverifiedAccount.class.getName()
              + " where emailAddress='"
              + unverifiedAccount.getEmailAddress() + "'")
          .executeUpdate();
      transaction.commit();

      return newAccount;
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  public ReportingPolicy addNewReportingPolicy(VerifiedAccount account,
      ReportingPolicyType type, Integer notifyAfterMinutes,
      Boolean notifyIfNoOpenTests)
      throws DuplicatedReportingPolicyException {
    for (ReportingPolicy reportingPolicy : account.getReportingPolicies()) {
      if (reportingPolicy.getType().equals(type)) {
        /*
         * TODO Error message
         */
        throw new DuplicatedReportingPolicyException();
      }
    }

    ReportingPolicy reportingPolicy = new ReportingPolicy();
    reportingPolicy.setType(type);
    reportingPolicy.setNotifyAfterMinutes(notifyAfterMinutes);
    reportingPolicy.setNotifyIfNoOpenTests(notifyIfNoOpenTests);
    reportingPolicy.setAccount(account);

    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      entityManager.persist(reportingPolicy);
      account.getReportingPolicies().add(reportingPolicy);
      transaction.commit();
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }

    return reportingPolicy;
  }

  public void removeReportingPolicy(VerifiedAccount account,
      ReportingPolicy reportingPolicy) {
    EntityTransaction transaction = entityManager.getTransaction();
    try {
      transaction.begin();
      account.getReportingPolicies().remove(reportingPolicy);
      entityManager.remove(reportingPolicy);
      transaction.commit();
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

}
TOP

Related Classes of cave.nice.testMessage.data.DataManager

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.