<repo_name>aleksandr5rikin/online-banking<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/command/client/ConfirmPayCommand.java
package ua.nure.petrikin.OnlineBanking.web.command.client;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import ua.nure.petrikin.OnlineBanking.db.AccountDao;
import ua.nure.petrikin.OnlineBanking.db.MySqlDaoFactory;
import ua.nure.petrikin.OnlineBanking.db.NoticeDao;
import ua.nure.petrikin.OnlineBanking.db.PaymentDao;
import ua.nure.petrikin.OnlineBanking.db.entity.Account;
import ua.nure.petrikin.OnlineBanking.db.entity.Notice;
import ua.nure.petrikin.OnlineBanking.db.entity.PayStatus;
import ua.nure.petrikin.OnlineBanking.db.entity.Payment;
import ua.nure.petrikin.OnlineBanking.db.entity.User;
import ua.nure.petrikin.OnlineBanking.exception.AppException;
import ua.nure.petrikin.OnlineBanking.web.Path;
import ua.nure.petrikin.OnlineBanking.web.command.Command;
import ua.nure.petrikin.OnlineBanking.web.websocket.ClientWebsocket;

public class ConfirmPayCommand extends Command {

	private static final Logger LOG = Logger.getLogger(ConfirmPayCommand.class);

	private static final long serialVersionUID = -3224495433136774938L;

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException, AppException {
		LOG.debug("START");

		String forward = Path.COMMAND_PAYMENT_LIST;

		HttpSession session = request.getSession(false);
		User user = (User) session.getAttribute("user");

		int recAccId = Integer.parseInt(request.getParameter("recAccId"));
		int payId = Integer.parseInt(request.getParameter("paymentId"));

		AccountDao accountDao = MySqlDaoFactory.getInstance().getDao(AccountDao.class);
		PaymentDao paymentDao = MySqlDaoFactory.getInstance().getDao(PaymentDao.class);
		NoticeDao noticeDao = MySqlDaoFactory.getInstance().getDao(NoticeDao.class);

		Account account = accountDao.get(recAccId);

		Payment p = paymentDao.get(payId);
		p.setPayStatusId(PayStatus.SUCEFULL.getId());
		p = paymentDao.save(p);

		if (p.getId() == null) {
			forward = Path.PAGE_ERROR_PAGE;
		} else {
			Notice notice = new Notice();
			notice.setUserId(account.getUserId());
			notice.setMessage("TEST");
			noticeDao.save(notice);
			ClientWebsocket.notifySend(account.getUserId());

			notice = new Notice();
			notice.setUserId(user.getId());
			notice.setMessage("TEST");
			noticeDao.save(notice);
			ClientWebsocket.notifySend(user.getId());
		}

		LOG.trace("Confirmed pay ID ====> " + payId);
		LOG.debug("FINISH");
		return forward;
	}

}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/websocket/ClientWebsocket.java
package ua.nure.petrikin.OnlineBanking.web.websocket;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import ua.nure.petrikin.OnlineBanking.db.MySqlDaoFactory;
import ua.nure.petrikin.OnlineBanking.db.NoticeDao;
import ua.nure.petrikin.OnlineBanking.exception.AppException;
import ua.nure.petrikin.OnlineBanking.exception.DBException;

@ServerEndpoint("/notifications/{userId}")
public class ClientWebsocket {

	private Integer id;
	private static final Map<Integer, SessionWarper> sessions = Collections.synchronizedMap(new HashMap<>());

	public static void notifySend(Integer userId) throws AppException {	
		SessionWarper sessionWarper = sessions.get(userId);
		if(sessionWarper != null){
			try {
				Session s = sessionWarper.getSession();
				Integer count = sessionWarper.getCount();
				s.getBasicRemote().sendObject(++count);
			} catch (IOException | EncodeException ex) {
				sessions.remove(userId);
				throw new AppException(ex.getMessage());
			}
		}
	}
	
	@OnOpen
	public void onOpen(@PathParam("userId") Integer userId, Session session) throws IOException, EncodeException, DBException {
		id = userId;
		SessionWarper sessionWarper = new SessionWarper();
		
		NoticeDao noticeDao = MySqlDaoFactory.getInstance().getDao(NoticeDao.class);
		int count = noticeDao.getCount(userId);
		
		sessionWarper.setCount(count);
		sessionWarper.setSession(session);
		session.getBasicRemote().sendObject(++count);
		
		sessions.put(userId, sessionWarper);
		
	}

	@OnClose
	public void onClose() throws IOException, EncodeException {
		sessions.remove(id);
	}
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/websocket/SessionWarper.java
package ua.nure.petrikin.OnlineBanking.web.websocket;

import javax.websocket.Session;

public class SessionWarper {
	private Integer count;
	private Session session;
	
	public Integer getCount() {
		return count;
	}
	public void setCount(Integer count) {
		this.count = count;
	}
	public Session getSession() {
		return session;
	}
	public void setSession(Session session) {
		this.session = session;
	}
	
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/exception/ConnectionNotAvailableException.java
package ua.nure.petrikin.OnlineBanking.exception;

public class ConnectionNotAvailableException extends AppException {

	private static final long serialVersionUID = 530988069619320888L;

	public ConnectionNotAvailableException(){
		super();
	}
	
	public ConnectionNotAvailableException(Throwable cause){
		super(cause);
	}
	
	public ConnectionNotAvailableException(String message){
		super(message);
	}
	
	public ConnectionNotAvailableException(String message, Throwable cause){
		super(message, cause);
	}
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/db/pool/ConnectionReleaser.java
package ua.nure.petrikin.OnlineBanking.db.pool;

import java.sql.SQLException;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;

public class ConnectionReleaser implements Runnable
{
	public static final Logger LOG = Logger.getLogger(ConnectionReleaser.class);
	public static final int TIMEOUT = 30000;
    private ConnectionPool pool;
    private LinkedBlockingQueue<PooledConnection> busyConnections;
    private long lastRun;   
    public ConnectionReleaser(ConnectionPool pool, LinkedBlockingQueue<PooledConnection> busyConnections) {
        this.pool = pool;
        this.busyConnections =  busyConnections;
    }

    @Override
    public void run() {
        this.lastRun = System.currentTimeMillis();
        LOG.debug("Time between runs: " + TIMEOUT);
        while (true) {
            if (this.pool.isClosed()) {
               return;
            }
            if(((System.currentTimeMillis() - this.lastRun) > TIMEOUT)) {
                if (this.busyConnections != null && this.busyConnections.size() > 0) {
                    for (int i = 0; i < this.busyConnections.size(); i++) {
                        PooledConnection conn = this.busyConnections.peek();
                        try {
                            if (conn != null && conn.isClosed()) {
                                this.pool.returnConnection(conn);
                                LOG.debug("Connection Released by ConnectionReleaser: " + conn);
                            }
                        } catch (SQLException e) {
                            LOG.error("Connection could not be released to the pool", e);
                        }
                    }
                    this.lastRun = System.currentTimeMillis();
                }
            }
        }
    }
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/exception/Messages.java
package ua.nure.petrikin.OnlineBanking.exception;

public final class Messages {

	private Messages() {
	}
	
	public static final String ERR_SQL_CONNECTION = "Cannot obtain a connection from the pool";
	public static final String ERR_SQL_SAVE_USER = "Cannot save new user";
	public static final String ERR_SQL_SAVE_ACCOUNT = "Cannot save new account";
	public static final String ERR_SQL_SAVE_PAYMENT = "Cannot save payment";
	public static final String ERR_SQL_FIND_USER = "Cannot find user";
	public static final String ERR_SQL_OBTAIN_USERS = "Cannot obtain user list";
	public static final String ERR_SQL_OBTAIN_ACCOUNTS = "Cannot obtain account list";
	public static final String ERR_SQL_OBTAIN_PAYMENTS = "Cannot obtain payments";
	public static final String ERR_SQL_LOCK_ACCOUNT = "Cannot lock account";
	public static final String ERR_LOCK_ACCOUNT = "Account is locked";
	public static final String ERR_LIMIT = "limit is exceeded";
	
	public static final String ERR_UNRESOLVED_PARAM = "Unreolved param!";	
	public static final String ERR_AUTH_PASS = "<PASSWORD>";
	public static final String ERR_AUTH_UNCOMFIRMED = "User status ===> 'UNCOMFIRMED'";
	public static final String ERR_SECUR_HASH_ALG = "No such hash algorithem";
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/filter/ValidationFilter.java
package ua.nure.petrikin.OnlineBanking.web.filter;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

import org.apache.log4j.Logger;

import ua.nure.petrikin.OnlineBanking.exception.AppException;
import ua.nure.petrikin.OnlineBanking.exception.Messages;
import ua.nure.petrikin.OnlineBanking.web.Path;
import ua.nure.petrikin.OnlineBanking.web.util.Param;
import ua.nure.petrikin.OnlineBanking.web.util.ParamContainer;

@WebFilter(servletNames = "Controller")
public class ValidationFilter implements Filter{

	private static final Logger LOG = Logger.getLogger(ValidationFilter.class);
	
	@Override
	public void destroy() {
		LOG.debug("DESTROY");
		
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		LOG.debug("START");

		boolean valid = true;
		
		String commandName = req.getParameter("command");
		
		LOG.trace("Request command ====> " + commandName);

		List<Param> requiredParams = ParamContainer.get(commandName);
		LOG.debug("requiredParams ====> " + requiredParams);
		
		try {
			for(Param param : requiredParams){
				String name = param.getName();
				LOG.debug("Param ====> " + name);
				String providetParam = req.getParameter(name);
				if(providetParam == null){
					LOG.warn("Providet param '" + name + "' == null");
					throw new AppException(Messages.ERR_UNRESOLVED_PARAM);
				}
				Map<String, String> tests = param.getTests();
				for(Map.Entry<String, String> entry : tests.entrySet()){
					Pattern p = Pattern.compile(entry.getValue());
					Matcher m = p.matcher(providetParam);
					if(!m.find()){
						String msg = entry.getKey() + ": " + providetParam;
						LOG.warn(msg);
						throw new AppException(msg);
					}
				}
				LOG.warn("Providet param ['" + name + "' : '" +providetParam + "'] is valid");
			}
		} catch (AppException ex) {
			valid = false;
			req.setAttribute("errorMessage", ex.getMessage());
			LOG.warn("Forward address ====> " + Path.PAGE_ERROR_PAGE);
			req.getRequestDispatcher(Path.PAGE_ERROR_PAGE).forward(req, resp);
		}
		
		if(valid){
			LOG.debug("FINISHED SUCEFULL");	
			chain.doFilter(req, resp);
		}
		
	}
	


	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		LOG.debug("INIT");
	}

}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/db/entity/AccStatus.java
package ua.nure.petrikin.OnlineBanking.db.entity;

import java.io.Serializable;

public enum AccStatus implements Serializable{
	UNLOCKED, LOCKED;
	
	public static AccStatus getAccStatus(Account account) {
		int accStatusId = account.getAccStatusId() - 1;
		return AccStatus.values()[accStatusId];
	}
	
	public String getName() {
		return name().toLowerCase();
	}
	
	public int getId() {
		return ordinal() + 1;
	}
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/command/client/AddAccountCommand.java
package ua.nure.petrikin.OnlineBanking.web.command.client;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import ua.nure.petrikin.OnlineBanking.db.AccountDao;
import ua.nure.petrikin.OnlineBanking.db.MySqlDaoFactory;
import ua.nure.petrikin.OnlineBanking.db.entity.AccStatus;
import ua.nure.petrikin.OnlineBanking.db.entity.Account;
import ua.nure.petrikin.OnlineBanking.db.entity.User;
import ua.nure.petrikin.OnlineBanking.exception.AppException;
import ua.nure.petrikin.OnlineBanking.web.Path;
import ua.nure.petrikin.OnlineBanking.web.command.Command;

public class AddAccountCommand extends Command {

	private static final Logger LOG = Logger.getLogger(AddAccountCommand.class);

	private static final long serialVersionUID = -4060341422635798377L;

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException, AppException {
		LOG.debug("START");

		String forward = Path.PAGE_ERROR_PAGE;
		HttpSession session = request.getSession(false);

		String name = request.getParameter("name");
		User user = (User) session.getAttribute("user");

		Account account = new Account();
		account.setName(name);
		account.setUserId(user.getId());
		account.setAccStatusId(AccStatus.UNLOCKED.getId());

		AccountDao accountDao = MySqlDaoFactory.getInstance().getDao(AccountDao.class);
		accountDao.save(account);

		if (account.getId() == null) {
			forward = Path.COMMAND_ACCOUNT_LIST;
		}

		LOG.trace("New Account ID ====> " + account.getId());
		LOG.debug("FINISH");
		return forward;
	}

}<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/command/client/AddPaymentCommand.java
package ua.nure.petrikin.OnlineBanking.web.command.client;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import ua.nure.petrikin.OnlineBanking.db.AccountDao;
import ua.nure.petrikin.OnlineBanking.db.MySqlDaoFactory;
import ua.nure.petrikin.OnlineBanking.db.PaymentDao;
import ua.nure.petrikin.OnlineBanking.db.entity.Account;
import ua.nure.petrikin.OnlineBanking.db.entity.PayStatus;
import ua.nure.petrikin.OnlineBanking.db.entity.Payment;
import ua.nure.petrikin.OnlineBanking.exception.AppException;
import ua.nure.petrikin.OnlineBanking.exception.Messages;
import ua.nure.petrikin.OnlineBanking.web.Path;
import ua.nure.petrikin.OnlineBanking.web.command.Command;

public class AddPaymentCommand extends Command {

	private static final Logger LOG = Logger.getLogger(AddPaymentCommand.class);

	private static final long serialVersionUID = -7506166075358571214L;

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException, AppException {
		LOG.debug("START");

		String forward = Path.PAGE_ERROR_PAGE;

		LOG.debug(request.getParameter("accountId"));
		LOG.debug(request.getParameter("reciverId"));
		LOG.debug(request.getParameter("sum"));
		LOG.debug(request.getParameter("found"));
		LOG.debug(request.getParameter("comment"));

		String found = request.getParameter("found");
		int accId = Integer.parseInt(request.getParameter("accountId"));
		int sum = Integer.parseInt(request.getParameter("sum"));
		String comment = request.getParameter("comment");
		AccountDao accountDao = MySqlDaoFactory.getInstance().getDao(AccountDao.class);
		Account account = accountDao.get(accId);

		if (account.getAccStatusId() == 2) {
			throw new AppException(Messages.ERR_LOCK_ACCOUNT);
		}

		if (account.getLim() != 0) {
			Timestamp t = account.getDate();
			Calendar c = Calendar.getInstance();
			c.setTimeInMillis(t.getTime());
			c.add(Calendar.MONTH, 1);

			long limitTime = c.getTimeInMillis();
			long currentTime = new Date().getTime();

			if (currentTime > limitTime) {
				t = new Timestamp(limitTime);
				account.setDate(t);
				account.setSpent(0);
				accountDao.save(account);
			}

			if (account.getLim() - account.getSpent() <= 0) {
				throw new AppException(Messages.ERR_LIMIT);
			}
		}

		Payment payment = new Payment();
		payment.setAccId(accId);
		payment.setSum(sum);
		payment.setComment(comment);

		if (found.equals("found")) {
			payment.setReciverId(accId);
			payment.setPayStatusId(PayStatus.SUCEFULL.getId());
		} else {
			int reciverId = Integer.parseInt(request.getParameter("reciverId"));
			payment.setReciverId(reciverId);
			payment.setPayStatusId(PayStatus.PREPEARED.getId());
		}

		PaymentDao paymentDao = MySqlDaoFactory.getInstance().getDao(PaymentDao.class);
		paymentDao.save(payment);

		if (payment.getId() != null) {
			forward = Path.COMMAND_ACCOUNT_LIST;
		}

		LOG.trace("New Payment ID ====> " + payment.getId());
		LOG.debug("FINISH");
		return forward;
	}

}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/web/common/LogoutCommand.java
package ua.nure.petrikin.OnlineBanking.web.common;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import ua.nure.petrikin.OnlineBanking.web.Path;
import ua.nure.petrikin.OnlineBanking.web.command.Command;

public class LogoutCommand extends Command{

	private static final long serialVersionUID = 3658358534929790935L;

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) {
		
		HttpSession session = request.getSession(false);
		if (session != null) {
			session.invalidate();
		}

		return Path.COMMAND_GET_LOGIN;
	}
}
<file_sep>/src/ua/nure/petrikin/OnlineBanking/db/PaymentDao.java
package ua.nure.petrikin.OnlineBanking.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import ua.nure.petrikin.OnlineBanking.db.entity.Payment;
import ua.nure.petrikin.OnlineBanking.db.pool.ConnectionPool;
import ua.nure.petrikin.OnlineBanking.exception.DBException;

public class PaymentDao extends AbstractDao<Payment, Integer>{
	
	private static final String SELECT_USER_PAY = "SELECT payments.* FROM payments, accounts "
			+ "WHERE (payments.account_id = accounts.id "
			+ "OR payments.reciver_id = accounts.id) AND accounts.user_id = ?";
	
	public PaymentDao(ConnectionPool connection) {
		super(connection);
	}

	@Override
	protected String getSelectQuery() {
		return "SELECT * FROM payments";
	}

	@Override
	protected String getUpdateQuery() {
		return "UPDATE payments SET pay_status_id = ? WHERE id = ?";
	}

	@Override
	protected String getCreateQuery() {
		return "INSERT INTO payments VALUE (DEFAULT, ?, ?, ?, ?, ?, DEFAULT)";
	}

	@Override
	protected String getDeleteQuery() {
		return "DELETE FROM payments WHERE id = ?";
	}

	@Override
	protected Payment parseResultSet(ResultSet rs) throws SQLException {
		Payment payment = new Payment();
		payment.setId(rs.getInt(Fields.PAYMENT_ID));
		payment.setAccId(rs.getInt(Fields.PAYMENT_ACCOUNT_ID));
		payment.setReciverId(rs.getInt(Fields.PAYMENT_RECIVER_ID));
		payment.setSum(rs.getInt(Fields.PAYMENT_SUM));
		payment.setPayStatusId(rs.getInt(Fields.PAYMENT_STATUS_ID));
		payment.setComment(rs.getString(Fields.PAYMENT_COMMENT));
		payment.setDate(rs.getTimestamp(Fields.PAYMENT_DATE));
		return payment;
	}

	@Override
	protected void prepareUpdateStatement(Payment entity, PreparedStatement ps) throws SQLException {
		ps.setInt(1, entity.getPayStatusId());
		ps.setInt(2, entity.getId());
	}

	@Override
	protected void prepareInsertStatement(Payment entity, PreparedStatement ps) throws SQLException {
		ps.setInt(1, entity.getAccId());
		ps.setInt(2, entity.getReciverId());
		ps.setInt(3, entity.getSum());
		ps.setInt(4, entity.getPayStatusId());
		ps.setString(5, entity.getComment());
	}
	
	public List<Payment> findUserPayment(int userId) throws DBException{
		Connection con = getConnectionFromPool();
		List<Payment> payments = new ArrayList<>();
		try {
			PreparedStatement ps = con.prepareStatement(SELECT_USER_PAY);
			ps.setInt(1, userId);
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				payments.add(parseResultSet(rs));
			}
		} catch (SQLException ex) {
			throw new DBException(ex.getMessage());
		}finally {
			try {
				con.close();
			} catch (SQLException e) {
				throw new DBException(e.getMessage());
			}
		}
		return payments;
	}
}