diff --git a/scm-core/src/main/java/sonia/scm/ModelObject.java b/scm-core/src/main/java/sonia/scm/ModelObject.java index 76ba021e67..cca9608ceb 100644 --- a/scm-core/src/main/java/sonia/scm/ModelObject.java +++ b/scm-core/src/main/java/sonia/scm/ModelObject.java @@ -53,5 +53,11 @@ public interface ModelObject * * @return unique id */ - public String getId(); + String getId(); + + void setLastModified(Long timestamp); + + Long getCreationDate(); + + void setCreationDate(Long timestamp); } diff --git a/scm-core/src/main/java/sonia/scm/group/GroupAlreadyExistsException.java b/scm-core/src/main/java/sonia/scm/group/GroupAlreadyExistsException.java index e63ee1d78b..2b3c73535e 100644 --- a/scm-core/src/main/java/sonia/scm/group/GroupAlreadyExistsException.java +++ b/scm-core/src/main/java/sonia/scm/group/GroupAlreadyExistsException.java @@ -42,15 +42,9 @@ package sonia.scm.group; public class GroupAlreadyExistsException extends GroupException { - /** Field description */ private static final long serialVersionUID = 4042878550219750430L; - /** - * Constructs a new instance. - * - * @param name The name (aka id) of the group - */ - public GroupAlreadyExistsException(String name) { - super(name + " group already exists"); + public GroupAlreadyExistsException(Group group) { + super(group.getName() + " group already exists"); } } diff --git a/scm-core/src/main/java/sonia/scm/group/GroupNotFoundException.java b/scm-core/src/main/java/sonia/scm/group/GroupNotFoundException.java index d4c06a1559..d1769da9e9 100644 --- a/scm-core/src/main/java/sonia/scm/group/GroupNotFoundException.java +++ b/scm-core/src/main/java/sonia/scm/group/GroupNotFoundException.java @@ -53,6 +53,6 @@ public class GroupNotFoundException extends GroupException * */ public GroupNotFoundException() { - super("group does not exists"); + super("group does not exist"); } } diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java index f1649efb43..4160fb1424 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java @@ -52,17 +52,11 @@ public class RepositoryNotFoundException extends RepositoryException * error detail message. * */ - public RepositoryNotFoundException() {} + public RepositoryNotFoundException() { + super("repository does not exist"); + } - /** - * Constructs a new {@link RepositoryNotFoundException} with the specified - * error detail message. - * - * - * @param message error detail message - */ - public RepositoryNotFoundException(String message) - { - super(message); + public RepositoryNotFoundException(String repositoryId) { + super("repository with id " + repositoryId + " does not exist"); } } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java index 5bd737a85a..315156db0d 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java @@ -37,20 +37,19 @@ package sonia.scm.repository.api; import com.github.legman.ReferenceType; import com.github.legman.Subscribe; - import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.Sets; import com.google.inject.Inject; import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.HandlerEventType; import sonia.scm.cache.Cache; import sonia.scm.cache.CacheManager; import sonia.scm.config.ScmConfiguration; +import sonia.scm.event.ScmEventBus; +import sonia.scm.repository.ClearRepositoryCacheEvent; import sonia.scm.repository.PostReceiveRepositoryHookEvent; import sonia.scm.repository.PreProcessorUtil; import sonia.scm.repository.Repository; @@ -63,11 +62,9 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import sonia.scm.repository.spi.RepositoryServiceResolver; import sonia.scm.security.ScmSecurityException; -//~--- JDK imports ------------------------------------------------------------ - import java.util.Set; -import sonia.scm.event.ScmEventBus; -import sonia.scm.repository.ClearRepositoryCacheEvent; + +//~--- JDK imports ------------------------------------------------------------ /** * The {@link RepositoryServiceFactory} is the entrypoint of the repository api. @@ -179,8 +176,7 @@ public final class RepositoryServiceFactory if (repository == null) { - throw new RepositoryNotFoundException( - "could not find a repository with id ".concat(repositoryId)); + throw new RepositoryNotFoundException(repositoryId); } return create(repository); diff --git a/scm-core/src/main/java/sonia/scm/user/UserAlreadyExistsException.java b/scm-core/src/main/java/sonia/scm/user/UserAlreadyExistsException.java index 52b91fa229..1c77cb4f86 100644 --- a/scm-core/src/main/java/sonia/scm/user/UserAlreadyExistsException.java +++ b/scm-core/src/main/java/sonia/scm/user/UserAlreadyExistsException.java @@ -41,19 +41,11 @@ package sonia.scm.user; public class UserAlreadyExistsException extends UserException { - /** Field description */ private static final long serialVersionUID = 9182294539718090814L; //~--- constructors --------------------------------------------------------- - /** - * Constructs a new instance. - * - * @param name The name (aka id) of the user - * @since 1.5 - */ - public UserAlreadyExistsException(String name) - { - super(name + " user already exists"); + public UserAlreadyExistsException(User user) { + super(user.getName() + " user already exists"); } } diff --git a/scm-core/src/main/java/sonia/scm/user/UserNotFoundException.java b/scm-core/src/main/java/sonia/scm/user/UserNotFoundException.java index e5755c2546..0f11615987 100644 --- a/scm-core/src/main/java/sonia/scm/user/UserNotFoundException.java +++ b/scm-core/src/main/java/sonia/scm/user/UserNotFoundException.java @@ -52,6 +52,6 @@ public class UserNotFoundException extends UserException * */ public UserNotFoundException() { - super("user does not exists"); + super("user does not exist"); } } diff --git a/scm-webapp/src/main/java/sonia/scm/ManagerDaoAdapter.java b/scm-webapp/src/main/java/sonia/scm/ManagerDaoAdapter.java new file mode 100644 index 0000000000..0f26a691b3 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/ManagerDaoAdapter.java @@ -0,0 +1,59 @@ +package sonia.scm; + +import com.github.sdorra.ssp.PermissionCheck; +import sonia.scm.util.AssertUtil; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class ManagerDaoAdapter { + + private final GenericDAO dao; + private final Supplier notFoundException; + private final Function alreadyExistsException; + + public ManagerDaoAdapter(GenericDAO dao, Supplier notFoundException, Function alreadyExistsException) { + this.dao = dao; + this.notFoundException = notFoundException; + this.alreadyExistsException = alreadyExistsException; + } + + public void modify(T object, Function permissionCheck, AroundHandler beforeUpdate, AroundHandler afterUpdate) throws E { + String name = object.getId(); + + T notModified = dao.get(name); + if (notModified != null) { + permissionCheck.apply(notModified).check(); + AssertUtil.assertIsValid(object); + + beforeUpdate.handle(notModified); + + object.setLastModified(System.currentTimeMillis()); + object.setCreationDate(notModified.getCreationDate()); + + dao.modify(object); + + afterUpdate.handle(notModified); + } else { + throw notFoundException.get(); + } + } + + public T create(T newObject, Supplier permissionCheck, AroundHandler beforeCreate, AroundHandler afterCreate) throws E { + permissionCheck.get().check(); + AssertUtil.assertIsValid(newObject); + if (dao.contains(newObject)) { + throw alreadyExistsException.apply(newObject); + } + newObject.setCreationDate(System.currentTimeMillis()); + beforeCreate.handle(newObject); + dao.add(newObject); + afterCreate.handle(newObject); + return newObject; + } + + @FunctionalInterface + public interface AroundHandler { + void handle(T notModified) throws E; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/group/DefaultGroupManager.java b/scm-webapp/src/main/java/sonia/scm/group/DefaultGroupManager.java index ed1d7723b2..5c6681cc30 100644 --- a/scm-webapp/src/main/java/sonia/scm/group/DefaultGroupManager.java +++ b/scm-webapp/src/main/java/sonia/scm/group/DefaultGroupManager.java @@ -43,6 +43,7 @@ import com.google.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.HandlerEventType; +import sonia.scm.ManagerDaoAdapter; import sonia.scm.SCMContextProvider; import sonia.scm.TransformFilter; import sonia.scm.search.SearchRequest; @@ -84,6 +85,10 @@ public class DefaultGroupManager extends AbstractGroupManager public DefaultGroupManager(GroupDAO groupDAO) { this.groupDAO = groupDAO; + this.managerDaoAdapter = new ManagerDaoAdapter<>( + groupDAO, + GroupNotFoundException::new, + GroupAlreadyExistsException::new); } //~--- methods -------------------------------------------------------------- @@ -101,46 +106,23 @@ public class DefaultGroupManager extends AbstractGroupManager // do nothing } - /** - * Method description - * - * - * @param group - * - * @throws GroupException - * @throws IOException - */ @Override - public Group create(Group group) throws GroupException - { + public Group create(Group group) throws GroupException { String type = group.getType(); - - if (Util.isEmpty(type)) - { + if (Util.isEmpty(type)) { group.setType(groupDAO.getType()); } - String name = group.getName(); - - if (logger.isInfoEnabled()) - { - logger.info("create group {} of type {}", name, - group.getType()); - } - - GroupPermissions.create().check(); - - if (groupDAO.contains(name)) - { - throw new GroupAlreadyExistsException(name); - } + logger.info("create group {} of type {}", group.getName(), group.getType()); removeDuplicateMembers(group); - group.setCreationDate(System.currentTimeMillis()); - fireEvent(HandlerEventType.BEFORE_CREATE, group); - groupDAO.add(group); - fireEvent(HandlerEventType.CREATE, group); - return group; + + return managerDaoAdapter.create( + group, + GroupPermissions::create, + newGroup -> fireEvent(HandlerEventType.BEFORE_CREATE, newGroup), + newGroup -> fireEvent(HandlerEventType.CREATE, newGroup) + ); } /** @@ -195,31 +177,18 @@ public class DefaultGroupManager extends AbstractGroupManager * @throws IOException */ @Override - public void modify(Group group) throws GroupException - { - if (logger.isInfoEnabled()) - { - logger.info("modify group {} of type {}", group.getName(), - group.getType()); - } + public void modify(Group group) throws GroupException { + logger.info("modify group {} of type {}", group.getName(), group.getType()); - String name = group.getName(); - GroupPermissions.modify().check(name); - - Group notModified = groupDAO.get(name); - if (notModified != null) - { - removeDuplicateMembers(group); - fireEvent(HandlerEventType.BEFORE_MODIFY, group, notModified); - group.setLastModified(System.currentTimeMillis()); - group.setCreationDate(notModified.getCreationDate()); - groupDAO.modify(group); - fireEvent(HandlerEventType.MODIFY, group, notModified); - } - else - { - throw new GroupNotFoundException(); - } + managerDaoAdapter.modify( + group, + GroupPermissions::modify, + notModified -> { + removeDuplicateMembers(group); + fireEvent(HandlerEventType.BEFORE_MODIFY, group, notModified); + }, + notModified -> fireEvent(HandlerEventType.MODIFY, group, notModified) + ); } /** @@ -458,4 +427,5 @@ public class DefaultGroupManager extends AbstractGroupManager /** Field description */ private GroupDAO groupDAO; + private final ManagerDaoAdapter managerDaoAdapter; } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index ffcf3d8dc3..13f0ce79c3 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory; import sonia.scm.ArgumentIsInvalidException; import sonia.scm.ConfigurationException; import sonia.scm.HandlerEventType; +import sonia.scm.ManagerDaoAdapter; import sonia.scm.SCMContextProvider; import sonia.scm.Type; import sonia.scm.config.ScmConfiguration; @@ -90,6 +91,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { private final Set types; private RepositoryMatcher repositoryMatcher; private NamespaceStrategy namespaceStrategy; + private final ManagerDaoAdapter managerDaoAdapter; @Inject @@ -116,6 +118,10 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { for (RepositoryHandler handler : handlerSet) { addHandler(contextProvider, handler); } + managerDaoAdapter = new ManagerDaoAdapter<>( + repositoryDAO, + RepositoryNotFoundException::new, + RepositoryAlreadyExistsException::create); } @@ -128,55 +134,28 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { } } - /** - * Method description - * - * - * @param repository - * @param initRepository - * - * @throws IOException - * @throws RepositoryException - */ - public Repository create(Repository repository, boolean initRepository) - throws RepositoryException { - logger.info("create repository {} of type {}", repository.getName(), - repository.getType()); - - RepositoryPermissions.create().check(); - AssertUtil.assertIsValid(repository); - - if (repositoryDAO.contains(repository)) { - throw RepositoryAlreadyExistsException.create(repository); - } - - repository.setId(keyGenerator.createKey()); - repository.setCreationDate(System.currentTimeMillis()); - repository.setNamespace(namespaceStrategy.getNamespace()); - - if (initRepository) { - getHandler(repository).create(repository); - } - - fireEvent(HandlerEventType.BEFORE_CREATE, repository); - repositoryDAO.add(repository); - fireEvent(HandlerEventType.CREATE, repository); - return repository; + @Override + public Repository create(Repository repository) throws RepositoryException { + return create(repository, true); } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ - @Override - public Repository create(Repository repository) - throws RepositoryException { - return create(repository, true); + public Repository create(Repository repository, boolean initRepository) throws RepositoryException { + repository.setId(keyGenerator.createKey()); + repository.setNamespace(namespaceStrategy.getNamespace()); + + logger.info("create repository {} of type {} in namespace {}", repository.getName(), repository.getType(), repository.getNamespace()); + + return managerDaoAdapter.create( + repository, + RepositoryPermissions::create, + newRepository -> { + if (initRepository) { + getHandler(newRepository).create(newRepository); + } + fireEvent(HandlerEventType.BEFORE_CREATE, newRepository); + }, + newRepository -> fireEvent(HandlerEventType.CREATE, newRepository) + ); } /** @@ -209,8 +188,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { repositoryDAO.delete(repository); fireEvent(HandlerEventType.DELETE, repository); } else { - throw new RepositoryNotFoundException( - "repository ".concat(repository.getName()).concat(" not found")); + throw new RepositoryNotFoundException(); } } @@ -249,30 +227,18 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { * @throws RepositoryException */ @Override - public void modify(Repository repository) - throws RepositoryException { - if (logger.isInfoEnabled()) { - logger.info("modify repository {} of type {}", repository.getName(), - repository.getType()); - } + public void modify(Repository repository) throws RepositoryException { + logger.info("modify repository {} of type {}", repository.getName(), repository.getType()); - AssertUtil.assertIsValid(repository); - - Repository oldRepository = repositoryDAO.get(repository.getType(), - repository.getName()); - - if (oldRepository != null) { - RepositoryPermissions.modify(oldRepository).check(); - fireEvent(HandlerEventType.BEFORE_MODIFY, repository, oldRepository); - repository.setLastModified(System.currentTimeMillis()); - repository.setCreationDate(oldRepository.getCreationDate()); - getHandler(repository).modify(repository); - repositoryDAO.modify(repository); - fireEvent(HandlerEventType.MODIFY, repository, oldRepository); - } else { - throw new RepositoryNotFoundException( - "repository ".concat(repository.getName()).concat(" not found")); - } + managerDaoAdapter.modify( + repository, + RepositoryPermissions::modify, + notModified -> { + fireEvent(HandlerEventType.BEFORE_MODIFY, repository, notModified); + getHandler(repository).modify(repository); + }, + notModified -> fireEvent(HandlerEventType.MODIFY, repository, notModified) + ); } /** @@ -296,8 +262,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { if (fresh != null) { fresh.copyProperties(repository); } else { - throw new RepositoryNotFoundException( - "repository ".concat(repository.getName()).concat(" not found")); + throw new RepositoryNotFoundException(); } } @@ -638,5 +603,4 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return handler; } - } diff --git a/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java b/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java index 5a13a7fef8..2b63a33a89 100644 --- a/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java +++ b/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java @@ -41,11 +41,11 @@ import com.google.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.HandlerEventType; +import sonia.scm.ManagerDaoAdapter; import sonia.scm.SCMContextProvider; import sonia.scm.TransformFilter; import sonia.scm.search.SearchRequest; import sonia.scm.search.SearchUtil; -import sonia.scm.util.AssertUtil; import sonia.scm.util.CollectionAppender; import sonia.scm.util.IOUtil; import sonia.scm.util.Util; @@ -96,6 +96,10 @@ public class DefaultUserManager extends AbstractUserManager public DefaultUserManager(UserDAO userDAO) { this.userDAO = userDAO; + this.managerDaoAdapter = new ManagerDaoAdapter<>( + userDAO, + UserNotFoundException::new, + UserAlreadyExistsException::new); } //~--- methods -------------------------------------------------------------- @@ -137,33 +141,20 @@ public class DefaultUserManager extends AbstractUserManager * @throws UserException */ @Override - public User create(User user) throws UserException - { + public User create(User user) throws UserException { String type = user.getType(); - - if (Util.isEmpty(type)) - { + if (Util.isEmpty(type)) { user.setType(userDAO.getType()); } - if (logger.isInfoEnabled()) - { - logger.info("create user {} of type {}", user.getName(), user.getType()); - } + logger.info("create user {} of type {}", user.getName(), user.getType()); - UserPermissions.create().check(); - - if (userDAO.contains(user.getName())) - { - throw new UserAlreadyExistsException(user.getName()); - } - - AssertUtil.assertIsValid(user); - user.setCreationDate(System.currentTimeMillis()); - fireEvent(HandlerEventType.BEFORE_CREATE, user); - userDAO.add(user); - fireEvent(HandlerEventType.CREATE, user); - return user; + return managerDaoAdapter.create( + user, + UserPermissions::create, + newUser -> fireEvent(HandlerEventType.BEFORE_CREATE, newUser), + newUser -> fireEvent(HandlerEventType.CREATE, newUser) + ); } /** @@ -227,27 +218,13 @@ public class DefaultUserManager extends AbstractUserManager @Override public void modify(User user) throws UserException { - String name = user.getName(); - if (logger.isInfoEnabled()) - { - logger.info("modify user {} of type {}", user.getName(), user.getType()); - } - - UserPermissions.modify(user).check(); - User notModified = userDAO.get(name); - if (notModified != null) - { - AssertUtil.assertIsValid(user); - fireEvent(HandlerEventType.BEFORE_MODIFY, user, notModified); - user.setLastModified(System.currentTimeMillis()); - user.setCreationDate(notModified.getCreationDate()); - userDAO.modify(user); - fireEvent(HandlerEventType.MODIFY, user, notModified); - } - else - { - throw new UserNotFoundException(); - } + logger.info("modify user {} of type {}", user.getName(), user.getType()); + + managerDaoAdapter.modify( + user, + UserPermissions::modify, + notModified -> fireEvent(HandlerEventType.BEFORE_MODIFY, user, notModified), + notModified -> fireEvent(HandlerEventType.MODIFY, user, notModified)); } /** @@ -497,6 +474,6 @@ public class DefaultUserManager extends AbstractUserManager //~--- fields --------------------------------------------------------------- - /** Field description */ private final UserDAO userDAO; + private final ManagerDaoAdapter managerDaoAdapter; } diff --git a/scm-webapp/src/test/java/sonia/scm/api/rest/resources/AbstractManagerResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/rest/resources/AbstractManagerResourceTest.java index e8421bc417..b3e931188a 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/rest/resources/AbstractManagerResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/rest/resources/AbstractManagerResourceTest.java @@ -105,6 +105,21 @@ public class AbstractManagerResourceTest { return id; } + @Override + public void setLastModified(Long timestamp) { + + } + + @Override + public Long getCreationDate() { + return null; + } + + @Override + public void setCreationDate(Long timestamp) { + + } + @Override public Long getLastModified() { return null;