com.gvmax.data.user.JDBCBasedUserDAO.java Source code

Java tutorial

Introduction

Here is the source code for com.gvmax.data.user.JDBCBasedUserDAO.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Hani Naguib.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 *
 * Contributors:
 *     Hani Naguib - initial API and implementation
 ******************************************************************************/
package com.gvmax.data.user;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import com.codahale.metrics.annotation.ExceptionMetered;
import com.codahale.metrics.annotation.Timed;
import com.gvmax.common.model.GlobalStats;
import com.gvmax.common.model.Stats;
import com.gvmax.common.model.User;
import com.gvmax.common.util.Enc;
import com.gvmax.common.util.JsonUtils;

/**
 * Implementation of UserDAO that is JDBC based.
 */
public class JDBCBasedUserDAO implements UserDAO {
    private static final Logger logger = Logger.getLogger(JDBCBasedUserDAO.class);
    public static final String USER_TABLE = "users";
    public static final String STATS_TABLE = "stats";
    public static final String BLACKLIST_TABLE = "blacklist";
    private JdbcTemplate jdbcTemplate;
    private Enc enc;

    public JDBCBasedUserDAO(DataSource dataSource, String encKey) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.enc = new Enc(encKey);
    }

    @Override
    @Timed
    @ExceptionMetered
    public boolean exists(String email) {
        // TODO: Review deprecated use
        int count = jdbcTemplate.queryForInt("select count(0) from " + USER_TABLE + " where email = ?", enc(email));
        return count > 0;
    }

    @Override
    @Timed
    @ExceptionMetered
    public List<User> getUsers(int offset, int limit) {
        return jdbcTemplate.query("select user from " + USER_TABLE + " LIMIT ?,?", new Object[] { offset, limit },
                new RowMapper<User>() {
                    @Override
                    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                        String userJson = rs.getString("user");
                        return toUser(userJson);
                    }
                });
    }

    @Override
    @Timed
    @ExceptionMetered
    public User retrieve(String email) {
        String userJson = queryForString("select user from " + USER_TABLE + " where email = ?", enc(email));
        return toUser(userJson);
    }

    @Override
    @Timed
    @ExceptionMetered
    public User retrieveByPin(String pin) {
        String userJson = queryForString("select user from " + USER_TABLE + " where pin = ?", enc(pin));
        return toUser(userJson);
    }

    @Override
    @Timed
    @ExceptionMetered
    public User retrieveByGTalk(String gTalkEmail) {
        String userJson = queryForString("select user from " + USER_TABLE + " where gTalkEmail = ?",
                enc(gTalkEmail));
        return toUser(userJson);
    }

    @Override
    @Timed
    @ExceptionMetered
    public void store(User user) {
        try {
            String userJson = JsonUtils.toJson(user);
            if (user.getEmail() != null) {
                user.setEmail(user.getEmail().trim().toLowerCase());
            }
            if (user.getgTalkEmail() != null) {
                user.setgTalkEmail(user.getgTalkEmail().trim().toLowerCase());
            }
            if (exists(user.getEmail())) {
                jdbcTemplate.update(
                        "update " + USER_TABLE + " set pin = ?, gTalkEmail = ?, user = ? where email = ?",
                        enc(user.getPin()), enc(user.getgTalkEmail()), enc(userJson), enc(user.getEmail()));
            } else {
                jdbcTemplate.update("insert into " + USER_TABLE + " (email, pin, gTalkEmail,user) values (?,?,?,?)",
                        enc(user.getEmail()), enc(user.getPin()), enc(user.getgTalkEmail()), enc(userJson));
                if (getStats(user.getEmail()) == null) {
                    store(new Stats(user.getEmail(), user.getPin()));
                }
            }
        } catch (IOException e) {
            logger.error("Unable to store user", e);
        }
    }

    @Override
    @Timed
    @ExceptionMetered
    public void setPassword(String email, String password) {
        User user = retrieve(email);
        user.setPassword(password);
        store(user);
    }

    @Override
    @Timed
    @ExceptionMetered
    public void setGVFwdPhone(String email, String number, String type) {
        User user = retrieve(email);
        user.setGvFwdPhone(number);
        user.setGvFwdPhoneType(type);
        store(user);
    }

    @Override
    @Timed
    @ExceptionMetered
    public void delete(String email) {
        jdbcTemplate.update("delete from " + USER_TABLE + " where email = ?", enc(email));
    }

    // -----------------
    // STATS
    // -----------------

    @Override
    @Timed
    @ExceptionMetered
    public GlobalStats getStats() {
        try {
            GlobalStats stats = jdbcTemplate.queryForObject(
                    "select " + "count(email) as statsCount," + "sum(smsInCount) as smsInCount,"
                            + "sum(smsOutCount) as smsOutCount," + "sum(vmInCount) as vmInCount,"
                            + "sum(mcInCount) as mcInCount," + "sum(emailInCount) as emailInCount,"
                            + "sum(gTalkCount) as gTalkCount," + "sum(apiCount) as apiCount,"
                            + "sum(errorCount) as errorCount," + "sum(invalidEmailCount) as invalidEmailCount,"
                            + "sum(fallbackCount) as fallbackCount " + "from " + STATS_TABLE,
                    new RowMapper<GlobalStats>() {
                        @Override
                        public GlobalStats mapRow(ResultSet rs, int row) throws SQLException {
                            GlobalStats stats = new GlobalStats();
                            stats.setTimestamp(System.currentTimeMillis());
                            stats.setStatsCount(rs.getInt("statsCount"));
                            stats.setSmsInCount(rs.getInt("smsInCount"));
                            stats.setSmsOutCount(rs.getInt("smsOutCount"));
                            stats.setVmInCount(rs.getInt("vmInCount"));
                            stats.setMcInCount(rs.getInt("mcInCount"));
                            stats.setEmailInCount(rs.getInt("emailInCount"));
                            stats.setgTalkCount(rs.getInt("gTalkCount"));
                            stats.setApiCount(rs.getInt("apiCount"));
                            stats.setErrorCount(rs.getInt("errorCount"));
                            stats.setInvalidEmailCount(rs.getInt("invalidEmailCount"));
                            stats.setFallbackCount(rs.getInt("fallbackCount"));
                            return stats;
                        }
                    });
            // TODO: Review deprecated use
            int userCount = jdbcTemplate.queryForInt("select count(email) from " + USER_TABLE);
            stats.setUserCount(userCount);
            return stats;
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    @Override
    @Timed
    @ExceptionMetered
    public Stats getStats(final String email) {
        try {
            Stats stats = jdbcTemplate.queryForObject("select * from " + STATS_TABLE + " where email = ?",
                    new Object[] { enc(email) }, new RowMapper<Stats>() {
                        @Override
                        public Stats mapRow(ResultSet rs, int row) throws SQLException {
                            Stats stats = new Stats(email, dec(rs.getString("pin")));
                            stats.setTimestamp(System.currentTimeMillis());
                            stats.setSmsInCount(rs.getInt("smsInCount"));
                            stats.setSmsOutCount(rs.getInt("smsOutCount"));
                            stats.setVmInCount(rs.getInt("vmInCount"));
                            stats.setMcInCount(rs.getInt("mcInCount"));
                            stats.setEmailInCount(rs.getInt("emailInCount"));
                            stats.setgTalkCount(rs.getInt("gTalkCount"));
                            stats.setApiCount(rs.getInt("apiCount"));
                            stats.setErrorCount(rs.getInt("errorCount"));
                            stats.setInvalidEmailCount(rs.getInt("invalidEmailCount"));
                            stats.setFallbackCount(rs.getInt("fallbackCount"));
                            return stats;
                        }
                    });
            return stats;
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    @Override
    @Timed
    @ExceptionMetered
    public void store(Stats stats) {
        jdbcTemplate.update("delete from " + STATS_TABLE + " where email = ?", stats.getEmail());
        jdbcTemplate.update("insert into " + STATS_TABLE + " "
                + "(email,pin,smsInCount,vmInCount,mcInCount,emailInCount,gTalkCount,smsOutCount,apiCount,errorCount,invalidEmailCount,fallbackCount) "
                + " values(?,?,?,?,?,?,?,?,?,?,?,?)", enc(stats.getEmail()), enc(stats.getPin()),
                stats.getSmsInCount(), stats.getVmInCount(), stats.getMcInCount(), stats.getEmailInCount(),
                stats.getgTalkCount(), stats.getSmsOutCount(), stats.getApiCount(), stats.getErrorCount(),
                stats.getInvalidEmailCount(), stats.getFallbackCount());
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementSMSInCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set smsInCount=smsInCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementVMInCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set vmInCount=vmInCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementMCInCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set mcInCount=mcInCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementEmailInCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set emailInCount=emailInCount+1 WHERE email = ?",
                enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementGTalkCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set gTalkCount=gTalkCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementApiCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set apiCount=apiCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementSMSOutCount(String email, int increment) {
        jdbcTemplate.update("update " + STATS_TABLE + " set smsOutCount=smsOutCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementErrorCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set errorCount=errorCount+1 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementFallbackCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set fallbackCount=fallbackCount+1 WHERE email = ?",
                enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void clearFallbackCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set fallbackCount=0 WHERE email = ?", enc(email));
    }

    @Override
    @Timed
    @ExceptionMetered
    public void incrementInvalidEmailCount(String email) {
        jdbcTemplate.update("update " + STATS_TABLE + " set invalidEmailCount=invalidEmailCount+1 WHERE email = ?",
                enc(email));
    }

    // --------------
    // BLACKLIST
    // --------------

    @Override
    @Timed
    @ExceptionMetered
    public boolean isBlacklisted(String value) {
        return false;
    }

    @Override
    @Timed
    @ExceptionMetered
    public void blacklist(String value) {
    }

    // -----------------
    // UTILS
    // -----------------

    private String enc(String value) {
        return enc.encrypt(value);
    }

    private String dec(String value) {
        return enc.decrypt(value);
    }

    private User toUser(String json) {
        if (json == null) {
            return null;
        }
        json = dec(json);
        try {
            return JsonUtils.fromJson(json, User.class);
        } catch (IOException e) {
            logger.error("Unable to convert json", e);
            return null;
        }
    }

    private String queryForString(String sql, Object... params) {
        List<String> res = jdbcTemplate.query(sql, params, new RowMapper<String>() {
            @Override
            public String mapRow(ResultSet resultSet, int row) throws SQLException {
                return resultSet.getString(1);
            }
        });
        if (res.isEmpty()) {
            return null;
        }
        return res.get(0);
    }

}