Package org.goat.caprabank.server

Source Code of org.goat.caprabank.server.BankServiceImpl

package org.goat.caprabank.server;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.goat.caprabank.client.BankService;
import org.goat.caprabank.shared.CaprabankException;
import org.goat.caprabank.shared.entity.BankTransaction;
import org.goat.caprabank.shared.entity.User;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.gwt.util.tools.shared.Md5Utils;

public class BankServiceImpl extends RemoteServiceServlet implements BankService {

  private static final String SESSION_USER_KEY = "CaprabankUser";

  private static final Logger log = Logger.getLogger(BankServiceImpl.class.getName());

  private static final int USER_LIMIT = 30;

  private final DataStore dataStore;

  public BankServiceImpl() {
    dataStore = new DataStore();
  }

  //////////////// Public API

  @Override
  public User login(String username, String password) throws CaprabankException {
    validateNotEmpty(username, "username");
    validateNotEmpty(password, "password");
    User user = dataStore.findUserByUsername(username);
    if (user == null || !Arrays.equals(user.passwordHash, hash(password))) {
      log.warning("Failed login attempt: " + username + "/" + password + ": " + (user == null ? "user not found." : "incorrect password."));
      throw new CaprabankException("Login failed - incorrect username or password.");
    }
    log.info("Logged in user " + username + ".");
    fillDetails(user);
    setCurrentUser(user);
    return user;
  }

  @Override
  public User register(String firstName, String lastName, String email, String username, String password) throws CaprabankException {
    if (dataStore.countUsers() > USER_LIMIT) {
      log.warning("Failed registration attempt - user count exceeded.");
      throw new CaprabankException("CapraBank is not accepting new customers at the moment.");
    }
    validateNotEmpty(firstName, "first name");
    validateNotEmpty(lastName, "last name");
    validateNotEmpty(email, "email");
    validateNotEmpty(username, "username");
    validateNotEmpty(password, "password");
    if (dataStore.findUserByUsername(username) != null) {
      log.warning("Failed registration attempt - username already exists: '" + username + ".");
      throw new CaprabankException("The username is already in use.");
    }
    User newUser = new User();
    newUser.accountNum = generateId();
    newUser.firstName = firstName;
    newUser.lastName = lastName;
    newUser.email = email;
    newUser.username = username;
    newUser.passwordHash = hash(password);
    newUser.balance = 0;
    dataStore.saveUser(newUser);
    log.info("Registered user " + username + "(" + (firstName + " " + lastName) + ", " + email + ").");

    sendMail(newUser, "Welcome to CapraBank!", "Thank you for registering at CapraBank!<br/><br/>Your account number <b>" + newUser.accountNum + "</b> has been successfully created. Your username is <b>" + newUser.username + "</b>.<br/><br/>Please visit the <a href=\"http://www.caprabank.com\">CapraBank site</a> to keep track of your account.");
    setCurrentUser(newUser);
    return newUser;
  }

  @Override
  public User getDetails() throws CaprabankException {
    return getCurrentUser();
  }

  @Override
  public User transfer(long toAccount, long amount, String comment) throws CaprabankException {
    User currentUser = getCurrentUser();
    if (toAccount == currentUser.accountNum) {
      log.warning("Self-tranfer attempted by user " + currentUser.username + ".");
      throw new CaprabankException("Very funny... That's you.");
    }
    if (amount <= 0) {
      log.warning("Negative amount tranfer attempted by user " + currentUser.username + " (amount=" + formatAmount(amount) + ").");
      throw new CaprabankException("Very funny...");
    }
    User toUser = dataStore.findUserByAccountNum(toAccount);
    if (toUser == null) {
      log.warning("Tranfer to nonexistent account attempted by user " + currentUser.username + " (account=" + toAccount + ").");
      throw new CaprabankException("Account " + toAccount + " not found.");
    }

    if (!"admin".equals(currentUser.username)) {
      if (amount > currentUser.balance) {
        log.warning("Insufficient funds for tranfer attempted by user " + currentUser.username + " (amount=" + formatAmount(amount) + ", balance=" + formatAmount(currentUser.balance) + ").");
        throw new CaprabankException("Insufficient funds.");
      }
    }

    BankTransaction transferTransaction = new BankTransaction();
    transferTransaction.transactionId = generateId();
    transferTransaction.timestamp = new Date();
    transferTransaction.fromAccount = currentUser.accountNum;
    transferTransaction.toAccount = toAccount;
    transferTransaction.amount = amount;
    transferTransaction.comment = comment;
    dataStore.saveTransaction(transferTransaction);
    log.info("User " + currentUser.username + " transferred " + formatAmount(amount) + " CapraCoins to account " + toAccount + " (" + toUser.username + ") with comment '" + comment + "'.");

    String messageBody = "Your CapraBank account " + toUser.accountNum + " just received a transfer of <b>" + formatAmount(amount) + "</b> CapraCoins from account <b>" + currentUser.accountNum + "</b>.";
    if (comment != null && !comment.isEmpty()) {
      messageBody += "<br/><br/>The sender has added the following comment:<br/><b>\"" + comment + "\"</b>";
    }
    sendMail(toUser, "Your CapraBank account has received a transfer.", messageBody);
    fillDetails(currentUser);
    return currentUser;
  }

  @Override
  public void logout() {
    boolean loggedOut = false;
    HttpServletRequest request = getThreadLocalRequest();
    if (request != null) {
      HttpSession session = request.getSession();
      if (session != null) {
        User currentUser = (User) session.getAttribute(SESSION_USER_KEY);
        if (currentUser != null) {
          loggedOut = true;
          session.invalidate();
          log.info("Logged out user " + currentUser.username + ".");
        }
      }
    }
    if (!loggedOut) {
      log.severe("Logout request without an active user.");
    }
  }

  //////////////// Private helpers

  private User getCurrentUser() throws CaprabankException {
    User currentUser = null;
    HttpServletRequest request = getThreadLocalRequest();
    if (request != null) {
      currentUser = (User) request.getSession(true).getAttribute(SESSION_USER_KEY);
    }
    if (currentUser == null) {
      throw new CaprabankException("User not logged in.");
    }
    fillDetails(currentUser);
    return currentUser;
  }

  private void setCurrentUser(User user) {
    HttpServletRequest request = getThreadLocalRequest();
    if (request != null) {
      request.getSession(true).setAttribute(SESSION_USER_KEY, user);
    }
  }

  private void fillDetails(User user) {
    long balance = 0;
    List<BankTransaction> fromAccount = dataStore.findTransactionsFromAccount(user);
    for (BankTransaction transaction : fromAccount) {
      balance -= transaction.amount;
    }
    List<BankTransaction> toAccount = dataStore.findTransactionsToAccount(user);
    for (BankTransaction transaction : toAccount) {
      balance += transaction.amount;
    }
    user.transactions = new ArrayList<BankTransaction>(fromAccount);
    user.transactions.addAll(toAccount);
    user.balance = balance;
    Collections.sort(user.transactions, new Comparator<BankTransaction>() {

      @Override
      public int compare(BankTransaction o1, BankTransaction o2) {
        return o1.timestamp.compareTo(o2.timestamp);
      }
    });
  }

  private void sendMail(User toUser, String subject, String messageBody) {
    try {
      Session session = Session.getDefaultInstance(new Properties(), null);
      Message msg = new MimeMessage(session);
      msg.setFrom(new InternetAddress("admin@caprabank.com", "CapraBank"));
      String fullName = toUser.firstName + " " + toUser.lastName;
      msg.addRecipient(Message.RecipientType.TO, new InternetAddress(toUser.email, fullName));
      msg.setSubject(subject);
      msg.setContent("<html><body>Dear " + fullName + ",<br/><br/>" + messageBody + "<br/><br/>Best regards,<br/>CapraBank.</body></html>", "text/html");
      Transport.send(msg);
      log.info("Mail sent to user " + toUser.username + " (" + toUser.email + ").");
    } catch (Exception e) {
      log.log(Level.SEVERE, "Error while sending email to user " + toUser.username + " (" + toUser.email + "): " + e.getMessage(), e);
    }
  }

  //////////////// Utilities

  private byte[] hash(String input) {
    byte[] result = null;
    try {
      result = Md5Utils.getMd5Digest(input.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
      // Yeah right...
    }
    return result;
  }

  private long generateId() {
    return (System.currentTimeMillis() - 1326900000000L) / 10L;
  }

  private String formatAmount(long amount) {
    return String.format("%.2f", ((double) amount / 100));
  }

  private void validateNotEmpty(String value, String name) throws CaprabankException {
    if (value == null || value.trim().isEmpty()) {
      throw new CaprabankException("The " + name + " cannot be empty.");
    }
  }
}
TOP

Related Classes of org.goat.caprabank.server.BankServiceImpl

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.