Java tutorial
/* * Copyright (C) 2010-2012 Taylor Leese (tleese22@gmail.com) * * This file is part of jappstart. * * jappstart is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * jappstart is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with jappstart. If not, see <http://www.gnu.org/licenses/>. */ package com.assetmanager.service.auth; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.taskqueue.Queue; import com.google.appengine.api.taskqueue.QueueFactory; import com.google.appengine.api.taskqueue.TaskOptions; import com.google.appengine.api.memcache.Expiration; import com.google.appengine.api.memcache.MemcacheService; import com.assetmanager.exception.DuplicateUserException; import com.assetmanager.model.auth.UserAccount; /** * The user details service implementation. */ @Service public class UserDetailsServiceImpl implements EnhancedUserDetailsService { /** * The default cache expiration in seconds. */ private static final int DEFAULT_EXPIRATION = 3600; /** * The username field name. */ private static final String USERNAME = "username"; /** * The select user query. */ private static final String SELECT_USER = "SELECT u FROM UserAccount u WHERE username = :username"; /** * The entity manager. */ @PersistenceContext private transient EntityManager entityManager; /** * The mail task name. */ private String mailTaskName; /** * The mail task URL. */ private String mailTaskUrl; /** * The datastore service. */ private DatastoreService datastoreService; /** * The memcache service. */ private MemcacheService memcacheService; /** * Returns the mail task name. * * @return the mail task name */ public final String getMailTaskName() { return mailTaskName; } /** * Sets the mail task name. * * @param mailTaskName the mail task name */ public final void setMailTaskName(final String mailTaskName) { this.mailTaskName = mailTaskName; } /** * Returns the mail task URL. * * @return the mail task URL */ public final String getMailTaskUrl() { return mailTaskUrl; } /** * Sets the mail task URL. * * @param mailTaskUrl the mail task URL */ public final void setMailTaskUrl(final String mailTaskUrl) { this.mailTaskUrl = mailTaskUrl; } /** * Returns the datastore service. * * @return the datastore service */ public final DatastoreService getDatastoreService() { return datastoreService; } /** * Sets the datastore service. * * @param datastoreService the datastore service */ public final void setDatastoreService(final DatastoreService datastoreService) { this.datastoreService = datastoreService; } /** * Returns the memcache service. * * @return the memcache service */ public final MemcacheService getMemcacheService() { return memcacheService; } /** * Sets the memcache service. * * @param memcacheService the memcache service */ public final void setMemcacheService(final MemcacheService memcacheService) { this.memcacheService = memcacheService; } /** * Locates the user based on the username. * * @param username string the username * @return the user details */ @Override public final UserDetails loadUserByUsername(final String username) { final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); UserAccount user = (UserAccount) memcacheService.get(username); if (user == null) { final Query query = entityManager.createQuery("SELECT u FROM UserAccount u WHERE username = :username"); query.setParameter(USERNAME, username); try { user = (UserAccount) query.getSingleResult(); memcacheService.put(username, user, Expiration.byDeltaSeconds(DEFAULT_EXPIRATION)); } catch (NoResultException e) { throw new UsernameNotFoundException("Username not found.", e); } } authorities.add(new SimpleGrantedAuthority(user.getRole())); return new EnhancedUser(user.getUsername(), user.getEmail(), user.getDisplayName(), user.getPassword(), user.getSalt(), user.isEnabled(), user.isAccountNonExpired(), user.isCredentialsNonExpired(), user.isAccountNonLocked(), authorities); } /** * Returns the user account for the given username. * * @param username the username * @return the user account */ @Override public final UserAccount getUser(final String username) { UserAccount user = (UserAccount) memcacheService.get(username); if (user == null) { final Query query = entityManager.createQuery("SELECT u FROM UserAccount u WHERE username = :username"); query.setParameter(USERNAME, username); try { user = (UserAccount) query.getSingleResult(); memcacheService.put(username, user, Expiration.byDeltaSeconds(DEFAULT_EXPIRATION)); } catch (NoResultException e) { return null; } } return user; } /** * Adds a user. * * @param user the user * @param locale the locale */ @Override @Transactional public final void addUser(final UserAccount user, final Locale locale) { final UserAccount cachedUser = (UserAccount) memcacheService.get(user.getUsername()); if (cachedUser != null) { throw new DuplicateUserException(); } final Query query = entityManager.createQuery("SELECT u FROM UserAccount u WHERE username = :username"); query.setParameter(USERNAME, user.getUsername()); @SuppressWarnings("unchecked") final List results = query.getResultList(); if (results != null && !results.isEmpty()) { throw new DuplicateUserException(); } entityManager.persist(user); memcacheService.put(user.getUsername(), user, Expiration.byDeltaSeconds(DEFAULT_EXPIRATION)); final TaskOptions taskOptions = TaskOptions.Builder.withUrl(mailTaskUrl) .param("username", user.getUsername()).param("locale", locale.toString()); final Queue queue = QueueFactory.getQueue(mailTaskName); queue.add(datastoreService.getCurrentTransaction(), taskOptions); } /** * Activates the user with the given activation key. * * @param key the activation key * @return true if successful; false otherwise */ @Override @Transactional public final boolean activateUser(final String key) { final Query query = entityManager.createQuery("SELECT u FROM UserAccount u WHERE activationKey = :key"); query.setParameter("key", key); try { final UserAccount user = (UserAccount) query.getSingleResult(); user.setEnabled(true); entityManager.persist(user); memcacheService.put(user.getUsername(), user, Expiration.byDeltaSeconds(DEFAULT_EXPIRATION)); return true; } catch (NoResultException e) { return false; } } /** * Indicates if the activation e-mail has been sent. * * @param username the username * @return true if sent; false otherwise */ @Override public final boolean isActivationEmailSent(final String username) { UserAccount user = (UserAccount) memcacheService.get(username); if (user == null) { final Query query = entityManager.createQuery(SELECT_USER); query.setParameter(USERNAME, username); try { user = (UserAccount) query.getSingleResult(); memcacheService.put(username, user, Expiration.byDeltaSeconds(DEFAULT_EXPIRATION)); } catch (NoResultException e) { throw new UsernameNotFoundException("Username not found.", e); } } return user.isActivationEmailSent(); } /** * Updates the activation e-mail sent status. * * @param username the username */ @Override @Transactional public final void activationEmailSent(final String username) { final Query query = entityManager.createQuery(SELECT_USER); query.setParameter(USERNAME, username); try { final UserAccount user = (UserAccount) query.getSingleResult(); user.setActivationEmailSent(true); entityManager.persist(user); memcacheService.put(user.getUsername(), user, Expiration.byDeltaSeconds(DEFAULT_EXPIRATION)); } catch (NoResultException e) { throw new UsernameNotFoundException("Username not found.", e); } } }