Merged 2.0.0-m3 into feature/repository_config_v2_endpoint

This commit is contained in:
Johannes Schnatterer
2018-08-07 17:37:25 +02:00
151 changed files with 5294 additions and 4670 deletions

View File

@@ -4,6 +4,7 @@ import com.github.sdorra.ssp.PermissionCheck;
import sonia.scm.util.AssertUtil;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class ManagerDaoAdapter<T extends ModelObject, E extends Exception> {
@@ -38,9 +39,13 @@ public class ManagerDaoAdapter<T extends ModelObject, E extends Exception> {
}
public T create(T newObject, Supplier<PermissionCheck> permissionCheck, AroundHandler<T, E> beforeCreate, AroundHandler<T, E> afterCreate) throws E {
return create(newObject, permissionCheck, beforeCreate, afterCreate, dao::contains);
}
public T create(T newObject, Supplier<PermissionCheck> permissionCheck, AroundHandler<T, E> beforeCreate, AroundHandler<T, E> afterCreate, Predicate<T> existsCheck) throws E {
permissionCheck.get().check();
AssertUtil.assertIsValid(newObject);
if (dao.contains(newObject)) {
if (existsCheck.test(newObject)) {
throw alreadyExistsException.apply(newObject);
}
newObject.setCreationDate(System.currentTimeMillis());

View File

@@ -374,20 +374,6 @@ public abstract class AbstractManagerResource<T extends ModelObject,
throwable.getMessage(), throwable);
}
/**
* Method description
*
*
* @param status
* @param throwable
*
* @return
*/
protected Response createErrorResponse(Status status, Throwable throwable)
{
return createErrorResponse(status, throwable.getMessage(), throwable);
}
/**
* Method description
*

View File

@@ -0,0 +1,32 @@
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static de.otto.edison.hal.Embedded.embeddedBuilder;
import static de.otto.edison.hal.Links.linkingTo;
abstract class CollectionToDtoMapper<E, D extends HalRepresentation> {
private final String collectionName;
private final BaseMapper<E, D> mapper;
protected CollectionToDtoMapper(String collectionName, BaseMapper<E, D> mapper) {
this.collectionName = collectionName;
this.mapper = mapper;
}
public HalRepresentation map(Collection<E> collection) {
List<D> dtos = collection.stream().map(mapper::map).collect(Collectors.toList());
return new HalRepresentation(
linkingTo().self(createSelfLink()).build(),
embeddedBuilder().with(collectionName, dtos).build()
);
}
protected abstract String createSelfLink();
}

View File

@@ -16,6 +16,9 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
/**
* RESTful Web Service Resource to manage the configuration.
*/
@Path(ConfigResource.CONFIG_PATH_V2)
public class ConfigResource {

View File

@@ -42,7 +42,7 @@ public class GroupCollectionResource {
@GET
@Path("")
@Produces(VndMediaType.GROUP_COLLECTION)
@TypeHint(GroupDto[].class)
@TypeHint(CollectionDto.class)
@StatusCodes({
@ResponseCode(code = 200, condition = "success"),
@ResponseCode(code = 400, condition = "\"sortBy\" field unknown"),

View File

@@ -21,6 +21,9 @@ public class MapperModule extends AbstractModule {
bind(RepositoryToRepositoryDtoMapper.class).to(Mappers.getMapper(RepositoryToRepositoryDtoMapper.class).getClass());
bind(RepositoryDtoToRepositoryMapper.class).to(Mappers.getMapper(RepositoryDtoToRepositoryMapper.class).getClass());
bind(RepositoryTypeToRepositoryTypeDtoMapper.class).to(Mappers.getMapper(RepositoryTypeToRepositoryTypeDtoMapper.class).getClass());
bind(RepositoryTypeCollectionToDtoMapper.class);
bind(UriInfoStore.class).in(ServletScopes.REQUEST);
}
}

View File

@@ -19,6 +19,9 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* RESTful Web Service Resource to get currently logged in users.
*/
@Path(MeResource.ME_PATH_V2)
public class MeResource {
static final String ME_PATH_V2 = "v2/me/";

View File

@@ -40,7 +40,7 @@ public class RepositoryCollectionResource {
@GET
@Path("")
@Produces(VndMediaType.REPOSITORY_COLLECTION)
@TypeHint(RepositoryDto[].class)
@TypeHint(CollectionDto.class)
@StatusCodes({
@ResponseCode(code = 200, condition = "success"),
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),

View File

@@ -3,14 +3,22 @@ package sonia.scm.api.v2.resources;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryIsNotArchivedException;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.util.Optional;
import java.util.function.Predicate;
@@ -40,7 +48,7 @@ public class RepositoryResource {
this.dtoToRepositoryMapper = dtoToRepositoryMapper;
this.manager = manager;
this.repositoryToDtoMapper = repositoryToDtoMapper;
this.adapter = new SingleResourceManagerAdapter<>(manager, Repository.class);
this.adapter = new SingleResourceManagerAdapter<>(manager, Repository.class, this::handleNotArchived);
this.tagRootResource = tagRootResource;
this.branchRootResource = branchRootResource;
this.changesetRootResource = changesetRootResource;
@@ -148,8 +156,16 @@ public class RepositoryResource {
return permissionRootResource.get();
}
private Optional<Response> handleNotArchived(Throwable throwable) {
if (throwable instanceof RepositoryIsNotArchivedException) {
return Optional.of(Response.status(Response.Status.PRECONDITION_FAILED).build());
} else {
return Optional.empty();
}
}
private Supplier<Optional<Repository>> loadBy(String namespace, String name) {
return () -> manager.getByNamespace(namespace, name);
return () -> Optional.ofNullable(manager.get(new NamespaceAndName(namespace, name)));
}
private Predicate<Repository> nameAndNamespaceStaysTheSame(String namespace, String name) {

View File

@@ -25,6 +25,7 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper<Reposit
@AfterMapping
void appendLinks(Repository repository, @MappingTarget RepositoryDto target) {
Links.Builder linksBuilder = linkingTo().self(resourceLinks.repository().self(target.getNamespace(), target.getName()));
linksBuilder.single(link("httpProtocol", resourceLinks.repository().clone(target.getType(), target.getNamespace(), target.getName())));
if (RepositoryPermissions.delete(repository).isPermitted()) {
linksBuilder.single(link("delete", resourceLinks.repository().delete(target.getNamespace(), target.getName())));
}

View File

@@ -0,0 +1,36 @@
package sonia.scm.api.v2.resources;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import de.otto.edison.hal.HalRepresentation;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
public class RepositoryTypeCollectionResource {
private RepositoryManager repositoryManager;
private RepositoryTypeCollectionToDtoMapper mapper;
@Inject
public RepositoryTypeCollectionResource(RepositoryManager repositoryManager, RepositoryTypeCollectionToDtoMapper mapper) {
this.repositoryManager = repositoryManager;
this.mapper = mapper;
}
@GET
@Path("")
@StatusCodes({
@ResponseCode(code = 200, condition = "success"),
@ResponseCode(code = 500, condition = "internal server error")
})
@Produces(VndMediaType.REPOSITORY_TYPE_COLLECTION)
public HalRepresentation getAll() {
return mapper.map(repositoryManager.getConfiguredTypes());
}
}

View File

@@ -0,0 +1,21 @@
package sonia.scm.api.v2.resources;
import sonia.scm.repository.RepositoryType;
import javax.inject.Inject;
public class RepositoryTypeCollectionToDtoMapper extends CollectionToDtoMapper<RepositoryType, RepositoryTypeDto> {
private final ResourceLinks resourceLinks;
@Inject
public RepositoryTypeCollectionToDtoMapper(RepositoryTypeToRepositoryTypeDtoMapper mapper, ResourceLinks resourceLinks) {
super("repositoryTypes", mapper);
this.resourceLinks = resourceLinks;
}
@Override
protected String createSelfLink() {
return resourceLinks.repositoryTypeCollection().self();
}
}

View File

@@ -0,0 +1,22 @@
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Links;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@NoArgsConstructor
@Getter
@Setter
public class RepositoryTypeDto extends HalRepresentation {
private String name;
private String displayName;
@Override
@SuppressWarnings("squid:S1185") // We want to have this method available in this package
protected HalRepresentation add(Links links) {
return super.add(links);
}
}

View File

@@ -0,0 +1,53 @@
package sonia.scm.api.v2.resources;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryType;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
public class RepositoryTypeResource {
private RepositoryManager repositoryManager;
private RepositoryTypeToRepositoryTypeDtoMapper mapper;
@Inject
public RepositoryTypeResource(RepositoryManager repositoryManager, RepositoryTypeToRepositoryTypeDtoMapper mapper) {
this.repositoryManager = repositoryManager;
this.mapper = mapper;
}
/**
* Returns the specified repository type.
*
* <strong>Note:</strong> This method requires "group" privilege.
*
* @param name of the requested repository type
*/
@GET
@Path("")
@Produces(VndMediaType.REPOSITORY_TYPE)
@TypeHint(RepositoryTypeDto.class)
@StatusCodes({
@ResponseCode(code = 200, condition = "success"),
@ResponseCode(code = 404, condition = "not found, no repository type with the specified name available"),
@ResponseCode(code = 500, condition = "internal server error")
})
public Response get(@PathParam("name") String name) {
for (RepositoryType type : repositoryManager.getConfiguredTypes()) {
if (name.equalsIgnoreCase(type.getName())) {
return Response.ok(mapper.map(type)).build();
}
}
return Response.status(Response.Status.NOT_FOUND).build();
}
}

View File

@@ -0,0 +1,35 @@
package sonia.scm.api.v2.resources;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.Path;
/**
* RESTful Web Service Resource to get available repository types.
*/
@Path(RepositoryTypeRootResource.PATH)
public class RepositoryTypeRootResource {
static final String PATH = "v2/repositoryTypes/";
private Provider<RepositoryTypeCollectionResource> collectionResourceProvider;
private Provider<RepositoryTypeResource> resourceProvider;
@Inject
public RepositoryTypeRootResource(Provider<RepositoryTypeCollectionResource> collectionResourceProvider, Provider<RepositoryTypeResource> resourceProvider) {
this.collectionResourceProvider = collectionResourceProvider;
this.resourceProvider = resourceProvider;
}
@Path("")
public RepositoryTypeCollectionResource getRepositoryTypeCollectionResource() {
return collectionResourceProvider.get();
}
@Path("{name}")
public RepositoryTypeResource getRepositoryTypeResource() {
return resourceProvider.get();
}
}

View File

@@ -0,0 +1,25 @@
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Links;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import sonia.scm.repository.RepositoryType;
import javax.inject.Inject;
import static de.otto.edison.hal.Links.linkingTo;
@Mapper
public abstract class RepositoryTypeToRepositoryTypeDtoMapper extends BaseMapper<RepositoryType, RepositoryTypeDto> {
@Inject
private ResourceLinks resourceLinks;
@AfterMapping
void appendLinks(RepositoryType repositoryType, @MappingTarget RepositoryTypeDto target) {
Links.Builder linksBuilder = linkingTo().self(resourceLinks.repositoryType().self(repositoryType.getName()));
target.add(linksBuilder.build());
}
}

View File

@@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources;
import javax.inject.Inject;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
class ResourceLinks {
@@ -127,15 +128,21 @@ class ResourceLinks {
static class RepositoryLinks {
private final LinkBuilder repositoryLinkBuilder;
private final UriInfo uriInfo;
RepositoryLinks(UriInfo uriInfo) {
repositoryLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class);
this.uriInfo = uriInfo;
}
String self(String namespace, String name) {
return repositoryLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("get").parameters().href();
}
String clone(String type, String namespace, String name) {
return uriInfo.getBaseUri().resolve(URI.create("../../" + type + "/" + namespace + "/" + name)).toASCIIString();
}
String delete(String namespace, String name) {
return repositoryLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("delete").parameters().href();
}
@@ -165,6 +172,39 @@ class ResourceLinks {
}
}
public RepositoryTypeLinks repositoryType() {
return new RepositoryTypeLinks(uriInfoStore.get());
}
static class RepositoryTypeLinks {
private final LinkBuilder repositoryTypeLinkBuilder;
RepositoryTypeLinks(UriInfo uriInfo) {
repositoryTypeLinkBuilder = new LinkBuilder(uriInfo, RepositoryTypeRootResource.class, RepositoryTypeResource.class);
}
String self(String name) {
return repositoryTypeLinkBuilder.method("getRepositoryTypeResource").parameters(name).method("get").parameters().href();
}
}
public RepositoryTypeCollectionLinks repositoryTypeCollection() {
return new RepositoryTypeCollectionLinks(uriInfoStore.get());
}
static class RepositoryTypeCollectionLinks {
private final LinkBuilder collectionLinkBuilder;
RepositoryTypeCollectionLinks(UriInfo uriInfo) {
collectionLinkBuilder = new LinkBuilder(uriInfo, RepositoryTypeRootResource.class, RepositoryTypeCollectionResource.class);
}
String self() {
return collectionLinkBuilder.method("getRepositoryTypeCollectionResource").parameters().method("getAll").parameters().href();
}
}
public TagCollectionLinks tagCollection() {
return new TagCollectionLinks(uriInfoStore.get());
}

View File

@@ -31,8 +31,15 @@ class SingleResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
DTO extends HalRepresentation,
EXCEPTION extends Exception> extends AbstractManagerResource<MODEL_OBJECT, EXCEPTION> {
private final Function<Throwable, Optional<Response>> errorHandler;
SingleResourceManagerAdapter(Manager<MODEL_OBJECT, EXCEPTION> manager, Class<MODEL_OBJECT> type) {
this(manager, type, e -> Optional.empty());
}
SingleResourceManagerAdapter(Manager<MODEL_OBJECT, EXCEPTION> manager, Class<MODEL_OBJECT> type, Function<Throwable, Optional<Response>> errorHandler) {
super(manager, type);
this.errorHandler = errorHandler;
}
/**
@@ -70,6 +77,11 @@ class SingleResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
.orElse(null);
}
@Override
protected Response createErrorResponse(Throwable throwable) {
return errorHandler.apply(throwable).orElse(super.createErrorResponse(throwable));
}
@Override
protected GenericEntity<Collection<MODEL_OBJECT>> createGenericEntity(Collection<MODEL_OBJECT> modelObjects) {
throw new UnsupportedOperationException();

View File

@@ -42,7 +42,7 @@ public class UserCollectionResource {
@GET
@Path("")
@Produces(VndMediaType.USER_COLLECTION)
@TypeHint(UserDto[].class)
@TypeHint(CollectionDto.class)
@StatusCodes({
@ResponseCode(code = 200, condition = "success"),
@ResponseCode(code = 400, condition = "\"sortBy\" field unknown"),

View File

@@ -34,13 +34,14 @@ import com.github.legman.ReferenceType;
import com.github.legman.Subscribe;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.EagerSingleton;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.PostReceiveRepositoryHookEvent;
import javax.inject.Inject;
/**
* {@link PostReceiveRepositoryHookEvent} which stores receives data and passes it to the {@link DebugService}.
*
@@ -78,7 +79,7 @@ public final class DebugHook
LOG.trace("store changeset ids from repository", event.getRepository().getId());
debugService.put(
event.getRepository().getId(),
event.getRepository().getNamespaceAndName(),
new DebugHookData(Collections2.transform(
event.getContext().getChangesetProvider().getChangesetList(), IDEXTRACTOR)
));

View File

@@ -30,20 +30,22 @@
*/
package sonia.scm.debug;
import java.util.Collection;
import sonia.scm.repository.NamespaceAndName;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Collection;
/**
* Rest api resource for the {@link DebugService}.
*
* @author Sebastian Sdorra
*/
@Path("debug/{repository}/post-receive")
@Path("debug/{namespace}/{name}/post-receive")
public final class DebugResource
{
private final DebugService debugService;
@@ -62,28 +64,30 @@ public final class DebugResource
/**
* Returns all received hook data for the given repository.
*
* @param repository repository id
*
* @param namespace repository namespace
* @param name repository name
*
* @return all received hook data for the given repository
*/
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Collection<DebugHookData> getAll(@PathParam("repository") String repository){
return debugService.getAll(repository);
public Collection<DebugHookData> getAll(@PathParam("namespace") String namespace, @PathParam("name") String name){
return debugService.getAll(new NamespaceAndName(namespace, name));
}
/**
* Returns the last received hook data for the given repository.
*
* @param repository repository id
*
* @param namespace repository namespace
* @param name repository name
*
* @return the last received hook data for the given repository
*/
@GET
@Path("last")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public DebugHookData getLast(@PathParam("repository") String repository){
return debugService.getLast(repository);
public DebugHookData getLast(@PathParam("namespace") String namespace, @PathParam("name") String name){
return debugService.getLast(new NamespaceAndName(namespace, name));
}
}

View File

@@ -34,10 +34,12 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.inject.Singleton;
import java.util.Collection;
import org.apache.shiro.SecurityUtils;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.security.Role;
import java.util.Collection;
/**
* The DebugService stores and returns received data from repository hook events.
*
@@ -47,30 +49,23 @@ import sonia.scm.security.Role;
public final class DebugService
{
private final Multimap<String,DebugHookData> receivedHooks = LinkedListMultimap.create();
private final Multimap<NamespaceAndName,DebugHookData> receivedHooks = LinkedListMultimap.create();
/**
* Stores {@link DebugHookData} for the given repository.
*
* @param repository repository id
* @param hookData received hook data
*/
void put(String repository, DebugHookData hookData)
void put(NamespaceAndName namespaceAndName, DebugHookData hookData)
{
receivedHooks.put(repository, hookData);
receivedHooks.put(namespaceAndName, hookData);
}
/**
* Returns the last received hook data for the given repository.
*
* @param repository repository id
*
* @return the last received hook data for the given repository
*/
public DebugHookData getLast(String repository){
public DebugHookData getLast(NamespaceAndName namespaceAndName){
SecurityUtils.getSubject().checkRole(Role.ADMIN);
DebugHookData hookData = null;
Collection<DebugHookData> receivedHookData = receivedHooks.get(repository);
Collection<DebugHookData> receivedHookData = receivedHooks.get(namespaceAndName);
if (receivedHookData != null && ! receivedHookData.isEmpty()){
hookData = Iterables.getLast(receivedHookData);
}
@@ -79,14 +74,9 @@ public final class DebugService
/**
* Returns all received hook data for the given repository.
*
* @param repository repository id
*
* @return all received hook data for the given repository
*/
public Collection<DebugHookData> getAll(String repository){
public Collection<DebugHookData> getAll(NamespaceAndName namespaceAndName){
SecurityUtils.getSubject().checkRole(Role.ADMIN);
return receivedHooks.get(repository);
return receivedHooks.get(namespaceAndName);
}
}

View File

@@ -1,17 +1,24 @@
package sonia.scm.repository;
import com.google.common.base.Strings;
import org.apache.shiro.SecurityUtils;
import sonia.scm.plugin.Extension;
/**
* The DefaultNamespaceStrategy returns the username of the currently logged in user as namespace.
* The DefaultNamespaceStrategy returns the predefined namespace of the given repository, if the namespace was not set
* the username of the currently loggedin user is used.
*
* @since 2.0.0
*/
@Extension
public class DefaultNamespaceStrategy implements NamespaceStrategy {
@Override
public String getNamespace() {
return SecurityUtils.getSubject().getPrincipal().toString();
public String createNamespace(Repository repository) {
String namespace = repository.getNamespace();
if (Strings.isNullOrEmpty(namespace)) {
namespace = SecurityUtils.getSubject().getPrincipal().toString();
}
return namespace;
}
}

View File

@@ -42,14 +42,30 @@ import com.google.inject.Singleton;
import org.apache.shiro.concurrent.SubjectAwareExecutorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.*;
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;
import sonia.scm.security.KeyGenerator;
import sonia.scm.util.*;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.CollectionAppender;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
@@ -125,7 +141,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
public Repository create(Repository repository, boolean initRepository) throws RepositoryException {
repository.setId(keyGenerator.createKey());
repository.setNamespace(namespaceStrategy.getNamespace());
repository.setNamespace(namespaceStrategy.createNamespace(repository));
logger.info("create repository {} of type {} in namespace {}", repository.getName(), repository.getType(), repository.getNamespace());
@@ -138,7 +154,8 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
}
fireEvent(HandlerEventType.BEFORE_CREATE, newRepository);
},
newRepository -> fireEvent(HandlerEventType.CREATE, newRepository)
newRepository -> fireEvent(HandlerEventType.CREATE, newRepository),
newRepository -> repositoryDAO.contains(newRepository.getNamespaceAndName())
);
}
@@ -155,7 +172,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
private void preDelete(Repository toDelete) throws RepositoryException {
if (configuration.isEnableRepositoryArchive() && !toDelete.isArchived()) {
throw new RepositoryIsNotArchivedException("Repository could not deleted, because it is not archived.");
throw new RepositoryIsNotArchivedException();
}
fireEvent(HandlerEventType.BEFORE_DELETE, toDelete);
getHandler(toDelete).delete(toDelete);
@@ -284,8 +301,8 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
}
@Override
public Collection<Type> getConfiguredTypes() {
List<Type> validTypes = Lists.newArrayList();
public Collection<RepositoryType> getConfiguredTypes() {
List<RepositoryType> validTypes = Lists.newArrayList();
for (RepositoryHandler handler : handlerMap.values()) {
if (handler.isConfigured()) {