Replace model object exception with generic ones and migrate guice

This commit is contained in:
René Pfeuffer
2018-08-21 07:53:33 +02:00
parent bb9a0657a5
commit a0f74e3329
227 changed files with 1380 additions and 3549 deletions

View File

@@ -34,13 +34,14 @@ package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
//~--- JDK imports ------------------------------------------------------------
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
@@ -97,7 +98,7 @@ public class ClassOverride implements Validateable
public String toString()
{
//J-
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("bind", bind)
.add("to", to)
.toString();

View File

@@ -7,19 +7,15 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class ManagerDaoAdapter<T extends ModelObject, E extends Exception> {
public class ManagerDaoAdapter<T extends ModelObject> {
private final GenericDAO<T> dao;
private final Function<T, E> notFoundException;
private final Function<T, E> alreadyExistsException;
public ManagerDaoAdapter(GenericDAO<T> dao, Function<T, E> notFoundException, Function<T, E> alreadyExistsException) {
public ManagerDaoAdapter(GenericDAO<T> dao) {
this.dao = dao;
this.notFoundException = notFoundException;
this.alreadyExistsException = alreadyExistsException;
}
public void modify(T object, Function<T, PermissionCheck> permissionCheck, AroundHandler<T, E> beforeUpdate, AroundHandler<T, E> afterUpdate) throws E {
public void modify(T object, Function<T, PermissionCheck> permissionCheck, AroundHandler<T> beforeUpdate, AroundHandler<T> afterUpdate) throws NotFoundException {
T notModified = dao.get(object.getId());
if (notModified != null) {
permissionCheck.apply(notModified).check();
@@ -34,19 +30,19 @@ public class ManagerDaoAdapter<T extends ModelObject, E extends Exception> {
afterUpdate.handle(notModified);
} else {
throw notFoundException.apply(object);
throw new NotFoundException();
}
}
public T create(T newObject, Supplier<PermissionCheck> permissionCheck, AroundHandler<T, E> beforeCreate, AroundHandler<T, E> afterCreate) throws E {
public T create(T newObject, Supplier<PermissionCheck> permissionCheck, AroundHandler<T> beforeCreate, AroundHandler<T> afterCreate) throws AlreadyExistsException {
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 {
public T create(T newObject, Supplier<PermissionCheck> permissionCheck, AroundHandler<T> beforeCreate, AroundHandler<T> afterCreate, Predicate<T> existsCheck) throws AlreadyExistsException {
permissionCheck.get().check();
AssertUtil.assertIsValid(newObject);
if (existsCheck.test(newObject)) {
throw alreadyExistsException.apply(newObject);
throw new AlreadyExistsException();
}
newObject.setCreationDate(System.currentTimeMillis());
beforeCreate.handle(newObject);
@@ -55,19 +51,19 @@ public class ManagerDaoAdapter<T extends ModelObject, E extends Exception> {
return newObject;
}
public void delete(T toDelete, Supplier<PermissionCheck> permissionCheck, AroundHandler<T, E> beforeDelete, AroundHandler<T, E> afterDelete) throws E {
public void delete(T toDelete, Supplier<PermissionCheck> permissionCheck, AroundHandler<T> beforeDelete, AroundHandler<T> afterDelete) throws NotFoundException {
permissionCheck.get().check();
if (dao.contains(toDelete)) {
beforeDelete.handle(toDelete);
dao.delete(toDelete);
afterDelete.handle(toDelete);
} else {
throw notFoundException.apply(toDelete);
throw new NotFoundException();
}
}
@FunctionalInterface
public interface AroundHandler<T extends ModelObject, E extends Exception> {
void handle(T notModified) throws E;
public interface AroundHandler<T extends ModelObject> {
void handle(T notModified);
}
}

View File

@@ -1,6 +1,6 @@
package sonia.scm.api.rest;
import sonia.scm.user.UserAlreadyExistsException;
import sonia.scm.AlreadyExistsException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@@ -8,9 +8,9 @@ import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class UserAlreadyExistsExceptionMapper implements ExceptionMapper<UserAlreadyExistsException> {
public class AlreadyExistsExceptionMapper implements ExceptionMapper<AlreadyExistsException> {
@Override
public Response toResponse(UserAlreadyExistsException exception) {
public Response toResponse(AlreadyExistsException exception) {
return Response.status(Status.CONFLICT).build();
}
}

View File

@@ -1,16 +0,0 @@
package sonia.scm.api.rest;
import sonia.scm.group.GroupAlreadyExistsException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class GroupAlreadyExistsExceptionMapper implements ExceptionMapper<GroupAlreadyExistsException> {
@Override
public Response toResponse(GroupAlreadyExistsException exception) {
return Response.status(Status.CONFLICT).build();
}
}

View File

@@ -34,15 +34,15 @@ package sonia.scm.api.rest;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
//~--- JDK imports ------------------------------------------------------------
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
//~--- JDK imports ------------------------------------------------------------
/**
*
@@ -127,7 +127,7 @@ public class Permission implements Serializable
public String toString()
{
//J-
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("value", value)
.toString();

View File

@@ -1,16 +0,0 @@
package sonia.scm.api.rest;
import sonia.scm.repository.RepositoryAlreadyExistsException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class RepositoryAlreadyExistsExceptionMapper implements ExceptionMapper<RepositoryAlreadyExistsException> {
@Override
public Response toResponse(RepositoryAlreadyExistsException exception) {
return Response.status(Status.CONFLICT).build();
}
}

View File

@@ -34,15 +34,16 @@ package sonia.scm.api.rest;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
//~--- JDK imports ------------------------------------------------------------
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
@@ -145,7 +146,7 @@ public class RestExceptionResult
public String toString()
{
//J-
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("message", message)
.add("stacktrace", stacktrace)
.toString();

View File

@@ -48,8 +48,13 @@ import sonia.scm.util.AssertUtil;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
import javax.ws.rs.core.*;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
@@ -61,28 +66,19 @@ import java.util.Date;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
*
* @param <T>
* @param <E>
*/
public abstract class AbstractManagerResource<T extends ModelObject,
E extends Exception>
{
public abstract class AbstractManagerResource<T extends ModelObject> {
/** the logger for AbstractManagerResource */
private static final Logger logger =
LoggerFactory.getLogger(AbstractManagerResource.class);
protected final Manager<T, E> manager;
protected final Manager<T> manager;
private final Class<T> type;
protected int cacheMaxAge = 0;
protected boolean disableCache = false;
public AbstractManagerResource(Manager<T, E> manager, Class<T> type) {
public AbstractManagerResource(Manager<T> manager, Class<T> type) {
this.manager = manager;
this.type = type;
}

View File

@@ -38,7 +38,6 @@ package sonia.scm.api.rest.resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RevisionNotFoundException;
import sonia.scm.repository.api.CatCommandBuilder;
import sonia.scm.repository.api.RepositoryService;
@@ -120,13 +119,13 @@ public class BrowserStreamingOutput implements StreamingOutput
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);
}
// 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);

View File

@@ -39,26 +39,20 @@ import com.google.inject.Inject;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.ConcurrentModificationException;
import sonia.scm.NotFoundException;
import sonia.scm.api.rest.RestActionResult;
import sonia.scm.security.Role;
import sonia.scm.security.ScmSecurityException;
import sonia.scm.user.User;
import sonia.scm.user.UserException;
import sonia.scm.user.UserManager;
import sonia.scm.util.AssertUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -67,6 +61,8 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
//~--- JDK imports ------------------------------------------------------------
/**
* Resource to change the password of the authenticated user.
*
@@ -104,11 +100,6 @@ public class ChangePasswordResource
*
* @param oldPassword old password of the current user
* @param newPassword new password for the current user
*
* @return
*
* @throws IOException
* @throws UserException
*/
@POST
@TypeHint(RestActionResult.class)
@@ -118,10 +109,7 @@ public class ChangePasswordResource
@ResponseCode(code = 500, condition = "internal server error")
})
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response changePassword(@FormParam("old-password") String oldPassword,
@FormParam("new-password") String newPassword)
throws UserException, IOException
{
public Response changePassword(@FormParam("old-password") String oldPassword, @FormParam("new-password") String newPassword) throws NotFoundException, ConcurrentModificationException {
AssertUtil.assertIsNotEmpty(oldPassword);
AssertUtil.assertIsNotEmpty(newPassword);

View File

@@ -35,26 +35,20 @@ package sonia.scm.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.io.Closeables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RevisionNotFoundException;
import sonia.scm.repository.api.DiffCommandBuilder;
import sonia.scm.repository.api.RepositoryService;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.io.OutputStream;
import sonia.scm.util.IOUtil;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import sonia.scm.util.IOUtil;
import java.io.IOException;
import java.io.OutputStream;
//~--- JDK imports ------------------------------------------------------------
/**
*
@@ -96,22 +90,11 @@ public class DiffStreamingOutput implements StreamingOutput
* @throws WebApplicationException
*/
@Override
public void write(OutputStream output)
throws IOException, WebApplicationException
{
public void write(OutputStream output) throws IOException {
try
{
builder.retriveContent(output);
}
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())
@@ -121,13 +104,13 @@ public class DiffStreamingOutput implements StreamingOutput
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);
}
// 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);

View File

@@ -43,12 +43,25 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import org.apache.shiro.SecurityUtils;
import sonia.scm.group.Group;
import sonia.scm.group.GroupException;
import sonia.scm.group.GroupManager;
import sonia.scm.security.Role;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Collection;
//~--- JDK imports ------------------------------------------------------------
@@ -60,23 +73,13 @@ import java.util.Collection;
*/
@Path("groups")
@Singleton
public class GroupResource
extends AbstractManagerResource<Group, GroupException>
{
public class GroupResource extends AbstractManagerResource<Group> {
/** Field description */
public static final String PATH_PART = "groups";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
*
* @param securityContextProvider
* @param groupManager
*/
@Inject
public GroupResource(GroupManager groupManager)
{

View File

@@ -35,7 +35,7 @@ package sonia.scm.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
@@ -47,10 +47,19 @@ import com.webcohesion.enunciate.metadata.rs.TypeHint;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.AlreadyExistsException;
import sonia.scm.NotFoundException;
import sonia.scm.NotSupportedFeatuerException;
import sonia.scm.Type;
import sonia.scm.api.rest.RestActionUploadResult;
import sonia.scm.repository.*;
import sonia.scm.repository.AdvancedImportHandler;
import sonia.scm.repository.ImportHandler;
import sonia.scm.repository.ImportResult;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryType;
import sonia.scm.repository.api.Command;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
@@ -58,8 +67,21 @@ import sonia.scm.repository.api.UnbundleCommandBuilder;
import sonia.scm.security.Role;
import sonia.scm.util.IOUtil;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@@ -256,10 +278,10 @@ public class RepositoryImportResource
service = serviceFactory.create(repository);
service.getPullCommand().pull(request.getUrl());
}
catch (RepositoryException ex)
{
handleImportFailure(ex, repository);
}
// catch (RepositoryException ex)
// {
// handleImportFailure(ex, repository);
// }
catch (IOException ex)
{
handleImportFailure(ex, repository);
@@ -413,11 +435,11 @@ public class RepositoryImportResource
logger.warn("exception occured durring directory import", ex);
response = Response.serverError().build();
}
catch (RepositoryException ex)
{
logger.warn("exception occured durring directory import", ex);
response = Response.serverError().build();
}
// catch (RepositoryException ex)
// {
// logger.warn("exception occured durring directory import", ex);
// response = Response.serverError().build();
// }
}
else
{
@@ -526,14 +548,14 @@ public class RepositoryImportResource
// repository = new Repository(null, type, name);
manager.create(repository);
}
catch (RepositoryAlreadyExistsException ex)
catch (AlreadyExistsException ex)
{
logger.warn("a {} repository with the name {} already exists", type,
name);
throw new WebApplicationException(Response.Status.CONFLICT);
}
catch (RepositoryException ex)
catch (InternalRepositoryException ex)
{
handleGenericCreationFailure(ex, type, name);
}
@@ -583,11 +605,7 @@ public class RepositoryImportResource
service = serviceFactory.create(repository);
service.getUnbundleCommand().setCompressed(compressed).unbundle(file);
}
catch (RepositoryException ex)
{
handleImportFailure(ex, repository);
}
catch (IOException ex)
catch (InternalRepositoryException ex)
{
handleImportFailure(ex, repository);
}
@@ -685,9 +703,9 @@ public class RepositoryImportResource
{
manager.delete(repository);
}
catch (RepositoryException e)
catch (InternalRepositoryException | NotFoundException e)
{
logger.error("can not delete repository", e);
logger.error("can not delete repository after import failure", e);
}
throw new WebApplicationException(ex,
@@ -741,7 +759,7 @@ public class RepositoryImportResource
{
throw new WebApplicationException(ex);
}
catch (RepositoryException ex)
catch (InternalRepositoryException ex)
{
throw new WebApplicationException(ex);
}
@@ -812,7 +830,7 @@ public class RepositoryImportResource
public String toString()
{
//J-
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("name", name)
.add("url", url)
.toString();

View File

@@ -46,16 +46,51 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.*;
import sonia.scm.repository.api.*;
import sonia.scm.NotFoundException;
import sonia.scm.repository.BlameResult;
import sonia.scm.repository.Branches;
import sonia.scm.repository.BrowserResult;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.ChangesetPagingResult;
import sonia.scm.repository.HealthChecker;
import sonia.scm.repository.Permission;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryIsNotArchivedException;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.repository.Tags;
import sonia.scm.repository.api.BlameCommandBuilder;
import sonia.scm.repository.api.BrowseCommandBuilder;
import sonia.scm.repository.api.CatCommandBuilder;
import sonia.scm.repository.api.CommandNotSupportedException;
import sonia.scm.repository.api.DiffCommandBuilder;
import sonia.scm.repository.api.DiffFormat;
import sonia.scm.repository.api.LogCommandBuilder;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -69,7 +104,7 @@ import java.util.Collection;
*/
@Singleton
@Path("repositories")
public class RepositoryResource extends AbstractManagerResource<Repository, RepositoryException>
public class RepositoryResource extends AbstractManagerResource<Repository>
{
/** Field description */
@@ -169,12 +204,15 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
{
logger.warn("delete not allowed", ex);
response = Response.status(Response.Status.FORBIDDEN).build();
} catch (NotFoundException e) {
// there is nothing to do because delete should be idempotent
response = Response.ok().build();
}
catch (RepositoryException ex)
{
logger.error("error during delete", ex);
response = createErrorResponse(ex);
}
// catch (IOException ex)
// {
// logger.error("error during delete", ex);
// response = Response.serverError().build();
// }
}
else
{
@@ -215,10 +253,8 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
{
logger.warn("could not find repository ".concat(id), ex);
response = Response.status(Status.NOT_FOUND).build();
}
catch (RepositoryException | IOException ex)
{
logger.error("error occured during health check", ex);
} catch (NotFoundException e) {
logger.error("error occured during health check", e);
response = Response.serverError().build();
}
@@ -312,7 +348,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return a annotate/blame view for the given path
*
* @throws IOException
* @throws RepositoryException
*/
@GET
@Path("{id}/blame")
@@ -326,7 +361,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getBlame(@PathParam("id") String id,
@QueryParam("revision") String revision, @QueryParam("path") String path)
throws RepositoryException, IOException
throws IOException
{
Response response = null;
RepositoryService service = null;
@@ -382,7 +417,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return all {@link Branches} of a repository
*
* @throws IOException
* @throws RepositoryException
*
* @since 1.18
*/
@@ -397,7 +431,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
@TypeHint(Branches.class)
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getBranches(@PathParam("id") String id)
throws RepositoryException, IOException
throws IOException
{
Response response = null;
RepositoryService service = null;
@@ -446,7 +480,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return a list of folders and files for the given folder
*
* @throws IOException
* @throws RepositoryException
*/
@GET
@Path("{id}/browse")
@@ -466,7 +499,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
@QueryParam("disableLastCommit") @DefaultValue("false") boolean disableLastCommit,
@QueryParam("disableSubRepositoryDetection") @DefaultValue("false") boolean disableSubRepositoryDetection,
@QueryParam("recursive") @DefaultValue("false") boolean recursive)
throws RepositoryException, IOException
throws IOException
//J+
{
Response response = null;
@@ -505,7 +538,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
response = Response.status(Response.Status.NOT_FOUND).build();
}
}
catch (RepositoryNotFoundException ex)
catch (NotFoundException ex)
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
@@ -531,7 +564,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return a {@link Changeset} from the given repository
*
* @throws IOException
* @throws RepositoryException
*/
@GET
@Path("{id}/changeset/{revision}")
@@ -545,7 +577,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getChangeset(@PathParam("id") String id,
@PathParam("revision") String revision)
throws IOException, RepositoryException
throws IOException
{
Response response = null;
@@ -568,7 +600,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
response = Response.status(Status.NOT_FOUND).build();
}
}
catch (RepositoryNotFoundException ex)
catch (NotFoundException ex)
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
@@ -603,7 +635,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return a list of {@link Changeset} for the given repository
*
* @throws IOException
* @throws RepositoryException
*/
@GET
@Path("{id}/changesets")
@@ -623,7 +654,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
@QueryParam("branch") String branch,
@DefaultValue("0") @QueryParam("start") int start,
@DefaultValue("20") @QueryParam("limit") int limit
) throws RepositoryException, IOException
) throws IOException
//J+
{
Response response = null;
@@ -664,7 +695,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
response = Response.ok().build();
}
}
catch (RepositoryNotFoundException ex)
catch (NotFoundException ex)
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
@@ -759,7 +790,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return the modifications of a {@link Changeset}
*
* @throws IOException
* @throws RepositoryException
*/
@GET
@Path("{id}/diff")
@@ -774,7 +804,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
public Response getDiff(@PathParam("id") String id,
@QueryParam("revision") String revision, @QueryParam("path") String path,
@QueryParam("format") DiffFormat format)
throws RepositoryException, IOException
throws IOException
{
AssertUtil.assertIsNotEmpty(id);
AssertUtil.assertIsNotEmpty(revision);
@@ -841,7 +871,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
* @return all {@link Tags} of a repository
*
* @throws IOException
* @throws RepositoryException
*
* @since 1.18
*/
@@ -856,7 +885,7 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
@TypeHint(Tags.class)
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getTags(@PathParam("id") String id)
throws RepositoryException, IOException
throws IOException
{
Response response = null;
RepositoryService service = null;

View File

@@ -45,13 +45,25 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.PasswordService;
import sonia.scm.security.Role;
import sonia.scm.user.User;
import sonia.scm.user.UserException;
import sonia.scm.user.UserManager;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.Util;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Collection;
//~--- JDK imports ------------------------------------------------------------
@@ -63,7 +75,7 @@ import java.util.Collection;
*/
@Singleton
@Path("users")
public class UserResource extends AbstractManagerResource<User, UserException>
public class UserResource extends AbstractManagerResource<User>
{
/** Field description */

View File

@@ -5,7 +5,6 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.repository.Branches;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.repository.api.CommandNotSupportedException;
import sonia.scm.repository.api.RepositoryService;
@@ -55,7 +54,7 @@ public class BranchRootResource {
@ResponseCode(code = 404, condition = "not found, no branch with the specified name for the repository available or repository not found"),
@ResponseCode(code = 500, condition = "internal server error")
})
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("branch") String branchName) throws IOException, RepositoryException {
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("branch") String branchName) throws IOException {
try (RepositoryService repositoryService = servicefactory.create(new NamespaceAndName(namespace, name))) {
Branches branches = repositoryService.getBranchesCommand().getBranches();
return branches.getBranches()
@@ -100,7 +99,7 @@ public class BranchRootResource {
@ResponseCode(code = 404, condition = "not found, no repository found for the given namespace and name"),
@ResponseCode(code = 500, condition = "internal server error")
})
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name) throws IOException, RepositoryException {
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name) throws IOException {
try (RepositoryService repositoryService = servicefactory.create(new NamespaceAndName(namespace, name))) {
Branches branches = repositoryService.getBranchesCommand().getBranches();
return Response.ok(branchCollectionToDtoMapper.map(namespace, name, branches.getBranches())).build();

View File

@@ -1,6 +1,7 @@
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import sonia.scm.AlreadyExistsException;
import sonia.scm.Manager;
import sonia.scm.ModelObject;
import sonia.scm.PageResult;
@@ -22,16 +23,14 @@ import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
*
* @param <MODEL_OBJECT> The type of the model object, eg. {@link sonia.scm.user.User}.
* @param <DTO> The corresponding transport object, eg. {@link UserDto}.
* @param <EXCEPTION> The exception type for the model object, eg. {@link sonia.scm.user.UserException}.
*
* @see SingleResourceManagerAdapter
*/
@SuppressWarnings("squid:S00119") // "MODEL_OBJECT" is much more meaningful than "M", right?
class CollectionResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
DTO extends HalRepresentation,
EXCEPTION extends Exception> extends AbstractManagerResource<MODEL_OBJECT, EXCEPTION> {
DTO extends HalRepresentation> extends AbstractManagerResource<MODEL_OBJECT> {
CollectionResourceManagerAdapter(Manager<MODEL_OBJECT, EXCEPTION> manager, Class<MODEL_OBJECT> type) {
CollectionResourceManagerAdapter(Manager<MODEL_OBJECT> manager, Class<MODEL_OBJECT> type) {
super(manager, type);
}
@@ -48,7 +47,7 @@ class CollectionResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
* Creates a model object for the given dto and returns a corresponding http response.
* This handles all corner cases, eg. no conflicts or missing privileges.
*/
public Response create(DTO dto, Supplier<MODEL_OBJECT> modelObjectSupplier, Function<MODEL_OBJECT, String> uriCreator) throws EXCEPTION {
public Response create(DTO dto, Supplier<MODEL_OBJECT> modelObjectSupplier, Function<MODEL_OBJECT, String> uriCreator) throws AlreadyExistsException {
if (dto == null) {
return Response.status(BAD_REQUEST).build();
}

View File

@@ -8,7 +8,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.repository.RevisionNotFoundException;
import sonia.scm.repository.api.RepositoryService;
@@ -79,9 +78,9 @@ public class ContentResource {
} catch (PathNotFoundException e) {
LOG.debug("path '{}' not found in repository {}/{}", path, namespace, name, e);
throw new WebApplicationException(Status.NOT_FOUND);
} catch (RepositoryException e) {
LOG.info("error reading repository resource {} from {}/{}", path, namespace, name, e);
throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
} catch (RevisionNotFoundException e) {
LOG.debug("revision '{}' not found in repository {}/{}", revision, namespace, name, e);
throw new WebApplicationException(Status.NOT_FOUND);
}
};
}
@@ -124,7 +123,7 @@ public class ContentResource {
} catch (RevisionNotFoundException e) {
LOG.debug("revision '{}' not found in repository {}/{}", revision, namespace, name, e);
return Response.status(Status.NOT_FOUND).build();
} catch (IOException | RepositoryException e) {
} 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();
}
@@ -137,7 +136,7 @@ public class ContentResource {
contentType.getLanguage().ifPresent(language -> responseBuilder.header("Language", language));
}
private byte[] getHead(String revision, String path, RepositoryService repositoryService) throws IOException, RepositoryException {
private byte[] getHead(String revision, String path, RepositoryService repositoryService) throws IOException, PathNotFoundException, RevisionNotFoundException {
InputStream stream = repositoryService.getCatCommand().setRevision(revision).getStream(path);
try {
byte[] buffer = new byte[HEAD_BUFFER_SIZE];

View File

@@ -1,15 +1,24 @@
package sonia.scm.api.v2.resources;
import com.webcohesion.enunciate.metadata.rs.*;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.AlreadyExistsException;
import sonia.scm.group.Group;
import sonia.scm.group.GroupException;
import sonia.scm.group.GroupManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.io.IOException;
public class GroupCollectionResource {
@@ -19,7 +28,7 @@ public class GroupCollectionResource {
private final GroupCollectionToDtoMapper groupCollectionToDtoMapper;
private final ResourceLinks resourceLinks;
private final IdResourceManagerAdapter<Group, GroupDto, GroupException> adapter;
private final IdResourceManagerAdapter<Group, GroupDto> adapter;
@Inject
public GroupCollectionResource(GroupManager manager, GroupDtoToGroupMapper dtoToGroupMapper, GroupCollectionToDtoMapper groupCollectionToDtoMapper, ResourceLinks resourceLinks) {
@@ -76,7 +85,7 @@ public class GroupCollectionResource {
})
@TypeHint(TypeHint.NO_CONTENT.class)
@ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created group"))
public Response create(GroupDto groupDto) throws IOException, GroupException {
public Response create(GroupDto groupDto) throws AlreadyExistsException {
return adapter.create(groupDto,
() -> dtoToGroupMapper.map(groupDto),
group -> resourceLinks.group().self(group.getName()));

View File

@@ -4,19 +4,24 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.group.Group;
import sonia.scm.group.GroupException;
import sonia.scm.group.GroupManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
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;
public class GroupResource {
private final GroupToGroupDtoMapper groupToGroupDtoMapper;
private final GroupDtoToGroupMapper dtoToGroupMapper;
private final IdResourceManagerAdapter<Group, GroupDto, GroupException> adapter;
private final IdResourceManagerAdapter<Group, GroupDto> adapter;
@Inject
public GroupResource(GroupManager manager, GroupToGroupDtoMapper groupToGroupDtoMapper,

View File

@@ -1,12 +1,12 @@
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import sonia.scm.AlreadyExistsException;
import sonia.scm.Manager;
import sonia.scm.ModelObject;
import sonia.scm.PageResult;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -18,15 +18,14 @@ import java.util.function.Supplier;
*/
@SuppressWarnings("squid:S00119") // "MODEL_OBJECT" is much more meaningful than "M", right?
class IdResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
DTO extends HalRepresentation,
EXCEPTION extends Exception> {
DTO extends HalRepresentation> {
private final Manager<MODEL_OBJECT, EXCEPTION> manager;
private final Manager<MODEL_OBJECT> manager;
private final SingleResourceManagerAdapter<MODEL_OBJECT, DTO, EXCEPTION> singleAdapter;
private final CollectionResourceManagerAdapter<MODEL_OBJECT, DTO, EXCEPTION> collectionAdapter;
private final SingleResourceManagerAdapter<MODEL_OBJECT, DTO> singleAdapter;
private final CollectionResourceManagerAdapter<MODEL_OBJECT, DTO> collectionAdapter;
IdResourceManagerAdapter(Manager<MODEL_OBJECT, EXCEPTION> manager, Class<MODEL_OBJECT> type) {
IdResourceManagerAdapter(Manager<MODEL_OBJECT> manager, Class<MODEL_OBJECT> type) {
this.manager = manager;
singleAdapter = new SingleResourceManagerAdapter<>(manager, type);
collectionAdapter = new CollectionResourceManagerAdapter<>(manager, type);
@@ -48,7 +47,7 @@ class IdResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
return collectionAdapter.getAll(page, pageSize, sortBy, desc, mapToDto);
}
public Response create(DTO dto, Supplier<MODEL_OBJECT> modelObjectSupplier, Function<MODEL_OBJECT, String> uriCreator) throws IOException, EXCEPTION {
public Response create(DTO dto, Supplier<MODEL_OBJECT> modelObjectSupplier, Function<MODEL_OBJECT, String> uriCreator) throws AlreadyExistsException {
return collectionAdapter.create(dto, modelObjectSupplier, uriCreator);
}

View File

@@ -5,7 +5,6 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import org.apache.shiro.SecurityUtils;
import sonia.scm.user.User;
import sonia.scm.user.UserException;
import sonia.scm.user.UserManager;
import sonia.scm.web.VndMediaType;
@@ -28,7 +27,7 @@ public class MeResource {
private final UserToUserDtoMapper userToDtoMapper;
private final IdResourceManagerAdapter<User, UserDto, UserException> adapter;
private final IdResourceManagerAdapter<User, UserDto> adapter;
@Inject
public MeResource(UserToUserDtoMapper userToDtoMapper, UserManager manager) {
this.userToDtoMapper = userToDtoMapper;

View File

@@ -5,8 +5,8 @@ import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.AlreadyExistsException;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.VndMediaType;
@@ -25,7 +25,7 @@ public class RepositoryCollectionResource {
private static final int DEFAULT_PAGE_SIZE = 10;
private final CollectionResourceManagerAdapter<Repository, RepositoryDto, RepositoryException> adapter;
private final CollectionResourceManagerAdapter<Repository, RepositoryDto> adapter;
private final RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper;
private final RepositoryDtoToRepositoryMapper dtoToRepositoryMapper;
private final ResourceLinks resourceLinks;
@@ -87,7 +87,7 @@ public class RepositoryCollectionResource {
})
@TypeHint(TypeHint.NO_CONTENT.class)
@ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created repository"))
public Response create(@Valid RepositoryDto repositoryDto) throws RepositoryException {
public Response create(@Valid RepositoryDto repositoryDto) throws AlreadyExistsException {
return adapter.create(repositoryDto,
() -> dtoToRepositoryMapper.map(repositoryDto, null),
repository -> resourceLinks.repository().self(repository.getNamespace(), repository.getName()));

View File

@@ -5,7 +5,6 @@ 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;
@@ -30,7 +29,7 @@ public class RepositoryResource {
private final RepositoryDtoToRepositoryMapper dtoToRepositoryMapper;
private final RepositoryManager manager;
private final SingleResourceManagerAdapter<Repository, RepositoryDto, RepositoryException> adapter;
private final SingleResourceManagerAdapter<Repository, RepositoryDto> adapter;
private final Provider<TagRootResource> tagRootResource;
private final Provider<BranchRootResource> branchRootResource;
private final Provider<ChangesetRootResource> changesetRootResource;

View File

@@ -22,22 +22,20 @@ import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
*
* @param <MODEL_OBJECT> The type of the model object, eg. {@link sonia.scm.user.User}.
* @param <DTO> The corresponding transport object, eg. {@link UserDto}.
* @param <EXCEPTION> The exception type for the model object, eg. {@link sonia.scm.user.UserException}.
*
* @see CollectionResourceManagerAdapter
*/
@SuppressWarnings("squid:S00119") // "MODEL_OBJECT" is much more meaningful than "M", right?
class SingleResourceManagerAdapter<MODEL_OBJECT extends ModelObject,
DTO extends HalRepresentation,
EXCEPTION extends Exception> extends AbstractManagerResource<MODEL_OBJECT, EXCEPTION> {
DTO extends HalRepresentation> extends AbstractManagerResource<MODEL_OBJECT> {
private final Function<Throwable, Optional<Response>> errorHandler;
SingleResourceManagerAdapter(Manager<MODEL_OBJECT, EXCEPTION> manager, Class<MODEL_OBJECT> type) {
SingleResourceManagerAdapter(Manager<MODEL_OBJECT> 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) {
SingleResourceManagerAdapter(Manager<MODEL_OBJECT> manager, Class<MODEL_OBJECT> type, Function<Throwable, Optional<Response>> errorHandler) {
super(manager, type);
this.errorHandler = errorHandler;
}

View File

@@ -1,15 +1,24 @@
package sonia.scm.api.v2.resources;
import com.webcohesion.enunciate.metadata.rs.*;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.AlreadyExistsException;
import sonia.scm.user.User;
import sonia.scm.user.UserException;
import sonia.scm.user.UserManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.io.IOException;
public class UserCollectionResource {
@@ -18,7 +27,7 @@ public class UserCollectionResource {
private final UserCollectionToDtoMapper userCollectionToDtoMapper;
private final ResourceLinks resourceLinks;
private final IdResourceManagerAdapter<User, UserDto, UserException> adapter;
private final IdResourceManagerAdapter<User, UserDto> adapter;
@Inject
public UserCollectionResource(UserManager manager, UserDtoToUserMapper dtoToUserMapper,
@@ -78,7 +87,7 @@ public class UserCollectionResource {
})
@TypeHint(TypeHint.NO_CONTENT.class)
@ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created user"))
public Response create(UserDto userDto) throws IOException, UserException {
public Response create(UserDto userDto) throws AlreadyExistsException {
return adapter.create(userDto,
() -> dtoToUserMapper.map(userDto, ""),
user -> resourceLinks.user().self(user.getName()));

View File

@@ -4,12 +4,17 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.user.User;
import sonia.scm.user.UserException;
import sonia.scm.user.UserManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
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;
public class UserResource {
@@ -17,7 +22,7 @@ public class UserResource {
private final UserDtoToUserMapper dtoToUserMapper;
private final UserToUserDtoMapper userToDtoMapper;
private final IdResourceManagerAdapter<User, UserDto, UserException> adapter;
private final IdResourceManagerAdapter<User, UserDto> adapter;
@Inject
public UserResource(UserDtoToUserMapper dtoToUserMapper, UserToUserDtoMapper userToDtoMapper, UserManager manager) {

View File

@@ -35,19 +35,18 @@ package sonia.scm.cache;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.Iterators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import static java.util.Collections.emptyIterator;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
@@ -109,7 +108,7 @@ public final class CacheConfigurations
if (it == null)
{
it = Iterators.emptyIterator();
it = emptyIterator();
}
return it;

View File

@@ -34,17 +34,16 @@ package sonia.scm.cache;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
//~--- JDK imports ------------------------------------------------------------
import java.io.Serializable;
import com.google.common.base.MoreObjects;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.Serializable;
//~--- JDK imports ------------------------------------------------------------
/**
*
@@ -70,7 +69,7 @@ public class GuavaCacheConfiguration implements Serializable
public String toString()
{
//J-
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("concurrencyLevel", concurrencyLevel)
.add("copyStrategy", copyStrategy)
.add("expireAfterAccess", expireAfterAccess)

View File

@@ -42,8 +42,10 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.AlreadyExistsException;
import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.NotFoundException;
import sonia.scm.SCMContextProvider;
import sonia.scm.TransformFilter;
import sonia.scm.search.SearchRequest;
@@ -52,7 +54,12 @@ import sonia.scm.util.CollectionAppender;
import sonia.scm.util.Util;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
//~--- JDK imports ------------------------------------------------------------
@@ -80,10 +87,7 @@ public class DefaultGroupManager extends AbstractGroupManager
public DefaultGroupManager(GroupDAO groupDAO)
{
this.groupDAO = groupDAO;
this.managerDaoAdapter = new ManagerDaoAdapter<>(
groupDAO,
GroupNotFoundException::new,
GroupAlreadyExistsException::new);
this.managerDaoAdapter = new ManagerDaoAdapter<>(groupDAO);
}
//~--- methods --------------------------------------------------------------
@@ -102,7 +106,7 @@ public class DefaultGroupManager extends AbstractGroupManager
}
@Override
public Group create(Group group) throws GroupException {
public Group create(Group group) throws AlreadyExistsException {
String type = group.getType();
if (Util.isEmpty(type)) {
group.setType(groupDAO.getType());
@@ -121,7 +125,7 @@ public class DefaultGroupManager extends AbstractGroupManager
}
@Override
public void delete(Group group) throws GroupException {
public void delete(Group group) throws NotFoundException {
logger.info("delete group {} of type {}", group.getName(), group.getType());
managerDaoAdapter.delete(
group,
@@ -140,17 +144,8 @@ public class DefaultGroupManager extends AbstractGroupManager
@Override
public void init(SCMContextProvider context) {}
/**
* Method description
*
*
* @param group
*
* @throws GroupException
* @throws IOException
*/
@Override
public void modify(Group group) throws GroupException {
public void modify(Group group) throws NotFoundException {
logger.info("modify group {} of type {}", group.getName(), group.getType());
managerDaoAdapter.modify(
@@ -164,18 +159,8 @@ public class DefaultGroupManager extends AbstractGroupManager
);
}
/**
* Method description
*
*
* @param group
*
* @throws GroupException
* @throws IOException
*/
@Override
public void refresh(Group group) throws GroupException
{
public void refresh(Group group) throws NotFoundException {
String name = group.getName();
if (logger.isInfoEnabled())
{
@@ -187,7 +172,7 @@ public class DefaultGroupManager extends AbstractGroupManager
if (fresh == null)
{
throw new GroupNotFoundException(group);
throw new NotFoundException("group", group.getId());
}
fresh.copyProperties(group);
@@ -400,5 +385,5 @@ public class DefaultGroupManager extends AbstractGroupManager
/** Field description */
private GroupDAO groupDAO;
private final ManagerDaoAdapter<Group, GroupException> managerDaoAdapter;
private final ManagerDaoAdapter<Group> managerDaoAdapter;
}

View File

@@ -42,10 +42,12 @@ import com.google.inject.Singleton;
import org.apache.shiro.concurrent.SubjectAwareExecutorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.AlreadyExistsException;
import sonia.scm.ArgumentIsInvalidException;
import sonia.scm.ConfigurationException;
import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.NotFoundException;
import sonia.scm.SCMContextProvider;
import sonia.scm.Type;
import sonia.scm.config.ScmConfiguration;
@@ -57,7 +59,6 @@ import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -91,7 +92,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
private final Set<Type> types;
private RepositoryMatcher repositoryMatcher;
private NamespaceStrategy namespaceStrategy;
private final ManagerDaoAdapter<Repository, RepositoryException> managerDaoAdapter;
private final ManagerDaoAdapter<Repository> managerDaoAdapter;
@Inject
@@ -118,10 +119,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
for (RepositoryHandler handler : handlerSet) {
addHandler(contextProvider, handler);
}
managerDaoAdapter = new ManagerDaoAdapter<>(
repositoryDAO,
RepositoryNotFoundException::new,
RepositoryAlreadyExistsException::create);
managerDaoAdapter = new ManagerDaoAdapter<>(repositoryDAO);
}
@@ -135,11 +133,11 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
}
@Override
public Repository create(Repository repository) throws RepositoryException {
public Repository create(Repository repository) throws AlreadyExistsException {
return create(repository, true);
}
public Repository create(Repository repository, boolean initRepository) throws RepositoryException {
public Repository create(Repository repository, boolean initRepository) throws AlreadyExistsException {
repository.setId(keyGenerator.createKey());
repository.setNamespace(namespaceStrategy.createNamespace(repository));
@@ -150,7 +148,11 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
RepositoryPermissions::create,
newRepository -> {
if (initRepository) {
getHandler(newRepository).create(newRepository);
try {
getHandler(newRepository).create(newRepository);
} catch (AlreadyExistsException e) {
throw new InternalRepositoryException("directory for repository does already exist", e);
}
}
fireEvent(HandlerEventType.BEFORE_CREATE, newRepository);
},
@@ -160,7 +162,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
}
@Override
public void delete(Repository repository) throws RepositoryException {
public void delete(Repository repository) throws NotFoundException {
logger.info("delete repository {}/{} of type {}", repository.getNamespace(), repository.getName(), repository.getType());
managerDaoAdapter.delete(
repository,
@@ -170,17 +172,16 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
);
}
private void preDelete(Repository toDelete) throws RepositoryException {
private void preDelete(Repository toDelete) {
if (configuration.isEnableRepositoryArchive() && !toDelete.isArchived()) {
throw new RepositoryIsNotArchivedException();
}
fireEvent(HandlerEventType.BEFORE_DELETE, toDelete);
getHandler(toDelete).delete(toDelete);
// getHandler(toDelete).delete(toDelete);
}
@Override
public void importRepository(Repository repository)
throws RepositoryException, IOException {
public void importRepository(Repository repository) throws AlreadyExistsException {
create(repository, false);
}
@@ -189,7 +190,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
}
@Override
public void modify(Repository repository) throws RepositoryException {
public void modify(Repository repository) throws NotFoundException {
logger.info("modify repository {}/{} of type {}", repository.getNamespace(), repository.getName(), repository.getType());
managerDaoAdapter.modify(
@@ -197,15 +198,18 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
RepositoryPermissions::modify,
notModified -> {
fireEvent(HandlerEventType.BEFORE_MODIFY, repository, notModified);
getHandler(repository).modify(repository);
try {
getHandler(repository).modify(repository);
} catch (NotFoundException e) {
throw new IllegalStateException("repository not found though just created", e);
}
},
notModified -> fireEvent(HandlerEventType.MODIFY, repository, notModified)
);
}
@Override
public void refresh(Repository repository)
throws RepositoryException {
public void refresh(Repository repository) throws RepositoryNotFoundException {
AssertUtil.assertIsNotNull(repository);
RepositoryPermissions.read(repository).check();
@@ -417,15 +421,14 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
}
private RepositoryHandler getHandler(Repository repository)
throws RepositoryException {
{
String type = repository.getType();
RepositoryHandler handler = handlerMap.get(type);
if (handler == null) {
throw new RepositoryHandlerNotFoundException(
"could not find handler for ".concat(type));
throw new InternalRepositoryException("could not find handler for " + type);
} else if (!handler.isConfigured()) {
throw new RepositoryException("handler is not configured");
throw new InternalRepositoryException("handler is not configured for type " + type);
}
return handler;

View File

@@ -36,15 +36,15 @@ package sonia.scm.repository;
import com.github.sdorra.ssp.PermissionActionCheck;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import sonia.scm.ConcurrentModificationException;
import sonia.scm.NotFoundException;
import java.util.Set;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
@@ -77,20 +77,7 @@ public final class HealthChecker
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param id
*
*
* @throws IOException
* @throws RepositoryException
* @throws RepositoryNotFoundException
*/
public void check(String id)
throws RepositoryNotFoundException, RepositoryException, IOException
{
public void check(String id) throws NotFoundException {
RepositoryPermissions.healthCheck(id).check();
Repository repository = repositoryManager.get(id);
@@ -104,28 +91,13 @@ public final class HealthChecker
doCheck(repository);
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
public void check(Repository repository)
throws RepositoryException, IOException
{
throws NotFoundException, ConcurrentModificationException {
RepositoryPermissions.healthCheck(repository).check();
doCheck(repository);
}
/**
* Method description
*
*
*/
public void checkAll()
{
logger.debug("check health of all repositories");
@@ -140,7 +112,7 @@ public final class HealthChecker
{
check(repository);
}
catch (RepositoryException | IOException ex)
catch (ConcurrentModificationException | NotFoundException ex)
{
logger.error("health check ends with exception", ex);
}
@@ -154,9 +126,7 @@ public final class HealthChecker
}
}
private void doCheck(Repository repository)
throws RepositoryException, IOException
{
private void doCheck(Repository repository) throws NotFoundException {
logger.info("start health check for repository {}", repository.getName());
HealthCheckResult result = HealthCheckResult.healthy();

View File

@@ -38,6 +38,7 @@ import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.EagerSingleton;
import sonia.scm.NotFoundException;
import sonia.scm.plugin.Extension;
import sonia.scm.web.security.AdministrationContext;
import sonia.scm.web.security.PrivilegedAction;
@@ -146,13 +147,10 @@ public final class LastModifiedUpdateListener
logger.info("update last modified date of repository {}", dbr.getId());
dbr.setLastModified(System.currentTimeMillis());
try
{
try {
repositoryManager.modify(dbr);
}
catch (RepositoryException ex)
{
logger.error("could not modify repository", ex);
} catch (NotFoundException e) {
logger.error("could not modify repository", e);
}
}
else

View File

@@ -30,12 +30,8 @@
*/
package sonia.scm.security;
import com.google.common.base.Objects;
import com.google.common.base.MoreObjects;
import com.google.inject.Inject;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
@@ -44,6 +40,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.config.ScmConfiguration;
import javax.inject.Singleton;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
* Configurable implementation of {@link LoginAttemptHandler}.
*
@@ -175,7 +176,7 @@ public class ConfigurableLoginAttemptHandler implements LoginAttemptHandler {
@Override
public String toString() {
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("counter", counter)
.add("lastAttempt", lastAttempt)
.toString();

View File

@@ -36,23 +36,19 @@ package sonia.scm.security;
//~--- non-JDK imports --------------------------------------------------------
import com.github.legman.Subscribe;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
import sonia.scm.group.GroupNames;
@@ -62,11 +58,11 @@ import sonia.scm.repository.RepositoryDAO;
import sonia.scm.user.User;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.util.List;
import java.util.Set;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra

View File

@@ -35,12 +35,12 @@ package sonia.scm.security;
import com.google.common.base.Objects;
//~--- JDK imports ------------------------------------------------------------
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
//~--- JDK imports ------------------------------------------------------------
/**
* Secure key can be used for singing messages and tokens.
*

View File

@@ -40,9 +40,11 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.AlreadyExistsException;
import sonia.scm.EagerSingleton;
import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.NotFoundException;
import sonia.scm.SCMContextProvider;
import sonia.scm.TransformFilter;
import sonia.scm.search.SearchRequest;
@@ -97,10 +99,7 @@ public class DefaultUserManager extends AbstractUserManager
public DefaultUserManager(UserDAO userDAO)
{
this.userDAO = userDAO;
this.managerDaoAdapter = new ManagerDaoAdapter<>(
userDAO,
UserNotFoundException::new,
UserAlreadyExistsException::new);
this.managerDaoAdapter = new ManagerDaoAdapter<>(userDAO);
}
//~--- methods --------------------------------------------------------------
@@ -139,10 +138,9 @@ public class DefaultUserManager extends AbstractUserManager
* @param user
*
* @throws IOException
* @throws UserException
*/
@Override
public User create(User user) throws UserException {
public User create(User user) throws AlreadyExistsException {
String type = user.getType();
if (Util.isEmpty(type)) {
user.setType(userDAO.getType());
@@ -159,7 +157,7 @@ public class DefaultUserManager extends AbstractUserManager
}
@Override
public void delete(User user) throws UserException {
public void delete(User user) throws NotFoundException {
logger.info("delete user {} of type {}", user.getName(), user.getType());
managerDaoAdapter.delete(
user,
@@ -193,11 +191,9 @@ public class DefaultUserManager extends AbstractUserManager
* @param user
*
* @throws IOException
* @throws UserException
*/
@Override
public void modify(User user) throws UserException
{
public void modify(User user) throws NotFoundException {
logger.info("modify user {} of type {}", user.getName(), user.getType());
managerDaoAdapter.modify(
@@ -214,11 +210,9 @@ public class DefaultUserManager extends AbstractUserManager
* @param user
*
* @throws IOException
* @throws UserException
*/
@Override
public void refresh(User user) throws UserException
{
public void refresh(User user) throws NotFoundException {
if (logger.isInfoEnabled())
{
logger.info("refresh user {} of type {}", user.getName(), user.getType());
@@ -229,7 +223,7 @@ public class DefaultUserManager extends AbstractUserManager
if (fresh == null)
{
throw new UserNotFoundException(user);
throw new NotFoundException();
}
fresh.copyProperties(user);
@@ -455,5 +449,5 @@ public class DefaultUserManager extends AbstractUserManager
//~--- fields ---------------------------------------------------------------
private final UserDAO userDAO;
private final ManagerDaoAdapter<User, UserException> managerDaoAdapter;
private final ManagerDaoAdapter<User> managerDaoAdapter;
}