Java tutorial
/* * Copyright (C) 2013 tarent AG * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.osiam.resources.provisioning; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.inject.Inject; import javax.persistence.NoResultException; import javax.persistence.PersistenceException; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; import org.osiam.resources.converter.UserConverter; import org.osiam.resources.exceptions.ResourceExistsException; import org.osiam.resources.exceptions.ResourceNotFoundException; import org.osiam.resources.provisioning.update.UserUpdater; import org.osiam.resources.scim.Constants; import org.osiam.resources.scim.SCIMSearchResult; import org.osiam.resources.scim.User; import org.osiam.storage.dao.SearchResult; import org.osiam.storage.dao.UserDao; import org.osiam.storage.entities.UserEntity; import org.osiam.storage.parser.LogicalOperatorRulesLexer; import org.osiam.storage.parser.LogicalOperatorRulesParser; import org.osiam.storage.query.EvalVisitor; import org.osiam.storage.query.OsiamAntlrErrorListener; import org.osiam.storage.query.QueryFilterParser; import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.stereotype.Service; import com.google.common.base.Strings; @Service public class SCIMUserProvisioning implements SCIMProvisioning<User> { private static final Logger LOGGER = Logger.getLogger(SCIMUserProvisioning.class.getName()); @Inject private UserConverter userConverter; @Inject private UserDao userDao; @Inject private PasswordEncoder passwordEncoder; @Inject private UserUpdater userUpdater; @Inject private QueryFilterParser queryFilterParser; @Override public User getById(String id) { try { UserEntity userEntity = userDao.getById(id); User user = userConverter.toScim(userEntity); return getUserWithoutPassword(user); } catch (NoResultException nre) { LOGGER.log(Level.INFO, nre.getMessage(), nre); throw new ResourceNotFoundException(String.format("User with id '%s' not found", id), nre); } catch (PersistenceException pe) { LOGGER.log(Level.WARNING, pe.getMessage(), pe); throw new ResourceNotFoundException(String.format("User with id '%s' not found", id), pe); } } @Override public User create(User user) { if (userDao.isUserNameAlreadyTaken(user.getUserName())) { throw new ResourceExistsException(String .format("Can't create a user. The username \"%s\" is already taken.", user.getUserName())); } if (userDao.isExternalIdAlreadyTaken(user.getExternalId())) { throw new ResourceExistsException(String .format("Can't create a user. The externalId \"%s\" is already taken.", user.getExternalId())); } UserEntity userEntity = userConverter.fromScim(user); userEntity.setId(UUID.randomUUID()); String hashedPassword = passwordEncoder.encodePassword(user.getPassword(), userEntity.getId()); userEntity.setPassword(hashedPassword); userDao.create(userEntity); User result = getUserWithoutPassword(userConverter.toScim(userEntity)); return result; } @Override public User replace(String id, User user) { UserEntity existingEntity = userDao.getById(id); if (userDao.isUserNameAlreadyTaken(user.getUserName(), id)) { throw new ResourceExistsException(String.format( "Can't replace the user with the id \"%s\". The username \"%s\" is already taken.", id, user.getUserName())); } if (userDao.isExternalIdAlreadyTaken(user.getExternalId(), id)) { throw new ResourceExistsException(String.format( "Can't replace the user with the id \"%s\". The externalId \"%s\" is already taken.", id, user.getExternalId())); } UserEntity userEntity = userConverter.fromScim(user); userEntity.setInternalId(existingEntity.getInternalId()); userEntity.setMeta(existingEntity.getMeta()); userEntity.setId(existingEntity.getId()); if (user.getPassword() != null && !user.getPassword().isEmpty()) { String hashedPassword = passwordEncoder.encodePassword(user.getPassword(), userEntity.getId()); userEntity.setPassword(hashedPassword); } else { userEntity.setPassword(existingEntity.getPassword()); } userEntity.touch(); userEntity = userDao.update(userEntity); User result = getUserWithoutPassword(userConverter.toScim(userEntity)); return result; } @Override public SCIMSearchResult<User> search(String filter, String sortBy, String sortOrder, int count, int startIndex) { List<User> users = new ArrayList<>(); ParseTree filterTree = queryFilterParser.getParseTree(filter); SearchResult<UserEntity> result = userDao.search(filterTree, sortBy, sortOrder, count, startIndex - 1); if (searchedForPasswordAndNoResult(result, filter)) { sleepIfForPasswordWasSearched(filterTree); } for (UserEntity userEntity : result.results) { User scimResultUser = userConverter.toScim(userEntity); users.add(getUserWithoutPassword(scimResultUser)); } return new SCIMSearchResult<>(users, result.totalResults, count, startIndex, Constants.USER_CORE_SCHEMA); } private boolean searchedForPasswordAndNoResult(SearchResult<UserEntity> result, String filter) { return result.totalResults == 0 && filter.contains("password"); } private void sleepIfForPasswordWasSearched(ParseTree tree) { if (tree == null) { return; } String leaf = tree.getText(); if (leaf.equalsIgnoreCase("password")) { try { Thread.sleep(500); return; } catch (InterruptedException e) { // doesn't matter } } for (int counter = 0; counter < tree.getChildCount(); counter++) { sleepIfForPasswordWasSearched(tree.getChild(counter)); } } @Override public User update(String id, User user) { UserEntity userEntity = userDao.getById(id); if (userDao.isUserNameAlreadyTaken(user.getUserName(), id)) { throw new ResourceExistsException( String.format("Can't update the user with the id \"%s\". The username \"%s\" is already taken.", id, user.getUserName())); } if (userDao.isExternalIdAlreadyTaken(user.getExternalId(), id)) { throw new ResourceExistsException(String.format( "Can't update the user with the id \"%s\". The externalId \"%s\" is already taken.", id, user.getExternalId())); } userUpdater.update(user, userEntity); userEntity.touch(); User result = getUserWithoutPassword(userConverter.toScim(userEntity)); return result; } @Override public void delete(String id) { try { userDao.delete(id); } catch (NoResultException nre) { throw new ResourceNotFoundException(String.format("User with id '%s' not found", id), nre); } } private User getUserWithoutPassword(User user) { return new User.Builder(user).setPassword(null).build(); } }