com.springsource.greenhouse.account.JdbcAccountRepository.java Source code

Java tutorial

Introduction

Here is the source code for com.springsource.greenhouse.account.JdbcAccountRepository.java

Source

/*
 * Copyright 2010 the original author or authors.
 *
 * 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 com.springsource.greenhouse.account;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.springsource.greenhouse.utils.EmailUtils;

/**
 * AccountRepository implementation that stores Accounts in a relational database using the JDBC API.
 * @author Keith Donald
 */
@Repository
public class JdbcAccountRepository implements AccountRepository {

    private final JdbcTemplate jdbcTemplate;

    private final PasswordEncoder passwordEncoder;

    private final AccountMapper accountMapper;

    @Autowired
    public JdbcAccountRepository(JdbcTemplate jdbcTemplate, PasswordEncoder passwordEncoder,
            AccountMapper accountMapper) {
        this.jdbcTemplate = jdbcTemplate;
        this.passwordEncoder = passwordEncoder;
        this.accountMapper = accountMapper;
    }

    @Transactional
    public Account createAccount(Person person) throws EmailAlreadyOnFileException {
        try {
            jdbcTemplate.update(
                    "insert into Member (firstName, lastName, email, password, gender, birthdate) values (?, ?, ?, ?, ?, ?)",
                    person.getFirstName(), person.getLastName(), person.getEmail(),
                    passwordEncoder.encode(person.getPassword()), person.getGender().code(),
                    person.getBirthdate().toString());
            Long accountId = jdbcTemplate.queryForLong("call identity()");
            return accountMapper.newAccount(accountId, person);
        } catch (DuplicateKeyException e) {
            throw new EmailAlreadyOnFileException(person.getEmail());
        }
    }

    public Account authenticate(String signin, String password)
            throws SignInNotFoundException, InvalidPasswordException {
        try {
            return jdbcTemplate
                    .queryForObject(passwordProtectedAccountQuery(signin), passwordProtectedAccountMapper, signin)
                    .accessAccount(password, passwordEncoder);
        } catch (EmptyResultDataAccessException e) {
            throw new SignInNotFoundException(signin);
        }
    }

    public void changePassword(Long accountId, String password) {
        jdbcTemplate.update("update Member set password = ? where id = ?", passwordEncoder.encode(password),
                accountId);
    }

    public Account findById(Long id) {
        return jdbcTemplate.queryForObject(AccountMapper.SELECT_ACCOUNT + " where id = ?", accountMapper, id);
    }

    public List<ProfileReference> findProfileReferencesByIds(List<Long> accountIds) {
        NamedParameterJdbcTemplate namedTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
        Map<String, Object> params = new HashMap<String, Object>(2, 1);
        params.put("accountIds", accountIds);
        return namedTemplate.query(AccountMapper.SELECT_ACCOUNT_REFERENCE + " where id in ( :accountIds )", params,
                accountMapper.getReferenceMapper());
    }

    public Account findBySignin(String signin) throws SignInNotFoundException {
        try {
            return jdbcTemplate.queryForObject(accountQuery(signin), accountMapper, signin);
        } catch (EmptyResultDataAccessException e) {
            throw new SignInNotFoundException(signin);
        }
    }

    // internal helpers

    private String accountQuery(String signin) {
        return EmailUtils.isEmail(signin) ? AccountMapper.SELECT_ACCOUNT + " where email = ?"
                : AccountMapper.SELECT_ACCOUNT + " where username = ?";
    }

    private String passwordProtectedAccountQuery(String signin) {
        return EmailUtils.isEmail(signin) ? SELECT_PASSWORD_PROTECTED_ACCOUNT + " where email = ?"
                : SELECT_PASSWORD_PROTECTED_ACCOUNT + " where username = ?";
    }

    private RowMapper<PasswordProtectedAccount> passwordProtectedAccountMapper = new RowMapper<PasswordProtectedAccount>() {
        public PasswordProtectedAccount mapRow(ResultSet rs, int row) throws SQLException {
            Account account = accountMapper.mapRow(rs, row);
            return new PasswordProtectedAccount(account, rs.getString("password"));
        }
    };

    private static class PasswordProtectedAccount {

        private Account account;

        private String encodedPassword;

        public PasswordProtectedAccount(Account account, String encodedPassword) {
            this.account = account;
            this.encodedPassword = encodedPassword;
        }

        public Account accessAccount(String password, PasswordEncoder passwordEncoder)
                throws InvalidPasswordException {
            if (passwordEncoder.matches(password, encodedPassword)) {
                return account;
            } else {
                throw new InvalidPasswordException();
            }
        }

    }

    private static final String SELECT_PASSWORD_PROTECTED_ACCOUNT = "select id, firstName, lastName, email, password, username, gender, pictureSet from Member";
}