mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 16:35:45 +01:00
Introduce default error object with context for not found exceptions
This commit is contained in:
@@ -30,7 +30,7 @@ public class ManagerDaoAdapter<T extends ModelObject> {
|
||||
|
||||
afterUpdate.handle(notModified);
|
||||
} else {
|
||||
throw new NotFoundException();
|
||||
throw new NotFoundException(object.getClass(), object.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ManagerDaoAdapter<T extends ModelObject> {
|
||||
dao.delete(toDelete);
|
||||
afterDelete.handle(toDelete);
|
||||
} else {
|
||||
throw new NotFoundException();
|
||||
throw new NotFoundException(toDelete.getClass(), toDelete.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ package sonia.scm.api.rest.resources;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.PathNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.CatCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.util.IOUtil;
|
||||
@@ -34,18 +32,6 @@ public class BrowserStreamingOutput implements StreamingOutput {
|
||||
public void write(OutputStream output) throws IOException {
|
||||
try {
|
||||
builder.retriveContent(output, path);
|
||||
} catch (PathNotFoundException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("could not find path {}", ex.getPath());
|
||||
}
|
||||
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
} catch (RevisionNotFoundException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("could not find revision {}", ex.getRevision());
|
||||
}
|
||||
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
} finally {
|
||||
IOUtil.close(repositoryService);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ package sonia.scm.api.rest.resources;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.DiffCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.util.IOUtil;
|
||||
@@ -95,22 +94,6 @@ public class DiffStreamingOutput implements StreamingOutput
|
||||
{
|
||||
builder.retriveContent(output);
|
||||
}
|
||||
catch (RevisionNotFoundException ex)
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("could not find revision {}", ex.getRevision());
|
||||
}
|
||||
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
// catch (RepositoryException ex)
|
||||
// {
|
||||
// logger.error("could not write content to page", ex);
|
||||
//
|
||||
// throw new WebApplicationException(ex,
|
||||
// Response.Status.INTERNAL_SERVER_ERROR);
|
||||
// }
|
||||
finally
|
||||
{
|
||||
IOUtil.close(repositoryService);
|
||||
|
||||
@@ -50,6 +50,7 @@ import sonia.scm.NotFoundException;
|
||||
import sonia.scm.NotSupportedFeatuerException;
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.api.rest.RestActionUploadResult;
|
||||
import sonia.scm.api.v2.resources.RepositoryResource;
|
||||
import sonia.scm.repository.*;
|
||||
import sonia.scm.repository.api.Command;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.repository.Branch;
|
||||
import sonia.scm.repository.Branches;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
@@ -105,7 +106,7 @@ public class BranchRootResource {
|
||||
.stream()
|
||||
.anyMatch(branch -> branchName.equals(branch.getName()));
|
||||
if (!branchExists){
|
||||
throw new NotFoundException("branch", branchName);
|
||||
throw NotFoundException.notFound(Branch.class, branchName).in(Repository.class, namespace + "/" + name).build();
|
||||
}
|
||||
Repository repository = repositoryService.getRepository();
|
||||
RepositoryPermissions.read(repository).check();
|
||||
|
||||
@@ -11,8 +11,6 @@ import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RepositoryPermissions;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.LogCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
@@ -56,7 +54,7 @@ public class ChangesetRootResource {
|
||||
@Produces(VndMediaType.CHANGESET_COLLECTION)
|
||||
@TypeHint(CollectionDto.class)
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name, @DefaultValue("0") @QueryParam("page") int page,
|
||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException, RevisionNotFoundException, RepositoryNotFoundException {
|
||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Repository repository = repositoryService.getRepository();
|
||||
RepositoryPermissions.read(repository).check();
|
||||
@@ -89,7 +87,7 @@ public class ChangesetRootResource {
|
||||
@Produces(VndMediaType.CHANGESET)
|
||||
@TypeHint(ChangesetDto.class)
|
||||
@Path("{id}")
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("id") String id) throws IOException, RevisionNotFoundException, RepositoryNotFoundException {
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("id") String id) throws IOException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Repository repository = repositoryService.getRepository();
|
||||
RepositoryPermissions.read(repository).check();
|
||||
|
||||
@@ -6,10 +6,9 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.PathNotFoundException;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.util.IOUtil;
|
||||
@@ -64,8 +63,8 @@ public class ContentResource {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Response.ResponseBuilder responseBuilder = Response.ok(stream);
|
||||
return createContentHeader(namespace, name, revision, path, repositoryService, responseBuilder);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
LOG.debug("path '{}' not found in repository {}/{}", path, namespace, name, e);
|
||||
} catch (NotFoundException e) {
|
||||
LOG.debug(e.getMessage());
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
}
|
||||
@@ -75,14 +74,8 @@ public class ContentResource {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
repositoryService.getCatCommand().setRevision(revision).retriveContent(os, path);
|
||||
os.close();
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
LOG.debug("repository {}/{} not found", path, namespace, name, e);
|
||||
throw new WebApplicationException(Status.NOT_FOUND);
|
||||
} catch (PathNotFoundException e) {
|
||||
LOG.debug("path '{}' not found in repository {}/{}", path, namespace, name, e);
|
||||
throw new WebApplicationException(Status.NOT_FOUND);
|
||||
} catch (RevisionNotFoundException e) {
|
||||
LOG.debug("revision '{}' not found in repository {}/{}", revision, namespace, name, e);
|
||||
} catch (NotFoundException e) {
|
||||
LOG.debug(e.getMessage());
|
||||
throw new WebApplicationException(Status.NOT_FOUND);
|
||||
}
|
||||
};
|
||||
@@ -111,8 +104,8 @@ public class ContentResource {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Response.ResponseBuilder responseBuilder = Response.ok();
|
||||
return createContentHeader(namespace, name, revision, path, repositoryService, responseBuilder);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
LOG.debug("path '{}' not found in repository {}/{}", path, namespace, name, e);
|
||||
} catch (NotFoundException e) {
|
||||
LOG.debug(e.getMessage());
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
}
|
||||
@@ -120,12 +113,6 @@ public class ContentResource {
|
||||
private Response createContentHeader(String namespace, String name, String revision, String path, RepositoryService repositoryService, Response.ResponseBuilder responseBuilder) {
|
||||
try {
|
||||
appendContentHeader(path, getHead(revision, path, repositoryService), responseBuilder);
|
||||
} catch (PathNotFoundException e) {
|
||||
LOG.debug("path '{}' not found in repository {}/{}", path, namespace, name, e);
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
} catch (RevisionNotFoundException e) {
|
||||
LOG.debug("revision '{}' not found in repository {}/{}", revision, namespace, name, e);
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
} catch (IOException e) {
|
||||
LOG.info("error reading repository resource {} from {}/{}", path, namespace, name, e);
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
|
||||
@@ -139,7 +126,7 @@ public class ContentResource {
|
||||
contentType.getLanguage().ifPresent(language -> responseBuilder.header("Language", language));
|
||||
}
|
||||
|
||||
private byte[] getHead(String revision, String path, RepositoryService repositoryService) throws IOException, PathNotFoundException, RevisionNotFoundException {
|
||||
private byte[] getHead(String revision, String path, RepositoryService repositoryService) throws IOException {
|
||||
InputStream stream = repositoryService.getCatCommand().setRevision(revision).getStream(path);
|
||||
try {
|
||||
byte[] buffer = new byte[HEAD_BUFFER_SIZE];
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
@@ -15,7 +14,6 @@ import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
@@ -54,13 +52,9 @@ public class DiffRootResource {
|
||||
HttpUtil.checkForCRLFInjection(revision);
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
StreamingOutput responseEntry = output -> {
|
||||
try {
|
||||
repositoryService.getDiffCommand()
|
||||
.setRevision(revision)
|
||||
.retriveContent(output);
|
||||
} catch (RevisionNotFoundException e) {
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
repositoryService.getDiffCommand()
|
||||
.setRevision(revision)
|
||||
.retriveContent(output);
|
||||
};
|
||||
return Response.ok(responseEntry)
|
||||
.header(HEADER_CONTENT_DISPOSITION, HttpUtil.createContentDispositionAttachmentHeader(String.format("%s-%s.diff", name, revision)))
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Getter;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.NotFoundException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class ErrorDto {
|
||||
private final String transactionId;
|
||||
private final String errorCode;
|
||||
private final List<ContextEntry> context;
|
||||
private final String message;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private final String url;
|
||||
|
||||
private ErrorDto(String transactionId, String errorCode, List<ContextEntry> context, String message) {
|
||||
this(transactionId, errorCode, context, message, null);
|
||||
}
|
||||
private ErrorDto(String transactionId, String errorCode, List<ContextEntry> context, String message, String url) {
|
||||
this.transactionId = transactionId;
|
||||
this.errorCode = errorCode;
|
||||
this.context = context;
|
||||
this.message = message;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
static ErrorDto from(NotFoundException notFoundException) {
|
||||
return new ErrorDto("todo", "todo", notFoundException.getContext(), notFoundException.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
@@ -51,8 +50,6 @@ public class FileHistoryRootResource {
|
||||
* @param pageSize pagination
|
||||
* @return all changesets related to the given file starting with the given revision
|
||||
* @throws IOException on io error
|
||||
* @throws RevisionNotFoundException on missing revision
|
||||
* @throws RepositoryNotFoundException on missing repository
|
||||
*/
|
||||
@GET
|
||||
@Path("{revision}/{path: .*}")
|
||||
@@ -69,7 +66,7 @@ public class FileHistoryRootResource {
|
||||
@PathParam("revision") String revision,
|
||||
@PathParam("path") String path,
|
||||
@DefaultValue("0") @QueryParam("page") int page,
|
||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException, RevisionNotFoundException, RepositoryNotFoundException {
|
||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
log.info("Get changesets of the file {} and revision {}", path, revision);
|
||||
Repository repository = repositoryService.getRepository();
|
||||
|
||||
@@ -5,6 +5,7 @@ import sonia.scm.AlreadyExistsException;
|
||||
import sonia.scm.ConcurrentModificationException;
|
||||
import sonia.scm.Manager;
|
||||
import sonia.scm.ModelObject;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.PageResult;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
@@ -22,6 +23,7 @@ class IdResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
|
||||
DTO extends HalRepresentation> {
|
||||
|
||||
private final Manager<MODEL_OBJECT> manager;
|
||||
private final String type;
|
||||
|
||||
private final SingleResourceManagerAdapter<MODEL_OBJECT, DTO> singleAdapter;
|
||||
private final CollectionResourceManagerAdapter<MODEL_OBJECT, DTO> collectionAdapter;
|
||||
@@ -30,6 +32,7 @@ class IdResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
|
||||
this.manager = manager;
|
||||
singleAdapter = new SingleResourceManagerAdapter<>(manager, type);
|
||||
collectionAdapter = new CollectionResourceManagerAdapter<>(manager, type);
|
||||
this.type = type.getSimpleName();
|
||||
}
|
||||
|
||||
Response get(String id, Function<MODEL_OBJECT, DTO> mapToDto) {
|
||||
@@ -56,8 +59,8 @@ class IdResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
|
||||
return singleAdapter.delete(id);
|
||||
}
|
||||
|
||||
private Supplier<Optional<MODEL_OBJECT>> loadBy(String id) {
|
||||
return () -> Optional.ofNullable(manager.get(id));
|
||||
private Supplier<MODEL_OBJECT> loadBy(String id) {
|
||||
return () -> Optional.ofNullable(manager.get(id)).orElseThrow(() -> new NotFoundException(type, id));
|
||||
}
|
||||
|
||||
private Predicate<MODEL_OBJECT> idStaysTheSame(String id) {
|
||||
|
||||
@@ -3,11 +3,8 @@ 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.InternalRepositoryException;
|
||||
import sonia.scm.repository.Modifications;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
@@ -46,7 +43,7 @@ public class ModificationsRootResource {
|
||||
@Produces(VndMediaType.MODIFICATIONS)
|
||||
@TypeHint(ModificationsDto.class)
|
||||
@Path("{revision}")
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws IOException, RevisionNotFoundException, RepositoryNotFoundException , InternalRepositoryException {
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws IOException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Modifications modifications = repositoryService.getModificationsCommand()
|
||||
.revision(revision)
|
||||
|
||||
@@ -32,18 +32,20 @@ package sonia.scm.api.v2.resources;
|
||||
|
||||
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.api.rest.StatusExceptionMapper;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Provider
|
||||
public class NotFoundExceptionMapper extends StatusExceptionMapper<NotFoundException> {
|
||||
|
||||
public NotFoundExceptionMapper() {
|
||||
super(NotFoundException.class, Response.Status.NOT_FOUND);
|
||||
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
|
||||
@Override
|
||||
public Response toResponse(NotFoundException exception) {
|
||||
return Response.status(Response.Status.NOT_FOUND).entity(ErrorDto.from(exception)).type(VndMediaType.ERROR_TYPE).build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class PermissionRootResource {
|
||||
.filter(filterPermission(permissionName))
|
||||
.map(permission -> modelToDtoMapper.map(permission, repository))
|
||||
.findFirst()
|
||||
.orElseThrow(NotFoundException::new)
|
||||
.orElseThrow(() -> NotFoundException.notFound(Permission.class, namespace).in(Repository.class, namespace + "/" + name).build())
|
||||
).build();
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ public class PermissionRootResource {
|
||||
RepositoryPermissions.permissionWrite(repository).check();
|
||||
String extractedPermissionName = getPermissionName(permissionName);
|
||||
if (!isPermissionExist(new PermissionDto(extractedPermissionName, isGroupPermission(permissionName)), repository)) {
|
||||
throw new NotFoundException("permission", extractedPermissionName);
|
||||
throw NotFoundException.notFound(Permission.class, namespace).in(Repository.class, namespace + "/" + name).build();
|
||||
}
|
||||
permission.setGroupPermission(isGroupPermission(permissionName));
|
||||
if (!extractedPermissionName.equals(permission.getName())) {
|
||||
@@ -174,7 +174,7 @@ public class PermissionRootResource {
|
||||
.stream()
|
||||
.filter(filterPermission(permissionName))
|
||||
.findFirst()
|
||||
.orElseThrow(NotFoundException::new);
|
||||
.orElseThrow(() -> NotFoundException.notFound(Permission.class, namespace).in(Repository.class, namespace + "/" + name).build());
|
||||
dtoToModelMapper.modify(existingPermission, permission);
|
||||
manager.modify(repository);
|
||||
log.info("the permission with name: {} is updated.", permissionName);
|
||||
|
||||
@@ -203,8 +203,8 @@ public class RepositoryResource {
|
||||
}
|
||||
}
|
||||
|
||||
private Supplier<Optional<Repository>> loadBy(String namespace, String name) {
|
||||
return () -> Optional.ofNullable(manager.get(new NamespaceAndName(namespace, name)));
|
||||
private Supplier<Repository> loadBy(String namespace, String name) {
|
||||
return () -> Optional.ofNullable(manager.get(new NamespaceAndName(namespace, name))).orElseThrow(() -> new NotFoundException(Repository.class, namespace + "/" + name));
|
||||
}
|
||||
|
||||
private Predicate<Repository> nameAndNamespaceStaysTheSame(String namespace, String name) {
|
||||
|
||||
@@ -38,7 +38,10 @@ class SingleResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
|
||||
this(manager, type, e -> Optional.empty());
|
||||
}
|
||||
|
||||
SingleResourceManagerAdapter(Manager<MODEL_OBJECT> manager, Class<MODEL_OBJECT> type, Function<Throwable, Optional<Response>> errorHandler) {
|
||||
SingleResourceManagerAdapter(
|
||||
Manager<MODEL_OBJECT> manager,
|
||||
Class<MODEL_OBJECT> type,
|
||||
Function<Throwable, Optional<Response>> errorHandler) {
|
||||
super(manager, type);
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
@@ -47,25 +50,16 @@ class SingleResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
|
||||
* Reads the model object for the given id, transforms it to a dto and returns a corresponding http response.
|
||||
* This handles all corner cases, eg. no matching object for the id or missing privileges.
|
||||
*/
|
||||
Response get(Supplier<Optional<MODEL_OBJECT>> reader, Function<MODEL_OBJECT, DTO> mapToDto) {
|
||||
return reader.get()
|
||||
.map(mapToDto)
|
||||
.map(Response::ok)
|
||||
.map(Response.ResponseBuilder::build)
|
||||
.orElseThrow(NotFoundException::new);
|
||||
}
|
||||
public Response update(Supplier<Optional<MODEL_OBJECT>> reader, Function<MODEL_OBJECT, MODEL_OBJECT> applyChanges, Predicate<MODEL_OBJECT> hasSameKey, Consumer<MODEL_OBJECT> checker) throws NotFoundException, ConcurrentModificationException {
|
||||
MODEL_OBJECT existingModelObject = reader.get().orElseThrow(NotFoundException::new);
|
||||
checker.accept(existingModelObject);
|
||||
return update(reader,applyChanges,hasSameKey);
|
||||
Response get(Supplier<MODEL_OBJECT> reader, Function<MODEL_OBJECT, DTO> mapToDto) {
|
||||
return Response.ok(mapToDto.apply(reader.get())).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the model object for the given id according to the given function and returns a corresponding http response.
|
||||
* This handles all corner cases, eg. no matching object for the id or missing privileges.
|
||||
*/
|
||||
public Response update(Supplier<Optional<MODEL_OBJECT>> reader, Function<MODEL_OBJECT, MODEL_OBJECT> applyChanges, Predicate<MODEL_OBJECT> hasSameKey) throws NotFoundException, ConcurrentModificationException {
|
||||
MODEL_OBJECT existingModelObject = reader.get().orElseThrow(NotFoundException::new);
|
||||
Response update(Supplier<MODEL_OBJECT> reader, Function<MODEL_OBJECT, MODEL_OBJECT> applyChanges, Predicate<MODEL_OBJECT> hasSameKey) throws ConcurrentModificationException {
|
||||
MODEL_OBJECT existingModelObject = reader.get();
|
||||
MODEL_OBJECT changedModelObject = applyChanges.apply(existingModelObject);
|
||||
if (!hasSameKey.test(changedModelObject)) {
|
||||
return Response.status(BAD_REQUEST).entity("illegal change of id").build();
|
||||
@@ -81,11 +75,13 @@ class SingleResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
|
||||
&& (updated.getLastModified() == null || existing.getLastModified() > updated.getLastModified());
|
||||
}
|
||||
|
||||
public Response delete(Supplier<Optional<MODEL_OBJECT>> reader) {
|
||||
return reader.get()
|
||||
.map(MODEL_OBJECT::getId)
|
||||
.map(this::delete)
|
||||
.orElse(null);
|
||||
public Response delete(Supplier<MODEL_OBJECT> reader) {
|
||||
try {
|
||||
return delete(reader.get().getId());
|
||||
} catch (NotFoundException e) {
|
||||
// due to idempotency of delete this does not matter here.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.BrowseCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -33,14 +31,14 @@ public class SourceRootResource {
|
||||
@GET
|
||||
@Produces(VndMediaType.SOURCE)
|
||||
@Path("")
|
||||
public Response getAllWithoutRevision(@PathParam("namespace") String namespace, @PathParam("name") String name) throws RevisionNotFoundException, RepositoryNotFoundException, IOException {
|
||||
public Response getAllWithoutRevision(@PathParam("namespace") String namespace, @PathParam("name") String name) throws IOException {
|
||||
return getSource(namespace, name, "/", null);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(VndMediaType.SOURCE)
|
||||
@Path("{revision}")
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws RevisionNotFoundException, RepositoryNotFoundException, IOException {
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws IOException {
|
||||
return getSource(namespace, name, "/", revision);
|
||||
}
|
||||
|
||||
@@ -51,7 +49,7 @@ public class SourceRootResource {
|
||||
return getSource(namespace, name, path, revision);
|
||||
}
|
||||
|
||||
private Response getSource(String namespace, String repoName, String path, String revision) throws IOException, RevisionNotFoundException, RepositoryNotFoundException {
|
||||
private Response getSource(String namespace, String repoName, String path, String revision) throws IOException {
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, repoName);
|
||||
try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) {
|
||||
BrowseCommandBuilder browseCommand = repositoryService.getBrowseCommand();
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.NotFoundException;
|
||||
|
||||
public class TagNotFoundException extends NotFoundException {
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ 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.NotFoundException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
@@ -47,7 +48,7 @@ public class TagRootResource {
|
||||
})
|
||||
@Produces(VndMediaType.TAG_COLLECTION)
|
||||
@TypeHint(CollectionDto.class)
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name) throws IOException, RepositoryNotFoundException {
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name) throws IOException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Tags tags = getTags(repositoryService);
|
||||
if (tags != null && tags.getTags() != null) {
|
||||
@@ -72,7 +73,7 @@ public class TagRootResource {
|
||||
@Produces(VndMediaType.TAG)
|
||||
@TypeHint(TagDto.class)
|
||||
@Path("{tagName}")
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("tagName") String tagName) throws IOException, RepositoryNotFoundException, TagNotFoundException {
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("tagName") String tagName) throws IOException {
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name);
|
||||
try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) {
|
||||
Tags tags = getTags(repositoryService);
|
||||
@@ -80,7 +81,7 @@ public class TagRootResource {
|
||||
Tag tag = tags.getTags().stream()
|
||||
.filter(t -> tagName.equals(t.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(TagNotFoundException::new);
|
||||
.orElseThrow(() -> createNotFoundException(namespace, name, tagName));
|
||||
return Response.ok(tagToTagDtoMapper.map(tag, namespaceAndName)).build();
|
||||
} else {
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
@@ -90,6 +91,10 @@ public class TagRootResource {
|
||||
}
|
||||
}
|
||||
|
||||
private NotFoundException createNotFoundException(String namespace, String name, String tagName) {
|
||||
return NotFoundException.notFound("Tag", tagName).in("Repository", namespace + "/" + name).build();
|
||||
}
|
||||
|
||||
private Tags getTags(RepositoryService repositoryService) throws IOException {
|
||||
Repository repository = repositoryService.getRepository();
|
||||
RepositoryPermissions.read(repository).check();
|
||||
|
||||
@@ -172,7 +172,7 @@ public class DefaultGroupManager extends AbstractGroupManager
|
||||
|
||||
if (fresh == null)
|
||||
{
|
||||
throw new NotFoundException("group", group.getId());
|
||||
throw new NotFoundException(Group.class, group.getId());
|
||||
}
|
||||
|
||||
fresh.copyProperties(group);
|
||||
|
||||
@@ -219,7 +219,7 @@ public class DefaultUserManager extends AbstractUserManager
|
||||
|
||||
if (fresh == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
throw new NotFoundException(User.class, user.getName());
|
||||
}
|
||||
|
||||
fresh.copyProperties(user);
|
||||
@@ -419,7 +419,7 @@ public class DefaultUserManager extends AbstractUserManager
|
||||
public void overwritePassword(String userId, String newPassword) {
|
||||
User user = get(userId);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
throw new NotFoundException(User.class, userId);
|
||||
}
|
||||
if (!isTypeDefault(user)) {
|
||||
throw new ChangePasswordNotAllowedException(user.getType());
|
||||
|
||||
Reference in New Issue
Block a user